[PATCH v3.1 1/3] Make call_usermodehelper_exec possible to set pid namespace

2016-10-18 Thread Cao Shufeng
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,
+  

[PATCH v3.1 1/3] Make call_usermodehelper_exec possible to set pid namespace

2016-10-18 Thread Cao Shufeng
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