Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -1482,14 +1482,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
	int sectors = r10_bio->sectors;
	mdk_rdev_t*rdev;
	int max_read_errors = atomic_read(&mddev->max_corr_read_errors);
	int d = r10_bio->devs[r10_bio->read_slot].devnum;

	rcu_read_lock();
	{
		int d = r10_bio->devs[r10_bio->read_slot].devnum;
	rdev = rcu_dereference(conf->mirrors[d].rdev);
	if (rdev) { /* If rdev is not NULL */
		char b[BDEVNAME_SIZE];
		int cur_read_error_count = 0;

		rdev = rcu_dereference(conf->mirrors[d].rdev);
		bdevname(rdev->bdev, b);

		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)

		rcu_read_lock();
		do {
			int d = r10_bio->devs[sl].devnum;
			d = r10_bio->devs[sl].devnum;
			rdev = rcu_dereference(conf->mirrors[d].rdev);
			if (rdev &&
			    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)
		rcu_read_lock();
		while (sl != r10_bio->read_slot) {
			char b[BDEVNAME_SIZE];
			int d;

			if (sl==0)
				sl = conf->copies;
			sl--;
@@ -1601,7 +1601,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
		}
		sl = start;
		while (sl != r10_bio->read_slot) {
			int d;

			if (sl==0)
				sl = conf->copies;
			sl--;