summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/proc/base.c4
-rw-r--r--fs/proc/root.c16
-rw-r--r--include/linux/proc_fs.h12
-rw-r--r--kernel/fork.c7
4 files changed, 39 insertions, 0 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 5e0c6a1ce8b3..21510c9aa89c 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 94e9d734384e..ec9cb3b6c93b 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 cbc1038c7900..1ff461672060 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 f252784f9330..ce9297e4e7d4 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);