* Re: [PATCH 1/2] umh, treewide: Explicitly include linux/umh.h where needed
From: Petr Pavlu @ 2026-07-09 9:49 UTC (permalink / raw)
To: Michal Koutný
Cc: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
Dave Hansen, x86, H. Peter Anvin, Philipp Reisner, Lars Ellenberg,
Christoph Böhmwalder, Jens Axboe, Johan Hovold, Alex Elder,
Greg Kroah-Hartman, Rafael J. Wysocki, Michal Januszewski,
Helge Deller, Alexander Viro, Christian Brauner, Jan Kara,
Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey, Mark Fasheh,
Joel Becker, Joseph Qi, Tejun Heo, Johannes Weiner,
Luis Chamberlain, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
Pavel Machek, Len Brown, Andrew Morton, Danilo Krummrich,
Nikolay Aleksandrov, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, David Howells,
Jarkko Sakkinen, Paul Moore, James Morris, Serge E. Hallyn,
Kentaro Takeda, Tetsuo Handa, linux-edac, linux-kernel, drbd-dev,
linux-block, greybus-dev, linuxppc-dev, linux-acpi, linux-fbdev,
dri-devel, linux-fsdevel, linux-nfs, ocfs2-devel, cgroups,
linux-modules, linux-pm, driver-core, bridge, netdev, keyrings,
linux-security-module
In-Reply-To: <ak6STbqZd-Q-c56v@localhost.localdomain>
On 7/8/26 8:13 PM, Michal Koutný wrote:
> Hi Petr.
>
> On Wed, Jul 08, 2026 at 05:44:29PM +0200, Petr Pavlu <petr.pavlu@suse.com> wrote:
>> diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
>> index a4337c9b5287..60eb994c32ae 100644
>> --- a/kernel/cgroup/cgroup-v1.c
>> +++ b/kernel/cgroup/cgroup-v1.c
>> @@ -16,6 +16,7 @@
>> #include <linux/pid_namespace.h>
>> #include <linux/cgroupstats.h>
>> #include <linux/fs_parser.h>
>> +#include <linux/umh.h>
>>
>> #include <trace/events/cgroup.h>
>
> There is kmod.h in here too but it's unnecessary, no module lazy loading
> in this code.
You're right. I'll remove the kmod.h include from
kernel/cgroup/cgroup-v1.c. I went through all the files again and it
seems this was the only place I missed.
--
Thanks,
Petr
^ permalink raw reply
* Re: [PATCH v2 1/9] security: add LSM blob and hooks for namespaces
From: Mickaël Salaün @ 2026-07-09 9:12 UTC (permalink / raw)
To: Paul Moore
Cc: Christian Brauner, Günther Noack, Serge E . Hallyn,
Daniel Durning, Jonathan Corbet, Justin Suess, Lennart Poettering,
Mikhail Ivanov, Nicolas Bouchinet, Shervin Oloumi, Tingmao Wang,
kernel-team, linux-fsdevel, linux-kernel, linux-security-module
In-Reply-To: <3d4fe99cd1665a1be0b36636aeeaf4ab@paul-moore.com>
On Wed, Jul 08, 2026 at 11:22:17PM -0400, Paul Moore wrote:
> On May 27, 2026 =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net> wrote:
> >
> > All namespace types now share the same ns_common infrastructure. Extend
> > this to include a security blob so LSMs can start managing namespaces
> > uniformly without having to add one-off hooks or security fields to
> > every individual namespace type.
> >
> > Add a ns_security pointer to ns_common and the corresponding lbs_ns blob
> > size to lsm_blob_sizes. Allocation and freeing hooks are called from the
> > common __ns_common_init() and __ns_common_free() paths so every
> > namespace type gets covered in one go. All information about the
> > namespace type and the appropriate casting helpers to get at the
> > containing namespace are available via ns_common making it
> > straightforward for LSMs to differentiate when they need to.
> >
> > A namespace_install hook is called from validate_ns() during setns(2)
> > giving LSMs a chance to enforce policy on namespace transitions. The
> > LSM check runs before ns->ops->install() so the security module can deny
> > the operation before any type-specific installation effects.
> >
> > Individual namespace types can still have their own specialized security
> > hooks when needed. This is just the common baseline that makes it easy
> > to track and manage namespaces from the security side without requiring
> > every namespace type to reinvent the wheel.
> >
> > Cc: Günther Noack <gnoack@google.com>
> > Cc: Paul Moore <paul@paul-moore.com>
> > Cc: Serge E. Hallyn <serge@hallyn.com>
> > Signed-off-by: Christian Brauner <brauner@kernel.org>
> > Link: https://lore.kernel.org/r/20260216-work-security-namespace-v1-1-075c28758e1f@kernel.org
> > Signed-off-by: Mickaël Salaün <mic@digikod.net>
> > ---
> > Changes since v1:
> > https://lore.kernel.org/r/20260312100444.2609563-2-mic@digikod.net
> > - Move security_namespace_install() before ns->ops->install() in
> > validate_ns() (suggested by Christian Brauner).
> > - Only call proc_free_inum() on security_namespace_alloc() failure
> > when inum was allocated by this function (suggested by Christian
> > Brauner).
> > - Fix anonymous mount namespace blob leak: move
> > security_namespace_free() into __ns_common_free() and make
> > proc_free_inum() conditional on dynamically allocated inums
> > via MNT_NS_INO_SPECIAL_MAX, so free_mnt_ns() can call
> > ns_common_free() unconditionally (suggested by Christian
> > Brauner). Also reported by Daniel Durning while working on
> > SELinux support for these hooks:
> > https://lore.kernel.org/r/20260318201747.4477-1-danieldurning.work@gmail.com
> > - Rename security_namespace_alloc() to security_namespace_init()
> > to match the caller-name convention and reflect that the hook
> > initialises LSM state attached to a constructed ns_common rather
> > than allocating the ns_common itself (suggested by Paul Moore).
> > - Refine the security_namespace_free() kdoc to clarify that
> > RCU-safe blob freeing is required only if an LSM exposes data
> > within the blob to concurrent RCU readers, and document that
> > the blob memory itself is released with kfree() after the
> > namespace_free hooks return (suggested by Paul Moore).
> > - Günther Noack's v1 Reviewed-by is not carried forward to v2:
> > the validate_ns() reordering and the anonymous-mount-namespace
> > blob-leak fix are semantic changes that were not part of his
> > review. Cc'd instead.
> > ---
> > fs/namespace.c | 3 +-
> > include/linux/lsm_hook_defs.h | 3 ++
> > include/linux/lsm_hooks.h | 1 +
> > include/linux/ns/ns_common_types.h | 3 ++
> > include/linux/security.h | 20 ++++++++
> > include/uapi/linux/nsfs.h | 1 +
> > kernel/nscommon.c | 17 ++++++-
> > kernel/nsproxy.c | 6 +++
> > security/lsm_init.c | 2 +
> > security/security.c | 77 ++++++++++++++++++++++++++++++
> > 10 files changed, 130 insertions(+), 3 deletions(-)
> >
> > diff --git a/fs/namespace.c b/fs/namespace.c
> > index fe919abd2f01..031ef3fafa48 100644
> > --- a/fs/namespace.c
> > +++ b/fs/namespace.c
> > @@ -4179,8 +4179,7 @@ static void dec_mnt_namespaces(struct ucounts *ucounts)
> >
> > static void free_mnt_ns(struct mnt_namespace *ns)
> > {
> > - if (!is_anon_ns(ns))
> > - ns_common_free(ns);
> > + ns_common_free(ns);
> > dec_mnt_namespaces(ns->ucounts);
> > mnt_ns_tree_remove(ns);
> > }
>
> ...
>
> > diff --git a/kernel/nscommon.c b/kernel/nscommon.c
> > index 3166c1fd844a..e72426bba29a 100644
> > --- a/kernel/nscommon.c
> > +++ b/kernel/nscommon.c
> > @@ -4,6 +4,7 @@
> > #include <linux/ns_common.h>
> > #include <linux/nstree.h>
> > #include <linux/proc_ns.h>
> > +#include <linux/security.h>
> > #include <linux/user_namespace.h>
> > #include <linux/vfsdebug.h>
> >
> > @@ -59,6 +60,9 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_ope
> >
> > refcount_set(&ns->__ns_ref, 1);
> > ns->stashed = NULL;
> > +#ifdef CONFIG_SECURITY
> > + ns->ns_security = NULL;
> > +#endif
> > ns->ops = ops;
> > ns->ns_id = 0;
> > ns->ns_type = ns_type;
> > @@ -77,6 +81,14 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_ope
> > ret = proc_alloc_inum(&ns->inum);
> > if (ret)
> > return ret;
> > +
> > + ret = security_namespace_init(ns);
> > + if (ret) {
> > + if (!inum)
> > + proc_free_inum(ns->inum);
> > + return ret;
> > + }
> > +
> > /*
> > * Tree ref starts at 0. It's incremented when namespace enters
> > * active use (installed in nsproxy) and decremented when all
> > @@ -91,7 +103,10 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_ope
> >
> > void __ns_common_free(struct ns_common *ns)
> > {
> > - proc_free_inum(ns->inum);
> > + security_namespace_free(ns);
> > +
> > + if (ns->inum > MNT_NS_INO_SPECIAL_MAX)
> > + proc_free_inum(ns->inum);
>
> The ns->inum check in the if-conditional above isn't quite the same as
> the is_anon_ns() check it replaces in free_mnt_ns(). You touch on this
> a bit in the changelog, but that really should be explained in the
> commit description.
>
> ... or honestly, should that change be a separate patch?
I think it's fine, but it's Christian's patch, so I'll let him answer
and propose a new commit description.
>
> > }
> >
> > struct ns_common *__must_check ns_owner(struct ns_common *ns)
> > diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
> > index d9d3d5973bf5..0f1b208d8eef 100644
> > --- a/kernel/nsproxy.c
> > +++ b/kernel/nsproxy.c
> > @@ -385,6 +385,12 @@ static int prepare_nsset(unsigned flags, struct nsset *nsset)
> >
> > static inline int validate_ns(struct nsset *nsset, struct ns_common *ns)
> > {
> > + int ret;
> > +
> > + ret = security_namespace_install(nsset, ns);
> > + if (ret)
> > + return ret;
> > +
> > return ns->ops->install(nsset, ns);
> > }
>
> In the previous revision to the patchset I asked about a
> security_namespace_switch() hook as we don't know if a namespace is
> actually attached to a process until we get to switch_task_namespaces().
> Perhaps that was answered, but I don't recall reading any mail about that
> and I'm not able to uncover any responses on lore.
From the cover letter:
no security_namespace_switch() post-hook is
added in this series: such a hook would only serve LSMs that maintain
per-task state derived from the active namespace set (SELinux-style
state tracking), and no current LSM (including this series) needs that.
Landlock enforces at namespace_install() and namespace_init(), before
the task-to-nsproxy switch. The hook is left for a separate LSM
infrastructure proposal once a concrete user emerges.
This follows the guidance of adding new hooks: there must be at least
one user.
>
> > diff --git a/security/security.c b/security/security.c
> > index 4e999f023651..21cc45d4bbd0 100644
> > --- a/security/security.c
> > +++ b/security/security.c
> > @@ -26,6 +26,7 @@
> > #include <linux/string.h>
> > #include <linux/xattr.h>
> > #include <linux/msg.h>
> > +#include <linux/ns_common.h>
> > #include <linux/overflow.h>
> > #include <linux/perf_event.h>
> > #include <linux/fs.h>
> > @@ -381,6 +382,19 @@ static int lsm_superblock_alloc(struct super_block *sb)
> > GFP_KERNEL);
> > }
> >
> > +/**
> > + * lsm_ns_alloc - allocate a composite namespace blob
> > + * @ns: the namespace that needs a blob
> > + *
> > + * Allocate the namespace blob for all the modules
> > + *
> > + * Returns 0, or -ENOMEM if memory can't be allocated.
> > + */
> > +static int lsm_ns_alloc(struct ns_common *ns)
> > +{
> > + return lsm_blob_alloc(&ns->ns_security, blob_sizes.lbs_ns, GFP_KERNEL);
> > +}
> > +
> > /**
> > * lsm_fill_user_ctx - Fill a user space lsm_ctx structure
> > * @uctx: a userspace LSM context to be filled
> > @@ -3358,6 +3372,69 @@ int security_create_user_ns(const struct cred *cred)
> > return call_int_hook(userns_create, cred);
> > }
> >
> > +/**
> > + * security_namespace_init() - Initialize LSM security data for a namespace
> > + * @ns: the namespace being initialized
> > + *
> > + * Initialize the LSM security blob attached to the namespace. The namespace type
> > + * is available via ns->ns_type, and the owning user namespace (if any)
> > + * via ns->ops->owner(ns).
> > + *
> > + * Return: Returns 0 if successful, otherwise < 0 error code.
> > + */
> > +int security_namespace_init(struct ns_common *ns)
> > +{
> > + int rc;
> > +
> > + rc = lsm_ns_alloc(ns);
> > + if (unlikely(rc))
> > + return rc;
> > +
> > + rc = call_int_hook(namespace_init, ns);
> > + if (unlikely(rc))
> > + security_namespace_free(ns);
> > +
> > + return rc;
> > +}
> > +
> > +/**
> > + * security_namespace_free() - Release LSM security data from a namespace
> > + * @ns: the namespace being freed
> > + *
> > + * Release security data attached to the namespace. Called before the
> > + * namespace structure is freed.
> > + *
> > + * Note: If an LSM exposes data within the security blob to concurrent
> > + * RCU readers, it must use RCU-safe freeing for that data. The blob
> > + * memory itself is released with kfree() after the namespace_free
> > + * hooks return.
>
> I appreciate that you revised the "Note:" based on my previous comments,
> but now it reads just like normal guidance on RCU and object lifetimes.
> Do we need this "Note:" at all?
Indeed, it's normal guidance, I'll remove it.
>
> > + */
> > +void security_namespace_free(struct ns_common *ns)
> > +{
> > + if (!ns->ns_security)
> > + return;
> > +
> > + call_void_hook(namespace_free, ns);
> > +
> > + kfree(ns->ns_security);
> > + ns->ns_security = NULL;
> > +}
> > +
> > +/**
> > + * security_namespace_install() - Check permission to install a namespace
> > + * @nsset: the target nsset being configured
> > + * @ns: the namespace being installed
> > + *
> > + * Check permission before allowing a namespace to be installed into the
> > + * process's set of namespaces via setns(2).
> > + *
> > + * Return: Returns 0 if permission is granted, otherwise < 0 error code.
> > + */
> > +int security_namespace_install(const struct nsset *nsset, struct ns_common *ns)
> > +{
> > + return call_int_hook(namespace_install, nsset, ns);
> > +}
> > +
> > /**
> > * security_ipc_permission() - Check if sysv ipc access is allowed
> > * @ipcp: ipc permission structure
> > --
> > 2.54.0
>
> --
> paul-moore.com
>
^ permalink raw reply
* [RESEND][RFC/discuss] memfd_secret(): opt-in visibility for security monitoring (eBPF/audit)
From: BoxStrikesTeam @ 2026-07-09 5:14 UTC (permalink / raw)
To: rppt@kernel.org, paul@paul-moore.com
Cc: akpm@linux-foundation.org, linux-mm@kvack.org,
linux-security-module@vger.kernel.org, jmorris@namei.org,
serge@hallyn.com
Note:Apologies for the HTML format in the previous send; this is a plain-text resend of the same message.
Paul,
Thanks - I found the Gottsche/inode_init_security_anon() thread and can see it landed. That answers (a) cleanly: labeling exists, policy can be layered on top via SELinux/AppArmor if a site wants alerting on memfd_secret() creation. Good to have that confirmed as already solved.
On (b), let me push on it a bit further, because I think it's worth spelling out explicitly rather than dropping it.
My concern: as it stands, an unprivileged process can populate a memfd_secret() region and mseal() the mapping, producing memory that is (a) unreadable by any kernel-side introspection path, including root-owned eBPF tracing programs, and (b) can't be coerced back into an inspectable state via mprotect/munmap. From a host-based detection standpoint that's a blind spot an attacker can use to park a payload where a CAP_BPF-privileged monitoring agent - something that in most other respects can inspect any process on the box - simply cannot look, no matter what capabilities it holds.
I understand the objection this invites, and I want to address it directly rather than pretend it isn't there: the memfd_secret() man page is explicit that its ROP protection rests on the absence of any in-kernel primitive for reading this memory. If I'm reading that right, the objection to (b) is that adding any such primitive - however capability-gated - re-creates exactly the artifact a ROP chain would want to call, undermining the "no primitive exists" property regardless of who's nominally allowed to invoke it.
I don't think that objection is wrong, but I'm not sure it's fully dispositive either, and I'd like to hear the maintainers' take on the tradeoff explicitly:
- The ROP threat model assumes an attacker who already has arbitrary kernel code execution (they're calling kernel functions directly). If they have that, they can likely already walk page tables and reconstruct the mapping by hand - the primitive removal raises the bar, but per the design's own caveat ("no 100% guarantee"), it was never advertised as absolute.
- The (b) scenario I'm raising is a different actor: a legitimate, privileged, kernel-mediated monitoring agent (eBPF LSM/tracing program) operating through the normal verifier-checked helper path, not an attacker executing arbitrary kernel code via a ROP chain. Conflating "any code path that can read this memory" with "a gadget a ROP chain can call" may be overly conservative if the new path is narrowly scoped (e.g., a new bpf_probe_read_secretmem() helper, verifier-restricted to CAP_PERFMON|CAP_BPF programs, opt-in per region via a memfd_secret() flag the owning process must set at creation time).
If that distinction doesn't hold up - if any additional kernel-callable read path is considered equally exploitable regardless of gating - I'd genuinely like to understand why, since it would mean the confidentiality guarantee is fundamentally incompatible with any form of authorized introspection, which seems worth stating plainly in the documentation for anyone building EDR/monitoring tooling around eBPF.
Even if (b) is rejected, I believe explicitly documenting that memfd_secret()+mseal() creates an introspection-proof region would be valuable for the security community, so EDR vendors can adjust their threat models accordingly.
Thanks again for engaging with this.
Eneshan Erdoğan Karaca.
^ permalink raw reply
* Re: [PATCH v2 1/9] security: add LSM blob and hooks for namespaces
From: Paul Moore @ 2026-07-09 3:22 UTC (permalink / raw)
To: Mickaël Salaün, Christian Brauner, Günther Noack,
Serge E . Hallyn
Cc: Daniel Durning, Jonathan Corbet, Justin Suess, Lennart Poettering,
Mickaël Salaün, Mikhail Ivanov, Nicolas Bouchinet,
Shervin Oloumi, Tingmao Wang, kernel-team, linux-fsdevel,
linux-kernel, linux-security-module
In-Reply-To: <20260527181127.879771-2-mic@digikod.net>
On May 27, 2026 =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net> wrote:
>
> All namespace types now share the same ns_common infrastructure. Extend
> this to include a security blob so LSMs can start managing namespaces
> uniformly without having to add one-off hooks or security fields to
> every individual namespace type.
>
> Add a ns_security pointer to ns_common and the corresponding lbs_ns blob
> size to lsm_blob_sizes. Allocation and freeing hooks are called from the
> common __ns_common_init() and __ns_common_free() paths so every
> namespace type gets covered in one go. All information about the
> namespace type and the appropriate casting helpers to get at the
> containing namespace are available via ns_common making it
> straightforward for LSMs to differentiate when they need to.
>
> A namespace_install hook is called from validate_ns() during setns(2)
> giving LSMs a chance to enforce policy on namespace transitions. The
> LSM check runs before ns->ops->install() so the security module can deny
> the operation before any type-specific installation effects.
>
> Individual namespace types can still have their own specialized security
> hooks when needed. This is just the common baseline that makes it easy
> to track and manage namespaces from the security side without requiring
> every namespace type to reinvent the wheel.
>
> Cc: Günther Noack <gnoack@google.com>
> Cc: Paul Moore <paul@paul-moore.com>
> Cc: Serge E. Hallyn <serge@hallyn.com>
> Signed-off-by: Christian Brauner <brauner@kernel.org>
> Link: https://lore.kernel.org/r/20260216-work-security-namespace-v1-1-075c28758e1f@kernel.org
> Signed-off-by: Mickaël Salaün <mic@digikod.net>
> ---
> Changes since v1:
> https://lore.kernel.org/r/20260312100444.2609563-2-mic@digikod.net
> - Move security_namespace_install() before ns->ops->install() in
> validate_ns() (suggested by Christian Brauner).
> - Only call proc_free_inum() on security_namespace_alloc() failure
> when inum was allocated by this function (suggested by Christian
> Brauner).
> - Fix anonymous mount namespace blob leak: move
> security_namespace_free() into __ns_common_free() and make
> proc_free_inum() conditional on dynamically allocated inums
> via MNT_NS_INO_SPECIAL_MAX, so free_mnt_ns() can call
> ns_common_free() unconditionally (suggested by Christian
> Brauner). Also reported by Daniel Durning while working on
> SELinux support for these hooks:
> https://lore.kernel.org/r/20260318201747.4477-1-danieldurning.work@gmail.com
> - Rename security_namespace_alloc() to security_namespace_init()
> to match the caller-name convention and reflect that the hook
> initialises LSM state attached to a constructed ns_common rather
> than allocating the ns_common itself (suggested by Paul Moore).
> - Refine the security_namespace_free() kdoc to clarify that
> RCU-safe blob freeing is required only if an LSM exposes data
> within the blob to concurrent RCU readers, and document that
> the blob memory itself is released with kfree() after the
> namespace_free hooks return (suggested by Paul Moore).
> - Günther Noack's v1 Reviewed-by is not carried forward to v2:
> the validate_ns() reordering and the anonymous-mount-namespace
> blob-leak fix are semantic changes that were not part of his
> review. Cc'd instead.
> ---
> fs/namespace.c | 3 +-
> include/linux/lsm_hook_defs.h | 3 ++
> include/linux/lsm_hooks.h | 1 +
> include/linux/ns/ns_common_types.h | 3 ++
> include/linux/security.h | 20 ++++++++
> include/uapi/linux/nsfs.h | 1 +
> kernel/nscommon.c | 17 ++++++-
> kernel/nsproxy.c | 6 +++
> security/lsm_init.c | 2 +
> security/security.c | 77 ++++++++++++++++++++++++++++++
> 10 files changed, 130 insertions(+), 3 deletions(-)
>
> diff --git a/fs/namespace.c b/fs/namespace.c
> index fe919abd2f01..031ef3fafa48 100644
> --- a/fs/namespace.c
> +++ b/fs/namespace.c
> @@ -4179,8 +4179,7 @@ static void dec_mnt_namespaces(struct ucounts *ucounts)
>
> static void free_mnt_ns(struct mnt_namespace *ns)
> {
> - if (!is_anon_ns(ns))
> - ns_common_free(ns);
> + ns_common_free(ns);
> dec_mnt_namespaces(ns->ucounts);
> mnt_ns_tree_remove(ns);
> }
...
> diff --git a/kernel/nscommon.c b/kernel/nscommon.c
> index 3166c1fd844a..e72426bba29a 100644
> --- a/kernel/nscommon.c
> +++ b/kernel/nscommon.c
> @@ -4,6 +4,7 @@
> #include <linux/ns_common.h>
> #include <linux/nstree.h>
> #include <linux/proc_ns.h>
> +#include <linux/security.h>
> #include <linux/user_namespace.h>
> #include <linux/vfsdebug.h>
>
> @@ -59,6 +60,9 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_ope
>
> refcount_set(&ns->__ns_ref, 1);
> ns->stashed = NULL;
> +#ifdef CONFIG_SECURITY
> + ns->ns_security = NULL;
> +#endif
> ns->ops = ops;
> ns->ns_id = 0;
> ns->ns_type = ns_type;
> @@ -77,6 +81,14 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_ope
> ret = proc_alloc_inum(&ns->inum);
> if (ret)
> return ret;
> +
> + ret = security_namespace_init(ns);
> + if (ret) {
> + if (!inum)
> + proc_free_inum(ns->inum);
> + return ret;
> + }
> +
> /*
> * Tree ref starts at 0. It's incremented when namespace enters
> * active use (installed in nsproxy) and decremented when all
> @@ -91,7 +103,10 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_ope
>
> void __ns_common_free(struct ns_common *ns)
> {
> - proc_free_inum(ns->inum);
> + security_namespace_free(ns);
> +
> + if (ns->inum > MNT_NS_INO_SPECIAL_MAX)
> + proc_free_inum(ns->inum);
The ns->inum check in the if-conditional above isn't quite the same as
the is_anon_ns() check it replaces in free_mnt_ns(). You touch on this
a bit in the changelog, but that really should be explained in the
commit description.
... or honestly, should that change be a separate patch?
> }
>
> struct ns_common *__must_check ns_owner(struct ns_common *ns)
> diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
> index d9d3d5973bf5..0f1b208d8eef 100644
> --- a/kernel/nsproxy.c
> +++ b/kernel/nsproxy.c
> @@ -385,6 +385,12 @@ static int prepare_nsset(unsigned flags, struct nsset *nsset)
>
> static inline int validate_ns(struct nsset *nsset, struct ns_common *ns)
> {
> + int ret;
> +
> + ret = security_namespace_install(nsset, ns);
> + if (ret)
> + return ret;
> +
> return ns->ops->install(nsset, ns);
> }
In the previous revision to the patchset I asked about a
security_namespace_switch() hook as we don't know if a namespace is
actually attached to a process until we get to switch_task_namespaces().
Perhaps that was answered, but I don't recall reading any mail about that
and I'm not able to uncover any responses on lore.
> diff --git a/security/security.c b/security/security.c
> index 4e999f023651..21cc45d4bbd0 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -26,6 +26,7 @@
> #include <linux/string.h>
> #include <linux/xattr.h>
> #include <linux/msg.h>
> +#include <linux/ns_common.h>
> #include <linux/overflow.h>
> #include <linux/perf_event.h>
> #include <linux/fs.h>
> @@ -381,6 +382,19 @@ static int lsm_superblock_alloc(struct super_block *sb)
> GFP_KERNEL);
> }
>
> +/**
> + * lsm_ns_alloc - allocate a composite namespace blob
> + * @ns: the namespace that needs a blob
> + *
> + * Allocate the namespace blob for all the modules
> + *
> + * Returns 0, or -ENOMEM if memory can't be allocated.
> + */
> +static int lsm_ns_alloc(struct ns_common *ns)
> +{
> + return lsm_blob_alloc(&ns->ns_security, blob_sizes.lbs_ns, GFP_KERNEL);
> +}
> +
> /**
> * lsm_fill_user_ctx - Fill a user space lsm_ctx structure
> * @uctx: a userspace LSM context to be filled
> @@ -3358,6 +3372,69 @@ int security_create_user_ns(const struct cred *cred)
> return call_int_hook(userns_create, cred);
> }
>
> +/**
> + * security_namespace_init() - Initialize LSM security data for a namespace
> + * @ns: the namespace being initialized
> + *
> + * Initialize the LSM security blob attached to the namespace. The namespace type
> + * is available via ns->ns_type, and the owning user namespace (if any)
> + * via ns->ops->owner(ns).
> + *
> + * Return: Returns 0 if successful, otherwise < 0 error code.
> + */
> +int security_namespace_init(struct ns_common *ns)
> +{
> + int rc;
> +
> + rc = lsm_ns_alloc(ns);
> + if (unlikely(rc))
> + return rc;
> +
> + rc = call_int_hook(namespace_init, ns);
> + if (unlikely(rc))
> + security_namespace_free(ns);
> +
> + return rc;
> +}
> +
> +/**
> + * security_namespace_free() - Release LSM security data from a namespace
> + * @ns: the namespace being freed
> + *
> + * Release security data attached to the namespace. Called before the
> + * namespace structure is freed.
> + *
> + * Note: If an LSM exposes data within the security blob to concurrent
> + * RCU readers, it must use RCU-safe freeing for that data. The blob
> + * memory itself is released with kfree() after the namespace_free
> + * hooks return.
I appreciate that you revised the "Note:" based on my previous comments,
but now it reads just like normal guidance on RCU and object lifetimes.
Do we need this "Note:" at all?
> + */
> +void security_namespace_free(struct ns_common *ns)
> +{
> + if (!ns->ns_security)
> + return;
> +
> + call_void_hook(namespace_free, ns);
> +
> + kfree(ns->ns_security);
> + ns->ns_security = NULL;
> +}
> +
> +/**
> + * security_namespace_install() - Check permission to install a namespace
> + * @nsset: the target nsset being configured
> + * @ns: the namespace being installed
> + *
> + * Check permission before allowing a namespace to be installed into the
> + * process's set of namespaces via setns(2).
> + *
> + * Return: Returns 0 if permission is granted, otherwise < 0 error code.
> + */
> +int security_namespace_install(const struct nsset *nsset, struct ns_common *ns)
> +{
> + return call_int_hook(namespace_install, nsset, ns);
> +}
> +
> /**
> * security_ipc_permission() - Check if sysv ipc access is allowed
> * @ipcp: ipc permission structure
> --
> 2.54.0
--
paul-moore.com
^ permalink raw reply
* Re: [RFC PATCH 06/20] bpf: lsm: Add Landlock kfuncs
From: Paul Moore @ 2026-07-09 2:52 UTC (permalink / raw)
To: Mickaël Salaün
Cc: Casey Schaufler, Justin Suess, ast, daniel, kpsingh,
john.fastabend, andrii, viro, brauner, kees, gnoack, jack,
jmorris, serge, song, yonghong.song, martin.lau, m, eddyz87, sdf,
skhan, bpf, linux-security-module, linux-kernel, linux-fsdevel,
Frederick Lawler
In-Reply-To: <20260702.ierahzaiLub3@digikod.net>
On Thu, Jul 2, 2026 at 5:53 AM Mickaël Salaün <mic@digikod.net> wrote:
> On Wed, Jul 01, 2026 at 07:32:57PM -0400, Paul Moore wrote:
> > On Wed, Jul 1, 2026 at 5:28 PM Mickaël Salaün <mic@digikod.net> wrote:
> > > On Wed, Jul 01, 2026 at 04:02:36PM -0400, Paul Moore wrote:
> > > > On Wed, Jul 1, 2026 at 3:55 PM Justin Suess <utilityemal77@gmail.com> wrote:
> > > > > On Wed, Jul 01, 2026 at 09:49:07PM +0200, Mickaël Salaün wrote:
> > > > > > On Wed, Jul 01, 2026 at 02:38:08PM -0400, Paul Moore wrote:
> > > > > > > On Wed, Jul 1, 2026 at 2:34 PM Mickaël Salaün <mic@digikod.net> wrote:
> > > > > > > > On Wed, Jul 01, 2026 at 09:28:22AM -0400, Paul Moore wrote:
> > > > > > > > > On Wed, Jul 1, 2026 at 8:52 AM Justin Suess <utilityemal77@gmail.com> wrote:
> > > > > > > > > > On Wed, Jul 01, 2026 at 08:12:34AM -0400, Paul Moore wrote:
> > > > > > > > > > > On Wed, Jul 1, 2026 at 6:59 AM Mickaël Salaün <mic@digikod.net> wrote:
> > > > > > > > > > > > On Tue, Apr 07, 2026 at 04:01:28PM -0400, Justin Suess wrote:
> > > > > > > > > > > > > Create 2 kfuncs exposing control over Landlock functionality to BPF
> > > > > > > > > > > > > callers. Export an opaque struct bpf_landlock_ruleset preventing callers
> > > > > > > > > > > > > from accessing unstable internal Landlock fields.
> > > > > > > > > > >
> > > > > > > > > > > Generally speaking we don't want to provide APIs, either in-kernel or
> > > > > > > > > > > at the userspace/kernel boundary, that are specific to a single LSM,
> > > > > > > > > > > see the LSM syscalls or the security_current_getlsmprop_subj()
> > > > > > > > > > > function as examples.
> > > > > > > >
> > > > > > > > This patch series is not about the LSM framework, only about Landlock
> > > > > > > > and its specific model and use case. Landlock using some of the LSM API
> > > > > > > > is not relevant here.
> > > > > > >
> > > > > > > Based on a quick look the patchset enables BPF programs to call
> > > > > > > directly into Landlock. For the same reason we discourage other parts
> > > > > > > of the kernel to call directly into individual LSMs, we want to
> > > > > > > discourage BPF programs from calling directly into individual LSMs.
> > > > > >
> > > > > > We're OK for a dedicated kfunc to call directly into Landlock (with a
> > > > > > tailored interface). Landlock is designed around its syscall interfaces
> > > > > > (well documented, tailored, tested), and this would be a new user of
> > > > > > almost the same UAPI.
> > > > >
> > > > > Paul, Mickaël,
> > > > >
> > > > > I think there's a cleaner way to resolve this.
> > > > >
> > > > > First, walking back my earlier email: I was wrong saying that we need to call
> > > > > into security/security.c to check whether Landlock is enabled. Landlock's
> > > > > init only runs when it's in the active lsm= list, so I can just test
> > > > > landlock_initialized directly. There's no per-invocation reason to route
> > > > > through the LSM framework for that.
> > > >
> > > > The landlock_initialized flag is not really a LSM framework API, that
> > > > is still Landlock specific which is something we try hard to avoid.
> > > >
> > > > > Rather than routing each kfunc *invocation* through a security/security.c
> > > > > wrapper, I think the right place for the framework to be involved is
> > > > > *registration*: have the LSM framework own registration of an LSM's
> > > > > kfunc sets, e.g.
> > > > >
> > > > > int security_register_lsm_kfunc_set(u64 lsm_id, enum bpf_prog_type type,
> > > > > const struct btf_kfunc_id_set *kset);
> > > >
> > > > That implies a set of LSM kfunc APIs which Alexei has been deadset
> > > > against (see other ongoing threads).
> > > >
> > > > > Each LSM calls this once to register its sets. Because registration goes
> > > > > through the framework, the framework gets to decide whether to actually
> > > > > register them so you could, for example, run an LSM while explicitly
> > > > > opting its BPF kfuncs out. (something that should be done at the LSM
> > > > > framework level).
> > > >
> > > > I'm not opposed to the LSM supporting a set of kfuncs, see my comments
> > > > in other threads, but we should treat these kfuncs just as we treat
> > > > other LSM hooks today because that is what they are: LSM hooks that
> > > > happened to be called from within a BPF program.
> > >
> > > What an LSM hook is or should be is the crux of the misunderstanding. I
> > > explained my point of view here:
> > > https://lore.kernel.org/all/20260701.jei4Paej3zen@digikod.net/
> > >
> > > LSM hooks make sense because they are designed for a specific subsystem
> > > (the caller) and their goal is to return an access decision or to keep
> > > up-to-date related states, which means that their API is designed for
> > > the caller, with its own types and specificities, not the other way
> > > around. This case is different, the kfunc is strongly typed and tied to
> > > the Landlock (subsystem) semantic with an API defined by and for
> > > Landlock. I don't think a multiplexer would be a good idea.
> > >
> > > I'd try to explain better: in a nutshell, an LSM hook exposes a subset
> > > of the context of the caller, for any access control system to be able
> > > to make a decision.
> >
> > That is true for some LSM hooks, but not all of them. LSM hooks are
> > really just another name for the functions that compose parts of the
> > LSM framework API; it isn't always strictly about access control in
> > the kernel.
>
> That's why I wrote "in a nutshell". Concrete examples and the rationale
> for such hooks would help.
See the LSM syscalls and the discussions leading up to them. See the
LSM namespacing API discussions. See any of the hooks in
security/security.c that aren't strictly about access control.
> > We leverage the "hooks" for the LSM syscalls, we've
> > discussed "hooks" for implementing a common LSM namespace API, and
> > there have also been early efforts at LSM policy loading via "hooks".
>
> All that is doable, my question is: why a kfunc multiplexer?
It's an interface into the LSM subsystem. Don't think of the LSM hook
interface as an optional, or nice-to-have, it *is* the interface to
the different LSMs. There are some legacy reasons around
configuration, and some of the userspace APIs (which have been a major
source of problems over the years), but we generally do better when we
find a way to develop a unified interface rather than separate, LSM
specific ones.
I'm not saying we need a LSM version of ioctl(), but we really must
look at developing LSM-wide APIs (yes, that includes kfuncs) first and
only if we are not able to develop a LSM agnostic API then we can
fallback to LSM specific interfaces.
> What are
> the pros and cons? I only see disadvantages for now. Please, convince
> us.
This logic is backwards. Work to develop an LSM interface first, and
then if we are all convinced that it isn't possible, or practical,
then fallback to a Landlock specific API.
--
paul-moore.com
^ permalink raw reply
* Re: [RFC/discuss] memfd_secret(): opt-in visibility for security monitoring (eBPF/audit)
From: Paul Moore @ 2026-07-09 2:21 UTC (permalink / raw)
To: BoxStrikesTeam
Cc: rppt@kernel.org, akpm@linux-foundation.org, linux-mm@kvack.org,
linux-security-module@vger.kernel.org, jmorris@namei.org,
serge@hallyn.com
In-Reply-To: <umQp9Qs18vw53oZDFIgYE4MyUWNemeNL8-Vbs-BOYEvQByiyPSZ3RrEvOpmdWUZ1YtjEHpjlgZnMo5DkJuJziwrKWTYS_A0QF_B3ixToMBY=@proton.me>
On Wed, Jul 8, 2026 at 8:09 AM BoxStrikesTeam <BoxStrikesTeam@proton.me> wrote:
>
> Hi,
>
> While experimenting with mseal() and memfd_secret() together on a
> recent kernel, I ran into what looks like a gap worth discussing:
> content placed in memfd_secret()-backed memory is invisible not just
> to other processes, but also to in-kernel tracing/observability
> mechanisms such as eBPF's bpf_probe_read_user() (EFAULT, as expected,
> since the region is removed from the direct map and kernel page
> tables entirely).
>
> That's working as designed for the threat model memfd_secret targets
> (protect secrets even from a compromised kernel / ROP-based
> exfiltration). But it does mean a local, unprivileged process can
> now allocate memory that:
>
> 1. Is invisible to kernel-side introspection (eBPF tracing,
> /proc/<pid>/mem, ptrace-based tooling) once populated via
> memfd_secret(), and
> 2. Can additionally be sealed against mprotect()/munmap()/mremap()
> via mseal() so its protection bits can't be relaxed either.
>
> Neither primitive alone is new or alarming - mseal() protects mapping
> metadata, not confidentiality, and memfd_secret() is explicitly
> opt-in and disabled by default. But combined, they let a process
> carve out a region that a host-based EDR relying on eBPF
> tracing/probe_read helpers cannot inspect, and cannot force back into
> an inspectable state either. For userland security tooling that
> assumes 'anything a tracing eBPF program can attach to, it can read',
> this is a small blind spot.
>
> I want to be clear I'm not suggesting memfd_secret()'s core guarantee
> should be weakened - the ability to keep data hidden from a
> compromised kernel is the entire point, and forcibly exposing content
> to tracing programs would undermine that model and create a new
> attack surface via the eBPF verifier/helper path itself.
>
> What I'd like to raise for discussion instead is something closer to
> what was already anticipated in the original series - Mike, your
> commit message for memfd_secret() mentions: 'Once there will be a use
> case that will require exposing secretmem to the kernel it will be an
> opt-in request in the system call flags.' Two lighter-weight
> directions that stay consistent with that opt-in philosophy:
>
> a) An LSM hook / audit event at memfd_secret() call time (this
> echoes Christian Gottsche's 2022 RFC to label secretmem inodes
> via inode_init_security_anon for SELinux). Even without content
> visibility, logging 'process X created a N-byte kernel-invisible
> mapping' gives EDR/audit systems a behavioral signal to alert on,
> without touching the confidentiality guarantee at all.
>
> b) A distinct opt-in flag (as foreshadowed in the original commit)
> that a process could set to allow a CAP_BPF/CAP_SYS_ADMIN-gated
> tracing context to read the region for legitimate
> monitoring/debugging - fully opt-in, off by default, and never
> implicitly available to unprivileged tracers.
>
> Is (a) something that's been considered further since the 2022
> secretmem-inode-labeling thread? And is there any existing tracking
> issue for the kind of opt-in-visibility idea in (b), or was it
> dropped as not worth the complexity?
Modern kernels do allow LSM labeling of secretmem inodes, see
secretmem_file_create().
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH v1] landlock: Document the threat model
From: Jann Horn @ 2026-07-08 21:48 UTC (permalink / raw)
To: Mickaël Salaün
Cc: Günther Noack, Bryam Vargas, Greg Kroah-Hartman, Jens Axboe,
Jonathan Corbet, Justin Suess, Konstantin Meskhidze,
Leon Romanovsky, Matthieu Buffet, Mikhail Ivanov,
Nicolas Bouchinet, Paul Moore, Shuah Khan, Tingmao Wang,
Ubisectech Sirius, Willy Tarreau, Yuxian Mao, kernel-team,
landlock, linux-doc, linux-kernel, linux-security-module
In-Reply-To: <20260707210336.2060040-1-mic@digikod.net>
On Tue, Jul 7, 2026 at 11:03 PM Mickaël Salaün <mic@digikod.net> wrote:
> +Sandboxing is layered
> +---------------------
> +
> +Landlock is the access-control layer of a sandbox, not the whole sandbox. A
> +robust sandbox also needs steps that are the program's responsibility: switching
> +to an unprivileged user, dropping capabilities, setting ``PR_SET_NO_NEW_PRIVS``,
> +and confining all threads of the process with the same domain. A
> +single-threaded process gets the latter for free; a multithreaded one can
> +enforce a ruleset atomically on all its threads, or must otherwise synchronize
> +them before any untrusted work. Landlock is typically applied last, to tighten
> +access and make the domain identifiable and auditable.
> +
> +Stronger isolation can come from combining Landlock with other mechanisms in a
> +defense-in-depth approach, notably seccomp-bpf (see
> +Documentation/userspace-api/seccomp_filter.rst) for what Landlock does not yet
> +cover. A long-term goal of Landlock is to control access to any kind of kernel
> +resource in a way suited to sandboxing.
I think this part is something that should go near the top of the
document, and should have a title like "How to securely use landlock"
- most of the document is focused on telling kernel developers or
security researchers what the boundaries of the threat model are, but
I think it is also important (and maybe even more important) to
present this from the perspective of "if I want to design a sandbox
using landlock, what do I need to pay attention to".
I think it would also make sense to give more specific guidance on
which sets of syscalls, with what argument restrictions, can be
permitted in a seccomp policy because landlock covers any accesses
that these syscalls can perform to objects to which the process
doesn't already hold file descriptors or such.
I think it would be helpful to have instructions like "you can safely
allow socket operations if you ensure that socket creation (socket())
only works for AF_UNIX, and that the process has no existing socket
file descriptors for non-covered socket types, and you have fs_access
rules, and the kernel is sufficiently recent".
^ permalink raw reply
* Re: [PATCH v2] NFSv4.2: fix nfs4_listxattr size accounting
From: Paul Moore @ 2026-07-08 20:10 UTC (permalink / raw)
To: Stephen Smalley
Cc: Anna Schumaker, Achilles Gaikwad, Trond Myklebust, linux-nfs,
linux-security-module, selinux
In-Reply-To: <CAEjxPJ7dttPDxQDa_xXFd1H-QT_vkUwjtnH+=3cmG5dhSiaAXw@mail.gmail.com>
On Wed, Jul 8, 2026 at 2:54 PM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
> On Tue, Jul 7, 2026 at 4:01 PM Paul Moore <paul@paul-moore.com> wrote:
> >
> > On Tue, Jul 7, 2026 at 3:12 PM Anna Schumaker <anna@kernel.org> wrote:
> > > On Tue, Jul 7, 2026, at 2:48 PM, Paul Moore wrote:
> > > > On Tue, Jul 7, 2026 at 11:24 AM Achilles Gaikwad
> > > > <achillesgaikwad@gmail.com> wrote:
> > > >>
> > > >> A call to listxattr() with a buffer size of 0 returns the actual
> > > >> size of the buffer needed for a subsequent call. On an NFSv4.2
> > > >> mount this triggers the following oops:
> > > >>
> > > >> [ 399.768687] BUG: kernel NULL pointer dereference, address: 0000000000000000
> > > >> [ 399.768705] RIP: 0010:_copy_from_pages+0x44/0xe0
> > > >> [ 399.768722] Call Trace:
> > > >> [ 399.768723] nfs4_xattr_alloc_entry+0x1bf/0x1e0
> > > >> [ 399.768730] nfs4_xattr_cache_set_list+0x43/0x1f0
> > > >> [ 399.768731] nfs4_listxattr+0x21f/0x250
> > > >> [ 399.768733] vfs_listxattr+0x55/0xa0
> > > >> [ 399.768736] listxattr+0x23/0x160
> > > >> [ 399.768737] path_listxattrat+0xba/0x1e0
> > > >> [ 399.768739] do_syscall_64+0xe2/0x680
> > > >>
> > > >> security_inode_listsecurity() (via the xattr_list_one() helper) now
> > > >> decrements the remaining size even when the buffer pointer is NULL, so
> > > >> in the size-query case, 'left' underflows to a huge size_t value. As a
> > > >> result, nfs4_listxattr_nfs4_user() treats the NULL buffer as a real one,
> > > >> leading to a NULL pointer dereference in _copy_from_pages().
> > > >>
> > > >> security_inode_listsecurity() does not return the number of bytes
> > > >> it added to the list, so the code derived it as
> > > >> 'size - error - left'. That is also wrong in the size-query case:
> > > >> the generic_listxattr() contribution is only subtracted from 'left'
> > > >> when a buffer is present. Thus, the query result comes up short by
> > > >> exactly that contribution (e.g., "system.nfs4_acl" on a mount with
> > > >> ACL support), and a caller that allocates the returned size gets
> > > >> -ERANGE on the subsequent call.
> > > >>
> > > >> Declare 'left' as ssize_t, use a scratch copy to measure security
> > > >> hook consumption, and only decrement 'left' if a buffer is present.
> > > >>
> > > >> Fixes: f71ece9712b7 ("security,fs,nfs,net: update security_inode_listsecurity() interface")
> > > >> Suggested-by: Paul Moore <paul@paul-moore.com>
> > > >> Signed-off-by: Achilles Gaikwad <achillesgaikwad@gmail.com>
> > > >> ---
> > > >> Changes in v2:
> > > >> - Use a scratch variable to track security label size directly,
> > > >> replacing the old formula that undercounted the size-query case.
> > > >> - Drop the now-unneeded NULL-buffer special case for
> > > >> nfs4_listxattr_nfs4_user().
> > > >> - Retitled from "fix nfs4_listxattr NULL pointer dereference"
> > > >> (the same accounting bug caused both the oops and the undercount).
> > > >> v1: https://lore.kernel.org/linux-nfs/20260703102759.9626-1-achillesgaikwad@gmail.com/
> > > >> fs/nfs/nfs4proc.c | 10 +++++++---
> > > >> 1 file changed, 7 insertions(+), 3 deletions(-)
> > > >
> > > > [CC'd the LSM and SELinux lists for visibility]
> > > >
> > > > Unfortunately my testing was unsuccessful due to an NFS problem that
> > > > started with the v7.2 merge window that I haven't had the time to
> > > > bisect yet. Assuming the NFS folks are okay with this change, I
> > > > figure they will want to send it up to Linus via their tree, if not
> > > > let me know and I can send this up via the LSM tree.
> > >
> > > Yeah, we'll send it through the NFS tree.
> >
> > Thanks Anna.
> >
> > > I'll be curious to hear
> > > what problem you're hitting, and what patch is the culprit once you
> > > do that bisect!
> >
> > Yes, me too :)
> >
> > I'm still working through a review backlog so it might be a bit before
> > I have a chance, but in case anyone wants to test it out, it's easily
> > reproduced using the selinux-testsuite and the NFS tests:
> >
> > https://github.com/SELinuxProject/selinux-testsuite#nfs
>
> They seem to pass for me with and without the patch (they don't
> exercise listxattr AFAIK).
> This was on the current selinux/dev branch, v7.2-rc1 based.
They work for me on vanilla v7.1 and fail somewhere before vanilla
v7.2-rc1 (still bisecting).
I wonder if there is an interaction problem with a recent userspace
update. What distro/userspace are you running for your tests? I'm
doing my testing on a relatively recent Rawhide.
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH v2] NFSv4.2: fix nfs4_listxattr size accounting
From: Stephen Smalley @ 2026-07-08 18:54 UTC (permalink / raw)
To: Paul Moore
Cc: Anna Schumaker, Achilles Gaikwad, Trond Myklebust, linux-nfs,
linux-security-module, selinux
In-Reply-To: <CAHC9VhQYjj3--K6KkDJBf6LfXqtj4TPh5LsMBpPYc0-Zz6wTMA@mail.gmail.com>
On Tue, Jul 7, 2026 at 4:01 PM Paul Moore <paul@paul-moore.com> wrote:
>
> On Tue, Jul 7, 2026 at 3:12 PM Anna Schumaker <anna@kernel.org> wrote:
> > On Tue, Jul 7, 2026, at 2:48 PM, Paul Moore wrote:
> > > On Tue, Jul 7, 2026 at 11:24 AM Achilles Gaikwad
> > > <achillesgaikwad@gmail.com> wrote:
> > >>
> > >> A call to listxattr() with a buffer size of 0 returns the actual
> > >> size of the buffer needed for a subsequent call. On an NFSv4.2
> > >> mount this triggers the following oops:
> > >>
> > >> [ 399.768687] BUG: kernel NULL pointer dereference, address: 0000000000000000
> > >> [ 399.768705] RIP: 0010:_copy_from_pages+0x44/0xe0
> > >> [ 399.768722] Call Trace:
> > >> [ 399.768723] nfs4_xattr_alloc_entry+0x1bf/0x1e0
> > >> [ 399.768730] nfs4_xattr_cache_set_list+0x43/0x1f0
> > >> [ 399.768731] nfs4_listxattr+0x21f/0x250
> > >> [ 399.768733] vfs_listxattr+0x55/0xa0
> > >> [ 399.768736] listxattr+0x23/0x160
> > >> [ 399.768737] path_listxattrat+0xba/0x1e0
> > >> [ 399.768739] do_syscall_64+0xe2/0x680
> > >>
> > >> security_inode_listsecurity() (via the xattr_list_one() helper) now
> > >> decrements the remaining size even when the buffer pointer is NULL, so
> > >> in the size-query case, 'left' underflows to a huge size_t value. As a
> > >> result, nfs4_listxattr_nfs4_user() treats the NULL buffer as a real one,
> > >> leading to a NULL pointer dereference in _copy_from_pages().
> > >>
> > >> security_inode_listsecurity() does not return the number of bytes
> > >> it added to the list, so the code derived it as
> > >> 'size - error - left'. That is also wrong in the size-query case:
> > >> the generic_listxattr() contribution is only subtracted from 'left'
> > >> when a buffer is present. Thus, the query result comes up short by
> > >> exactly that contribution (e.g., "system.nfs4_acl" on a mount with
> > >> ACL support), and a caller that allocates the returned size gets
> > >> -ERANGE on the subsequent call.
> > >>
> > >> Declare 'left' as ssize_t, use a scratch copy to measure security
> > >> hook consumption, and only decrement 'left' if a buffer is present.
> > >>
> > >> Fixes: f71ece9712b7 ("security,fs,nfs,net: update security_inode_listsecurity() interface")
> > >> Suggested-by: Paul Moore <paul@paul-moore.com>
> > >> Signed-off-by: Achilles Gaikwad <achillesgaikwad@gmail.com>
> > >> ---
> > >> Changes in v2:
> > >> - Use a scratch variable to track security label size directly,
> > >> replacing the old formula that undercounted the size-query case.
> > >> - Drop the now-unneeded NULL-buffer special case for
> > >> nfs4_listxattr_nfs4_user().
> > >> - Retitled from "fix nfs4_listxattr NULL pointer dereference"
> > >> (the same accounting bug caused both the oops and the undercount).
> > >> v1: https://lore.kernel.org/linux-nfs/20260703102759.9626-1-achillesgaikwad@gmail.com/
> > >> fs/nfs/nfs4proc.c | 10 +++++++---
> > >> 1 file changed, 7 insertions(+), 3 deletions(-)
> > >
> > > [CC'd the LSM and SELinux lists for visibility]
> > >
> > > Unfortunately my testing was unsuccessful due to an NFS problem that
> > > started with the v7.2 merge window that I haven't had the time to
> > > bisect yet. Assuming the NFS folks are okay with this change, I
> > > figure they will want to send it up to Linus via their tree, if not
> > > let me know and I can send this up via the LSM tree.
> >
> > Yeah, we'll send it through the NFS tree.
>
> Thanks Anna.
>
> > I'll be curious to hear
> > what problem you're hitting, and what patch is the culprit once you
> > do that bisect!
>
> Yes, me too :)
>
> I'm still working through a review backlog so it might be a bit before
> I have a chance, but in case anyone wants to test it out, it's easily
> reproduced using the selinux-testsuite and the NFS tests:
>
> https://github.com/SELinuxProject/selinux-testsuite#nfs
They seem to pass for me with and without the patch (they don't
exercise listxattr AFAIK).
This was on the current selinux/dev branch, v7.2-rc1 based.
^ permalink raw reply
* Re: [PATCH bpf-next v6 0/8] Verify BPF signed loader at load time
From: patchwork-bot+netdevbpf @ 2026-07-08 18:30 UTC (permalink / raw)
To: Daniel Borkmann
Cc: ast, kpsingh, James.Bottomley, paul, bboscaccy, memxor, torvalds,
a.s.protopopov, bpf, linux-security-module
In-Reply-To: <20260708075343.358712-1-daniel@iogearbox.net>
Hello:
This series was applied to bpf/bpf-next.git (master)
by Kumar Kartikeya Dwivedi <memxor@gmail.com>:
On Wed, 8 Jul 2026 09:53:35 +0200 you wrote:
> The BPF signing scheme signs a light skeleton's loader program and lets
> the loader vouch for everything else: bpftool bakes the SHA256 of the
> metadata map into the loader's instructions, signs the instructions, and
> the loader compares the (frozen, exclusive) map against that hash from
> within BPF once it runs. The construction is sound as a trusted hash
> chain, but the kernel itself never attests the metadata, and that split
> has been the recurring objection from the LSM / integrity side since the
> scheme was proposed.
>
> [...]
Here is the summary with links:
- [bpf-next,v6,1/8] bpf: Resolve and cache fd_array objects at load time
https://git.kernel.org/bpf/bpf-next/c/d5a85392392c
- [bpf-next,v6,2/8] bpf: Verify signed loader metadata at load time
https://git.kernel.org/bpf/bpf-next/c/b707068e0ed9
- [bpf-next,v6,3/8] libbpf: Drop in-loader metadata check for load-time verification
https://git.kernel.org/bpf/bpf-next/c/a2d784869a0f
- [bpf-next,v6,4/8] bpftool: Check EVP_Digest when computing excl_prog_hash
https://git.kernel.org/bpf/bpf-next/c/576bcaa1f5c2
- [bpf-next,v6,5/8] bpftool: Cover loader metadata with the program signature
https://git.kernel.org/bpf/bpf-next/c/92c7717981bb
- [bpf-next,v6,6/8] selftests/bpf: Adjust bpf_map layout in verifier_map_ptr
https://git.kernel.org/bpf/bpf-next/c/77e5f3c91453
- [bpf-next,v6,7/8] selftests/bpf: Verify load-time signed loader metadata
https://git.kernel.org/bpf/bpf-next/c/99b321dde704
- [bpf-next,v6,8/8] Documentation/bpf: Add BPF signing and enforcement doc
https://git.kernel.org/bpf/bpf-next/c/84c42f515f18
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH 1/2] umh, treewide: Explicitly include linux/umh.h where needed
From: Michal Koutný @ 2026-07-08 18:13 UTC (permalink / raw)
To: Petr Pavlu
Cc: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
Dave Hansen, x86, H. Peter Anvin, Philipp Reisner, Lars Ellenberg,
Christoph Böhmwalder, Jens Axboe, Johan Hovold, Alex Elder,
Greg Kroah-Hartman, Rafael J. Wysocki, Michal Januszewski,
Helge Deller, Alexander Viro, Christian Brauner, Jan Kara,
Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey, Mark Fasheh,
Joel Becker, Joseph Qi, Tejun Heo, Johannes Weiner,
Luis Chamberlain, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
Pavel Machek, Len Brown, Andrew Morton, Danilo Krummrich,
Nikolay Aleksandrov, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, David Howells,
Jarkko Sakkinen, Paul Moore, James Morris, Serge E. Hallyn,
Kentaro Takeda, Tetsuo Handa, linux-edac, linux-kernel, drbd-dev,
linux-block, greybus-dev, linuxppc-dev, linux-acpi, linux-fbdev,
dri-devel, linux-fsdevel, linux-nfs, ocfs2-devel, cgroups,
linux-modules, linux-pm, driver-core, bridge, netdev, keyrings,
linux-security-module
In-Reply-To: <20260708154510.6794-2-petr.pavlu@suse.com>
[-- Attachment #1: Type: text/plain, Size: 583 bytes --]
Hi Petr.
On Wed, Jul 08, 2026 at 05:44:29PM +0200, Petr Pavlu <petr.pavlu@suse.com> wrote:
> diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
> index a4337c9b5287..60eb994c32ae 100644
> --- a/kernel/cgroup/cgroup-v1.c
> +++ b/kernel/cgroup/cgroup-v1.c
> @@ -16,6 +16,7 @@
> #include <linux/pid_namespace.h>
> #include <linux/cgroupstats.h>
> #include <linux/fs_parser.h>
> +#include <linux/umh.h>
>
> #include <trace/events/cgroup.h>
There is kmod.h in here too but it's unnecessary, no module lazy loading
in this code.
Thanks,
Michal
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 265 bytes --]
^ permalink raw reply
* [PATCH 2/2] module: Bring includes in linux/kmod.h up to date
From: Petr Pavlu @ 2026-07-08 15:44 UTC (permalink / raw)
To: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
Dave Hansen, x86, H. Peter Anvin, Philipp Reisner, Lars Ellenberg,
Christoph Böhmwalder, Jens Axboe, Johan Hovold, Alex Elder,
Greg Kroah-Hartman, Rafael J. Wysocki, Michal Januszewski,
Helge Deller, Alexander Viro, Christian Brauner, Jan Kara,
Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey, Mark Fasheh,
Joel Becker, Joseph Qi, Tejun Heo, Johannes Weiner,
Michal Koutný, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Pavel Machek, Len Brown,
Andrew Morton, Danilo Krummrich, Nikolay Aleksandrov,
Ido Schimmel, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, David Howells, Jarkko Sakkinen,
Paul Moore, James Morris, Serge E. Hallyn, Kentaro Takeda,
Tetsuo Handa
Cc: linux-edac, linux-kernel, drbd-dev, linux-block, greybus-dev,
linuxppc-dev, linux-acpi, linux-fbdev, dri-devel, linux-fsdevel,
linux-nfs, ocfs2-devel, cgroups, linux-modules, linux-pm,
driver-core, bridge, netdev, keyrings, linux-security-module
In-Reply-To: <20260708154510.6794-1-petr.pavlu@suse.com>
Including linux/kmod.h alone results in 1.5 MB of preprocessed output, even
though it provides only a few functions and macros.
The header currently depends on:
* __printf() -> linux/compiler_attributes.h,
* ENOSYS -> linux/errno.h,
* bool -> linux/types.h.
Include only these files, reducing the preprocessed output to 10 kB.
Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
---
include/linux/kmod.h | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 9a07c3215389..b9474a62a568 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -2,17 +2,9 @@
#ifndef __LINUX_KMOD_H__
#define __LINUX_KMOD_H__
-/*
- * include/linux/kmod.h
- */
-
-#include <linux/umh.h>
-#include <linux/gfp.h>
-#include <linux/stddef.h>
+#include <linux/compiler_attributes.h>
#include <linux/errno.h>
-#include <linux/compiler.h>
-#include <linux/workqueue.h>
-#include <linux/sysctl.h>
+#include <linux/types.h>
#ifdef CONFIG_MODULES
/* modprobe exit status on success, -ve on error. Return value
--
2.54.0
^ permalink raw reply related
* [PATCH 1/2] umh, treewide: Explicitly include linux/umh.h where needed
From: Petr Pavlu @ 2026-07-08 15:44 UTC (permalink / raw)
To: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
Dave Hansen, x86, H. Peter Anvin, Philipp Reisner, Lars Ellenberg,
Christoph Böhmwalder, Jens Axboe, Johan Hovold, Alex Elder,
Greg Kroah-Hartman, Rafael J. Wysocki, Michal Januszewski,
Helge Deller, Alexander Viro, Christian Brauner, Jan Kara,
Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey, Mark Fasheh,
Joel Becker, Joseph Qi, Tejun Heo, Johannes Weiner,
Michal Koutný, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Pavel Machek, Len Brown,
Andrew Morton, Danilo Krummrich, Nikolay Aleksandrov,
Ido Schimmel, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, David Howells, Jarkko Sakkinen,
Paul Moore, James Morris, Serge E. Hallyn, Kentaro Takeda,
Tetsuo Handa
Cc: linux-edac, linux-kernel, drbd-dev, linux-block, greybus-dev,
linuxppc-dev, linux-acpi, linux-fbdev, dri-devel, linux-fsdevel,
linux-nfs, ocfs2-devel, cgroups, linux-modules, linux-pm,
driver-core, bridge, netdev, keyrings, linux-security-module
In-Reply-To: <20260708154510.6794-1-petr.pavlu@suse.com>
The usermode helper declarations were previously provided by linux/kmod.h
but commit c1f3fa2a4fde ("kmod: split off umh headers into its own file")
moved them to linux/umh.h in 2017. Add explicit includes of linux/umh.h to
files that use usermode helpers and remove linux/kmod.h where it is no
longer needed.
Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
---
arch/x86/kernel/cpu/mce/dev-mcelog.c | 2 +-
drivers/block/drbd/drbd_nl.c | 1 +
drivers/greybus/svc_watchdog.c | 1 +
drivers/macintosh/windfarm_core.c | 1 +
drivers/pnp/pnpbios/core.c | 2 +-
drivers/video/fbdev/uvesafb.c | 1 +
fs/coredump.c | 2 +-
fs/nfs/cache_lib.c | 2 +-
fs/nfsd/nfs4layouts.c | 2 +-
fs/nfsd/nfs4recover.c | 1 +
fs/ocfs2/stackglue.c | 1 +
kernel/cgroup/cgroup-v1.c | 1 +
kernel/module/kmod.c | 1 +
kernel/power/process.c | 2 +-
kernel/reboot.c | 2 +-
kernel/umh.c | 2 +-
lib/kobject_uevent.c | 2 +-
net/bridge/br_stp_if.c | 2 +-
security/keys/request_key.c | 2 +-
security/tomoyo/common.h | 2 +-
20 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/arch/x86/kernel/cpu/mce/dev-mcelog.c b/arch/x86/kernel/cpu/mce/dev-mcelog.c
index 053555206d81..af4e76babe7a 100644
--- a/arch/x86/kernel/cpu/mce/dev-mcelog.c
+++ b/arch/x86/kernel/cpu/mce/dev-mcelog.c
@@ -11,7 +11,7 @@
#include <linux/miscdevice.h>
#include <linux/slab.h>
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <linux/poll.h>
#include "internal.h"
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index f9ffcd67607b..de90cf4a0789 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -14,6 +14,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
+#include <linux/umh.h>
#include <linux/drbd.h>
#include <linux/in.h>
#include <linux/fs.h>
diff --git a/drivers/greybus/svc_watchdog.c b/drivers/greybus/svc_watchdog.c
index 16e6de5e9eff..b318eb34bcca 100644
--- a/drivers/greybus/svc_watchdog.c
+++ b/drivers/greybus/svc_watchdog.c
@@ -7,6 +7,7 @@
#include <linux/delay.h>
#include <linux/suspend.h>
+#include <linux/umh.h>
#include <linux/workqueue.h>
#include <linux/greybus.h>
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 5307b1e34261..e66de11c69a3 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -34,6 +34,7 @@
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/freezer.h>
+#include <linux/umh.h>
#include "windfarm.h"
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index f7e86ae9f72f..46af1f549337 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -47,7 +47,7 @@
#include <linux/delay.h>
#include <linux/acpi.h>
#include <linux/freezer.h>
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <linux/kthread.h>
#include <asm/page.h>
diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c
index 9d82326c744f..6c503e6914d6 100644
--- a/drivers/video/fbdev/uvesafb.c
+++ b/drivers/video/fbdev/uvesafb.c
@@ -23,6 +23,7 @@
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/umh.h>
#include <video/edid.h>
#include <video/uvesafb.h>
#ifdef CONFIG_X86
diff --git a/fs/coredump.c b/fs/coredump.c
index e68a76ff92a3..4908b44f6fdc 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -32,7 +32,7 @@
#include <linux/tsacct_kern.h>
#include <linux/cn_proc.h>
#include <linux/audit.h>
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <linux/fsnotify.h>
#include <linux/fs_struct.h>
#include <linux/pipe_fs_i.h>
diff --git a/fs/nfs/cache_lib.c b/fs/nfs/cache_lib.c
index 9738a1ae92ca..ca4e81d4e315 100644
--- a/fs/nfs/cache_lib.c
+++ b/fs/nfs/cache_lib.c
@@ -6,7 +6,7 @@
*
* Copyright (c) 2009 Trond Myklebust <Trond.Myklebust@netapp.com>
*/
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mount.h>
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index f34320e4c2f4..008f0f088c3a 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -3,7 +3,7 @@
* Copyright (c) 2014 Christoph Hellwig.
*/
#include <linux/exportfs_block.h>
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <linux/file.h>
#include <linux/jhash.h>
#include <linux/sched.h>
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 6ea25a52d2f4..20b98e43f668 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -41,6 +41,7 @@
#include <linux/fs.h>
#include <linux/hex.h>
#include <linux/module.h>
+#include <linux/umh.h>
#include <net/net_namespace.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
#include <linux/sunrpc/clnt.h>
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index 741d6191d871..0ccaab29426d 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -18,6 +18,7 @@
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/sysctl.h>
+#include <linux/umh.h>
#include "ocfs2_fs.h"
diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
index a4337c9b5287..60eb994c32ae 100644
--- a/kernel/cgroup/cgroup-v1.c
+++ b/kernel/cgroup/cgroup-v1.c
@@ -16,6 +16,7 @@
#include <linux/pid_namespace.h>
#include <linux/cgroupstats.h>
#include <linux/fs_parser.h>
+#include <linux/umh.h>
#include <trace/events/cgroup.h>
diff --git a/kernel/module/kmod.c b/kernel/module/kmod.c
index a25dccdf7aa7..dcaad5d65275 100644
--- a/kernel/module/kmod.c
+++ b/kernel/module/kmod.c
@@ -28,6 +28,7 @@
#include <linux/ptrace.h>
#include <linux/async.h>
#include <linux/uaccess.h>
+#include <linux/umh.h>
#include <trace/events/module.h>
#include "internal.h"
diff --git a/kernel/power/process.c b/kernel/power/process.c
index dc0dfc349f22..295904ec9a82 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -16,7 +16,7 @@
#include <linux/freezer.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <trace/events/power.h>
#include <linux/cpuset.h>
diff --git a/kernel/reboot.c b/kernel/reboot.c
index 695c33e75efd..3d4a262973e7 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -11,13 +11,13 @@
#include <linux/ctype.h>
#include <linux/export.h>
#include <linux/kexec.h>
-#include <linux/kmod.h>
#include <linux/kmsg_dump.h>
#include <linux/reboot.h>
#include <linux/suspend.h>
#include <linux/syscalls.h>
#include <linux/syscore_ops.h>
#include <linux/uaccess.h>
+#include <linux/umh.h>
/*
* this indicates whether you can reboot with ctrl-alt-del: the default is yes
diff --git a/kernel/umh.c b/kernel/umh.c
index 48117c569e1a..72b2d9a878aa 100644
--- a/kernel/umh.c
+++ b/kernel/umh.c
@@ -8,7 +8,7 @@
#include <linux/binfmts.h>
#include <linux/syscalls.h>
#include <linux/unistd.h>
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/cred.h>
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index ddbc4d7482d2..a67129e452a3 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -17,7 +17,7 @@
#include <linux/string.h>
#include <linux/kobject.h>
#include <linux/export.h>
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <linux/slab.h>
#include <linux/socket.h>
#include <linux/skbuff.h>
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index a7e5422eb5d1..89bc161a4b47 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -8,7 +8,7 @@
*/
#include <linux/kernel.h>
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
#include <net/switchdev.h>
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index fa2bb9f2f538..e6ba2d054399 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -9,7 +9,7 @@
#include <linux/export.h>
#include <linux/sched.h>
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <linux/err.h>
#include <linux/keyctl.h>
#include <linux/slab.h>
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index d098cf8aae61..d26034000913 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -16,7 +16,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/file.h>
-#include <linux/kmod.h>
+#include <linux/umh.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/namei.h>
--
2.54.0
^ permalink raw reply related
* [PATCH 0/2] Bring includes in linux/kmod.h up to date
From: Petr Pavlu @ 2026-07-08 15:44 UTC (permalink / raw)
To: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
Dave Hansen, x86, H. Peter Anvin, Philipp Reisner, Lars Ellenberg,
Christoph Böhmwalder, Jens Axboe, Johan Hovold, Alex Elder,
Greg Kroah-Hartman, Rafael J. Wysocki, Michal Januszewski,
Helge Deller, Alexander Viro, Christian Brauner, Jan Kara,
Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey, Mark Fasheh,
Joel Becker, Joseph Qi, Tejun Heo, Johannes Weiner,
Michal Koutný, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Pavel Machek, Len Brown,
Andrew Morton, Danilo Krummrich, Nikolay Aleksandrov,
Ido Schimmel, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, David Howells, Jarkko Sakkinen,
Paul Moore, James Morris, Serge E. Hallyn, Kentaro Takeda,
Tetsuo Handa
Cc: linux-edac, linux-kernel, drbd-dev, linux-block, greybus-dev,
linuxppc-dev, linux-acpi, linux-fbdev, dri-devel, linux-fsdevel,
linux-nfs, ocfs2-devel, cgroups, linux-modules, linux-pm,
driver-core, bridge, netdev, keyrings, linux-security-module
The usermode helper declarations were previously provided by linux/kmod.h
but commit c1f3fa2a4fde ("kmod: split off umh headers into its own file")
moved them to linux/umh.h in 2017. Add explicit includes of linux/umh.h to
files that use usermode helpers and remove linux/kmod.h where it is no
longer needed.
Then clean up linux/kmod.h so that it includes only the headers that it
actually requires, importantly removing the compat linux/umh.h include.
Apologies for the wide distribution.
This cleanup is motivated by trying to reduce the preprocessed size of
linux/module.h, which includes linux/kmod.h. The linux/module.h header is
included by every *.mod.c file to provide `struct module` and other related
definitions, so it should avoid pulling in unnecessary dependencies. Note
that this series doesn't immediately improve the situation, since most of
the files included by linux/kmod.h are, for now, also included by
linux/module.h through other paths.
Petr Pavlu (2):
umh, treewide: Explicitly include linux/umh.h where needed
module: Bring includes in linux/kmod.h up to date
arch/x86/kernel/cpu/mce/dev-mcelog.c | 2 +-
drivers/block/drbd/drbd_nl.c | 1 +
drivers/greybus/svc_watchdog.c | 1 +
drivers/macintosh/windfarm_core.c | 1 +
drivers/pnp/pnpbios/core.c | 2 +-
drivers/video/fbdev/uvesafb.c | 1 +
fs/coredump.c | 2 +-
fs/nfs/cache_lib.c | 2 +-
fs/nfsd/nfs4layouts.c | 2 +-
fs/nfsd/nfs4recover.c | 1 +
fs/ocfs2/stackglue.c | 1 +
include/linux/kmod.h | 12 ++----------
kernel/cgroup/cgroup-v1.c | 1 +
kernel/module/kmod.c | 1 +
kernel/power/process.c | 2 +-
kernel/reboot.c | 2 +-
kernel/umh.c | 2 +-
lib/kobject_uevent.c | 2 +-
net/bridge/br_stp_if.c | 2 +-
security/keys/request_key.c | 2 +-
security/tomoyo/common.h | 2 +-
21 files changed, 22 insertions(+), 22 deletions(-)
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
--
2.54.0
^ permalink raw reply
* Re: [PATCH v1] landlock: Update formatting
From: Günther Noack @ 2026-07-08 15:30 UTC (permalink / raw)
To: Mickaël Salaün
Cc: linux-security-module, Bart Van Assche, Miguel Ojeda
In-Reply-To: <20260708110635.2083515-1-mic@digikod.net>
On Wed, Jul 08, 2026 at 01:06:33PM +0200, Mickaël Salaün wrote:
> Following commit 99df2a8eba34 ("clang-format: fix formatting of guard()
> and scoped_guard() statements"), update scoped_guard() formatting.
> Also, see the related fix [1].
>
> Cc: Günther Noack <gnoack@google.com>
> Cc: Miguel Ojeda <ojeda@kernel.org>
> Link: https://lore.kernel.org/r/20260708105713.2073335-1-mic@digikod.net [1]
> Signed-off-by: Mickaël Salaün <mic@digikod.net>
> ---
> security/landlock/task.c | 9 +++------
> 1 file changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/security/landlock/task.c b/security/landlock/task.c
> index 7ddf211f75c3..360d226d0f51 100644
> --- a/security/landlock/task.c
> +++ b/security/landlock/task.c
> @@ -95,8 +95,7 @@ static int hook_ptrace_access_check(struct task_struct *const child,
> if (!parent_subject)
> return 0;
>
> - scoped_guard(rcu)
> - {
> + scoped_guard(rcu) {
> const struct landlock_ruleset *const child_dom =
> landlock_get_task_domain(child);
> err = domain_ptrace(parent_subject->domain, child_dom);
> @@ -370,8 +369,7 @@ static int hook_task_kill(struct task_struct *const p,
> if (!subject)
> return 0;
>
> - scoped_guard(rcu)
> - {
> + scoped_guard(rcu) {
> is_scoped = domain_is_scoped(subject->domain,
> landlock_get_task_domain(p),
> signal_scope.scope);
> @@ -422,8 +420,7 @@ static int hook_file_send_sigiotask(struct task_struct *tsk,
> if (task_tgid(tsk) == landlock_file(fown->file)->fown_tg)
> return 0;
>
> - scoped_guard(rcu)
> - {
> + scoped_guard(rcu) {
> is_scoped = domain_is_scoped(subject->domain,
> landlock_get_task_domain(tsk),
> signal_scope.scope);
> --
> 2.54.0
Reviewed-by: Günther Noack <gnoack@google.com>
^ permalink raw reply
* [PATCH 3/3] landlock: Document LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
From: Justin Suess @ 2026-07-08 13:39 UTC (permalink / raw)
To: mic, linux-security-module; +Cc: gnoack, Justin Suess
In-Reply-To: <20260708133928.852999-1-utilityemal77@gmail.com>
Document staged no_new_privs on exec, following the same compatibility
section style as previous ABI additions.
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
Documentation/userspace-api/landlock.rst | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst
index 5a63d4476c1c..1d779dd7bb5f 100644
--- a/Documentation/userspace-api/landlock.rst
+++ b/Documentation/userspace-api/landlock.rst
@@ -8,7 +8,7 @@ Landlock: unprivileged access control
=====================================
:Author: Mickaël Salaün
-:Date: June 2026
+:Date: July 2026
The goal of Landlock is to enable restriction of ambient rights (e.g. global
filesystem or network access) for a set of processes. Because Landlock
@@ -789,6 +789,25 @@ when at least one sys_landlock_add_rule() call is made for it with the
``LANDLOCK_ADD_RULE_QUIET`` flag, additional add-rule calls for the same
object without this flag do not clear it.
+Staged no_new_privs on exec (ABI < 11)
+--------------------------------------
+
+Starting with the Landlock ABI version 11, it is possible to stage
+no_new_privs so that it is only set at the next :manpage:`execve(2)` of the
+calling thread, past its point of no return, using the
+``LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC`` flag passed to
+sys_landlock_restrict_self(). This flag may be used with a ``ruleset_fd``
+value of -1 to stage no_new_privs without enforcing a ruleset, and does not
+relax the no_new_privs / ``CAP_SYS_ADMIN`` requirement of the system call.
+This flag does not change how the next :manpage:`execve(2)` itself computes
+credentials: set-user-ID, set-group-ID and file capabilities are still
+honored for that execution. The executed program then runs with
+no_new_privs set, with its usual effect on subsequent :manpage:`execve(2)`
+calls. Staging is per-thread by default: when combined with
+``LANDLOCK_RESTRICT_SELF_TSYNC``, the staged no_new_privs is propagated to
+the sibling threads along with the rest of the Landlock configuration, and
+each thread then sets no_new_privs at its own next :manpage:`execve(2)`.
+
.. _kernel_support:
Kernel support
--
2.54.0
^ permalink raw reply related
* [PATCH 2/3] selftests/landlock: Test LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
From: Justin Suess @ 2026-07-08 13:39 UTC (permalink / raw)
To: mic, linux-security-module; +Cc: gnoack, Justin Suess
In-Reply-To: <20260708133928.852999-1-utilityemal77@gmail.com>
Add an nnp_on_exec fixture checking that staging no_new_privs does not
set it before execve(2) but does set it for the executed program, with
and without a ruleset, and that LANDLOCK_RESTRICT_SELF_TSYNC propagates
the staged state to sibling threads. Also check that the
no_new_privs/CAP_SYS_ADMIN requirement still applies to stage-only
calls.
Update the ABI version and last-flag checks accordingly.
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
tools/testing/selftests/landlock/base_test.c | 259 ++++++++++++++++++-
1 file changed, 255 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c
index cbd3c1669951..55ae26a72752 100644
--- a/tools/testing/selftests/landlock/base_test.c
+++ b/tools/testing/selftests/landlock/base_test.c
@@ -11,9 +11,12 @@
#include <fcntl.h>
#include <linux/keyctl.h>
#include <linux/landlock.h>
+#include <pthread.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include "common.h"
@@ -76,7 +79,7 @@ TEST(abi_version)
const struct landlock_ruleset_attr ruleset_attr = {
.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
};
- ASSERT_EQ(10, landlock_create_ruleset(NULL, 0,
+ ASSERT_EQ(11, landlock_create_ruleset(NULL, 0,
LANDLOCK_CREATE_RULESET_VERSION));
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
@@ -288,7 +291,7 @@ TEST(restrict_self_fd)
EXPECT_EQ(EBADFD, errno);
}
-TEST(restrict_self_fd_logging_flags)
+TEST(restrict_self_fd_flags)
{
int fd;
@@ -302,11 +305,16 @@ TEST(restrict_self_fd_logging_flags)
EXPECT_EQ(-1, landlock_restrict_self(
fd, LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF));
EXPECT_EQ(EBADFD, errno);
+
+ /* Same for LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC. */
+ EXPECT_EQ(-1, landlock_restrict_self(
+ fd, LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC));
+ EXPECT_EQ(EBADFD, errno);
}
-TEST(restrict_self_logging_flags)
+TEST(restrict_self_flags)
{
- const __u32 last_flag = LANDLOCK_RESTRICT_SELF_TSYNC;
+ const __u32 last_flag = LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC;
/* Tests invalid flag combinations. */
@@ -349,6 +357,12 @@ TEST(restrict_self_logging_flags)
LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON));
EXPECT_EQ(EBADF, errno);
+ EXPECT_EQ(-1,
+ landlock_restrict_self(
+ -1, LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF |
+ LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC));
+ EXPECT_EQ(EBADF, errno);
+
/* Tests with an invalid ruleset_fd. */
EXPECT_EQ(-1, landlock_restrict_self(
@@ -359,6 +373,243 @@ TEST(restrict_self_logging_flags)
-1, LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF));
}
+/*
+ * Exits with the NoNewPrivs value of the executed shell, as read from
+ * /proc/self/status, making the staged no_new_privs observable after an
+ * execve(2).
+ */
+static const char nnp_script[] =
+ "#!/bin/sh\n"
+ "while read -r label value; do\n"
+ " if [ \"$label\" = \"NoNewPrivs:\" ]; then\n"
+ " exit \"$value\"\n"
+ " fi\n"
+ "done < /proc/self/status\n"
+ "exit 42\n";
+
+/* Returns the no_new_privs value inherited through fork(2) and execve(2). */
+static int get_nnp_after_exec(const char *const script_path)
+{
+ int status;
+ const pid_t child = fork();
+
+ if (child < 0)
+ return -errno;
+
+ if (child == 0) {
+ char *const argv[] = { (char *)script_path, NULL };
+
+ execve(script_path, argv, NULL);
+ _exit(127);
+ }
+
+ if (waitpid(child, &status, 0) != child)
+ return -ECHILD;
+
+ if (!WIFEXITED(status))
+ return -EIO;
+
+ return WEXITSTATUS(status);
+}
+
+struct nnp_staging_thread {
+ const char *script_path;
+ int ruleset_fd;
+ __u32 flags;
+ int restrict_ret;
+ int restrict_errno;
+ int open_write_ret;
+ int open_write_errno;
+ int nnp_before_exec;
+ int nnp_after_exec;
+};
+
+/*
+ * Stages no_new_privs from a sibling thread of the test thread, so that the
+ * test thread can observe whether LANDLOCK_RESTRICT_SELF_TSYNC propagated the
+ * staged state.
+ */
+static void *stage_nnp_on_exec(void *data)
+{
+ struct nnp_staging_thread *const ctx = data;
+
+ ctx->restrict_ret = landlock_restrict_self(ctx->ruleset_fd, ctx->flags);
+ ctx->restrict_errno = errno;
+
+ /*
+ * Tries to open the script for writing to check that a ruleset passed
+ * along LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC is enforced immediately,
+ * unlike the staged no_new_privs.
+ */
+ ctx->open_write_ret = open(ctx->script_path, O_WRONLY | O_CLOEXEC);
+ ctx->open_write_errno = errno;
+ if (ctx->open_write_ret >= 0)
+ close(ctx->open_write_ret);
+
+ ctx->nnp_before_exec = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
+ ctx->nnp_after_exec = get_nnp_after_exec(ctx->script_path);
+ return NULL;
+}
+
+FIXTURE(nnp_on_exec)
+{
+ char script_path[sizeof("/tmp/landlock_nnp_XXXXXX")];
+};
+
+FIXTURE_VARIANT(nnp_on_exec)
+{
+ const bool with_ruleset;
+ const bool tsync;
+ const bool nnp_before;
+ const bool cap_sys_admin;
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(nnp_on_exec, no_ruleset) {
+ /* clang-format on */
+ .cap_sys_admin = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(nnp_on_exec, with_ruleset) {
+ /* clang-format on */
+ .with_ruleset = true,
+ .cap_sys_admin = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(nnp_on_exec, no_ruleset_tsync) {
+ /* clang-format on */
+ .tsync = true,
+ .cap_sys_admin = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(nnp_on_exec, with_ruleset_tsync) {
+ /* clang-format on */
+ .with_ruleset = true,
+ .tsync = true,
+ .cap_sys_admin = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(nnp_on_exec, nnp_already_set) {
+ /* clang-format on */
+ .nnp_before = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(nnp_on_exec, nnp_already_set_tsync) {
+ /* clang-format on */
+ .nnp_before = true,
+ .tsync = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(nnp_on_exec, unprivileged) {
+ /* clang-format on */
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(nnp_on_exec, unprivileged_tsync) {
+ /* clang-format on */
+ .tsync = true,
+};
+
+FIXTURE_SETUP(nnp_on_exec)
+{
+ int script_fd;
+
+ disable_caps(_metadata);
+
+ memcpy(self->script_path, "/tmp/landlock_nnp_XXXXXX",
+ sizeof(self->script_path));
+ script_fd = mkstemp(self->script_path);
+ ASSERT_LE(0, script_fd);
+ ASSERT_EQ(sizeof(nnp_script) - 1,
+ write(script_fd, nnp_script, sizeof(nnp_script) - 1));
+ ASSERT_EQ(0, fchmod(script_fd, 0700));
+ ASSERT_EQ(0, close(script_fd));
+}
+
+FIXTURE_TEARDOWN(nnp_on_exec)
+{
+ EXPECT_EQ(0, unlink(self->script_path));
+}
+
+TEST_F(nnp_on_exec, staging)
+{
+ /* The nnp/CAP_SYS_ADMIN gate applies even to stage-only calls. */
+ const bool expect_success = variant->nnp_before ||
+ variant->cap_sys_admin;
+ struct nnp_staging_thread staging = {
+ .script_path = self->script_path,
+ .ruleset_fd = -1,
+ .flags = LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC,
+ };
+ pthread_t thread;
+
+ if (variant->tsync)
+ staging.flags |= LANDLOCK_RESTRICT_SELF_TSYNC;
+
+ if (variant->with_ruleset) {
+ const struct landlock_ruleset_attr ruleset_attr = {
+ .handled_access_fs = LANDLOCK_ACCESS_FS_WRITE_FILE,
+ };
+
+ staging.ruleset_fd =
+ landlock_create_ruleset(&ruleset_attr,
+ sizeof(ruleset_attr), 0);
+ ASSERT_LE(0, staging.ruleset_fd);
+ }
+
+ if (variant->nnp_before)
+ ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
+ if (variant->cap_sys_admin)
+ set_cap(_metadata, CAP_SYS_ADMIN);
+
+ /* The staging thread inherits no_new_privs and capabilities. */
+ ASSERT_EQ(0, pthread_create(&thread, NULL, stage_nnp_on_exec,
+ &staging));
+ ASSERT_EQ(0, pthread_join(thread, NULL));
+
+ if (variant->cap_sys_admin)
+ clear_cap(_metadata, CAP_SYS_ADMIN);
+
+ if (expect_success) {
+ EXPECT_EQ(0, staging.restrict_ret);
+ } else {
+ EXPECT_EQ(-1, staging.restrict_ret);
+ EXPECT_EQ(EPERM, staging.restrict_errno);
+ }
+
+ /* A ruleset is enforced immediately, unlike the staged no_new_privs. */
+ if (variant->with_ruleset) {
+ EXPECT_EQ(-1, staging.open_write_ret);
+ EXPECT_EQ(EACCES, staging.open_write_errno);
+ } else {
+ EXPECT_LE(0, staging.open_write_ret);
+ }
+
+ /* Staging never sets no_new_privs before the execve(2)... */
+ EXPECT_EQ(variant->nnp_before, staging.nnp_before_exec);
+ /* ...but a successful call sets it for the executed program. */
+ EXPECT_EQ(expect_success, staging.nnp_after_exec);
+
+ /*
+ * On this sibling thread, the staged state is only visible if it was
+ * propagated with LANDLOCK_RESTRICT_SELF_TSYNC, and it is still not
+ * set before the execve(2).
+ */
+ EXPECT_EQ(variant->nnp_before,
+ prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));
+ EXPECT_EQ((variant->nnp_before || (expect_success && variant->tsync)),
+ get_nnp_after_exec(self->script_path));
+
+ if (variant->with_ruleset)
+ EXPECT_EQ(0, close(staging.ruleset_fd));
+}
+
TEST(ruleset_fd_io)
{
struct landlock_ruleset_attr ruleset_attr = {
--
2.54.0
^ permalink raw reply related
* [PATCH 1/3] landlock: Add LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
From: Justin Suess @ 2026-07-08 13:39 UTC (permalink / raw)
To: mic, linux-security-module; +Cc: gnoack, Justin Suess
In-Reply-To: <20260708133928.852999-1-utilityemal77@gmail.com>
Add a landlock_restrict_self(2) flag to stage no_new_privs so that it is
only set at the next execve(2) of the calling thread, past its point of
no return. This makes it possible to prepare an execution environment
where the new program runs with no_new_privs, without changing the
behavior of the calling program, and without leaving no_new_privs set if
the execve(2) fails.
The staged bit lives in the Landlock credential blob and is installed by
a new bprm_committing_creds hook. This flag does not relax the
no_new_privs/CAP_SYS_ADMIN requirement of landlock_restrict_self(2), and
may be used with a ruleset_fd of -1 to stage no_new_privs without
enforcing a ruleset. Combined with LANDLOCK_RESTRICT_SELF_TSYNC, the
staged state is propagated to sibling threads like the rest of the
Landlock credential state, and each thread then sets no_new_privs at its
own next execve(2).
Because no_new_privs is only set once the credentials of the new program
have been computed, this flag does not change how the next execve(2)
itself computes credentials: set-user-ID, set-group-ID and file
capabilities are still honored for that execution. The executed program
then runs with no_new_privs set, with its usual effect on subsequent
execve(2) calls.
Bump the Landlock ABI version to 11.
Cc: Mickaël Salaün <mic@digikod.net>
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
include/uapi/linux/landlock.h | 36 ++++++++++++++++++++++-
security/landlock/cred.c | 22 ++++++++++++++
security/landlock/cred.h | 8 ++++++
security/landlock/limits.h | 2 +-
security/landlock/syscalls.c | 54 ++++++++++++++++++++++++++---------
5 files changed, 107 insertions(+), 15 deletions(-)
diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h
index 7ffe2ef127ee..8d5b41d94c4a 100644
--- a/include/uapi/linux/landlock.h
+++ b/include/uapi/linux/landlock.h
@@ -190,13 +190,47 @@ struct landlock_ruleset_attr {
* logging configurations on these threads.
*
* If the calling thread is running with no_new_privs, this operation
- * enables no_new_privs on the sibling threads as well.
+ * enables no_new_privs on the sibling threads as well. If the calling
+ * thread has no_new_privs staged with
+ * %LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC (whether by the same call or a
+ * previous one), the staged state is propagated to the sibling threads as
+ * well.
+ *
+ * The following flag stages no_new_privs so that it only takes effect at the
+ * next :manpage:`execve(2)` of the calling thread, rather than immediately.
+ * It does not relax the permission check performed by
+ * sys_landlock_restrict_self(): the calling thread must still be running with
+ * no_new_privs or hold %CAP_SYS_ADMIN in its namespace.
+ *
+ * %LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
+ * Sets the no_new_privs attribute of the calling thread, but only at the
+ * next :manpage:`execve(2)` and past its point of no return, so a failed
+ * :manpage:`execve(2)` leaves the attribute unchanged. Because
+ * sys_landlock_restrict_self() already requires no_new_privs or
+ * %CAP_SYS_ADMIN, this flag cannot be used to defer around that
+ * requirement: when no_new_privs is already set it is effectively a
+ * no-op, and otherwise the caller must hold %CAP_SYS_ADMIN. This flag
+ * may be used with a @ruleset_fd value of -1 to stage no_new_privs
+ * without enforcing a ruleset.
+ *
+ * This flag does not change how the next :manpage:`execve(2)` itself
+ * computes credentials: set-user-ID, set-group-ID and file capabilities
+ * are still honored for that execution. The executed program then runs
+ * with no_new_privs set, with its usual effect on subsequent
+ * :manpage:`execve(2)` calls.
+ *
+ * Staging is per-thread by default. When combined with
+ * %LANDLOCK_RESTRICT_SELF_TSYNC, the staged no_new_privs is propagated
+ * to the sibling threads along with the rest of the Landlock
+ * configuration, and each thread then sets no_new_privs at its own next
+ * :manpage:`execve(2)`.
*/
/* clang-format off */
#define LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF (1U << 0)
#define LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON (1U << 1)
#define LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF (1U << 2)
#define LANDLOCK_RESTRICT_SELF_TSYNC (1U << 3)
+#define LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC (1U << 4)
/* clang-format on */
/**
diff --git a/security/landlock/cred.c b/security/landlock/cred.c
index cc419de75cd6..31fa4f78adef 100644
--- a/security/landlock/cred.c
+++ b/security/landlock/cred.c
@@ -10,6 +10,7 @@
#include <linux/binfmts.h>
#include <linux/cred.h>
#include <linux/lsm_hooks.h>
+#include <linux/sched.h>
#include "common.h"
#include "cred.h"
@@ -52,11 +53,32 @@ static int hook_bprm_creds_for_exec(struct linux_binprm *const bprm)
#endif /* CONFIG_AUDIT */
+/*
+ * Installs the no_new_privs attribute staged with
+ * LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC.
+ *
+ * This hook runs from begin_new_exec(), past the execution's point of no
+ * return: a binary that cannot be loaded (or any earlier failure) never reaches
+ * this point, so a failed execve(2) leaves the thread's no_new_privs attribute
+ * untouched.
+ */
+static void hook_bprm_committing_creds(const struct linux_binprm *const bprm)
+{
+ struct landlock_cred_security *const llcred = landlock_cred(bprm->cred);
+
+ if (llcred->set_nnp_on_exec) {
+ task_set_no_new_privs(current);
+ llcred->set_nnp_on_exec = 0;
+ }
+}
+
static struct security_hook_list landlock_hooks[] __ro_after_init = {
LSM_HOOK_INIT(cred_prepare, hook_cred_prepare),
LSM_HOOK_INIT(cred_transfer, hook_cred_transfer),
LSM_HOOK_INIT(cred_free, hook_cred_free),
+ LSM_HOOK_INIT(bprm_committing_creds, hook_bprm_committing_creds),
+
#ifdef CONFIG_AUDIT
LSM_HOOK_INIT(bprm_creds_for_exec, hook_bprm_creds_for_exec),
#endif /* CONFIG_AUDIT */
diff --git a/security/landlock/cred.h b/security/landlock/cred.h
index f287c56b5fd4..673206d3c3f3 100644
--- a/security/landlock/cred.h
+++ b/security/landlock/cred.h
@@ -35,6 +35,14 @@ struct landlock_cred_security {
*/
struct landlock_ruleset *domain;
+ /**
+ * @set_nnp_on_exec: Set if %LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
+ * requested that no_new_privs be enabled at the next execve(2).
+ * Propagated to sibling threads by %LANDLOCK_RESTRICT_SELF_TSYNC like
+ * the rest of this struct. Consumed by hook_bprm_committing_creds().
+ */
+ u8 set_nnp_on_exec : 1;
+
#ifdef CONFIG_AUDIT
/**
* @domain_exec: Bitmask identifying the domain layers that were enforced by
diff --git a/security/landlock/limits.h b/security/landlock/limits.h
index 08d5f2f6d321..29c190d00540 100644
--- a/security/landlock/limits.h
+++ b/security/landlock/limits.h
@@ -34,7 +34,7 @@
#define LANDLOCK_NUM_ACCESS_MAX \
MAX(MAX(LANDLOCK_NUM_ACCESS_FS, LANDLOCK_NUM_ACCESS_NET), LANDLOCK_NUM_SCOPE)
-#define LANDLOCK_LAST_RESTRICT_SELF LANDLOCK_RESTRICT_SELF_TSYNC
+#define LANDLOCK_LAST_RESTRICT_SELF LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
#define LANDLOCK_MASK_RESTRICT_SELF ((LANDLOCK_LAST_RESTRICT_SELF << 1) - 1)
/* clang-format on */
diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
index 36b02892c62f..daed1ea80455 100644
--- a/security/landlock/syscalls.c
+++ b/security/landlock/syscalls.c
@@ -169,7 +169,7 @@ static const struct file_operations ruleset_fops = {
* If the change involves a fix that requires userspace awareness, also update
* the errata documentation in Documentation/userspace-api/landlock.rst .
*/
-const int landlock_abi_version = 10;
+const int landlock_abi_version = 11;
/**
* sys_landlock_create_ruleset - Create a new ruleset
@@ -502,12 +502,21 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
* - %LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON
* - %LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF
* - %LANDLOCK_RESTRICT_SELF_TSYNC
+ * - %LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
*
* This system call enforces a Landlock ruleset on the current thread.
* Enforcing a ruleset requires that the task has %CAP_SYS_ADMIN in its
* namespace or is running with no_new_privs. This avoids scenarios where
* unprivileged tasks can affect the behavior of privileged children.
*
+ * With %LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC, no_new_privs is not set
+ * immediately but staged to be set at the next execve(2), past its point of no
+ * return. This flag does not relax the no_new_privs / %CAP_SYS_ADMIN
+ * requirement above. Staging is per-thread by default; when combined with
+ * %LANDLOCK_RESTRICT_SELF_TSYNC, the staged no_new_privs is propagated to the
+ * sibling threads along with the rest of the Landlock credential state, and
+ * each thread then sets no_new_privs at its own next execve(2).
+ *
* Return: 0 on success, or -errno on failure. Possible returned errors are:
*
* - %EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
@@ -526,6 +535,10 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
flags)
{
+ /* Flags that do not require a ruleset_fd. */
+ const __u32 fd_optional_flags =
+ LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF |
+ LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC;
struct landlock_ruleset *ruleset __free(landlock_put_ruleset) = NULL;
struct cred *new_cred;
struct landlock_cred_security *new_llcred;
@@ -538,6 +551,10 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
/*
* Similar checks as for seccomp(2), except that an -EPERM may be
* returned.
+ *
+ * This gate runs before any flag-specific handling, so
+ * LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC cannot be used to defer around the
+ * no_new_privs / CAP_SYS_ADMIN requirement.
*/
if (!task_no_new_privs(current) &&
!ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN))
@@ -555,14 +572,15 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
log_subdomains = !(flags & LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF);
/*
- * It is allowed to set LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF with
- * -1 as ruleset_fd, optionally combined with
- * LANDLOCK_RESTRICT_SELF_TSYNC to propagate this configuration to all
- * threads. No other flag must be set.
+ * A ruleset is not required when only muting subdomain logs
+ * (LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF, optionally combined with
+ * LANDLOCK_RESTRICT_SELF_TSYNC to propagate it to all threads) and/or
+ * staging no_new_privs on exec (LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC).
+ * Such calls may pass -1 as ruleset_fd. Any other flag (or the absence
+ * of these) requires a real ruleset.
*/
- if (!(ruleset_fd == -1 &&
- (flags & ~LANDLOCK_RESTRICT_SELF_TSYNC) ==
- LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF)) {
+ if (!(ruleset_fd == -1 && (flags & fd_optional_flags) &&
+ !(flags & ~(fd_optional_flags | LANDLOCK_RESTRICT_SELF_TSYNC)))) {
/* Gets and checks the ruleset. */
ruleset = get_ruleset_from_fd(ruleset_fd, FMODE_CAN_READ);
if (IS_ERR(ruleset))
@@ -583,11 +601,12 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
#endif /* CONFIG_AUDIT */
/*
- * The only case when a ruleset may not be set is if
- * LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF is set (optionally with
- * LANDLOCK_RESTRICT_SELF_TSYNC) and ruleset_fd is -1. We could
- * optimize this case by not calling commit_creds() if this flag was
- * already set, but it is not worth the complexity.
+ * A ruleset may legitimately be absent here when only muting subdomain
+ * logs (LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF, optionally with
+ * LANDLOCK_RESTRICT_SELF_TSYNC) and/or staging no_new_privs on exec
+ * (LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC) with ruleset_fd == -1. We could
+ * optimize some of these cases by not calling commit_creds(), but it is
+ * not worth the complexity.
*/
if (ruleset) {
/*
@@ -618,6 +637,15 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
#endif /* CONFIG_AUDIT */
}
+ /*
+ * Stages no_new_privs to be set at the next execve(2). Because the bit
+ * lives in new_cred, TSYNC below propagates it to the sibling threads
+ * (whether it was staged by this call or a previous one), and each
+ * thread then sets no_new_privs at its own next execve(2).
+ */
+ if (flags & LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC)
+ new_llcred->set_nnp_on_exec = 1;
+
if (flags & LANDLOCK_RESTRICT_SELF_TSYNC) {
const int err = landlock_restrict_sibling_threads(
current_cred(), new_cred);
--
2.54.0
^ permalink raw reply related
* [PATCH 0/3] Implement LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
From: Justin Suess @ 2026-07-08 13:39 UTC (permalink / raw)
To: mic, linux-security-module; +Cc: gnoack, Justin Suess
Good morning,
This series adds a new landlock_restrict_self(2) flag:
LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC.
This flag stages a bit in the Landlock credentials indicating that the
next successful execution will set the no_new_privs attribute while
committing its new credentials.
Differences from prctl(PR_SET_NO_NEW_PRIVS):
PR_SET_NO_NEW_PRIVS takes effect immediately: it prevents gaining
privileges through set-user-ID, set-group-ID and file capabilities
starting with the very next execve(2).
LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC instead only sets the task's
no_new_privs attribute once the next execve(2) is guaranteed to succeed
(past its point of no return, in bprm_committing_creds), after any
privilege gain through set-user-ID, set-group-ID or file capabilities
has already taken place. The executed program then runs with
no_new_privs, so subsequent executions cannot gain privileges. A
failed execve(2) leaves no_new_privs untouched.
Use cases:
Enforcing a Landlock ruleset requires that the calling process either
already has no_new_privs set or possesses CAP_SYS_ADMIN. This series
does not grant any exception to this rule; for a caller that already
has no_new_privs set, the flag is effectively a no-op. It is therefore
mostly useful for CAP_SYS_ADMIN callers that need to execute programs
that legitimately escalate privileges (e.g. transition to another
user), while ensuring that further executions cannot gain privileges.
Consider a sandbox launcher that depends on a set-user-ID helper, such
as launching applications through bubblewrap on distributions where
unprivileged user namespaces are disabled and bwrap is installed
set-user-ID root. The launcher cannot set PR_SET_NO_NEW_PRIVS before
the execution, as that would neuter the very helper it depends on:
sandbox launcher (CAP_SYS_ADMIN)
|
| landlock_restrict_self(-1, LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC)
V
/usr/bin/bwrap (set-user-ID root: honored for this execution;
| no_new_privs set once the execution is past its
| point of no return)
V
sandboxed application (runs with no_new_privs; cannot gain
privileges through any further execution, and
may enforce its own Landlock ruleset without
CAP_SYS_ADMIN)
This flag also closes a gap for CAP_SYS_ADMIN callers of
landlock_restrict_self(2) itself. The no_new_privs/CAP_SYS_ADMIN
requirement exists to keep set-user-ID programs from running confused
inside a sandbox they do not expect. However, a privileged process
that enforces a domain without setting no_new_privs leaves that hole
open for all of its descendants: anything running in the domain may
still execute a set-user-ID binary, which then runs privileged under a
restricted view of the system. A privileged process that needs one
legitimate set-user-ID/set-group-ID transition currently has to choose
between breaking that transition (setting no_new_privs first) or
leaving the hole open for the lifetime of the domain.
LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC allows the one intended transition
and then closes the hole.
Design:
This flag is implemented simply: a bit is stored in the Landlock
credential blob (struct landlock_cred_security) indicating whether the
next execution should set no_new_privs when it commits its new
credentials.
The bit is not coupled to any ruleset and, like
LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF, may be passed with no
ruleset (i.e. ruleset_fd = -1). It may also be combined with
LANDLOCK_RESTRICT_SELF_TSYNC to propagate the staged state to sibling
threads, each thread then setting no_new_privs at its own next
execve(2).
The staged bit is inherited across fork(2) and persists in the
credentials until the next successful execution. To consume it,
Landlock handles the bprm_committing_creds hook, which runs while the
credentials of the new program are being committed: if the bit is set,
task_set_no_new_privs(current) is called and the bit is cleared.
Again, this flag does not bypass the requirement to either have
CAP_SYS_ADMIN or no_new_privs already set to call
landlock_restrict_self(2).
The Landlock ABI version is bumped to 11.
Test coverage:
The new nnp_on_exec fixture generates a shell script that reads the
NoNewPrivs value from /proc/self/status and exits with it. The
variants select the conditions under which the flag is tested (with
and without a ruleset, with and without CAP_SYS_ADMIN/no_new_privs
already set, with and without TSYNC, etc.), then compare no_new_privs
before the execution and in the executed script. The ruleset variants
also check that a ruleset passed along the flag is enforced
immediately, unlike the staged no_new_privs.
Justin Suess (3):
landlock: Add LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
selftests/landlock: Test LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
landlock: Document LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
Documentation/userspace-api/landlock.rst | 21 +-
include/uapi/linux/landlock.h | 36 ++-
security/landlock/cred.c | 22 ++
security/landlock/cred.h | 8 +
security/landlock/limits.h | 2 +-
security/landlock/syscalls.c | 54 +++-
tools/testing/selftests/landlock/base_test.c | 259 ++++++++++++++++++-
7 files changed, 382 insertions(+), 20 deletions(-)
--
2.54.0
^ permalink raw reply
* Re: [PATCH v5 bpf-next 0/3] bpf: add bpf_init_inode_xattr kfunc for atomic inode labeling
From: David Windsor @ 2026-07-08 12:51 UTC (permalink / raw)
To: Kumar Kartikeya Dwivedi
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Jiri Olsa, Emil Tsalapatis,
Matt Bobrowski, Paul Moore, James Morris, Serge E . Hallyn,
Casey Schaufler, Stephen Smalley, Ondrej Mosnacek, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Alexander Viro,
Christian Brauner, Jan Kara, Shuah Khan, bpf,
linux-security-module, linux-fsdevel, linux-integrity, selinux,
linux-kselftest, linux-kernel
In-Reply-To: <DJSV0P2OINKE.34OCOC34KFEEF@gmail.com>
On Tue, Jul 7, 2026 at 11:12 PM Kumar Kartikeya Dwivedi
<memxor@gmail.com> wrote:
>
> On Wed Jul 8, 2026 at 2:09 AM CEST, David Windsor wrote:
> > Many in-kernel LSMs (SELinux, Smack, IMA) store security labels in
> > extended attributes. For these LSMs, atomic labeling during inode
> > creation is critical: if the inode becomes accessible before its xattr
> > is set, it is briefly unlabeled, which can disrupt LSMs making policy
> > decisions based on file labels.
> >
> > Existing LSMs solve this by setting xattrs directly in the
> > inode_init_security hook, which runs before the inode becomes
> > accessible. BPF LSM programs currently lack this capability because
> > the hook uses an output parameter (xattr_count) that BPF programs
> > cannot write to, and existing kfuncs like bpf_set_dentry_xattr
> > require a dentry that isn't available until after the inode is
> > accessible.
> >
> > This series introduces the bpf_init_inode_xattr() kfunc, which takes
> > the combined inode_init_security xattr context argument and claims a
> > slot in it via the new security_lsmxattr_add() LSM helper.
> >
>
> There are various CI failures in newly added tests, I don't think any of them
> are passing. Please fix before respinning.
>
> https://github.com/kernel-patches/bpf/pull/12730
>
> E.g. both test_init_inode_xattr and test_init_inode_xattr_slot do not have
> expected results.
>
This is happening because the path "/tmp" in bpf ci isn't mounted on
tmpfs, rather on 9p:
[ 5.813072] VFS: Mounted root (9p filesystem) on device 0:22.
[ 5.924390] vmtest: Mounting tmpfs at /dev/shm
[ 5.971012] vmtest: Mounting tmpfs at /run
[ 6.096271] vmtest: Mounting tmpfs at /mnt
... which doesn't call inode_init_security. Changing the test to
create its file in /dev/shm, which has a real tmpfs, fixes this. We
can update the test to skip on filesystems where the hook doesn't
fire.
I'll wait to gather feedback from Alexei and Paul before sending v6.
> pw-bot: cr
>
> > [...]
^ permalink raw reply
* [RFC/discuss] memfd_secret(): opt-in visibility for security monitoring (eBPF/audit)
From: BoxStrikesTeam @ 2026-07-08 12:09 UTC (permalink / raw)
To: rppt@kernel.org, akpm@linux-foundation.org
Cc: linux-mm@kvack.org, linux-security-module@vger.kernel.org,
paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com
Hi,
While experimenting with mseal() and memfd_secret() together on a
recent kernel, I ran into what looks like a gap worth discussing:
content placed in memfd_secret()-backed memory is invisible not just
to other processes, but also to in-kernel tracing/observability
mechanisms such as eBPF's bpf_probe_read_user() (EFAULT, as expected,
since the region is removed from the direct map and kernel page
tables entirely).
That's working as designed for the threat model memfd_secret targets
(protect secrets even from a compromised kernel / ROP-based
exfiltration). But it does mean a local, unprivileged process can
now allocate memory that:
1. Is invisible to kernel-side introspection (eBPF tracing,
/proc/<pid>/mem, ptrace-based tooling) once populated via
memfd_secret(), and
2. Can additionally be sealed against mprotect()/munmap()/mremap()
via mseal() so its protection bits can't be relaxed either.
Neither primitive alone is new or alarming - mseal() protects mapping
metadata, not confidentiality, and memfd_secret() is explicitly
opt-in and disabled by default. But combined, they let a process
carve out a region that a host-based EDR relying on eBPF
tracing/probe_read helpers cannot inspect, and cannot force back into
an inspectable state either. For userland security tooling that
assumes 'anything a tracing eBPF program can attach to, it can read',
this is a small blind spot.
I want to be clear I'm not suggesting memfd_secret()'s core guarantee
should be weakened - the ability to keep data hidden from a
compromised kernel is the entire point, and forcibly exposing content
to tracing programs would undermine that model and create a new
attack surface via the eBPF verifier/helper path itself.
What I'd like to raise for discussion instead is something closer to
what was already anticipated in the original series - Mike, your
commit message for memfd_secret() mentions: 'Once there will be a use
case that will require exposing secretmem to the kernel it will be an
opt-in request in the system call flags.' Two lighter-weight
directions that stay consistent with that opt-in philosophy:
a) An LSM hook / audit event at memfd_secret() call time (this
echoes Christian Gottsche's 2022 RFC to label secretmem inodes
via inode_init_security_anon for SELinux). Even without content
visibility, logging 'process X created a N-byte kernel-invisible
mapping' gives EDR/audit systems a behavioral signal to alert on,
without touching the confidentiality guarantee at all.
b) A distinct opt-in flag (as foreshadowed in the original commit)
that a process could set to allow a CAP_BPF/CAP_SYS_ADMIN-gated
tracing context to read the region for legitimate
monitoring/debugging - fully opt-in, off by default, and never
implicitly available to unprivileged tracers.
Is (a) something that's been considered further since the 2022
secretmem-inode-labeling thread? And is there any existing tracking
issue for the kind of opt-in-visibility idea in (b), or was it
dropped as not worth the complexity?
Happy to help test/write a small selftest if there's interest in
pursuing either direction.
Thanks,
BoxStrike Team.
Researcher:Eneshan Erdoğan Karaca, Other ananymous
Researcher emails:cyberblackk@proton.me
^ permalink raw reply
* [PATCH v1] landlock: Update formatting
From: Mickaël Salaün @ 2026-07-08 11:06 UTC (permalink / raw)
To: Günther Noack
Cc: Mickaël Salaün, linux-security-module, Bart Van Assche,
Miguel Ojeda
Following commit 99df2a8eba34 ("clang-format: fix formatting of guard()
and scoped_guard() statements"), update scoped_guard() formatting.
Also, see the related fix [1].
Cc: Günther Noack <gnoack@google.com>
Cc: Miguel Ojeda <ojeda@kernel.org>
Link: https://lore.kernel.org/r/20260708105713.2073335-1-mic@digikod.net [1]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
---
security/landlock/task.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/security/landlock/task.c b/security/landlock/task.c
index 7ddf211f75c3..360d226d0f51 100644
--- a/security/landlock/task.c
+++ b/security/landlock/task.c
@@ -95,8 +95,7 @@ static int hook_ptrace_access_check(struct task_struct *const child,
if (!parent_subject)
return 0;
- scoped_guard(rcu)
- {
+ scoped_guard(rcu) {
const struct landlock_ruleset *const child_dom =
landlock_get_task_domain(child);
err = domain_ptrace(parent_subject->domain, child_dom);
@@ -370,8 +369,7 @@ static int hook_task_kill(struct task_struct *const p,
if (!subject)
return 0;
- scoped_guard(rcu)
- {
+ scoped_guard(rcu) {
is_scoped = domain_is_scoped(subject->domain,
landlock_get_task_domain(p),
signal_scope.scope);
@@ -422,8 +420,7 @@ static int hook_file_send_sigiotask(struct task_struct *tsk,
if (task_tgid(tsk) == landlock_file(fown->file)->fown_tg)
return 0;
- scoped_guard(rcu)
- {
+ scoped_guard(rcu) {
is_scoped = domain_is_scoped(subject->domain,
landlock_get_task_domain(tsk),
signal_scope.scope);
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v2] selftests/landlock: fix spelling error in fs_test comment
From: Mickaël Salaün @ 2026-07-08 10:42 UTC (permalink / raw)
To: Wang Yan
Cc: gnoack, shuah, linux-security-module, linux-kselftest,
linux-kernel
In-Reply-To: <20260702015823.368529-1-wangyan01@kylinos.cn>
Applied, thanks!
On Thu, Jul 02, 2026 at 09:58:23AM +0800, Wang Yan wrote:
> Fix typo "allowes" -> "allows" in Landlock filesystem test comment.
>
> Signed-off-by: Wang Yan <wangyan01@kylinos.cn>
> ---
> tools/testing/selftests/landlock/fs_test.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c
> index 86e08aa6e0a7..e672089e9329 100644
> --- a/tools/testing/selftests/landlock/fs_test.c
> +++ b/tools/testing/selftests/landlock/fs_test.c
> @@ -6927,7 +6927,7 @@ TEST_F_FORK(layout2_overlay, same_content_different_file)
> ASSERT_EQ(0, test_open(path_entry, O_RDWR));
> }
>
> - /* Only allowes access to the merge hierarchy. */
> + /* Only allows access to the merge hierarchy. */
> enforce_fs(_metadata, ACCESS_RW, layer5_merge_only);
>
> /* Checks new accesses on lower layer. */
> --
> 2.25.1
>
>
^ permalink raw reply
* Re: [PATCH] landlock: Documentation wording cleanups
From: Mickaël Salaün @ 2026-07-08 10:40 UTC (permalink / raw)
To: Günther Noack
Cc: linux-doc, linux-security-module, Alejandro Colomar,
Alejandro Colomar
In-Reply-To: <20260516190112.4924-1-gnoack3000@gmail.com>
Thanks, applied!
On Sat, May 16, 2026 at 09:01:12PM +0200, Günther Noack wrote:
> Documentation cleanups suggested by Alejandro Colomar,
> which we have also applied in the man pages.
>
> Link: https://lore.kernel.org/all/agW4yMK6CinJGqXt@devuan/
> Suggested-by: Alejandro Colomar <alx@kernel.org>
> Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> ---
> include/uapi/linux/landlock.h | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h
> index 10a346e55e95..48c12ddf1108 100644
> --- a/include/uapi/linux/landlock.h
> +++ b/include/uapi/linux/landlock.h
> @@ -255,16 +255,16 @@ struct landlock_net_port_attr {
> * :manpage:`connect(2)` as well as calls to :manpage:`sendmsg(2)` with an
> * explicit recipient address.
> *
> - * This access right only applies to connections to UNIX server sockets which
> + * This access right applies only to connections to UNIX server sockets which
> * were created outside of the newly created Landlock domain (e.g. from within
> * a parent domain or from an unrestricted process). Newly created UNIX
> * servers within the same Landlock domain continue to be accessible. In this
> * regard, %LANDLOCK_ACCESS_FS_RESOLVE_UNIX has the same semantics as the
> * ``LANDLOCK_SCOPE_*`` flags.
> *
> - * If a resolve attempt is denied, the operation returns an ``EACCES`` error,
> - * in line with other filesystem access rights (but different to denials for
> - * abstract UNIX domain sockets).
> + * If a resolution attempt is denied, the operation returns an ``EACCES``
> + * error, in line with other filesystem access rights (but different to
> + * denials for abstract UNIX domain sockets).
> *
> * This access right is available since the ninth version of the Landlock ABI.
> *
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH bpf-next v6 5/8] bpftool: Cover loader metadata with the program signature
From: Quentin Monnet @ 2026-07-08 8:55 UTC (permalink / raw)
To: Daniel Borkmann, ast
Cc: kpsingh, James.Bottomley, paul, bboscaccy, memxor, torvalds,
a.s.protopopov, bpf, linux-security-module
In-Reply-To: <20260708075343.358712-6-daniel@iogearbox.net>
On 08/07/2026 08:53, Daniel Borkmann wrote:
> bpftool_prog_sign() signed only the loader instructions. The metadata
> blob the loader installs was left to an in-loader hash check, which
> the kernel now performs at load time over insns || metadata.
>
> Sign that same concatenation: pass the metadata blob (gen_loader_opts
> data) through to bpftool_prog_sign() and feed insns || metadata to
> CMS_final(). The excl_prog_hash stays a digest of the instructions
> alone; it binds the metadata map to the loader and is matched against
> prog->digest by the verifier, independent of what the signature covers.
>
> The signed artifact is now plain data: both bytes the signature
> covers are embedded verbatim in the generated skeleton, so signing
> and verifying an lskel is an ordinary CMS operation that a signer or
> auditor can perform (or reproduce) offline, without analyzing loader
> bytecode to establish what the signature actually attests to.
>
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Quentin Monnet <qmo@kernel.org>
Thanks!
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox