diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2009-10-28 14:51:06 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 14:24:51 -0500 |
commit | ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21 (patch) | |
tree | 648580b63fd02a8abd55b1f84171f93c2956dbe5 /drivers/base/devtmpfs.c | |
parent | 0092699643703aefca6af0aa758a73f1624d53be (diff) |
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>
Diffstat (limited to 'drivers/base/devtmpfs.c')
-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 48526b935682..1cf498fd2b52 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c | |||
@@ -32,6 +32,8 @@ static int dev_mount = 1; | |||
32 | static int dev_mount; | 32 | static int dev_mount; |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | static rwlock_t dirlock; | ||
36 | |||
35 | static int __init mount_param(char *str) | 37 | static int __init mount_param(char *str) |
36 | { | 38 | { |
37 | dev_mount = simple_strtoul(str, NULL, 0); | 39 | dev_mount = simple_strtoul(str, NULL, 0); |
@@ -86,16 +88,12 @@ static int dev_mkdir(const char *name, mode_t mode) | |||
86 | 88 | ||
87 | static int create_path(const char *nodepath) | 89 | static int create_path(const char *nodepath) |
88 | { | 90 | { |
89 | char *path; | ||
90 | struct nameidata nd; | 91 | struct nameidata nd; |
91 | int err = 0; | 92 | int err = 0; |
92 | 93 | ||
93 | path = kstrdup(nodepath, GFP_KERNEL); | 94 | read_lock(&dirlock); |
94 | if (!path) | ||
95 | return -ENOMEM; | ||
96 | |||
97 | err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, | 95 | err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, |
98 | path, LOOKUP_PARENT, &nd); | 96 | nodepath, LOOKUP_PARENT, &nd); |
99 | if (err == 0) { | 97 | if (err == 0) { |
100 | struct dentry *dentry; | 98 | struct dentry *dentry; |
101 | 99 | ||
@@ -107,14 +105,17 @@ static int create_path(const char *nodepath) | |||
107 | dput(dentry); | 105 | dput(dentry); |
108 | } | 106 | } |
109 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 107 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
110 | |||
111 | path_put(&nd.path); | 108 | path_put(&nd.path); |
112 | } else if (err == -ENOENT) { | 109 | } else if (err == -ENOENT) { |
110 | char *path; | ||
113 | char *s; | 111 | char *s; |
114 | 112 | ||
115 | /* parent directories do not exist, create them */ | 113 | /* parent directories do not exist, create them */ |
114 | path = kstrdup(nodepath, GFP_KERNEL); | ||
115 | if (!path) | ||
116 | return -ENOMEM; | ||
116 | s = path; | 117 | s = path; |
117 | while (1) { | 118 | for (;;) { |
118 | s = strchr(s, '/'); | 119 | s = strchr(s, '/'); |
119 | if (!s) | 120 | if (!s) |
120 | break; | 121 | break; |
@@ -125,9 +126,10 @@ static int create_path(const char *nodepath) | |||
125 | s[0] = '/'; | 126 | s[0] = '/'; |
126 | s++; | 127 | s++; |
127 | } | 128 | } |
129 | kfree(path); | ||
128 | } | 130 | } |
131 | read_unlock(&dirlock); | ||
129 | 132 | ||
130 | kfree(path); | ||
131 | return err; | 133 | return err; |
132 | } | 134 | } |
133 | 135 | ||
@@ -234,7 +236,8 @@ static int delete_path(const char *nodepath) | |||
234 | if (!path) | 236 | if (!path) |
235 | return -ENOMEM; | 237 | return -ENOMEM; |
236 | 238 | ||
237 | while (1) { | 239 | write_lock(&dirlock); |
240 | for (;;) { | ||
238 | char *base; | 241 | char *base; |
239 | 242 | ||
240 | base = strrchr(path, '/'); | 243 | base = strrchr(path, '/'); |
@@ -245,6 +248,7 @@ static int delete_path(const char *nodepath) | |||
245 | if (err) | 248 | if (err) |
246 | break; | 249 | break; |
247 | } | 250 | } |
251 | write_unlock(&dirlock); | ||
248 | 252 | ||
249 | kfree(path); | 253 | kfree(path); |
250 | return err; | 254 | return err; |
@@ -360,6 +364,8 @@ int __init devtmpfs_init(void) | |||
360 | int err; | 364 | int err; |
361 | struct vfsmount *mnt; | 365 | struct vfsmount *mnt; |
362 | 366 | ||
367 | rwlock_init(&dirlock); | ||
368 | |||
363 | err = register_filesystem(&dev_fs_type); | 369 | err = register_filesystem(&dev_fs_type); |
364 | if (err) { | 370 | if (err) { |
365 | printk(KERN_ERR "devtmpfs: unable to register devtmpfs " | 371 | printk(KERN_ERR "devtmpfs: unable to register devtmpfs " |