Commit 09411e42 authored by Bart Van Assche's avatar Bart Van Assche Committed by Ben Hutchings

Avoid dangling pointer in scsi_requeue_command()

commit 940f5d47 upstream.

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: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarBart Van Assche <bvanassche@acm.org>
Reviewed-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Reviewed-by: default avatarTejun Heo <tj@kernel.org>
[jejb: enhance commend and add commit log for stable]
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 9c63d964
...@@ -479,15 +479,26 @@ void scsi_requeue_run_queue(struct work_struct *work) ...@@ -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) static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
{ {
struct scsi_device *sdev = cmd->device;
struct request *req = cmd->request; struct request *req = cmd->request;
unsigned long flags; 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); spin_lock_irqsave(q->queue_lock, flags);
scsi_unprep_request(req); scsi_unprep_request(req);
blk_requeue_request(q, req); blk_requeue_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags); spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q); scsi_run_queue(q);
put_device(&sdev->sdev_gendev);
} }
void scsi_next_command(struct scsi_cmnd *cmd) void scsi_next_command(struct scsi_cmnd *cmd)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment