diff --git a/fs/proc/base.c b/fs/proc/base.c index 5e0c6a1ce8b34c175c2fc7b3186d4ff873ed72f6..21510c9aa89cb51688581c982547c967539c0e90 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 94e9d734384e1fb3023e779ce8a58ea37097b11f..ec9cb3b6c93bf777e8c6cb8ed4a6f8405898fa87 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 cbc1038c7900962af1208aefb5f7296a4455610f..1ff461672060ebc52d882156e0659250944d4110 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 f252784f93308077d483bca888593ec7fad36774..ce9297e4e7d43fde235ce9ad5dc4083e11821fd4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -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);