[PATCH RFC v3 60/90] keys: ignore an equal uid or gid across cells

From: Josef Bacik

Date: Thu Nov 05 2026 - 10:31:29 EST


key_task_permission() grants the permissions of the owner to any
credential whose fsuid equals the uid of the key. Key serial numbers are
global. A cell with a single id runs with the kuid of the user who created
it. So a task of the cell can link the user keyring of that user into one
of its own keyrings and read the keys in it.

Record in each key the id of the cell that its uid and gid belong to.
Grant the owner and group permissions only to credentials of that cell.

Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
include/linux/key.h | 1 +
security/keys/key.c | 2 ++
security/keys/permission.c | 7 +++++++
3 files changed, 10 insertions(+)

diff --git a/include/linux/key.h b/include/linux/key.h
index 0bd77fcab4db..c291165e9096 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -215,6 +215,7 @@ struct key {
time64_t last_used_at; /* last time used for LRU keyring discard */
kuid_t uid;
kgid_t gid;
+ u64 cell_id; /* the cell those ids are to be read in */
key_perm_t perm; /* access permissions */
unsigned short quotalen; /* length added to quota */
unsigned short datalen; /* payload data length
diff --git a/security/keys/key.c b/security/keys/key.c
index 0a6e741805d6..bbc594a0cb21 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -6,6 +6,7 @@
*/

#include <linux/export.h>
+#include <linux/cell.h>
#include <linux/init.h>
#include <linux/poison.h>
#include <linux/sched.h>
@@ -331,6 +332,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->datalen = type->def_datalen;
key->uid = uid;
key->gid = gid;
+ key->cell_id = cred_cell_id(cred);
key->perm = perm;
key->expiry = TIME64_MAX;
key->restrict_link = restrict_link;
diff --git a/security/keys/permission.c b/security/keys/permission.c
index 4a61f804e80f..7b367c59cd3f 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -6,6 +6,7 @@
*/

#include <linux/export.h>
+#include <linux/cell.h>
#include <linux/security.h>
#include "internal.h"

@@ -50,6 +51,12 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred,

key = key_ref_to_ptr(key_ref);

+ /* Across cells an equal uid, or gid, means nothing. */
+ if (key->cell_id != cred_cell_id(cred)) {
+ kperm = key->perm;
+ goto use_these_perms;
+ }
+
/* use the second 8-bits of permissions for keys the caller owns */
if (uid_eq(key->uid, cred->fsuid)) {
kperm = key->perm >> 16;

--
2.55.0