Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7695650a924a6859910c8c19dfa43b4d08224d66
Commit:     7695650a924a6859910c8c19dfa43b4d08224d66
Parent:     79c0b2df79eb56fc71e54c75cd7fb3acf84370f9
Author:     Alexey Dobriyan <[EMAIL PROTECTED]>
AuthorDate: Tue May 8 00:25:45 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue May 8 11:15:01 2007 -0700

    Fix race between proc_get_inode() and remove_proc_entry()
    
    proc_lookup                         remove_proc_entry
    ===========                         =================
    
    lock_kernel();
    spin_lock(&proc_subdir_lock);
    [find PDE with refcount 0]
    spin_unlock(&proc_subdir_lock);
                                        spin_lock(&proc_subdir_lock);
                                        [find PDE with refcount 0]
                                        [check refcount and free PDE]
                                        spin_unlock(&proc_subdir_lock);
    proc_get_inode:
        de_get(de); /* boom */
    
    Signed-off-by: Alexey Dobriyan <[EMAIL PROTECTED]>
    Cc: "Eric W. Biederman" <[EMAIL PROTECTED]>
    Cc: Oleg Nesterov <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/proc/generic.c       |    2 ++
 fs/proc/inode.c         |   12 ++++--------
 include/linux/proc_fs.h |    3 +++
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 775fb21..22a08ff 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -398,6 +398,7 @@ struct dentry *proc_lookup(struct inode * dir, struct 
dentry *dentry, struct nam
                        if (!memcmp(dentry->d_name.name, de->name, 
de->namelen)) {
                                unsigned int ino = de->low_ino;
 
+                               de_get(de);
                                spin_unlock(&proc_subdir_lock);
                                error = -EINVAL;
                                inode = proc_get_inode(dir->i_sb, ino, de);
@@ -414,6 +415,7 @@ struct dentry *proc_lookup(struct inode * dir, struct 
dentry *dentry, struct nam
                d_add(dentry, inode);
                return NULL;
        }
+       de_put(de);
        return ERR_PTR(error);
 }
 
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 22b1158..d1de637 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -21,7 +21,7 @@
 
 #include "internal.h"
 
-static inline struct proc_dir_entry * de_get(struct proc_dir_entry *de)
+struct proc_dir_entry *de_get(struct proc_dir_entry *de)
 {
        if (de)
                atomic_inc(&de->count);
@@ -31,7 +31,7 @@ static inline struct proc_dir_entry * de_get(struct 
proc_dir_entry *de)
 /*
  * Decrements the use count and checks for deferred deletion.
  */
-static void de_put(struct proc_dir_entry *de)
+void de_put(struct proc_dir_entry *de)
 {
        if (de) {       
                lock_kernel();          
@@ -146,11 +146,6 @@ struct inode *proc_get_inode(struct super_block *sb, 
unsigned int ino,
 {
        struct inode * inode;
 
-       /*
-        * Increment the use count so the dir entry can't disappear.
-        */
-       de_get(de);
-
        WARN_ON(de && de->deleted);
 
        if (de != NULL && !try_module_get(de->owner))
@@ -184,7 +179,6 @@ out_ino:
        if (de != NULL)
                module_put(de->owner);
 out_mod:
-       de_put(de);
        return NULL;
 }                      
 
@@ -199,6 +193,7 @@ int proc_fill_super(struct super_block *s, void *data, int 
silent)
        s->s_op = &proc_sops;
        s->s_time_gran = 1;
        
+       de_get(&proc_root);
        root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
        if (!root_inode)
                goto out_no_root;
@@ -212,6 +207,7 @@ int proc_fill_super(struct super_block *s, void *data, int 
silent)
 out_no_root:
        printk("proc_read_super: get root inode failed\n");
        iput(root_inode);
+       de_put(&proc_root);
        return -ENOMEM;
 }
 MODULE_LICENSE("GPL");
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index f4f7a63..3469f96 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -106,6 +106,9 @@ int task_statm(struct mm_struct *, int *, int *, int *, int 
*);
 char *task_mem(struct mm_struct *, char *);
 void clear_refs_smap(struct mm_struct *mm);
 
+struct proc_dir_entry *de_get(struct proc_dir_entry *de);
+void de_put(struct proc_dir_entry *de);
+
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
                                                struct proc_dir_entry *parent);
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to