[PATCH v11 1/6] s390/cert_store: Pin the user session keyring

From: Jarkko Sakkinen

Date: Sat Nov 14 2026 - 11:12:42 EST


The user session keyring stays alive only because the session keyring is
pinned by current_cred().

Pin the reference at:

1. find_cs_keyring()
2. cleanup_cs_keys()
3. create_cs_keyring()

Cc: David Howells <dhowells@xxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx # v6.1+
Fixes: 8cf57d7217c3 ("s390: add support for user-defined certificates")
Signed-off-by: Jarkko Sakkinen <jarkko@xxxxxxxxxx>
---
arch/s390/kernel/cert_store.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/arch/s390/kernel/cert_store.c b/arch/s390/kernel/cert_store.c
index 998f2da56175..bb218b42a2c9 100644
--- a/arch/s390/kernel/cert_store.c
+++ b/arch/s390/kernel/cert_store.c
@@ -307,7 +307,6 @@ static struct key *get_user_session_keyring(void)
PTR_ERR(us_keyring_ref));
return ERR_PTR(-ENOKEY);
}
- key_ref_put(us_keyring_ref);
return key_ref_to_ptr(us_keyring_ref);
}

@@ -352,11 +351,17 @@ static int invalidate_keyring_keys(struct key *keyring)
static struct key *find_cs_keyring(void)
{
key_ref_t cs_keyring_ref;
+ struct key *us_keyring;
struct key *cs_keyring;

- cs_keyring_ref = keyring_search(make_key_ref(get_user_session_keyring(), true),
+ us_keyring = get_user_session_keyring();
+ if (IS_ERR(us_keyring))
+ return NULL;
+
+ cs_keyring_ref = keyring_search(make_key_ref(us_keyring, true),
&key_type_keyring, CERT_STORE_KEYRING_NAME,
false);
+ key_put(us_keyring);
if (!IS_ERR(cs_keyring_ref)) {
cs_keyring = key_ref_to_ptr(cs_keyring_ref);
key_ref_put(cs_keyring_ref);
@@ -373,6 +378,7 @@ static struct key *find_cs_keyring(void)

static void cleanup_cs_keys(void)
{
+ struct key *us_keyring;
struct key *cs_keyring;

cs_keyring = find_cs_keyring();
@@ -390,20 +396,33 @@ static void cleanup_cs_keys(void)
keyring_clear(cs_keyring);
key_invalidate(cs_keyring);
key_put(cs_keyring);
- key_unlink(get_user_session_keyring(), cs_keyring);
+
+ us_keyring = get_user_session_keyring();
+ if (IS_ERR(us_keyring))
+ return;
+
+ key_unlink(us_keyring, cs_keyring);
+ key_put(us_keyring);
}

static struct key *create_cs_keyring(void)
{
static struct key *cs_keyring;
+ struct key *us_keyring;

/* Cleanup previous cs_keyring and all associated keys if any. */
cleanup_cs_keys();
+
+ us_keyring = get_user_session_keyring();
+ if (IS_ERR(us_keyring))
+ return NULL;
+
cs_keyring = keyring_alloc(CERT_STORE_KEYRING_NAME, GLOBAL_ROOT_UID,
GLOBAL_ROOT_GID, current_cred(),
(KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ,
KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_SET_KEEP,
- NULL, get_user_session_keyring());
+ NULL, us_keyring);
+ key_put(us_keyring);
if (IS_ERR(cs_keyring)) {
pr_dbf_msg("Can't allocate cert_store keyring");
return NULL;
--
2.47.3