Linux Security Modules development
 help / color / mirror / Atom feed
* Re: [PATCH v3] hardening: Default randstruct off with rust for better allmodconfig support
From: Mark Brown @ 2026-07-13 12:45 UTC (permalink / raw)
  To: Kees Cook, Gustavo A. R. Silva, Paul Moore, James Morris,
	Serge E. Hallyn, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich
  Cc: linux-hardening, linux-security-module, linux-kernel,
	rust-for-linux
In-Reply-To: <20260702-rust-reverse-randstruct-dep-v3-1-e4e09c50014e@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 651 bytes --]

On Thu, Jul 02, 2026 at 06:37:08PM +0100, Mark Brown wrote:
> Currently randstruct does not support rust so we have Kconfig dependencies
> which prevent rust being enabled when randstruct is. Unfortunately this
> prevents rust being enabled in allmodconfig, our standard coverage build.
> randstruct gets turned on by default, then the dependency on !RANDSTRUCT
> causes rust to get disabled.

Any news on this?  I'm flying blind doing -next merges of rust code with
build coverage gone, and I suspect a bunch of other people think they
have build coverage in their tests but it's silently vanished (I know at
least one person ran into that already).

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH -next] ima: add cond_resched() in ima_calc_file_hash_tfm loop
From: Roberto Sassu @ 2026-07-13 12:06 UTC (permalink / raw)
  To: Gaosheng Cui, lujialin4, zohar, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, paul, jmorris, serge
  Cc: linux-integrity, linux-security-module
In-Reply-To: <20260713111022.2418849-1-cuigaosheng1@huawei.com>

On Mon, 2026-07-13 at 11:10 +0000, Gaosheng Cui wrote:
> When hashing large files, the while loop in ima_calc_file_hash_tfm
> processes PAGE_SIZE chunks without any scheduling point, which can
> cause soft lockup warnings:
> watchdog: BUG: soft lockup - CPU#0 stuck for 50s!
> Call Trace:
>   _sha256_update+0x12d/0x1a0
>   ima_calc_file_hash_tfm+0xfb/0x150
>   ima_calc_file_hash+0x6e/0x160
>   ima_collect_measurement+0x202/0x340
>   process_measurement+0x3a9/0xb30
>   ima_file_check+0x56/0xa0
>   do_open+0x11b/0x250
>   path_openat+0x10b/0x1d0
>   do_filp_open+0xa9/0x150
>   do_sys_openat2+0x223/0x2a0
>   __x64_sys_openat+0x54/0xa0
>   do_syscall_64+0x59/0x110
>   entry_SYSCALL_64_after_hwframe+0x78/0xe2
> 
> Add cond_resched() at the end of each loop iteration to voluntarily
> yield the CPU when needed.
> 
> Fixes: 3323eec921ef ("integrity: IMA as an integrity service provider")
> Signed-off-by: Gaosheng Cui <cuigaosheng1@huawei.com>
> ---
>  security/integrity/ima/ima_crypto.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
> index 0d72b48249ee..3b7d41a9fd18 100644
> --- a/security/integrity/ima/ima_crypto.c
> +++ b/security/integrity/ima/ima_crypto.c
> @@ -233,6 +233,8 @@ static int ima_calc_file_hash_tfm(struct file *file,
>  		rc = crypto_shash_update(shash, rbuf, rbuf_len);
>  		if (rc)
>  			break;
> +
> +		cond_resched();

I would recommend not doing at every loop but every 4 MB at least:

if (IS_ALIGNED(offset, SZ_4M))
        cond_resched();

Thanks

Roberto

>  	}
>  	kfree(rbuf);
>  out:


^ permalink raw reply

* [PATCH -next] ima: add cond_resched() in ima_calc_file_hash_tfm loop
From: Gaosheng Cui @ 2026-07-13 11:10 UTC (permalink / raw)
  To: cuigaosheng1, lujialin4, zohar, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, paul, jmorris, serge
  Cc: linux-integrity, linux-security-module

When hashing large files, the while loop in ima_calc_file_hash_tfm
processes PAGE_SIZE chunks without any scheduling point, which can
cause soft lockup warnings:
watchdog: BUG: soft lockup - CPU#0 stuck for 50s!
Call Trace:
  _sha256_update+0x12d/0x1a0
  ima_calc_file_hash_tfm+0xfb/0x150
  ima_calc_file_hash+0x6e/0x160
  ima_collect_measurement+0x202/0x340
  process_measurement+0x3a9/0xb30
  ima_file_check+0x56/0xa0
  do_open+0x11b/0x250
  path_openat+0x10b/0x1d0
  do_filp_open+0xa9/0x150
  do_sys_openat2+0x223/0x2a0
  __x64_sys_openat+0x54/0xa0
  do_syscall_64+0x59/0x110
  entry_SYSCALL_64_after_hwframe+0x78/0xe2

Add cond_resched() at the end of each loop iteration to voluntarily
yield the CPU when needed.

Fixes: 3323eec921ef ("integrity: IMA as an integrity service provider")
Signed-off-by: Gaosheng Cui <cuigaosheng1@huawei.com>
---
 security/integrity/ima/ima_crypto.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 0d72b48249ee..3b7d41a9fd18 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -233,6 +233,8 @@ static int ima_calc_file_hash_tfm(struct file *file,
 		rc = crypto_shash_update(shash, rbuf, rbuf_len);
 		if (rc)
 			break;
+
+		cond_resched();
 	}
 	kfree(rbuf);
 out:
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH 11/13 RFC net-next] net: cipso: guard IPv4 packet manipulation functions
From: Paul Moore @ 2026-07-12 16:22 UTC (permalink / raw)
  To: Fernando Fernandez Mancera
  Cc: netdev, davem, edumazet, kuba, pabeni, dsahern, horms, idosch,
	linux-security-module, linux-kernel
In-Reply-To: <20260712013941.4570-12-fmancera@suse.de>

On Sat, Jul 11, 2026 at 9:41 PM Fernando Fernandez Mancera
<fmancera@suse.de> wrote:
>
> To enable compiling the network stack without IPv4, the CIPSO functions
> that manipulate IPv4 options and generate ICMP errors must be bypassed.
>
> Ideally, CIPSO should not be compiled when IPv4 is disabled but
> currently it is too integrated within netlabel, so let's just bypassed
> the relevant functions.
>
> Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
> ---
>  net/ipv4/cipso_ipv4.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)

I think I would prefer to make CONFIG_NETLABEL dependent on
CONFIG_IPV4 at this point in time.  This will keep the code cleaner
and allow time to do the proper work of wrapping the CIPSO code with
CONFIG_CIPSO (or similar) and making that dependent on CONFIG_IPV4.

-- 
paul-moore.com

^ permalink raw reply

* [PATCH] apparmor: replace decompress_zstd() prototype with its entity
From: Tetsuo Handa @ 2026-07-12 10:17 UTC (permalink / raw)
  To: Maxime Bélair, John Johansen; +Cc: linux-security-module
In-Reply-To: <83eb9325-9688-4a6c-9727-e137df773694@I-love.SAKURA.ne.jp>

Fix "undefined symbol: decompress_zstd" error caused by decompress_zstd()
being guarded by CONFIG_SECURITY_APPARMOR_EXPORT_BINARY=y.

Reported-by: syzbot+1f14a35d0c73d31555e4@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=1f14a35d0c73d31555e4
Fixes: 17b5758bf35c ("apparmor: Initial support for compressed policies")
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/apparmor/apparmorfs.c | 72 +++++++++++++++++-----------------
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 2ae9ab94a5a91..152c7967ff1ba 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -483,7 +483,42 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf,
 
 	return data;
 }
-static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen);
+
+static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen)
+{
+	if (slen < dlen) {
+		const size_t wksp_len = zstd_dctx_workspace_bound();
+		zstd_dctx *ctx;
+		void *wksp;
+		size_t out_len;
+		int ret = 0;
+
+		wksp = kvzalloc(wksp_len, GFP_KERNEL);
+		if (!wksp) {
+			ret = -ENOMEM;
+			goto cleanup;
+		}
+		ctx = zstd_init_dctx(wksp, wksp_len);
+		if (ctx == NULL) {
+			ret = -ENOMEM;
+			goto cleanup;
+		}
+		out_len = zstd_decompress_dctx(ctx, dst, dlen, src, slen);
+		if (zstd_is_error(out_len)) {
+			ret = -EINVAL;
+			goto cleanup;
+		}
+cleanup:
+		kvfree(wksp);
+		return ret;
+	}
+
+	if (dlen < slen)
+		return -EINVAL;
+	memcpy(dst, src, slen);
+	return 0;
+}
+
 /**
  * aa_get_data_from_compressed - common routine for getting compressed policy
  * from user and get both compressed and uncompressed version.
@@ -1517,41 +1552,6 @@ SEQ_RAWDATA_FOPS(revision);
 SEQ_RAWDATA_FOPS(hash);
 SEQ_RAWDATA_FOPS(compressed_size);
 
-static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen)
-{
-	if (slen < dlen) {
-		const size_t wksp_len = zstd_dctx_workspace_bound();
-		zstd_dctx *ctx;
-		void *wksp;
-		size_t out_len;
-		int ret = 0;
-
-		wksp = kvzalloc(wksp_len, GFP_KERNEL);
-		if (!wksp) {
-			ret = -ENOMEM;
-			goto cleanup;
-		}
-		ctx = zstd_init_dctx(wksp, wksp_len);
-		if (ctx == NULL) {
-			ret = -ENOMEM;
-			goto cleanup;
-		}
-		out_len = zstd_decompress_dctx(ctx, dst, dlen, src, slen);
-		if (zstd_is_error(out_len)) {
-			ret = -EINVAL;
-			goto cleanup;
-		}
-cleanup:
-		kvfree(wksp);
-		return ret;
-	}
-
-	if (dlen < slen)
-		return -EINVAL;
-	memcpy(dst, src, slen);
-	return 0;
-}
-
 static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size,
 			    loff_t *ppos)
 {
-- 
2.52.0



^ permalink raw reply related

* [PATCH 3/3] assoc_array: trim the final shortcut word when skip_to_level is chunk-aligned
From: Michael Bommarito @ 2026-07-12  1:45 UTC (permalink / raw)
  To: David Howells, Jarkko Sakkinen
  Cc: Paul Moore, James Morris, Serge E . Hallyn, Andrew Morton,
	keyrings, linux-security-module, linux-kernel
In-Reply-To: <20260712014500.480410-1-michael.bommarito@gmail.com>

assoc_array_walk() masks off the bits past shortcut->skip_to_level in
the final word of a shortcut before testing it, gated on
round_up(sc_level, chunk_size) > skip_to_level.  Once sc_level is
word-aligned (every word after the first) round_up() is a no-op and the
guard never fires for the word that contains skip_to_level, so its stale
high bits leak into the dissimilarity word and can steer the walk down
the wrong descendant.

Test sc_level + ASSOC_ARRAY_KEY_CHUNK_SIZE > skip_to_level directly; an
exact-multiple skip_to_level ends on the boundary and stays untrimmed.

Fixes: 3cb989501c26 ("Add a generic associative array implementation.")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
 lib/assoc_array.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/assoc_array.c b/lib/assoc_array.c
index bcc6e0a013eb8..1de2c337f8fcf 100644
--- a/lib/assoc_array.c
+++ b/lib/assoc_array.c
@@ -255,7 +255,7 @@ assoc_array_walk(const struct assoc_array *array,
 		sc_segments = shortcut->index_key[sc_level >> ASSOC_ARRAY_KEY_CHUNK_SHIFT];
 		dissimilarity = segments ^ sc_segments;
 
-		if (round_up(sc_level, ASSOC_ARRAY_KEY_CHUNK_SIZE) > shortcut->skip_to_level) {
+		if (sc_level + ASSOC_ARRAY_KEY_CHUNK_SIZE > shortcut->skip_to_level) {
 			/* Trim segments that are beyond the shortcut */
 			int shift = shortcut->skip_to_level & ASSOC_ARRAY_KEY_CHUNK_MASK;
 			dissimilarity &= ~(ULONG_MAX << shift);
-- 
2.53.0


^ permalink raw reply related

* [PATCH 2/3] keys: make keyring key-chunk byte order agree with keyring_diff_objects()
From: Michael Bommarito @ 2026-07-12  1:44 UTC (permalink / raw)
  To: David Howells, Jarkko Sakkinen
  Cc: Paul Moore, James Morris, Serge E . Hallyn, Andrew Morton,
	keyrings, linux-security-module, linux-kernel
In-Reply-To: <20260712014500.480410-1-michael.bommarito@gmail.com>

keyring_get_key_chunk() loads description bytes into the index chunk low
address first, while keyring_diff_objects() numbers the first differing
bit from the low end and folds the absolute byte index into the level
without removing the inline-prefix offset the level already carries.
The two disagree on byte order and bit position, so the array can be
told two keys first differ at a bit that does not differ in the chunk
the walker uses, letting crafted descriptions collide into one node.

Load the chunk in the order keyring_diff_objects() assumes and drop the
inline-prefix length when folding the byte index into the level.  This
only changes the in-memory ordering used to place keys within a keyring;
add, search and read of non-colliding keys are unaffected.

Fixes: f771fde82051 ("keys: Simplify key description management")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
 security/keys/keyring.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 1739373172ad5..e7066893e6ffc 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -292,9 +292,10 @@ static unsigned long keyring_get_key_chunk(const void *data, int level)
 		desc_len -= offset;
 		if (desc_len > n)
 			desc_len = n;
+		d += desc_len;
 		do {
 			chunk <<= 8;
-			chunk |= *d++;
+			chunk |= *--d;
 		} while (--desc_len > 0);
 		return chunk;
 	}
@@ -375,7 +376,7 @@ static int keyring_diff_objects(const void *object, const void *data)
 	return -1;
 
 differ_plus_i:
-	level += i;
+	level += i - (int)sizeof(a->desc);
 differ:
 	i = level * 8 + __ffs(seg_a ^ seg_b);
 	return i;
-- 
2.53.0


^ permalink raw reply related

* [PATCH 1/3] keys: fix out-of-bounds read in keyring_get_key_chunk()
From: Michael Bommarito @ 2026-07-12  1:44 UTC (permalink / raw)
  To: David Howells, Jarkko Sakkinen
  Cc: Paul Moore, James Morris, Serge E . Hallyn, Andrew Morton,
	keyrings, linux-security-module, linux-kernel
In-Reply-To: <20260712014500.480410-1-michael.bommarito@gmail.com>

For description-level chunks keyring_get_key_chunk() advances the read
pointer by level * sizeof(long) past the inline prefix but only
bounds-checks the prefix, so a long enough key description is read past
its kmemdup(desc, desc_len + 1) allocation.  Compute the full byte
offset and bounds-check the description against it before reading.

The walk only reaches a description-level chunk when two keys collide
through the hash, x, type and domain_tag chunks, so this is reached from
an unprivileged add_key(2) with a crafted pair of same-type keys whose
index hashes collide; KASAN reports a slab-out-of-bounds read.

Fixes: f771fde82051 ("keys: Simplify key description management")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
 security/keys/keyring.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

KASAN, x86_64: add_key(2) of a crafted hash-colliding "user"-key pair
(~63-byte descriptions) reports

  BUG: KASAN: slab-out-of-bounds in keyring_get_key_chunk
  keyring_get_key_chunk <- assoc_array_insert <- __key_link_begin
    <- __do_sys_add_key

reading one byte past the description allocation; the same trigger is
KASAN-clean with this patch.  On a kernel built without init-on-alloc,
reading the colliding keyring back with KEYCTL_READ returns
uninitialized slab until patches 2 and 3 are applied too.  Trigger
available off-list.

diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 7a2ee0ded7c93..1739373172ad5 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -270,7 +270,7 @@ static unsigned long keyring_get_key_chunk(const void *data, int level)
 	const struct keyring_index_key *index_key = data;
 	unsigned long chunk = 0;
 	const u8 *d;
-	int desc_len = index_key->desc_len, n = sizeof(chunk);
+	int desc_len = index_key->desc_len, n = sizeof(chunk), offset;
 
 	level /= ASSOC_ARRAY_KEY_CHUNK_SIZE;
 	switch (level) {
@@ -284,12 +284,12 @@ static unsigned long keyring_get_key_chunk(const void *data, int level)
 		return (unsigned long)index_key->domain_tag;
 	default:
 		level -= 4;
-		if (desc_len <= sizeof(index_key->desc))
+		offset = sizeof(index_key->desc) + level * sizeof(long);
+		if (desc_len <= offset)
 			return 0;
 
-		d = index_key->description + sizeof(index_key->desc);
-		d += level * sizeof(long);
-		desc_len -= sizeof(index_key->desc);
+		d = index_key->description + offset;
+		desc_len -= offset;
 		if (desc_len > n)
 			desc_len = n;
 		do {
-- 
2.53.0


^ permalink raw reply related

* [PATCH 0/3] keys: fix keyring assoc-array out-of-bounds read and index inconsistency
From: Michael Bommarito @ 2026-07-12  1:44 UTC (permalink / raw)
  To: David Howells, Jarkko Sakkinen
  Cc: Paul Moore, James Morris, Serge E . Hallyn, Andrew Morton,
	keyrings, linux-security-module, linux-kernel

keyring_get_key_chunk() advances the description read pointer by
level * sizeof(long) past the inline prefix but only bounds-checks the
prefix, so once the associative-array walk reaches a description-level
chunk it reads past the kmemdup(desc, desc_len + 1) description
allocation.  Reaching that depth needs two keys that collide through the
hash, x, type and domain_tag chunks, which an unprivileged add_key(2)
can arrange with a crafted pair of same-type keys.

An unprivileged user can thus read up to sizeof(long) bytes past a
keyring key's description; on kernels built without init-on-alloc the
same collision, read back with KEYCTL_READ, returns uninitialized kernel
slab.

Patch 1 is the memory-safety fix and stands alone.  Patches 2 and 3 fix
two index-key consistency bugs that let the crafted keys collide into a
single malformed node in the first place, which is what enables the
KEYCTL_READ disclosure.

The KASAN reproduction is on patch 1. Trigger is available off-list.

Michael Bommarito (3):
  keys: fix out-of-bounds read in keyring_get_key_chunk()
  keys: make keyring key-chunk byte order agree with
    keyring_diff_objects()
  assoc_array: trim the final shortcut word when skip_to_level is
    chunk-aligned

 lib/assoc_array.c       |  2 +-
 security/keys/keyring.c | 15 ++++++++-------
 2 files changed, 9 insertions(+), 8 deletions(-)


base-commit: 2c7c88a412aa6d09cd04b414211b4ef8553b5309
--
2.53.0


^ permalink raw reply

* [PATCH 11/13 RFC net-next] net: cipso: guard IPv4 packet manipulation functions
From: Fernando Fernandez Mancera @ 2026-07-12  1:39 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, dsahern, horms, idosch,
	Fernando Fernandez Mancera, Paul Moore, linux-security-module,
	linux-kernel
In-Reply-To: <20260712013941.4570-1-fmancera@suse.de>

To enable compiling the network stack without IPv4, the CIPSO functions
that manipulate IPv4 options and generate ICMP errors must be bypassed.

Ideally, CIPSO should not be compiled when IPv4 is disabled but
currently it is too integrated within netlabel, so let's just bypassed
the relevant functions.

Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
---
 net/ipv4/cipso_ipv4.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index a05aa075de1a..17bb723299d7 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1714,6 +1714,7 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option)
  */
 void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
 {
+#if IS_ENABLED(CONFIG_IPV4)
 	struct inet_skb_parm parm;
 	int res;
 
@@ -1738,6 +1739,7 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
 		__icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0, &parm);
 	else
 		__icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0, &parm);
+#endif
 }
 
 /**
@@ -2171,6 +2173,7 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb,
 			    const struct cipso_v4_doi *doi_def,
 			    const struct netlbl_lsm_secattr *secattr)
 {
+#if IS_ENABLED(CONFIG_IPV4)
 	int ret_val;
 	struct iphdr *iph;
 	struct ip_options *opt = &IPCB(skb)->opt;
@@ -2235,6 +2238,9 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb,
 	ip_send_check(iph);
 
 	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif
 }
 
 /**
@@ -2248,6 +2254,7 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb,
  */
 int cipso_v4_skbuff_delattr(struct sk_buff *skb)
 {
+#if IS_ENABLED(CONFIG_IPV4)
 	int ret_val, cipso_len, hdr_len_actual, new_hdr_len_actual, new_hdr_len,
 	    hdr_len_delta;
 	struct iphdr *iph;
@@ -2296,6 +2303,9 @@ int cipso_v4_skbuff_delattr(struct sk_buff *skb)
 	ip_send_check(iph);
 
 	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif
 }
 
 /*
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH 0/3] Implement LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
From: Justin Suess @ 2026-07-11 17:00 UTC (permalink / raw)
  To: Simon McVittie; +Cc: Mickaël Salaün, linux-security-module, gnoack
In-Reply-To: <ak-EgMPeFtH8MAQP@descent>

On Thu, Jul 09, 2026 at 12:22:40PM +0100, Simon McVittie wrote:
> 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.
>
Understandable. I guess my usecase proposed was narrower than thought.
And we probably want to avoid creating risky confused deputy scenarios.

So now I'm leaning towards the LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS path,
dropping the "ON_EXEC" part as Mickaël proposed.

But I'm struggling to see where the value is added over the prctl call.
Sure atomic enforcement with the ruleset is nice, but not a huge value added
on it's own.

Perhaps the setting of this bit with a -1 ruleset_fd could enable auditing
of the (failed or successful) privilege acquisition for the domain via the
fcaps/suid/guid methods w/o setting NNP? (otherwise this would be no
different from a Landlock specific prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)
call).

And setting it with a non -1 ruleset_fd would set NNP *and* enable the
same auditing.

That way we are making this a "value-added" flag instead of just a landlock-flavored
prctl call.

This would work well with the LANDLOCK_PERM_CAPABILITY_USE proposal,
which allows us to audit both methods of acquiring new capabilities.
(the clone/unshare path, and the fcaps/setuid/setgid path).

What do you think Mickaël?

Justin
>     smcv

^ permalink raw reply

* Re: [GIT PULL] selinux/selinux-pr-20260710
From: pr-tracker-bot @ 2026-07-11  3:07 UTC (permalink / raw)
  To: Paul Moore; +Cc: Linus Torvalds, selinux, linux-security-module, linux-kernel
In-Reply-To: <44e0f55f936543053d657f0a86a53bd9@paul-moore.com>

The pull request you sent on Fri, 10 Jul 2026 15:13:45 -0400:

> https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git tags/selinux-pr-20260710

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/ccce5f6e7c86f103d76534e2d06d1c903dce551c

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html

^ permalink raw reply

* Re: [PATCH v2] NFSv4.2: fix nfs4_listxattr size accounting
From: Paul Moore @ 2026-07-10 22:20 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Anna Schumaker, Achilles Gaikwad, Trond Myklebust, linux-nfs,
	linux-security-module, selinux
In-Reply-To: <CAHC9VhRq+Vth-4D4OHFAY_6hXqmj=MgTc_2G=3Ehr6bAQzp26Q@mail.gmail.com>

On Fri, Jul 10, 2026 at 5:55 PM Paul Moore <paul@paul-moore.com> wrote:
>
> On Fri, Jul 10, 2026 at 5:54 PM Paul Moore <paul@paul-moore.com> wrote:
> > On Thu, Jul 9, 2026 at 8:33 AM Stephen Smalley
> > <stephen.smalley.work@gmail.com> wrote:
> > > 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.
> >
> > I haven't had a chance to look into this yet, but the git bisect just
> > produced the commit below as the offending commit:
> >
> >    commit 01c2305795a3b6b164df48e72b12022a68fd60c1
> >    Author: Jeff Layton <jlayton@kernel.org>
> >    Date:   Wed Mar 25 10:40:32 2026 -0400
>
> Ooops, nevermind, scratch that - I still have one more kernel to test.

... and scratch that, the offending commit was that one.

   commit 01c2305795a3b6b164df48e72b12022a68fd60c1
   Author: Jeff Layton <jlayton@kernel.org>
   Date:   Wed Mar 25 10:40:32 2026 -0400

   nfsd: add netlink upcall for the nfsd.fh cache

   Add netlink-based cache upcall support for the expkey (nfsd.fh) cache,
   following the same pattern as the existing svc_export netlink support.

   Add expkey to the cache-type enum, a new expkey attribute-set with
   client, fsidtype, fsid, negative, expiry, and path fields, and the
   expkey-get-reqs / expkey-set-reqs operations to the nfsd YAML spec
   and generated headers.

   Implement nfsd_nl_expkey_get_reqs_dumpit() which snapshots pending
   expkey cache requests and sends each entry's seqno, client name,
   fsidtype, and fsid over netlink.

   Implement nfsd_nl_expkey_set_reqs_doit() which parses expkey cache
   responses from userspace (client, fsidtype, fsid, expiry, and path
   or negative flag) and updates the cache via svc_expkey_lookup() /
   svc_expkey_update().

   Wire up the expkey_notify() callback in svc_expkey_cache_template
   so cache misses trigger NFSD_CMD_CACHE_NOTIFY multicast events with
   NFSD_CACHE_TYPE_EXPKEY.

   Signed-off-by: Jeff Layton <jlayton@kernel.org>
   Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

-- 
paul-moore.com

^ permalink raw reply

* Re: [PATCH v2] NFSv4.2: fix nfs4_listxattr size accounting
From: Paul Moore @ 2026-07-10 21:55 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Anna Schumaker, Achilles Gaikwad, Trond Myklebust, linux-nfs,
	linux-security-module, selinux
In-Reply-To: <CAHC9VhSxpAx+G35fbcMjJ1PfqJxDZYpTEu=qpO+0PQe=nkX5-g@mail.gmail.com>

On Fri, Jul 10, 2026 at 5:54 PM Paul Moore <paul@paul-moore.com> wrote:
> On Thu, Jul 9, 2026 at 8:33 AM Stephen Smalley
> <stephen.smalley.work@gmail.com> wrote:
> > 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.
>
> I haven't had a chance to look into this yet, but the git bisect just
> produced the commit below as the offending commit:
>
>    commit 01c2305795a3b6b164df48e72b12022a68fd60c1
>    Author: Jeff Layton <jlayton@kernel.org>
>    Date:   Wed Mar 25 10:40:32 2026 -0400

Ooops, nevermind, scratch that - I still have one more kernel to test.

-- 
paul-moore.com

^ permalink raw reply

* Re: [PATCH v2] NFSv4.2: fix nfs4_listxattr size accounting
From: Paul Moore @ 2026-07-10 21:54 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Anna Schumaker, Achilles Gaikwad, Trond Myklebust, linux-nfs,
	linux-security-module, selinux
In-Reply-To: <CAEjxPJ4+wgUDY3YxajZ=2D3WLzgat_Mqvr05VtJ4KrXW7_kuXA@mail.gmail.com>

On Thu, Jul 9, 2026 at 8:33 AM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
> 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.

I haven't had a chance to look into this yet, but the git bisect just
produced the commit below as the offending commit:

   commit 01c2305795a3b6b164df48e72b12022a68fd60c1
   Author: Jeff Layton <jlayton@kernel.org>
   Date:   Wed Mar 25 10:40:32 2026 -0400

   nfsd: add netlink upcall for the nfsd.fh cache

   Add netlink-based cache upcall support for the expkey (nfsd.fh) cache,
   following the same pattern as the existing svc_export netlink support.

   Add expkey to the cache-type enum, a new expkey attribute-set with
   client, fsidtype, fsid, negative, expiry, and path fields, and the
   expkey-get-reqs / expkey-set-reqs operations to the nfsd YAML spec
   and generated headers.

   Implement nfsd_nl_expkey_get_reqs_dumpit() which snapshots pending
   expkey cache requests and sends each entry's seqno, client name,
   fsidtype, and fsid over netlink.

   Implement nfsd_nl_expkey_set_reqs_doit() which parses expkey cache
   responses from userspace (client, fsidtype, fsid, expiry, and path
   or negative flag) and updates the cache via svc_expkey_lookup() /
   svc_expkey_update().

   Wire up the expkey_notify() callback in svc_expkey_cache_template
   so cache misses trigger NFSD_CMD_CACHE_NOTIFY multicast events with
   NFSD_CACHE_TYPE_EXPKEY.

   Signed-off-by: Jeff Layton <jlayton@kernel.org>
   Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

-- 
paul-moore.com

^ permalink raw reply

* İlt: Re: [RESEND][RFC/discuss] memfd_secret(): opt-in visibility for security monitoring (eBPF/audit)
From: BoxStrikesTeam @ 2026-07-10 21:51 UTC (permalink / raw)
  To: paul@paul-moore.com
  Cc: akpm@linux-foundation.org, rppt@kernel.org, linux-mm@kvack.org,
	linux-security-module@vger.kernel.org, serge@hallyn.com,
	jmorris@namei.org
In-Reply-To: <CAHC9VhSWs4=-BN09XWUsJXh+9HB5zeYa0oiRsRNGb4s_sTW2HQ@mail.gmail.com>





Proton Mail güvenli e-posta ile gönderildi.

------- Forwarded Message -------
Kimden: Paul Moore <paul@paul-moore.com>
Tarih: 11 Temmuz 2026 Cumartesi saat 00:00
Konu: Re: [RESEND][RFC/discuss] memfd_secret(): opt-in visibility for security monitoring (eBPF/audit)
Kime: BoxStrikesTeam <BoxStrikesTeam@proton.me>
CC: rppt@kernel.org <rppt@kernel.org>, akpm@linux-foundation.org <akpm@linux-foundation.org>, linux-mm@kvack.org <linux-mm@kvack.org>, linux-security-module@vger.kernel.org <linux-security-module@vger.kernel.org>, jmorris@namei.org <jmorris@namei.org>, serge@hallyn.com <serge@hallyn.com>


> On Thu, Jul 9, 2026 at 1:14 AM BoxStrikesTeam <BoxStrikesTeam@proton.me> wrote:
> > 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.
>
> To be very honest, I'm not too concerned about out-of-tree, security
> products; I'm focused on the in-tree kernel code.  If you are
> concerned about userspace making use of memfd_secret(), you could
> block the operation on a per-process/domain basis using either seccomp
> or SELinux (other LSMs may have similar functionality, that's an
> exercise left to the reader).
>
> Also, it is important to note that if you find the kernel
> documentation lacking in a particular area, I would encourage you to
> submit a patch to address the shortcomings.
>
> --
> paul-moore.com
>


Paul,

Thanks for the discussion and for the pointer to secretmem_file_create() — that resolves (a) for me.

On (b), I've thought about it further and agree a kernel patch isn't the right answer here. A few closing observations for the record:

1. Dynamic detection isn't actually closed off by memfd_secret()+mseal(). Every syscall a payload makes traps through the normal syscall entry path, and pt_regs->ip at that point reflects the calling address regardless of whether that address sits inside a secretmem VMA. Cross-referencing that IP against /proc/pid/maps (or vma->vm_start/vm_end in-kernel) lets a tracer attribute syscalls to a secretmem-backed region without ever reading the region's contents. So the confidentiality guarantee holds, but it doesn't buy an attacker syscall-level anonymity — only content opacity.

2. That said, I recognize this is a bypassable heuristic on its own (an attacker can proxy syscalls through a separate, non-secretmem code path), which is why I don't think dynamic detection alone is a complete answer either.

3. The more durable idea, I think, is one that doesn't touch confidentiality at all: hooking the memfd_secret()/mmap()/mseal() call sites and building a signature purely from call metadata — arguments, region size, protection flags, and the sequence/timing of these calls — rather than from region contents. This gives EDR/eBPF tooling something for static/behavioral matching without requiring any new in-kernel read primitive, since none of that metadata is protected by secretmem's threat model. This is achievable entirely in userspace/eBPF today with existing hooks, so no kernel change is needed for it either.

Given that, I don't think there's a kernel patch to propose here. This looks like it's squarely a detection-engineering problem for security products to solve on top of existing tracepoints, not a kernel gap. I'll leave the follow-through on that side to the community.

Thanks again for engaging with this — appreciated the back and forth.

Best,
Eneshan Erdoğan Karaca

^ permalink raw reply

* Re: [RESEND][RFC/discuss] memfd_secret(): opt-in visibility for security monitoring (eBPF/audit)
From: Paul Moore @ 2026-07-10 21:00 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: <MZlCECz5s73hPgQxtqWZ2VbXNTCZnItnwMHu2iZQlRC6ba0B9GuqxT2EhvhwQ-uanBDsNn7Bg09nGVynBHdmSsiRjhyI1udkYbqOoPfpe6w=@proton.me>

On Thu, Jul 9, 2026 at 1:14 AM BoxStrikesTeam <BoxStrikesTeam@proton.me> wrote:
> 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.

To be very honest, I'm not too concerned about out-of-tree, security
products; I'm focused on the in-tree kernel code.  If you are
concerned about userspace making use of memfd_secret(), you could
block the operation on a per-process/domain basis using either seccomp
or SELinux (other LSMs may have similar functionality, that's an
exercise left to the reader).

Also, it is important to note that if you find the kernel
documentation lacking in a particular area, I would encourage you to
submit a patch to address the shortcomings.

-- 
paul-moore.com

^ permalink raw reply

* Re: [PATCH v2 1/9] security: add LSM blob and hooks for namespaces
From: Paul Moore @ 2026-07-10 20:42 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.paitheut7Ief@digikod.net>

On Thu, Jul 9, 2026 at 11:58 AM Mickaël Salaün <mic@digikod.net> 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:

...

> > 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?

Yes.

Just a heads-up, and some of this depends on timing, but as we've got
multiple patchsets (there is a SELinux patchset that depends on these
hooks) I'll want to take this hook additions via the LSM tree.  I can
take the associated Landlock patches too if you like, or you base the
Landlock tree off the LSM branch; no worries either way, we can sort
out the details once the patchset is ready for merging.

-- 
paul-moore.com

^ permalink raw reply

* [GIT PULL] selinux/selinux-pr-20260710
From: Paul Moore @ 2026-07-10 19:13 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: selinux, linux-security-module, linux-kernel

Linus,

Two small SELinux patches to fix a missing permission check for
TCP Fast Open operations and fix a socket lookup issue with SCTP ASCONF
operations.

Paul

--
The following changes since commit dc59e4fea9d83f03bad6bddf3fa2e52491777482:

  Linux 7.2-rc1 (2026-06-28 12:01:31 -0700)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
    tags/selinux-pr-20260710

for you to fetch changes up to 56acfeb10019e200ab6787d01f8d7cbe0f01526f:

  selinux: avoid sk_socket dereference in selinux_sctp_bind_connect()
    (2026-07-01 18:22:22 -0400)

----------------------------------------------------------------
selinux/stable-7.2 PR 20260710
----------------------------------------------------------------

Stephen Smalley (1):
      selinux: check connect-related permissions on TCP Fast Open

Tristan Madani (1):
      selinux: avoid sk_socket dereference in
         selinux_sctp_bind_connect()

 security/selinux/hooks.c |   38 ++++++++++++++++++++++++++++----------
 1 file changed, 28 insertions(+), 10 deletions(-)

--
paul-moore.com

^ permalink raw reply

* Re: [PATCH 2/2] module: Bring includes in linux/kmod.h up to date
From: Aaron Tomlin @ 2026-07-10 13:57 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,
	Michal Koutný, Luis Chamberlain, Daniel Gomez, Sami Tolvanen,
	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-3-petr.pavlu@suse.com>

On Wed, Jul 08, 2026 at 05:44:30PM +0200, Petr Pavlu wrote:
> 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
> 

LGTM. Thank you.

Reviewed-by: Aaron Tomlin <atomlin@atomlin.com>
-- 
Aaron Tomlin

^ permalink raw reply

* Re: [PATCH 0/3] Implement LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC
From: Justin Suess @ 2026-07-10 13:56 UTC (permalink / raw)
  To: Mickaël Salaün; +Cc: linux-security-module, gnoack
In-Reply-To: <20260709.Eaphooyoh6sh@digikod.net>

On Thu, Jul 09, 2026 at 12:09:25PM +0200, Mickaël Salaün wrote:
> 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?
> 
tldr I think your idea is better, see below.
> 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...
>
Atomically with respect to the ruleset enforcement I presume?
I guess that makes this even easier... just run it at the end after all
possible errors in the landlock_restrict_self path.

In this case then, we must consider whether this would be sufficient to
serve as a substitute for NNP || cap_sys_admin check.

> > 
> > 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.
>
Yes, and it does have CAP_SYS_ADMIN in this example. It "feels" risky
though to mess with further escalations. But if you are CAP_SYS_ADMIN,
you can load kernel modules, potentially write to any memory, etc.

So that is less the argument I would make.

I think the main argument that hasn't been highlighted yet against *my
proposal* (I like to red team my own proposals) is that this whole
thing has nothing to do with Landlock. My feature doesn't touch Landlock
rulesets, or anything Landlock specific, so if this were implemented,
why not just make it a prctl? Why tie it to an LSM at all?

So I like your proposal better (atomic nnp with Landlock) because it's
actually relevant to Landlock rulesets.

The last remaining questions:

1. Shall the NNP || cap_sys_admin check remain in place for the NNP Landlock flag?
2. Should we allow enforcement with ruleset_fd being -1 (would basically
be equivalent to the prctl version of set no new privs)?

Justin

> >   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.
> 
Yes, I  
> > 
> > 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

* İlt: Re: [RFC/discuss] memfd_secret(): opt-in visibility for security monitoring (eBPF/audit)
From: BoxStrikesTeam @ 2026-07-10 13:40 UTC (permalink / raw)
  To: paul@paul-moore.com
  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: <CAHC9VhRCo1nc2qLfq=Fk9Q26vjSOUBgfM8wV6U4S+Hv1KM9LNQ@mail.gmail.com>

Proton Mail güvenli e-posta ile gönderildi.


------- Forwarded Message -------
Kimden: Paul Moore paul@paul-moore.com

Tarih: 9 Temmuz 2026 Perşembe saat 05:21
Konu: Re: [RFC/discuss] memfd_secret(): opt-in visibility for security monitoring (eBPF/audit)
Kime: BoxStrikesTeam BoxStrikesTeam@proton.me

CC: rppt@kernel.org rppt@kernel.org, akpm@linux-foundation.org akpm@linux-foundation.org, linux-mm@kvack.org linux-mm@kvack.org, linux-security-module@vger.kernel.org linux-security-module@vger.kernel.org, jmorris@namei.org jmorris@namei.org, serge@hallyn.com serge@hallyn.com



> 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


Hello,

Option B caught my interest. Do you have any updates, disclosures, new ideas, or anything new to share?

By the way, I strengthened my finding with a proof of concept and have now disclosed it publicly.

Thank you.

https://github.com/BoxStrikesTeam/Counter-Attack-Injection-Method

https://boxstrikesteam.github.io/Bulgular/001/finding-001.html

^ permalink raw reply

* Re: [PATCH] PM: hibernate: Allow hibernation opt-in when locked down
From: Nicolas Bouchinet @ 2026-07-10 13:09 UTC (permalink / raw)
  To: Sean Rhodes
  Cc: rafael, lenb, pavel, corbet, skhan, paul, jmorris, serge,
	xiujianfeng, keescook, linux-pm, linux-doc, linux-security-module,
	linux-kernel, mjg59@srcf.ucam.org
In-Reply-To: <CABtds-1d8uYi5YbxgbL5MwZOXTUgBmeLQWiggVhBKtqct5VC-g@mail.gmail.com>

On Thu, Jul 09, 2026 at 04:33:38PM -0400, Sean Rhodes wrote:
> 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

Hi Sean, thanks for your contribution.

While I understand the frustration of Lockdown disabling hibernation, it really
is necessary in order to protect against the root user which is in Lockdown's
threat model. Similar discussions already happened in this patch set [1].

About Lockdown hibernation support, some work have started some time ago by
Matthew, it blog post [2] describe really well the security issue of hibernation.
This has then lead to a first implementation [3] that has been recently bumped
[4] but sadly no news have been given since.
Some interesting discussion also happened recently about this subject on
mastodon [5].

If a solution have to be implemented, it definitively should take a different
approach than just disabling Lockdown. If your interested by working on the
original patch, I'd gladly review it.

[1]: https://lore.kernel.org/all/20250728111517.134116-1-nik.borisov@suse.com/
[2]: https://mjg59.dreamwidth.org/55845.html
[3]: https://lore.kernel.org/lkml/20210220013255.1083202-1-matthewgarrett@google.com/
[4]: https://lore.kernel.org/all/IA1PR14MB62243E515C24AE8BF40E36BCB14BA@IA1PR14MB6224.namprd14.prod.outlook.com/
[5]: https://nondeterministic.computer/@mjg59/115491928573781876.

Best regards,

Nicolas

^ permalink raw reply

* Re: [PATCH] selftests/landlock: Skip scoped_signal subtest with MSG_OOB if not available
From: Mickaël Salaün @ 2026-07-10 11:10 UTC (permalink / raw)
  To: Thomas Huth
  Cc: Günther Noack, linux-security-module, Shuah Khan,
	linux-kselftest, linux-kernel
In-Reply-To: <20260710081642.405916-1-thuth@redhat.com>

Applied (with a Fixes tag), thanks!

On Fri, Jul 10, 2026 at 10:16:42AM +0200, Thomas Huth wrote:
> 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

* 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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox