aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2007-10-19 02:40:11 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:40 -0400
commit6f4e643353aea52d80f33960bd88954a7c074f0f (patch)
tree5b7e452f7e31be89f06a52a2c077183b7fe74c3b
parent130f77ecb2e7d5ac3e53e620f55e374f4a406b20 (diff)
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 <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>
-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)
2275 proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr, 2275 proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr,
2276 leader ? 0 : tgid->numbers[i].nr); 2276 leader ? 0 : tgid->numbers[i].nr);
2277 } 2277 }
2278
2279 upid = &pid->numbers[pid->level];
2280 if (upid->nr == 1)
2281 pid_ns_release_proc(upid->ns);
2278} 2282}
2279 2283
2280static struct dentry *proc_pid_instantiate(struct inode *dir, 2284static 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 = {
212 .parent = &proc_root, 212 .parent = &proc_root,
213}; 213};
214 214
215int pid_ns_prepare_proc(struct pid_namespace *ns)
216{
217 struct vfsmount *mnt;
218
219 mnt = kern_mount_data(&proc_fs_type, ns);
220 if (IS_ERR(mnt))
221 return PTR_ERR(mnt);
222
223 return 0;
224}
225
226void pid_ns_release_proc(struct pid_namespace *ns)
227{
228 mntput(ns->proc_mnt);
229}
230
215EXPORT_SYMBOL(proc_symlink); 231EXPORT_SYMBOL(proc_symlink);
216EXPORT_SYMBOL(proc_mkdir); 232EXPORT_SYMBOL(proc_mkdir);
217EXPORT_SYMBOL(create_proc_entry); 233EXPORT_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;
143extern const struct file_operations proc_kmsg_operations; 143extern const struct file_operations proc_kmsg_operations;
144extern const struct file_operations ppc_htab_operations; 144extern const struct file_operations ppc_htab_operations;
145 145
146extern int pid_ns_prepare_proc(struct pid_namespace *ns);
147extern void pid_ns_release_proc(struct pid_namespace *ns);
148
146/* 149/*
147 * proc_tty.c 150 * proc_tty.c
148 */ 151 */
@@ -235,6 +238,15 @@ static inline void proc_tty_unregister_driver(struct tty_driver *driver) {};
235 238
236extern struct proc_dir_entry proc_root; 239extern struct proc_dir_entry proc_root;
237 240
241static inline int pid_ns_prepare_proc(struct pid_namespace *ns)
242{
243 return 0;
244}
245
246static inline void pid_ns_release_proc(struct pid_namespace *ns)
247{
248}
249
238#endif /* CONFIG_PROC_FS */ 250#endif /* CONFIG_PROC_FS */
239 251
240#if !defined(CONFIG_PROC_KCORE) 252#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 @@
50#include <linux/taskstats_kern.h> 50#include <linux/taskstats_kern.h>
51#include <linux/random.h> 51#include <linux/random.h>
52#include <linux/tty.h> 52#include <linux/tty.h>
53#include <linux/proc_fs.h>
53 54
54#include <asm/pgtable.h> 55#include <asm/pgtable.h>
55#include <asm/pgalloc.h> 56#include <asm/pgalloc.h>
@@ -1150,6 +1151,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1150 pid = alloc_pid(task_active_pid_ns(p)); 1151 pid = alloc_pid(task_active_pid_ns(p));
1151 if (!pid) 1152 if (!pid)
1152 goto bad_fork_cleanup_namespaces; 1153 goto bad_fork_cleanup_namespaces;
1154
1155 if (clone_flags & CLONE_NEWPID) {
1156 retval = pid_ns_prepare_proc(task_active_pid_ns(p));
1157 if (retval < 0)
1158 goto bad_fork_free_pid;
1159 }
1153 } 1160 }
1154 1161
1155 p->pid = pid_nr(pid); 1162 p->pid = pid_nr(pid);