Messages in this thread Patch in this message | | | Subject | [RFC PATCH 5/8] KEYS: exec request-key within the requesting task's init namespace | From | Ian Kent <> | Date | Thu, 05 Feb 2015 10:34:24 +0800 |
| |
Containerized request key helper callbacks need the ability to execute a binary in a container's context. To do this calling an in kernel equivalent of setns(2) should be sufficient since the user mode helper execution kernel thread ultimately calls do_execve().
Signed-off-by: Ian Kent <ikent@redhat.com> Cc: Benjamin Coddington <bcodding@redhat.com> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: J. Bruce Fields <bfields@fieldses.org> Cc: David Howells <dhowells@redhat.com> Cc: Trond Myklebust <trond.myklebust@primarydata.com> Cc: Oleg Nesterov <onestero@redhat.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Jeff Layton <jeff.layton@primarydata.com> --- security/keys/request_key.c | 60 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 8 deletions(-)
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 9e79bbf..59282aa 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -17,6 +17,9 @@ #include <linux/err.h> #include <linux/keyctl.h> #include <linux/slab.h> +#include <linux/fs.h> +#include <linux/nsproxy.h> +#include <net/net_namespace.h> #include "internal.h" #define key_negative_timeout 60 /* default timeout on a negative key's existence */ @@ -46,6 +49,11 @@ void complete_request_key(struct key_construction *cons, int error) } EXPORT_SYMBOL(complete_request_key); +struct request_key_info { + struct key *keyring; + struct task_struct *tsk; +}; + /* * Initialise a usermode helper that is going to have a specific session * keyring. @@ -55,9 +63,18 @@ EXPORT_SYMBOL(complete_request_key); */ static int umh_keys_init(struct subprocess_info *info, struct cred *cred) { - struct key *keyring = info->data; + struct request_key_info *rki = info->data; + struct task_struct *tsk = rki->tsk; + + if (tsk) { + int err; + + err = umh_enter_ns(tsk, cred); + if (err) + return err; + } - return install_session_keyring_to_cred(cred, keyring); + return install_session_keyring_to_cred(cred, rki->keyring); } /* @@ -65,8 +82,11 @@ static int umh_keys_init(struct subprocess_info *info, struct cred *cred) */ static void umh_keys_cleanup(struct subprocess_info *info) { - struct key *keyring = info->data; - key_put(keyring); + struct request_key_info *rki = info->data; + if (rki->tsk) + put_task_struct(rki->tsk); + key_put(rki->keyring); + kfree(rki); } /* @@ -76,12 +96,32 @@ static int call_usermodehelper_keys(char *path, char **argv, char **envp, struct key *session_keyring, int flags) { struct subprocess_info *info; + struct request_key_info *rki; + unsigned int use_ns = flags & UMH_USE_NS; + struct task_struct *tsk = NULL; + + rki = kmalloc(sizeof(*rki), GFP_KERNEL); + if (!rki) + return -ENOMEM; + + if (use_ns) { + tsk = umh_get_init_pid(); + if (IS_ERR(tsk)) + return PTR_ERR(tsk); + } + + rki->keyring = session_keyring; + rki->tsk = tsk; info = call_usermodehelper_setup(path, argv, envp, GFP_KERNEL, umh_keys_init, umh_keys_cleanup, - session_keyring); - if (!info) + rki); + if (!info) { + if (tsk) + put_task_struct(rki->tsk); + kfree(rki); return -ENOMEM; + } key_get(session_keyring); return call_usermodehelper_exec(info, flags); @@ -102,10 +142,15 @@ static int call_sbin_request_key(struct key_construction *cons, char *argv[9], *envp[3], uid_str[12], gid_str[12]; char key_str[12], keyring_str[3][12]; char desc[20]; + int flags = UMH_WAIT_PROC; int ret, i; kenter("{%d},{%d},%s", key->serial, authkey->serial, op); + /* If running within a container use the container namespace */ + if (current->nsproxy->net_ns != &init_net) + flags |= UMH_USE_NS; + ret = install_user_keyrings(); if (ret < 0) goto error_alloc; @@ -172,8 +217,7 @@ static int call_sbin_request_key(struct key_construction *cons, argv[i] = NULL; /* do it */ - ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, - UMH_WAIT_PROC); + ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, flags); kdebug("usermode -> 0x%x", ret); if (ret >= 0) { /* ret is the exit/wait code */
| |