pid namespaces: initialize the namespace's proc_mnt
authorPavel Emelyanov <xemul@openvz.org>
Fri, 19 Oct 2007 06:40:11 +0000 (23:40 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 19 Oct 2007 18:53:40 +0000 (11:53 -0700)
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 <xemul@openvz.org>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Sukadev Bhattiprolu <sukadev@us.ibm.com>
Cc: Paul Menage <menage@google.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/proc/base.c
fs/proc/root.c
include/linux/proc_fs.h
kernel/fork.c

index 5e0c6a1ce8b34c175c2fc7b3186d4ff873ed72f6..21510c9aa89cb51688581c982547c967539c0e90 100644 (file)
@@ -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,
index 94e9d734384e1fb3023e779ce8a58ea37097b11f..ec9cb3b6c93bf777e8c6cb8ed4a6f8405898fa87 100644 (file)
@@ -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);
index cbc1038c7900962af1208aefb5f7296a4455610f..1ff461672060ebc52d882156e0659250944d4110 100644 (file)
@@ -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)
index f252784f93308077d483bca888593ec7fad36774..ce9297e4e7d43fde235ce9ad5dc4083e11821fd4 100644 (file)
@@ -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);