From: Fan Wu <wufan@kernel.org>
To: manuelh@nvidia.com, 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
Subject: Re: [PATCH RFC 1/4] ipe: add the .ipe policy keyring
Date: Mon, 19 Oct 2026 16:15:57 -0700 [thread overview]
Message-ID: <702ade20-a2f3-4919-97e6-c72faa89399a@kernel.org> (raw)
In-Reply-To: <20261019-b4-ipe-keyring-rfc-v1-1-156f0b93e843@nvidia.com>
On 10/19/2026 2:40 PM, Manuel Huber via B4 Relay wrote:
> 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.
>
You might need to explain why the existing keyrings, i.e. builtin/secondary/platform cannot be used in your scenario. Like the firmware is not trusted?
> 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.
> +
I would prefer a Kconfig CONFIG_SECURITY_IPE_KEYRING default to N instead, like the fsverity keyring. In the kconfig you can also describe in which cases should this option be turned on.
> 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 \
with Kconfig this can be obj-$(CONFIG_IPE_KEYRING) += 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;
You can remove static here then the other ipe code can directly use the variable instead of a function call.
> +
> +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_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;
You might need to panic here like the fsverity kerying.
> + }
> +
> + 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;
> + }
> + }
This looks kind of awkward, like if unseal is not set, it can create an empty keyring then immediately seal it. I would switch to the fsverity's approach to let userspace seal it.
> +
> + 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);
> + }
With Kconfig this part can be just like the above cases.
Fan
> if (rc)
> goto err;
> } else {
>
next prev parent reply other threads:[~2026-10-19 23:15 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-19 21:40 [PATCH RFC 0/4] IPE: add a dedicated policy keyring Manuel Huber via B4 Relay
2026-10-19 21:40 ` [PATCH RFC 1/4] ipe: add the .ipe " Manuel Huber via B4 Relay
2026-10-19 21:52 ` Randy Dunlap
2026-10-19 23:15 ` Fan Wu [this message]
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-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-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=702ade20-a2f3-4919-97e6-c72faa89399a@kernel.org \
--to=wufan@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 \
/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