aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2014-08-08 17:21:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-08 18:57:22 -0400
commitdbcdb504417ae108a20454ef89776a614b948571 (patch)
tree397a024e382d28f09ccb020d4a2daedd2d251e9d /fs/proc
parentccf94f1b4a8560ffdc221840535bae5e5a91a53c (diff)
proc: add and remove /proc entry create checks
* remove proc_create(NULL, ...) check, let it oops * warn about proc_create("", ...) and proc_create("very very long name", ...) proc code keeps length as u8, no 256+ name length possible * warn about proc_create("123", ...) /proc/$PID and /proc/misc namespaces are separate things, but dumb module might create funky a-la $PID entry. * remove post mortem strchr('/') check Triggering it implies either strchr() is buggy or memory corruption. It should be VFS check anyway. In reality, none of these checks will ever trigger, it is preparation for the next patch. Based on patch from Al Viro. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c4
-rw-r--r--fs/proc/fd.c2
-rw-r--r--fs/proc/generic.c30
-rw-r--r--fs/proc/internal.h6
4 files changed, 21 insertions, 21 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 79df9ff71afd..11375216b493 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2785,7 +2785,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsign
2785 unsigned tgid; 2785 unsigned tgid;
2786 struct pid_namespace *ns; 2786 struct pid_namespace *ns;
2787 2787
2788 tgid = name_to_int(dentry); 2788 tgid = name_to_int(&dentry->d_name);
2789 if (tgid == ~0U) 2789 if (tgid == ~0U)
2790 goto out; 2790 goto out;
2791 2791
@@ -3033,7 +3033,7 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
3033 if (!leader) 3033 if (!leader)
3034 goto out_no_task; 3034 goto out_no_task;
3035 3035
3036 tid = name_to_int(dentry); 3036 tid = name_to_int(&dentry->d_name);
3037 if (tid == ~0U) 3037 if (tid == ~0U)
3038 goto out; 3038 goto out;
3039 3039
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 0788d093f5d8..955bb55fab8c 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -206,7 +206,7 @@ static struct dentry *proc_lookupfd_common(struct inode *dir,
206{ 206{
207 struct task_struct *task = get_proc_task(dir); 207 struct task_struct *task = get_proc_task(dir);
208 int result = -ENOENT; 208 int result = -ENOENT;
209 unsigned fd = name_to_int(dentry); 209 unsigned fd = name_to_int(&dentry->d_name);
210 210
211 if (!task) 211 if (!task)
212 goto out_no_task; 212 goto out_no_task;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index b7f268eb5f45..190862e89880 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -330,28 +330,28 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
330 nlink_t nlink) 330 nlink_t nlink)
331{ 331{
332 struct proc_dir_entry *ent = NULL; 332 struct proc_dir_entry *ent = NULL;
333 const char *fn = name; 333 const char *fn;
334 unsigned int len; 334 struct qstr qstr;
335
336 /* make sure name is valid */
337 if (!name || !strlen(name))
338 goto out;
339 335
340 if (xlate_proc_name(name, parent, &fn) != 0) 336 if (xlate_proc_name(name, parent, &fn) != 0)
341 goto out; 337 goto out;
338 qstr.name = fn;
339 qstr.len = strlen(fn);
340 if (qstr.len == 0 || qstr.len >= 256) {
341 WARN(1, "name len %u\n", qstr.len);
342 return NULL;
343 }
344 if (*parent == &proc_root && name_to_int(&qstr) != ~0U) {
345 WARN(1, "create '/proc/%s' by hand\n", qstr.name);
346 return NULL;
347 }
342 348
343 /* At this point there must not be any '/' characters beyond *fn */ 349 ent = kzalloc(sizeof(struct proc_dir_entry) + qstr.len + 1, GFP_KERNEL);
344 if (strchr(fn, '/'))
345 goto out;
346
347 len = strlen(fn);
348
349 ent = kzalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
350 if (!ent) 350 if (!ent)
351 goto out; 351 goto out;
352 352
353 memcpy(ent->name, fn, len + 1); 353 memcpy(ent->name, fn, qstr.len + 1);
354 ent->namelen = len; 354 ent->namelen = qstr.len;
355 ent->mode = mode; 355 ent->mode = mode;
356 ent->nlink = nlink; 356 ent->nlink = nlink;
357 atomic_set(&ent->count, 1); 357 atomic_set(&ent->count, 1);
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 3ab6d14e71c5..a38408a1dd84 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -112,10 +112,10 @@ static inline int task_dumpable(struct task_struct *task)
112 return 0; 112 return 0;
113} 113}
114 114
115static inline unsigned name_to_int(struct dentry *dentry) 115static inline unsigned name_to_int(const struct qstr *qstr)
116{ 116{
117 const char *name = dentry->d_name.name; 117 const char *name = qstr->name;
118 int len = dentry->d_name.len; 118 int len = qstr->len;
119 unsigned n = 0; 119 unsigned n = 0;
120 120
121 if (len > 1 && *name == '0') 121 if (len > 1 && *name == '0')