Linux Kernel Selftest development
 help / color / mirror / Atom feed
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 {
> 


  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