Re: [RFC PATCH 07/20] KEYS: Add a facility to restrict new links into a keyring [ver #2]
From: Mimi Zohar
Date: Mon Feb 08 2016 - 07:00:25 EST
On Tue, 2016-01-19 at 11:31 +0000, David Howells wrote:
> Add a facility whereby proposed new links to be added to a keyring can be
> vetted, permitting them to be rejected if necessary. This can be used to
> block public keys from which the signature cannot be verified or for which
> the signature verification fails. It could also be used to provide
> blacklisting.
>
> This affects operations like add_key(), KEYCTL_LINK and KEYCTL_INSTANTIATE.
>
> To this end:
>
> (1) A function pointer is added to the key struct that, if set, points to
> the vetting function. This is called as:
>
> int (*restrict_link)(struct key *keyring,
> const struct key_type *key_type,
> unsigned long key_flags,
> const union key_payload *key_payload),
>
> where 'keyring' will be the keyring being added to, key_type and
> key_payload will describe the key being added and key_flags[*] can be
> AND'ed with KEY_FLAG_TRUSTED.
>
> [*] This parameter will be removed in a later patch when
> KEY_FLAG_TRUSTED is removed.
>
> The function should return 0 to allow the link to take place or an
> error (typically -ENOKEY, -ENOPKG or -EKEYREJECTED) to reject the
> link.
>
> The pointer should not be set directly, but rather should be set
> through keyring_alloc().
>
> Note that if called during add_key(), preparse is called before this
> method, but a key isn't actually allocated until after this function
> is called.
>
> (2) KEY_ALLOC_BYPASS_RESTRICTION is added. This can be passed to
> key_create_or_update() or key_instantiate_and_link() to bypass the
> restriction check.
>
> (3) KEY_FLAG_TRUSTED_ONLY is removed. The entire contents of a keyring
> with this restriction emplaced can be considered 'trustworthy' by
> virtue of being in the keyring when that keyring is consulted.
>
> (4) key_alloc() and keyring_alloc() take an extra argument that will be
> used to set restrict_link in the new key. This ensures that the
> pointer is set before the key is published, thus preventing a window
> of unrestrictedness. Normally this argument will be NULL.
>
> (5) As a temporary affair, keyring_restrict_trusted_only() is added. It
> should be passed to keyring_alloc() as the extra argument instead of
> setting KEY_FLAG_TRUSTED_ONLY on a keyring. This will be replaced in
> a later patch with functions that look in the appropriate places for
> authoritative keys.
>
> Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
Rephrase restrict_link documentation comment inline below.
Reviewed-by: Mimi Zohar <zohar@xxxxxxxxxxxxxxxxxx>
> ---
>
> Documentation/security/keys.txt | 14 ++++++++++
> certs/blacklist.c | 2 +
> certs/system_keyring.c | 8 +++---
> fs/cifs/cifsacl.c | 2 +
> fs/nfs/nfs4idmap.c | 2 +
> include/linux/key.h | 48 ++++++++++++++++++++++++++++-------
> net/dns_resolver/dns_key.c | 2 +
> net/rxrpc/ar-key.c | 4 +--
> security/integrity/digsig.c | 7 ++---
> security/integrity/ima/ima_mok.c | 8 +++---
> security/keys/key.c | 43 ++++++++++++++++++++++++++-----
> security/keys/keyring.c | 52 +++++++++++++++++++++++++++++++++-----
> security/keys/persistent.c | 4 +--
> security/keys/process_keys.c | 16 +++++++-----
> security/keys/request_key.c | 4 +--
> security/keys/request_key_auth.c | 2 +
> 16 files changed, 165 insertions(+), 53 deletions(-)
>
> diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
> index 8c183873b2b7..3e2e958f2091 100644
> --- a/Documentation/security/keys.txt
> +++ b/Documentation/security/keys.txt
> @@ -999,6 +999,10 @@ 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 *),
> unsigned long flags,
> struct key *dest);
>
> @@ -1010,6 +1014,16 @@ 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 will be called to
> + vet all attempts to link keys into the keyring, though this can be
> + overridden by passing KEY_ALLOC_BYPASS_RESTRICTION to
> + key_create_or_update().
Please fix the first part of the sentence. Maybe add an example of
when it is appropriate to bypass the restriction - (eg. loading the
builtin keys).
> +
> + 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.
> +
>
> (*) To check the validity of a key, this function can be called:
>
> diff --git a/certs/blacklist.c b/certs/blacklist.c
> index 5f54baae3a32..7f769479c17b 100644
> --- a/certs/blacklist.c
> +++ b/certs/blacklist.c
> @@ -148,7 +148,7 @@ static int __init blacklist_init(void)
> KEY_USR_SEARCH,
> KEY_ALLOC_NOT_IN_QUOTA |
> KEY_FLAG_KEEP,
> - NULL);
> + NULL, NULL);
> if (IS_ERR(blacklist_keyring))
> panic("Can't allocate system blacklist keyring\n");
>
> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
> index dc18869ff680..417d65882870 100644
> --- a/certs/system_keyring.c
> +++ b/certs/system_keyring.c
> @@ -36,11 +36,10 @@ static __init int system_trusted_keyring_init(void)
> KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
> ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
> KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
> - KEY_ALLOC_NOT_IN_QUOTA, NULL);
> + KEY_ALLOC_NOT_IN_QUOTA,
> + keyring_restrict_trusted_only, NULL);
> if (IS_ERR(system_trusted_keyring))
> panic("Can't allocate system trusted keyring\n");
> -
> - set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags);
> return 0;
> }
>
> @@ -85,7 +84,8 @@ static __init int load_system_certificate_list(void)
> KEY_USR_VIEW | KEY_USR_READ),
> KEY_ALLOC_NOT_IN_QUOTA |
> KEY_ALLOC_TRUSTED |
> - KEY_ALLOC_BUILT_IN);
> + KEY_ALLOC_BUILT_IN |
> + KEY_ALLOC_BYPASS_RESTRICTION);
> if (IS_ERR(key)) {
> pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
> PTR_ERR(key));
> diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
> index 3f93125916bf..71e8a56e9479 100644
> --- a/fs/cifs/cifsacl.c
> +++ b/fs/cifs/cifsacl.c
> @@ -360,7 +360,7 @@ init_cifs_idmap(void)
> GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
> (KEY_POS_ALL & ~KEY_POS_SETATTR) |
> KEY_USR_VIEW | KEY_USR_READ,
> - KEY_ALLOC_NOT_IN_QUOTA, NULL);
> + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
> if (IS_ERR(keyring)) {
> ret = PTR_ERR(keyring);
> goto failed_put_cred;
> diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c
> index 5ba22c6b0ffa..c444285bb1b1 100644
> --- a/fs/nfs/nfs4idmap.c
> +++ b/fs/nfs/nfs4idmap.c
> @@ -201,7 +201,7 @@ int nfs_idmap_init(void)
> GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
> (KEY_POS_ALL & ~KEY_POS_SETATTR) |
> KEY_USR_VIEW | KEY_USR_READ,
> - KEY_ALLOC_NOT_IN_QUOTA, NULL);
> + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
> if (IS_ERR(keyring)) {
> ret = PTR_ERR(keyring);
> goto failed_put_cred;
> diff --git a/include/linux/key.h b/include/linux/key.h
> index 5f5b1129dc92..c331b8bed035 100644
> --- a/include/linux/key.h
> +++ b/include/linux/key.h
> @@ -174,10 +174,9 @@ struct key {
> #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */
> #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */
> #define KEY_FLAG_TRUSTED 8 /* set if key is trusted */
> -#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */
> -#define KEY_FLAG_BUILTIN 10 /* set if key is builtin */
> -#define KEY_FLAG_ROOT_CAN_INVAL 11 /* set if key can be invalidated by root without permission */
> -#define KEY_FLAG_KEEP 12 /* set if key should not be removed */
> +#define KEY_FLAG_BUILTIN 9 /* set if key is built in to the kernel */
> +#define KEY_FLAG_ROOT_CAN_INVAL 10 /* set if key can be invalidated by root without permission */
> +#define KEY_FLAG_KEEP 11 /* set if key should not be removed */
>
> /* the key type and key description string
> * - the desc is used to match a key against search criteria
> @@ -205,6 +204,21 @@ struct key {
> };
> int reject_error;
> };
> +
> + /* 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
> + * keyring is open to any addition. It is ignored for non-keyring
> + * keys.
> + *
> + * This is intended for use with rings of trusted keys whereby addition
> + * to the keyring needs to be controlled. KEY_ALLOC_BYPASS_RESTRICTION
> + * overrides this, allowing the kernel to add extra keys without
> + * restriction.
> + */
> + int (*restrict_link)(struct key *keyring,
> + const struct key_type *type,
> + unsigned long flags,
> + const union key_payload *payload);
> };
>
> extern struct key *key_alloc(struct key_type *type,
> @@ -212,14 +226,19 @@ extern struct key *key_alloc(struct key_type *type,
> kuid_t uid, kgid_t gid,
> const struct cred *cred,
> key_perm_t perm,
> - unsigned long flags);
> + unsigned long flags,
> + int (*restrict_link)(struct key *,
> + const struct key_type *,
> + unsigned long,
> + const union key_payload *));
>
>
> -#define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */
> -#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */
> -#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */
> -#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */
> -#define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */
> +#define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */
> +#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */
> +#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */
> +#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */
> +#define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */
> +#define KEY_ALLOC_BYPASS_RESTRICTION 0x0010 /* Override the check on restricted keyrings */
>
> extern void key_revoke(struct key *key);
> extern void key_invalidate(struct key *key);
> @@ -288,8 +307,17 @@ 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 *,
> + unsigned long,
> + const union key_payload *),
> struct key *dest);
>
> +extern int keyring_restrict_trusted_only(struct key *keyring,
> + const struct key_type *type,
> + unsigned long,
> + const union key_payload *payload);
> +
> extern int keyring_clear(struct key *keyring);
>
> extern key_ref_t keyring_search(key_ref_t keyring,
> diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
> index c79b85eb4d4c..8737412c7b27 100644
> --- a/net/dns_resolver/dns_key.c
> +++ b/net/dns_resolver/dns_key.c
> @@ -281,7 +281,7 @@ static int __init init_dns_resolver(void)
> GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
> (KEY_POS_ALL & ~KEY_POS_SETATTR) |
> KEY_USR_VIEW | KEY_USR_READ,
> - KEY_ALLOC_NOT_IN_QUOTA, NULL);
> + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
> if (IS_ERR(keyring)) {
> ret = PTR_ERR(keyring);
> goto failed_put_cred;
> diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
> index 3f6571651d32..b8e87a16c544 100644
> --- a/net/rxrpc/ar-key.c
> +++ b/net/rxrpc/ar-key.c
> @@ -965,7 +965,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
>
> key = key_alloc(&key_type_rxrpc, "x",
> GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0,
> - KEY_ALLOC_NOT_IN_QUOTA);
> + KEY_ALLOC_NOT_IN_QUOTA, NULL);
> if (IS_ERR(key)) {
> _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
> return -ENOMEM;
> @@ -1012,7 +1012,7 @@ struct key *rxrpc_get_null_key(const char *keyname)
>
> key = key_alloc(&key_type_rxrpc, keyname,
> GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
> - KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA);
> + KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, NULL);
> if (IS_ERR(key))
> return key;
>
> diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
> index 8ef15118cc78..659566c2200b 100644
> --- a/security/integrity/digsig.c
> +++ b/security/integrity/digsig.c
> @@ -83,10 +83,9 @@ int __init integrity_init_keyring(const unsigned int id)
> ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
> KEY_USR_VIEW | KEY_USR_READ |
> KEY_USR_WRITE | KEY_USR_SEARCH),
> - KEY_ALLOC_NOT_IN_QUOTA, NULL);
> - if (!IS_ERR(keyring[id]))
> - set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags);
> - else {
> + KEY_ALLOC_NOT_IN_QUOTA,
> + NULL, NULL);
> + if (IS_ERR(keyring[id])) {
> err = PTR_ERR(keyring[id]);
> pr_info("Can't allocate %s keyring (%d)\n",
> keyring_name[id], err);
> diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c
> index 676885e4320e..ef91248cb934 100644
> --- a/security/integrity/ima/ima_mok.c
> +++ b/security/integrity/ima/ima_mok.c
> @@ -35,20 +35,20 @@ __init int ima_mok_init(void)
> (KEY_POS_ALL & ~KEY_POS_SETATTR) |
> KEY_USR_VIEW | KEY_USR_READ |
> KEY_USR_WRITE | KEY_USR_SEARCH,
> - KEY_ALLOC_NOT_IN_QUOTA, NULL);
> + KEY_ALLOC_NOT_IN_QUOTA,
> + keyring_restrict_trusted_only, NULL);
>
> ima_blacklist_keyring = keyring_alloc(".ima_blacklist",
> KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
> (KEY_POS_ALL & ~KEY_POS_SETATTR) |
> KEY_USR_VIEW | KEY_USR_READ |
> KEY_USR_WRITE | KEY_USR_SEARCH,
> - KEY_ALLOC_NOT_IN_QUOTA, NULL);
> + KEY_ALLOC_NOT_IN_QUOTA,
> + keyring_restrict_trusted_only, NULL);
>
> if (IS_ERR(ima_mok_keyring) || IS_ERR(ima_blacklist_keyring))
> panic("Can't allocate IMA MOK or blacklist keyrings.");
> - set_bit(KEY_FLAG_TRUSTED_ONLY, &ima_mok_keyring->flags);
>
> - set_bit(KEY_FLAG_TRUSTED_ONLY, &ima_blacklist_keyring->flags);
> set_bit(KEY_FLAG_KEEP, &ima_blacklist_keyring->flags);
> return 0;
> }
> diff --git a/security/keys/key.c b/security/keys/key.c
> index 48dbfa543bcb..23b271b1834d 100644
> --- a/security/keys/key.c
> +++ b/security/keys/key.c
> @@ -201,6 +201,7 @@ serial_exists:
> * @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.
> *
> * 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
> @@ -223,7 +224,11 @@ serial_exists:
> */
> 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_perm_t perm, unsigned long flags,
> + int (*restrict_link)(struct key *,
> + const struct key_type *,
> + unsigned long,
> + const union key_payload *))
> {
> struct key_user *user = NULL;
> struct key *key;
> @@ -291,6 +296,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
> key->uid = uid;
> key->gid = gid;
> key->perm = perm;
> + key->restrict_link = restrict_link;
>
> if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
> key->flags |= 1 << KEY_FLAG_IN_QUOTA;
> @@ -495,6 +501,12 @@ int key_instantiate_and_link(struct key *key,
> }
>
> if (keyring) {
> + if (keyring->restrict_link) {
> + ret = keyring->restrict_link(keyring, key->type,
> + key->flags, &prep.payload);
> + if (ret < 0)
> + goto error;
> + }
> ret = __key_link_begin(keyring, &key->index_key, &edit);
> if (ret < 0)
> goto error;
> @@ -550,8 +562,12 @@ int key_reject_and_link(struct key *key,
> awaken = 0;
> ret = -EBUSY;
>
> - if (keyring)
> + if (keyring) {
> + if (keyring->restrict_link)
> + return -EPERM;
> +
> link_ret = __key_link_begin(keyring, &key->index_key, &edit);
> + }
>
> mutex_lock(&key_construction_mutex);
>
> @@ -792,6 +808,10 @@ 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 *,
> + unsigned long,
> + const union key_payload *) = NULL;
>
> /* look up the key type to see if it's one of the registered kernel
> * types */
> @@ -810,6 +830,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
>
> key_check(keyring);
>
> + key_ref = ERR_PTR(-EPERM);
> + if (!(flags & KEY_ALLOC_BYPASS_RESTRICTION))
> + restrict_link = keyring->restrict_link;
> +
> key_ref = ERR_PTR(-ENOTDIR);
> if (keyring->type != &key_type_keyring)
> goto error_put_type;
> @@ -834,10 +858,15 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
> }
> index_key.desc_len = strlen(index_key.description);
>
> - key_ref = ERR_PTR(-EPERM);
> - if (!prep.trusted && test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags))
> - goto error_free_prep;
> - flags |= prep.trusted ? KEY_ALLOC_TRUSTED : 0;
> + if (restrict_link) {
> + unsigned long kflags = prep.trusted ? KEY_FLAG_TRUSTED : 0;
> + ret = restrict_link(keyring,
> + index_key.type, kflags, &prep.payload);
> + if (ret < 0) {
> + key_ref = ERR_PTR(ret);
> + goto error_free_prep;
> + }
> + }
>
> ret = __key_link_begin(keyring, &index_key, &edit);
> if (ret < 0) {
> @@ -878,7 +907,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
>
> /* allocate a new key */
> key = key_alloc(index_key.type, index_key.description,
> - cred->fsuid, cred->fsgid, cred, perm, flags);
> + cred->fsuid, cred->fsgid, cred, perm, flags, NULL);
> if (IS_ERR(key)) {
> key_ref = ERR_CAST(key);
> goto error_link_end;
> diff --git a/security/keys/keyring.c b/security/keys/keyring.c
> index f931ccfeefb0..ea023ca6d217 100644
> --- a/security/keys/keyring.c
> +++ b/security/keys/keyring.c
> @@ -491,13 +491,18 @@ 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, struct key *dest)
> + unsigned long flags,
> + int (*restrict_link)(struct key *,
> + const struct key_type *,
> + unsigned long,
> + const union key_payload *),
> + struct key *dest)
> {
> struct key *keyring;
> int ret;
>
> keyring = key_alloc(&key_type_keyring, description,
> - uid, gid, cred, perm, flags);
> + uid, gid, cred, perm, flags, restrict_link);
> if (!IS_ERR(keyring)) {
> ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
> if (ret < 0) {
> @@ -510,6 +515,30 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
> }
> EXPORT_SYMBOL(keyring_alloc);
>
> +/**
> + * keyring_restrict_trusted_only - Restrict additions to a keyring to trusted keys only
> + * @keyring: The keyring being added to.
> + * @type: The type of key being added.
> + * @flags: The key flags.
> + * @payload: The payload of the key intended to be added.
> + *
> + * Reject the addition of any links to a keyring that point to keys that aren't
> + * marked as being trusted. It can be overridden by 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().
> + */
> +int keyring_restrict_trusted_only(struct key *keyring,
> + const struct key_type *type,
> + unsigned long flags,
> + const union key_payload *payload)
> +{
> +
> + return flags & KEY_FLAG_TRUSTED ? 0 : -EPERM;
> +}
> +
> /*
> * By default, we keys found by getting an exact match on their descriptions.
> */
> @@ -1191,6 +1220,17 @@ void __key_link_end(struct key *keyring,
> up_write(&keyring->sem);
> }
>
> +/*
> + * Check addition of keys to restricted keyrings.
> + */
> +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->flags, &key->payload);
> +}
> +
> /**
> * key_link - Link a key to a keyring
> * @keyring: The keyring to make the link in.
> @@ -1221,14 +1261,12 @@ int key_link(struct key *keyring, struct key *key)
> key_check(keyring);
> key_check(key);
>
> - if (test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags) &&
> - !test_bit(KEY_FLAG_TRUSTED, &key->flags))
> - return -EPERM;
> -
> ret = __key_link_begin(keyring, &key->index_key, &edit);
> if (ret == 0) {
> kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage));
> - ret = __key_link_check_live_key(keyring, key);
> + ret = __key_link_check_restriction(keyring, key);
> + if (ret == 0)
> + ret = __key_link_check_live_key(keyring, key);
> if (ret == 0)
> __key_link(key, &edit);
> __key_link_end(keyring, &key->index_key, edit);
> diff --git a/security/keys/persistent.c b/security/keys/persistent.c
> index c9fae5ea89fe..2ef45b319dd9 100644
> --- a/security/keys/persistent.c
> +++ b/security/keys/persistent.c
> @@ -26,7 +26,7 @@ static int key_create_persistent_register(struct user_namespace *ns)
> current_cred(),
> ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
> KEY_USR_VIEW | KEY_USR_READ),
> - KEY_ALLOC_NOT_IN_QUOTA, NULL);
> + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
> if (IS_ERR(reg))
> return PTR_ERR(reg);
>
> @@ -60,7 +60,7 @@ static key_ref_t key_create_persistent(struct user_namespace *ns, kuid_t uid,
> uid, INVALID_GID, current_cred(),
> ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
> KEY_USR_VIEW | KEY_USR_READ),
> - KEY_ALLOC_NOT_IN_QUOTA,
> + KEY_ALLOC_NOT_IN_QUOTA, NULL,
> ns->persistent_keyring_register);
> if (IS_ERR(persistent))
> return ERR_CAST(persistent);
> diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
> index a3f85d2a00bb..9bb6bb5fd845 100644
> --- a/security/keys/process_keys.c
> +++ b/security/keys/process_keys.c
> @@ -76,7 +76,8 @@ int install_user_keyrings(void)
> if (IS_ERR(uid_keyring)) {
> uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID,
> cred, user_keyring_perm,
> - KEY_ALLOC_IN_QUOTA, NULL);
> + KEY_ALLOC_IN_QUOTA,
> + NULL, NULL);
> if (IS_ERR(uid_keyring)) {
> ret = PTR_ERR(uid_keyring);
> goto error;
> @@ -92,7 +93,8 @@ int install_user_keyrings(void)
> session_keyring =
> keyring_alloc(buf, user->uid, INVALID_GID,
> cred, user_keyring_perm,
> - KEY_ALLOC_IN_QUOTA, NULL);
> + KEY_ALLOC_IN_QUOTA,
> + NULL, NULL);
> if (IS_ERR(session_keyring)) {
> ret = PTR_ERR(session_keyring);
> goto error_release;
> @@ -134,7 +136,8 @@ int install_thread_keyring_to_cred(struct cred *new)
>
> keyring = keyring_alloc("_tid", new->uid, new->gid, new,
> KEY_POS_ALL | KEY_USR_VIEW,
> - KEY_ALLOC_QUOTA_OVERRUN, NULL);
> + KEY_ALLOC_QUOTA_OVERRUN,
> + NULL, NULL);
> if (IS_ERR(keyring))
> return PTR_ERR(keyring);
>
> @@ -180,7 +183,8 @@ int install_process_keyring_to_cred(struct cred *new)
>
> keyring = keyring_alloc("_pid", new->uid, new->gid, new,
> KEY_POS_ALL | KEY_USR_VIEW,
> - KEY_ALLOC_QUOTA_OVERRUN, NULL);
> + KEY_ALLOC_QUOTA_OVERRUN,
> + NULL, NULL);
> if (IS_ERR(keyring))
> return PTR_ERR(keyring);
>
> @@ -231,7 +235,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
>
> keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred,
> KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
> - flags, NULL);
> + flags, NULL, NULL);
> if (IS_ERR(keyring))
> return PTR_ERR(keyring);
> } else {
> @@ -785,7 +789,7 @@ long join_session_keyring(const char *name)
> keyring = keyring_alloc(
> name, old->uid, old->gid, old,
> KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK,
> - KEY_ALLOC_IN_QUOTA, NULL);
> + KEY_ALLOC_IN_QUOTA, NULL, NULL);
> if (IS_ERR(keyring)) {
> ret = PTR_ERR(keyring);
> goto error2;
> diff --git a/security/keys/request_key.c b/security/keys/request_key.c
> index c7a117c9a8f3..a29e3554751e 100644
> --- a/security/keys/request_key.c
> +++ b/security/keys/request_key.c
> @@ -116,7 +116,7 @@ static int call_sbin_request_key(struct key_construction *cons,
> cred = get_current_cred();
> keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred,
> KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
> - KEY_ALLOC_QUOTA_OVERRUN, NULL);
> + KEY_ALLOC_QUOTA_OVERRUN, NULL, NULL);
> put_cred(cred);
> if (IS_ERR(keyring)) {
> ret = PTR_ERR(keyring);
> @@ -355,7 +355,7 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
>
> key = key_alloc(ctx->index_key.type, ctx->index_key.description,
> ctx->cred->fsuid, ctx->cred->fsgid, ctx->cred,
> - perm, flags);
> + perm, flags, NULL);
> if (IS_ERR(key))
> goto alloc_failed;
>
> diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
> index 4f0f112fe276..9db8b4a82787 100644
> --- a/security/keys/request_key_auth.c
> +++ b/security/keys/request_key_auth.c
> @@ -202,7 +202,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
> authkey = key_alloc(&key_type_request_key_auth, desc,
> cred->fsuid, cred->fsgid, cred,
> KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
> - KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
> + KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA, NULL);
> if (IS_ERR(authkey)) {
> ret = PTR_ERR(authkey);
> goto error_alloc;
>