diff options
author | David Herrmann <dh.herrmann@googlemail.com> | 2012-11-17 12:45:48 +0100 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2013-01-17 13:04:57 +0100 |
commit | 30783587b0f318b9e2e165f34cf5dfd9425a4904 (patch) | |
tree | 4aeaf43d76cda5cad2c968214c1efce047f53f71 /fs/fuse/cuse.c | |
parent | 8ce03fd76d323526a693d05d85296ef07a387a9f (diff) | |
download | linux-stable-30783587b0f318b9e2e165f34cf5dfd9425a4904.tar.gz linux-stable-30783587b0f318b9e2e165f34cf5dfd9425a4904.tar.bz2 linux-stable-30783587b0f318b9e2e165f34cf5dfd9425a4904.zip |
cuse: do not register multiple devices with identical names
Sysfs doesn't allow two devices with the same name, but we register a
sysfs entry for each cuse device without checking for name collisions.
This extends the registration to first check whether the name was already
registered.
To avoid race-conditions between the name-check and linking the device, we
need to protect the whole registration with a mutex.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse/cuse.c')
-rw-r--r-- | fs/fuse/cuse.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 048e89f25082..2a2797e2abc5 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -304,14 +304,14 @@ static void cuse_gendev_release(struct device *dev) */ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) { - struct cuse_conn *cc = fc_to_cc(fc); + struct cuse_conn *cc = fc_to_cc(fc), *pos; struct cuse_init_out *arg = req->out.args[0].value; struct page *page = req->pages[0]; struct cuse_devinfo devinfo = { }; struct device *dev; struct cdev *cdev; dev_t devt; - int rc; + int rc, i; if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) { @@ -355,15 +355,24 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) dev_set_drvdata(dev, cc); dev_set_name(dev, "%s", devinfo.name); + mutex_lock(&cuse_lock); + + /* make sure the device-name is unique */ + for (i = 0; i < CUSE_CONNTBL_LEN; ++i) { + list_for_each_entry(pos, &cuse_conntbl[i], list) + if (!strcmp(dev_name(pos->dev), dev_name(dev))) + goto err_unlock; + } + rc = device_add(dev); if (rc) - goto err_device; + goto err_unlock; /* register cdev */ rc = -ENOMEM; cdev = cdev_alloc(); if (!cdev) - goto err_device; + goto err_unlock; cdev->owner = THIS_MODULE; cdev->ops = &cuse_frontend_fops; @@ -376,7 +385,6 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) cc->cdev = cdev; /* make the device available */ - mutex_lock(&cuse_lock); list_add(&cc->list, cuse_conntbl_head(devt)); mutex_unlock(&cuse_lock); @@ -390,7 +398,8 @@ out: err_cdev: cdev_del(cdev); -err_device: +err_unlock: + mutex_unlock(&cuse_lock); put_device(dev); err_region: unregister_chrdev_region(devt, 1); |