* [PATCH v2 0/3] IPE: add a dedicated policy keyring
@ 2026-10-29 0:30 ` Manuel Huber via B4 Relay
0 siblings, 0 replies; 11+ messages in thread
From: Manuel Huber @ 2026-10-29 0:30 UTC (permalink / raw)
To: Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, keyrings,
linux-doc, linux-kernel, kexec, Manuel Huber
Add a dedicated ".ipe" keyring for IPE policy-signature verification,
allowing userspace to provision IPE-specific policy-signing certificates.
Systems that do not provision the keyring retain their existing behavior.
This series is based on commit 48f936e302a9 ("ipe: update the project and
test suite links") from ipe/next. The BPF, dm-verity, and fs-verity
well-known key IDs are now in mainline [1]; KEY_SPEC_IPE_KEYRING follows
these IDs at -12. The series should be rebased once that work is available
in ipe/next.
IPE currently checks the keyring's entry count directly. A separate
keys RFC proposes keyring_is_empty() to encapsulate this check [2].
This series does not depend on that RFC; it should use the helper if
available in the submission base.
Testing:
- Built x86_64 kernels with GCC 15.2.0 and Clang/LLD 21.1.8.
- Passed all 33 in-tree IPE parser KUnit cases under QEMU/KVM.
- Passed all 2,364 IPE CI cases under QEMU/KVM, including eight new
.ipe keyring cases [3]. The CI changes are in draft PR [4].
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=62c457528529
[2] https://lore.kernel.org/r/20261016215326.4110064-5-jarkko@kernel.org
[3] The CI run used a local compatibility adjustment to locate
usr/gen_init_cpio on this kernel base.
[4] https://github.com/Integrity-Policy-Enforcement/ci/pull/4
Signed-off-by: Manuel Huber <manuelh@nvidia.com>
---
Changes in v2:
- Drop the RFC designation.
- Replace ipe.keyring_unsealed with default-off CONFIG_SECURITY_IPE_KEYRING;
leave provisioning and restriction of the enabled keyring to userspace.
- Require restrict_link_reject before using .ipe for policy verification.
- Access the keyring directly instead of through a lookup helper, and panic
if keyring allocation fails.
- Explain the per-guest signing use case and the reason for avoiding a
static private key in guest build artifacts.
- Retain the well-known key ID commit, but refine its commit message.
- Define the IPE acronym in kernel-parameters.txt.
- Document the userspace-provisioned threat model and kexec requirements.
- Drop the kselftest commit; instead, add tests to IPE CI's policy_signature
batch [4].
- Link to v1: https://lore.kernel.org/r/20261019-b4-ipe-keyring-rfc-v1-0-156f0b93e843@nvidia.com
---
Manuel Huber (3):
ipe: add the .ipe policy keyring
keys: add KEY_SPEC_IPE_KEYRING
Documentation: ipe: document the IPE keyring
Documentation/admin-guide/LSM/ipe.rst | 77 ++++++++++++++++++++++++-
Documentation/admin-guide/kernel-parameters.txt | 1 +
Documentation/security/ipe.rst | 19 ++++--
Documentation/security/keys/core.rst | 12 ++++
include/linux/key.h | 2 +
include/uapi/linux/keyctl.h | 1 +
security/ipe/Kconfig | 16 +++++
security/ipe/Makefile | 2 +
security/ipe/ipe.c | 4 ++
security/ipe/keyring.c | 32 ++++++++++
security/ipe/keyring.h | 17 ++++++
security/ipe/policy.c | 17 ++++++
security/keys/process_keys.c | 23 ++++++++
13 files changed, 217 insertions(+), 6 deletions(-)
---
base-commit: 48f936e302a9c48cfc032eb5944c3a6246bc9043
change-id: 20261019-b4-ipe-keyring-rfc-b93b9ae129a2
Best regards,
--
Manuel Huber <manuelh@nvidia.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 0/3] IPE: add a dedicated policy keyring
@ 2026-10-29 0:30 ` Manuel Huber via B4 Relay
0 siblings, 0 replies; 11+ messages in thread
From: Manuel Huber via B4 Relay @ 2026-10-29 0:30 UTC (permalink / raw)
To: Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, keyrings,
linux-doc, linux-kernel, kexec, Manuel Huber
Add a dedicated ".ipe" keyring for IPE policy-signature verification,
allowing userspace to provision IPE-specific policy-signing certificates.
Systems that do not provision the keyring retain their existing behavior.
This series is based on commit 48f936e302a9 ("ipe: update the project and
test suite links") from ipe/next. The BPF, dm-verity, and fs-verity
well-known key IDs are now in mainline [1]; KEY_SPEC_IPE_KEYRING follows
these IDs at -12. The series should be rebased once that work is available
in ipe/next.
IPE currently checks the keyring's entry count directly. A separate
keys RFC proposes keyring_is_empty() to encapsulate this check [2].
This series does not depend on that RFC; it should use the helper if
available in the submission base.
Testing:
- Built x86_64 kernels with GCC 15.2.0 and Clang/LLD 21.1.8.
- Passed all 33 in-tree IPE parser KUnit cases under QEMU/KVM.
- Passed all 2,364 IPE CI cases under QEMU/KVM, including eight new
.ipe keyring cases [3]. The CI changes are in draft PR [4].
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=62c457528529
[2] https://lore.kernel.org/r/20261016215326.4110064-5-jarkko@kernel.org
[3] The CI run used a local compatibility adjustment to locate
usr/gen_init_cpio on this kernel base.
[4] https://github.com/Integrity-Policy-Enforcement/ci/pull/4
Signed-off-by: Manuel Huber <manuelh@nvidia.com>
---
Changes in v2:
- Drop the RFC designation.
- Replace ipe.keyring_unsealed with default-off CONFIG_SECURITY_IPE_KEYRING;
leave provisioning and restriction of the enabled keyring to userspace.
- Require restrict_link_reject before using .ipe for policy verification.
- Access the keyring directly instead of through a lookup helper, and panic
if keyring allocation fails.
- Explain the per-guest signing use case and the reason for avoiding a
static private key in guest build artifacts.
- Retain the well-known key ID commit, but refine its commit message.
- Define the IPE acronym in kernel-parameters.txt.
- Document the userspace-provisioned threat model and kexec requirements.
- Drop the kselftest commit; instead, add tests to IPE CI's policy_signature
batch [4].
- Link to v1: https://lore.kernel.org/r/20261019-b4-ipe-keyring-rfc-v1-0-156f0b93e843@nvidia.com
---
Manuel Huber (3):
ipe: add the .ipe policy keyring
keys: add KEY_SPEC_IPE_KEYRING
Documentation: ipe: document the IPE keyring
Documentation/admin-guide/LSM/ipe.rst | 77 ++++++++++++++++++++++++-
Documentation/admin-guide/kernel-parameters.txt | 1 +
Documentation/security/ipe.rst | 19 ++++--
Documentation/security/keys/core.rst | 12 ++++
include/linux/key.h | 2 +
include/uapi/linux/keyctl.h | 1 +
security/ipe/Kconfig | 16 +++++
security/ipe/Makefile | 2 +
security/ipe/ipe.c | 4 ++
security/ipe/keyring.c | 32 ++++++++++
security/ipe/keyring.h | 17 ++++++
security/ipe/policy.c | 17 ++++++
security/keys/process_keys.c | 23 ++++++++
13 files changed, 217 insertions(+), 6 deletions(-)
---
base-commit: 48f936e302a9c48cfc032eb5944c3a6246bc9043
change-id: 20261019-b4-ipe-keyring-rfc-b93b9ae129a2
Best regards,
--
Manuel Huber <manuelh@nvidia.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 1/3] ipe: add the .ipe policy keyring
2026-10-29 0:30 ` Manuel Huber via B4 Relay
@ 2026-10-29 0:30 ` Manuel Huber via B4 Relay
-1 siblings, 0 replies; 11+ messages in thread
From: Manuel Huber @ 2026-10-29 0:30 UTC (permalink / raw)
To: Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, keyrings,
linux-doc, linux-kernel, kexec, Manuel Huber
Add a dedicated .ipe keyring for IPE policy signature verification.
With this, userspace can provision its own keys into the keyring,
then restrict it and activate it for IPE policy signature verification.
Gate creation of the keyring behind a new by-default disabled
CONFIG_SECURITY_IPE_KEYRING Kconfig option. When created, the keyring
is empty and writable. The keyring is used as a fallback after the
existing policy trust sources only when it is created, non-empty, and
restricted with restrict_link_reject.
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. While in that usage scenario, signing a per-guest
policy with a pre-provisioned policy-signing certificate in the
builtin, secondary, or platform keyrings would be technically possible,
it would require including its corresponding private key in the guest
build artifacts. Making it possible to use an ephemeral,
userspace-provided key avoids shipping a static policy-signing private
key with the guest rootfs.
Signed-off-by: Manuel Huber <manuelh@nvidia.com>
---
Documentation/admin-guide/kernel-parameters.txt | 1 +
security/ipe/Kconfig | 16 +++++++++++++
security/ipe/Makefile | 2 ++
security/ipe/ipe.c | 4 ++++
security/ipe/keyring.c | 30 +++++++++++++++++++++++++
security/ipe/keyring.h | 17 ++++++++++++++
security/ipe/policy.c | 17 ++++++++++++++
7 files changed, 87 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index e75344f4e0cd..9fabbc1c95b6 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -23,6 +23,7 @@
HW Appropriate hardware is enabled.
HYPER_V HYPERV support is enabled.
IMA Integrity measurement architecture is enabled.
+ IPE Integrity Policy Enforcement is enabled.
IP_PNP IP DHCP, BOOTP, or RARP is enabled.
IPV6 IPv6 support is enabled.
ISAPNP ISA PnP code is enabled.
diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig
index a110a6cd848b..5c51da074264 100644
--- a/security/ipe/Kconfig
+++ b/security/ipe/Kconfig
@@ -51,6 +51,22 @@ config IPE_POLICY_SIG_PLATFORM_KEYRING
If unsure, answer Y.
+config SECURITY_IPE_KEYRING
+ bool "IPE policy keyring"
+ default n
+ help
+ This option creates the .ipe keyring, which allows trusted
+ userspace to provision certificates for IPE policy signature
+ verification. IPE uses the keyring only after userspace has added
+ at least one certificate and applied a reject-all restriction.
+
+ Enable this only when the userspace component that provisions and
+ restricts the keyring is part of the system's trusted computing
+ base. Such systems must also prevent unauthorized kexec, which
+ would start a new kernel without preserving the keyring state.
+
+ If unsure, answer N.
+
menu "IPE Trust Providers"
config IPE_PROP_DM_VERITY
diff --git a/security/ipe/Makefile b/security/ipe/Makefile
index 2ffabfa63fe9..78161dfb48ea 100644
--- a/security/ipe/Makefile
+++ b/security/ipe/Makefile
@@ -25,6 +25,8 @@ obj-$(CONFIG_SECURITY_IPE) += \
policy_parser.o \
audit.o \
+obj-$(CONFIG_SECURITY_IPE_KEYRING) += keyring.o
+
clean-files := boot_policy.c \
obj-$(CONFIG_SECURITY_IPE_KUNIT_TEST) += \
diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c
index 495bb765de1b..ee8731eb4070 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,7 @@ DEFINE_LSM(ipe) = {
.init = ipe_init,
.blobs = &ipe_blobs,
.initcall_fs = ipe_init_securityfs,
+#ifdef CONFIG_SECURITY_IPE_KEYRING
+ .initcall_late = ipe_keyring_init,
+#endif
};
diff --git a/security/ipe/keyring.c b/security/ipe/keyring.c
new file mode 100644
index 000000000000..8502f825945d
--- /dev/null
+++ b/security/ipe/keyring.c
@@ -0,0 +1,30 @@
+// 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 "keyring.h"
+
+struct key *ipe_keyring __ro_after_init;
+
+/**
+ * ipe_keyring_init() - Allocate and configure the IPE keyring.
+ *
+ * Return: Always %0.
+ */
+int __init ipe_keyring_init(void)
+{
+ ipe_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(ipe_keyring))
+ panic("failed to allocate \".ipe\" keyring");
+ return 0;
+}
diff --git a/security/ipe/keyring.h b/security/ipe/keyring.h
new file mode 100644
index 000000000000..d9a057a14978
--- /dev/null
+++ b/security/ipe/keyring.h
@@ -0,0 +1,17 @@
+/* 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;
+
+extern struct key *ipe_keyring;
+
+int __init ipe_keyring_init(void);
+
+#endif /* _IPE_KEYRING_H */
diff --git a/security/ipe/policy.c b/security/ipe/policy.c
index e542329726bc..514a1985b5e1 100644
--- a/security/ipe/policy.c
+++ b/security/ipe/policy.c
@@ -4,11 +4,13 @@
*/
#include <linux/errno.h>
+#include <linux/key.h>
#include <linux/verification.h>
#include "ipe.h"
#include "eval.h"
#include "fs.h"
+#include "keyring.h"
#include "policy.h"
#include "policy_parser.h"
#include "audit.h"
@@ -160,6 +162,9 @@ struct ipe_policy *ipe_new_policy(const char *text, size_t textlen,
const char *pkcs7, size_t pkcs7len)
{
struct ipe_policy *new = NULL;
+#ifdef CONFIG_SECURITY_IPE_KEYRING
+ struct key_restriction *restriction;
+#endif
int rc = 0;
new = kzalloc_obj(*new);
@@ -188,6 +193,18 @@ struct ipe_policy *ipe_new_policy(const char *text, size_t textlen,
VERIFY_USE_PLATFORM_KEYRING,
VERIFYING_UNSPECIFIED_SIGNATURE,
set_pkcs7_data, new);
+#endif
+#ifdef CONFIG_SECURITY_IPE_KEYRING
+ if (rc == -ENOKEY || rc == -EKEYREJECTED) {
+ restriction = READ_ONCE(ipe_keyring->restrict_link);
+ if (READ_ONCE(ipe_keyring->keys.nr_leaves_on_tree) &&
+ restriction &&
+ READ_ONCE(restriction->check) == restrict_link_reject)
+ rc = verify_pkcs7_signature(NULL, 0, new->pkcs7,
+ pkcs7len, ipe_keyring,
+ VERIFYING_UNSPECIFIED_SIGNATURE,
+ set_pkcs7_data, new);
+ }
#endif
if (rc)
goto err;
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 1/3] ipe: add the .ipe policy keyring
@ 2026-10-29 0:30 ` Manuel Huber via B4 Relay
0 siblings, 0 replies; 11+ messages in thread
From: Manuel Huber via B4 Relay @ 2026-10-29 0:30 UTC (permalink / raw)
To: Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, keyrings,
linux-doc, linux-kernel, kexec, Manuel Huber
From: Manuel Huber <manuelh@nvidia.com>
Add a dedicated .ipe keyring for IPE policy signature verification.
With this, userspace can provision its own keys into the keyring,
then restrict it and activate it for IPE policy signature verification.
Gate creation of the keyring behind a new by-default disabled
CONFIG_SECURITY_IPE_KEYRING Kconfig option. When created, the keyring
is empty and writable. The keyring is used as a fallback after the
existing policy trust sources only when it is created, non-empty, and
restricted with restrict_link_reject.
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. While in that usage scenario, signing a per-guest
policy with a pre-provisioned policy-signing certificate in the
builtin, secondary, or platform keyrings would be technically possible,
it would require including its corresponding private key in the guest
build artifacts. Making it possible to use an ephemeral,
userspace-provided key avoids shipping a static policy-signing private
key with the guest rootfs.
Signed-off-by: Manuel Huber <manuelh@nvidia.com>
---
Documentation/admin-guide/kernel-parameters.txt | 1 +
security/ipe/Kconfig | 16 +++++++++++++
security/ipe/Makefile | 2 ++
security/ipe/ipe.c | 4 ++++
security/ipe/keyring.c | 30 +++++++++++++++++++++++++
security/ipe/keyring.h | 17 ++++++++++++++
security/ipe/policy.c | 17 ++++++++++++++
7 files changed, 87 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index e75344f4e0cd..9fabbc1c95b6 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -23,6 +23,7 @@
HW Appropriate hardware is enabled.
HYPER_V HYPERV support is enabled.
IMA Integrity measurement architecture is enabled.
+ IPE Integrity Policy Enforcement is enabled.
IP_PNP IP DHCP, BOOTP, or RARP is enabled.
IPV6 IPv6 support is enabled.
ISAPNP ISA PnP code is enabled.
diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig
index a110a6cd848b..5c51da074264 100644
--- a/security/ipe/Kconfig
+++ b/security/ipe/Kconfig
@@ -51,6 +51,22 @@ config IPE_POLICY_SIG_PLATFORM_KEYRING
If unsure, answer Y.
+config SECURITY_IPE_KEYRING
+ bool "IPE policy keyring"
+ default n
+ help
+ This option creates the .ipe keyring, which allows trusted
+ userspace to provision certificates for IPE policy signature
+ verification. IPE uses the keyring only after userspace has added
+ at least one certificate and applied a reject-all restriction.
+
+ Enable this only when the userspace component that provisions and
+ restricts the keyring is part of the system's trusted computing
+ base. Such systems must also prevent unauthorized kexec, which
+ would start a new kernel without preserving the keyring state.
+
+ If unsure, answer N.
+
menu "IPE Trust Providers"
config IPE_PROP_DM_VERITY
diff --git a/security/ipe/Makefile b/security/ipe/Makefile
index 2ffabfa63fe9..78161dfb48ea 100644
--- a/security/ipe/Makefile
+++ b/security/ipe/Makefile
@@ -25,6 +25,8 @@ obj-$(CONFIG_SECURITY_IPE) += \
policy_parser.o \
audit.o \
+obj-$(CONFIG_SECURITY_IPE_KEYRING) += keyring.o
+
clean-files := boot_policy.c \
obj-$(CONFIG_SECURITY_IPE_KUNIT_TEST) += \
diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c
index 495bb765de1b..ee8731eb4070 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,7 @@ DEFINE_LSM(ipe) = {
.init = ipe_init,
.blobs = &ipe_blobs,
.initcall_fs = ipe_init_securityfs,
+#ifdef CONFIG_SECURITY_IPE_KEYRING
+ .initcall_late = ipe_keyring_init,
+#endif
};
diff --git a/security/ipe/keyring.c b/security/ipe/keyring.c
new file mode 100644
index 000000000000..8502f825945d
--- /dev/null
+++ b/security/ipe/keyring.c
@@ -0,0 +1,30 @@
+// 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 "keyring.h"
+
+struct key *ipe_keyring __ro_after_init;
+
+/**
+ * ipe_keyring_init() - Allocate and configure the IPE keyring.
+ *
+ * Return: Always %0.
+ */
+int __init ipe_keyring_init(void)
+{
+ ipe_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(ipe_keyring))
+ panic("failed to allocate \".ipe\" keyring");
+ return 0;
+}
diff --git a/security/ipe/keyring.h b/security/ipe/keyring.h
new file mode 100644
index 000000000000..d9a057a14978
--- /dev/null
+++ b/security/ipe/keyring.h
@@ -0,0 +1,17 @@
+/* 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;
+
+extern struct key *ipe_keyring;
+
+int __init ipe_keyring_init(void);
+
+#endif /* _IPE_KEYRING_H */
diff --git a/security/ipe/policy.c b/security/ipe/policy.c
index e542329726bc..514a1985b5e1 100644
--- a/security/ipe/policy.c
+++ b/security/ipe/policy.c
@@ -4,11 +4,13 @@
*/
#include <linux/errno.h>
+#include <linux/key.h>
#include <linux/verification.h>
#include "ipe.h"
#include "eval.h"
#include "fs.h"
+#include "keyring.h"
#include "policy.h"
#include "policy_parser.h"
#include "audit.h"
@@ -160,6 +162,9 @@ struct ipe_policy *ipe_new_policy(const char *text, size_t textlen,
const char *pkcs7, size_t pkcs7len)
{
struct ipe_policy *new = NULL;
+#ifdef CONFIG_SECURITY_IPE_KEYRING
+ struct key_restriction *restriction;
+#endif
int rc = 0;
new = kzalloc_obj(*new);
@@ -188,6 +193,18 @@ struct ipe_policy *ipe_new_policy(const char *text, size_t textlen,
VERIFY_USE_PLATFORM_KEYRING,
VERIFYING_UNSPECIFIED_SIGNATURE,
set_pkcs7_data, new);
+#endif
+#ifdef CONFIG_SECURITY_IPE_KEYRING
+ if (rc == -ENOKEY || rc == -EKEYREJECTED) {
+ restriction = READ_ONCE(ipe_keyring->restrict_link);
+ if (READ_ONCE(ipe_keyring->keys.nr_leaves_on_tree) &&
+ restriction &&
+ READ_ONCE(restriction->check) == restrict_link_reject)
+ rc = verify_pkcs7_signature(NULL, 0, new->pkcs7,
+ pkcs7len, ipe_keyring,
+ VERIFYING_UNSPECIFIED_SIGNATURE,
+ set_pkcs7_data, new);
+ }
#endif
if (rc)
goto err;
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 2/3] keys: add KEY_SPEC_IPE_KEYRING
2026-10-29 0:30 ` Manuel Huber via B4 Relay
@ 2026-10-29 0:30 ` Manuel Huber via B4 Relay
-1 siblings, 0 replies; 11+ messages in thread
From: Manuel Huber @ 2026-10-29 0:30 UTC (permalink / raw)
To: Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, keyrings,
linux-doc, linux-kernel, kexec, Manuel Huber
The BPF, dm-verity, and fs-verity keyrings have well-known IDs which
allow userspace to directly address them. This commit follows the same
pattern for the .ipe keyring.
This provides a direct interface independent of resolving %:.ipe through
process keyrings and /proc/keys.
Signed-off-by: Manuel Huber <manuelh@nvidia.com>
---
Documentation/security/keys/core.rst | 12 ++++++++++++
include/linux/key.h | 2 ++
include/uapi/linux/keyctl.h | 1 +
security/ipe/keyring.c | 2 ++
security/keys/process_keys.c | 23 +++++++++++++++++++++++
5 files changed, 40 insertions(+)
diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst
index 326b8a973828..64b37817a335 100644
--- a/Documentation/security/keys/core.rst
+++ b/Documentation/security/keys/core.rst
@@ -373,6 +373,18 @@ process making the call::
KEY_SPEC_REQKEY_AUTH_KEY -7 assumed request_key()
authorisation key
+There are also values that refer to a specific kernel keyring rather than to
+anything belonging to the caller. These well-known IDs allow userspace to
+name kernel keyrings directly even when they are not linked into a process
+keyring::
+
+ CONSTANT VALUE KEY REFERENCED
+ ============================== ====== ===========================
+ KEY_SPEC_IPE_KEYRING -12 the ".ipe" keyring
+
+The availability of a subsystem keyring depends on its kernel configuration.
+Looking up an unavailable keyring returns ``ENOKEY``.
+
The main syscalls are:
diff --git a/include/linux/key.h b/include/linux/key.h
index 81b8f05c6898..9c2ac0c70d56 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -440,6 +440,8 @@ extern key_ref_t keyring_search(key_ref_t keyring,
extern int keyring_restrict(key_ref_t keyring, const char *type,
const char *restriction);
+extern void key_register_ipe_keyring(struct key *keyring);
+
extern struct key *key_lookup(key_serial_t id);
static inline key_serial_t key_serial(const struct key *key)
diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h
index 4c8884eea808..e42fca286b15 100644
--- a/include/uapi/linux/keyctl.h
+++ b/include/uapi/linux/keyctl.h
@@ -24,6 +24,7 @@
#define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */
#define KEY_SPEC_REQKEY_AUTH_KEY -7 /* - key ID for assumed request_key auth key */
#define KEY_SPEC_REQUESTOR_KEYRING -8 /* - key ID for request_key() dest keyring */
+#define KEY_SPEC_IPE_KEYRING -12 /* - key ID for the .ipe keyring */
/* request-key default keyrings */
#define KEY_REQKEY_DEFL_NO_CHANGE -1
diff --git a/security/ipe/keyring.c b/security/ipe/keyring.c
index 8502f825945d..14626df46e71 100644
--- a/security/ipe/keyring.c
+++ b/security/ipe/keyring.c
@@ -26,5 +26,7 @@ int __init ipe_keyring_init(void)
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
if (IS_ERR(ipe_keyring))
panic("failed to allocate \".ipe\" keyring");
+ key_register_ipe_keyring(ipe_keyring);
+
return 0;
}
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index a63c46bb2d14..20d6faefb75e 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -22,6 +22,9 @@
/* Session keyring create vs join semaphore */
static DEFINE_MUTEX(key_session_mutex);
+/* IPE keyring reachable through KEY_SPEC_IPE_KEYRING */
+static struct key *ipe_keyring __ro_after_init;
+
/* The root user's tracking struct */
struct key_user root_key_user = {
.usage = REFCOUNT_INIT(3),
@@ -590,6 +593,18 @@ bool lookup_user_key_possessed(const struct key *key,
return key == match_data->raw_data;
}
+/**
+ * key_register_ipe_keyring - Publish the IPE keyring
+ * @keyring: The keyring to publish
+ *
+ * Make @keyring reachable by userspace through the KEY_SPEC_IPE_KEYRING
+ * special key ID. Called once, from an initcall, and never undone.
+ */
+void key_register_ipe_keyring(struct key *keyring)
+{
+ ipe_keyring = keyring;
+}
+
/*
* Look up a key ID given us by userspace with a given permissions mask to get
* the key it refers to.
@@ -741,6 +756,14 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
key_ref = make_key_ref(key, 1);
break;
+ case KEY_SPEC_IPE_KEYRING:
+ key = ipe_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)
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 2/3] keys: add KEY_SPEC_IPE_KEYRING
@ 2026-10-29 0:30 ` Manuel Huber via B4 Relay
0 siblings, 0 replies; 11+ messages in thread
From: Manuel Huber via B4 Relay @ 2026-10-29 0:30 UTC (permalink / raw)
To: Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, keyrings,
linux-doc, linux-kernel, kexec, Manuel Huber
From: Manuel Huber <manuelh@nvidia.com>
The BPF, dm-verity, and fs-verity keyrings have well-known IDs which
allow userspace to directly address them. This commit follows the same
pattern for the .ipe keyring.
This provides a direct interface independent of resolving %:.ipe through
process keyrings and /proc/keys.
Signed-off-by: Manuel Huber <manuelh@nvidia.com>
---
Documentation/security/keys/core.rst | 12 ++++++++++++
include/linux/key.h | 2 ++
include/uapi/linux/keyctl.h | 1 +
security/ipe/keyring.c | 2 ++
security/keys/process_keys.c | 23 +++++++++++++++++++++++
5 files changed, 40 insertions(+)
diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst
index 326b8a973828..64b37817a335 100644
--- a/Documentation/security/keys/core.rst
+++ b/Documentation/security/keys/core.rst
@@ -373,6 +373,18 @@ process making the call::
KEY_SPEC_REQKEY_AUTH_KEY -7 assumed request_key()
authorisation key
+There are also values that refer to a specific kernel keyring rather than to
+anything belonging to the caller. These well-known IDs allow userspace to
+name kernel keyrings directly even when they are not linked into a process
+keyring::
+
+ CONSTANT VALUE KEY REFERENCED
+ ============================== ====== ===========================
+ KEY_SPEC_IPE_KEYRING -12 the ".ipe" keyring
+
+The availability of a subsystem keyring depends on its kernel configuration.
+Looking up an unavailable keyring returns ``ENOKEY``.
+
The main syscalls are:
diff --git a/include/linux/key.h b/include/linux/key.h
index 81b8f05c6898..9c2ac0c70d56 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -440,6 +440,8 @@ extern key_ref_t keyring_search(key_ref_t keyring,
extern int keyring_restrict(key_ref_t keyring, const char *type,
const char *restriction);
+extern void key_register_ipe_keyring(struct key *keyring);
+
extern struct key *key_lookup(key_serial_t id);
static inline key_serial_t key_serial(const struct key *key)
diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h
index 4c8884eea808..e42fca286b15 100644
--- a/include/uapi/linux/keyctl.h
+++ b/include/uapi/linux/keyctl.h
@@ -24,6 +24,7 @@
#define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */
#define KEY_SPEC_REQKEY_AUTH_KEY -7 /* - key ID for assumed request_key auth key */
#define KEY_SPEC_REQUESTOR_KEYRING -8 /* - key ID for request_key() dest keyring */
+#define KEY_SPEC_IPE_KEYRING -12 /* - key ID for the .ipe keyring */
/* request-key default keyrings */
#define KEY_REQKEY_DEFL_NO_CHANGE -1
diff --git a/security/ipe/keyring.c b/security/ipe/keyring.c
index 8502f825945d..14626df46e71 100644
--- a/security/ipe/keyring.c
+++ b/security/ipe/keyring.c
@@ -26,5 +26,7 @@ int __init ipe_keyring_init(void)
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
if (IS_ERR(ipe_keyring))
panic("failed to allocate \".ipe\" keyring");
+ key_register_ipe_keyring(ipe_keyring);
+
return 0;
}
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index a63c46bb2d14..20d6faefb75e 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -22,6 +22,9 @@
/* Session keyring create vs join semaphore */
static DEFINE_MUTEX(key_session_mutex);
+/* IPE keyring reachable through KEY_SPEC_IPE_KEYRING */
+static struct key *ipe_keyring __ro_after_init;
+
/* The root user's tracking struct */
struct key_user root_key_user = {
.usage = REFCOUNT_INIT(3),
@@ -590,6 +593,18 @@ bool lookup_user_key_possessed(const struct key *key,
return key == match_data->raw_data;
}
+/**
+ * key_register_ipe_keyring - Publish the IPE keyring
+ * @keyring: The keyring to publish
+ *
+ * Make @keyring reachable by userspace through the KEY_SPEC_IPE_KEYRING
+ * special key ID. Called once, from an initcall, and never undone.
+ */
+void key_register_ipe_keyring(struct key *keyring)
+{
+ ipe_keyring = keyring;
+}
+
/*
* Look up a key ID given us by userspace with a given permissions mask to get
* the key it refers to.
@@ -741,6 +756,14 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
key_ref = make_key_ref(key, 1);
break;
+ case KEY_SPEC_IPE_KEYRING:
+ key = ipe_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)
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 3/3] Documentation: ipe: document the IPE keyring
2026-10-29 0:30 ` Manuel Huber via B4 Relay
@ 2026-10-29 0:30 ` Manuel Huber via B4 Relay
-1 siblings, 0 replies; 11+ messages in thread
From: Manuel Huber @ 2026-10-29 0:30 UTC (permalink / raw)
To: Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, keyrings,
linux-doc, linux-kernel, kexec, Manuel Huber
Document the .ipe policy-verification keyring with its additive use
after the existing trust sources and the userspace's role in
sustaining trust. Mention requirements for maintaining policy trust
in kexec scenarios.
Signed-off-by: Manuel Huber <manuelh@nvidia.com>
---
Documentation/admin-guide/LSM/ipe.rst | 77 ++++++++++++++++++++++++++++++++++-
Documentation/security/ipe.rst | 19 ++++++---
2 files changed, 90 insertions(+), 6 deletions(-)
diff --git a/Documentation/admin-guide/LSM/ipe.rst b/Documentation/admin-guide/LSM/ipe.rst
index 9e82a2082b94..273f9c3d62e2 100644
--- a/Documentation/admin-guide/LSM/ipe.rst
+++ b/Documentation/admin-guide/LSM/ipe.rst
@@ -150,6 +150,39 @@ Additionally, IPE draws hard security boundary between userspace and
kernelspace. As a result, kernel-level exploits are considered outside
the scope of IPE and mitigation is left to other mechanisms.
+Userspace-provisioned policy trust
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When ``CONFIG_SECURITY_IPE_KEYRING`` is enabled, IPE can authenticate policy
+signatures with certificates provisioned into the ``.ipe`` keyring. This
+differs from IPE's other policy trust sources, whose roots of trust originate
+in the kernel image or firmware: the userspace component that provisions the
+``.ipe`` keyring becomes part of the trusted computing base.
+
+That component must fulfill various requirements. The component must:
+
+- run before any untrusted userspace component runs
+- be backed by code from a trusted location
+- obtain its policy inputs from trusted sources
+- complete provisioning without failures before allowing untrusted code to
+ run. This includes adding all intended certificates, applying the
+ reject-all keyring restriction, and removing the keyring permissions which
+ would allow later modification.
+- destroy the policy-signing private key after signing the policy, if it
+ generated one.
+
+The ``.ipe`` keyring authenticates policy signatures; it does not make the
+active policy immutable or otherwise change authorization for IPE's
+securityfs control interfaces.
+
+Note on Kexec: Kexec bypasses firmware and bootloader trust checks and does
+not preserve the ``.ipe`` keyring or active policy. Deployments must thus
+prevent unauthorized kexec or establish equivalent trust in the replacement
+environment, including any initramfs and command line. Controls that deny
+further kexec loading do not prevent execution of an already-loaded image,
+so any previously loaded image must satisfy the same trust requirements or
+be unloaded before those controls take effect.
+
Policy
------
@@ -238,7 +271,12 @@ unconstrained root, and deploying an "allow all" policy). These
policies must be signed by a certificate that chains to the
``SYSTEM_TRUSTED_KEYRING``, or to the secondary and/or platform keyrings if
``CONFIG_IPE_POLICY_SIG_SECONDARY_KEYRING`` and/or
-``CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING`` are enabled, respectively.
+``CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING`` are enabled, respectively. When
+``CONFIG_SECURITY_IPE_KEYRING`` is enabled, IPE also provides a dedicated
+``.ipe`` keyring for policy-signing certificates that are provisioned by
+userspace, as described below. The ``.ipe`` keyring is an additive final
+fallback and does not replace the configured system trust sources.
+
With openssl, the policy can be signed by::
openssl smime -sign \
@@ -251,6 +289,43 @@ With openssl, the policy can be signed by::
-outform der \
-out "$MY_POLICY.p7b"
+Provisioning the IPE policy keyring
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``.ipe`` keyring allows a system to provision an IPE-specific policy
+signing certificate without embedding it in the kernel or firmware trust
+stores. It is not linked into any process keyring. Userspace addresses it
+directly with the ``KEY_SPEC_IPE_KEYRING`` special key ID (``-12``), which does
+not grant possession of the keyring.
+
+The keyring exists when ``CONFIG_SECURITY_IPE_KEYRING`` is enabled and starts
+empty and writable. If the option is disabled, using
+``KEY_SPEC_IPE_KEYRING`` fails with ``ENOKEY``. Userspace can add a DER-encoded
+X.509 certificate and then apply a reject-all restriction::
+
+ keyctl padd asymmetric "" -12 < policy-signing-key.der
+ keyctl restrict_keyring -12
+
+Both steps are required. IPE ignores the keyring until it is nonempty and its
+restriction is the reject-all restriction installed by the second command, so
+a partially provisioned, mutable keyring is not a trust source. The
+restriction cannot be removed. More than one certificate can be enrolled by
+repeating the ``keyctl padd`` command before restricting the keyring.
+
+Restriction prevents adding keys, but it does not prevent userspace from
+removing keys or otherwise disabling the keyring. To lock it against further
+userspace modification, drop its write and setattr permissions::
+
+ keyctl setperm -12 0x08030000
+
+This retains the permissions needed for verification and inspection.
+Provisioning, restriction, and permission hardening must be completed as
+described in `Userspace-provisioned policy trust`_ before relying on ``.ipe``
+as a trust source.
+
+Once nonempty and restricted, ``.ipe`` is searched after the configured system
+trust sources. An absent, empty, or unrestricted ``.ipe`` keyring is ignored.
+
Deploying the policies is done through securityfs, through the
``new_policy`` node. To deploy a policy, simply cat the file into the
securityfs node::
diff --git a/Documentation/security/ipe.rst b/Documentation/security/ipe.rst
index 4490aed5918a..8afa8172c9ec 100644
--- a/Documentation/security/ipe.rst
+++ b/Documentation/security/ipe.rst
@@ -248,11 +248,20 @@ policy updates have to be done rebootlessly.
To allow an update from an external source, it could be potentially malicious,
so this policy needs to have a way to be identified as trusted. This is
-done via a signature chained to a trust source in the kernel. Arbitrarily,
-this is the ``SYSTEM_TRUSTED_KEYRING``, a keyring that is initially
-populated at kernel compile-time, as this matches the expectation that the
-author of the compiled-in policy described above is the same entity that can
-deploy policy updates.
+done via a signature chained to a trust source in the kernel. IPE can use the
+builtin trusted keyring and, when configured, the secondary and platform
+keyrings. This matches systems where the entity that establishes the kernel or
+firmware trust store is also authorized to deploy policy updates.
+
+When ``CONFIG_SECURITY_IPE_KEYRING`` is enabled, IPE also has a dedicated
+``.ipe`` keyring for deployments that establish an IPE-specific trust anchor
+from userspace. In this case, IPE uses it as a fallback after the configured
+system keyrings, but only when it is nonempty and has a reject-all
+restriction. This model makes the userspace component that provisions and
+restricts ``.ipe`` part of the trusted computing base, for instance a
+component running in early stages of the lifecycle of a system. The
+threat model and provisioning requirements are documented in
+:doc:`/admin-guide/LSM/ipe`.
Anti-Rollback / Anti-Replay
~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 3/3] Documentation: ipe: document the IPE keyring
@ 2026-10-29 0:30 ` Manuel Huber via B4 Relay
0 siblings, 0 replies; 11+ messages in thread
From: Manuel Huber via B4 Relay @ 2026-10-29 0:30 UTC (permalink / raw)
To: Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, keyrings,
linux-doc, linux-kernel, kexec, Manuel Huber
From: Manuel Huber <manuelh@nvidia.com>
Document the .ipe policy-verification keyring with its additive use
after the existing trust sources and the userspace's role in
sustaining trust. Mention requirements for maintaining policy trust
in kexec scenarios.
Signed-off-by: Manuel Huber <manuelh@nvidia.com>
---
Documentation/admin-guide/LSM/ipe.rst | 77 ++++++++++++++++++++++++++++++++++-
Documentation/security/ipe.rst | 19 ++++++---
2 files changed, 90 insertions(+), 6 deletions(-)
diff --git a/Documentation/admin-guide/LSM/ipe.rst b/Documentation/admin-guide/LSM/ipe.rst
index 9e82a2082b94..273f9c3d62e2 100644
--- a/Documentation/admin-guide/LSM/ipe.rst
+++ b/Documentation/admin-guide/LSM/ipe.rst
@@ -150,6 +150,39 @@ Additionally, IPE draws hard security boundary between userspace and
kernelspace. As a result, kernel-level exploits are considered outside
the scope of IPE and mitigation is left to other mechanisms.
+Userspace-provisioned policy trust
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When ``CONFIG_SECURITY_IPE_KEYRING`` is enabled, IPE can authenticate policy
+signatures with certificates provisioned into the ``.ipe`` keyring. This
+differs from IPE's other policy trust sources, whose roots of trust originate
+in the kernel image or firmware: the userspace component that provisions the
+``.ipe`` keyring becomes part of the trusted computing base.
+
+That component must fulfill various requirements. The component must:
+
+- run before any untrusted userspace component runs
+- be backed by code from a trusted location
+- obtain its policy inputs from trusted sources
+- complete provisioning without failures before allowing untrusted code to
+ run. This includes adding all intended certificates, applying the
+ reject-all keyring restriction, and removing the keyring permissions which
+ would allow later modification.
+- destroy the policy-signing private key after signing the policy, if it
+ generated one.
+
+The ``.ipe`` keyring authenticates policy signatures; it does not make the
+active policy immutable or otherwise change authorization for IPE's
+securityfs control interfaces.
+
+Note on Kexec: Kexec bypasses firmware and bootloader trust checks and does
+not preserve the ``.ipe`` keyring or active policy. Deployments must thus
+prevent unauthorized kexec or establish equivalent trust in the replacement
+environment, including any initramfs and command line. Controls that deny
+further kexec loading do not prevent execution of an already-loaded image,
+so any previously loaded image must satisfy the same trust requirements or
+be unloaded before those controls take effect.
+
Policy
------
@@ -238,7 +271,12 @@ unconstrained root, and deploying an "allow all" policy). These
policies must be signed by a certificate that chains to the
``SYSTEM_TRUSTED_KEYRING``, or to the secondary and/or platform keyrings if
``CONFIG_IPE_POLICY_SIG_SECONDARY_KEYRING`` and/or
-``CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING`` are enabled, respectively.
+``CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING`` are enabled, respectively. When
+``CONFIG_SECURITY_IPE_KEYRING`` is enabled, IPE also provides a dedicated
+``.ipe`` keyring for policy-signing certificates that are provisioned by
+userspace, as described below. The ``.ipe`` keyring is an additive final
+fallback and does not replace the configured system trust sources.
+
With openssl, the policy can be signed by::
openssl smime -sign \
@@ -251,6 +289,43 @@ With openssl, the policy can be signed by::
-outform der \
-out "$MY_POLICY.p7b"
+Provisioning the IPE policy keyring
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``.ipe`` keyring allows a system to provision an IPE-specific policy
+signing certificate without embedding it in the kernel or firmware trust
+stores. It is not linked into any process keyring. Userspace addresses it
+directly with the ``KEY_SPEC_IPE_KEYRING`` special key ID (``-12``), which does
+not grant possession of the keyring.
+
+The keyring exists when ``CONFIG_SECURITY_IPE_KEYRING`` is enabled and starts
+empty and writable. If the option is disabled, using
+``KEY_SPEC_IPE_KEYRING`` fails with ``ENOKEY``. Userspace can add a DER-encoded
+X.509 certificate and then apply a reject-all restriction::
+
+ keyctl padd asymmetric "" -12 < policy-signing-key.der
+ keyctl restrict_keyring -12
+
+Both steps are required. IPE ignores the keyring until it is nonempty and its
+restriction is the reject-all restriction installed by the second command, so
+a partially provisioned, mutable keyring is not a trust source. The
+restriction cannot be removed. More than one certificate can be enrolled by
+repeating the ``keyctl padd`` command before restricting the keyring.
+
+Restriction prevents adding keys, but it does not prevent userspace from
+removing keys or otherwise disabling the keyring. To lock it against further
+userspace modification, drop its write and setattr permissions::
+
+ keyctl setperm -12 0x08030000
+
+This retains the permissions needed for verification and inspection.
+Provisioning, restriction, and permission hardening must be completed as
+described in `Userspace-provisioned policy trust`_ before relying on ``.ipe``
+as a trust source.
+
+Once nonempty and restricted, ``.ipe`` is searched after the configured system
+trust sources. An absent, empty, or unrestricted ``.ipe`` keyring is ignored.
+
Deploying the policies is done through securityfs, through the
``new_policy`` node. To deploy a policy, simply cat the file into the
securityfs node::
diff --git a/Documentation/security/ipe.rst b/Documentation/security/ipe.rst
index 4490aed5918a..8afa8172c9ec 100644
--- a/Documentation/security/ipe.rst
+++ b/Documentation/security/ipe.rst
@@ -248,11 +248,20 @@ policy updates have to be done rebootlessly.
To allow an update from an external source, it could be potentially malicious,
so this policy needs to have a way to be identified as trusted. This is
-done via a signature chained to a trust source in the kernel. Arbitrarily,
-this is the ``SYSTEM_TRUSTED_KEYRING``, a keyring that is initially
-populated at kernel compile-time, as this matches the expectation that the
-author of the compiled-in policy described above is the same entity that can
-deploy policy updates.
+done via a signature chained to a trust source in the kernel. IPE can use the
+builtin trusted keyring and, when configured, the secondary and platform
+keyrings. This matches systems where the entity that establishes the kernel or
+firmware trust store is also authorized to deploy policy updates.
+
+When ``CONFIG_SECURITY_IPE_KEYRING`` is enabled, IPE also has a dedicated
+``.ipe`` keyring for deployments that establish an IPE-specific trust anchor
+from userspace. In this case, IPE uses it as a fallback after the configured
+system keyrings, but only when it is nonempty and has a reject-all
+restriction. This model makes the userspace component that provisions and
+restricts ``.ipe`` part of the trusted computing base, for instance a
+component running in early stages of the lifecycle of a system. The
+threat model and provisioning requirements are documented in
+:doc:`/admin-guide/LSM/ipe`.
Anti-Rollback / Anti-Replay
~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 3/3] Documentation: ipe: document the IPE keyring
2026-10-29 0:30 ` Manuel Huber via B4 Relay
(?)
@ 2026-10-29 0:37 ` sashiko-bot
-1 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-10-29 0:37 UTC (permalink / raw)
To: Manuel Huber, Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, kexec
> From: Manuel Huber <manuelh@nvidia.com>
>
> Document the .ipe policy-verification keyring with its additive use
> after the existing trust sources and the userspace's role in
> sustaining trust. Mention requirements for maintaining policy trust
> in kexec scenarios.
>
> Signed-off-by: Manuel Huber <manuelh@nvidia.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261029-b4-ipe-keyring-rfc-v2-0-77727b205844@nvidia.com?part=3
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/3] keys: add KEY_SPEC_IPE_KEYRING
2026-10-29 0:30 ` Manuel Huber via B4 Relay
(?)
@ 2026-10-29 0:50 ` sashiko-bot
-1 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-10-29 0:50 UTC (permalink / raw)
To: Manuel Huber, Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, keyrings,
kexec
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] keys: KEY_SPEC_IPE_KEYRING uses -12 assuming nonexistent keyring IDs
--
commit 44da1efd13cdd5eb92238870e4d4626fe42f170e
Author: Manuel Huber <manuelh@nvidia.com>
keys: add KEY_SPEC_IPE_KEYRING
This commit adds the KEY_SPEC_IPE_KEYRING (-12) special key ID so that
userspace can directly reference the .ipe keyring via lookup_user_key()
without resolving it through process keyrings or /proc/keys.
> keys: add KEY_SPEC_IPE_KEYRING
>
> The BPF, dm-verity, and fs-verity keyrings have well-known IDs which
> allow userspace to directly address them. This commit follows the same
> pattern for the .ipe keyring.
>
> This provides a direct interface independent of resolving %:.ipe through
> process keyrings and /proc/keys.
>
> Signed-off-by: Manuel Huber <manuelh@nvidia.com>
>
> diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst
> index 326b8a9738289..64b37817a3356 100644
> --- a/Documentation/security/keys/core.rst
> +++ b/Documentation/security/keys/core.rst
> @@ -373,6 +373,18 @@ process making the call::
> KEY_SPEC_REQKEY_AUTH_KEY -7 assumed request_key()
> authorisation key
>
> +There are also values that refer to a specific kernel keyring rather than to
> +anything belonging to the caller. These well-known IDs allow userspace to
> +name kernel keyrings directly even when they are not linked into a process
> +keyring::
> +
> + CONSTANT VALUE KEY REFERENCED
> + ============================== ====== ===========================
> + KEY_SPEC_IPE_KEYRING -12 the ".ipe" keyring
> +
> +The availability of a subsystem keyring depends on its kernel configuration.
> +Looking up an unavailable keyring returns ``ENOKEY``.
> +
>
> The main syscalls are:
>
[ ... ]
> diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h
> index 4c8884eea8084..e42fca286b156 100644
> --- a/include/uapi/linux/keyctl.h
> +++ b/include/uapi/linux/keyctl.h
> @@ -24,6 +24,7 @@
> #define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */
> #define KEY_SPEC_REQKEY_AUTH_KEY -7 /* - key ID for assumed request_key auth key */
> #define KEY_SPEC_REQUESTOR_KEYRING -8 /* - key ID for request_key() dest keyring */
> +#define KEY_SPEC_IPE_KEYRING -12 /* - key ID for the .ipe keyring */
[Severity: Medium]
The commit message states that the BPF, dm-verity, and fs-verity keyrings
have well-known IDs, and defines KEY_SPEC_IPE_KEYRING as -12 immediately
after KEY_SPEC_REQUESTOR_KEYRING (-8) in include/uapi/linux/keyctl.h.
However, in the kernel tree, none of the BPF, dm-verity, or fs-verity
keyrings have KEY_SPEC_* IDs in include/uapi/linux/keyctl.h,
Documentation/security/keys/core.rst, or lookup_user_key() in
security/keys/process_keys.c.
This leaves an unexplained gap (-9 through -11) in the UAPI numbering and
makes KEY_SPEC_IPE_KEYRING (-12) the sole entry in the kernel keyring table
in Documentation/security/keys/core.rst.
Was this patch based on an unmerged series that assigned -9, -10, and -11 to
those keyrings, and should the numbering and commit description be adjusted
to match the current tree?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261029-b4-ipe-keyring-rfc-v2-0-77727b205844@nvidia.com?part=2
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 1/3] ipe: add the .ipe policy keyring
2026-10-29 0:30 ` Manuel Huber via B4 Relay
(?)
@ 2026-10-29 0:50 ` sashiko-bot
-1 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-10-29 0:50 UTC (permalink / raw)
To: Manuel Huber, Fan Wu, David Howells, Jarkko Sakkinen
Cc: Christian Brauner, Andrew Halaney, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Luca Boccassi, James Bottomley, linux-security-module, kexec
> From: Manuel Huber <manuelh@nvidia.com>
>
> Add a dedicated .ipe keyring for IPE policy signature verification.
> With this, userspace can provision its own keys into the keyring,
> then restrict it and activate it for IPE policy signature verification.
>
> Gate creation of the keyring behind a new by-default disabled
> CONFIG_SECURITY_IPE_KEYRING Kconfig option. When created, the keyring
> is empty and writable. The keyring is used as a fallback after the
> existing policy trust sources only when it is created, non-empty, and
> restricted with restrict_link_reject.
>
> 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
> [ ... ]
> build artifacts. Making it possible to use an ephemeral,
> userspace-provided key avoids shipping a static policy-signing private
> key with the guest rootfs.
>
> Signed-off-by: Manuel Huber <manuelh@nvidia.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261029-b4-ipe-keyring-rfc-v2-0-77727b205844@nvidia.com?part=1
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-10-29 0:50 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29 0:30 [PATCH v2 0/3] IPE: add a dedicated policy keyring Manuel Huber
2026-10-29 0:30 ` Manuel Huber via B4 Relay
2026-10-29 0:30 ` [PATCH v2 1/3] ipe: add the .ipe " Manuel Huber
2026-10-29 0:30 ` Manuel Huber via B4 Relay
2026-10-29 0:50 ` sashiko-bot
2026-10-29 0:30 ` [PATCH v2 2/3] keys: add KEY_SPEC_IPE_KEYRING Manuel Huber
2026-10-29 0:30 ` Manuel Huber via B4 Relay
2026-10-29 0:50 ` sashiko-bot
2026-10-29 0:30 ` [PATCH v2 3/3] Documentation: ipe: document the IPE keyring Manuel Huber
2026-10-29 0:30 ` Manuel Huber via B4 Relay
2026-10-29 0:37 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.