diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2007-10-18 23:40:11 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 11:53:40 -0700 |
commit | 6f4e643353aea52d80f33960bd88954a7c074f0f (patch) | |
tree | 5b7e452f7e31be89f06a52a2c077183b7fe74c3b /fs/proc | |
parent | 130f77ecb2e7d5ac3e53e620f55e374f4a406b20 (diff) | |
download | kernel_samsung_crespo-6f4e643353aea52d80f33960bd88954a7c074f0f.zip kernel_samsung_crespo-6f4e643353aea52d80f33960bd88954a7c074f0f.tar.gz kernel_samsung_crespo-6f4e643353aea52d80f33960bd88954a7c074f0f.tar.bz2 |
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>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/base.c | 4 | ||||
-rw-r--r-- | fs/proc/root.c | 16 |
2 files changed, 20 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); |