aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid10.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-09-10 03:21:23 -0400
committerNeilBrown <neilb@suse.de>2011-09-10 03:21:23 -0400
commit079fa166a2874985ae58b2e21e26e1cbc91127d4 (patch)
tree39f67f9078465bd67c29216b35370a78907e4f3b /drivers/md/raid10.c
parent19d5f834d6aff7efb1c9353523865c5bce869470 (diff)
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=41862 Reported-by: Bruno Wolff III <bruno@wolff.to> Tested-by: Bruno Wolff III <bruno@wolff.to> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid10.c')
-rw-r--r--drivers/md/raid10.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index f6873fc8e5ee..d7a8468ddeab 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1132,13 +1132,12 @@ retry_write:
1132 spin_unlock_irqrestore(&conf->device_lock, flags); 1132 spin_unlock_irqrestore(&conf->device_lock, flags);
1133 } 1133 }
1134 1134
1135 /* Remove the bias on 'remaining' */ 1135 /* Don't remove the bias on 'remaining' (one_write_done) until
1136 one_write_done(r10_bio); 1136 * after checking if we need to go around again.
1137 1137 */
1138 /* In case raid10d snuck in to freeze_array */
1139 wake_up(&conf->wait_barrier);
1140 1138
1141 if (sectors_handled < (bio->bi_size >> 9)) { 1139 if (sectors_handled < (bio->bi_size >> 9)) {
1140 one_write_done(r10_bio);
1142 /* We need another r10_bio. It has already been counted 1141 /* We need another r10_bio. It has already been counted
1143 * in bio->bi_phys_segments. 1142 * in bio->bi_phys_segments.
1144 */ 1143 */
@@ -1152,6 +1151,10 @@ retry_write:
1152 r10_bio->state = 0; 1151 r10_bio->state = 0;
1153 goto retry_write; 1152 goto retry_write;
1154 } 1153 }
1154 one_write_done(r10_bio);
1155
1156 /* In case raid10d snuck in to freeze_array */
1157 wake_up(&conf->wait_barrier);
1155 1158
1156 if (do_sync || !mddev->bitmap || !plugged) 1159 if (do_sync || !mddev->bitmap || !plugged)
1157 md_wakeup_thread(mddev->thread); 1160 md_wakeup_thread(mddev->thread);