Message ID | 20221109025019.1855-3-linux@weissschuh.net (mailing list archive) |
---|---|
State | Handled Elsewhere |
Headers | show |
Series | certs: Prevent spurious errors on repeated blacklisting | expand |
On Wed, Nov 09, 2022 at 03:50:18AM +0100, Thomas Weißschuh wrote: > This function works like key_create_or_update() but does not allow > updating an existing key instead returning -EEXIST. > > This new function will be used by the blacklist keyring. How? > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net> > --- > include/linux/key.h | 8 +++ > security/keys/key.c | 149 +++++++++++++++++++++++++++++++++----------- > 2 files changed, 120 insertions(+), 37 deletions(-) > > diff --git a/include/linux/key.h b/include/linux/key.h > index d27477faf00d..8dc7f7c3088b 100644 > --- a/include/linux/key.h > +++ b/include/linux/key.h > @@ -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, > diff --git a/security/keys/key.c b/security/keys/key.c > index c45afdd1dfbb..f84bcd8457f4 100644 > --- a/security/keys/key.c > +++ b/security/keys/key.c > @@ -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, > - 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,94 @@ 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. > -- > 2.38.1 > BR, Jarkko
diff --git a/include/linux/key.h b/include/linux/key.h index d27477faf00d..8dc7f7c3088b 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -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, diff --git a/security/keys/key.c b/security/keys/key.c index c45afdd1dfbb..f84bcd8457f4 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -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, - 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,94 @@ 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.
This function works like key_create_or_update() but does not allow updating an existing key instead returning -EEXIST. This new function will be used by the blacklist keyring. Signed-off-by: Thomas Weißschuh <linux@weissschuh.net> --- include/linux/key.h | 8 +++ security/keys/key.c | 149 +++++++++++++++++++++++++++++++++----------- 2 files changed, 120 insertions(+), 37 deletions(-)