From cb481e59ea6cae3b7796ac1d7a22b6b24c3f3c0b Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Mon, 1 Jun 2026 23:11:54 +0300 Subject: KEYS: fix overflow in keyctl_pkey_params_get_2() The length for the internal output buffer is calculated incorrectly, which can result overflow when a too small buffer is provided. Fix the bug by allocating internal output with the size of the maximum length of the cryptographic primitive instead of caller provided size. Link: https://lore.kernel.org/keyrings/20260531024914.3712130-1-jarkko@kernel.org/ Cc: stable@vger.kernel.org # v4.20+ Fixes: 00d60fd3b932 ("KEYS: Provide keyctls to drive the new key type ops for asymmetric keys [ver #2]") Reported-by: Alessandro Groppo Tested-by: Alessandro Groppo Signed-off-by: Jarkko Sakkinen --- security/keys/keyctl_pkey.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/security/keys/keyctl_pkey.c b/security/keys/keyctl_pkey.c index 97bc27bbf079..ba150ee2d4a3 100644 --- a/security/keys/keyctl_pkey.c +++ b/security/keys/keyctl_pkey.c @@ -138,28 +138,35 @@ static int keyctl_pkey_params_get_2(const struct keyctl_pkey_params __user *_par if (uparams.in_len > info.max_dec_size || uparams.out_len > info.max_enc_size) return -EINVAL; + + params->out_len = info.max_enc_size; break; case KEYCTL_PKEY_DECRYPT: if (uparams.in_len > info.max_enc_size || uparams.out_len > info.max_dec_size) return -EINVAL; + + params->out_len = info.max_dec_size; break; case KEYCTL_PKEY_SIGN: if (uparams.in_len > info.max_data_size || uparams.out_len > info.max_sig_size) return -EINVAL; + + params->out_len = info.max_sig_size; break; case KEYCTL_PKEY_VERIFY: if (uparams.in_len > info.max_data_size || uparams.in2_len > info.max_sig_size) return -EINVAL; + + params->out_len = info.max_sig_size; break; default: BUG(); } params->in_len = uparams.in_len; - params->out_len = uparams.out_len; /* Note: same as in2_len */ return 0; } -- cgit v1.2.3 From 3a1705d180b203a6764d2a142d602bbf522d339b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 8 Apr 2026 11:41:35 +0300 Subject: KEYS: encrypted: Remove unnecessary selection of CRYPTO_RNG encrypted-keys uses the regular Linux RNG (get_random_bytes()), not the duplicative crypto_rng one. So it does not need to select CRYPTO_RNG. Signed-off-by: Eric Biggers Reviewed-by: Mimi Zohar Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- security/keys/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/security/keys/Kconfig b/security/keys/Kconfig index 84f39e50ca36..f4510d8cb485 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -87,7 +87,6 @@ config ENCRYPTED_KEYS select CRYPTO_AES select CRYPTO_CBC select CRYPTO_LIB_SHA256 - select CRYPTO_RNG help This option provides support for create/encrypting/decrypting keys in the kernel. Encrypted keys are instantiated using kernel -- cgit v1.2.3 From 4d05e948cebe03974ab9927daee55273207fdc22 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Thu, 9 Apr 2026 19:07:51 +0300 Subject: KEYS: trusted: Debugging as a feature TPM_DEBUG, and other similar flags, are a non-standard way to specify a feature in Linux kernel. Introduce CONFIG_TRUSTED_KEYS_DEBUG for trusted keys, and use it to replace these ad-hoc feature flags. Given that trusted keys debug dumps can contain sensitive data, harden the feature as follows: 1. In the Kconfig description postulate that pr_debug() statements must be used. 2. Use pr_debug() statements in TPM 1.x driver to print the protocol dump. 3. Require trusted.debug=1 on the kernel command line (default: 0) to activate dumps at runtime, even when CONFIG_TRUSTED_KEYS_DEBUG=y. Traces, when actually needed, can be easily enabled by providing trusted.dyndbg='+p' and trusted.debug=1 in the kernel command-line. Reported-by: Nayna Jain Closes: https://lore.kernel.org/all/7f8b8478-5cd8-4d97-bfd0-341fd5cf10f9@linux.ibm.com/ Reviewed-by: Nayna Jain Tested-by: Srish Srinivasan Signed-off-by: Jarkko Sakkinen --- Documentation/admin-guide/kernel-parameters.txt | 16 +++++++++ include/keys/trusted-type.h | 21 +++++++----- security/keys/trusted-keys/Kconfig | 23 +++++++++++++ security/keys/trusted-keys/trusted_caam.c | 7 ++-- security/keys/trusted-keys/trusted_core.c | 6 ++++ security/keys/trusted-keys/trusted_tpm1.c | 44 ++++++++++++++----------- 6 files changed, 87 insertions(+), 30 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 672665ea6265..2f0056b8e692 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -7875,6 +7875,22 @@ Kernel parameters first trust source as a backend which is initialized successfully during iteration. + trusted.debug= [KEYS] + Format: + Enable trusted keys debug traces at runtime when + CONFIG_TRUSTED_KEYS_DEBUG=y. + + To make the traces visible after enabling the option, + use trusted.dyndbg='+p' as needed. By convention, + the subsystem uses pr_debug() for these traces. + + SAFETY: The traces can leak sensitive data, so be + cautious before enabling this. They remain inactive + unless this parameter is set this option to a true + value. + + Default: false + trusted.rng= [KEYS] Format: The RNG used to generate key material for trusted keys. diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h index 03527162613f..9f9940482da4 100644 --- a/include/keys/trusted-type.h +++ b/include/keys/trusted-type.h @@ -83,18 +83,21 @@ struct trusted_key_source { extern struct key_type key_type_trusted; -#define TRUSTED_DEBUG 0 +#ifdef CONFIG_TRUSTED_KEYS_DEBUG +extern bool trusted_debug; -#if TRUSTED_DEBUG static inline void dump_payload(struct trusted_key_payload *p) { - pr_info("key_len %d\n", p->key_len); - print_hex_dump(KERN_INFO, "key ", DUMP_PREFIX_NONE, - 16, 1, p->key, p->key_len, 0); - pr_info("bloblen %d\n", p->blob_len); - print_hex_dump(KERN_INFO, "blob ", DUMP_PREFIX_NONE, - 16, 1, p->blob, p->blob_len, 0); - pr_info("migratable %d\n", p->migratable); + if (!trusted_debug) + return; + + pr_debug("key_len %d\n", p->key_len); + print_hex_dump_debug("key ", DUMP_PREFIX_NONE, + 16, 1, p->key, p->key_len, 0); + pr_debug("bloblen %d\n", p->blob_len); + print_hex_dump_debug("blob ", DUMP_PREFIX_NONE, + 16, 1, p->blob, p->blob_len, 0); + pr_debug("migratable %d\n", p->migratable); } #else static inline void dump_payload(struct trusted_key_payload *p) diff --git a/security/keys/trusted-keys/Kconfig b/security/keys/trusted-keys/Kconfig index 9e00482d886a..e5a4a53aeab2 100644 --- a/security/keys/trusted-keys/Kconfig +++ b/security/keys/trusted-keys/Kconfig @@ -1,10 +1,29 @@ config HAVE_TRUSTED_KEYS bool +config HAVE_TRUSTED_KEYS_DEBUG + bool + +config TRUSTED_KEYS_DEBUG + bool "Debug trusted keys" + depends on HAVE_TRUSTED_KEYS_DEBUG + default n + help + Trusted key backends and core code that support debug traces can + opt-in that feature here. Traces must only use debug level output, as + sensitive data may pass by. In the kernel-command line traces can be + enabled via trusted.dyndbg='+p'. + + SAFETY: Debug dumps are inactive at runtime until trusted.debug is set + to a true value on the kernel command-line. Use at your utmost + consideration when enabling this feature on a production build. The + general advice is not to do this. + config TRUSTED_KEYS_TPM bool "TPM-based trusted keys" depends on TCG_TPM >= TRUSTED_KEYS default y + select HAVE_TRUSTED_KEYS_DEBUG select CRYPTO_HASH_INFO select CRYPTO_LIB_SHA1 select CRYPTO_LIB_UTILS @@ -23,6 +42,7 @@ config TRUSTED_KEYS_TEE bool "TEE-based trusted keys" depends on TEE >= TRUSTED_KEYS default y + select HAVE_TRUSTED_KEYS_DEBUG select HAVE_TRUSTED_KEYS help Enable use of the Trusted Execution Environment (TEE) as trusted @@ -33,6 +53,7 @@ config TRUSTED_KEYS_CAAM depends on CRYPTO_DEV_FSL_CAAM_JR >= TRUSTED_KEYS select CRYPTO_DEV_FSL_CAAM_BLOB_GEN default y + select HAVE_TRUSTED_KEYS_DEBUG select HAVE_TRUSTED_KEYS help Enable use of NXP's Cryptographic Accelerator and Assurance Module @@ -42,6 +63,7 @@ config TRUSTED_KEYS_DCP bool "DCP-based trusted keys" depends on CRYPTO_DEV_MXS_DCP >= TRUSTED_KEYS default y + select HAVE_TRUSTED_KEYS_DEBUG select HAVE_TRUSTED_KEYS help Enable use of NXP's DCP (Data Co-Processor) as trusted key backend. @@ -50,6 +72,7 @@ config TRUSTED_KEYS_PKWM bool "PKWM-based trusted keys" depends on PSERIES_PLPKS >= TRUSTED_KEYS default y + select HAVE_TRUSTED_KEYS_DEBUG select HAVE_TRUSTED_KEYS help Enable use of IBM PowerVM Key Wrapping Module (PKWM) as a trusted key backend. diff --git a/security/keys/trusted-keys/trusted_caam.c b/security/keys/trusted-keys/trusted_caam.c index 601943ce0d60..6a33dbf2a7f5 100644 --- a/security/keys/trusted-keys/trusted_caam.c +++ b/security/keys/trusted-keys/trusted_caam.c @@ -28,10 +28,13 @@ static const match_table_t key_tokens = { {opt_err, NULL} }; -#ifdef CAAM_DEBUG +#ifdef CONFIG_TRUSTED_KEYS_DEBUG static inline void dump_options(const struct caam_pkey_info *pkey_info) { - pr_info("key encryption algo %d\n", pkey_info->key_enc_algo); + if (!trusted_debug) + return; + + pr_debug("key encryption algo %d\n", pkey_info->key_enc_algo); } #else static inline void dump_options(const struct caam_pkey_info *pkey_info) diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c index 0b142d941cd2..6aed17bee09d 100644 --- a/security/keys/trusted-keys/trusted_core.c +++ b/security/keys/trusted-keys/trusted_core.c @@ -31,6 +31,12 @@ static char *trusted_rng = "default"; module_param_named(rng, trusted_rng, charp, 0); MODULE_PARM_DESC(rng, "Select trusted key RNG"); +#ifdef CONFIG_TRUSTED_KEYS_DEBUG +bool trusted_debug; +module_param_named(debug, trusted_debug, bool, 0); +MODULE_PARM_DESC(debug, "Enable trusted keys debug traces (default: 0)"); +#endif + static char *trusted_key_source; module_param_named(source, trusted_key_source, charp, 0); MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam, dcp or pkwm)"); diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c index 6ea728f1eae6..13513819991e 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -46,38 +46,44 @@ enum { SRK_keytype = 4 }; -#define TPM_DEBUG 0 - -#if TPM_DEBUG +#ifdef CONFIG_TRUSTED_KEYS_DEBUG static inline void dump_options(struct trusted_key_options *o) { - pr_info("sealing key type %d\n", o->keytype); - pr_info("sealing key handle %0X\n", o->keyhandle); - pr_info("pcrlock %d\n", o->pcrlock); - pr_info("pcrinfo %d\n", o->pcrinfo_len); - print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE, - 16, 1, o->pcrinfo, o->pcrinfo_len, 0); + if (!trusted_debug) + return; + + pr_debug("sealing key type %d\n", o->keytype); + pr_debug("sealing key handle %0X\n", o->keyhandle); + pr_debug("pcrlock %d\n", o->pcrlock); + pr_debug("pcrinfo %d\n", o->pcrinfo_len); + print_hex_dump_debug("pcrinfo ", DUMP_PREFIX_NONE, + 16, 1, o->pcrinfo, o->pcrinfo_len, 0); } static inline void dump_sess(struct osapsess *s) { - print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE, - 16, 1, &s->handle, 4, 0); - pr_info("secret:\n"); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, - 16, 1, &s->secret, SHA1_DIGEST_SIZE, 0); - pr_info("trusted-key: enonce:\n"); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, - 16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0); + if (!trusted_debug) + return; + + print_hex_dump_debug("trusted-key: handle ", DUMP_PREFIX_NONE, + 16, 1, &s->handle, 4, 0); + pr_debug("secret:\n"); + print_hex_dump_debug("", DUMP_PREFIX_NONE, + 16, 1, &s->secret, SHA1_DIGEST_SIZE, 0); + pr_debug("trusted-key: enonce:\n"); + print_hex_dump_debug("", DUMP_PREFIX_NONE, + 16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0); } static inline void dump_tpm_buf(unsigned char *buf) { int len; - pr_info("\ntpm buffer\n"); + if (!trusted_debug) + return; + pr_debug("\ntpm buffer\n"); len = LOAD32(buf, TPM_SIZE_OFFSET); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0); + print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, buf, len, 0); } #else static inline void dump_options(struct trusted_key_options *o) -- cgit v1.2.3 From 8f2e22cfc45903b28bb9c5829a9ddbccc5001ea3 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 4 May 2026 11:31:00 +0200 Subject: keys: use kmalloc_flex in user_preparse Use kmalloc_flex() when allocating a new struct user_key_payload in user_preparse() to replace the open-coded size arithmetic and to keep the size type-safe. Signed-off-by: Thorsten Blum Link: https://lore.kernel.org/r/20260504093058.49720-3-thorsten.blum@linux.dev Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- security/keys/user_defined.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 686d56e4cc85..6f88b507f927 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -64,7 +64,7 @@ int user_preparse(struct key_preparsed_payload *prep) if (datalen == 0 || datalen > 32767 || !prep->data) return -EINVAL; - upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL); + upayload = kmalloc_flex(*upayload, data, datalen); if (!upayload) return -ENOMEM; -- cgit v1.2.3 From cc99abbe2aa7aed48fc7d8d21514240e063ea732 Mon Sep 17 00:00:00 2001 From: Len Bao Date: Sat, 16 May 2026 15:22:47 +0000 Subject: keys/trusted_keys: mark 'migratable' as __ro_after_init The 'migratable' variable is initialized only during the init phase in the 'init_trusted' function and never changed. So, mark it as __ro_after_init. Signed-off-by: Len Bao Reviewed-by: Jarkko Sakkinen Link: https://lore.kernel.org/r/20260516152249.41851-1-len.bao@gmx.us Signed-off-by: Jarkko Sakkinen --- security/keys/trusted-keys/trusted_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c index 6aed17bee09d..0509d9955f2a 100644 --- a/security/keys/trusted-keys/trusted_core.c +++ b/security/keys/trusted-keys/trusted_core.c @@ -65,7 +65,7 @@ DEFINE_STATIC_CALL_NULL(trusted_key_unseal, DEFINE_STATIC_CALL_NULL(trusted_key_get_random, *trusted_key_sources[0].ops->get_random); static void (*trusted_key_exit)(void); -static unsigned char migratable; +static unsigned char migratable __ro_after_init; enum { Opt_err, -- cgit v1.2.3 From c1201b37f666f6466ab1fd3a381c2b7a4b7e9fee Mon Sep 17 00:00:00 2001 From: Gui-Dong Han Date: Fri, 29 May 2026 11:34:06 +0800 Subject: KEYS: Use acquire when reading state in keyring search The negative-key race fix added release/acquire ordering for key use. Publish payload before state; read state before payload. keyring_search_iterator() still uses READ_ONCE() before match callbacks. An asymmetric match callback calls asymmetric_key_ids(), which reads key->payload.data[asym_key_ids]. Use key_read_state() there to complete that ordering. Fixes: 363b02dab09b ("KEYS: Fix race between updating and finding a negative key") Signed-off-by: Gui-Dong Han Reviewed-by: Jarkko Sakkinen Link: https://lore.kernel.org/r/20260529033406.20673-1-hanguidong02@gmail.com Signed-off-by: Jarkko Sakkinen --- security/keys/keyring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 5a9887d6b7be..7a2ee0ded7c9 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -576,7 +576,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data) struct keyring_search_context *ctx = iterator_data; const struct key *key = keyring_ptr_to_key(object); unsigned long kflags = READ_ONCE(key->flags); - short state = READ_ONCE(key->state); + short state = key_read_state(key); kenter("{%d}", key->serial); -- cgit v1.2.3 From 44b9597fea4b4d6d79d8b70a297ea425e05543c1 Mon Sep 17 00:00:00 2001 From: David Laight Date: Sat, 6 Jun 2026 21:26:03 +0100 Subject: keys: Replace strcpy(derived_buf, "AUTH_KEY") with strscpy(..., HASH_SIZE) derived_buf is guaranteed to be HASH_SIZE - and it is more than enough. The strscpy() degenerates into an memcpy() (as did the strcpy()). Do the same for the associated "ENC_KEY" copy. Removes a possibly unbounded strcpy(). Signed-off-by: David Laight Reviewed-by: Jarkko Sakkinen Link: https://lore.kernel.org/r/20260606202633.5018-9-david.laight.linux@gmail.com Signed-off-by: Jarkko Sakkinen --- security/keys/encrypted-keys/encrypted.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 56b531587a1e..59cb77b237b3 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -343,9 +343,9 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type, return -ENOMEM; if (key_type) - strcpy(derived_buf, "AUTH_KEY"); + strscpy(derived_buf, "AUTH_KEY", HASH_SIZE); else - strcpy(derived_buf, "ENC_KEY"); + strscpy(derived_buf, "ENC_KEY", HASH_SIZE); memcpy(derived_buf + strlen(derived_buf) + 1, master_key, master_keylen); -- cgit v1.2.3 From 0934c38b12bd838cc133d5895fc8b42c2c1717ee Mon Sep 17 00:00:00 2001 From: Mohammed EL Kadiri Date: Wed, 10 Jun 2026 07:50:52 +0100 Subject: keys: prevent slab cache merging for key_jar Add SLAB_NO_MERGE to key_jar to prevent the allocator from merging it with other similarly-sized caches. This hardens struct key isolation by ensuring dedicated slab pages. Acked-by: Vlastimil Babka (SUSE) Signed-off-by: Mohammed EL Kadiri Reviewed-by: Jarkko Sakkinen Link: https://lore.kernel.org/r/20260610065052.9120-1-med08elkadiri@gmail.com Signed-off-by: Jarkko Sakkinen --- security/keys/key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/key.c b/security/keys/key.c index 091ee084bc30..b34a64d81d47 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -1275,7 +1275,7 @@ void __init key_init(void) { /* allocate a slab in which we can store keys */ key_jar = kmem_cache_create("key_jar", sizeof(struct key), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); + 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_NO_MERGE, NULL); /* add the special key types */ list_add_tail(&key_type_keyring.link, &key_types_list); -- cgit v1.2.3 From fd15b457a86939c38aa12116adabd8ff686c5e51 Mon Sep 17 00:00:00 2001 From: Shaomin Chen Date: Wed, 10 Jun 2026 13:10:05 +0300 Subject: keys: Pin request_key_auth payload in instantiate paths A: request_key() B: KEYCTL_INSTANTIATE_IOV ================ ========================= create auth key store rka in auth key wait for helper get auth key load rka from auth key copy user payload sleep on #PF helper completed detach and free rka destroy auth key wake up use rka->target_key **USE-AFTER-FREE** Give request_key_auth payloads a refcount. Take a payload reference while authkey->sem stabilizes the payload and revocation state. Hold that reference across the instantiate and reject paths. Drop the auth key owning reference from revoke and destroy. [jarkko: Replaced the first two paragraphs of text with an actual concurrency scenario.] Cc: stable@vger.kernel.org # v5.10+ Fixes: b5f545c880a2 ("[PATCH] keys: Permit running process to instantiate keys") Reported-by: Shaomin Chen Closes: https://lore.kernel.org/r/20260519144403.436694-1-eeesssooo020@gmail.com Signed-off-by: Shaomin Chen Signed-off-by: Jarkko Sakkinen --- include/keys/request_key_auth-type.h | 2 ++ security/keys/internal.h | 2 ++ security/keys/keyctl.c | 24 ++++++++++++++++++------ security/keys/request_key_auth.c | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/include/keys/request_key_auth-type.h b/include/keys/request_key_auth-type.h index 36b89a933310..01e42ee5f409 100644 --- a/include/keys/request_key_auth-type.h +++ b/include/keys/request_key_auth-type.h @@ -9,12 +9,14 @@ #define _KEYS_REQUEST_KEY_AUTH_TYPE_H #include +#include /* * Authorisation record for request_key(). */ struct request_key_auth { struct rcu_head rcu; + refcount_t usage; struct key *target_key; struct key *dest_keyring; const struct cred *cred; diff --git a/security/keys/internal.h b/security/keys/internal.h index 2cffa6dc8255..b7b622bc36a1 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -208,6 +208,8 @@ extern struct key *request_key_auth_new(struct key *target, const void *callout_info, size_t callout_len, struct key *dest_keyring); +struct request_key_auth *request_key_auth_get(struct key *authkey); +void request_key_auth_put(struct request_key_auth *rka); extern struct key *key_get_instantiation_authkey(key_serial_t target_id); diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index ef855d69c97a..d14ace88e529 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1197,9 +1197,13 @@ static long keyctl_instantiate_key_common(key_serial_t id, if (!instkey) goto error; - rka = instkey->payload.data[0]; - if (rka->target_key->serial != id) + rka = request_key_auth_get(instkey); + if (!rka) { + ret = -EKEYREVOKED; goto error; + } + if (rka->target_key->serial != id) + goto error_put_rka; /* pull the payload in if one was supplied */ payload = NULL; @@ -1208,7 +1212,7 @@ static long keyctl_instantiate_key_common(key_serial_t id, ret = -ENOMEM; payload = kvmalloc(plen, GFP_KERNEL); if (!payload) - goto error; + goto error_put_rka; ret = -EFAULT; if (!copy_from_iter_full(payload, plen, from)) @@ -1234,6 +1238,8 @@ static long keyctl_instantiate_key_common(key_serial_t id, error2: kvfree_sensitive(payload, plen); +error_put_rka: + request_key_auth_put(rka); error: return ret; } @@ -1358,15 +1364,19 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error, if (!instkey) goto error; - rka = instkey->payload.data[0]; - if (rka->target_key->serial != id) + rka = request_key_auth_get(instkey); + if (!rka) { + ret = -EKEYREVOKED; goto error; + } + if (rka->target_key->serial != id) + goto error_put_rka; /* find the destination keyring if present (which must also be * writable) */ ret = get_instantiation_keyring(ringid, rka, &dest_keyring); if (ret < 0) - goto error; + goto error_put_rka; /* instantiate the key and link it into a keyring */ ret = key_reject_and_link(rka->target_key, timeout, error, @@ -1379,6 +1389,8 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error, if (ret == 0) keyctl_change_reqkey_auth(NULL); +error_put_rka: + request_key_auth_put(rka); error: return ret; } diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index a7d7538c1f70..282e09d8fa46 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -23,6 +23,7 @@ static void request_key_auth_describe(const struct key *, struct seq_file *); static void request_key_auth_revoke(struct key *); static void request_key_auth_destroy(struct key *); static long request_key_auth_read(const struct key *, char *, size_t); +static void request_key_auth_rcu_disposal(struct rcu_head *); /* * The request-key authorisation key type definition. @@ -115,6 +116,31 @@ static void free_request_key_auth(struct request_key_auth *rka) kfree(rka); } +/* + * Take a reference to the request-key authorisation payload so callers can + * drop authkey->sem before doing operations that may sleep. + */ +struct request_key_auth *request_key_auth_get(struct key *authkey) +{ + struct request_key_auth *rka; + + down_read(&authkey->sem); + rka = dereference_key_locked(authkey); + if (rka && !test_bit(KEY_FLAG_REVOKED, &authkey->flags)) + refcount_inc(&rka->usage); + else + rka = NULL; + up_read(&authkey->sem); + + return rka; +} + +void request_key_auth_put(struct request_key_auth *rka) +{ + if (rka && refcount_dec_and_test(&rka->usage)) + call_rcu(&rka->rcu, request_key_auth_rcu_disposal); +} + /* * Dispose of the request_key_auth record under RCU conditions */ @@ -136,8 +162,10 @@ static void request_key_auth_revoke(struct key *key) struct request_key_auth *rka = dereference_key_locked(key); kenter("{%d}", key->serial); + if (!rka) + return; rcu_assign_keypointer(key, NULL); - call_rcu(&rka->rcu, request_key_auth_rcu_disposal); + request_key_auth_put(rka); } /* @@ -150,7 +178,7 @@ static void request_key_auth_destroy(struct key *key) kenter("{%d}", key->serial); if (rka) { rcu_assign_keypointer(key, NULL); - call_rcu(&rka->rcu, request_key_auth_rcu_disposal); + request_key_auth_put(rka); } } @@ -174,6 +202,7 @@ struct key *request_key_auth_new(struct key *target, const char *op, rka = kzalloc_obj(*rka); if (!rka) goto error; + refcount_set(&rka->usage, 1); rka->callout_info = kmemdup(callout_info, callout_len, GFP_KERNEL); if (!rka->callout_info) goto error_free_rka; -- cgit v1.2.3 From 10366fe27a4ce08a392eb16ed48ea0a440e671c2 Mon Sep 17 00:00:00 2001 From: Mohammed EL Kadiri Date: Sat, 13 Jun 2026 14:04:07 +0100 Subject: keys: request_key: replace BUG with return -EINVAL Replace BUG() in construct_get_dest_keyring() default case with return -EINVAL to handle the unimplemented group keyring destination gracefully. Signed-off-by: Mohammed EL Kadiri Reviewed-by: Jarkko Sakkinen Link: https://lore.kernel.org/r/20260613130408.13709-2-med08elkadiri@gmail.com Signed-off-by: Jarkko Sakkinen --- security/keys/request_key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/request_key.c b/security/keys/request_key.c index a7673ad86d18..fa2bb9f2f538 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -332,7 +332,7 @@ static int construct_get_dest_keyring(struct key **_dest_keyring) case KEY_REQKEY_DEFL_GROUP_KEYRING: default: - BUG(); + return -EINVAL; } /* -- cgit v1.2.3 From 1b9524250996b1f2f49833a1b2ae21c34e486f85 Mon Sep 17 00:00:00 2001 From: Mohammed EL Kadiri Date: Mon, 15 Jun 2026 15:11:50 +0300 Subject: keys: keyctl_pkey: replace BUG with return -EOPNOTSUPP Replace two BUG() calls in keyctl_pkey_params_get_2() and keyctl_pkey_e_d_s() default cases with -EOPNOTSUPP, matching the error style already used in these functions. Signed-off-by: Mohammed EL Kadiri Signed-off-by: Jarkko Sakkinen --- security/keys/keyctl_pkey.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/security/keys/keyctl_pkey.c b/security/keys/keyctl_pkey.c index ba150ee2d4a3..15b6bf6399b5 100644 --- a/security/keys/keyctl_pkey.c +++ b/security/keys/keyctl_pkey.c @@ -163,7 +163,7 @@ static int keyctl_pkey_params_get_2(const struct keyctl_pkey_params __user *_par params->out_len = info.max_sig_size; break; default: - BUG(); + return -EOPNOTSUPP; } params->in_len = uparams.in_len; @@ -245,7 +245,8 @@ long keyctl_pkey_e_d_s(int op, params.op = kernel_pkey_sign; break; default: - BUG(); + ret = -EOPNOTSUPP; + goto error_params; } in = memdup_user(_in, params.in_len); -- cgit v1.2.3