diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2009-10-28 19:51:06 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 11:24:51 -0800 |
commit | ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21 (patch) | |
tree | 648580b63fd02a8abd55b1f84171f93c2956dbe5 | |
parent | 0092699643703aefca6af0aa758a73f1624d53be (diff) | |
download | kernel-crypto-ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21.tar.gz kernel-crypto-ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21.tar.xz kernel-crypto-ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21.zip |
Driver core: devtmpfs: prevent concurrent subdirectory creation and removal
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/base/devtmpfs.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 48526b93568..1cf498fd2b5 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -32,6 +32,8 @@ static int dev_mount = 1; static int dev_mount; #endif +static rwlock_t dirlock; + static int __init mount_param(char *str) { dev_mount = simple_strtoul(str, NULL, 0); @@ -86,16 +88,12 @@ static int dev_mkdir(const char *name, mode_t mode) static int create_path(const char *nodepath) { - char *path; struct nameidata nd; int err = 0; - path = kstrdup(nodepath, GFP_KERNEL); - if (!path) - return -ENOMEM; - + read_lock(&dirlock); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, - path, LOOKUP_PARENT, &nd); + nodepath, LOOKUP_PARENT, &nd); if (err == 0) { struct dentry *dentry; @@ -107,14 +105,17 @@ static int create_path(const char *nodepath) dput(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); - path_put(&nd.path); } else if (err == -ENOENT) { + char *path; char *s; /* parent directories do not exist, create them */ + path = kstrdup(nodepath, GFP_KERNEL); + if (!path) + return -ENOMEM; s = path; - while (1) { + for (;;) { s = strchr(s, '/'); if (!s) break; @@ -125,9 +126,10 @@ static int create_path(const char *nodepath) s[0] = '/'; s++; } + kfree(path); } + read_unlock(&dirlock); - kfree(path); return err; } @@ -234,7 +236,8 @@ static int delete_path(const char *nodepath) if (!path) return -ENOMEM; - while (1) { + write_lock(&dirlock); + for (;;) { char *base; base = strrchr(path, '/'); @@ -245,6 +248,7 @@ static int delete_path(const char *nodepath) if (err) break; } + write_unlock(&dirlock); kfree(path); return err; @@ -360,6 +364,8 @@ int __init devtmpfs_init(void) int err; struct vfsmount *mnt; + rwlock_init(&dirlock); + err = register_filesystem(&dev_fs_type); if (err) { printk(KERN_ERR "devtmpfs: unable to register devtmpfs " |