Presently, a core_pattern pipe endpoint will be run in the init namespace. It will receive the virtual pid (task_tgid_vnr->%p) of the core dumping process but will have no access to that processes /proc without walking the init namespace /proc looking through all the global pids until it finds the one it thinks matches. One option for implementing this I've already posed: https://patchwork.kernel.org/patch/185912/ However, it's unclear if it is desirable for the core_pattern to run outside the namespace. In particular, it can easily access the mounts via /proc/[pid_nr]/root, but if there is a net namespace, it will not have access. (Originally introduced in 2007 in commit b488893a390edfe027bae7a46e9af8083e740668 ) Instead, this change implements the more complex option two. It migrates the ____call_usermodehelper() thread into the same namespaces as the dumping process. It does not assign a pid in that namespace so the collector will appear to be pid 0. (Using alloc_pid and change_pid are options though. I avoided it because kernel_thread's returned pid will then mismatch the actual threads pid.) Signed-off-by: Will Drewry <wad@xxxxxxxxxxxx> --- fs/exec.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 53 insertions(+), 3 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 828dd24..3b82607 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -51,6 +51,7 @@ #include <linux/audit.h> #include <linux/tracehook.h> #include <linux/kmod.h> +#include <linux/nsproxy.h> #include <linux/fsnotify.h> #include <linux/fs_struct.h> #include <linux/pipe_fs_i.h> @@ -65,6 +66,12 @@ char core_pattern[CORENAME_MAX_SIZE] = "core"; unsigned int core_pipe_limit; int suid_dumpable = 0; +struct coredump_pipe_params { + struct coredump_params *params; + struct nsproxy *nsproxy; + struct fs_struct *fs; +}; + /* The maximal length of core_pattern is also specified in sysctl.c */ static LIST_HEAD(formats); @@ -1819,8 +1826,34 @@ static int umh_pipe_setup(struct subprocess_info *info) { struct file *rp, *wp; struct fdtable *fdt; - struct coredump_params *cp = (struct coredump_params *)info->data; - struct files_struct *cf = current->files; + struct coredump_pipe_params *pipe_params = + (struct coredump_pipe_params *)info->data; + struct coredump_params *cp = pipe_params->params; + struct task_struct *tsk = current; + struct files_struct *cf = tsk->files; + struct fs_struct *cfs = tsk->fs; + + /* Migrate this thread into the crashing namespaces, but + * don't change its pid struct to avoid breaking any other + * dependencies. This will mean the process is pid=0 if it + * was migrated into a pid namespace. + */ + if (pipe_params->nsproxy && pipe_params->fs) { + int kill; + switch_task_namespaces(tsk, pipe_params->nsproxy); + pipe_params->nsproxy = NULL; + + task_lock(tsk); + tsk->fs = pipe_params->fs; + task_unlock(tsk); + pipe_params->fs = NULL; + /* Clean up the previous fs struct */ + write_lock(&cfs->lock); + kill = !--cfs->users; + write_unlock(&cfs->lock); + if (kill) + free_fs_struct(cfs); + } wp = create_write_pipe(0); if (IS_ERR(wp)) @@ -1911,6 +1944,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) if (ispipe) { int dump_count; char **helper_argv; + struct coredump_pipe_params pipe_params = { .params = &cprm }; if (cprm.limit == 1) { /* @@ -1950,10 +1984,26 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) goto fail_dropcount; } + /* Run the core_collector in the crashing namespaces */ + if (copy_namespaces_unattached(0, current, + &pipe_params.nsproxy, &pipe_params.fs)) { + printk(KERN_WARNING "%s failed to copy namespaces\n", + __func__); + argv_free(helper_argv); + goto fail_dropcount; + } + retval = call_usermodehelper_fns(helper_argv[0], helper_argv, NULL, UMH_WAIT_EXEC, umh_pipe_setup, - NULL, &cprm); + NULL, &pipe_params); argv_free(helper_argv); + /* nsproxy and fs will survive if call_usermodehelper_fns hits + * ENOMEM prior to creating a new thread. + */ + if (pipe_params.nsproxy) + put_nsproxy(pipe_params.nsproxy); + if (pipe_params.fs) /* not in use by anything else */ + free_fs_struct(pipe_params.fs); if (retval) { printk(KERN_INFO "Core dump to %s pipe failed\n", corename); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html