Skip to content

Commit

Permalink
[SCSI] Avoid dangling pointer in scsi_requeue_command()
Browse files Browse the repository at this point in the history
When we call scsi_unprep_request() the command associated with the request
gets destroyed and therefore drops its reference on the device.  If this was
the only reference, the device may get released and we end up with a NULL
pointer deref when we call blk_requeue_request.

Reported-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Reviewed-by: Tejun Heo <tj@kernel.org>
Cc: <stable@kernel.org>
[jejb: enhance commend and add commit log for stable]
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Bart Van Assche authored and James Bottomley committed Jul 20, 2012
1 parent 67bd941 commit 940f5d4
Showing 1 changed file with 11 additions and 0 deletions.
11 changes: 11 additions & 0 deletions drivers/scsi/scsi_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,15 +479,26 @@ void scsi_requeue_run_queue(struct work_struct *work)
*/
static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
{
struct scsi_device *sdev = cmd->device;
struct request *req = cmd->request;
unsigned long flags;

/*
* We need to hold a reference on the device to avoid the queue being
* killed after the unlock and before scsi_run_queue is invoked which
* may happen because scsi_unprep_request() puts the command which
* releases its reference on the device.
*/
get_device(&sdev->sdev_gendev);

spin_lock_irqsave(q->queue_lock, flags);
scsi_unprep_request(req);
blk_requeue_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags);

scsi_run_queue(q);

put_device(&sdev->sdev_gendev);
}

void scsi_next_command(struct scsi_cmnd *cmd)
Expand Down

0 comments on commit 940f5d4

Please sign in to comment.