From: Ian Kent <ik...@redhat.com> 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 <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> --- include/linux/key.h | 3 +++ security/keys/gc.c | 2 ++ security/keys/key.c | 4 ++++ security/keys/request_key.c | 35 +++++++++++++++++++++++++++++++++-- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/include/linux/key.h b/include/linux/key.h index e1d4715..89dc2d7 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -209,6 +209,9 @@ struct key { } payload; struct assoc_array keys; }; + + /* Namespace token */ + long umh_token; }; extern struct key *key_alloc(struct key_type *type, diff --git a/security/keys/gc.c b/security/keys/gc.c index c795237..57a0730 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -156,6 +156,8 @@ static noinline void key_gc_unused_keys(struct list_head *keys) kfree(key->description); + umh_ns_put_token(key->umh_token); + #ifdef KEY_DEBUGGING key->magic = KEY_DEBUG_MAGIC_X; #endif diff --git a/security/keys/key.c b/security/keys/key.c index aee2ec5..e7ab89d 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -18,6 +18,7 @@ #include <linux/workqueue.h> #include <linux/random.h> #include <linux/err.h> +#include <net/net_namespace.h> #include "internal.h" struct kmem_cache *key_jar; @@ -309,6 +310,9 @@ struct key *key_alloc(struct key_type *type, const char *desc, /* publish the key by giving it a serial number */ atomic_inc(&user->nkeys); key_alloc_serial(key); + /* If running within a container use the container namespace */ + if (current->nsproxy->net_ns != &init_net) + key->umh_token = umh_ns_get_token(0); error: return key; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index e865f9f..16ac3b0 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -90,6 +90,31 @@ static int call_usermodehelper_keys(char *path, char **argv, char **envp, } /* + * Call a usermode helper with a specific session keyring and execute + * within a namespace. + */ +static int call_usermodehelper_keys_ns(char *path, char **argv, char **envp, + struct key *session_keyring, + unsigned int wait, long token) +{ + struct subprocess_info *info; + unsigned int gfp_mask = (wait & UMH_NO_WAIT) ? + GFP_ATOMIC : GFP_KERNEL; + + if (token <= 0) + return -EINVAL; + + info = call_usermodehelper_setup_ns(path, argv, envp, gfp_mask, + umh_keys_init, umh_keys_cleanup, + session_keyring, token); + if (!info) + return -ENOMEM; + + key_get(session_keyring); + return call_usermodehelper_exec(info, wait|UMH_USE_NS); +} + +/* * Request userspace finish the construction of a key * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" */ @@ -104,6 +129,7 @@ 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]; + unsigned int wait = UMH_WAIT_PROC; int ret, i; kenter("{%d},{%d},%s", key->serial, authkey->serial, op); @@ -174,8 +200,13 @@ 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); + /* If running within a container use the container namespace */ + if (key->umh_token) + ret = call_usermodehelper_keys_ns(argv[0], argv, envp, + keyring, wait, key->umh_token); + else + ret = call_usermodehelper_keys(argv[0], + argv, envp, keyring, wait); kdebug("usermode -> 0x%x", ret); if (ret >= 0) { /* ret is the exit/wait code */ -- 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/