Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b6aa412 authored by Mat Martineau's avatar Mat Martineau
Browse files

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: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
parent e9cc0f68
Loading
Loading
Loading
Loading
+12 −9
Original line number Diff line number Diff line
@@ -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,14 +1044,17 @@ 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
    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.
    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 a key pointer
    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 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 type, the payload of the key being added, and data to be
+20 −1
Original line number Diff line number Diff line
@@ -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");
+4 −4
Original line number Diff line number Diff line
@@ -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,
+8 −1
Original line number Diff line number Diff line
@@ -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)
{
	const struct cred *cred = current_cred();
	struct key_restriction *restriction;
	int err = 0;

	if (!init_keyring)
		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),
				    KGIDT_INIT(0), cred,
				    ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
				     KEY_USR_VIEW | KEY_USR_READ |
				     KEY_USR_WRITE | KEY_USR_SEARCH),
				    KEY_ALLOC_NOT_IN_QUOTA,
				    restrict_link_to_ima, NULL);
				    restriction, NULL);
	if (IS_ERR(keyring[id])) {
		err = PTR_ERR(keyring[id]);
		pr_info("Can't allocate %s keyring (%d)\n",
+10 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/cred.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <keys/system_keyring.h>


@@ -27,15 +28,23 @@ struct key *ima_blacklist_keyring;
 */
__init int ima_mok_init(void)
{
	struct key_restriction *restriction;

	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",
				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,
				restrict_link_by_builtin_trusted, NULL);
				restriction, NULL);

	if (IS_ERR(ima_blacklist_keyring))
		panic("Can't allocate IMA blacklist keyring.");
Loading