mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Manuel Huber via B4 Relay <devnull+manuelh.nvidia.com@kernel.org>
To: Fan Wu <wufan@kernel.org>, David Howells <dhowells@redhat.com>,
	 Jarkko Sakkinen <jarkko@kernel.org>
Cc: Christian Brauner <brauner@kernel.org>,
	 Andrew Halaney <andrew@amutable.com>,
	Paul Moore <paul@paul-moore.com>,
	 James Morris <jmorris@namei.org>,
	"Serge E. Hallyn" <serge@hallyn.com>,
	 Jonathan Corbet <corbet@lwn.net>,
	Shuah Khan <skhan@linuxfoundation.org>,
	 Shuah Khan <shuah@kernel.org>,
	Randy Dunlap <rdunlap@infradead.org>,
	 Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	 linux-security-module@vger.kernel.org, keyrings@vger.kernel.org,
	 linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org,
	 bpf@vger.kernel.org, linux-kernel@vger.kernel.org,
	 Manuel Huber <manuelh@nvidia.com>
Subject: [PATCH RFC 1/4] ipe: add the .ipe policy keyring
Date: Mon, 19 Oct 2026 21:40:25 +0000	[thread overview]
Message-ID: <20261019-b4-ipe-keyring-rfc-v1-1-156f0b93e843@nvidia.com> (raw)
In-Reply-To: <20261019-b4-ipe-keyring-rfc-v1-0-156f0b93e843@nvidia.com>

From: Manuel Huber <manuelh@nvidia.com>

Add a dedicated .ipe keyring for IPE policy signature verification,
modeled after the .dm-verity and .bpf keyring implementations.

With this, userspace can provision its own keys into the keyring,
then restrict it and activate it for IPE policy signature verification.

This enables scenarios in which a trusted userspace component generates
an IPE policy, and creates an ephemeral policy-signing key pair,
provisions its public certificate, and restricts the IPE keyring during
the early lifetime of a system. The trusted component can then sign the
IPE policy, destroy the private key, and load and activate the policy.
During that phase, the system is considered in a trusted state whereas
the system transitions into a possibly untrusted state afterwards,
running arbitrary user-provided applications. In such a scenario, the
trusted userspace component could reside on a dm-verity protected
rootfs disk, and applications would reside on additional dm-verity
protected disks. The latter disks would be dynamically attached and
their dm-verity root hashes and/or signatures not known a priori to
launching the system.

A concrete usage scenario could be Kata Containers, which enables
running Kubernetes pods in ephemeral, headless utility VMs, possibly
without systemd. The rootfs disk is static and known beforehand, but
containerd's image layers might be acquired and transported into the
VM using the erofs snapshotter and dynamic block device attachment
using dm-verity.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
---
 Documentation/admin-guide/kernel-parameters.txt |  9 +++
 security/ipe/Makefile                           |  1 +
 security/ipe/ipe.c                              |  2 +
 security/ipe/keyring.c                          | 79 +++++++++++++++++++++++++
 security/ipe/keyring.h                          | 16 +++++
 security/ipe/policy.c                           | 10 ++++
 6 files changed, 117 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index e75344f4e0cd..fd508dd779ed 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2733,6 +2733,15 @@ Kernel parameters
 			Determine whether IPE starts in permissive (0) or
 			enforce (1) mode. The default is enforce.
 
+	ipe.keyring_unsealed=
+			[IPE]
+			Format: <bool>
+			When set to 1, leave the IPE policy keyring
+			unsealed after initialization so userspace can provision
+			keys. Once the keyring is nonempty and restricted, it is
+			searched during policy-signature verification. The default
+			is 0, which creates the keyring restricted and empty.
+
 	ipe.success_audit=
 			[IPE]
 			Format: <bool>
diff --git a/security/ipe/Makefile b/security/ipe/Makefile
index 2ffabfa63fe9..109e736696a5 100644
--- a/security/ipe/Makefile
+++ b/security/ipe/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_SECURITY_IPE) += \
 	hooks.o \
 	fs.o \
 	ipe.o \
+	keyring.o \
 	policy.o \
 	policy_fs.o \
 	policy_parser.o \
diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c
index 495bb765de1b..f5232f850dc2 100644
--- a/security/ipe/ipe.c
+++ b/security/ipe/ipe.c
@@ -7,6 +7,7 @@
 #include "ipe.h"
 #include "eval.h"
 #include "hooks.h"
+#include "keyring.h"
 
 extern const char *const ipe_boot_policy;
 bool ipe_enabled;
@@ -97,4 +98,5 @@ DEFINE_LSM(ipe) = {
 	.init = ipe_init,
 	.blobs = &ipe_blobs,
 	.initcall_fs = ipe_init_securityfs,
+	.initcall_late = ipe_keyring_init,
 };
diff --git a/security/ipe/keyring.c b/security/ipe/keyring.c
new file mode 100644
index 000000000000..ea8d164b62a6
--- /dev/null
+++ b/security/ipe/keyring.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ */
+
+#include <linux/cred.h>
+#include <linux/err.h>
+#include <linux/key.h>
+#include <linux/moduleparam.h>
+
+#include "ipe.h"
+#include "keyring.h"
+
+static struct key *ipe_keyring __ro_after_init;
+
+static bool ipe_keyring_unsealed __ro_after_init;
+
+/* Set the right module name for built-in parameters. */
+#ifdef KBUILD_MODNAME
+#undef KBUILD_MODNAME
+#define KBUILD_MODNAME "ipe"
+#endif
+
+module_param_named(keyring_unsealed, ipe_keyring_unsealed, bool, 0444);
+MODULE_PARM_DESC(keyring_unsealed, "Leave the IPE keyring unsealed");
+
+/**
+ * ipe_keyring_lookup() - Get the IPE keyring if it is ready for use.
+ *
+ * Return: A borrowed pointer to the IPE keyring if it is nonempty and
+ * restricted, or %NULL otherwise. The keyring has system lifetime.
+ */
+struct key *ipe_keyring_lookup(void)
+{
+	if (!ipe_keyring)
+		return NULL;
+
+	if (!READ_ONCE(ipe_keyring->keys.nr_leaves_on_tree) ||
+	    !READ_ONCE(ipe_keyring->restrict_link))
+		return NULL;
+
+	return ipe_keyring;
+}
+
+/**
+ * ipe_keyring_init() - Allocate and configure the IPE keyring.
+ *
+ * Return: Always %0. A failure leaves IPE without its dedicated keyring.
+ */
+int __init ipe_keyring_init(void)
+{
+	struct key *keyring;
+	int rc;
+
+	keyring = keyring_alloc(".ipe", GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
+				current_cred(),
+				KEY_POS_SEARCH |
+				KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE |
+				KEY_USR_SEARCH | KEY_USR_SETATTR,
+				KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
+	if (IS_ERR(keyring)) {
+		pr_err("failed to allocate keyring: %ld\n", PTR_ERR(keyring));
+		return 0;
+	}
+
+	if (!ipe_keyring_unsealed) {
+		rc = keyring_restrict(make_key_ref(keyring, true), NULL, NULL);
+		if (rc) {
+			pr_err("failed to restrict keyring: %d\n", rc);
+			key_revoke(keyring);
+			key_put(keyring);
+			return 0;
+		}
+	}
+
+	ipe_keyring = keyring;
+
+	return 0;
+}
diff --git a/security/ipe/keyring.h b/security/ipe/keyring.h
new file mode 100644
index 000000000000..3d450a465511
--- /dev/null
+++ b/security/ipe/keyring.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ */
+
+#ifndef _IPE_KEYRING_H
+#define _IPE_KEYRING_H
+
+#include <linux/init.h>
+
+struct key;
+
+int __init ipe_keyring_init(void);
+struct key *ipe_keyring_lookup(void);
+
+#endif /* _IPE_KEYRING_H */
diff --git a/security/ipe/policy.c b/security/ipe/policy.c
index e542329726bc..abc1ff9ac230 100644
--- a/security/ipe/policy.c
+++ b/security/ipe/policy.c
@@ -9,6 +9,7 @@
 #include "ipe.h"
 #include "eval.h"
 #include "fs.h"
+#include "keyring.h"
 #include "policy.h"
 #include "policy_parser.h"
 #include "audit.h"
@@ -160,6 +161,7 @@ struct ipe_policy *ipe_new_policy(const char *text, size_t textlen,
 				  const char *pkcs7, size_t pkcs7len)
 {
 	struct ipe_policy *new = NULL;
+	struct key *keyring;
 	int rc = 0;
 
 	new = kzalloc_obj(*new);
@@ -189,6 +191,14 @@ struct ipe_policy *ipe_new_policy(const char *text, size_t textlen,
 						    VERIFYING_UNSPECIFIED_SIGNATURE,
 						    set_pkcs7_data, new);
 #endif
+		if (rc == -ENOKEY || rc == -EKEYREJECTED) {
+			keyring = ipe_keyring_lookup();
+			if (keyring)
+				rc = verify_pkcs7_signature(NULL, 0, new->pkcs7,
+							    pkcs7len, keyring,
+							    VERIFYING_UNSPECIFIED_SIGNATURE,
+							    set_pkcs7_data, new);
+		}
 		if (rc)
 			goto err;
 	} else {

-- 
2.53.0



  reply	other threads:[~2026-10-19 21:40 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-19 21:40 [PATCH RFC 0/4] IPE: add a dedicated " Manuel Huber via B4 Relay
2026-10-19 21:40 ` Manuel Huber via B4 Relay [this message]
2026-10-19 21:52   ` [PATCH RFC 1/4] ipe: add the .ipe " Randy Dunlap
2026-10-19 23:15   ` Fan Wu
2026-10-21 13:54     ` Christian Brauner
2026-10-21 16:51       ` Paul Moore
2026-10-22 10:18         ` Christian Brauner
2026-10-22 17:18           ` Paul Moore
2026-10-26 12:57             ` luca.boccassi
2026-10-27 11:07               ` Luca Boccassi
2026-10-28 12:42                 ` James Bottomley
2026-10-28 14:26                   ` Luca Boccassi
2026-10-28 16:14                     ` James Bottomley
2026-10-28 19:03                       ` Luca Boccassi
2026-10-22 18:01     ` Manuel Huber
2026-10-22 20:25       ` Fan Wu
2026-10-23 11:59         ` Christian Brauner
2026-10-27 20:12     ` Manuel Huber
2026-10-27 20:51       ` Fan Wu
2026-10-19 21:40 ` [PATCH RFC 2/4] keys: add KEY_SPEC_IPE_KEYRING Manuel Huber via B4 Relay
2026-10-19 23:24   ` Fan Wu
2026-10-21 13:51     ` Christian Brauner
2026-10-19 21:40 ` [PATCH RFC 3/4] Documentation: ipe: document the IPE keyring Manuel Huber via B4 Relay
2026-10-19 21:40 ` [PATCH RFC 4/4] selftests/ipe: test the IPE policy keyring Manuel Huber via B4 Relay
2026-10-19 23:28   ` Fan Wu
2026-10-22 17:22     ` Manuel Huber
2026-10-19 21:54 ` [PATCH RFC 0/4] IPE: add a dedicated " Jarkko Sakkinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261019-b4-ipe-keyring-rfc-v1-1-156f0b93e843@nvidia.com \
    --to=devnull+manuelh.nvidia.com@kernel.org \
    --cc=andrew@amutable.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=brauner@kernel.org \
    --cc=corbet@lwn.net \
    --cc=daniel@iogearbox.net \
    --cc=dhowells@redhat.com \
    --cc=jarkko@kernel.org \
    --cc=jmorris@namei.org \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=manuelh@nvidia.com \
    --cc=paul@paul-moore.com \
    --cc=rdunlap@infradead.org \
    --cc=serge@hallyn.com \
    --cc=shuah@kernel.org \
    --cc=skhan@linuxfoundation.org \
    --cc=wufan@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®