Commit 6c1976ad authored by Thomas Weißschuh's avatar Thomas Weißschuh Committed by Jarkko Sakkinen
Browse files

KEYS: Add new function key_create()



key_create() works like key_create_or_update() but does not allow
updating an existing key, instead returning ERR_PTR(-EEXIST).

key_create() will be used by the blacklist keyring which should not
create duplicate entries or update existing entries.
Instead a dedicated message with appropriate severity will be logged.

Signed-off-by: default avatarThomas Weißschuh <linux@weissschuh.net>
Signed-off-by: default avatarJarkko Sakkinen <jarkko@kernel.org>
parent 06b53b02
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -386,6 +386,14 @@ extern int wait_for_key_construction(struct key *key, bool intr);

extern int key_validate(const struct key *key);

extern key_ref_t key_create(key_ref_t keyring,
			    const char *type,
			    const char *description,
			    const void *payload,
			    size_t plen,
			    key_perm_t perm,
			    unsigned long flags);

extern key_ref_t key_create_or_update(key_ref_t keyring,
				      const char *type,
				      const char *description,
+100 −37
Original line number Diff line number Diff line
@@ -788,38 +788,18 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
	goto out;
}

/**
 * key_create_or_update - Update or create and instantiate a key.
 * @keyring_ref: A pointer to the destination keyring with possession flag.
 * @type: The type of key.
 * @description: The searchable description for the key.
 * @payload: The data to use to instantiate or update the key.
 * @plen: The length of @payload.
 * @perm: The permissions mask for a new key.
 * @flags: The quota flags for a new key.
 *
 * Search the destination keyring for a key of the same description and if one
 * is found, update it, otherwise create and instantiate a new one and create a
 * link to it from that keyring.
 *
 * If perm is KEY_PERM_UNDEF then an appropriate key permissions mask will be
 * concocted.
 *
 * Returns a pointer to the new key if successful, -ENODEV if the key type
 * wasn't available, -ENOTDIR if the keyring wasn't a keyring, -EACCES if the
 * caller isn't permitted to modify the keyring or the LSM did not permit
 * creation of the key.
 *
 * On success, the possession flag from the keyring ref will be tacked on to
 * the key ref before it is returned.
/*
 * Create or potentially update a key. The combined logic behind
 * key_create_or_update() and key_create()
 */
key_ref_t key_create_or_update(key_ref_t keyring_ref,
static key_ref_t __key_create_or_update(key_ref_t keyring_ref,
					const char *type,
					const char *description,
					const void *payload,
					size_t plen,
					key_perm_t perm,
			       unsigned long flags)
					unsigned long flags,
					bool allow_update)
{
	struct keyring_index_key index_key = {
		.description	= description,
@@ -906,15 +886,24 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
		goto error_link_end;
	}

	/* if it's possible to update this type of key, search for an existing
	 * key of the same type and description in the destination keyring and
	 * update that instead if possible
	/* if it's requested and possible to update this type of key, search
	 * for an existing key of the same type and description in the
	 * destination keyring and update that instead if possible
	 */
	if (allow_update) {
		if (index_key.type->update) {
			key_ref = find_key_to_update(keyring_ref, &index_key);
			if (key_ref)
				goto found_matching_key;
		}
	} else {
		key_ref = find_key_to_update(keyring_ref, &index_key);
		if (key_ref) {
			key_ref_put(key_ref);
			key_ref = ERR_PTR(-EEXIST);
			goto error_link_end;
		}
	}

	/* if the client doesn't provide, decide on the permissions we want */
	if (perm == KEY_PERM_UNDEF) {
@@ -985,8 +974,82 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,

	goto error_free_prep;
}

/**
 * key_create_or_update - Update or create and instantiate a key.
 * @keyring_ref: A pointer to the destination keyring with possession flag.
 * @type: The type of key.
 * @description: The searchable description for the key.
 * @payload: The data to use to instantiate or update the key.
 * @plen: The length of @payload.
 * @perm: The permissions mask for a new key.
 * @flags: The quota flags for a new key.
 *
 * Search the destination keyring for a key of the same description and if one
 * is found, update it, otherwise create and instantiate a new one and create a
 * link to it from that keyring.
 *
 * If perm is KEY_PERM_UNDEF then an appropriate key permissions mask will be
 * concocted.
 *
 * Returns a pointer to the new key if successful, -ENODEV if the key type
 * wasn't available, -ENOTDIR if the keyring wasn't a keyring, -EACCES if the
 * caller isn't permitted to modify the keyring or the LSM did not permit
 * creation of the key.
 *
 * On success, the possession flag from the keyring ref will be tacked on to
 * the key ref before it is returned.
 */
key_ref_t key_create_or_update(key_ref_t keyring_ref,
			       const char *type,
			       const char *description,
			       const void *payload,
			       size_t plen,
			       key_perm_t perm,
			       unsigned long flags)
{
	return __key_create_or_update(keyring_ref, type, description, payload,
				      plen, perm, flags, true);
}
EXPORT_SYMBOL(key_create_or_update);

/**
 * key_create - Create and instantiate a key.
 * @keyring_ref: A pointer to the destination keyring with possession flag.
 * @type: The type of key.
 * @description: The searchable description for the key.
 * @payload: The data to use to instantiate or update the key.
 * @plen: The length of @payload.
 * @perm: The permissions mask for a new key.
 * @flags: The quota flags for a new key.
 *
 * Create and instantiate a new key and link to it from the destination keyring.
 *
 * If perm is KEY_PERM_UNDEF then an appropriate key permissions mask will be
 * concocted.
 *
 * Returns a pointer to the new key if successful, -EEXIST if a key with the
 * same description already exists, -ENODEV if the key type wasn't available,
 * -ENOTDIR if the keyring wasn't a keyring, -EACCES if the caller isn't
 * permitted to modify the keyring or the LSM did not permit creation of the
 * key.
 *
 * On success, the possession flag from the keyring ref will be tacked on to
 * the key ref before it is returned.
 */
key_ref_t key_create(key_ref_t keyring_ref,
		     const char *type,
		     const char *description,
		     const void *payload,
		     size_t plen,
		     key_perm_t perm,
		     unsigned long flags)
{
	return __key_create_or_update(keyring_ref, type, description, payload,
				      plen, perm, flags, false);
}
EXPORT_SYMBOL(key_create);

/**
 * key_update - Update a key's contents.
 * @key_ref: The pointer (plus possession flag) to the key.