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.c80
1 files changed, 29 insertions, 51 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 7b3ae3cc0ef9..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) {
@@ -261,16 +252,9 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
261 if (error) 252 if (error)
262 return error; 253 return error;
263 254
264 if ((iattr->ia_valid & ATTR_SIZE) &&
265 iattr->ia_size != i_size_read(inode)) {
266 error = vmtruncate(inode, iattr->ia_size);
267 if (error)
268 return error;
269 }
270
271 setattr_copy(inode, iattr); 255 setattr_copy(inode, iattr);
272 mark_inode_dirty(inode); 256 mark_inode_dirty(inode);
273 257
274 de->uid = inode->i_uid; 258 de->uid = inode->i_uid;
275 de->gid = inode->i_gid; 259 de->gid = inode->i_gid;
276 de->mode = inode->i_mode; 260 de->mode = inode->i_mode;
@@ -359,18 +343,18 @@ retry:
359 if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL)) 343 if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
360 return -ENOMEM; 344 return -ENOMEM;
361 345
362 spin_lock(&proc_inum_lock); 346 spin_lock_irq(&proc_inum_lock);
363 error = ida_get_new(&proc_inum_ida, &i); 347 error = ida_get_new(&proc_inum_ida, &i);
364 spin_unlock(&proc_inum_lock); 348 spin_unlock_irq(&proc_inum_lock);
365 if (error == -EAGAIN) 349 if (error == -EAGAIN)
366 goto retry; 350 goto retry;
367 else if (error) 351 else if (error)
368 return error; 352 return error;
369 353
370 if (i > UINT_MAX - PROC_DYNAMIC_FIRST) { 354 if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
371 spin_lock(&proc_inum_lock); 355 spin_lock_irq(&proc_inum_lock);
372 ida_remove(&proc_inum_ida, i); 356 ida_remove(&proc_inum_ida, i);
373 spin_unlock(&proc_inum_lock); 357 spin_unlock_irq(&proc_inum_lock);
374 return -ENOSPC; 358 return -ENOSPC;
375 } 359 }
376 *inum = PROC_DYNAMIC_FIRST + i; 360 *inum = PROC_DYNAMIC_FIRST + i;
@@ -379,9 +363,10 @@ retry:
379 363
380void proc_free_inum(unsigned int inum) 364void proc_free_inum(unsigned int inum)
381{ 365{
382 spin_lock(&proc_inum_lock); 366 unsigned long flags;
367 spin_lock_irqsave(&proc_inum_lock, flags);
383 ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST); 368 ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
384 spin_unlock(&proc_inum_lock); 369 spin_unlock_irqrestore(&proc_inum_lock, flags);
385} 370}
386 371
387static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) 372static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
@@ -418,8 +403,7 @@ static const struct dentry_operations proc_dentry_operations =
418struct 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,
419 struct dentry *dentry) 404 struct dentry *dentry)
420{ 405{
421 struct inode *inode = NULL; 406 struct inode *inode;
422 int error = -ENOENT;
423 407
424 spin_lock(&proc_subdir_lock); 408 spin_lock(&proc_subdir_lock);
425 for (de = de->subdir; de ; de = de->next) { 409 for (de = de->subdir; de ; de = de->next) {
@@ -428,22 +412,16 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
428 if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { 412 if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
429 pde_get(de); 413 pde_get(de);
430 spin_unlock(&proc_subdir_lock); 414 spin_unlock(&proc_subdir_lock);
431 error = -ENOMEM;
432 inode = proc_get_inode(dir->i_sb, de); 415 inode = proc_get_inode(dir->i_sb, de);
433 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;
434 } 421 }
435 } 422 }
436 spin_unlock(&proc_subdir_lock); 423 spin_unlock(&proc_subdir_lock);
437out_unlock: 424 return ERR_PTR(-ENOENT);
438
439 if (inode) {
440 d_set_d_op(dentry, &proc_dentry_operations);
441 d_add(dentry, inode);
442 return NULL;
443 }
444 if (de)
445 pde_put(de);
446 return ERR_PTR(error);
447} 425}
448 426
449struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, 427struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
@@ -466,7 +444,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
466{ 444{
467 unsigned int ino; 445 unsigned int ino;
468 int i; 446 int i;
469 struct inode *inode = filp->f_path.dentry->d_inode; 447 struct inode *inode = file_inode(filp);
470 int ret = 0; 448 int ret = 0;
471 449
472 ino = inode->i_ino; 450 ino = inode->i_ino;
@@ -528,7 +506,7 @@ out:
528 506
529int proc_readdir(struct file *filp, void *dirent, filldir_t filldir) 507int proc_readdir(struct file *filp, void *dirent, filldir_t filldir)
530{ 508{
531 struct inode *inode = filp->f_path.dentry->d_inode; 509 struct inode *inode = file_inode(filp);
532 510
533 return proc_readdir_de(PDE(inode), filp, dirent, filldir); 511 return proc_readdir_de(PDE(inode), filp, dirent, filldir);
534} 512}
@@ -582,7 +560,7 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
582 560
583 for (tmp = dir->subdir; tmp; tmp = tmp->next) 561 for (tmp = dir->subdir; tmp; tmp = tmp->next)
584 if (strcmp(tmp->name, dp->name) == 0) { 562 if (strcmp(tmp->name, dp->name) == 0) {
585 WARN(1, KERN_WARNING "proc_dir_entry '%s/%s' already registered\n", 563 WARN(1, "proc_dir_entry '%s/%s' already registered\n",
586 dir->name, dp->name); 564 dir->name, dp->name);
587 break; 565 break;
588 } 566 }
@@ -843,9 +821,9 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
843 if (S_ISDIR(de->mode)) 821 if (S_ISDIR(de->mode))
844 parent->nlink--; 822 parent->nlink--;
845 de->nlink = 0; 823 de->nlink = 0;
846 WARN(de->subdir, KERN_WARNING "%s: removing non-empty directory " 824 WARN(de->subdir, "%s: removing non-empty directory "
847 "'%s/%s', leaking at least '%s'\n", __func__, 825 "'%s/%s', leaking at least '%s'\n", __func__,
848 de->parent->name, de->name, de->subdir->name); 826 de->parent->name, de->name, de->subdir->name);
849 pde_put(de); 827 pde_put(de);
850} 828}
851EXPORT_SYMBOL(remove_proc_entry); 829EXPORT_SYMBOL(remove_proc_entry);