Commit cc9aa824 authored by Li Nan's avatar Li Nan
Browse files

md: ensure child flush IO does not affect origin bio->bi_status

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAKQB5


CVE: CVE-2024-43855

--------------------------------

When a flush is issued to an RAID array, a child flush IO is created and
issued for each member disk in the RAID array. Since patch b75197e86e6d
("md: Remove flush handling"), each child flush IO has been chained with
the original bio. As a result, the failure of any child IO could modify
the bi_status of the original bio, potentially impacting the upper-layer
filesystem.

Fix the issue by preventing child flush IO from altering the original
bio->bi_status as before. However, this design introduces a known
issue: in the event of a power failure, if a flush IO on a member
disk fails, the upper layers may not be informed. This issue will be
fixed in a future patch.

Fixes: b75197e86e6d ("md: Remove flush handling")
Signed-off-by: default avatarLi Nan <linan122@huawei.com>
parent 05fa42d2
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -536,6 +536,23 @@ void mddev_resume(struct mddev *mddev)
}
EXPORT_SYMBOL_GPL(mddev_resume);

static void md_end_flush(struct bio *bio)
{
	struct bio *parent = bio->bi_private;
	char b[BDEVNAME_SIZE];

	/*
	 * If any flush io error before the power failure,
	 * disk data may be lost.
	 */
	if (bio->bi_status)
		pr_err("md: %s flush io error %d\n", bio_devname(bio, b),
			blk_status_to_errno(bio->bi_status));

	bio_put(bio);
	bio_endio(parent);
}

bool md_flush_request(struct mddev *mddev, struct bio *bio)
{
	struct md_rdev *rdev;
@@ -550,7 +567,9 @@ bool md_flush_request(struct mddev *mddev, struct bio *bio)
		new = bio_alloc_mddev(GFP_NOIO, 0, mddev);
		bio_set_dev(new, rdev->bdev);
		new->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
		bio_chain(new, bio);
		new->bi_private = bio;
		new->bi_end_io = md_end_flush;
		bio_inc_remaining(bio);
		submit_bio(new);
		rcu_read_lock();
	}