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 Cc: stable@vger.kernel.org # v6.1+ Fixes: 8cf57d7217c3 ("s390: add support for user-defined certificates") Signed-off-by: Jarkko Sakkinen --- 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