From 5815341fde0f9fbbe1ec5bb9d4aaffbeb61c72c3 Mon Sep 17 00:00:00 2001 From: Li Nan Date: Sat, 3 Jun 2023 14:50:32 +0800 Subject: [PATCH] md: fix sysfs duplicate file while adding rdev hulk inclusion category: bugfix bugzilla: 188553, https://gitee.com/openeuler/kernel/issues/I6TNFX CVE: NA -------------------------------- rdev->del_work has not been queued to md_rdev_misc_wq and flush_workqueue will not flush it if tow threads add and remove same device. sysfs might WARN duplicate filename as below. //T1 //T2 mdadm write super add success remove unbind_rdev_from_array md_ioctl flush_workqueue INIT_WORK queue_work md_add_new_disk duplicate filename dev-xxx Check if there is any kobj with the same name, and return busy if true. Fixes: 5792a2856a63 ("md: avoid a deadlock when removing a device from an md array via sysfs") Signed-off-by: Li Nan Reviewed-by: Hou Tao --- drivers/md/md.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 9c96ea461e37..4d744cf8ffc6 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2402,8 +2402,9 @@ EXPORT_SYMBOL(md_integrity_add_rdev); static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) { - char b[BDEVNAME_SIZE]; + char b[BDEVNAME_SIZE + 4]; struct kobject *ko; + struct kernfs_node *sysfs_rdev; int err; /* prevent duplicates */ @@ -2454,7 +2455,8 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) mdname(mddev), mddev->max_disks); return -EBUSY; } - bdevname(rdev->bdev,b); + memcpy(b, "dev-", 4); + bdevname(rdev->bdev, b + 4); strreplace(b, '/', '!'); rdev->mddev = mddev; @@ -2463,7 +2465,15 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) if (mddev->raid_disks) mddev_create_serial_pool(mddev, rdev, false); - if ((err = kobject_add(&rdev->kobj, &mddev->kobj, "dev-%s", b))) + sysfs_rdev = sysfs_get_dirent_safe(mddev->kobj.sd, b); + if (sysfs_rdev) { + sysfs_put(sysfs_rdev); + err = -EBUSY; + goto fail; + } + + err = kobject_add(&rdev->kobj, &mddev->kobj, b); + if (err) goto fail; ko = &part_to_dev(rdev->bdev->bd_part)->kobj; @@ -2484,7 +2494,7 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) return 0; fail: - pr_warn("md: failed to register dev-%s for %s\n", + pr_warn("md: failed to register %s for %s\n", b, mdname(mddev)); return err; } -- GitLab