Re: [PATCH] MD: md, fix lock imbalance



On Sunday June 21, jirislaby@xxxxxxxxx wrote:
Add unlock and put to one of fail paths in md_alloc.

Hi Jiri,
thanks for finding this.
I have split it up in to two patches. One just fixes the bug as
simply as possible. This will be tagged for -stable.
The other tidies up the exist paths (a little differently to the way
you did). That one won't go to -stable.

See below.

Thanks,
NeilBrown

commit d7a0dc02b59b8656d7817bf2da3822df64fe4886
Author: NeilBrown <neilb@xxxxxxx>
Date: Wed Jul 1 11:45:14 2009 +1000

md: fix error patch which duplicate name is found on md device creation.

When an md device is created by name (rather than number) we need to
check that the name is not already in use. If this check finds a
duplicate, we return an error without dropping the lock or freeing
the newly create mddev.
This patch fixes that.

Cc: stable@xxxxxxxxxx
Found-by: Jiri Slaby <jirislaby@xxxxxxxxx>
Signed-off-by: NeilBrown <neilb@xxxxxxx>

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 2166af8..58bee23 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3862,6 +3862,8 @@ static int md_alloc(dev_t dev, char *name)
if (mddev2->gendisk &&
strcmp(mddev2->gendisk->disk_name, name) == 0) {
spin_unlock(&all_mddevs_lock);
+ mutex_unlock(&disks_mutex);
+ mddev_put(mddev);
return -EEXIST;
}
spin_unlock(&all_mddevs_lock);

commit 84dfea9c9910a7e01ecb2463c6298c0689a0c6a1
Author: NeilBrown <neilb@xxxxxxx>
Date: Wed Jul 1 11:45:14 2009 +1000

md: tidy up error paths in md_alloc

As the recent bug in md_alloc showed, having a single exit path for
unlocking and putting is a good idea. So restructure md_alloc to have
a single mutex_unlock and mddev_put, and use gotos where necessary.

Found-by: Jiri Slaby <jirislaby@xxxxxxxxx>
Signed-off-by: NeilBrown <neilb@xxxxxxx>

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 58bee23..65fe35b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3846,11 +3846,9 @@ static int md_alloc(dev_t dev, char *name)
flush_scheduled_work();

mutex_lock(&disks_mutex);
- if (mddev->gendisk) {
- mutex_unlock(&disks_mutex);
- mddev_put(mddev);
- return -EEXIST;
- }
+ error = -EEXIST;
+ if (mddev->gendisk)
+ goto abort;

if (name) {
/* Need to ensure that 'name' is not a duplicate.
@@ -3862,19 +3860,15 @@ static int md_alloc(dev_t dev, char *name)
if (mddev2->gendisk &&
strcmp(mddev2->gendisk->disk_name, name) == 0) {
spin_unlock(&all_mddevs_lock);
- mutex_unlock(&disks_mutex);
- mddev_put(mddev);
- return -EEXIST;
+ goto abort;
}
spin_unlock(&all_mddevs_lock);
}

+ error = -ENOMEM;
mddev->queue = blk_alloc_queue(GFP_KERNEL);
- if (!mddev->queue) {
- mutex_unlock(&disks_mutex);
- mddev_put(mddev);
- return -ENOMEM;
- }
+ if (!mddev->queue)
+ goto abort;
mddev->queue->queuedata = mddev;

/* Can be unlocked because the queue is new: no concurrency */
@@ -3884,11 +3878,9 @@ static int md_alloc(dev_t dev, char *name)

disk = alloc_disk(1 << shift);
if (!disk) {
- mutex_unlock(&disks_mutex);
blk_cleanup_queue(mddev->queue);
mddev->queue = NULL;
- mddev_put(mddev);
- return -ENOMEM;
+ goto abort;
}
disk->major = MAJOR(mddev->unit);
disk->first_minor = unit << shift;
@@ -3910,16 +3902,22 @@ static int md_alloc(dev_t dev, char *name)
mddev->gendisk = disk;
error = kobject_init_and_add(&mddev->kobj, &md_ktype,
&disk_to_dev(disk)->kobj, "%s", "md");
- mutex_unlock(&disks_mutex);
- if (error)
+ if (error) {
+ /* This isn't possible, but as kobject_init_and_add is marked
+ * __must_check, we must do something with the result
+ */
printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
disk->disk_name);
- else {
+ error = 0;
+ }
+ abort:
+ mutex_unlock(&disks_mutex);
+ if (!error) {
kobject_uevent(&mddev->kobj, KOBJ_ADD);
mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state");
}
mddev_put(mddev);
- return 0;
+ return error;
}

static struct kobject *md_probe(dev_t dev, int *part, void *data)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



Relevant Pages

  • Oracle support is just cracking me up
    ... I have had an SR with an open bug for 5/6 months now (more I guess it ... well they want to close my bug as a duplicate of another bug (did ... fixes ... ...
    (comp.databases.oracle.server)
  • Re: [PATCH 2.4] i2c cleanups, third wave
    ... > I want to merge only bug fixes or practical corrections. ... Bus scanning is known to be possibly harmful, ... 1* I can submit "light" versions of the patches that only contain the ...
    (Linux-Kernel)
  • Re: Open Delphi?
    ... I didn't see any claim made by Open Delphi to that end. ... would not have to wait for "the new version" to apply fixes for known ... Enhancements and bug fixes could begin ... Another developer ended up writing a VB "relay" application to ferry ...
    (borland.public.delphi.non-technical)
  • Re: network home folder not mapped correctly
    ... Yeah, I hope this fixes it, it sure is like a bug, but at least we probably ... But the homeshare should have a big warning in it's description to make sure ... I have now been testing the GPO change for a while, ...
    (microsoft.public.windowsxp.general)
  • Insight from Borland developer on bugfix status
    ... fixes are written but the process for releasing ... have you applied all the patches?". ... JB>that I write bug free code. ...
    (borland.public.delphi.non-technical)