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 that get a token to a service thread created within the container environment for usermode helper calls.
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 | 5 +++++ security/keys/request_key.c | 34 +++++++++++++++++++++++++++------- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/include/linux/key.h b/include/linux/key.h index e1d4715..144727d 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -209,6 +209,9 @@ struct key { } payload; struct assoc_array keys; }; + + /* Namespace token */ + int 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..c689ffd 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_wq_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..3ca0825 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -18,6 +18,8 @@ #include <linux/workqueue.h> #include <linux/random.h> #include <linux/err.h> +#include <net/net_namespace.h> +#include <linux/nsproxy.h> #include "internal.h" struct kmem_cache *key_jar; @@ -309,6 +311,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_wq_get_token(0, "keys"); error: return key; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index e865f9f..233e837 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -70,26 +70,40 @@ static void umh_keys_cleanup(struct subprocess_info *info) } /* - * Call a usermode helper with a specific session keyring. + * Call a usermode helper with a specific session keyring and execute + * within a namespace. */ -static int call_usermodehelper_keys(char *path, char **argv, char **envp, - struct key *session_keyring, int wait) +static int call_usermodehelper_keys_service(char *path, + char **argv, char **envp, + struct key *session_keyring, + int token, unsigned int wait) { struct subprocess_info *info; unsigned int gfp_mask = (wait & UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; info = call_usermodehelper_setup(path, argv, envp, gfp_mask, - umh_keys_init, umh_keys_cleanup, - session_keyring); + umh_keys_init, umh_keys_cleanup, + session_keyring); if (!info) return -ENOMEM; + info->wq_token = token; key_get(session_keyring); return call_usermodehelper_exec(info, wait); } /* + * Call a usermode helper with a specific session keyring. + */ +static int call_usermodehelper_keys(char *path, char **argv, char **envp, + struct key *session_keyring, int wait) +{ + return call_usermodehelper_keys_service(path, argv, envp, + session_keyring, 0, wait); +} + +/* * Request userspace finish the construction of a key * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" */ @@ -174,8 +188,14 @@ 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_service(argv[0], argv, envp, + keyring, key->umh_token, + UMH_WAIT_PROC); + else + ret = call_usermodehelper_keys(argv[0], argv, envp, + keyring, UMH_WAIT_PROC); 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/