KEYS: Use structure to capture key restriction function and data
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 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>
This commit is contained in:
parent
e9cc0f689a
commit
2b6aa412ff
|
@ -1032,7 +1032,7 @@ payload contents" for more information.
|
||||||
struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
|
struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
|
||||||
const struct cred *cred,
|
const struct cred *cred,
|
||||||
key_perm_t perm,
|
key_perm_t perm,
|
||||||
key_restrict_link_func_t restrict_link,
|
struct key_restriction *restrict_link,
|
||||||
unsigned long flags,
|
unsigned long flags,
|
||||||
struct key *dest);
|
struct key *dest);
|
||||||
|
|
||||||
|
@ -1044,14 +1044,17 @@ payload contents" for more information.
|
||||||
KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted
|
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.
|
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
|
If restrict_link is not NULL, it should point to a structure that contains
|
||||||
called each time an attempt is made to link a key into the new keyring.
|
the function that will be called each time an attempt is made to link a
|
||||||
This function is called to check whether a key may be added into the keying
|
key into the new keyring. The structure may also contain a key pointer
|
||||||
or not. Callers of key_create_or_update() within the kernel can pass
|
and an associated key type. The function is called to check whether a key
|
||||||
KEY_ALLOC_BYPASS_RESTRICTION to suppress the check. An example of using
|
may be added into the keyring or not. The key type is used by the garbage
|
||||||
this is to manage rings of cryptographic keys that are set up when the
|
collector to clean up function or data pointers in this structure if the
|
||||||
kernel boots where userspace is also permitted to add keys - provided they
|
given key type is unregistered. Callers of key_create_or_update() within
|
||||||
can be verified by a key the kernel already has.
|
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 can be verified by a key the kernel already has.
|
||||||
|
|
||||||
When called, the restriction function will be passed the keyring being
|
When called, the restriction function will be passed the keyring being
|
||||||
added to, the key type, the payload of the key being added, and data to be
|
added to, the key type, the payload of the key being added, and data to be
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
#include <keys/asymmetric-type.h>
|
#include <keys/asymmetric-type.h>
|
||||||
#include <keys/system_keyring.h>
|
#include <keys/system_keyring.h>
|
||||||
#include <crypto/pkcs7.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,
|
return restrict_link_by_signature(dest_keyring, type, payload,
|
||||||
secondary_trusted_keys);
|
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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -95,7 +114,7 @@ static __init int system_trusted_keyring_init(void)
|
||||||
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
|
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
|
||||||
KEY_USR_WRITE),
|
KEY_USR_WRITE),
|
||||||
KEY_ALLOC_NOT_IN_QUOTA,
|
KEY_ALLOC_NOT_IN_QUOTA,
|
||||||
restrict_link_by_builtin_and_secondary_trusted,
|
get_builtin_and_secondary_restriction(),
|
||||||
NULL);
|
NULL);
|
||||||
if (IS_ERR(secondary_trusted_keys))
|
if (IS_ERR(secondary_trusted_keys))
|
||||||
panic("Can't allocate secondary trusted keyring\n");
|
panic("Can't allocate secondary trusted keyring\n");
|
||||||
|
|
|
@ -217,7 +217,7 @@ struct key {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This is set on a keyring to restrict the addition of a link to a 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
|
* keyring is open to any addition. It is ignored for non-keyring
|
||||||
* keys.
|
* keys.
|
||||||
*
|
*
|
||||||
|
@ -226,7 +226,7 @@ struct key {
|
||||||
* overrides this, allowing the kernel to add extra keys without
|
* overrides this, allowing the kernel to add extra keys without
|
||||||
* restriction.
|
* restriction.
|
||||||
*/
|
*/
|
||||||
key_restrict_link_func_t restrict_link;
|
struct key_restriction *restrict_link;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct key *key_alloc(struct key_type *type,
|
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,
|
const struct cred *cred,
|
||||||
key_perm_t perm,
|
key_perm_t perm,
|
||||||
unsigned long flags,
|
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 */
|
#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,
|
const struct cred *cred,
|
||||||
key_perm_t perm,
|
key_perm_t perm,
|
||||||
unsigned long flags,
|
unsigned long flags,
|
||||||
key_restrict_link_func_t restrict_link,
|
struct key_restriction *restrict_link,
|
||||||
struct key *dest);
|
struct key *dest);
|
||||||
|
|
||||||
extern int restrict_link_reject(struct key *keyring,
|
extern int restrict_link_reject(struct key *keyring,
|
||||||
|
|
|
@ -81,18 +81,25 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
|
||||||
int __init integrity_init_keyring(const unsigned int id)
|
int __init integrity_init_keyring(const unsigned int id)
|
||||||
{
|
{
|
||||||
const struct cred *cred = current_cred();
|
const struct cred *cred = current_cred();
|
||||||
|
struct key_restriction *restriction;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!init_keyring)
|
if (!init_keyring)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
|
||||||
|
if (!restriction)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
restriction->check = restrict_link_to_ima;
|
||||||
|
|
||||||
keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
|
keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
|
||||||
KGIDT_INIT(0), cred,
|
KGIDT_INIT(0), cred,
|
||||||
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
|
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
|
||||||
KEY_USR_VIEW | KEY_USR_READ |
|
KEY_USR_VIEW | KEY_USR_READ |
|
||||||
KEY_USR_WRITE | KEY_USR_SEARCH),
|
KEY_USR_WRITE | KEY_USR_SEARCH),
|
||||||
KEY_ALLOC_NOT_IN_QUOTA,
|
KEY_ALLOC_NOT_IN_QUOTA,
|
||||||
restrict_link_to_ima, NULL);
|
restriction, NULL);
|
||||||
if (IS_ERR(keyring[id])) {
|
if (IS_ERR(keyring[id])) {
|
||||||
err = PTR_ERR(keyring[id]);
|
err = PTR_ERR(keyring[id]);
|
||||||
pr_info("Can't allocate %s keyring (%d)\n",
|
pr_info("Can't allocate %s keyring (%d)\n",
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
#include <keys/system_keyring.h>
|
#include <keys/system_keyring.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,15 +28,23 @@ struct key *ima_blacklist_keyring;
|
||||||
*/
|
*/
|
||||||
__init int ima_mok_init(void)
|
__init int ima_mok_init(void)
|
||||||
{
|
{
|
||||||
|
struct key_restriction *restriction;
|
||||||
|
|
||||||
pr_notice("Allocating IMA blacklist keyring.\n");
|
pr_notice("Allocating IMA blacklist keyring.\n");
|
||||||
|
|
||||||
|
restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
|
||||||
|
if (!restriction)
|
||||||
|
panic("Can't allocate IMA blacklist restriction.");
|
||||||
|
|
||||||
|
restriction->check = restrict_link_by_builtin_trusted;
|
||||||
|
|
||||||
ima_blacklist_keyring = keyring_alloc(".ima_blacklist",
|
ima_blacklist_keyring = keyring_alloc(".ima_blacklist",
|
||||||
KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
|
KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
|
||||||
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
|
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
|
||||||
KEY_USR_VIEW | KEY_USR_READ |
|
KEY_USR_VIEW | KEY_USR_READ |
|
||||||
KEY_USR_WRITE | KEY_USR_SEARCH,
|
KEY_USR_WRITE | KEY_USR_SEARCH,
|
||||||
KEY_ALLOC_NOT_IN_QUOTA,
|
KEY_ALLOC_NOT_IN_QUOTA,
|
||||||
restrict_link_by_builtin_trusted, NULL);
|
restriction, NULL);
|
||||||
|
|
||||||
if (IS_ERR(ima_blacklist_keyring))
|
if (IS_ERR(ima_blacklist_keyring))
|
||||||
panic("Can't allocate IMA blacklist keyring.");
|
panic("Can't allocate IMA blacklist keyring.");
|
||||||
|
|
|
@ -229,6 +229,9 @@ continue_scanning:
|
||||||
set_bit(KEY_FLAG_DEAD, &key->flags);
|
set_bit(KEY_FLAG_DEAD, &key->flags);
|
||||||
key->perm = 0;
|
key->perm = 0;
|
||||||
goto skip_dead_key;
|
goto skip_dead_key;
|
||||||
|
} else if (key->type == &key_type_keyring &&
|
||||||
|
key->restrict_link) {
|
||||||
|
goto found_restricted_keyring;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +337,14 @@ found_unreferenced_key:
|
||||||
gc_state |= KEY_GC_REAP_AGAIN;
|
gc_state |= KEY_GC_REAP_AGAIN;
|
||||||
goto maybe_resched;
|
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
|
/* 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
|
* 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
|
* have to wait for the old payload to be destroyed by RCU before we
|
||||||
|
|
|
@ -168,6 +168,8 @@ extern void key_change_session_keyring(struct callback_head *twork);
|
||||||
extern struct work_struct key_gc_work;
|
extern struct work_struct key_gc_work;
|
||||||
extern unsigned key_gc_delay;
|
extern unsigned key_gc_delay;
|
||||||
extern void keyring_gc(struct key *keyring, time_t limit);
|
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(time_t gc_at);
|
||||||
extern void key_schedule_gc_links(void);
|
extern void key_schedule_gc_links(void);
|
||||||
extern void key_gc_keytype(struct key_type *ktype);
|
extern void key_gc_keytype(struct key_type *ktype);
|
||||||
|
|
|
@ -201,12 +201,15 @@ serial_exists:
|
||||||
* @cred: The credentials specifying UID namespace.
|
* @cred: The credentials specifying UID namespace.
|
||||||
* @perm: The permissions mask of the new key.
|
* @perm: The permissions mask of the new key.
|
||||||
* @flags: Flags specifying quota properties.
|
* @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
|
* 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
|
* returned in an uninstantiated state and the caller needs to instantiate the
|
||||||
* key before returning.
|
* 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 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
|
* the user's key data quota has the default for the key type reserved. The
|
||||||
* instantiation function should amend this as necessary. If insufficient
|
* instantiation function should amend this as necessary. If insufficient
|
||||||
|
@ -225,7 +228,7 @@ serial_exists:
|
||||||
struct key *key_alloc(struct key_type *type, const char *desc,
|
struct key *key_alloc(struct key_type *type, const char *desc,
|
||||||
kuid_t uid, kgid_t gid, const struct cred *cred,
|
kuid_t uid, kgid_t gid, const struct cred *cred,
|
||||||
key_perm_t perm, unsigned long flags,
|
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_user *user = NULL;
|
||||||
struct key *key;
|
struct key *key;
|
||||||
|
@ -497,9 +500,11 @@ int key_instantiate_and_link(struct key *key,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyring) {
|
if (keyring) {
|
||||||
if (keyring->restrict_link) {
|
if (keyring->restrict_link && keyring->restrict_link->check) {
|
||||||
ret = keyring->restrict_link(keyring, key->type,
|
struct key_restriction *keyres = keyring->restrict_link;
|
||||||
&prep.payload, NULL);
|
|
||||||
|
ret = keyres->check(keyring, key->type, &prep.payload,
|
||||||
|
keyres->key);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -804,7 +809,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
|
||||||
struct key *keyring, *key = NULL;
|
struct key *keyring, *key = NULL;
|
||||||
key_ref_t key_ref;
|
key_ref_t key_ref;
|
||||||
int ret;
|
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
|
/* look up the key type to see if it's one of the registered kernel
|
||||||
* types */
|
* 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);
|
index_key.desc_len = strlen(index_key.description);
|
||||||
|
|
||||||
if (restrict_link) {
|
if (restrict_link && restrict_link->check) {
|
||||||
ret = restrict_link(keyring, index_key.type, &prep.payload,
|
ret = restrict_link->check(keyring, index_key.type,
|
||||||
NULL);
|
&prep.payload, restrict_link->key);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
key_ref = ERR_PTR(ret);
|
key_ref = ERR_PTR(ret);
|
||||||
goto error_free_prep;
|
goto error_free_prep;
|
||||||
|
|
|
@ -394,6 +394,13 @@ static void keyring_destroy(struct key *keyring)
|
||||||
write_unlock(&keyring_name_lock);
|
write_unlock(&keyring_name_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (keyring->restrict_link) {
|
||||||
|
struct key_restriction *keyres = keyring->restrict_link;
|
||||||
|
|
||||||
|
key_put(keyres->key);
|
||||||
|
kfree(keyres);
|
||||||
|
}
|
||||||
|
|
||||||
assoc_array_destroy(&keyring->keys, &keyring_assoc_array_ops);
|
assoc_array_destroy(&keyring->keys, &keyring_assoc_array_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,7 +499,7 @@ static long keyring_read(const struct key *keyring,
|
||||||
struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
|
struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
|
||||||
const struct cred *cred, key_perm_t perm,
|
const struct cred *cred, key_perm_t perm,
|
||||||
unsigned long flags,
|
unsigned long flags,
|
||||||
key_restrict_link_func_t restrict_link,
|
struct key_restriction *restrict_link,
|
||||||
struct key *dest)
|
struct key *dest)
|
||||||
{
|
{
|
||||||
struct key *keyring;
|
struct key *keyring;
|
||||||
|
@ -523,8 +530,8 @@ EXPORT_SYMBOL(keyring_alloc);
|
||||||
* passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when
|
* passing KEY_ALLOC_BYPASS_RESTRICTION to key_instantiate_and_link() when
|
||||||
* adding a key to a keyring.
|
* adding a key to a keyring.
|
||||||
*
|
*
|
||||||
* This is meant to be passed as the restrict_link parameter to
|
* This is meant to be stored in a key_restriction structure which is passed
|
||||||
* keyring_alloc().
|
* in the restrict_link parameter to keyring_alloc().
|
||||||
*/
|
*/
|
||||||
int restrict_link_reject(struct key *keyring,
|
int restrict_link_reject(struct key *keyring,
|
||||||
const struct key_type *type,
|
const struct key_type *type,
|
||||||
|
@ -1220,9 +1227,10 @@ void __key_link_end(struct key *keyring,
|
||||||
*/
|
*/
|
||||||
static int __key_link_check_restriction(struct key *keyring, struct key *key)
|
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 0;
|
||||||
return keyring->restrict_link(keyring, key->type, &key->payload, NULL);
|
return keyring->restrict_link->check(keyring, key->type, &key->payload,
|
||||||
|
keyring->restrict_link->key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1426,3 +1434,53 @@ do_gc:
|
||||||
up_write(&keyring->sem);
|
up_write(&keyring->sem);
|
||||||
kleave(" [gc]");
|
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;
|
||||||
|
|
||||||
|
key_put(keyres->key);
|
||||||
|
keyres->key = NULL;
|
||||||
|
keyres->keytype = NULL;
|
||||||
|
|
||||||
|
up_write(&keyring->sem);
|
||||||
|
|
||||||
|
kleave(" [restriction gc]");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue