[PATCH v3.1 1/3] Make call_usermodehelper_exec possible to set pid namespace
From: Zhao LeiCurrent call_usermodehelper_exec() can not set pid namespace for the executed program, because we need addition fork to make pid namespace active. This patch add above function for call_usermodehelper_exec(). When init_intermediate callback return -EAGAIN, the usermodehelper will fork again to make pid namespace active, and run program in the child process. This function is helpful for coredump to run pipe_program in specific container environment. Signed-off-by: Zhao Lei --- fs/coredump.c | 3 +- include/linux/kmod.h| 2 + init/do_mounts_initrd.c | 3 +- kernel/kmod.c | 133 ++-- lib/kobject_uevent.c| 3 +- security/keys/request_key.c | 4 +- 6 files changed, 127 insertions(+), 21 deletions(-) diff --git a/fs/coredump.c b/fs/coredump.c index 281b768..ceb0ee8 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -641,7 +641,8 @@ void do_coredump(const siginfo_t *siginfo) retval = -ENOMEM; sub_info = call_usermodehelper_setup(helper_argv[0], helper_argv, NULL, GFP_KERNEL, - umh_pipe_setup, NULL, ); + NULL, umh_pipe_setup, + NULL, ); if (sub_info) retval = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); diff --git a/include/linux/kmod.h b/include/linux/kmod.h index fcfd2bf..8fb8c0e 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -61,6 +61,7 @@ struct subprocess_info { char **envp; int wait; int retval; + int (*init_intermediate)(struct subprocess_info *info); int (*init)(struct subprocess_info *info, struct cred *new); void (*cleanup)(struct subprocess_info *info); void *data; @@ -71,6 +72,7 @@ call_usermodehelper(char *path, char **argv, char **envp, int wait); extern struct subprocess_info * call_usermodehelper_setup(char *path, char **argv, char **envp, gfp_t gfp_mask, + int (*init_intermediate)(struct subprocess_info *info), int (*init)(struct subprocess_info *info, struct cred *new), void (*cleanup)(struct subprocess_info *), void *data); diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c index a1000ca..bb5dce5 100644 --- a/init/do_mounts_initrd.c +++ b/init/do_mounts_initrd.c @@ -72,7 +72,8 @@ static void __init handle_initrd(void) current->flags |= PF_FREEZER_SKIP; info = call_usermodehelper_setup("/linuxrc", argv, envp_init, -GFP_KERNEL, init_linuxrc, NULL, NULL); +GFP_KERNEL, NULL, init_linuxrc, NULL, +NULL); if (!info) return; call_usermodehelper_exec(info, UMH_WAIT_PROC); diff --git a/kernel/kmod.c b/kernel/kmod.c index 0277d12..30a5802 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -91,7 +91,7 @@ static int call_modprobe(char *module_name, int wait) argv[4] = NULL; info = call_usermodehelper_setup(modprobe_path, argv, envp, GFP_KERNEL, -NULL, free_modprobe_argv, NULL); +NULL, NULL, free_modprobe_argv, NULL); if (!info) goto free_module_name; @@ -209,14 +209,11 @@ static void umh_complete(struct subprocess_info *sub_info) call_usermodehelper_freeinfo(sub_info); } -/* - * This is the task which runs the usermode application - */ -static int call_usermodehelper_exec_async(void *data) +static int __call_usermodehelper_exec_doexec(void *data) { struct subprocess_info *sub_info = data; struct cred *new; - int retval; + int retval = 0; spin_lock_irq(>sighand->siglock); flush_signal_handlers(current, 1); @@ -228,10 +225,11 @@ static int call_usermodehelper_exec_async(void *data) */ set_user_nice(current, 0); - retval = -ENOMEM; new = prepare_kernel_cred(current); - if (!new) + if (!new) { + retval = -ENOMEM; goto out; + } spin_lock(_sysctl_lock); new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset); @@ -248,20 +246,121 @@ static int call_usermodehelper_exec_async(void *data) } commit_creds(new); - retval = do_execve(getname_kernel(sub_info->path), - (const char __user *const __user *)sub_info->argv, - (const char __user *const __user *)sub_info->envp); + (const char __user *const __user *)sub_info->argv, +
[PATCH v3.1 1/3] Make call_usermodehelper_exec possible to set pid namespace
From: Zhao Lei Current call_usermodehelper_exec() can not set pid namespace for the executed program, because we need addition fork to make pid namespace active. This patch add above function for call_usermodehelper_exec(). When init_intermediate callback return -EAGAIN, the usermodehelper will fork again to make pid namespace active, and run program in the child process. This function is helpful for coredump to run pipe_program in specific container environment. Signed-off-by: Zhao Lei --- fs/coredump.c | 3 +- include/linux/kmod.h| 2 + init/do_mounts_initrd.c | 3 +- kernel/kmod.c | 133 ++-- lib/kobject_uevent.c| 3 +- security/keys/request_key.c | 4 +- 6 files changed, 127 insertions(+), 21 deletions(-) diff --git a/fs/coredump.c b/fs/coredump.c index 281b768..ceb0ee8 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -641,7 +641,8 @@ void do_coredump(const siginfo_t *siginfo) retval = -ENOMEM; sub_info = call_usermodehelper_setup(helper_argv[0], helper_argv, NULL, GFP_KERNEL, - umh_pipe_setup, NULL, ); + NULL, umh_pipe_setup, + NULL, ); if (sub_info) retval = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); diff --git a/include/linux/kmod.h b/include/linux/kmod.h index fcfd2bf..8fb8c0e 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -61,6 +61,7 @@ struct subprocess_info { char **envp; int wait; int retval; + int (*init_intermediate)(struct subprocess_info *info); int (*init)(struct subprocess_info *info, struct cred *new); void (*cleanup)(struct subprocess_info *info); void *data; @@ -71,6 +72,7 @@ call_usermodehelper(char *path, char **argv, char **envp, int wait); extern struct subprocess_info * call_usermodehelper_setup(char *path, char **argv, char **envp, gfp_t gfp_mask, + int (*init_intermediate)(struct subprocess_info *info), int (*init)(struct subprocess_info *info, struct cred *new), void (*cleanup)(struct subprocess_info *), void *data); diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c index a1000ca..bb5dce5 100644 --- a/init/do_mounts_initrd.c +++ b/init/do_mounts_initrd.c @@ -72,7 +72,8 @@ static void __init handle_initrd(void) current->flags |= PF_FREEZER_SKIP; info = call_usermodehelper_setup("/linuxrc", argv, envp_init, -GFP_KERNEL, init_linuxrc, NULL, NULL); +GFP_KERNEL, NULL, init_linuxrc, NULL, +NULL); if (!info) return; call_usermodehelper_exec(info, UMH_WAIT_PROC); diff --git a/kernel/kmod.c b/kernel/kmod.c index 0277d12..30a5802 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -91,7 +91,7 @@ static int call_modprobe(char *module_name, int wait) argv[4] = NULL; info = call_usermodehelper_setup(modprobe_path, argv, envp, GFP_KERNEL, -NULL, free_modprobe_argv, NULL); +NULL, NULL, free_modprobe_argv, NULL); if (!info) goto free_module_name; @@ -209,14 +209,11 @@ static void umh_complete(struct subprocess_info *sub_info) call_usermodehelper_freeinfo(sub_info); } -/* - * This is the task which runs the usermode application - */ -static int call_usermodehelper_exec_async(void *data) +static int __call_usermodehelper_exec_doexec(void *data) { struct subprocess_info *sub_info = data; struct cred *new; - int retval; + int retval = 0; spin_lock_irq(>sighand->siglock); flush_signal_handlers(current, 1); @@ -228,10 +225,11 @@ static int call_usermodehelper_exec_async(void *data) */ set_user_nice(current, 0); - retval = -ENOMEM; new = prepare_kernel_cred(current); - if (!new) + if (!new) { + retval = -ENOMEM; goto out; + } spin_lock(_sysctl_lock); new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset); @@ -248,20 +246,121 @@ static int call_usermodehelper_exec_async(void *data) } commit_creds(new); - retval = do_execve(getname_kernel(sub_info->path), - (const char __user *const __user *)sub_info->argv, - (const char __user *const __user *)sub_info->envp); + (const char __user *const __user *)sub_info->argv, + (const char __user *const