* [RFC PATCH 0/2] keys: Address lookup_user_key() mutability
@ 2026-09-24 5:55 Jarkko Sakkinen
2026-09-24 5:55 ` [RFC PATCH 1/2] keys: Return user session keyring on lookup Jarkko Sakkinen
2026-09-24 5:55 ` [RFC PATCH 2/2] keys: Reject keyring creation with overridden credentials Jarkko Sakkinen
0 siblings, 2 replies; 3+ messages in thread
From: Jarkko Sakkinen @ 2026-09-24 5:55 UTC (permalink / raw)
To: keyrings
Cc: Jann Horn, linux-kernel, linux-security-module, Jarkko Sakkinen,
David Howells, Paul Moore, James Morris, Serge E. Hallyn
The main objective in these patches is to remove to unneeded mutability
from key look ups. It does harm and brings no value so it is pretty obvious
to me that addressing this harmful behaviour is what we should do.
I based the first patch on what Jann suggested in [1]. Nothing too clever here
and I'm ofc open for further suggestions.
[1] https://lore.kernel.org/keyrings/CAG48ez0XjVSR=M--UBauTm8sJuc+ZbhKzaPa3a6wrSVHyoKevw@mail.gmail.com/
Jarkko Sakkinen (2):
keys: Return user session keyring on lookup
keys: Reject keyring creation with overridden credentials
Documentation/security/keys/core.rst | 7 ++-
security/keys/process_keys.c | 65 +++++++++++++++-------------
2 files changed, 40 insertions(+), 32 deletions(-)
--
2.47.3
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH 1/2] keys: Return user session keyring on lookup
2026-09-24 5:55 [RFC PATCH 0/2] keys: Address lookup_user_key() mutability Jarkko Sakkinen
@ 2026-09-24 5:55 ` Jarkko Sakkinen
2026-09-24 5:55 ` [RFC PATCH 2/2] keys: Reject keyring creation with overridden credentials Jarkko Sakkinen
1 sibling, 0 replies; 3+ messages in thread
From: Jarkko Sakkinen @ 2026-09-24 5:55 UTC (permalink / raw)
To: keyrings
Cc: Jann Horn, linux-kernel, linux-security-module, Jarkko Sakkinen,
David Howells, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Paul Moore, James Morris, Serge E. Hallyn,
open list:DOCUMENTATION
A process without a session keyring looking up KEY_SPEC_SESSION_KEYRING
without KEY_LOOKUP_CREATE mutates the credentials. This causes struct creds
instances shared with other subsystems to become stale.
Address this by returning the resolved user session keyring directly
without installing it into credentials.
Suggested-by: Jann Horn <jannh@google.com>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
---
Documentation/security/keys/core.rst | 6 ++--
security/keys/process_keys.c | 44 +++++++---------------------
2 files changed, 14 insertions(+), 36 deletions(-)
diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst
index 326b8a973828..c81a3a9fe236 100644
--- a/Documentation/security/keys/core.rst
+++ b/Documentation/security/keys/core.rst
@@ -165,8 +165,10 @@ The key service provides a number of features besides keys:
When a process changes its real UID, if it used to have no session key, it
will be subscribed to the default session key for the new UID.
- If a process attempts to access its session key when it doesn't have one,
- it will be subscribed to the default for its current UID.
+ If a process attempts to access its session keyring when it doesn't have
+ one, the default user session keyring for its current UID is returned
+ without being installed into its credentials. If creation is requested,
+ an anonymous session keyring is installed.
* Each user has two quotas against which the keys they own are tracked. One
limits the total number of keys and keyrings, the other limits the total
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index a63c46bb2d14..a5aa056a6725 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -346,31 +346,6 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
return 0;
}
-/*
- * Install the given keyring as the session keyring of the current task,
- * replacing the existing one if any. If the given keyring is NULL, then
- * install a new anonymous session keyring.
- *
- * Return: 0 on success; -errno on failure.
- */
-static int install_session_keyring(struct key *keyring)
-{
- struct cred *new;
- int ret;
-
- new = prepare_creds();
- if (!new)
- return -ENOMEM;
-
- ret = install_session_keyring_to_cred(new, keyring);
- if (ret < 0) {
- abort_creds(new);
- return ret;
- }
-
- return commit_creds(new);
-}
-
/*
* Handle the fsuid changing.
*/
@@ -665,20 +640,21 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
case KEY_SPEC_SESSION_KEYRING:
if (!ctx.cred->session_keyring) {
- /* always install a session keyring upon access if one
- * doesn't exist yet */
ret = look_up_user_keyrings(NULL, &user_session);
if (ret < 0)
goto error;
- if (lflags & KEY_LOOKUP_CREATE)
+
+ if (lflags & KEY_LOOKUP_CREATE) {
+ key_put(user_session);
ret = join_session_keyring(NULL);
- else
- ret = install_session_keyring(user_session);
+ if (ret < 0)
+ goto error;
+ goto reget_creds;
+ }
- key_put(user_session);
- if (ret < 0)
- goto error;
- goto reget_creds;
+ key = user_session;
+ key_ref = make_key_ref(key, 1);
+ break;
} else if (test_bit(KEY_FLAG_UID_KEYRING,
&ctx.cred->session_keyring->flags) &&
lflags & KEY_LOOKUP_CREATE) {
--
2.47.3
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH 2/2] keys: Reject keyring creation with overridden credentials
2026-09-24 5:55 [RFC PATCH 0/2] keys: Address lookup_user_key() mutability Jarkko Sakkinen
2026-09-24 5:55 ` [RFC PATCH 1/2] keys: Return user session keyring on lookup Jarkko Sakkinen
@ 2026-09-24 5:55 ` Jarkko Sakkinen
1 sibling, 0 replies; 3+ messages in thread
From: Jarkko Sakkinen @ 2026-09-24 5:55 UTC (permalink / raw)
To: keyrings
Cc: Jann Horn, linux-kernel, linux-security-module, Jarkko Sakkinen,
David Howells, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Paul Moore, James Morris, Serge E. Hallyn,
open list:DOCUMENTATION
If the current task is running with overridden credentials calling
commit_creds() is forbidden and triggers a BUG_ON().
Reject keyring creation with -EPERM when credentials are overridden.
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
---
Documentation/security/keys/core.rst | 3 ++-
security/keys/process_keys.c | 31 +++++++++++++++++++++++++++-
2 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst
index c81a3a9fe236..9779ce71df47 100644
--- a/Documentation/security/keys/core.rst
+++ b/Documentation/security/keys/core.rst
@@ -168,7 +168,8 @@ The key service provides a number of features besides keys:
If a process attempts to access its session keyring when it doesn't have
one, the default user session keyring for its current UID is returned
without being installed into its credentials. If creation is requested,
- an anonymous session keyring is installed.
+ an anonymous session keyring is installed, failing with -EPERM if
+ credentials are overridden.
* Each user has two quotas against which the keys they own are tracked. One
limits the total number of keys and keyrings, the other limits the total
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index a5aa056a6725..bd68dbc028e2 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -346,6 +346,14 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
return 0;
}
+/*
+ * Determine whether the current task is running with overridden credentials.
+ */
+static bool cred_overridden(void)
+{
+ return current_cred() != current_real_cred();
+}
+
/*
* Handle the fsuid changing.
*/
@@ -578,7 +586,8 @@ bool lookup_user_key_possessed(const struct key *key,
* to a key or the best found key was a negative key; -EKEYREVOKED or
* -EKEYEXPIRED if the best found key was revoked or expired; -EACCES if the
* found key doesn't grant the requested permit or the LSM denied access to it;
- * or -ENOMEM if a special keyring couldn't be created.
+ * -ENOMEM if a special keyring couldn't be created; or -EPERM if creating one
+ * while credentials are overridden.
*
* In the case of a successful return, the possession attribute is set on the
* returned key reference.
@@ -607,6 +616,11 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
if (!(lflags & KEY_LOOKUP_CREATE))
goto error;
+ if (cred_overridden()) {
+ key_ref = ERR_PTR(-EPERM);
+ goto error;
+ }
+
ret = install_thread_keyring();
if (ret < 0) {
key_ref = ERR_PTR(ret);
@@ -625,6 +639,11 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
if (!(lflags & KEY_LOOKUP_CREATE))
goto error;
+ if (cred_overridden()) {
+ key_ref = ERR_PTR(-EPERM);
+ goto error;
+ }
+
ret = install_process_keyring();
if (ret < 0) {
key_ref = ERR_PTR(ret);
@@ -646,6 +665,11 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
if (lflags & KEY_LOOKUP_CREATE) {
key_put(user_session);
+ if (cred_overridden()) {
+ key_ref = ERR_PTR(-EPERM);
+ goto error;
+ }
+
ret = join_session_keyring(NULL);
if (ret < 0)
goto error;
@@ -658,6 +682,11 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
} else if (test_bit(KEY_FLAG_UID_KEYRING,
&ctx.cred->session_keyring->flags) &&
lflags & KEY_LOOKUP_CREATE) {
+ if (cred_overridden()) {
+ key_ref = ERR_PTR(-EPERM);
+ goto error;
+ }
+
ret = join_session_keyring(NULL);
if (ret < 0)
goto error;
--
2.47.3
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-24 5:55 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-24 5:55 [RFC PATCH 0/2] keys: Address lookup_user_key() mutability Jarkko Sakkinen
2026-09-24 5:55 ` [RFC PATCH 1/2] keys: Return user session keyring on lookup Jarkko Sakkinen
2026-09-24 5:55 ` [RFC PATCH 2/2] keys: Reject keyring creation with overridden credentials Jarkko Sakkinen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®