aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/generic.c
diff options
context:
space:
mode:
authorDebabrata Banerjee <dbanerje@akamai.com>2014-12-10 18:45:04 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 20:41:09 -0500
commitb208d54b75399b276b05f9e70cce8d3a59a42547 (patch)
tree6fceaa2169ca97be38c6dd7561542194dbca553b /fs/proc/generic.c
parent710585d4922fd315f2cada8fbe550ae8ed23e994 (diff)
procfs: fix error handling of proc_register()
proc_register() error paths are leaking inodes and directory refcounts. Signed-off-by: Debabrata Banerjee <dbanerje@akamai.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc/generic.c')
-rw-r--r--fs/proc/generic.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 9f8fa1e5e8aa..be39c6feb3e5 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -369,14 +369,21 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
369 dp->proc_iops = &proc_file_inode_operations; 369 dp->proc_iops = &proc_file_inode_operations;
370 } else { 370 } else {
371 WARN_ON(1); 371 WARN_ON(1);
372 proc_free_inum(dp->low_ino);
372 return -EINVAL; 373 return -EINVAL;
373 } 374 }
374 375
375 spin_lock(&proc_subdir_lock); 376 spin_lock(&proc_subdir_lock);
376 dp->parent = dir; 377 dp->parent = dir;
377 if (pde_subdir_insert(dir, dp) == false) 378 if (pde_subdir_insert(dir, dp) == false) {
378 WARN(1, "proc_dir_entry '%s/%s' already registered\n", 379 WARN(1, "proc_dir_entry '%s/%s' already registered\n",
379 dir->name, dp->name); 380 dir->name, dp->name);
381 spin_unlock(&proc_subdir_lock);
382 if (S_ISDIR(dp->mode))
383 dir->nlink--;
384 proc_free_inum(dp->low_ino);
385 return -EEXIST;
386 }
380 spin_unlock(&proc_subdir_lock); 387 spin_unlock(&proc_subdir_lock);
381 388
382 return 0; 389 return 0;