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: Thomas Weißschuh <linux@weissschuh.net>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
This commit is contained in:
Thomas Weißschuh 2023-01-09 23:59:42 +00:00 committed by Jarkko Sakkinen
parent 06b53b0294
commit 6c1976addf
2 changed files with 108 additions and 37 deletions

View File

@ -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,

View File

@ -788,38 +788,18 @@ error:
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,
const char *type,
const char *description,
const void *payload,
size_t plen,
key_perm_t perm,
unsigned long flags)
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,
bool allow_update)
{
struct keyring_index_key index_key = {
.description = description,
@ -906,14 +886,23 @@ 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 (index_key.type->update) {
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)
goto found_matching_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 */
@ -985,8 +974,82 @@ error:
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.