aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2005-04-16 18:25:40 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:25:40 -0400
commit4a534f93b371e8e6e87ae302757365f0f583e06b (patch)
treef9ed5470c81bd63dba86f425a2c3731802000c79 /drivers
parent9c340d80f66faaea3522812d0d8c91d6a1b48a22 (diff)
[PATCH] possible use-after-free of bio
There is a possibility that a bio will be accessed after it has been freed on SCSI. It happens if you submit a bio with BIO_SYNC marked and the auto-unplugging kicks the request_fn, SCSI re-enables interrupts in-between so if the request completes between the add_request() in __make_request() and the bio_sync() call, we could be looking at a dead bio. It's a slim race, but it has been triggered in the Real World. So assign bio_sync() to a local variable instead. Signed-off-by: Jens Axboe <axboe@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/ll_rw_blk.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 02242e8ba996..2d6934a02867 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -2559,7 +2559,7 @@ EXPORT_SYMBOL(__blk_attempt_remerge);
2559static int __make_request(request_queue_t *q, struct bio *bio) 2559static int __make_request(request_queue_t *q, struct bio *bio)
2560{ 2560{
2561 struct request *req, *freereq = NULL; 2561 struct request *req, *freereq = NULL;
2562 int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err; 2562 int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync;
2563 sector_t sector; 2563 sector_t sector;
2564 2564
2565 sector = bio->bi_sector; 2565 sector = bio->bi_sector;
@@ -2567,6 +2567,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
2567 cur_nr_sectors = bio_cur_sectors(bio); 2567 cur_nr_sectors = bio_cur_sectors(bio);
2568 2568
2569 rw = bio_data_dir(bio); 2569 rw = bio_data_dir(bio);
2570 sync = bio_sync(bio);
2570 2571
2571 /* 2572 /*
2572 * low level driver can indicate that it wants pages above a 2573 * low level driver can indicate that it wants pages above a
@@ -2698,7 +2699,7 @@ get_rq:
2698out: 2699out:
2699 if (freereq) 2700 if (freereq)
2700 __blk_put_request(q, freereq); 2701 __blk_put_request(q, freereq);
2701 if (bio_sync(bio)) 2702 if (sync)
2702 __generic_unplug_device(q); 2703 __generic_unplug_device(q);
2703 2704
2704 spin_unlock_irq(q->queue_lock); 2705 spin_unlock_irq(q->queue_lock);