From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932191AbbCQCqc (ORCPT ); Mon, 16 Mar 2015 22:46:32 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:37005 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754319AbbCQCqY (ORCPT ); Mon, 16 Mar 2015 22:46:24 -0400 X-Sasl-enc: L54Rj5XtAoDGSM71Rgx75pNUNK2abeN674qt9gvIvswz 1426560383 Subject: [RFC PATCH v4 12/12] KEYS: exec request-key within the requesting task's init namespace From: Ian Kent To: Kernel Mailing List Cc: David Howells , Oleg Nesterov , Trond Myklebust , "J. Bruce Fields" , Benjamin Coddington , Al Viro , Jeff Layton , "Eric W. Biederman" Date: Tue, 17 Mar 2015 10:46:08 +0800 Message-ID: <20150317024607.24592.67322.stgit@pluto.fritz.box> In-Reply-To: <20150317022308.24592.35785.stgit@pluto.fritz.box> References: <20150317022308.24592.35785.stgit@pluto.fritz.box> User-Agent: StGit/0.17-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ian Kent 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 Cc: Benjamin Coddington Cc: Al Viro Cc: J. Bruce Fields Cc: David Howells Cc: Trond Myklebust Cc: Oleg Nesterov Cc: Eric W. Biederman Cc: Jeff Layton --- 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 #include #include +#include #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 " */ @@ -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 */