From: Jarkko Sakkinen <jarkko@kernel.org>
To: David Howells <dhowells@redhat.com>
Cc: Eric Biggers <ebiggers@kernel.org>,
linux-integrity@vger.kernel.org, Mimi Zohar <zohar@linux.ibm.com>,
keyrings@vger.kernel.org, Jarkko Sakkinen <jarkko@kernel.org>,
Roberto Sassu <roberto.sassu@huawei.com>,
Dmitry Kasatkin <dmitry.kasatkin@gmail.com>,
Eric Snowberg <eric.snowberg@oracle.com>,
Paul Moore <paul@paul-moore.com>,
James Morris <jmorris@namei.org>,
"Serge E. Hallyn" <serge@hallyn.com>,
linux-kernel@vger.kernel.org (open list),
linux-security-module@vger.kernel.org (open list:SECURITY
SUBSYSTEM)
Subject: [RFC PATCH v2 09/11] KEYS: Pin the backing kernel module for a key type
Date: Tue, 3 Nov 2026 05:02:14 +0200 [thread overview]
Message-ID: <20261103030226.2685251-10-jarkko@kernel.org> (raw)
In-Reply-To: <20261103030226.2685251-1-jarkko@kernel.org>
Add the owner field (populated with THIS_MODULE) to struct key_type.
Pin the module in key_alloc() and keyring_restrict(), and release it in
key_gc_unused_keys() and keyring_destroy(), which are wires to the keys
and restrictions.
Reject module owners still in MODULE_STATE_COMING so that the failed
module_init() paths cannot leave behind referenced keys.
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
---
include/linux/key-type.h | 6 ++++-
security/keys/gc.c | 3 +++
security/keys/key.c | 48 ++++++++++++++++++++++++++++++----------
security/keys/keyring.c | 33 ++++++++++++++++++++++-----
4 files changed, 71 insertions(+), 19 deletions(-)
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index c4f329b6ae3f..9ecec31ad571 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -10,9 +10,11 @@
#include <linux/key.h>
#include <linux/errno.h>
+#include <linux/init.h>
#ifdef CONFIG_KEYS
+struct module;
struct kernel_pkey_query;
struct kernel_pkey_params;
@@ -161,6 +163,7 @@ struct key_type {
const void *in, const void *in2);
/* internal fields */
+ struct module *owner;
atomic64_t index_id; /* Opaque keyring index ID */
struct list_head link; /* link in types list */
struct lock_class_key lock_class; /* key->sem lock class */
@@ -168,7 +171,8 @@ struct key_type {
extern struct key_type key_type_keyring;
-extern int register_key_type(struct key_type *ktype);
+int __register_key_type(struct key_type *ktype, struct module *owner);
+#define register_key_type(ktype) __register_key_type(ktype, THIS_MODULE)
extern void unregister_key_type(struct key_type *ktype);
extern int key_payload_reserve(struct key *key, size_t datalen);
diff --git a/security/keys/gc.c b/security/keys/gc.c
index 3cfbf00085b3..f4ae3e57a4be 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -6,6 +6,7 @@
*/
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/security.h>
#include <keys/keyring-type.h>
#include "internal.h"
@@ -151,6 +152,7 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
while (!list_empty(keys)) {
struct key *key =
list_entry(keys->next, struct key, graveyard_link);
+ struct module *owner = key->type->owner;
short state = key->state;
list_del(&key->graveyard_link);
@@ -179,6 +181,7 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
memzero_explicit(key, sizeof(*key));
kmem_cache_free(key_jar, key);
+ module_put(owner);
}
}
diff --git a/security/keys/key.c b/security/keys/key.c
index 3f1f0fc13710..0b2a03c511e5 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -7,6 +7,7 @@
#include <linux/export.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/poison.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -234,19 +235,34 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key = ERR_PTR(-EINVAL);
if (!desc || !*desc)
- goto error;
+ goto out;
+
+ /* Failed module initialization ignores outstanding module references. */
+ if ((type->owner && module_is_coming(type->owner)) ||
+ !try_module_get(type->owner)) {
+ key = ERR_PTR(-ENOENT);
+ goto out;
+ }
+
+ if (restrict_link && restrict_link->keytype &&
+ ((restrict_link->keytype->owner &&
+ module_is_coming(restrict_link->keytype->owner)) ||
+ !try_module_get(restrict_link->keytype->owner))) {
+ key = ERR_PTR(-ENOENT);
+ goto out_put_module;
+ }
if (type->vet_description) {
ret = type->vet_description(desc);
if (ret < 0) {
key = ERR_PTR(ret);
- goto error;
+ goto out_put_restrict_module;
}
}
desclen = strlen(desc);
if (desclen >= KEY_MAX_DESC_SIZE)
- goto error;
+ goto out_put_restrict_module;
quotalen = desclen + 1 + type->def_datalen;
/* get hold of the key tracking for this user */
@@ -323,8 +339,6 @@ struct key *key_alloc(struct key_type *type, const char *desc,
refcount_inc(&key->domain_tag->usage);
atomic_inc(&user->nkeys);
key_alloc_serial(key);
-
-error:
return key;
security_error:
@@ -338,7 +352,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
}
key_user_put(user);
key = ERR_PTR(ret);
- goto error;
+ goto out_put_restrict_module;
no_memory_3:
kmem_cache_free(key_jar, key);
@@ -352,13 +366,22 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key_user_put(user);
no_memory_1:
key = ERR_PTR(-ENOMEM);
- goto error;
+ goto out_put_restrict_module;
no_quota:
spin_unlock_irqrestore(&user->lock, irqflags);
key_user_put(user);
key = ERR_PTR(-EDQUOT);
- goto error;
+
+out_put_restrict_module:
+ if (restrict_link && restrict_link->keytype)
+ module_put(restrict_link->keytype->owner);
+
+out_put_module:
+ module_put(type->owner);
+
+out:
+ return key;
}
EXPORT_SYMBOL(key_alloc);
@@ -1231,19 +1254,20 @@ int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
EXPORT_SYMBOL(generic_key_instantiate);
/**
- * register_key_type - Register a type of key.
+ * __register_key_type - Register a type of key.
* @ktype: The new key type.
+ * @owner: Module owning the key type.
*
* Register a new key type.
*
* Returns 0 on success or -EEXIST if a type of this name already exists.
*/
-int register_key_type(struct key_type *ktype)
+int __register_key_type(struct key_type *ktype, struct module *owner)
{
struct key_type *p;
int ret;
- memset(&ktype->lock_class, 0, sizeof(ktype->lock_class));
+ ktype->owner = owner;
ret = -EEXIST;
down_write(&key_types_sem);
@@ -1264,7 +1288,7 @@ int register_key_type(struct key_type *ktype)
up_write(&key_types_sem);
return ret;
}
-EXPORT_SYMBOL(register_key_type);
+EXPORT_SYMBOL(__register_key_type);
/**
* unregister_key_type - Unregister a type of key.
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 5281da9d5bf7..1561406b68fa 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -7,6 +7,7 @@
#include <linux/export.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/security.h>
@@ -436,6 +437,9 @@ static void keyring_destroy(struct key *keyring)
if (keyring->restrict_link) {
struct key_restriction *keyres = keyring->restrict_link;
+ if (keyres->keytype)
+ module_put(keyres->keytype->owner);
+
key_put(keyres->key);
kfree(keyres);
}
@@ -1062,7 +1066,7 @@ int keyring_restrict(key_ref_t keyring_ref, const char *type,
if (!restrict_type->lookup_restriction) {
ret = -ENOENT;
- goto error;
+ goto out;
}
restrict_link = restrict_type->lookup_restriction(restriction);
@@ -1070,7 +1074,15 @@ int keyring_restrict(key_ref_t keyring_ref, const char *type,
if (IS_ERR(restrict_link)) {
ret = PTR_ERR(restrict_link);
- goto error;
+ goto out;
+ }
+
+ if (restrict_link && restrict_link->keytype &&
+ ((restrict_link->keytype->owner &&
+ module_is_coming(restrict_link->keytype->owner)) ||
+ !try_module_get(restrict_link->keytype->owner))) {
+ ret = -ENOENT;
+ goto out_free_restriction;
}
down_write(&keyring->sem);
@@ -1088,12 +1100,21 @@ int keyring_restrict(key_ref_t keyring_ref, const char *type,
up_write(&keyring_serialise_restrict_sem);
up_write(&keyring->sem);
- if (ret < 0) {
+ if (ret < 0)
+ goto out_put_module;
+
+ goto out;
+
+out_put_module:
+ if (restrict_link && restrict_link->keytype)
+ module_put(restrict_link->keytype->owner);
+
+out_free_restriction:
+ if (restrict_link)
key_put(restrict_link->key);
- kfree(restrict_link);
- }
+ kfree(restrict_link);
-error:
+out:
if (restrict_type)
key_type_put(restrict_type);
--
2.47.3
next prev parent reply other threads:[~2026-11-03 3:03 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 3:02 [RFC PATCH v2 00/11] KEYS: Sanitize the garbage collector Jarkko Sakkinen
2026-11-03 3:02 ` [RFC PATCH v2 01/11] KEYS: Add key_gc_flush() for draining RCU callbacks Jarkko Sakkinen
2026-11-04 3:03 ` sashiko-bot
2026-11-03 3:02 ` [RFC PATCH v2 02/11] nvme-keyring: Add a missing key_put() call to nvme_tls_key_lookup() Jarkko Sakkinen
2026-11-03 5:33 ` Christoph Hellwig
2026-11-03 12:29 ` Jarkko Sakkinen
2026-11-04 9:04 ` Christoph Hellwig
2026-11-04 14:43 ` Jarkko Sakkinen
2026-11-04 15:53 ` Keith Busch
2026-11-04 3:03 ` sashiko-bot
2026-11-04 7:45 ` Hannes Reinecke
2026-11-04 14:43 ` Jarkko Sakkinen
2026-11-03 3:02 ` [RFC PATCH v2 03/11] dns_resolver: Clear .dns_resolver cache when the last client unloads Jarkko Sakkinen
2026-11-04 3:03 ` sashiko-bot
2026-11-03 3:02 ` [RFC PATCH v2 04/11] NFSv4: Clear idmap keyring " Jarkko Sakkinen
2026-11-04 3:03 ` sashiko-bot
2026-11-03 3:02 ` [RFC PATCH v2 05/11] smb: client: Clear idmap/SPNEGO caches when the last session is unloaded Jarkko Sakkinen
2026-11-04 3:03 ` sashiko-bot
2026-11-03 3:02 ` [RFC PATCH v2 06/11] s390/cert_store: Track subsystem keys instead of re-registering key_type Jarkko Sakkinen
2026-11-03 12:06 ` Jarkko Sakkinen
2026-11-04 3:03 ` sashiko-bot
2026-11-03 3:02 ` [RFC PATCH v2 07/11] KEYS: trusted: TEE: Disable sysfs bind attributes Jarkko Sakkinen
2026-11-04 3:03 ` sashiko-bot
2026-11-03 3:02 ` [RFC PATCH v2 08/11] KEYS: trusted: TEE: Synchronize session lifetime Jarkko Sakkinen
2026-11-04 3:03 ` sashiko-bot
2026-11-03 3:02 ` Jarkko Sakkinen [this message]
2026-11-04 3:03 ` [RFC PATCH v2 09/11] KEYS: Pin the backing kernel module for a key type sashiko-bot
2026-11-03 3:02 ` [RFC PATCH v2 10/11] KEYS: Remove key_type_dead Jarkko Sakkinen
2026-11-04 3:03 ` sashiko-bot
2026-11-03 3:02 ` [RFC PATCH v2 11/11] KEYS: key_garbage_collector(): process in chunks Jarkko Sakkinen
2026-11-04 3:03 ` sashiko-bot
2026-11-03 3:10 ` [RFC PATCH v2 00/11] KEYS: Sanitize the garbage collector Jarkko Sakkinen
2026-11-03 12:32 ` Jarkko Sakkinen
2026-11-03 10:03 ` David Howells
2026-11-03 12:03 ` Jarkko Sakkinen
2026-11-03 14:00 ` David Howells
2026-11-03 15:06 ` Jarkko Sakkinen
2026-11-03 15:32 ` David Howells
2026-11-03 16:58 ` Jarkko Sakkinen
2026-11-04 0:30 ` Jarkko Sakkinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261103030226.2685251-10-jarkko@kernel.org \
--to=jarkko@kernel.org \
--cc=dhowells@redhat.com \
--cc=dmitry.kasatkin@gmail.com \
--cc=ebiggers@kernel.org \
--cc=eric.snowberg@oracle.com \
--cc=jmorris@namei.org \
--cc=keyrings@vger.kernel.org \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=paul@paul-moore.com \
--cc=roberto.sassu@huawei.com \
--cc=serge@hallyn.com \
--cc=zohar@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.