iscsi: Always free a cdw before its associated ctl_io.
cxgbei stores state about a target transfer in the ctl_private[] array of a ctl_io that is freed when a target transfer (represented by the cdw) is freed. As such, freeing a ctl_io before a cdw that references it can result in a use after free in cxgbei. Two of the four places freed the cdw first, and the other two freed the ctl_io first. Fix the latter two places to free the cdw first. Reported by: Jithesh Arakkan @ Chelsio Reviewed by: mav Differential Revision: https://reviews.freebsd.org/D30270
This commit is contained in:
parent
f17a590085
commit
71e3d1b3a0
@ -1112,7 +1112,7 @@ static void
|
|||||||
cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs)
|
cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs)
|
||||||
{
|
{
|
||||||
struct cfiscsi_data_wait *cdw;
|
struct cfiscsi_data_wait *cdw;
|
||||||
union ctl_io *io;
|
union ctl_io *io, *cdw_io;
|
||||||
int error, last, wait;
|
int error, last, wait;
|
||||||
|
|
||||||
if (cs->cs_target == NULL)
|
if (cs->cs_target == NULL)
|
||||||
@ -1144,10 +1144,11 @@ cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs)
|
|||||||
* assuming that the data transfer actually succeeded
|
* assuming that the data transfer actually succeeded
|
||||||
* and writing uninitialized data to disk.
|
* and writing uninitialized data to disk.
|
||||||
*/
|
*/
|
||||||
cdw->cdw_ctl_io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
|
cdw_io = cdw->cdw_ctl_io;
|
||||||
cdw->cdw_ctl_io->scsiio.io_hdr.port_status = 42;
|
cdw_io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
|
||||||
ctl_datamove_done(cdw->cdw_ctl_io, false);
|
cdw_io->scsiio.io_hdr.port_status = 42;
|
||||||
cfiscsi_data_wait_free(cs, cdw);
|
cfiscsi_data_wait_free(cs, cdw);
|
||||||
|
ctl_datamove_done(cdw_io, false);
|
||||||
CFISCSI_SESSION_LOCK(cs);
|
CFISCSI_SESSION_LOCK(cs);
|
||||||
}
|
}
|
||||||
CFISCSI_SESSION_UNLOCK(cs);
|
CFISCSI_SESSION_UNLOCK(cs);
|
||||||
@ -2920,6 +2921,7 @@ cfiscsi_task_management_done(union ctl_io *io)
|
|||||||
struct cfiscsi_data_wait *cdw, *tmpcdw;
|
struct cfiscsi_data_wait *cdw, *tmpcdw;
|
||||||
struct cfiscsi_session *cs, *tcs;
|
struct cfiscsi_session *cs, *tcs;
|
||||||
struct cfiscsi_softc *softc;
|
struct cfiscsi_softc *softc;
|
||||||
|
union ctl_io *cdw_io;
|
||||||
int cold_reset = 0;
|
int cold_reset = 0;
|
||||||
|
|
||||||
request = PRIV_REQUEST(io);
|
request = PRIV_REQUEST(io);
|
||||||
@ -2953,10 +2955,11 @@ cfiscsi_task_management_done(union ctl_io *io)
|
|||||||
#endif
|
#endif
|
||||||
TAILQ_REMOVE(&cs->cs_waiting_for_data_out,
|
TAILQ_REMOVE(&cs->cs_waiting_for_data_out,
|
||||||
cdw, cdw_next);
|
cdw, cdw_next);
|
||||||
io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
|
cdw_io = cdw->cdw_ctl_io;
|
||||||
cdw->cdw_ctl_io->scsiio.io_hdr.port_status = 43;
|
cdw_io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
|
||||||
ctl_datamove_done(cdw->cdw_ctl_io, false);
|
cdw_io->scsiio.io_hdr.port_status = 43;
|
||||||
cfiscsi_data_wait_free(cs, cdw);
|
cfiscsi_data_wait_free(cs, cdw);
|
||||||
|
ctl_datamove_done(cdw_io, false);
|
||||||
}
|
}
|
||||||
CFISCSI_SESSION_UNLOCK(cs);
|
CFISCSI_SESSION_UNLOCK(cs);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user