diff options
author | Prasanna S. Panchamukhi <prasanna.panchamukhi@riverbed.com> | 2010-06-23 23:31:03 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2010-06-23 23:31:03 -0400 |
commit | 0544a21db02c1d8883158fd6f323364f830a120a (patch) | |
tree | 086c38e3c9132a8ecdee0ccbdd845ce2604caad9 /drivers/md | |
parent | f3b99be19ded511a1bf05a148276239d9f13eefa (diff) |
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: Prasanna S. Panchamukhi <prasanna.panchamukhi@riverbed.com>
Signed-off-by: Rob Becker <rbecker@riverbed.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid10.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 03724992cdf2..6d420cb487b5 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1482,14 +1482,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) | |||
1482 | int sectors = r10_bio->sectors; | 1482 | int sectors = r10_bio->sectors; |
1483 | mdk_rdev_t*rdev; | 1483 | mdk_rdev_t*rdev; |
1484 | int max_read_errors = atomic_read(&mddev->max_corr_read_errors); | 1484 | int max_read_errors = atomic_read(&mddev->max_corr_read_errors); |
1485 | int d = r10_bio->devs[r10_bio->read_slot].devnum; | ||
1485 | 1486 | ||
1486 | rcu_read_lock(); | 1487 | rcu_read_lock(); |
1487 | { | 1488 | rdev = rcu_dereference(conf->mirrors[d].rdev); |
1488 | int d = r10_bio->devs[r10_bio->read_slot].devnum; | 1489 | if (rdev) { /* If rdev is not NULL */ |
1489 | char b[BDEVNAME_SIZE]; | 1490 | char b[BDEVNAME_SIZE]; |
1490 | int cur_read_error_count = 0; | 1491 | int cur_read_error_count = 0; |
1491 | 1492 | ||
1492 | rdev = rcu_dereference(conf->mirrors[d].rdev); | ||
1493 | bdevname(rdev->bdev, b); | 1493 | bdevname(rdev->bdev, b); |
1494 | 1494 | ||
1495 | if (test_bit(Faulty, &rdev->flags)) { | 1495 | 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 | 1530 | ||
1531 | rcu_read_lock(); | 1531 | rcu_read_lock(); |
1532 | do { | 1532 | do { |
1533 | int d = r10_bio->devs[sl].devnum; | 1533 | d = r10_bio->devs[sl].devnum; |
1534 | rdev = rcu_dereference(conf->mirrors[d].rdev); | 1534 | rdev = rcu_dereference(conf->mirrors[d].rdev); |
1535 | if (rdev && | 1535 | if (rdev && |
1536 | test_bit(In_sync, &rdev->flags)) { | 1536 | 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 | rcu_read_lock(); | 1564 | rcu_read_lock(); |
1565 | while (sl != r10_bio->read_slot) { | 1565 | while (sl != r10_bio->read_slot) { |
1566 | char b[BDEVNAME_SIZE]; | 1566 | char b[BDEVNAME_SIZE]; |
1567 | int d; | 1567 | |
1568 | if (sl==0) | 1568 | if (sl==0) |
1569 | sl = conf->copies; | 1569 | sl = conf->copies; |
1570 | sl--; | 1570 | sl--; |
@@ -1601,7 +1601,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) | |||
1601 | } | 1601 | } |
1602 | sl = start; | 1602 | sl = start; |
1603 | while (sl != r10_bio->read_slot) { | 1603 | while (sl != r10_bio->read_slot) { |
1604 | int d; | 1604 | |
1605 | if (sl==0) | 1605 | if (sl==0) |
1606 | sl = conf->copies; | 1606 | sl = conf->copies; |
1607 | sl--; | 1607 | sl--; |