* [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
* [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 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
* 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
* 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 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 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 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: [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: [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: [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
* [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: 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
* 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 0/3] Implement LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
From: Mickaël Salaün @ 2026-07-09 10:09 UTC (permalink / raw)
To: Justin Suess; +Cc: linux-security-module, gnoack
In-Reply-To: <20260708133928.852999-1-utilityemal77@gmail.com>
Hi Justin,
Thanks for this patch series, I like the underlying idea, but I'm not
convince we should mix NNP and ON_EXEC. Why not a
LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS flag instead?
One issue with this NNP_ON_EXEC is that it might be confusing for one
thread to set it and expect the next exec to be NNP, but if the exec is
requested by another thread that would not happen. With a
LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS flag, we could have an atomic
Landlock and NNP enforcement, which can also be combined with the TSYNC
flag, both useful cases.
If we want an enforcement to happen at exec time, we could add a
dedicated flag, similar to the TSYNC one, but I'm not sure it would be
useful for now.
On Wed, Jul 08, 2026 at 09:39:24AM -0400, Justin Suess wrote:
> 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.
That's a good point, but why not just set NNP for the whole process at
landlock_restrict_self() call time? There is a partial answer below
but...
>
> 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)
This should only be allowed if the launcher has CAP_SYS_ADMIN, otherwise
it would be like changing the state of a more privileged process.
Anyway, even with this safeguard, this approach looks risky.
> 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.
In a nutshell, not setting NNP might be risky, even when not strictly
needed. We might want to update the Landlock doc with that.
>
> 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.
Also, if we don't have the ON_EXEC part, there is no need to store
anything in the cred.
>
> 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 0/3] Implement LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
From: Simon McVittie @ 2026-07-09 11:22 UTC (permalink / raw)
To: Mickaël Salaün; +Cc: Justin Suess, linux-security-module, gnoack
In-Reply-To: <20260709.Eaphooyoh6sh@digikod.net>
On Thu, 09 Jul 2026 at 12:09:25 +0200, Mickaël Salaün wrote:
> On Wed, Jul 08, 2026 at 09:39:24AM -0400, Justin Suess wrote:
> > 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.
It's perhaps worth noting that the current version 0.11.2 of bubblewrap
deprecates this mode of use (it will refuse to run while setuid unless
that was explicitly enabled at compile-time), and the next release 0.12.0
will also remove the ability to enable it at compile-time.
When bubblewrap was first written, having it be setuid was a necessary
workaround for kernels/distros not letting it do its sandboxing job any
other way; but now that unprivileged user namespaces are more widespread,
its maintainers have come to the conclusion that when it's setuid,
the risk of vulnerabilities that allow a root privilege escalation
(CVE-2020-5291, CVE-2026-41163) is unacceptably high, so being able to
make it setuid is no longer a good trade-off.
> > 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
>
> In a nutshell, not setting NNP might be risky, even when not strictly
> needed. We might want to update the Landlock doc with that.
If the CAP_SYS_ADMIN caller is setuid or setcap, then it has been
granted special privileges by the sysadmin or distro, and part of
the "contract" between the sysadmin/distro and the setuid program is
that setuid/setcap must only be set on executables that have taken
responsibility for ensuring that they can't create insecure situations
(for example bubblewrap always sets PR_SET_NO_NEW_PRIVS, unconditionally,
for this reason).
A large part of why bubblewrap no longer supports being setuid is that
its maintainers don't want it to have this heavy responsibility.
smcv
^ permalink raw reply
* Re: [PATCH v2] NFSv4.2: fix nfs4_listxattr size accounting
From: Stephen Smalley @ 2026-07-09 12:32 UTC (permalink / raw)
To: Paul Moore
Cc: Anna Schumaker, Achilles Gaikwad, Trond Myklebust, linux-nfs,
linux-security-module, selinux
In-Reply-To: <CAHC9VhSyCuiPBRWz_vUbx7+L5yLiXkjKX+7UyCLr82-_gAj2NQ@mail.gmail.com>
On Wed, Jul 8, 2026 at 4:11 PM Paul Moore <paul@paul-moore.com> wrote:
>
> 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.
I was on F44, so yes, it could be a difference in e.g. coreutils or
other userspace on rawhide that is tickling this particular bug.
^ permalink raw reply
* Re: [PATCH v2 1/9] security: add LSM blob and hooks for namespaces
From: Paul Moore @ 2026-07-09 13:03 UTC (permalink / raw)
To: Mickaël Salaün
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: <20260709.kaemaiTia6Li@digikod.net>
On Thu, Jul 9, 2026 at 5:12 AM Mickaël Salaün <mic@digikod.net> wrote:
> 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.
...
> > > @@ -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.
I don't have a strong opinion on either approach, either a separate
patch or doc update, but one of the two needs to happen.
> > > 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.
I'm aware of the new hook guidance, I was the one who documented it :)
In the future, it's both helpful and polite to reply to the email
asking the question with your response. Adding it to the cover letter
is fine, but to be perfectly honest, once we get past v1 of a
patchset, I don't often read the cover letter very closely unless
there is a significant change. However, I do look back at the
previous posting to ensure all the feedback from everyone has been
either answered or incorporated into the current revision.
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH v2 1/9] security: add LSM blob and hooks for namespaces
From: Mickaël Salaün @ 2026-07-09 15:58 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: <CAHC9VhSVQ0MLwU=C90FmohAThwaQj-mfB7L03fvkB5A0-J2jCg@mail.gmail.com>
On Thu, Jul 09, 2026 at 09:03:58AM -0400, Paul Moore wrote:
> On Thu, Jul 9, 2026 at 5:12 AM Mickaël Salaün <mic@digikod.net> wrote:
> > 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.
>
> ...
>
> > > > @@ -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.
>
> I don't have a strong opinion on either approach, either a separate
> patch or doc update, but one of the two needs to happen.
Noted, I'll follow on this with Christian.
>
> > > > 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.
>
> I'm aware of the new hook guidance, I was the one who documented it :)
I know. I guess that means you're ok with that?
>
> In the future, it's both helpful and polite to reply to the email
> asking the question with your response. Adding it to the cover letter
> is fine, but to be perfectly honest, once we get past v1 of a
> patchset, I don't often read the cover letter very closely unless
> there is a significant change. However, I do look back at the
> previous posting to ensure all the feedback from everyone has been
> either answered or incorporated into the current revision.
I forgot to reply to your email, I didn't mean to be impolite, sorry for
the inconvenience. It's useful to know that the cover letter is not
always part of your review process.
^ permalink raw reply
* [PATCH] selftests/landlock: Fix screwed up pointers in the scoped_signal_test
From: Thomas Huth @ 2026-07-09 16:43 UTC (permalink / raw)
To: Mickaël Salaün, Günther Noack,
linux-security-module
Cc: Shuah Khan, linux-kselftest, linux-kernel, rbriggs
From: Thomas Huth <thuth@redhat.com>
The scoped_signal_test uses pthread_join(..., (void **)&ret)) in
a couple of places, i.e. the return value of the thread is stored
in the shape of a "void *" into the memory location of &ret.
Pointers are 64-bit on modern computers, but the ret variable is
declared as a simple "enum thread_return" which is only 32 bits.
So the pthread_join() will overflow the ret variable by 4 byte.
The problem is very visible on big endian systems like s390x
where the test is failing: The least significant byte that carries
the return code of the thread is not written into the ret variable
here, but somewhere else in the stack frame, so the comparison
for the right return code is failing here.
Fix it by getting rid of the enum and defining the THREAD_* constants
and "ret" variables as proper "void *" pointers. This way we can
also get rid of some ugly (void *) castings in a couple of spots.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
.../selftests/landlock/scoped_signal_test.c | 44 +++++++++----------
1 file changed, 21 insertions(+), 23 deletions(-)
diff --git a/tools/testing/selftests/landlock/scoped_signal_test.c b/tools/testing/selftests/landlock/scoped_signal_test.c
index f24f2c28f62e5..58d25157fe781 100644
--- a/tools/testing/selftests/landlock/scoped_signal_test.c
+++ b/tools/testing/selftests/landlock/scoped_signal_test.c
@@ -249,12 +249,10 @@ TEST_F(scoped_domains, check_access_signal)
_metadata->exit_code = KSFT_FAIL;
}
-enum thread_return {
- THREAD_INVALID = 0,
- THREAD_SUCCESS = 1,
- THREAD_ERROR = 2,
- THREAD_TEST_FAILED = 3,
-};
+#define THREAD_INVALID ((void *)0)
+#define THREAD_SUCCESS ((void *)1)
+#define THREAD_ERROR ((void *)2)
+#define THREAD_TEST_FAILED ((void *)3)
static void *thread_sync(void *arg)
{
@@ -262,15 +260,15 @@ static void *thread_sync(void *arg)
char buf;
if (read(pipe_read, &buf, 1) != 1)
- return (void *)THREAD_ERROR;
+ return THREAD_ERROR;
- return (void *)THREAD_SUCCESS;
+ return THREAD_SUCCESS;
}
TEST(signal_scoping_thread_before)
{
pthread_t no_sandbox_thread;
- enum thread_return ret = THREAD_INVALID;
+ void *ret = THREAD_INVALID;
int thread_pipe[2];
drop_caps(_metadata);
@@ -285,7 +283,7 @@ TEST(signal_scoping_thread_before)
EXPECT_EQ(0, pthread_kill(no_sandbox_thread, 0));
EXPECT_EQ(1, write(thread_pipe[1], ".", 1));
- EXPECT_EQ(0, pthread_join(no_sandbox_thread, (void **)&ret));
+ EXPECT_EQ(0, pthread_join(no_sandbox_thread, &ret));
EXPECT_EQ(THREAD_SUCCESS, ret);
EXPECT_EQ(0, close(thread_pipe[0]));
@@ -295,7 +293,7 @@ TEST(signal_scoping_thread_before)
TEST(signal_scoping_thread_after)
{
pthread_t scoped_thread;
- enum thread_return ret = THREAD_INVALID;
+ void *ret = THREAD_INVALID;
int thread_pipe[2];
drop_caps(_metadata);
@@ -310,7 +308,7 @@ TEST(signal_scoping_thread_after)
EXPECT_EQ(0, pthread_kill(scoped_thread, 0));
EXPECT_EQ(1, write(thread_pipe[1], ".", 1));
- EXPECT_EQ(0, pthread_join(scoped_thread, (void **)&ret));
+ EXPECT_EQ(0, pthread_join(scoped_thread, &ret));
EXPECT_EQ(THREAD_SUCCESS, ret);
EXPECT_EQ(0, close(thread_pipe[0]));
@@ -327,20 +325,20 @@ void *thread_setuid(void *ptr)
char buf;
if (read(arg->pipe_read, &buf, 1) != 1)
- return (void *)THREAD_ERROR;
+ return THREAD_ERROR;
/* libc's setuid() should update all thread's credentials. */
if (getuid() != arg->new_uid)
- return (void *)THREAD_TEST_FAILED;
+ return THREAD_TEST_FAILED;
- return (void *)THREAD_SUCCESS;
+ return THREAD_SUCCESS;
}
TEST(signal_scoping_thread_setuid)
{
struct thread_setuid_args arg;
pthread_t no_sandbox_thread;
- enum thread_return ret = THREAD_INVALID;
+ void *ret = THREAD_INVALID;
int pipe_parent[2];
int prev_uid;
@@ -367,7 +365,7 @@ TEST(signal_scoping_thread_setuid)
EXPECT_EQ(arg.new_uid, getuid());
EXPECT_EQ(1, write(pipe_parent[1], ".", 1));
- EXPECT_EQ(0, pthread_join(no_sandbox_thread, (void **)&ret));
+ EXPECT_EQ(0, pthread_join(no_sandbox_thread, &ret));
EXPECT_EQ(THREAD_SUCCESS, ret);
clear_cap(_metadata, CAP_SETUID);
@@ -667,20 +665,20 @@ static void *thread_setown_scoped(void *arg)
ruleset_fd =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
if (ruleset_fd < 0)
- return (void *)THREAD_ERROR;
+ return THREAD_ERROR;
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
landlock_restrict_self(ruleset_fd, 0)) {
close(ruleset_fd);
- return (void *)THREAD_ERROR;
+ return THREAD_ERROR;
}
close(ruleset_fd);
/* Makes this process group own the SIGIO source. */
if (fcntl(fd, F_SETSIG, SIGURG) || fcntl(fd, F_SETOWN, -getpgrp()) ||
fcntl(fd, F_SETFL, O_ASYNC))
- return (void *)THREAD_ERROR;
+ return THREAD_ERROR;
- return (void *)THREAD_SUCCESS;
+ return THREAD_SUCCESS;
}
/*
@@ -702,7 +700,7 @@ TEST(sigio_to_pgid_self)
{
int trigger[2];
pthread_t thread;
- enum thread_return ret = THREAD_INVALID;
+ void *ret = THREAD_INVALID;
int i;
drop_caps(_metadata);
@@ -722,7 +720,7 @@ TEST(sigio_to_pgid_self)
*/
ASSERT_EQ(0, pthread_create(&thread, NULL, thread_setown_scoped,
&trigger[0]));
- ASSERT_EQ(0, pthread_join(thread, (void **)&ret));
+ ASSERT_EQ(0, pthread_join(thread, &ret));
ASSERT_EQ(THREAD_SUCCESS, ret);
/* Fans SIGURG out to the process group. */
--
2.55.0
^ permalink raw reply related
* [PATCH] PM: hibernate: Allow hibernation opt-in when locked down
From: Sean Rhodes @ 2026-07-09 19:23 UTC (permalink / raw)
To: rafael
Cc: lenb, pavel, corbet, skhan, paul, jmorris, serge,
nicolas.bouchinet, xiujianfeng, keescook, linux-pm, linux-doc,
linux-security-module, linux-kernel
Kernel lockdown disables hibernation because the resume image cannot be
verified before it is restored. On systems where external platform or
storage policy protects the hibernation image from offline modification,
users may still need hibernation while lockdown is active.
Add a hibernate=allow_locked_down command line option to make that opt-in
explicit. This only bypasses the LOCKDOWN_HIBERNATION gate; nohibernate,
secretmem and CXL memory restrictions still apply.
The kernel does not validate the external policy or authenticate the image
with this option.
Build-tested with Fedora config:
make O=../linux-lockdown-hibernate-build kernel/power/hibernate.o
Signed-off-by: Sean Rhodes <sean@starlabs.systems>
---
Documentation/admin-guide/kernel-parameters.txt | 5 +++++
kernel/power/hibernate.c | 6 +++++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt
b/Documentation/admin-guide/kernel-parameters.txt
index b5493a7f8f22..0d20ad9c7d78 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1967,6 +1967,11 @@ Kernel parameters
protect_image Turn on image protection during restoration
(that will set all pages holding image data
during restoration read-only).
+ allow_locked_down
+ Allow hibernation even when kernel lockdown would
+ otherwise disable it. The kernel does not verify
+ the hibernation image; only use this when external
+ policy protects the image from offline modification.
hibernate.compressor= [HIBERNATION] Compression algorithm to be
used with hibernation.
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index d2479c69d71a..71232eece9a3 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -41,6 +41,7 @@
static int nocompress;
static int noresume;
static int nohibernate;
+static bool allow_locked_down_hibernation;
static int resume_wait;
static unsigned int resume_delay;
static char resume_file[256] = CONFIG_PM_STD_PARTITION;
@@ -109,7 +110,8 @@ bool hibernation_in_progress(void)
bool hibernation_available(void)
{
return nohibernate == 0 &&
- !security_locked_down(LOCKDOWN_HIBERNATION) &&
+ (allow_locked_down_hibernation ||
+ !security_locked_down(LOCKDOWN_HIBERNATION)) &&
!secretmem_active() && !cxl_mem_active();
}
@@ -1433,6 +1435,8 @@ static int __init hibernate_setup(char *str)
} else if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)
&& !strncmp(str, "protect_image", 13)) {
enable_restore_image_protection();
+ } else if (!strncmp(str, "allow_locked_down", 17)) {
+ allow_locked_down_hibernation = true;
}
return 1;
}
--
2.53.0
^ permalink raw reply related
* Re: [PATCH] PM: hibernate: Allow hibernation opt-in when locked down
From: Sean Rhodes @ 2026-07-09 20:33 UTC (permalink / raw)
To: rafael
Cc: lenb, pavel, corbet, skhan, paul, jmorris, serge,
nicolas.bouchinet, xiujianfeng, keescook, linux-pm, linux-doc,
linux-security-module, linux-kernel
In-Reply-To: <CABtds-0AUr1jD2Sri6ViiFiqyBbjc3-6xeAOr12YLJA9ux-2BA@mail.gmail.com>
Please ignore this patch; the approach was wrong.
I'll follow up with a v2.
On Thu, 9 Jul 2026 12:23:11 -0700, Sean Rhodes <sean@starlabs.systems> wrote:
> Kernel lockdown disables hibernation because the resume image cannot be
> verified before it is restored. On systems where external platform or
> storage policy protects the hibernation image from offline modification,
> users may still need hibernation while lockdown is active.
>
> Add a hibernate=allow_locked_down command line option to make that opt-in
> explicit. This only bypasses the LOCKDOWN_HIBERNATION gate; nohibernate,
> secretmem and CXL memory restrictions still apply.
>
> The kernel does not validate the external policy or authenticate the image
> with this option.
>
> Build-tested with Fedora config:
> make O=../linux-lockdown-hibernate-build kernel/power/hibernate.o
>
> Signed-off-by: Sean Rhodes <sean@starlabs.systems>
> ---
> Documentation/admin-guide/kernel-parameters.txt | 5 +++++
> kernel/power/hibernate.c | 6 +++++-
> 2 files changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index b5493a7f8f22..0d20ad9c7d78 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -1967,6 +1967,11 @@ Kernel parameters
> protect_image Turn on image protection during restoration
> (that will set all pages holding image data
> during restoration read-only).
> + allow_locked_down
> + Allow hibernation even when kernel lockdown would
> + otherwise disable it. The kernel does not verify
> + the hibernation image; only use this when external
> + policy protects the image from offline modification.
>
> hibernate.compressor= [HIBERNATION] Compression algorithm to be
> used with hibernation.
> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> index d2479c69d71a..71232eece9a3 100644
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -41,6 +41,7 @@
> static int nocompress;
> static int noresume;
> static int nohibernate;
> +static bool allow_locked_down_hibernation;
> static int resume_wait;
> static unsigned int resume_delay;
> static char resume_file[256] = CONFIG_PM_STD_PARTITION;
> @@ -109,7 +110,8 @@ bool hibernation_in_progress(void)
> bool hibernation_available(void)
> {
> return nohibernate == 0 &&
> - !security_locked_down(LOCKDOWN_HIBERNATION) &&
> + (allow_locked_down_hibernation ||
> + !security_locked_down(LOCKDOWN_HIBERNATION)) &&
> !secretmem_active() && !cxl_mem_active();
> }
>
> @@ -1433,6 +1435,8 @@ static int __init hibernate_setup(char *str)
> } else if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)
> && !strncmp(str, "protect_image", 13)) {
> enable_restore_image_protection();
> + } else if (!strncmp(str, "allow_locked_down", 17)) {
> + allow_locked_down_hibernation = true;
> }
> return 1;
> }
> --
> 2.53.0
^ permalink raw reply
* Re: [PATCH v2 1/9] security: add LSM blob and hooks for namespaces
From: Christian Brauner @ 2026-07-10 6:55 UTC (permalink / raw)
To: Mickaël Salaün
Cc: Paul Moore, 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: <20260709.paitheut7Ief@digikod.net>
On 2026-07-09 17:58 +0200, Mickaël Salaün wrote:
> On Thu, Jul 09, 2026 at 09:03:58AM -0400, Paul Moore wrote:
> > On Thu, Jul 9, 2026 at 5:12 AM Mickaël Salaün <mic@digikod.net> wrote:
> > > 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.
> >
> > ...
> >
> > > > > @@ -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.
> >
> > I don't have a strong opinion on either approach, either a separate
> > patch or doc update, but one of the two needs to happen.
>
> Noted, I'll follow on this with Christian.
I think we should add this as a separate patch.
^ permalink raw reply
* [PATCH] selftests/landlock: Skip scoped_signal subtest with MSG_OOB if not available
From: Thomas Huth @ 2026-07-10 8:16 UTC (permalink / raw)
To: Mickaël Salaün, Günther Noack,
linux-security-module
Cc: Shuah Khan, linux-kselftest, linux-kernel
From: Thomas Huth <thuth@redhat.com>
MSG_OOB might be disabled in the kernel for unix sockets (by not
selecting CONFIG_AF_UNIX_OOB), and in this case the related tests
of the scoped_signal_test are currently failing. Add a runtime
probe using socketpair() to detect MSG_OOB support and skip the
test gracefully if it is unavailable.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
.../selftests/landlock/scoped_signal_test.c | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/tools/testing/selftests/landlock/scoped_signal_test.c b/tools/testing/selftests/landlock/scoped_signal_test.c
index 58d25157fe781..3cf20d769f2bc 100644
--- a/tools/testing/selftests/landlock/scoped_signal_test.c
+++ b/tools/testing/selftests/landlock/scoped_signal_test.c
@@ -398,6 +398,24 @@ static int setup_signal_handler(int signal)
return sigaction(SIGURG, &sa, NULL);
}
+/*
+ * MSG_OOB might be disabled in the kernel via the CONFIG_AF_UNIX_OOB
+ * switch, so this function can be used for probing for its availability.
+ */
+static bool has_af_unix_oob(void)
+{
+ bool available = false;
+ int sp[2];
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0) {
+ available = (send(sp[0], ".", 1, MSG_OOB) == 1);
+ close(sp[0]);
+ close(sp[1]);
+ }
+
+ return available;
+}
+
/* clang-format off */
FIXTURE(fown) {};
/* clang-format on */
@@ -460,6 +478,9 @@ TEST_F(fown, sigurg_socket)
int pipe_parent[2], pipe_child[2];
pid_t child;
+ if (!has_af_unix_oob())
+ SKIP(return, "CONFIG_AF_UNIX_OOB / MSG_OOB not available");
+
memset(&server_address, 0, sizeof(server_address));
set_unix_address(&server_address, 0);
--
2.55.0
^ permalink raw reply related
* Re: [PATCH] selftests/landlock: Fix screwed up pointers in the scoped_signal_test
From: Mickaël Salaün @ 2026-07-10 11:09 UTC (permalink / raw)
To: Thomas Huth
Cc: Günther Noack, linux-security-module, Shuah Khan,
linux-kselftest, linux-kernel, rbriggs
In-Reply-To: <20260709164340.339656-1-thuth@redhat.com>
Applied (with a Fixes tag), thanks!
On Thu, Jul 09, 2026 at 06:43:40PM +0200, Thomas Huth wrote:
> From: Thomas Huth <thuth@redhat.com>
>
> The scoped_signal_test uses pthread_join(..., (void **)&ret)) in
> a couple of places, i.e. the return value of the thread is stored
> in the shape of a "void *" into the memory location of &ret.
> Pointers are 64-bit on modern computers, but the ret variable is
> declared as a simple "enum thread_return" which is only 32 bits.
> So the pthread_join() will overflow the ret variable by 4 byte.
>
> The problem is very visible on big endian systems like s390x
> where the test is failing: The least significant byte that carries
> the return code of the thread is not written into the ret variable
> here, but somewhere else in the stack frame, so the comparison
> for the right return code is failing here.
>
> Fix it by getting rid of the enum and defining the THREAD_* constants
> and "ret" variables as proper "void *" pointers. This way we can
> also get rid of some ugly (void *) castings in a couple of spots.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
> .../selftests/landlock/scoped_signal_test.c | 44 +++++++++----------
> 1 file changed, 21 insertions(+), 23 deletions(-)
>
> diff --git a/tools/testing/selftests/landlock/scoped_signal_test.c b/tools/testing/selftests/landlock/scoped_signal_test.c
> index f24f2c28f62e5..58d25157fe781 100644
> --- a/tools/testing/selftests/landlock/scoped_signal_test.c
> +++ b/tools/testing/selftests/landlock/scoped_signal_test.c
> @@ -249,12 +249,10 @@ TEST_F(scoped_domains, check_access_signal)
> _metadata->exit_code = KSFT_FAIL;
> }
>
> -enum thread_return {
> - THREAD_INVALID = 0,
> - THREAD_SUCCESS = 1,
> - THREAD_ERROR = 2,
> - THREAD_TEST_FAILED = 3,
> -};
I just added clang-format markups.
> +#define THREAD_INVALID ((void *)0)
> +#define THREAD_SUCCESS ((void *)1)
> +#define THREAD_ERROR ((void *)2)
> +#define THREAD_TEST_FAILED ((void *)3)
>
> static void *thread_sync(void *arg)
> {
> @@ -262,15 +260,15 @@ static void *thread_sync(void *arg)
> char buf;
>
> if (read(pipe_read, &buf, 1) != 1)
> - return (void *)THREAD_ERROR;
> + return THREAD_ERROR;
>
> - return (void *)THREAD_SUCCESS;
> + return THREAD_SUCCESS;
> }
>
> TEST(signal_scoping_thread_before)
> {
> pthread_t no_sandbox_thread;
> - enum thread_return ret = THREAD_INVALID;
> + void *ret = THREAD_INVALID;
> int thread_pipe[2];
>
> drop_caps(_metadata);
> @@ -285,7 +283,7 @@ TEST(signal_scoping_thread_before)
> EXPECT_EQ(0, pthread_kill(no_sandbox_thread, 0));
> EXPECT_EQ(1, write(thread_pipe[1], ".", 1));
>
> - EXPECT_EQ(0, pthread_join(no_sandbox_thread, (void **)&ret));
> + EXPECT_EQ(0, pthread_join(no_sandbox_thread, &ret));
> EXPECT_EQ(THREAD_SUCCESS, ret);
>
> EXPECT_EQ(0, close(thread_pipe[0]));
> @@ -295,7 +293,7 @@ TEST(signal_scoping_thread_before)
> TEST(signal_scoping_thread_after)
> {
> pthread_t scoped_thread;
> - enum thread_return ret = THREAD_INVALID;
> + void *ret = THREAD_INVALID;
> int thread_pipe[2];
>
> drop_caps(_metadata);
> @@ -310,7 +308,7 @@ TEST(signal_scoping_thread_after)
> EXPECT_EQ(0, pthread_kill(scoped_thread, 0));
> EXPECT_EQ(1, write(thread_pipe[1], ".", 1));
>
> - EXPECT_EQ(0, pthread_join(scoped_thread, (void **)&ret));
> + EXPECT_EQ(0, pthread_join(scoped_thread, &ret));
> EXPECT_EQ(THREAD_SUCCESS, ret);
>
> EXPECT_EQ(0, close(thread_pipe[0]));
> @@ -327,20 +325,20 @@ void *thread_setuid(void *ptr)
> char buf;
>
> if (read(arg->pipe_read, &buf, 1) != 1)
> - return (void *)THREAD_ERROR;
> + return THREAD_ERROR;
>
> /* libc's setuid() should update all thread's credentials. */
> if (getuid() != arg->new_uid)
> - return (void *)THREAD_TEST_FAILED;
> + return THREAD_TEST_FAILED;
>
> - return (void *)THREAD_SUCCESS;
> + return THREAD_SUCCESS;
> }
>
> TEST(signal_scoping_thread_setuid)
> {
> struct thread_setuid_args arg;
> pthread_t no_sandbox_thread;
> - enum thread_return ret = THREAD_INVALID;
> + void *ret = THREAD_INVALID;
> int pipe_parent[2];
> int prev_uid;
>
> @@ -367,7 +365,7 @@ TEST(signal_scoping_thread_setuid)
> EXPECT_EQ(arg.new_uid, getuid());
> EXPECT_EQ(1, write(pipe_parent[1], ".", 1));
>
> - EXPECT_EQ(0, pthread_join(no_sandbox_thread, (void **)&ret));
> + EXPECT_EQ(0, pthread_join(no_sandbox_thread, &ret));
> EXPECT_EQ(THREAD_SUCCESS, ret);
>
> clear_cap(_metadata, CAP_SETUID);
> @@ -667,20 +665,20 @@ static void *thread_setown_scoped(void *arg)
> ruleset_fd =
> landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
> if (ruleset_fd < 0)
> - return (void *)THREAD_ERROR;
> + return THREAD_ERROR;
> if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
> landlock_restrict_self(ruleset_fd, 0)) {
> close(ruleset_fd);
> - return (void *)THREAD_ERROR;
> + return THREAD_ERROR;
> }
> close(ruleset_fd);
>
> /* Makes this process group own the SIGIO source. */
> if (fcntl(fd, F_SETSIG, SIGURG) || fcntl(fd, F_SETOWN, -getpgrp()) ||
> fcntl(fd, F_SETFL, O_ASYNC))
> - return (void *)THREAD_ERROR;
> + return THREAD_ERROR;
>
> - return (void *)THREAD_SUCCESS;
> + return THREAD_SUCCESS;
> }
>
> /*
> @@ -702,7 +700,7 @@ TEST(sigio_to_pgid_self)
> {
> int trigger[2];
> pthread_t thread;
> - enum thread_return ret = THREAD_INVALID;
> + void *ret = THREAD_INVALID;
> int i;
>
> drop_caps(_metadata);
> @@ -722,7 +720,7 @@ TEST(sigio_to_pgid_self)
> */
> ASSERT_EQ(0, pthread_create(&thread, NULL, thread_setown_scoped,
> &trigger[0]));
> - ASSERT_EQ(0, pthread_join(thread, (void **)&ret));
> + ASSERT_EQ(0, pthread_join(thread, &ret));
> ASSERT_EQ(THREAD_SUCCESS, ret);
>
> /* Fans SIGURG out to the process group. */
> --
> 2.55.0
>
>
^ 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