Skip to content

Commit 6f4e643

Browse files
xemulLinus Torvalds
authored andcommitted
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 <[email protected]> Cc: Oleg Nesterov <[email protected]> Cc: Sukadev Bhattiprolu <[email protected]> Cc: Paul Menage <[email protected]> Cc: "Eric W. Biederman" <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 130f77e commit 6f4e643

File tree

4 files changed

+39
-0
lines changed

4 files changed

+39
-0
lines changed

fs/proc/base.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2275,6 +2275,10 @@ void proc_flush_task(struct task_struct *task)
22752275
proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr,
22762276
leader ? 0 : tgid->numbers[i].nr);
22772277
}
2278+
2279+
upid = &pid->numbers[pid->level];
2280+
if (upid->nr == 1)
2281+
pid_ns_release_proc(upid->ns);
22782282
}
22792283

22802284
static struct dentry *proc_pid_instantiate(struct inode *dir,

fs/proc/root.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,22 @@ struct proc_dir_entry proc_root = {
212212
.parent = &proc_root,
213213
};
214214

215+
int 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+
226+
void pid_ns_release_proc(struct pid_namespace *ns)
227+
{
228+
mntput(ns->proc_mnt);
229+
}
230+
215231
EXPORT_SYMBOL(proc_symlink);
216232
EXPORT_SYMBOL(proc_mkdir);
217233
EXPORT_SYMBOL(create_proc_entry);

include/linux/proc_fs.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ extern const struct file_operations proc_kcore_operations;
143143
extern const struct file_operations proc_kmsg_operations;
144144
extern const struct file_operations ppc_htab_operations;
145145

146+
extern int pid_ns_prepare_proc(struct pid_namespace *ns);
147+
extern void pid_ns_release_proc(struct pid_namespace *ns);
148+
146149
/*
147150
* proc_tty.c
148151
*/
@@ -235,6 +238,15 @@ static inline void proc_tty_unregister_driver(struct tty_driver *driver) {};
235238

236239
extern struct proc_dir_entry proc_root;
237240

241+
static inline int pid_ns_prepare_proc(struct pid_namespace *ns)
242+
{
243+
return 0;
244+
}
245+
246+
static inline void pid_ns_release_proc(struct pid_namespace *ns)
247+
{
248+
}
249+
238250
#endif /* CONFIG_PROC_FS */
239251

240252
#if !defined(CONFIG_PROC_KCORE)

kernel/fork.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include <linux/taskstats_kern.h>
5151
#include <linux/random.h>
5252
#include <linux/tty.h>
53+
#include <linux/proc_fs.h>
5354

5455
#include <asm/pgtable.h>
5556
#include <asm/pgalloc.h>
@@ -1150,6 +1151,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
11501151
pid = alloc_pid(task_active_pid_ns(p));
11511152
if (!pid)
11521153
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+
}
11531160
}
11541161

11551162
p->pid = pid_nr(pid);

0 commit comments

Comments
 (0)