提交 079fa166 编写于 作者: N NeilBrown

md/raid1,10: Remove use-after-free bug in make_request.

A single request to RAID1 or RAID10 might result in multiple
requests if there are known bad blocks that need to be avoided.

To detect if we need to submit another write request we test:
 	if (sectors_handled < (bio->bi_size >> 9)) {

However this is after we call **_write_done() so the 'bio' no longer
belongs to us - the writes could have completed and the bio freed.

So move the **_write_done call until after the test against
bio->bi_size.

This addresses https://bugzilla.kernel.org/show_bug.cgi?id=41862Reported-by: NBruno Wolff III <bruno@wolff.to>
Tested-by: NBruno Wolff III <bruno@wolff.to>
Signed-off-by: NNeilBrown <neilb@suse.de>
上级 19d5f834
...@@ -1099,12 +1099,11 @@ static int make_request(mddev_t *mddev, struct bio * bio) ...@@ -1099,12 +1099,11 @@ static int make_request(mddev_t *mddev, struct bio * bio)
bio_list_add(&conf->pending_bio_list, mbio); bio_list_add(&conf->pending_bio_list, mbio);
spin_unlock_irqrestore(&conf->device_lock, flags); spin_unlock_irqrestore(&conf->device_lock, flags);
} }
r1_bio_write_done(r1_bio); /* Mustn't call r1_bio_write_done before this next test,
* as it could result in the bio being freed.
/* In case raid1d snuck in to freeze_array */ */
wake_up(&conf->wait_barrier);
if (sectors_handled < (bio->bi_size >> 9)) { if (sectors_handled < (bio->bi_size >> 9)) {
r1_bio_write_done(r1_bio);
/* We need another r1_bio. It has already been counted /* We need another r1_bio. It has already been counted
* in bio->bi_phys_segments * in bio->bi_phys_segments
*/ */
...@@ -1117,6 +1116,11 @@ static int make_request(mddev_t *mddev, struct bio * bio) ...@@ -1117,6 +1116,11 @@ static int make_request(mddev_t *mddev, struct bio * bio)
goto retry_write; goto retry_write;
} }
r1_bio_write_done(r1_bio);
/* In case raid1d snuck in to freeze_array */
wake_up(&conf->wait_barrier);
if (do_sync || !bitmap || !plugged) if (do_sync || !bitmap || !plugged)
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->thread);
......
...@@ -1132,13 +1132,12 @@ static int make_request(mddev_t *mddev, struct bio * bio) ...@@ -1132,13 +1132,12 @@ static int make_request(mddev_t *mddev, struct bio * bio)
spin_unlock_irqrestore(&conf->device_lock, flags); spin_unlock_irqrestore(&conf->device_lock, flags);
} }
/* Remove the bias on 'remaining' */ /* Don't remove the bias on 'remaining' (one_write_done) until
one_write_done(r10_bio); * after checking if we need to go around again.
*/
/* In case raid10d snuck in to freeze_array */
wake_up(&conf->wait_barrier);
if (sectors_handled < (bio->bi_size >> 9)) { if (sectors_handled < (bio->bi_size >> 9)) {
one_write_done(r10_bio);
/* We need another r10_bio. It has already been counted /* We need another r10_bio. It has already been counted
* in bio->bi_phys_segments. * in bio->bi_phys_segments.
*/ */
...@@ -1152,6 +1151,10 @@ static int make_request(mddev_t *mddev, struct bio * bio) ...@@ -1152,6 +1151,10 @@ static int make_request(mddev_t *mddev, struct bio * bio)
r10_bio->state = 0; r10_bio->state = 0;
goto retry_write; goto retry_write;
} }
one_write_done(r10_bio);
/* In case raid10d snuck in to freeze_array */
wake_up(&conf->wait_barrier);
if (do_sync || !mddev->bitmap || !plugged) if (do_sync || !mddev->bitmap || !plugged)
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->thread);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册