Commit 0544a21d authored by Prasanna S. Panchamukhi's avatar Prasanna S. Panchamukhi Committed by NeilBrown

md: raid10: Fix null pointer dereference in fix_read_error()

Such NULL pointer dereference can occur when the driver was fixing the
read errors/bad blocks and the disk was physically removed
causing a system crash. This patch check if the
rcu_dereference() returns valid rdev before accessing it in fix_read_error().

Cc: stable@kernel.org
Signed-off-by: default avatarPrasanna S. Panchamukhi <prasanna.panchamukhi@riverbed.com>
Signed-off-by: default avatarRob Becker <rbecker@riverbed.com>
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent f3b99be1
...@@ -1482,14 +1482,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) ...@@ -1482,14 +1482,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
int sectors = r10_bio->sectors; int sectors = r10_bio->sectors;
mdk_rdev_t*rdev; mdk_rdev_t*rdev;
int max_read_errors = atomic_read(&mddev->max_corr_read_errors); int max_read_errors = atomic_read(&mddev->max_corr_read_errors);
int d = r10_bio->devs[r10_bio->read_slot].devnum;
rcu_read_lock(); rcu_read_lock();
{ rdev = rcu_dereference(conf->mirrors[d].rdev);
int d = r10_bio->devs[r10_bio->read_slot].devnum; if (rdev) { /* If rdev is not NULL */
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
int cur_read_error_count = 0; int cur_read_error_count = 0;
rdev = rcu_dereference(conf->mirrors[d].rdev);
bdevname(rdev->bdev, b); bdevname(rdev->bdev, b);
if (test_bit(Faulty, &rdev->flags)) { if (test_bit(Faulty, &rdev->flags)) {
...@@ -1530,7 +1530,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) ...@@ -1530,7 +1530,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
rcu_read_lock(); rcu_read_lock();
do { do {
int d = r10_bio->devs[sl].devnum; d = r10_bio->devs[sl].devnum;
rdev = rcu_dereference(conf->mirrors[d].rdev); rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev && if (rdev &&
test_bit(In_sync, &rdev->flags)) { test_bit(In_sync, &rdev->flags)) {
...@@ -1564,7 +1564,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) ...@@ -1564,7 +1564,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
rcu_read_lock(); rcu_read_lock();
while (sl != r10_bio->read_slot) { while (sl != r10_bio->read_slot) {
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
int d;
if (sl==0) if (sl==0)
sl = conf->copies; sl = conf->copies;
sl--; sl--;
...@@ -1601,7 +1601,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) ...@@ -1601,7 +1601,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
} }
sl = start; sl = start;
while (sl != r10_bio->read_slot) { while (sl != r10_bio->read_slot) {
int d;
if (sl==0) if (sl==0)
sl = conf->copies; sl = conf->copies;
sl--; sl--;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment