From: Ian Kent <ik...@redhat.com> The call_usermodehelper() function executes all binaries in the global "init" root context. This doesn't allow a binary to be run within a namespace (eg. the namespaces of a container).
The init process of the callers environment is used to setup the namespaces in almost the same way the root init process when the UMH_USE_NS flag is used. Signed-off-by: Ian Kent <ik...@redhat.com> Cc: Benjamin Coddington <bcodd...@redhat.com> Cc: Al Viro <v...@zeniv.linux.org.uk> Cc: J. Bruce Fields <bfie...@fieldses.org> Cc: David Howells <dhowe...@redhat.com> Cc: Trond Myklebust <trond.mykleb...@primarydata.com> Cc: Oleg Nesterov <onest...@redhat.com> Cc: Eric W. Biederman <ebied...@xmission.com> Cc: Jeff Layton <jeff.lay...@primarydata.com> --- kernel/kmod.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/kernel/kmod.c b/kernel/kmod.c index 213dbe0..d6ee21a 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -56,6 +56,8 @@ static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET; static DEFINE_SPINLOCK(umh_sysctl_lock); static DECLARE_RWSEM(umhelper_sem); +static void umh_put_nsproxy(struct subprocess_info *); + #ifdef CONFIG_MODULES /* @@ -194,6 +196,7 @@ static void call_usermodehelper_freeinfo(struct subprocess_info *info) { if (info->cleanup) (*info->cleanup)(info); + umh_put_nsproxy(info); kfree(info); } @@ -565,6 +568,61 @@ static void helper_unlock(void) wake_up(&running_helpers_waitq); } +#ifndef CONFIG_NAMESPACES +static int umh_get_nsproxy(struct subprocess_info *sub_info) +{ + return -ENOTSUP; +} + +static void umh_put_nsproxy(struct subprocess_info *sub_info) +{ +} +#else +static int umh_get_nsproxy(struct subprocess_info *sub_info) +{ + struct umh_ns_info *nsinfo = &sub_info->nsinfo; + struct task_struct *tsk; + struct user_namespace *user_ns; + struct nsproxy *new; + int err = 0; + + rcu_read_lock(); + tsk = find_task_by_vpid(1); + if (tsk) + get_task_struct(tsk); + rcu_read_unlock(); + if (!tsk) { + err = -ESRCH; + goto out; + } + + user_ns = get_user_ns(tsk->cred->user_ns); + + new = create_new_namespaces(0, tsk, user_ns, tsk->fs); + if (IS_ERR(new)) { + err = PTR_ERR(new); + put_user_ns(user_ns); + put_task_struct(tsk); + goto out; + } + + put_task_struct(tsk); + + nsinfo->nsproxy = new; + nsinfo->user_ns = user_ns; +out: + return err; +} + +static void umh_put_nsproxy(struct subprocess_info *sub_info) +{ + if (sub_info->nsinfo.nsproxy) { + put_nsproxy(sub_info->nsinfo.nsproxy); + put_user_ns(sub_info->nsinfo.user_ns); + } +} +#endif + /** * call_usermodehelper_setup - prepare to call a usermode helper * @path: path to usermode executable @@ -697,6 +755,14 @@ int call_usermodehelper(char *path, if (info == NULL) return -ENOMEM; + if (flags & UMH_USE_NS) { + int err = umh_get_nsproxy(info); + if (err) { + kfree(info); + return err; + } + } + return call_usermodehelper_exec(info, flags); } EXPORT_SYMBOL(call_usermodehelper); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/