From: Petr Uzel Date: Fri, 21 Oct 2011 11:31:09 +0000 (+0200) Subject: st: fix race in st_scsi_execute_end X-Git-Tag: v3.0.9~49 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=292b3893b8e010398a338b482f40cbcd62e01a97;p=karo-tx-linux.git st: fix race in st_scsi_execute_end commit c68bf8eeaa57c852e74adcf597237be149eef830 upstream. The call to complete() in st_scsi_execute_end() wakes up sleeping thread in write_behind_check(), which frees the st_request, thus invalidating the pointer to the associated bio structure, which is then passed to the blk_rq_unmap_user(). Fix by storing pointer to bio structure into temporary local variable. This bug is present since at least linux-2.6.32. Signed-off-by: Petr Uzel Reported-by: Juergen Groß Reviewed-by: Jan Kara Acked-by: Kai Mäkisara Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 1871b8ae83ae..9b28f39bac26 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -462,14 +462,16 @@ static void st_scsi_execute_end(struct request *req, int uptodate) { struct st_request *SRpnt = req->end_io_data; struct scsi_tape *STp = SRpnt->stp; + struct bio *tmp; STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors; STp->buffer->cmdstat.residual = req->resid_len; + tmp = SRpnt->bio; if (SRpnt->waiting) complete(SRpnt->waiting); - blk_rq_unmap_user(SRpnt->bio); + blk_rq_unmap_user(tmp); __blk_put_request(req->q, req); }