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: Li Nan linan122@huawei.com --- drivers/md/md.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 94ea0de3f06f..d96921ff1d29 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -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(); }