All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v12 00/10] Make keyring link restrictions accessible from userspace
@ 2017-03-09 20:23 Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 01/10] KEYS: Use a typedef for restrict_link function pointers Mat Martineau
                   ` (12 more replies)
  0 siblings, 13 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

Keyrings recently acquired the ability to validate keys before they are
linked using kernel internal APIs. This patch set enables configuration
of restricted keyrings from userspace.

These patches apply to linux-fs/keys-misc and are also available here:

    https://git.kernel.org/cgit/linux/kernel/git/martineau/linux.git/log/?h=keyctl-restrict

v12: Rework the KEYCTL_RESTRICT_KEYRING command to take an additional
parameter, renamed some functions based on feedback, and dropped an
unnecessary locking change (patch 1 in previous set).

v11: Configure restrictions using KEYCTL_RESTRICT_KEYRING instead of
using a keyring payload at creation time. Make the garbage collector
aware of restrictions.

v10: Fixups from maintainer feedback. Added some missing documentation.

v9: Rebased on linux-fs/keys-misc (v4.9-rc5)

v8: Add option to look for signing keys within the destination keyring.
Fix a consistency issue with keyring locking and restriction checks.

v7: Rework key restriction payload syntax. Move key-type-specific payload
parsing to the key-type. Attach more restriction information to keyrings
(restriction function, data, and data free) so future restrictions are not
limited to storing a key ID to use for key validation. Validate key before
using it to verify another key. Modify key type locking model to allow key
type lookup during keyring creation.

v6: Return error if only restrict_key is supplied, address misc. review
comments.

v5: Fixed signature bypass problem in patch 3/6

v4: Added userspace restriction options based on builtin keyrings.
restrict_link_by_signature implementation is no longer modified. Split
up v3's patch 2/5 to isolate the change to key.h.

v3: Updated commit message for patch 2/5 (restrict_link_by_signature_indirect)

v2: Payload is now preparsed

Mat Martineau (10):
  KEYS: Use a typedef for restrict_link function pointers
  KEYS: Split role of the keyring pointer for keyring restrict functions
  KEYS: Add a key restriction struct
  KEYS: Use structure to capture key restriction function and data
  KEYS: Add an optional lookup_restriction hook to key_type
  KEYS: Consistent ordering for __key_link_begin and restrict check
  KEYS: Add KEYCTL_RESTRICT_KEYRING
  KEYS: Add a lookup_restriction function for the asymmetric key type
  KEYS: Restrict asymmetric key linkage using a specific keychain
  KEYS: Keyring asymmetric key restrict method with chaining

 Documentation/crypto/asymmetric-keys.txt |  51 ++++++++++
 Documentation/security/keys.txt          |  59 ++++++++---
 certs/system_keyring.c                   |  39 ++++++--
 crypto/asymmetric_keys/asymmetric_type.c | 114 ++++++++++++++++++++--
 crypto/asymmetric_keys/restrict.c        | 161 ++++++++++++++++++++++++++++++-
 include/crypto/public_key.h              |  13 ++-
 include/keys/system_keyring.h            |   6 +-
 include/linux/key-type.h                 |   9 ++
 include/linux/key.h                      |  34 ++++---
 include/uapi/linux/keyctl.h              |   1 +
 security/keys/compat.c                   |   4 +
 security/keys/gc.c                       |  11 +++
 security/keys/internal.h                 |   5 +
 security/keys/key.c                      |  46 +++++----
 security/keys/keyctl.c                   |  58 +++++++++++
 security/keys/keyring.c                  | 155 +++++++++++++++++++++++++++--
 16 files changed, 691 insertions(+), 75 deletions(-)

-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v12 01/10] KEYS: Use a typedef for restrict_link function pointers
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
@ 2017-03-09 20:23 ` Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 02/10] KEYS: Split role of the keyring pointer for keyring restrict functions Mat Martineau
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

This pointer type needs to be returned from a lookup function, and
without a typedef the syntax gets cumbersome.

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 Documentation/security/keys.txt |  5 +----
 include/linux/key.h             | 16 +++++++---------
 security/keys/key.c             |  8 ++------
 security/keys/keyring.c         |  4 +---
 4 files changed, 11 insertions(+), 22 deletions(-)

diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index 3849814bfe6d..df695bddc140 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -1032,10 +1032,7 @@ payload contents" for more information.
 	struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
 				  const struct cred *cred,
 				  key_perm_t perm,
-				  int (*restrict_link)(struct key *,
-						       const struct key_type *,
-						       unsigned long,
-						       const union key_payload *),
+				  key_restrict_link_func_t restrict_link,
 				  unsigned long flags,
 				  struct key *dest);
 
diff --git a/include/linux/key.h b/include/linux/key.h
index 722914798f37..455171320ffc 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -126,6 +126,10 @@ static inline bool is_key_possessed(const key_ref_t key_ref)
 	return (unsigned long) key_ref & 1UL;
 }
 
+typedef int (*key_restrict_link_func_t)(struct key *keyring,
+					const struct key_type *type,
+					const union key_payload *payload);
+
 /*****************************************************************************/
 /*
  * authentication token / access credential / keyring
@@ -214,9 +218,7 @@ struct key {
 	 * overrides this, allowing the kernel to add extra keys without
 	 * restriction.
 	 */
-	int (*restrict_link)(struct key *keyring,
-			     const struct key_type *type,
-			     const union key_payload *payload);
+	key_restrict_link_func_t restrict_link;
 };
 
 extern struct key *key_alloc(struct key_type *type,
@@ -225,9 +227,7 @@ extern struct key *key_alloc(struct key_type *type,
 			     const struct cred *cred,
 			     key_perm_t perm,
 			     unsigned long flags,
-			     int (*restrict_link)(struct key *,
-						  const struct key_type *,
-						  const union key_payload *));
+			     key_restrict_link_func_t restrict_link);
 
 
 #define KEY_ALLOC_IN_QUOTA		0x0000	/* add to quota, reject if would overrun */
@@ -303,9 +303,7 @@ extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid
 				 const struct cred *cred,
 				 key_perm_t perm,
 				 unsigned long flags,
-				 int (*restrict_link)(struct key *,
-						      const struct key_type *,
-						      const union key_payload *),
+				 key_restrict_link_func_t restrict_link,
 				 struct key *dest);
 
 extern int restrict_link_reject(struct key *keyring,
diff --git a/security/keys/key.c b/security/keys/key.c
index 346fbf201c22..4e9138cc89e0 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -225,9 +225,7 @@ static inline void key_alloc_serial(struct key *key)
 struct key *key_alloc(struct key_type *type, const char *desc,
 		      kuid_t uid, kgid_t gid, const struct cred *cred,
 		      key_perm_t perm, unsigned long flags,
-		      int (*restrict_link)(struct key *,
-					   const struct key_type *,
-					   const union key_payload *))
+		      key_restrict_link_func_t restrict_link)
 {
 	struct key_user *user = NULL;
 	struct key *key;
@@ -806,9 +804,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 	struct key *keyring, *key = NULL;
 	key_ref_t key_ref;
 	int ret;
-	int (*restrict_link)(struct key *,
-			     const struct key_type *,
-			     const union key_payload *) = NULL;
+	key_restrict_link_func_t restrict_link = NULL;
 
 	/* look up the key type to see if it's one of the registered kernel
 	 * types */
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index c91e4e0cea08..a7f26fd08f6c 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -492,9 +492,7 @@ static long keyring_read(const struct key *keyring,
 struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
 			  const struct cred *cred, key_perm_t perm,
 			  unsigned long flags,
-			  int (*restrict_link)(struct key *,
-					       const struct key_type *,
-					       const union key_payload *),
+			  key_restrict_link_func_t restrict_link,
 			  struct key *dest)
 {
 	struct key *keyring;
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v12 02/10] KEYS: Split role of the keyring pointer for keyring restrict functions
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 01/10] KEYS: Use a typedef for restrict_link function pointers Mat Martineau
@ 2017-03-09 20:23 ` Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 03/10] KEYS: Add a key restriction struct Mat Martineau
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

The first argument to the restrict_link_func_t functions was a keyring
pointer. These functions are called by the key subsystem with this
argument set to the destination keyring, but restrict_link_by_signature
expects a pointer to the relevant trusted keyring.

Restrict functions may need something other than a single struct key
pointer to allow or reject key linkage, so the data used to make that
decision (such as the trust keyring) is moved to a new, fourth
argument. The first argument is now always the destination keyring.

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 Documentation/security/keys.txt   |  8 ++++----
 certs/system_keyring.c            | 18 +++++++++++-------
 crypto/asymmetric_keys/restrict.c |  9 ++++++---
 include/crypto/public_key.h       |  3 ++-
 include/keys/system_keyring.h     |  6 ++++--
 include/linux/key.h               |  8 +++++---
 security/keys/key.c               |  5 +++--
 security/keys/keyring.c           |  6 ++++--
 8 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index df695bddc140..5e7f63bade96 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -1054,10 +1054,10 @@ payload contents" for more information.
     can be verified by a key the kernel already has.
 
     When called, the restriction function will be passed the keyring being
-    added to, the key flags value and the type and payload of the key being
-    added.  Note that when a new key is being created, this is called between
-    payload preparsing and actual key creation.  The function should return 0
-    to allow the link or an error to reject it.
+    added to, the key type, the payload of the key being added, and data to be
+    used in the restriction check.  Note that when a new key is being created,
+    this is called between payload preparsing and actual key creation.  The
+    function should return 0 to allow the link or an error to reject it.
 
     A convenience function, restrict_link_reject, exists to always return
     -EPERM to in this case.
diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index 50979d6dcecd..e904653b7cff 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -32,11 +32,13 @@ extern __initconst const unsigned long system_certificate_list_size;
  * Restrict the addition of keys into a keyring based on the key-to-be-added
  * being vouched for by a key in the built in system keyring.
  */
-int restrict_link_by_builtin_trusted(struct key *keyring,
+int restrict_link_by_builtin_trusted(struct key *dest_keyring,
 				     const struct key_type *type,
-				     const union key_payload *payload)
+				     const union key_payload *payload,
+				     void *data)
 {
-	return restrict_link_by_signature(builtin_trusted_keys, type, payload);
+	return restrict_link_by_signature(dest_keyring, type, payload,
+					  builtin_trusted_keys);
 }
 
 #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
@@ -49,20 +51,22 @@ int restrict_link_by_builtin_trusted(struct key *keyring,
  * keyrings.
  */
 int restrict_link_by_builtin_and_secondary_trusted(
-	struct key *keyring,
+	struct key *dest_keyring,
 	const struct key_type *type,
-	const union key_payload *payload)
+	const union key_payload *payload,
+	void *data)
 {
 	/* If we have a secondary trusted keyring, then that contains a link
 	 * through to the builtin keyring and the search will follow that link.
 	 */
 	if (type == &key_type_keyring &&
-	    keyring == secondary_trusted_keys &&
+	    dest_keyring == secondary_trusted_keys &&
 	    payload == &builtin_trusted_keys->payload)
 		/* Allow the builtin keyring to be added to the secondary */
 		return 0;
 
-	return restrict_link_by_signature(secondary_trusted_keys, type, payload);
+	return restrict_link_by_signature(dest_keyring, type, payload,
+					  secondary_trusted_keys);
 }
 #endif
 
diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c
index 19d1afb9890f..d223929e01ac 100644
--- a/crypto/asymmetric_keys/restrict.c
+++ b/crypto/asymmetric_keys/restrict.c
@@ -56,9 +56,10 @@ __setup("ca_keys=", ca_keys_setup);
 
 /**
  * restrict_link_by_signature - Restrict additions to a ring of public keys
- * @trust_keyring: A ring of keys that can be used to vouch for the new cert.
+ * @dest_keyring: Keyring being linked to.
  * @type: The type of key being added.
  * @payload: The payload of the new key.
+ * @data: A ring of keys that can be used to vouch for the new cert.
  *
  * Check the new certificate against the ones in the trust keyring.  If one of
  * those is the signing key and validates the new certificate, then mark the
@@ -69,13 +70,15 @@ __setup("ca_keys=", ca_keys_setup);
  * signature check fails or the key is blacklisted and some other error if
  * there is a matching certificate but the signature check cannot be performed.
  */
-int restrict_link_by_signature(struct key *trust_keyring,
+int restrict_link_by_signature(struct key *dest_keyring,
 			       const struct key_type *type,
-			       const union key_payload *payload)
+			       const union key_payload *payload,
+			       void *data)
 {
 	const struct public_key_signature *sig;
 	struct key *key;
 	int ret;
+	struct key *trust_keyring = (struct key *) data;
 
 	pr_devel("==>%s()\n", __func__);
 
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index 882ca0e1e7a5..e28b182833cc 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -52,7 +52,8 @@ union key_payload;
 
 extern int restrict_link_by_signature(struct key *trust_keyring,
 				      const struct key_type *type,
-				      const union key_payload *payload);
+				      const union key_payload *payload,
+				      void *data);
 
 extern int verify_signature(const struct key *key,
 			    const struct public_key_signature *sig);
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 0d8762622ab9..d82e657b75a1 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -18,7 +18,8 @@
 
 extern int restrict_link_by_builtin_trusted(struct key *keyring,
 					    const struct key_type *type,
-					    const union key_payload *payload);
+					    const union key_payload *payload,
+					    void *data);
 
 #else
 #define restrict_link_by_builtin_trusted restrict_link_reject
@@ -28,7 +29,8 @@ extern int restrict_link_by_builtin_trusted(struct key *keyring,
 extern int restrict_link_by_builtin_and_secondary_trusted(
 	struct key *keyring,
 	const struct key_type *type,
-	const union key_payload *payload);
+	const union key_payload *payload,
+	void *data);
 #else
 #define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted
 #endif
diff --git a/include/linux/key.h b/include/linux/key.h
index 455171320ffc..c4016bc314f7 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -126,9 +126,10 @@ static inline bool is_key_possessed(const key_ref_t key_ref)
 	return (unsigned long) key_ref & 1UL;
 }
 
-typedef int (*key_restrict_link_func_t)(struct key *keyring,
+typedef int (*key_restrict_link_func_t)(struct key *dest_keyring,
 					const struct key_type *type,
-					const union key_payload *payload);
+					const union key_payload *payload,
+					void *data);
 
 /*****************************************************************************/
 /*
@@ -308,7 +309,8 @@ extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid
 
 extern int restrict_link_reject(struct key *keyring,
 				const struct key_type *type,
-				const union key_payload *payload);
+				const union key_payload *payload,
+				void *data);
 
 extern int keyring_clear(struct key *keyring);
 
diff --git a/security/keys/key.c b/security/keys/key.c
index 4e9138cc89e0..128ea40b01bd 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -499,7 +499,7 @@ int key_instantiate_and_link(struct key *key,
 	if (keyring) {
 		if (keyring->restrict_link) {
 			ret = keyring->restrict_link(keyring, key->type,
-						     &prep.payload);
+						     &prep.payload, NULL);
 			if (ret < 0)
 				goto error;
 		}
@@ -851,7 +851,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 	index_key.desc_len = strlen(index_key.description);
 
 	if (restrict_link) {
-		ret = restrict_link(keyring, index_key.type, &prep.payload);
+		ret = restrict_link(keyring, index_key.type, &prep.payload,
+				    NULL);
 		if (ret < 0) {
 			key_ref = ERR_PTR(ret);
 			goto error_free_prep;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index a7f26fd08f6c..ccffb536d17e 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -517,6 +517,7 @@ EXPORT_SYMBOL(keyring_alloc);
  * @keyring: The keyring being added to.
  * @type: The type of key being added.
  * @payload: The payload of the key intended to be added.
+ * @data: Additional data for evaluating restriction.
  *
  * Reject the addition of any links to a keyring.  It can be overridden by
  * passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when
@@ -527,7 +528,8 @@ EXPORT_SYMBOL(keyring_alloc);
  */
 int restrict_link_reject(struct key *keyring,
 			 const struct key_type *type,
-			 const union key_payload *payload)
+			 const union key_payload *payload,
+			 void *data)
 {
 	return -EPERM;
 }
@@ -1220,7 +1222,7 @@ static int __key_link_check_restriction(struct key *keyring, struct key *key)
 {
 	if (!keyring->restrict_link)
 		return 0;
-	return keyring->restrict_link(keyring, key->type, &key->payload);
+	return keyring->restrict_link(keyring, key->type, &key->payload, NULL);
 }
 
 /**
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v12 03/10] KEYS: Add a key restriction struct
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 01/10] KEYS: Use a typedef for restrict_link function pointers Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 02/10] KEYS: Split role of the keyring pointer for keyring restrict functions Mat Martineau
@ 2017-03-09 20:23 ` Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 04/10] KEYS: Use structure to capture key restriction function and data Mat Martineau
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

Key link restrictions require restriction-specific data as well as a
restriction-specific function pointer. As a first step toward replacing
the restrict_link pointer in struct key, define a more general
key_restriction structure that captures the function and data, as well
as a data freeing function and a key type pointer for use in garbage
collection. Key type modules should not be pinned on account of this
key type pointer because the pointer will be cleared by the garbage
collector if the key type is unregistered.

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 include/linux/key.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/key.h b/include/linux/key.h
index c4016bc314f7..771eda3385e0 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -131,6 +131,13 @@ typedef int (*key_restrict_link_func_t)(struct key *dest_keyring,
 					const union key_payload *payload,
 					void *data);
 
+struct key_restriction {
+	key_restrict_link_func_t check;
+	void (*free_data)(void *data);
+	void *data;
+	struct key_type *keytype;
+};
+
 /*****************************************************************************/
 /*
  * authentication token / access credential / keyring
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v12 04/10] KEYS: Use structure to capture key restriction function and data
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
                   ` (2 preceding siblings ...)
  2017-03-09 20:23 ` [PATCH v12 03/10] KEYS: Add a key restriction struct Mat Martineau
@ 2017-03-09 20:23 ` Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 05/10] KEYS: Add an optional lookup_restriction hook to key_type Mat Martineau
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

Replace struct key's restrict_link function pointer with a pointer to
the new struct key_restriction. The structure contains pointers to the
restriction function as well as relevant data for evaluating the
restriction. The optional key_restriction free_data function is called
at keyring destruction time.

The garbage collector checks restrict_link->keytype when key types are
unregistered. Restrictions involving a removed key type are converted
to use restrict_link_reject so that restrictions cannot be removed by
unregistering key types.

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 Documentation/security/keys.txt | 14 +++++---
 certs/system_keyring.c          | 21 +++++++++++-
 include/linux/key.h             |  8 ++---
 security/keys/gc.c              | 11 +++++++
 security/keys/internal.h        |  2 ++
 security/keys/key.c             | 23 ++++++++-----
 security/keys/keyring.c         | 73 ++++++++++++++++++++++++++++++++++++++---
 7 files changed, 128 insertions(+), 24 deletions(-)

diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index 5e7f63bade96..a31b7af8f5cf 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -1032,7 +1032,7 @@ payload contents" for more information.
 	struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
 				  const struct cred *cred,
 				  key_perm_t perm,
-				  key_restrict_link_func_t restrict_link,
+				  struct key_restriction *restrict_link,
 				  unsigned long flags,
 				  struct key *dest);
 
@@ -1044,10 +1044,14 @@ payload contents" for more information.
     KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted
     towards the user's quota).  Error ENOMEM can also be returned.
 
-    If restrict_link not NULL, it should point to a function that will be
-    called each time an attempt is made to link a key into the new keyring.
-    This function is called to check whether a key may be added into the keying
-    or not.  Callers of key_create_or_update() within the kernel can pass
+    If restrict_link is not NULL, it should point to a structure that contains
+    the function that will be called each time an attempt is made to link a key
+    into the new keyring.  The structure may also contain pertinent data, a
+    function to free that data, and an associated key type.  The function is
+    called to check whether a key may be added into the keyring or not.  The
+    key type is used by the garbage collector to clean up function or data
+    pointers in this structure if the given key type is unregistered.  Callers
+    of key_create_or_update() within the kernel can pass
     KEY_ALLOC_BYPASS_RESTRICTION to suppress the check.  An example of using
     this is to manage rings of cryptographic keys that are set up when the
     kernel boots where userspace is also permitted to add keys - provided they
diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index e904653b7cff..a64419bdf91e 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/cred.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 #include <keys/asymmetric-type.h>
 #include <keys/system_keyring.h>
 #include <crypto/pkcs7.h>
@@ -68,6 +69,24 @@ int restrict_link_by_builtin_and_secondary_trusted(
 	return restrict_link_by_signature(dest_keyring, type, payload,
 					  secondary_trusted_keys);
 }
+
+/**
+ * Allocate a struct key_restriction for the "builtin and secondary trust"
+ * keyring. Only for use in system_trusted_keyring_init().
+ */
+static __init struct key_restriction *get_builtin_and_secondary_restriction(void)
+{
+	struct key_restriction *restriction;
+
+	restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
+
+	if (!restriction)
+		panic("Can't allocate secondary trusted keyring restriction\n");
+
+	restriction->check = restrict_link_by_builtin_and_secondary_trusted;
+
+	return restriction;
+}
 #endif
 
 /*
@@ -95,7 +114,7 @@ static __init int system_trusted_keyring_init(void)
 			       KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
 			       KEY_USR_WRITE),
 			      KEY_ALLOC_NOT_IN_QUOTA,
-			      restrict_link_by_builtin_and_secondary_trusted,
+			      get_builtin_and_secondary_restriction(),
 			      NULL);
 	if (IS_ERR(secondary_trusted_keys))
 		panic("Can't allocate secondary trusted keyring\n");
diff --git a/include/linux/key.h b/include/linux/key.h
index 771eda3385e0..36725f728145 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -217,7 +217,7 @@ struct key {
 	};
 
 	/* This is set on a keyring to restrict the addition of a link to a key
-	 * to it.  If this method isn't provided then it is assumed that the
+	 * to it.  If this structure isn't provided then it is assumed that the
 	 * keyring is open to any addition.  It is ignored for non-keyring
 	 * keys.
 	 *
@@ -226,7 +226,7 @@ struct key {
 	 * overrides this, allowing the kernel to add extra keys without
 	 * restriction.
 	 */
-	key_restrict_link_func_t restrict_link;
+	struct key_restriction *restrict_link;
 };
 
 extern struct key *key_alloc(struct key_type *type,
@@ -235,7 +235,7 @@ extern struct key *key_alloc(struct key_type *type,
 			     const struct cred *cred,
 			     key_perm_t perm,
 			     unsigned long flags,
-			     key_restrict_link_func_t restrict_link);
+			     struct key_restriction *restrict_link);
 
 
 #define KEY_ALLOC_IN_QUOTA		0x0000	/* add to quota, reject if would overrun */
@@ -311,7 +311,7 @@ extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid
 				 const struct cred *cred,
 				 key_perm_t perm,
 				 unsigned long flags,
-				 key_restrict_link_func_t restrict_link,
+				 struct key_restriction *restrict_link,
 				 struct key *dest);
 
 extern int restrict_link_reject(struct key *keyring,
diff --git a/security/keys/gc.c b/security/keys/gc.c
index addf060399e0..d107a49a99d3 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -229,6 +229,9 @@ static void key_garbage_collector(struct work_struct *work)
 				set_bit(KEY_FLAG_DEAD, &key->flags);
 				key->perm = 0;
 				goto skip_dead_key;
+			} else if (key->type == &key_type_keyring &&
+				   key->restrict_link) {
+				goto found_restricted_keyring;
 			}
 		}
 
@@ -334,6 +337,14 @@ static void key_garbage_collector(struct work_struct *work)
 	gc_state |= KEY_GC_REAP_AGAIN;
 	goto maybe_resched;
 
+	/* We found a restricted keyring and need to update the restriction if
+	 * it is associated with the dead key type.
+	 */
+found_restricted_keyring:
+	spin_unlock(&key_serial_lock);
+	keyring_restriction_gc(key, key_gc_dead_keytype);
+	goto maybe_resched;
+
 	/* We found a keyring and we need to check the payload for links to
 	 * dead or expired keys.  We don't flag another reap immediately as we
 	 * have to wait for the old payload to be destroyed by RCU before we
diff --git a/security/keys/internal.h b/security/keys/internal.h
index a705a7d92ad7..3caeeee10a3e 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -166,6 +166,8 @@ extern void key_change_session_keyring(struct callback_head *twork);
 extern struct work_struct key_gc_work;
 extern unsigned key_gc_delay;
 extern void keyring_gc(struct key *keyring, time_t limit);
+extern void keyring_restriction_gc(struct key *keyring,
+				   struct key_type *dead_type);
 extern void key_schedule_gc(time_t gc_at);
 extern void key_schedule_gc_links(void);
 extern void key_gc_keytype(struct key_type *ktype);
diff --git a/security/keys/key.c b/security/keys/key.c
index 128ea40b01bd..488adf2b6ad4 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -201,12 +201,15 @@ static inline void key_alloc_serial(struct key *key)
  * @cred: The credentials specifying UID namespace.
  * @perm: The permissions mask of the new key.
  * @flags: Flags specifying quota properties.
- * @restrict_link: Optional link restriction method for new keyrings.
+ * @restrict_link: Optional link restriction for new keyrings.
  *
  * Allocate a key of the specified type with the attributes given.  The key is
  * returned in an uninstantiated state and the caller needs to instantiate the
  * key before returning.
  *
+ * The restrict_link structure (if not NULL) will be freed when the
+ * keyring is destroyed, so it must be dynamically allocated.
+ *
  * The user's key count quota is updated to reflect the creation of the key and
  * the user's key data quota has the default for the key type reserved.  The
  * instantiation function should amend this as necessary.  If insufficient
@@ -225,7 +228,7 @@ static inline void key_alloc_serial(struct key *key)
 struct key *key_alloc(struct key_type *type, const char *desc,
 		      kuid_t uid, kgid_t gid, const struct cred *cred,
 		      key_perm_t perm, unsigned long flags,
-		      key_restrict_link_func_t restrict_link)
+		      struct key_restriction *restrict_link)
 {
 	struct key_user *user = NULL;
 	struct key *key;
@@ -497,9 +500,11 @@ int key_instantiate_and_link(struct key *key,
 	}
 
 	if (keyring) {
-		if (keyring->restrict_link) {
-			ret = keyring->restrict_link(keyring, key->type,
-						     &prep.payload, NULL);
+		if (keyring->restrict_link && keyring->restrict_link->check) {
+			struct key_restriction *keyres = keyring->restrict_link;
+
+			ret = keyres->check(keyring, key->type, &prep.payload,
+					    keyres->data);
 			if (ret < 0)
 				goto error;
 		}
@@ -804,7 +809,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 	struct key *keyring, *key = NULL;
 	key_ref_t key_ref;
 	int ret;
-	key_restrict_link_func_t restrict_link = NULL;
+	struct key_restriction *restrict_link = NULL;
 
 	/* look up the key type to see if it's one of the registered kernel
 	 * types */
@@ -850,9 +855,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 	}
 	index_key.desc_len = strlen(index_key.description);
 
-	if (restrict_link) {
-		ret = restrict_link(keyring, index_key.type, &prep.payload,
-				    NULL);
+	if (restrict_link && restrict_link->check) {
+		ret = restrict_link->check(keyring, index_key.type,
+					   &prep.payload, restrict_link->data);
 		if (ret < 0) {
 			key_ref = ERR_PTR(ret);
 			goto error_free_prep;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index ccffb536d17e..9b1195bb841c 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -394,6 +394,15 @@ static void keyring_destroy(struct key *keyring)
 		write_unlock(&keyring_name_lock);
 	}
 
+	if (keyring->restrict_link) {
+		struct key_restriction *keyres = keyring->restrict_link;
+
+		if (keyres->free_data)
+			keyres->free_data(keyres->data);
+
+		kfree(keyres);
+	}
+
 	assoc_array_destroy(&keyring->keys, &keyring_assoc_array_ops);
 }
 
@@ -492,7 +501,7 @@ static long keyring_read(const struct key *keyring,
 struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
 			  const struct cred *cred, key_perm_t perm,
 			  unsigned long flags,
-			  key_restrict_link_func_t restrict_link,
+			  struct key_restriction *restrict_link,
 			  struct key *dest)
 {
 	struct key *keyring;
@@ -523,8 +532,8 @@ EXPORT_SYMBOL(keyring_alloc);
  * passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when
  * adding a key to a keyring.
  *
- * This is meant to be passed as the restrict_link parameter to
- * keyring_alloc().
+ * This is meant to be stored in a key_restriction structure which is passed
+ * in the restrict_link parameter to keyring_alloc().
  */
 int restrict_link_reject(struct key *keyring,
 			 const struct key_type *type,
@@ -1220,9 +1229,10 @@ void __key_link_end(struct key *keyring,
  */
 static int __key_link_check_restriction(struct key *keyring, struct key *key)
 {
-	if (!keyring->restrict_link)
+	if (!keyring->restrict_link || !keyring->restrict_link->check)
 		return 0;
-	return keyring->restrict_link(keyring, key->type, &key->payload, NULL);
+	return keyring->restrict_link->check(keyring, key->type, &key->payload,
+					     keyring->restrict_link->data);
 }
 
 /**
@@ -1426,3 +1436,56 @@ void keyring_gc(struct key *keyring, time_t limit)
 	up_write(&keyring->sem);
 	kleave(" [gc]");
 }
+
+/*
+ * Garbage collect restriction pointers from a keyring.
+ *
+ * Keyring restrictions are associated with a key type, and must be cleaned
+ * up if the key type is unregistered. The restriction is altered to always
+ * reject additional keys so a keyring cannot be opened up by unregistering
+ * a key type.
+ *
+ * Not called with any keyring locks held. The keyring's key struct will not
+ * be deallocated under us as only our caller may deallocate it.
+ *
+ * The caller is required to hold key_types_sem and dead_type->sem. This is
+ * fulfilled by key_gc_keytype() holding the locks on behalf of
+ * key_garbage_collector(), which it invokes on a workqueue.
+ */
+void keyring_restriction_gc(struct key *keyring, struct key_type *dead_type)
+{
+	struct key_restriction *keyres;
+
+	kenter("%x{%s}", keyring->serial, keyring->description ?: "");
+
+	/*
+	 * keyring->restrict_link is only assigned at key allocation time
+	 * or with the key type locked, so the only values that could be
+	 * concurrently assigned to keyring->restrict_link are for key
+	 * types other than dead_type. Given this, it's ok to check
+	 * the key type before acquiring keyring->sem.
+	 */
+	if (!dead_type || !keyring->restrict_link ||
+	    keyring->restrict_link->keytype != dead_type) {
+		kleave(" [no restriction gc]");
+		return;
+	}
+
+	/* Lock the keyring to ensure that a link is not in progress */
+	down_write(&keyring->sem);
+
+	keyres = keyring->restrict_link;
+
+	keyres->check = restrict_link_reject;
+
+	if (keyres->free_data)
+		keyres->free_data(keyres->data);
+
+	keyres->data = NULL;
+	keyres->free_data = NULL;
+	keyres->keytype = NULL;
+
+	up_write(&keyring->sem);
+
+	kleave(" [restriction gc]");
+}
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v12 05/10] KEYS: Add an optional lookup_restriction hook to key_type
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
                   ` (3 preceding siblings ...)
  2017-03-09 20:23 ` [PATCH v12 04/10] KEYS: Use structure to capture key restriction function and data Mat Martineau
@ 2017-03-09 20:23 ` Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check Mat Martineau
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

The restrict_link functions used to validate keys as they are linked
to a keyring can be associated with specific key types.  Each key type
may be loaded (or not) at runtime, so lookup of restrict_link
functions needs to be part of the key type implementation to ensure
that the requested keys can be examined.

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 Documentation/security/keys.txt | 9 +++++++++
 include/linux/key-type.h        | 9 +++++++++
 2 files changed, 18 insertions(+)

diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index a31b7af8f5cf..18d54fbc9129 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -1433,6 +1433,15 @@ The structure has a number of fields, some of which are mandatory:
      	 The authorisation key.
 
 
+ (*) struct key_restriction *(*lookup_restriction)(const char *params);
+
+     This optional method is used to enable userspace configuration of keyring
+     restrictions. The restriction parameter string (not including the key type
+     name) is passed in, and this method returns a pointer to a key_restriction
+     structure containing the relevant functions and data to evaluate each
+     attempted key link operation. If there is no match, -EINVAL is returned.
+
+
 ============================
 REQUEST-KEY CALLBACK SERVICE
 ============================
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index eaee981c5558..0a0b4c61e829 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -147,6 +147,15 @@ struct key_type {
 	 */
 	request_key_actor_t request_key;
 
+	/* Look up a keyring access restriction (optional)
+	 *
+	 * - The caller must hold a read lock on the key type's semaphore
+	 * - NULL is a valid return value (meaning the requested restriction
+	 *   is known but will never block addition of a key)
+	 * - should return -EINVAL if the restriction is unknown
+	 */
+	struct key_restriction *(*lookup_restriction)(const char *params);
+
 	/* internal fields */
 	struct list_head	link;		/* link in types list */
 	struct lock_class_key	lock_class;	/* key->sem lock class */
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
                   ` (4 preceding siblings ...)
  2017-03-09 20:23 ` [PATCH v12 05/10] KEYS: Add an optional lookup_restriction hook to key_type Mat Martineau
@ 2017-03-09 20:23 ` Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 07/10] KEYS: Add KEYCTL_RESTRICT_KEYRING Mat Martineau
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

The keyring restrict callback was sometimes called before
__key_link_begin and sometimes after, which meant that the keyring
semaphores were not always held during the restrict callback.

If the semaphores are consistently acquired before checking link
restrictions, keyring contents cannot be changed after the restrict
check is complete but before the evaluated key is linked to the keyring.

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 security/keys/key.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/security/keys/key.c b/security/keys/key.c
index 488adf2b6ad4..989ec35c1c48 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -500,21 +500,23 @@ int key_instantiate_and_link(struct key *key,
 	}
 
 	if (keyring) {
+		ret = __key_link_begin(keyring, &key->index_key, &edit);
+		if (ret < 0)
+			goto error;
+
 		if (keyring->restrict_link && keyring->restrict_link->check) {
 			struct key_restriction *keyres = keyring->restrict_link;
 
 			ret = keyres->check(keyring, key->type, &prep.payload,
 					    keyres->data);
 			if (ret < 0)
-				goto error;
+				goto error_link_end;
 		}
-		ret = __key_link_begin(keyring, &key->index_key, &edit);
-		if (ret < 0)
-			goto error;
 	}
 
 	ret = __key_instantiate_and_link(key, &prep, keyring, authkey, &edit);
 
+error_link_end:
 	if (keyring)
 		__key_link_end(keyring, &key->index_key, edit);
 
@@ -855,21 +857,21 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 	}
 	index_key.desc_len = strlen(index_key.description);
 
+	ret = __key_link_begin(keyring, &index_key, &edit);
+	if (ret < 0) {
+		key_ref = ERR_PTR(ret);
+		goto error_free_prep;
+	}
+
 	if (restrict_link && restrict_link->check) {
 		ret = restrict_link->check(keyring, index_key.type,
 					   &prep.payload, restrict_link->data);
 		if (ret < 0) {
 			key_ref = ERR_PTR(ret);
-			goto error_free_prep;
+			goto error_link_end;
 		}
 	}
 
-	ret = __key_link_begin(keyring, &index_key, &edit);
-	if (ret < 0) {
-		key_ref = ERR_PTR(ret);
-		goto error_free_prep;
-	}
-
 	/* if we're going to allocate a new key, we're going to have
 	 * to modify the keyring */
 	ret = key_permission(keyring_ref, KEY_NEED_WRITE);
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info@ http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v12 07/10] KEYS: Add KEYCTL_RESTRICT_KEYRING
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
                   ` (5 preceding siblings ...)
  2017-03-09 20:23 ` [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check Mat Martineau
@ 2017-03-09 20:23 ` Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 08/10] KEYS: Add a lookup_restriction function for the asymmetric key type Mat Martineau
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

Keyrings recently gained restrict_link capabilities that allow
individual keys to be validated prior to linking.  This functionality
was only available using internal kernel APIs.

With the KEYCTL_RESTRICT_KEYRING command existing keyrings can be
configured to check the content of keys before they are linked, and
then allow or disallow linkage of that key to the keyring.

To restrict a keyring, call:

  keyctl(KEYCTL_RESTRICT_KEYRING, key_serial_t keyring, char *restriction)

where 'restriction' is a string of format:

  "<key type>[:<restriction options>]"

The restriction option syntax is specific to each key type.

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 Documentation/security/keys.txt | 25 ++++++++++++++
 include/linux/key.h             |  5 ++-
 include/uapi/linux/keyctl.h     |  1 +
 security/keys/compat.c          |  4 +++
 security/keys/internal.h        |  3 ++
 security/keys/keyctl.c          | 58 +++++++++++++++++++++++++++++++
 security/keys/keyring.c         | 76 +++++++++++++++++++++++++++++++++++++++++
 7 files changed, 171 insertions(+), 1 deletion(-)

diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index 18d54fbc9129..8757e805dc84 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -857,6 +857,31 @@ The keyctl syscall functions are:
      supported, error ENOKEY if the key could not be found, or error
      EACCES if the key is not readable by the caller.
 
+ (*) Restrict keyring linkage
+
+       long keyctl(KEYCTL_RESTRICT_KEYRING, key_serial_t keyring,
+		   const char *type, const char *restriction);
+
+     An existing keyring can restrict linkage of additional keys by evaluating
+     the contents of the key according to a restriction scheme.
+
+     "keyring" is the key ID for an existing keyring to apply a restriction
+     to. It may be empty or may already have keys linked. Existing linked keys
+     will remain in the keyring even if the new restriction would reject them.
+
+     "type" is a registered key type.
+
+     "restriction" is a string describing how key linkage is to be restricted.
+     The format varies depending on the key type, and the string is passed to
+     the lookup_restriction() function for the requested type.  It may specify
+     a method and relevant data for the restriction such as signature
+     verification or constraints on key payload. If the requested key type is
+     later unregistered, no keys may be added to the keyring after the key type
+     is removed.
+
+     To apply a keyring restriction the process must have Set Attribute
+     permission and the keyring must not be previously restricted.
+
 ===============
 KERNEL SERVICES
 ===============
diff --git a/include/linux/key.h b/include/linux/key.h
index 36725f728145..6915f3e38df3 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -219,7 +219,7 @@ struct key {
 	/* This is set on a keyring to restrict the addition of a link to a key
 	 * to it.  If this structure isn't provided then it is assumed that the
 	 * keyring is open to any addition.  It is ignored for non-keyring
-	 * keys.
+	 * keys. Only set this value using key_alloc() or keyring_restrict().
 	 *
 	 * This is intended for use with rings of trusted keys whereby addition
 	 * to the keyring needs to be controlled.  KEY_ALLOC_BYPASS_RESTRICTION
@@ -328,6 +328,9 @@ extern key_ref_t keyring_search(key_ref_t keyring,
 extern int keyring_add_key(struct key *keyring,
 			   struct key *key);
 
+extern int keyring_restrict(key_ref_t keyring, const char *type,
+			    const char *restriction);
+
 extern struct key *key_lookup(key_serial_t id);
 
 static inline key_serial_t key_serial(const struct key *key)
diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h
index 86eddd6241f3..ff79c44e49a3 100644
--- a/include/uapi/linux/keyctl.h
+++ b/include/uapi/linux/keyctl.h
@@ -60,6 +60,7 @@
 #define KEYCTL_INVALIDATE		21	/* invalidate a key */
 #define KEYCTL_GET_PERSISTENT		22	/* get a user's persistent keyring */
 #define KEYCTL_DH_COMPUTE		23	/* Compute Diffie-Hellman values */
+#define KEYCTL_RESTRICT_KEYRING		29	/* Restrict keys allowed to link to a keyring */
 
 /* keyctl structures */
 struct keyctl_dh_params {
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 36c80bf5b89c..bb98f2b8dd7d 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -136,6 +136,10 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
 		return keyctl_dh_compute(compat_ptr(arg2), compat_ptr(arg3),
 					 arg4, compat_ptr(arg5));
 
+	case KEYCTL_RESTRICT_KEYRING:
+		return keyctl_restrict_keyring(arg2, compat_ptr(arg3),
+					       compat_ptr(arg4));
+
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 3caeeee10a3e..3da71856633e 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -250,6 +250,9 @@ struct iov_iter;
 extern long keyctl_instantiate_key_common(key_serial_t,
 					  struct iov_iter *,
 					  key_serial_t);
+extern long keyctl_restrict_keyring(key_serial_t id,
+				    const char __user *_type,
+				    const char __user *_restriction);
 #ifdef CONFIG_PERSISTENT_KEYRINGS
 extern long keyctl_get_persistent(uid_t, key_serial_t);
 extern unsigned persistent_keyring_expiry;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index d580ad06b792..a07944223c9d 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1581,6 +1581,59 @@ long keyctl_session_to_parent(void)
 }
 
 /*
+ * Apply a restriction to a given keyring.
+ *
+ * The caller must have Setattr permission to change keyring restrictions.
+ *
+ * The requested type name may be a NULL pointer to reject all attempts
+ * to link to the keyring. If _type is non-NULL, _restriction can be
+ * NULL or a pointer to a string describing the restriction. If _type is
+ * NULL, _restriction must also be NULL.
+ *
+ * Returns 0 if successful.
+ */
+long keyctl_restrict_keyring(key_serial_t id, const char __user *_type,
+			     const char __user *_restriction)
+{
+	key_ref_t key_ref;
+	bool link_reject = !_type;
+	char type[32];
+	char *restriction = NULL;
+	long ret;
+
+	key_ref = lookup_user_key(id, 0, KEY_NEED_SETATTR);
+	if (IS_ERR(key_ref))
+		return PTR_ERR(key_ref);
+
+	if (_type) {
+		ret = key_get_type_from_user(type, _type, sizeof(type));
+		if (ret < 0)
+			goto error;
+	}
+
+	if (_restriction) {
+		if (!_type) {
+			ret = -EINVAL;
+			goto error;
+		}
+
+		restriction = strndup_user(_restriction, PAGE_SIZE);
+		if (IS_ERR(restriction)) {
+			ret = PTR_ERR(restriction);
+			goto error;
+		}
+	}
+
+	ret = keyring_restrict(key_ref, link_reject ? NULL : type, restriction);
+	kfree(restriction);
+
+error:
+	key_ref_put(key_ref);
+
+	return ret;
+}
+
+/*
  * The key control system call
  */
 SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
@@ -1691,6 +1744,11 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
 					 (char __user *) arg3, (size_t) arg4,
 					 (void __user *) arg5);
 
+	case KEYCTL_RESTRICT_KEYRING:
+		return keyctl_restrict_keyring((key_serial_t) arg2,
+					       (const char __user *) arg3,
+					       (const char __user *) arg4);
+
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 9b1195bb841c..55590ed4f322 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -949,6 +949,82 @@ key_ref_t keyring_search(key_ref_t keyring,
 }
 EXPORT_SYMBOL(keyring_search);
 
+static struct key_restriction *keyring_restriction_alloc(
+	key_restrict_link_func_t check)
+{
+	struct key_restriction *keyres =
+		kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
+
+	if (!keyres)
+		return ERR_PTR(-ENOMEM);
+
+	keyres->check = check;
+
+	return keyres;
+}
+
+/**
+ * keyring_restrict - Look up and apply a restriction to a keyring
+ *
+ * @keyring: The keyring to be restricted
+ * @restriction: The restriction options to apply to the keyring
+ */
+int keyring_restrict(key_ref_t keyring_ref, const char *type,
+		     const char *restriction)
+{
+	struct key *keyring;
+	struct key_type *restrict_type = NULL;
+	struct key_restriction *restrict_link;
+	int ret;
+
+	keyring = key_ref_to_ptr(keyring_ref);
+	key_check(keyring);
+
+	if (keyring->type != &key_type_keyring)
+		return -ENOTDIR;
+
+	if (!type) {
+		restrict_link = keyring_restriction_alloc(restrict_link_reject);
+	} else {
+		restrict_type = key_type_lookup(type);
+
+		if (IS_ERR(restrict_type))
+			return PTR_ERR(restrict_type);
+
+		if (!restrict_type->lookup_restriction) {
+			ret = -ENOENT;
+			goto error;
+		}
+
+		restrict_link = restrict_type->lookup_restriction(restriction);
+	}
+
+	if (IS_ERR(restrict_link)) {
+		ret = PTR_ERR(restrict_link);
+		goto error;
+	}
+
+	down_write(&keyring->sem);
+	if (!keyring->restrict_link) {
+		keyring->restrict_link = restrict_link;
+		ret = 0;
+	} else {
+		if (restrict_link->free_data)
+			restrict_link->free_data(restrict_link->data);
+
+		kfree(restrict_link);
+		ret = -EEXIST;
+	}
+	up_write(&keyring->sem);
+
+error:
+	if (restrict_type)
+		key_type_put(restrict_type);
+
+	return ret;
+}
+EXPORT_SYMBOL(keyring_restrict);
+
 /*
  * Search the given keyring for a key that might be updated.
  *
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v12 08/10] KEYS: Add a lookup_restriction function for the asymmetric key type
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
                   ` (6 preceding siblings ...)
  2017-03-09 20:23 ` [PATCH v12 07/10] KEYS: Add KEYCTL_RESTRICT_KEYRING Mat Martineau
@ 2017-03-09 20:23 ` Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 09/10] KEYS: Restrict asymmetric key linkage using a specific keychain Mat Martineau
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

Look up asymmetric keyring restriction information using the key-type
lookup_restrict hook.

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 Documentation/crypto/asymmetric-keys.txt | 35 +++++++++++++++++++
 crypto/asymmetric_keys/asymmetric_type.c | 59 +++++++++++++++++++++++++++-----
 2 files changed, 86 insertions(+), 8 deletions(-)

diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt
index 2b7816dea370..4373e7d86c6a 100644
--- a/Documentation/crypto/asymmetric-keys.txt
+++ b/Documentation/crypto/asymmetric-keys.txt
@@ -311,3 +311,38 @@ Functions are provided to register and unregister parsers:
 
 Parsers may not have the same name.  The names are otherwise only used for
 displaying in debugging messages.
+
+
+=========================
+KEYRING LINK RESTRICTIONS
+=========================
+
+Keyrings created from userspace using add_key can be configured to check the
+signature of the key being linked.
+
+Several restriction methods are available:
+
+ (1) Restrict using the kernel builtin trusted keyring
+
+     - Option string used with KEYCTL_RESTRICT_KEYRING:
+       - "builtin_trusted"
+
+     The kernel builtin trusted keyring will be searched for the signing
+     key. The ca_keys kernel parameter also affects which keys are used for
+     signature verification.
+
+ (2) Restrict using the kernel builtin and secondary trusted keyrings
+
+     - Option string used with KEYCTL_RESTRICT_KEYRING:
+       - "builtin_and_secondary_trusted"
+
+     The kernel builtin and secondary trusted keyrings will be searched for the
+     signing key. The ca_keys kernel parameter also affects which keys are used
+     for signature verification.
+
+In all of these cases, if the signing key is found the signature of the key to
+be linked will be verified using the signing key.  The requested key is added
+to the keyring only if the signature is successfully verified.  -ENOKEY is
+returned if the parent certificate could not be found, or -EKEYREJECTED is
+returned if the signature check fails or the key is blacklisted.  Other errors
+may be returned if the signature check could not be performed.
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index 6600181d5d01..39708253defc 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/ctype.h>
+#include <keys/system_keyring.h>
 #include "asymmetric_keys.h"
 
 MODULE_LICENSE("GPL");
@@ -451,15 +452,57 @@ static void asymmetric_key_destroy(struct key *key)
 	asymmetric_key_free_kids(kids);
 }
 
+static struct key_restriction *asymmetric_restriction_alloc(
+	key_restrict_link_func_t check,
+	void (*free_data)(void *),
+	void *data)
+{
+	struct key_restriction *keyres =
+		kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
+
+	if (!keyres) {
+		if (free_data)
+			free_data(data);
+
+		return ERR_PTR(-ENOMEM);
+	}
+
+	keyres->check = check;
+	keyres->free_data = free_data;
+	keyres->data = data;
+	keyres->keytype = &key_type_asymmetric;
+
+	return keyres;
+}
+
+/*
+ * look up keyring restrict functions for asymmetric keys
+ */
+static struct key_restriction *asymmetric_lookup_restriction(
+	const char *restriction)
+{
+	if (strcmp("builtin_trusted", restriction) == 0)
+		return asymmetric_restriction_alloc(
+			restrict_link_by_builtin_trusted, NULL, NULL);
+
+	if (strcmp("builtin_and_secondary_trusted", restriction) == 0)
+		return asymmetric_restriction_alloc(
+			restrict_link_by_builtin_and_secondary_trusted,
+			NULL, NULL);
+
+	return ERR_PTR(-EINVAL);
+}
+
 struct key_type key_type_asymmetric = {
-	.name		= "asymmetric",
-	.preparse	= asymmetric_key_preparse,
-	.free_preparse	= asymmetric_key_free_preparse,
-	.instantiate	= generic_key_instantiate,
-	.match_preparse	= asymmetric_key_match_preparse,
-	.match_free	= asymmetric_key_match_free,
-	.destroy	= asymmetric_key_destroy,
-	.describe	= asymmetric_key_describe,
+	.name			= "asymmetric",
+	.preparse		= asymmetric_key_preparse,
+	.free_preparse		= asymmetric_key_free_preparse,
+	.instantiate		= generic_key_instantiate,
+	.match_preparse		= asymmetric_key_match_preparse,
+	.match_free		= asymmetric_key_match_free,
+	.destroy		= asymmetric_key_destroy,
+	.describe		= asymmetric_key_describe,
+	.lookup_restriction	= asymmetric_lookup_restriction,
 };
 EXPORT_SYMBOL_GPL(key_type_asymmetric);
 
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v12 09/10] KEYS: Restrict asymmetric key linkage using a specific keychain
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
                   ` (7 preceding siblings ...)
  2017-03-09 20:23 ` [PATCH v12 08/10] KEYS: Add a lookup_restriction function for the asymmetric key type Mat Martineau
@ 2017-03-09 20:23 ` Mat Martineau
  2017-03-09 20:23 ` [PATCH v12 10/10] KEYS: Keyring asymmetric key restrict method with chaining Mat Martineau
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

Adds restrict_link_by_signature_keyring(), which uses the restrict_key
member of the provided destination_keyring data structure as the
key or keyring to search for signing keys.

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 Documentation/crypto/asymmetric-keys.txt | 11 +++++
 crypto/asymmetric_keys/asymmetric_type.c | 39 ++++++++++++++++-
 crypto/asymmetric_keys/restrict.c        | 72 ++++++++++++++++++++++++++++++++
 include/crypto/public_key.h              |  5 +++
 4 files changed, 126 insertions(+), 1 deletion(-)

diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt
index 4373e7d86c6a..9814722f4b6b 100644
--- a/Documentation/crypto/asymmetric-keys.txt
+++ b/Documentation/crypto/asymmetric-keys.txt
@@ -340,6 +340,17 @@ Several restriction methods are available:
      signing key. The ca_keys kernel parameter also affects which keys are used
      for signature verification.
 
+ (3) Restrict using a separate key or keyring
+
+     - Option string used with KEYCTL_RESTRICT_KEYRING:
+       - "key_or_keyring:<key or keyring serial number>"
+
+     Whenever a key link is requested, the link will only succeed if the key
+     being linked is signed by one of the designated keys. This key may be
+     specified directly by providing a serial number for one asymmetric key, or
+     a group of keys may be searched for the signing key by providing the
+     serial number for a keyring.
+
 In all of these cases, if the signing key is found the signature of the key to
 be linked will be verified using the signing key.  The requested key is added
 to the keyring only if the signature is successfully verified.  -ENOKEY is
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index 39708253defc..7e14c201b72c 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -475,12 +475,22 @@ static struct key_restriction *asymmetric_restriction_alloc(
 	return keyres;
 }
 
+static void asymmetric_free_restriction(void *data)
+{
+	key_put((struct key *)data);
+}
+
 /*
  * look up keyring restrict functions for asymmetric keys
  */
 static struct key_restriction *asymmetric_lookup_restriction(
 	const char *restriction)
 {
+	char *restrict_method;
+	char *parse_buf;
+	char *next;
+	struct key_restriction *ret = ERR_PTR(-EINVAL);
+
 	if (strcmp("builtin_trusted", restriction) == 0)
 		return asymmetric_restriction_alloc(
 			restrict_link_by_builtin_trusted, NULL, NULL);
@@ -490,7 +500,34 @@ static struct key_restriction *asymmetric_lookup_restriction(
 			restrict_link_by_builtin_and_secondary_trusted,
 			NULL, NULL);
 
-	return ERR_PTR(-EINVAL);
+	parse_buf = kstrndup(restriction, PAGE_SIZE, GFP_KERNEL);
+	if (!parse_buf)
+		return ERR_PTR(-ENOMEM);
+
+	next = parse_buf;
+	restrict_method = strsep(&next, ":");
+
+	if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) {
+		key_serial_t serial;
+		struct key *key;
+
+		if (kstrtos32(next, 0, &serial) < 0)
+			goto out;
+
+		key = key_lookup(serial);
+		if (IS_ERR(key)) {
+			ret = ERR_PTR(PTR_ERR(key));
+			goto out;
+		}
+
+		ret = asymmetric_restriction_alloc(restrict_link_by_key_or_keyring,
+						   asymmetric_free_restriction,
+						   key);
+	}
+
+out:
+	kfree(parse_buf);
+	return ret;
 }
 
 struct key_type key_type_asymmetric = {
diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c
index d223929e01ac..b61002b42098 100644
--- a/crypto/asymmetric_keys/restrict.c
+++ b/crypto/asymmetric_keys/restrict.c
@@ -109,3 +109,75 @@ int restrict_link_by_signature(struct key *dest_keyring,
 	key_put(key);
 	return ret;
 }
+
+/**
+ * restrict_link_by_key_or_keyring - Restrict additions to a ring of public
+ * keys using the restrict_key information stored in the ring.
+ * @dest_keyring: Keyring being linked to.
+ * @type: The type of key being added.
+ * @payload: The payload of the new key.
+ * @data: A key or ring of keys that can be used to vouch for the new cert.
+ *
+ * Check the new certificate only against the key or keys passed in the data
+ * parameter. If one of those is the signing key and validates the new
+ * certificate, then mark the new certificate as being ok to link.
+ *
+ * Returns 0 if the new certificate was accepted, -ENOKEY if we
+ * couldn't find a matching parent certificate in the trusted list,
+ * -EKEYREJECTED if the signature check fails, and some other error if
+ * there is a matching certificate but the signature check cannot be
+ * performed.
+ */
+int restrict_link_by_key_or_keyring(struct key *dest_keyring,
+				    const struct key_type *type,
+				    const union key_payload *payload,
+				    void *data)
+{
+	const struct public_key_signature *sig;
+	struct key *key;
+	int ret;
+	struct key *trusted = (struct key *) data;
+
+	pr_devel("==>%s()\n", __func__);
+
+	if (!dest_keyring)
+		return -ENOKEY;
+	else if (dest_keyring->type != &key_type_keyring)
+		return -EOPNOTSUPP;
+
+	if (!trusted)
+		return -ENOKEY;
+
+	if (type != &key_type_asymmetric)
+		return -EOPNOTSUPP;
+
+	sig = payload->data[asym_auth];
+	if (!sig->auth_ids[0] && !sig->auth_ids[1])
+		return -ENOKEY;
+
+	if (trusted->type == &key_type_keyring) {
+		/* See if we have a key that signed this one. */
+		key = find_asymmetric_key(trusted, sig->auth_ids[0],
+					  sig->auth_ids[1], false);
+		if (IS_ERR(key))
+			return -ENOKEY;
+	} else if (trusted->type == &key_type_asymmetric) {
+		const struct asymmetric_key_ids *kids;
+
+		kids = asymmetric_key_ids(trusted);
+
+		if (!asymmetric_key_id_same(kids->id[1], sig->auth_ids[0]))
+			return -ENOKEY;
+
+		key = __key_get(trusted);
+	} else {
+		return -EOPNOTSUPP;
+	}
+
+	ret = key_validate(key);
+	if (ret == 0)
+		ret = verify_signature(key, sig);
+
+	key_put(key);
+	return ret;
+}
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index e28b182833cc..7f7facca7fd1 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -55,6 +55,11 @@ extern int restrict_link_by_signature(struct key *trust_keyring,
 				      const union key_payload *payload,
 				      void *data);
 
+extern int restrict_link_by_key_or_keyring(struct key *trust_keyring,
+					   const struct key_type *type,
+					   const union key_payload *payload,
+					   void *data);
+
 extern int verify_signature(const struct key *key,
 			    const struct public_key_signature *sig);
 
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v12 10/10] KEYS: Keyring asymmetric key restrict method with chaining
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
                   ` (8 preceding siblings ...)
  2017-03-09 20:23 ` [PATCH v12 09/10] KEYS: Restrict asymmetric key linkage using a specific keychain Mat Martineau
@ 2017-03-09 20:23 ` Mat Martineau
  2017-03-16 10:00 ` [PATCH v12 02/10] KEYS: Split role of the keyring pointer for keyring restrict functions David Howells
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-09 20:23 UTC (permalink / raw)
  To: linux-security-module

Add a restrict_link_by_key_or_keyring_chain link restriction that
searches for signing keys in the destination keyring in addition to the
signing key or keyring designated when the destination keyring was
created. Userspace enables this behavior by including the "chain" option
in the keyring restriction:

  keyctl(KEYCTL_RESTRICT_KEYRING, keyring,
         "asymmetric:key_or_keyring:<signing key>:chain");

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 Documentation/crypto/asymmetric-keys.txt |   7 +-
 crypto/asymmetric_keys/asymmetric_type.c |  30 ++++--
 crypto/asymmetric_keys/restrict.c        | 156 +++++++++++++++++++++++--------
 include/crypto/public_key.h              |   5 +
 4 files changed, 153 insertions(+), 45 deletions(-)

diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt
index 9814722f4b6b..5ad6480e3fb9 100644
--- a/Documentation/crypto/asymmetric-keys.txt
+++ b/Documentation/crypto/asymmetric-keys.txt
@@ -343,7 +343,7 @@ Several restriction methods are available:
  (3) Restrict using a separate key or keyring
 
      - Option string used with KEYCTL_RESTRICT_KEYRING:
-       - "key_or_keyring:<key or keyring serial number>"
+       - "key_or_keyring:<key or keyring serial number>[:chain]"
 
      Whenever a key link is requested, the link will only succeed if the key
      being linked is signed by one of the designated keys. This key may be
@@ -351,6 +351,11 @@ Several restriction methods are available:
      a group of keys may be searched for the signing key by providing the
      serial number for a keyring.
 
+     When the "chain" option is provided at the end of the string, the keys
+     within the destination keyring will also be searched for signing keys.
+     This allows for verification of certificate chains by adding each
+     cert in order (starting closest to the root) to one keyring.
+
 In all of these cases, if the signing key is found the signature of the key to
 be linked will be verified using the signing key.  The requested key is added
 to the keyring only if the signature is successfully verified.  -ENOKEY is
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index 7e14c201b72c..71db06f1723e 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -508,19 +508,37 @@ static struct key_restriction *asymmetric_lookup_restriction(
 	restrict_method = strsep(&next, ":");
 
 	if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) {
+		char *key_text;
 		key_serial_t serial;
 		struct key *key;
+		key_restrict_link_func_t link_fn =
+			restrict_link_by_key_or_keyring;
+		bool allow_null_key = false;
 
-		if (kstrtos32(next, 0, &serial) < 0)
-			goto out;
+		key_text = strsep(&next, ":");
+
+		if (next) {
+			if (strcmp(next, "chain") != 0)
+				goto out;
+
+			link_fn = restrict_link_by_key_or_keyring_chain;
+			allow_null_key = true;
+		}
 
-		key = key_lookup(serial);
-		if (IS_ERR(key)) {
-			ret = ERR_PTR(PTR_ERR(key));
+		if (kstrtos32(key_text, 0, &serial) < 0)
 			goto out;
+
+		if ((serial == 0) && allow_null_key) {
+			key = NULL;
+		} else {
+			key = key_lookup(serial);
+			if (IS_ERR(key)) {
+				ret = ERR_PTR(PTR_ERR(key));
+				goto out;
+			}
 		}
 
-		ret = asymmetric_restriction_alloc(restrict_link_by_key_or_keyring,
+		ret = asymmetric_restriction_alloc(link_fn,
 						   asymmetric_free_restriction,
 						   key);
 	}
diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c
index b61002b42098..e4b1283649f7 100644
--- a/crypto/asymmetric_keys/restrict.c
+++ b/crypto/asymmetric_keys/restrict.c
@@ -110,31 +110,20 @@ int restrict_link_by_signature(struct key *dest_keyring,
 	return ret;
 }
 
-/**
- * restrict_link_by_key_or_keyring - Restrict additions to a ring of public
- * keys using the restrict_key information stored in the ring.
- * @dest_keyring: Keyring being linked to.
- * @type: The type of key being added.
- * @payload: The payload of the new key.
- * @data: A key or ring of keys that can be used to vouch for the new cert.
- *
- * Check the new certificate only against the key or keys passed in the data
- * parameter. If one of those is the signing key and validates the new
- * certificate, then mark the new certificate as being ok to link.
- *
- * Returns 0 if the new certificate was accepted, -ENOKEY if we
- * couldn't find a matching parent certificate in the trusted list,
- * -EKEYREJECTED if the signature check fails, and some other error if
- * there is a matching certificate but the signature check cannot be
- * performed.
- */
-int restrict_link_by_key_or_keyring(struct key *dest_keyring,
-				    const struct key_type *type,
-				    const union key_payload *payload,
-				    void *data)
+static bool match_either_id(const struct asymmetric_key_ids *pair,
+			    const struct asymmetric_key_id *single)
+{
+	return (asymmetric_key_id_same(pair->id[0], single) ||
+		asymmetric_key_id_same(pair->id[1], single));
+}
+
+static int key_or_keyring_common(struct key *dest_keyring,
+				 const struct key_type *type,
+				 const union key_payload *payload,
+				 void *data, bool check_dest)
 {
 	const struct public_key_signature *sig;
-	struct key *key;
+	struct key *key = NULL;
 	int ret;
 	struct key *trusted = (struct key *) data;
 
@@ -145,7 +134,7 @@ int restrict_link_by_key_or_keyring(struct key *dest_keyring,
 	else if (dest_keyring->type != &key_type_keyring)
 		return -EOPNOTSUPP;
 
-	if (!trusted)
+	if (!trusted && !check_dest)
 		return -ENOKEY;
 
 	if (type != &key_type_asymmetric)
@@ -155,25 +144,64 @@ int restrict_link_by_key_or_keyring(struct key *dest_keyring,
 	if (!sig->auth_ids[0] && !sig->auth_ids[1])
 		return -ENOKEY;
 
-	if (trusted->type == &key_type_keyring) {
-		/* See if we have a key that signed this one. */
-		key = find_asymmetric_key(trusted, sig->auth_ids[0],
-					  sig->auth_ids[1], false);
-		if (IS_ERR(key))
-			return -ENOKEY;
-	} else if (trusted->type == &key_type_asymmetric) {
-		const struct asymmetric_key_ids *kids;
+	if (trusted) {
+		if (trusted->type == &key_type_keyring) {
+			/* See if we have a key that signed this one. */
+			key = find_asymmetric_key(trusted, sig->auth_ids[0],
+						  sig->auth_ids[1], false);
+			if (IS_ERR(key))
+				key = NULL;
+		} else if (trusted->type == &key_type_asymmetric) {
+			const struct asymmetric_key_ids *signer_ids;
 
-		kids = asymmetric_key_ids(trusted);
+			signer_ids = asymmetric_key_ids(trusted);
 
-		if (!asymmetric_key_id_same(kids->id[1], sig->auth_ids[0]))
-			return -ENOKEY;
+			/*
+			 * The auth_ids come from the candidate key (the
+			 * one that is being considered for addition to
+			 * dest_keyring) and identify the key that was
+			 * used to sign.
+			 *
+			 * The signer_ids are identifiers for the
+			 * signing key specified for dest_keyring.
+			 *
+			 * The first auth_id is the preferred id, and
+			 * the second is the fallback. If only one
+			 * auth_id is present, it may match against
+			 * either signer_id. If two auth_ids are
+			 * present, the first auth_id must match one
+			 * signer_id and the second auth_id must match
+			 * the second signer_id.
+			 */
+			if (!sig->auth_ids[0] || !sig->auth_ids[1]) {
+				const struct asymmetric_key_id *auth_id;
 
-		key = __key_get(trusted);
-	} else {
-		return -EOPNOTSUPP;
+				auth_id = sig->auth_ids[0] ?: sig->auth_ids[1];
+				if (match_either_id(signer_ids, auth_id))
+					key = __key_get(trusted);
+
+			} else if (asymmetric_key_id_same(signer_ids->id[1],
+							  sig->auth_ids[1]) &&
+				   match_either_id(signer_ids,
+						   sig->auth_ids[0])) {
+				key = __key_get(trusted);
+			}
+		} else {
+			return -EOPNOTSUPP;
+		}
 	}
 
+	if (check_dest && !key) {
+		/* See if the destination has a key that signed this one. */
+		key = find_asymmetric_key(dest_keyring, sig->auth_ids[0],
+					  sig->auth_ids[1], false);
+		if (IS_ERR(key))
+			key = NULL;
+	}
+
+	if (!key)
+		return -ENOKEY;
+
 	ret = key_validate(key);
 	if (ret == 0)
 		ret = verify_signature(key, sig);
@@ -181,3 +209,55 @@ int restrict_link_by_key_or_keyring(struct key *dest_keyring,
 	key_put(key);
 	return ret;
 }
+
+/**
+ * restrict_link_by_key_or_keyring - Restrict additions to a ring of public
+ * keys using the restrict_key information stored in the ring.
+ * @dest_keyring: Keyring being linked to.
+ * @type: The type of key being added.
+ * @payload: The payload of the new key.
+ * @data: A key or ring of keys that can be used to vouch for the new cert.
+ *
+ * Check the new certificate only against the key or keys passed in the data
+ * parameter. If one of those is the signing key and validates the new
+ * certificate, then mark the new certificate as being ok to link.
+ *
+ * Returns 0 if the new certificate was accepted, -ENOKEY if we
+ * couldn't find a matching parent certificate in the trusted list,
+ * -EKEYREJECTED if the signature check fails, and some other error if
+ * there is a matching certificate but the signature check cannot be
+ * performed.
+ */
+int restrict_link_by_key_or_keyring(struct key *dest_keyring,
+				    const struct key_type *type,
+				    const union key_payload *payload,
+				    void *data)
+{
+	return key_or_keyring_common(dest_keyring, type, payload, data, false);
+}
+
+/**
+ * restrict_link_by_key_or_keyring_chain - Restrict additions to a ring of
+ * public keys using the restrict_key information stored in the ring.
+ * @dest_keyring: Keyring being linked to.
+ * @type: The type of key being added.
+ * @payload: The payload of the new key.
+ * @data: A key or ring of keys that can be used to vouch for the new cert.
+ *
+ * Check the new certificate only against the key or keys passed in the data
+ * parameter. If one of those is the signing key and validates the new
+ * certificate, then mark the new certificate as being ok to link.
+ *
+ * Returns 0 if the new certificate was accepted, -ENOKEY if we
+ * couldn't find a matching parent certificate in the trusted list,
+ * -EKEYREJECTED if the signature check fails, and some other error if
+ * there is a matching certificate but the signature check cannot be
+ * performed.
+ */
+int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring,
+					  const struct key_type *type,
+					  const union key_payload *payload,
+					  void *data)
+{
+	return key_or_keyring_common(dest_keyring, type, payload, data, true);
+}
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index 7f7facca7fd1..24e5bef2fa1c 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -60,6 +60,11 @@ extern int restrict_link_by_key_or_keyring(struct key *trust_keyring,
 					   const union key_payload *payload,
 					   void *data);
 
+extern int restrict_link_by_key_or_keyring_chain(struct key *trust_keyring,
+						 const struct key_type *type,
+						 const union key_payload *payload,
+						 void *data);
+
 extern int verify_signature(const struct key *key,
 			    const struct public_key_signature *sig);
 
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v12 02/10] KEYS: Split role of the keyring pointer for keyring restrict functions
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
                   ` (9 preceding siblings ...)
  2017-03-09 20:23 ` [PATCH v12 10/10] KEYS: Keyring asymmetric key restrict method with chaining Mat Martineau
@ 2017-03-16 10:00 ` David Howells
  2017-03-16 10:09 ` [PATCH v12 05/10] KEYS: Add an optional lookup_restriction hook to key_type David Howells
  2017-03-16 10:17 ` [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check David Howells
  12 siblings, 0 replies; 19+ messages in thread
From: David Howells @ 2017-03-16 10:00 UTC (permalink / raw)
  To: linux-security-module

Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:

> +			       void *data)
>  {
>  	const struct public_key_signature *sig;
>  	struct key *key;
>  	int ret;
> +	struct key *trust_keyring = (struct key *) data;

The cast is unnecessary, but let that pass unless the patches get respun
again.

David
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v12 05/10] KEYS: Add an optional lookup_restriction hook to key_type
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
                   ` (10 preceding siblings ...)
  2017-03-16 10:00 ` [PATCH v12 02/10] KEYS: Split role of the keyring pointer for keyring restrict functions David Howells
@ 2017-03-16 10:09 ` David Howells
  2017-03-16 23:02   ` Mat Martineau
  2017-03-16 10:17 ` [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check David Howells
  12 siblings, 1 reply; 19+ messages in thread
From: David Howells @ 2017-03-16 10:09 UTC (permalink / raw)
  To: linux-security-module

Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:

> +	/* Look up a keyring access restriction (optional)
> +	 *
> +	 * - The caller must hold a read lock on the key type's semaphore
> +	 * - NULL is a valid return value (meaning the requested restriction
> +	 *   is known but will never block addition of a key)
> +	 * - should return -EINVAL if the restriction is unknown
> +	 */
> +	struct key_restriction *(*lookup_restriction)(const char *params);

I wonder if this can be improved in future to using the rcu read lock instead
of a semaphore.

David
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check
  2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
                   ` (11 preceding siblings ...)
  2017-03-16 10:09 ` [PATCH v12 05/10] KEYS: Add an optional lookup_restriction hook to key_type David Howells
@ 2017-03-16 10:17 ` David Howells
  2017-03-17  0:47   ` Mat Martineau
  2017-03-17  7:43   ` David Howells
  12 siblings, 2 replies; 19+ messages in thread
From: David Howells @ 2017-03-16 10:17 UTC (permalink / raw)
  To: linux-security-module

Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:

> The keyring restrict callback was sometimes called before
> __key_link_begin and sometimes after, which meant that the keyring
> semaphores were not always held during the restrict callback.
> 
> If the semaphores are consistently acquired before checking link
> restrictions, keyring contents cannot be changed after the restrict
> check is complete but before the evaluated key is linked to the keyring.

I'm still not entirely sure that this gains us anything.  At the point we did
the restriction check, the key was validated.  Yes, the keyring can be
modified between then and the actual link, thereby rendering the chain broken
- but this is true after the link also.  The whole point is that it was valid
at the time of asking.

Mainly I have an aversion to doing things under a lock when I can do it
outside of the lock.

Btw, do you check for cycles anywhere?  For example, if I create two keyrings,
A and B, and can I then set restrictions such that A is restricted by B and B
is restricted by A?

David
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v12 05/10] KEYS: Add an optional lookup_restriction hook to key_type
  2017-03-16 10:09 ` [PATCH v12 05/10] KEYS: Add an optional lookup_restriction hook to key_type David Howells
@ 2017-03-16 23:02   ` Mat Martineau
  0 siblings, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-16 23:02 UTC (permalink / raw)
  To: linux-security-module


On Thu, 16 Mar 2017, David Howells wrote:

> Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:
>
>> +	/* Look up a keyring access restriction (optional)
>> +	 *
>> +	 * - The caller must hold a read lock on the key type's semaphore
>> +	 * - NULL is a valid return value (meaning the requested restriction
>> +	 *   is known but will never block addition of a key)
>> +	 * - should return -EINVAL if the restriction is unknown
>> +	 */
>> +	struct key_restriction *(*lookup_restriction)(const char *params);
>
> I wonder if this can be improved in future to using the rcu read lock instead
> of a semaphore.

I'll update this comment to remove the read lock line, since the patch 
adding the key type semaphore has been dropped. The comment here was not 
really needed anyway, it should be obvious that the key type can't go away 
while you're calling in to it.

--
Mat Martineau
Intel OTC
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check
  2017-03-16 10:17 ` [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check David Howells
@ 2017-03-17  0:47   ` Mat Martineau
  2017-03-17  7:43   ` David Howells
  1 sibling, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-17  0:47 UTC (permalink / raw)
  To: linux-security-module

On Thu, 16 Mar 2017, David Howells wrote:

> Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:
>
>> The keyring restrict callback was sometimes called before
>> __key_link_begin and sometimes after, which meant that the keyring
>> semaphores were not always held during the restrict callback.
>>
>> If the semaphores are consistently acquired before checking link
>> restrictions, keyring contents cannot be changed after the restrict
>> check is complete but before the evaluated key is linked to the keyring.
>
> I'm still not entirely sure that this gains us anything.  At the point we did
> the restriction check, the key was validated.  Yes, the keyring can be
> modified between then and the actual link, thereby rendering the chain broken
> - but this is true after the link also.  The whole point is that it was valid
> at the time of asking.
>
> Mainly I have an aversion to doing things under a lock when I can do it
> outside of the lock.

Restriction methods can consider the contents of the keyring being linked 
to, and they can't really be thought of as enforcing invariants on the 
contents of the keyring without this patch.

This locking change had more concrete consequences before 
KEYCTL_RESTRICT_KEYRING, when you could add the first cert to an empty 
keyring without a signature check and all later additions would verify 
signatures based on certificates already in the keyring. It would have 
been possible to add multiple certs (that hadn't signed each other) to an 
empty keyring if the keys were both checked before they were linked.

In the current iteration of the patch set, it comes down to enforcing 
invariants (as I mentioned above) and consistency in lock/check ordering 
across different code paths. Restriction functions (present or future) 
can't offer a consistency or security guarantee about the state of the 
keyring if the contents of the keyring can change between the check and 
the link. I share your locking aversion, but think this is a case where 
a lock is needed.

> Btw, do you check for cycles anywhere?  For example, if I create two keyrings,
> A and B, and can I then set restrictions such that A is restricted by B and B
> is restricted by A?

I don't check for cycles yet, but the references held by the restrictions 
could be a problem. I'm not sure how to address it yet, I could clear the 
restriction info when a keyring is revoked/dead/etc or I could check when 
restrictions are created.

--
Mat Martineau
Intel OTC
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check
  2017-03-16 10:17 ` [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check David Howells
  2017-03-17  0:47   ` Mat Martineau
@ 2017-03-17  7:43   ` David Howells
  2017-03-17 22:35     ` Mat Martineau
  2017-03-18  8:10     ` David Howells
  1 sibling, 2 replies; 19+ messages in thread
From: David Howells @ 2017-03-17  7:43 UTC (permalink / raw)
  To: linux-security-module

Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:

> > Btw, do you check for cycles anywhere?  For example, if I create two keyrings,
> > A and B, and can I then set restrictions such that A is restricted by B and B
> > is restricted by A?
> 
> I don't check for cycles yet, but the references held by the restrictions
> could be a problem. I'm not sure how to address it yet, I could clear the
> restriction info when a keyring is revoked/dead/etc or I could check when
> restrictions are created.

Yep.

The way to do it is to store the pointer to the restriction keyring in the
restriction record and then when you set a restriction on keyring A that
refers to keyring B as a source of authority, you go to B's restriction record
and if it points to A, say no, if it points to C, go to C's record and if it
points to A, say no, if it points to D, go to D's record and so on and so on -
all whilst under a master lock.

As the above algorithm only has one pointer to follow each time, it can be
done iteratively, so no particular stack overhead.  And as a lock is held
whilst you do the check and the add, you can't get one process adding an A->B
dependency whilst another adds B->A.

David
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check
  2017-03-17  7:43   ` David Howells
@ 2017-03-17 22:35     ` Mat Martineau
  2017-03-18  8:10     ` David Howells
  1 sibling, 0 replies; 19+ messages in thread
From: Mat Martineau @ 2017-03-17 22:35 UTC (permalink / raw)
  To: linux-security-module


On Fri, 17 Mar 2017, David Howells wrote:

> Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:
>
>>> Btw, do you check for cycles anywhere?  For example, if I create two keyrings,
>>> A and B, and can I then set restrictions such that A is restricted by B and B
>>> is restricted by A?
>>
>> I don't check for cycles yet, but the references held by the restrictions
>> could be a problem. I'm not sure how to address it yet, I could clear the
>> restriction info when a keyring is revoked/dead/etc or I could check when
>> restrictions are created.
>
> Yep.
>
> The way to do it is to store the pointer to the restriction keyring in the
> restriction record and then when you set a restriction on keyring A that
> refers to keyring B as a source of authority, you go to B's restriction record
> and if it points to A, say no, if it points to C, go to C's record and if it
> points to A, say no, if it points to D, go to D's record and so on and so on -
> all whilst under a master lock.
>
> As the above algorithm only has one pointer to follow each time, it can be
> done iteratively, so no particular stack overhead.  And as a lock is held
> whilst you do the check and the add, you can't get one process adding an A->B
> dependency whilst another adds B->A.


v6 and earlier of the patch set had a pointer to the restriction keyring 
in the restriction record, then we generalized the structure to use a 
void* and the free_data function. The void* is helpful for letting the key 
types have more complicated restrictions (maybe even having *multiple* 
keyring dependencies), but it rules out the iterative search technique.

I see why my first suggestion doesn't work: while destroyed keyrings 
already clear out their restriction references, that doesn't help when the 
ref count goes to 0 on an instantiated keyring.


Do we go back to the simpler restriction record (just a key pointer, no 
void*, no free_data) so we can detect cycles without the stack overhead of 
a depth-first search, like this?

struct key_restriction {
 	key_restrict_link_func_t check;
 	struct key *key;
 	struct key_type *owner_type;
};

If we have both a key pointer and a void*, the void* won't be used by the 
asymmetric key type and future restriction implementations could end up 
with cycle problems if they stash key pointers behind that void*.

Other solutions I can think of would add a lot of complexity (like adding 
weak references), so I favor using the single key pointer as in the struct 
above.

--
Mat Martineau
Intel OTC
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check
  2017-03-17  7:43   ` David Howells
  2017-03-17 22:35     ` Mat Martineau
@ 2017-03-18  8:10     ` David Howells
  1 sibling, 0 replies; 19+ messages in thread
From: David Howells @ 2017-03-18  8:10 UTC (permalink / raw)
  To: linux-security-module

Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:

> Do we go back to the simpler restriction record (just a key pointer, no void*,
> no free_data) so we can detect cycles without the stack overhead of a
> depth-first search, like this?

Sure.  We can always add data in future.

David
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2017-03-18  8:10 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-09 20:23 [PATCH v12 00/10] Make keyring link restrictions accessible from userspace Mat Martineau
2017-03-09 20:23 ` [PATCH v12 01/10] KEYS: Use a typedef for restrict_link function pointers Mat Martineau
2017-03-09 20:23 ` [PATCH v12 02/10] KEYS: Split role of the keyring pointer for keyring restrict functions Mat Martineau
2017-03-09 20:23 ` [PATCH v12 03/10] KEYS: Add a key restriction struct Mat Martineau
2017-03-09 20:23 ` [PATCH v12 04/10] KEYS: Use structure to capture key restriction function and data Mat Martineau
2017-03-09 20:23 ` [PATCH v12 05/10] KEYS: Add an optional lookup_restriction hook to key_type Mat Martineau
2017-03-09 20:23 ` [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check Mat Martineau
2017-03-09 20:23 ` [PATCH v12 07/10] KEYS: Add KEYCTL_RESTRICT_KEYRING Mat Martineau
2017-03-09 20:23 ` [PATCH v12 08/10] KEYS: Add a lookup_restriction function for the asymmetric key type Mat Martineau
2017-03-09 20:23 ` [PATCH v12 09/10] KEYS: Restrict asymmetric key linkage using a specific keychain Mat Martineau
2017-03-09 20:23 ` [PATCH v12 10/10] KEYS: Keyring asymmetric key restrict method with chaining Mat Martineau
2017-03-16 10:00 ` [PATCH v12 02/10] KEYS: Split role of the keyring pointer for keyring restrict functions David Howells
2017-03-16 10:09 ` [PATCH v12 05/10] KEYS: Add an optional lookup_restriction hook to key_type David Howells
2017-03-16 23:02   ` Mat Martineau
2017-03-16 10:17 ` [PATCH v12 06/10] KEYS: Consistent ordering for __key_link_begin and restrict check David Howells
2017-03-17  0:47   ` Mat Martineau
2017-03-17  7:43   ` David Howells
2017-03-17 22:35     ` Mat Martineau
2017-03-18  8:10     ` David Howells

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.