Skip to content

Commit 3de59bb

Browse files
Yufen YuShaohua Li
Yufen Yu
authored and
Shaohua Li
committed
md/raid1: fix NULL pointer dereference
In handle_write_finished(), if r1_bio->bios[m] != NULL, it thinks the corresponding conf->mirrors[m].rdev is also not NULL. But, it is not always true. Even if some io hold replacement rdev(i.e. rdev->nr_pending.count > 0), raid1_remove_disk() can also set the rdev as NULL. That means, bios[m] != NULL, but mirrors[m].rdev is NULL, resulting in NULL pointer dereference in handle_write_finished and sync_request_write. This patch can fix BUGs as follows: BUG: unable to handle kernel NULL pointer dereference at 0000000000000140 IP: [<ffffffff815bbbbd>] raid1d+0x2bd/0xfc0 PGD 12ab52067 PUD 12f587067 PMD 0 Oops: 0000 [#1] SMP CPU: 1 PID: 2008 Comm: md3_raid1 Not tainted 4.1.44+ torvalds#130 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1.fc26 04/01/2014 Call Trace: ? schedule+0x37/0x90 ? prepare_to_wait_event+0x83/0xf0 md_thread+0x144/0x150 ? wake_atomic_t_function+0x70/0x70 ? md_start_sync+0xf0/0xf0 kthread+0xd8/0xf0 ? kthread_worker_fn+0x160/0x160 ret_from_fork+0x42/0x70 ? kthread_worker_fn+0x160/0x160 BUG: unable to handle kernel NULL pointer dereference at 00000000000000b8 IP: sync_request_write+0x9e/0x980 PGD 800000007c518067 P4D 800000007c518067 PUD 8002b067 PMD 0 Oops: 0000 [#1] SMP PTI CPU: 24 PID: 2549 Comm: md3_raid1 Not tainted 4.15.0+ torvalds#118 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1.fc26 04/01/2014 Call Trace: ? sched_clock+0x5/0x10 ? sched_clock_cpu+0xc/0xb0 ? flush_pending_writes+0x3a/0xd0 ? pick_next_task_fair+0x4d5/0x5f0 ? __switch_to+0xa2/0x430 raid1d+0x65a/0x870 ? find_pers+0x70/0x70 ? find_pers+0x70/0x70 ? md_thread+0x11c/0x160 md_thread+0x11c/0x160 ? finish_wait+0x80/0x80 kthread+0x111/0x130 ? kthread_create_worker_on_cpu+0x70/0x70 ? do_syscall_64+0x6f/0x190 ? SyS_exit_group+0x10/0x10 ret_from_fork+0x35/0x40 Reviewed-by: NeilBrown <[email protected]> Signed-off-by: Yufen Yu <[email protected]> Signed-off-by: Shaohua Li <[email protected]>
1 parent 8876391 commit 3de59bb

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

drivers/md/raid1.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,6 +1809,17 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
18091809
struct md_rdev *repl =
18101810
conf->mirrors[conf->raid_disks + number].rdev;
18111811
freeze_array(conf, 0);
1812+
if (atomic_read(&repl->nr_pending)) {
1813+
/* It means that some queued IO of retry_list
1814+
* hold repl. Thus, we cannot set replacement
1815+
* as NULL, avoiding rdev NULL pointer
1816+
* dereference in sync_request_write and
1817+
* handle_write_finished.
1818+
*/
1819+
err = -EBUSY;
1820+
unfreeze_array(conf);
1821+
goto abort;
1822+
}
18121823
clear_bit(Replacement, &repl->flags);
18131824
p->rdev = repl;
18141825
conf->mirrors[conf->raid_disks + number].rdev = NULL;

0 commit comments

Comments
 (0)