[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>
This commit is contained in:
parent
9c340d80f6
commit
4a534f93b3
1 changed files with 3 additions and 2 deletions
|
@ -2559,7 +2559,7 @@ EXPORT_SYMBOL(__blk_attempt_remerge);
|
||||||
static int __make_request(request_queue_t *q, struct bio *bio)
|
static int __make_request(request_queue_t *q, struct bio *bio)
|
||||||
{
|
{
|
||||||
struct request *req, *freereq = NULL;
|
struct request *req, *freereq = NULL;
|
||||||
int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err;
|
int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync;
|
||||||
sector_t sector;
|
sector_t sector;
|
||||||
|
|
||||||
sector = bio->bi_sector;
|
sector = bio->bi_sector;
|
||||||
|
@ -2567,6 +2567,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
|
||||||
cur_nr_sectors = bio_cur_sectors(bio);
|
cur_nr_sectors = bio_cur_sectors(bio);
|
||||||
|
|
||||||
rw = bio_data_dir(bio);
|
rw = bio_data_dir(bio);
|
||||||
|
sync = bio_sync(bio);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* low level driver can indicate that it wants pages above a
|
* low level driver can indicate that it wants pages above a
|
||||||
|
@ -2698,7 +2699,7 @@ get_rq:
|
||||||
out:
|
out:
|
||||||
if (freereq)
|
if (freereq)
|
||||||
__blk_put_request(q, freereq);
|
__blk_put_request(q, freereq);
|
||||||
if (bio_sync(bio))
|
if (sync)
|
||||||
__generic_unplug_device(q);
|
__generic_unplug_device(q);
|
||||||
|
|
||||||
spin_unlock_irq(q->queue_lock);
|
spin_unlock_irq(q->queue_lock);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue