summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-27 08:01:30 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-27 08:01:30 -1000
commit62c457528529cdcfa32bc52b331ceca10f3937b6 (patch)
tree996f24181b89b02cbc2afcbe74888590877e9639 /security
parentc60ebc3208b9ce1d8915318347962f7ce1dbd07d (diff)
parent503b65da9a7e5447d91222f62399522f2f62a0fa (diff)
Merge tag 'vfs-7.4-rc1.keyring' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs keyring updates from Christian Brauner: "The kernel has two keyrings that userspace fills with X.509 certificates at boot: .fs-verity for fs-verity built-in signatures and .dm-verity for dm-verity root hash signatures. Neither is linked into any process keyring. Hence, request_key() and KEYCTL_SEARCH can't find them. The only way for userspace to identify them is to read their serial number out of /proc/keys. That is not just a large file often the names can also be reused and appear multiple times which allows forging these keyrings. This adds two fixed special key ids, KEY_SPEC_DM_VERITY_KEYRING and KEY_SPEC_FS_VERITY_KEYRING next to KEY_SPEC_BPF_KEYRING. The latter went in through bpf-next this merge window. lookup_user_key() resolves the fixed key ids to the two keyrings. So userspace can add a dm-verity (fixed keyring id: -10) certificate with keyctl padd asymmetric "" -10 < cert.der and seal the keyring with keyctl restrict_keyring -10 without looking anything up first" * tag 'vfs-7.4-rc1.keyring' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: Documentation: keys: document IDs added since KEY_SPEC_REQKEY_AUTH_KEY keys: add KEY_SPEC_FS_VERITY_KEYRING keys: add KEY_SPEC_DM_VERITY_KEYRING
Diffstat (limited to 'security')
-rw-r--r--security/keys/process_keys.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index cf638bf1f7b9..3af71c6322af 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -25,6 +25,13 @@ 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);
+
+/* fs-verity keyring reachable through KEY_SPEC_FS_VERITY_KEYRING */
+static struct key *fs_verity_keyring __ro_after_init;
+
/* The root user's tracking struct */
struct key_user root_key_user = {
.usage = REFCOUNT_INIT(3),
@@ -606,6 +613,38 @@ 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);
+
+/**
+ * key_register_fs_verity_keyring - Publish the keyring for KEY_SPEC_FS_VERITY_KEYRING
+ * @keyring: The keyring to publish
+ *
+ * Make @keyring reachable by userspace through the KEY_SPEC_FS_VERITY_KEYRING
+ * special key ID, so that provisioning it does not require scraping its
+ * serial out of /proc/keys first. Called once, from an initcall, and never
+ * undone.
+ */
+void key_register_fs_verity_keyring(struct key *keyring)
+{
+ fs_verity_keyring = keyring;
+}
+
/*
* Look up a key ID given us by userspace with a given permissions mask to get
* the key it refers to.
@@ -765,6 +804,25 @@ 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;
+
+ case KEY_SPEC_FS_VERITY_KEYRING:
+ key = fs_verity_keyring;
+ if (!key)
+ goto error;
+ __key_get(key);
+ key_ref = make_key_ref(key, 0);
+ break;
+
default:
key_ref = ERR_PTR(-EINVAL);
if (id < 1)