diff mbox series

[2/2] KEYS: Add keyagent request_key

Message ID 061dd6fe81dc97a4375e52ec0da20a54cf582cb5.1657624639.git.bcodding@redhat.com (mailing list archive)
State New, archived
Headers show
Series Keyagents: another call_usermodehelper approach for namespaces | expand

Commit Message

Benjamin Coddington July 12, 2022, 12:35 p.m. UTC
During key construction, search the calling process' session keyring for a
keyagent key with a description that matches the requested key_type.  If
found, link the authkey into the keyagent's process_keyring, and signal the
keyagent task with a realtime signal containing the serial number of the
key that needs to be constructed.

Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
---
 include/uapi/asm-generic/siginfo.h |  1 +
 security/keys/internal.h           |  4 ++
 security/keys/keyagent.c           | 85 ++++++++++++++++++++++++++++++
 security/keys/request_key.c        |  9 ++++
 4 files changed, 99 insertions(+)

Comments

kernel test robot July 14, 2022, 10:10 p.m. UTC | #1
Hi Benjamin,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on jmorris-security/next-testing]
[also build test WARNING on dhowells-fs/fscache-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Benjamin-Coddington/Keyagents-another-call_usermodehelper-approach-for-namespaces/20220712-203658
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git next-testing
config: hexagon-randconfig-r005-20220714 (https://download.01.org/0day-ci/archive/20220715/202207150537.QnoEUasf-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 5e61b9c556267086ef9b743a0b57df302eef831b)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/4d4f4ae463335d3e611bdb71330ab37af115cde9
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Benjamin-Coddington/Keyagents-another-call_usermodehelper-approach-for-namespaces/20220712-203658
        git checkout 4d4f4ae463335d3e611bdb71330ab37af115cde9
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash security/keys/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> security/keys/request_key.c:254:1: warning: unused label 'done' [-Wunused-label]
   done:
   ^~~~~
   1 warning generated.


vim +/done +254 security/keys/request_key.c

   217	
   218	/*
   219	 * Call out to userspace for key construction.
   220	 *
   221	 * Program failure is ignored in favour of key status.
   222	 */
   223	static int construct_key(struct key *key, const void *callout_info,
   224				 size_t callout_len, void *aux,
   225				 struct key *dest_keyring)
   226	{
   227		request_key_actor_t actor;
   228		struct key *authkey;
   229		int ret;
   230	
   231		kenter("%d,%p,%zu,%p", key->serial, callout_info, callout_len, aux);
   232	
   233		/* allocate an authorisation key */
   234		authkey = request_key_auth_new(key, "create", callout_info, callout_len,
   235					       dest_keyring);
   236		if (IS_ERR(authkey))
   237			return PTR_ERR(authkey);
   238	
   239		/* Make the call */
   240		actor = call_sbin_request_key;
   241		if (key->type->request_key)
   242			actor = key->type->request_key;
   243	#ifdef CONFIG_KEYAGENT
   244		else {
   245			ret = keyagent_request_key(authkey, aux);
   246	
   247			/* ENOKEY: no keyagents match on calling process' keyrings */
   248			if (ret != -ENOKEY)
   249				goto done;
   250		}
   251	#endif
   252		ret = actor(authkey, aux);
   253	
 > 254	done:
   255		/* check that the actor called complete_request_key() prior to
   256		 * returning an error */
   257		WARN_ON(ret < 0 &&
   258			!test_bit(KEY_FLAG_INVALIDATED, &authkey->flags));
   259	
   260		key_put(authkey);
   261		kleave(" = %d", ret);
   262		return ret;
   263	}
   264
kernel test robot July 15, 2022, 3:28 p.m. UTC | #2
Hi Benjamin,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on jmorris-security/next-testing]
[also build test WARNING on dhowells-fs/fscache-next arnd-asm-generic/master linus/master v5.19-rc6 next-20220714]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Benjamin-Coddington/Keyagents-another-call_usermodehelper-approach-for-namespaces/20220712-203658
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git next-testing
config: i386-defconfig (https://download.01.org/0day-ci/archive/20220715/202207152343.9SGLm8sP-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce (this is a W=1 build):
        # https://github.com/intel-lab-lkp/linux/commit/4d4f4ae463335d3e611bdb71330ab37af115cde9
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Benjamin-Coddington/Keyagents-another-call_usermodehelper-approach-for-namespaces/20220712-203658
        git checkout 4d4f4ae463335d3e611bdb71330ab37af115cde9
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash security/keys/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   security/keys/request_key.c: In function 'construct_key':
>> security/keys/request_key.c:254:1: warning: label 'done' defined but not used [-Wunused-label]
     254 | done:
         | ^~~~


vim +/done +254 security/keys/request_key.c

   217	
   218	/*
   219	 * Call out to userspace for key construction.
   220	 *
   221	 * Program failure is ignored in favour of key status.
   222	 */
   223	static int construct_key(struct key *key, const void *callout_info,
   224				 size_t callout_len, void *aux,
   225				 struct key *dest_keyring)
   226	{
   227		request_key_actor_t actor;
   228		struct key *authkey;
   229		int ret;
   230	
   231		kenter("%d,%p,%zu,%p", key->serial, callout_info, callout_len, aux);
   232	
   233		/* allocate an authorisation key */
   234		authkey = request_key_auth_new(key, "create", callout_info, callout_len,
   235					       dest_keyring);
   236		if (IS_ERR(authkey))
   237			return PTR_ERR(authkey);
   238	
   239		/* Make the call */
   240		actor = call_sbin_request_key;
   241		if (key->type->request_key)
   242			actor = key->type->request_key;
   243	#ifdef CONFIG_KEYAGENT
   244		else {
   245			ret = keyagent_request_key(authkey, aux);
   246	
   247			/* ENOKEY: no keyagents match on calling process' keyrings */
   248			if (ret != -ENOKEY)
   249				goto done;
   250		}
   251	#endif
   252		ret = actor(authkey, aux);
   253	
 > 254	done:
   255		/* check that the actor called complete_request_key() prior to
   256		 * returning an error */
   257		WARN_ON(ret < 0 &&
   258			!test_bit(KEY_FLAG_INVALIDATED, &authkey->flags));
   259	
   260		key_put(authkey);
   261		kleave(" = %d", ret);
   262		return ret;
   263	}
   264
kernel test robot July 15, 2022, 3:28 p.m. UTC | #3
Hi Benjamin,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on jmorris-security/next-testing]
[also build test WARNING on dhowells-fs/fscache-next arnd-asm-generic/master linus/master v5.19-rc6 next-20220714]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Benjamin-Coddington/Keyagents-another-call_usermodehelper-approach-for-namespaces/20220712-203658
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git next-testing
config: i386-allyesconfig (https://download.01.org/0day-ci/archive/20220715/202207152310.dTPT29kb-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce (this is a W=1 build):
        # https://github.com/intel-lab-lkp/linux/commit/4d4f4ae463335d3e611bdb71330ab37af115cde9
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Benjamin-Coddington/Keyagents-another-call_usermodehelper-approach-for-namespaces/20220712-203658
        git checkout 4d4f4ae463335d3e611bdb71330ab37af115cde9
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash security/keys/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> security/keys/keyagent.c:78:5: warning: no previous prototype for 'keyagent_request_key' [-Wmissing-prototypes]
      78 | int keyagent_request_key(struct key *authkey, void *aux)
         |     ^~~~~~~~~~~~~~~~~~~~


vim +/keyagent_request_key +78 security/keys/keyagent.c

    72	
    73	/*
    74	 * Search the calling process' keyrings for a keyagent that
    75	 * matches the requested key type.  If found, signal the keyagent
    76	 * to construct and link the key, else return -ENOKEY.
    77	 */
  > 78	int keyagent_request_key(struct key *authkey, void *aux)
    79	{
    80		struct key *ka_key, *target_key;
    81		struct request_key_auth *rka;
    82		key_ref_t ka_ref;
    83		const struct cred *cred = current_cred();
    84		int ret;
    85	
    86		/* We must be careful not to touch authkey and aux if
    87		 * returning -ENOKEY, since it will be reused.   */
    88		rka = get_request_key_auth(authkey);
    89		target_key = rka->target_key;
    90	
    91		/* Does the calling process have a keyagent in its session keyring? */
    92		ka_ref = keyring_search(
    93						make_key_ref(cred->session_keyring, 1),
    94						&key_type_keyagent,
    95						target_key->type->name, false);
    96	
    97		if (IS_ERR(ka_ref))
    98			return -ENOKEY;
    99	
   100		/* We found a keyagent, let's call out to it. */
   101		ka_key = key_ref_to_ptr(ka_ref);
   102		ret = keyagent_signal(ka_key, target_key, authkey);
   103		key_put(key_ref_to_ptr(ka_ref));
   104	
   105		return ret;
   106	}
   107
diff mbox series

Patch

diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index ffbe4cec9f32..542e297f4466 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -185,6 +185,7 @@  typedef struct siginfo {
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 #define SI_TKILL	-6		/* sent by tkill system call */
 #define SI_DETHREAD	-7		/* sent by execve() killing subsidiary threads */
+#define SI_KEYAGENT	-8		/* sent by request-key */
 #define SI_ASYNCNL	-60		/* sent by glibc async name lookup completion */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 9b9cf3b6fcbb..a6db6eecfff5 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -372,5 +372,9 @@  static inline void key_check(const struct key *key)
 
 #define key_check(key) do {} while(0)
 
+#endif
+
+#ifdef CONFIG_KEYAGENT
+extern int keyagent_request_key(struct key *authkey, void *aux);
 #endif
 #endif /* _INTERNAL_H */
diff --git a/security/keys/keyagent.c b/security/keys/keyagent.c
index 87ebfe00c710..cf70146925f0 100644
--- a/security/keys/keyagent.c
+++ b/security/keys/keyagent.c
@@ -9,8 +9,11 @@ 
 #include <linux/slab.h>
 #include <linux/key.h>
 #include <linux/key-type.h>
+#include <linux/sched/signal.h>
+#include <linux/sched/task.h>
 
 #include <keys/user-type.h>
+#include <keys/request_key_auth-type.h>
 
 /*
  * Keyagent key payload.
@@ -20,6 +23,88 @@  struct keyagent {
 	int sig;
 };
 
+struct key_type key_type_keyagent;
+
+/*
+ * Given a key representing a keyagent and a target_key to construct, link
+ * the the authkey into the keyagent's process_keyring and signal the
+ * keyagent to construct the target_key.
+ */
+static int keyagent_signal(struct key *ka_key, struct key *target_key,
+							struct key *authkey)
+{
+	struct keyagent *ka = ka_key->payload.data[0];
+	struct task_struct *task;
+	const struct cred *cred;
+	kernel_siginfo_t info = {
+		.si_code = SI_KEYAGENT,
+		.si_signo = ka->sig,
+		.si_int = target_key->serial,
+	};
+	int ret = -ENOKEY;
+
+	task = get_pid_task(ka->pid, PIDTYPE_PID);
+	/* If the task is gone, should we revoke the keyagent key? */
+	if (!task) {
+		key_revoke(ka_key);
+		goto out;
+	}
+
+	/* We're expecting valid keyagents to have a process keyring,
+	 * if not, should we warn? */
+	cred = get_cred(task->cred);
+	if (!cred->process_keyring)
+		goto out_nolink;
+
+	/* Link the autkey to the keyagent's process_keyring */
+	ret = key_link(cred->process_keyring, authkey);
+	if (ret < 0)
+		goto out_nolink;
+
+	ret = send_sig_info(ka->sig, &info, task);
+
+out_nolink:
+	put_cred(cred);
+	put_task_struct(task);
+out:
+	return ret;
+}
+
+/*
+ * Search the calling process' keyrings for a keyagent that
+ * matches the requested key type.  If found, signal the keyagent
+ * to construct and link the key, else return -ENOKEY.
+ */
+int keyagent_request_key(struct key *authkey, void *aux)
+{
+	struct key *ka_key, *target_key;
+	struct request_key_auth *rka;
+	key_ref_t ka_ref;
+	const struct cred *cred = current_cred();
+	int ret;
+
+	/* We must be careful not to touch authkey and aux if
+	 * returning -ENOKEY, since it will be reused.   */
+	rka = get_request_key_auth(authkey);
+	target_key = rka->target_key;
+
+	/* Does the calling process have a keyagent in its session keyring? */
+	ka_ref = keyring_search(
+					make_key_ref(cred->session_keyring, 1),
+					&key_type_keyagent,
+					target_key->type->name, false);
+
+	if (IS_ERR(ka_ref))
+		return -ENOKEY;
+
+	/* We found a keyagent, let's call out to it. */
+	ka_key = key_ref_to_ptr(ka_ref);
+	ret = keyagent_signal(ka_key, target_key, authkey);
+	key_put(key_ref_to_ptr(ka_ref));
+
+	return ret;
+}
+
 /*
  * Instantiate takes a reference to the current task's struct pid
  * and the requested realtime signal number.
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 2da4404276f0..4c1f5ef55856 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -240,9 +240,18 @@  static int construct_key(struct key *key, const void *callout_info,
 	actor = call_sbin_request_key;
 	if (key->type->request_key)
 		actor = key->type->request_key;
+#ifdef CONFIG_KEYAGENT
+	else {
+		ret = keyagent_request_key(authkey, aux);
 
+		/* ENOKEY: no keyagents match on calling process' keyrings */
+		if (ret != -ENOKEY)
+			goto done;
+	}
+#endif
 	ret = actor(authkey, aux);
 
+done:
 	/* check that the actor called complete_request_key() prior to
 	 * returning an error */
 	WARN_ON(ret < 0 &&