Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6f4e643353aea52d80f33960bd88954a7c074f0f
Commit:     6f4e643353aea52d80f33960bd88954a7c074f0f
Parent:     130f77ecb2e7d5ac3e53e620f55e374f4a406b20
Author:     Pavel Emelyanov <[EMAIL PROTECTED]>
AuthorDate: Thu Oct 18 23:40:11 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Fri Oct 19 11:53:40 2007 -0700

    pid namespaces: initialize the namespace's proc_mnt
    
    The namespace's proc_mnt must be kern_mount-ed to make this pointer always
    valid, independently of whether the user space mounted the proc or not.  
This
    solves raced in proc_flush_task, etc.  with the proc_mnt switching from NULL
    to not-NULL.
    
    The initialization is done after the init's pid is created and hashed to 
make
    proc_get_sb() finr it and get for root inode.
    
    Sice the namespace holds the vfsmnt, vfsmnt holds the superblock and the
    superblock holds the namespace we must explicitly break this circle to 
destroy
    all the stuff.  This is done after the init of the namespace dies.  Running 
a
    few steps forward - when init exits it will kill all its children, so no
    proc_mnt will be needed after its death.
    
    Signed-off-by: Pavel Emelyanov <[EMAIL PROTECTED]>
    Cc: Oleg Nesterov <[EMAIL PROTECTED]>
    Cc: Sukadev Bhattiprolu <[EMAIL PROTECTED]>
    Cc: Paul Menage <[EMAIL PROTECTED]>
    Cc: "Eric W. Biederman" <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/proc/base.c          |    4 ++++
 fs/proc/root.c          |   16 ++++++++++++++++
 include/linux/proc_fs.h |   12 ++++++++++++
 kernel/fork.c           |    7 +++++++
 4 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 5e0c6a1..21510c9 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2275,6 +2275,10 @@ void proc_flush_task(struct task_struct *task)
                proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr,
                                leader ? 0 : tgid->numbers[i].nr);
        }
+
+       upid = &pid->numbers[pid->level];
+       if (upid->nr == 1)
+               pid_ns_release_proc(upid->ns);
 }
 
 static struct dentry *proc_pid_instantiate(struct inode *dir,
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 94e9d73..ec9cb3b 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -212,6 +212,22 @@ struct proc_dir_entry proc_root = {
        .parent         = &proc_root,
 };
 
+int pid_ns_prepare_proc(struct pid_namespace *ns)
+{
+       struct vfsmount *mnt;
+
+       mnt = kern_mount_data(&proc_fs_type, ns);
+       if (IS_ERR(mnt))
+               return PTR_ERR(mnt);
+
+       return 0;
+}
+
+void pid_ns_release_proc(struct pid_namespace *ns)
+{
+       mntput(ns->proc_mnt);
+}
+
 EXPORT_SYMBOL(proc_symlink);
 EXPORT_SYMBOL(proc_mkdir);
 EXPORT_SYMBOL(create_proc_entry);
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index cbc1038..1ff4616 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -143,6 +143,9 @@ extern const struct file_operations proc_kcore_operations;
 extern const struct file_operations proc_kmsg_operations;
 extern const struct file_operations ppc_htab_operations;
 
+extern int pid_ns_prepare_proc(struct pid_namespace *ns);
+extern void pid_ns_release_proc(struct pid_namespace *ns);
+
 /*
  * proc_tty.c
  */
@@ -235,6 +238,15 @@ static inline void proc_tty_unregister_driver(struct 
tty_driver *driver) {};
 
 extern struct proc_dir_entry proc_root;
 
+static inline int pid_ns_prepare_proc(struct pid_namespace *ns)
+{
+       return 0;
+}
+
+static inline void pid_ns_release_proc(struct pid_namespace *ns)
+{
+}
+
 #endif /* CONFIG_PROC_FS */
 
 #if !defined(CONFIG_PROC_KCORE)
diff --git a/kernel/fork.c b/kernel/fork.c
index f252784..ce9297e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -50,6 +50,7 @@
 #include <linux/taskstats_kern.h>
 #include <linux/random.h>
 #include <linux/tty.h>
+#include <linux/proc_fs.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -1150,6 +1151,12 @@ static struct task_struct *copy_process(unsigned long 
clone_flags,
                pid = alloc_pid(task_active_pid_ns(p));
                if (!pid)
                        goto bad_fork_cleanup_namespaces;
+
+               if (clone_flags & CLONE_NEWPID) {
+                       retval = pid_ns_prepare_proc(task_active_pid_ns(p));
+                       if (retval < 0)
+                               goto bad_fork_free_pid;
+               }
        }
 
        p->pid = pid_nr(pid);
-
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