summaryrefslogtreecommitdiff
path: root/security/keys
diff options
context:
space:
mode:
authorAndrew Halaney <andrew@amutable.com>2026-10-08 15:57:35 -0500
committerChristian Brauner <brauner@kernel.org>2026-10-12 23:37:41 +0200
commit1041fca2ee8a9236255c5819d685ec34e89b4928 (patch)
treea593b3ddcda202a34fc24754b87c53d8fe420d90 /security/keys
parent592d26f625acef962aa40d1f22f29388bc05de13 (diff)
keys: add KEY_SPEC_DM_VERITY_KEYRING
The .dm-verity keyring is not linked into any process keyring, so request_key() and KEYCTL_SEARCH cannot find it. Userspace has to scrape /proc/keys for the serial to use. That's not great, one could put in a bogus description containing a newline to confuse userspace further. For example, thanks to AI models, which I run as root but you could show off as any old user: # DESC=$'.dm-verity: 1\n0badf00d I--Q--- 1 perm 082f0000 0 0 keyring .dm-verity' # k=$(echo -n "1234567" | keyctl padd user "$DESC" @s) # keyctl setperm "$k" 0x3f010001 # cat /proc/keys | grep dm-verity 10402023 I------ 2 perm 082f0000 0 0 keyring .dm-verity: empty 12e0bee6 I--Q--- 1 perm 3f010001 0 0 user .dm-verity: 1 0badf00d I--Q--- 1 perm 082f0000 0 0 keyring .dm-verity: 7 0x0badf00d is not a keyring, it is the text inside our user's key description. Telling the two apart needs a KEYCTL_DESCRIBE per row which is annoying to do. i.e.: # keyctl rdescribe 0x10402023 keyring;0;0;082f0000;.dm-verity # keyctl rdescribe 0x0badf00d keyctl_describe: Required key not available Let's just give it a well known identifier, i.e.: # keyctl rdescribe -10 keyring;0;0;082f0000;.dm-verity This is exactly what commit 264d8fd2794f ("bpf, keys: Add a bpf keyring for program signature validation") did, and was the inspiration for this commit minus the spinlock bits required due to dm-verity being a module. Suggested-by: Christian Brauner (Amutable) <brauner@kernel.org> Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> Reviewed-by: Christian Brauner (Amutable) <brauner@kernel.org> Signed-off-by: Andrew Halaney <andrew@amutable.com> Link: https://patch.msgid.link/20261008-ajhalaney-dmverity-key-identifier-v2-1-008456d189cb@amutable.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/process_keys.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 44358388e395..dba3df41638b 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -25,6 +25,10 @@ static DEFINE_MUTEX(key_session_mutex);
/* BPF keyring reachable through KEY_SPEC_BPF_KEYRING */
static struct key *bpf_keyring __ro_after_init;
+/* dm-verity keyring reachable through KEY_SPEC_DM_VERITY_KEYRING */
+static struct key *dm_verity_keyring;
+static DEFINE_SPINLOCK(dm_verity_keyring_lock);
+
/* The root user's tracking struct */
struct key_user root_key_user = {
.usage = REFCOUNT_INIT(3),
@@ -607,6 +611,24 @@ void key_register_bpf_keyring(struct key *keyring)
bpf_keyring = keyring;
}
+/**
+ * key_register_dm_verity_keyring - Publish the keyring for KEY_SPEC_DM_VERITY_KEYRING
+ * @keyring: The keyring to publish, or NULL to withdraw it
+ *
+ * Make @keyring reachable by userspace through the KEY_SPEC_DM_VERITY_KEYRING
+ * special key ID, so that provisioning it does not require scraping its
+ * serial out of /proc/keys first. dm-verity can be unloaded as a module
+ * and the keyring deregistered, as such serialize access with
+ * dm_verity_keyring_lock.
+ */
+void key_register_dm_verity_keyring(struct key *keyring)
+{
+ spin_lock(&dm_verity_keyring_lock);
+ dm_verity_keyring = keyring;
+ spin_unlock(&dm_verity_keyring_lock);
+}
+EXPORT_SYMBOL_GPL(key_register_dm_verity_keyring);
+
/*
* Look up a key ID given us by userspace with a given permissions mask to get
* the key it refers to.
@@ -766,6 +788,17 @@ try_again:
key_ref = make_key_ref(key, 0);
break;
+ case KEY_SPEC_DM_VERITY_KEYRING:
+ spin_lock(&dm_verity_keyring_lock);
+ key = dm_verity_keyring;
+ if (key)
+ __key_get(key);
+ spin_unlock(&dm_verity_keyring_lock);
+ if (!key)
+ goto error;
+ key_ref = make_key_ref(key, 0);
+ break;
+
default:
key_ref = ERR_PTR(-EINVAL);
if (id < 1)