aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/generic.c')
-rw-r--r--fs/proc/generic.c71
1 files changed, 28 insertions, 43 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index e064f562b1f7..4b3b3ffb52f1 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -15,6 +15,7 @@
15#include <linux/mm.h> 15#include <linux/mm.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/printk.h>
18#include <linux/mount.h> 19#include <linux/mount.h>
19#include <linux/init.h> 20#include <linux/init.h>
20#include <linux/idr.h> 21#include <linux/idr.h>
@@ -42,7 +43,7 @@ static ssize_t
42__proc_file_read(struct file *file, char __user *buf, size_t nbytes, 43__proc_file_read(struct file *file, char __user *buf, size_t nbytes,
43 loff_t *ppos) 44 loff_t *ppos)
44{ 45{
45 struct inode * inode = file->f_path.dentry->d_inode; 46 struct inode * inode = file_inode(file);
46 char *page; 47 char *page;
47 ssize_t retval=0; 48 ssize_t retval=0;
48 int eof=0; 49 int eof=0;
@@ -132,11 +133,8 @@ __proc_file_read(struct file *file, char __user *buf, size_t nbytes,
132 } 133 }
133 134
134 if (start == NULL) { 135 if (start == NULL) {
135 if (n > PAGE_SIZE) { 136 if (n > PAGE_SIZE) /* Apparent buffer overflow */
136 printk(KERN_ERR
137 "proc_file_read: Apparent buffer overflow!\n");
138 n = PAGE_SIZE; 137 n = PAGE_SIZE;
139 }
140 n -= *ppos; 138 n -= *ppos;
141 if (n <= 0) 139 if (n <= 0)
142 break; 140 break;
@@ -144,26 +142,19 @@ __proc_file_read(struct file *file, char __user *buf, size_t nbytes,
144 n = count; 142 n = count;
145 start = page + *ppos; 143 start = page + *ppos;
146 } else if (start < page) { 144 } else if (start < page) {
147 if (n > PAGE_SIZE) { 145 if (n > PAGE_SIZE) /* Apparent buffer overflow */
148 printk(KERN_ERR
149 "proc_file_read: Apparent buffer overflow!\n");
150 n = PAGE_SIZE; 146 n = PAGE_SIZE;
151 }
152 if (n > count) { 147 if (n > count) {
153 /* 148 /*
154 * Don't reduce n because doing so might 149 * Don't reduce n because doing so might
155 * cut off part of a data block. 150 * cut off part of a data block.
156 */ 151 */
157 printk(KERN_WARNING 152 pr_warn("proc_file_read: count exceeded\n");
158 "proc_file_read: Read count exceeded\n");
159 } 153 }
160 } else /* start >= page */ { 154 } else /* start >= page */ {
161 unsigned long startoff = (unsigned long)(start - page); 155 unsigned long startoff = (unsigned long)(start - page);
162 if (n > (PAGE_SIZE - startoff)) { 156 if (n > (PAGE_SIZE - startoff)) /* buffer overflow? */
163 printk(KERN_ERR
164 "proc_file_read: Apparent buffer overflow!\n");
165 n = PAGE_SIZE - startoff; 157 n = PAGE_SIZE - startoff;
166 }
167 if (n > count) 158 if (n > count)
168 n = count; 159 n = count;
169 } 160 }
@@ -188,7 +179,7 @@ static ssize_t
188proc_file_read(struct file *file, char __user *buf, size_t nbytes, 179proc_file_read(struct file *file, char __user *buf, size_t nbytes,
189 loff_t *ppos) 180 loff_t *ppos)
190{ 181{
191 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); 182 struct proc_dir_entry *pde = PDE(file_inode(file));
192 ssize_t rv = -EIO; 183 ssize_t rv = -EIO;
193 184
194 spin_lock(&pde->pde_unload_lock); 185 spin_lock(&pde->pde_unload_lock);
@@ -209,7 +200,7 @@ static ssize_t
209proc_file_write(struct file *file, const char __user *buffer, 200proc_file_write(struct file *file, const char __user *buffer,
210 size_t count, loff_t *ppos) 201 size_t count, loff_t *ppos)
211{ 202{
212 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); 203 struct proc_dir_entry *pde = PDE(file_inode(file));
213 ssize_t rv = -EIO; 204 ssize_t rv = -EIO;
214 205
215 if (pde->write_proc) { 206 if (pde->write_proc) {
@@ -352,18 +343,18 @@ retry:
352 if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL)) 343 if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
353 return -ENOMEM; 344 return -ENOMEM;
354 345
355 spin_lock_bh(&proc_inum_lock); 346 spin_lock_irq(&proc_inum_lock);
356 error = ida_get_new(&proc_inum_ida, &i); 347 error = ida_get_new(&proc_inum_ida, &i);
357 spin_unlock_bh(&proc_inum_lock); 348 spin_unlock_irq(&proc_inum_lock);
358 if (error == -EAGAIN) 349 if (error == -EAGAIN)
359 goto retry; 350 goto retry;
360 else if (error) 351 else if (error)
361 return error; 352 return error;
362 353
363 if (i > UINT_MAX - PROC_DYNAMIC_FIRST) { 354 if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
364 spin_lock_bh(&proc_inum_lock); 355 spin_lock_irq(&proc_inum_lock);
365 ida_remove(&proc_inum_ida, i); 356 ida_remove(&proc_inum_ida, i);
366 spin_unlock_bh(&proc_inum_lock); 357 spin_unlock_irq(&proc_inum_lock);
367 return -ENOSPC; 358 return -ENOSPC;
368 } 359 }
369 *inum = PROC_DYNAMIC_FIRST + i; 360 *inum = PROC_DYNAMIC_FIRST + i;
@@ -372,9 +363,10 @@ retry:
372 363
373void proc_free_inum(unsigned int inum) 364void proc_free_inum(unsigned int inum)
374{ 365{
375 spin_lock_bh(&proc_inum_lock); 366 unsigned long flags;
367 spin_lock_irqsave(&proc_inum_lock, flags);
376 ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST); 368 ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
377 spin_unlock_bh(&proc_inum_lock); 369 spin_unlock_irqrestore(&proc_inum_lock, flags);
378} 370}
379 371
380static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) 372static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
@@ -411,8 +403,7 @@ static const struct dentry_operations proc_dentry_operations =
411struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir, 403struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
412 struct dentry *dentry) 404 struct dentry *dentry)
413{ 405{
414 struct inode *inode = NULL; 406 struct inode *inode;
415 int error = -ENOENT;
416 407
417 spin_lock(&proc_subdir_lock); 408 spin_lock(&proc_subdir_lock);
418 for (de = de->subdir; de ; de = de->next) { 409 for (de = de->subdir; de ; de = de->next) {
@@ -421,22 +412,16 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
421 if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { 412 if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
422 pde_get(de); 413 pde_get(de);
423 spin_unlock(&proc_subdir_lock); 414 spin_unlock(&proc_subdir_lock);
424 error = -ENOMEM;
425 inode = proc_get_inode(dir->i_sb, de); 415 inode = proc_get_inode(dir->i_sb, de);
426 goto out_unlock; 416 if (!inode)
417 return ERR_PTR(-ENOMEM);
418 d_set_d_op(dentry, &proc_dentry_operations);
419 d_add(dentry, inode);
420 return NULL;
427 } 421 }
428 } 422 }
429 spin_unlock(&proc_subdir_lock); 423 spin_unlock(&proc_subdir_lock);
430out_unlock: 424 return ERR_PTR(-ENOENT);
431
432 if (inode) {
433 d_set_d_op(dentry, &proc_dentry_operations);
434 d_add(dentry, inode);
435 return NULL;
436 }
437 if (de)
438 pde_put(de);
439 return ERR_PTR(error);
440} 425}
441 426
442struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, 427struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
@@ -459,7 +444,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
459{ 444{
460 unsigned int ino; 445 unsigned int ino;
461 int i; 446 int i;
462 struct inode *inode = filp->f_path.dentry->d_inode; 447 struct inode *inode = file_inode(filp);
463 int ret = 0; 448 int ret = 0;
464 449
465 ino = inode->i_ino; 450 ino = inode->i_ino;
@@ -521,7 +506,7 @@ out:
521 506
522int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) 507int proc_readdir(struct file *filp, void *dirent, filldir_t filldir)
523{ 508{
524 struct inode *inode = filp->f_path.dentry->d_inode; 509 struct inode *inode = file_inode(filp);
525 510
526 return proc_readdir_de(PDE(inode), filp, dirent, filldir); 511 return proc_readdir_de(PDE(inode), filp, dirent, filldir);
527} 512}
@@ -575,7 +560,7 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
575 560
576 for (tmp = dir->subdir; tmp; tmp = tmp->next) 561 for (tmp = dir->subdir; tmp; tmp = tmp->next)
577 if (strcmp(tmp->name, dp->name) == 0) { 562 if (strcmp(tmp->name, dp->name) == 0) {
578 WARN(1, KERN_WARNING "proc_dir_entry '%s/%s' already registered\n", 563 WARN(1, "proc_dir_entry '%s/%s' already registered\n",
579 dir->name, dp->name); 564 dir->name, dp->name);
580 break; 565 break;
581 } 566 }
@@ -836,9 +821,9 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
836 if (S_ISDIR(de->mode)) 821 if (S_ISDIR(de->mode))
837 parent->nlink--; 822 parent->nlink--;
838 de->nlink = 0; 823 de->nlink = 0;
839 WARN(de->subdir, KERN_WARNING "%s: removing non-empty directory " 824 WARN(de->subdir, "%s: removing non-empty directory "
840 "'%s/%s', leaking at least '%s'\n", __func__, 825 "'%s/%s', leaking at least '%s'\n", __func__,
841 de->parent->name, de->name, de->subdir->name); 826 de->parent->name, de->name, de->subdir->name);
842 pde_put(de); 827 pde_put(de);
843} 828}
844EXPORT_SYMBOL(remove_proc_entry); 829EXPORT_SYMBOL(remove_proc_entry);