Linux Security Modules development
 help / color / mirror / Atom feed
* Re: [PATCH v5 06/14] module: Switch load_info::len to size_t
From: Thomas Weißschuh @ 2026-05-26 11:35 UTC (permalink / raw)
  To: Petr Pavlu
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
	Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Sami Tolvanen,
	Daniel Gomez, Paul Moore, James Morris, Serge E. Hallyn,
	Jonathan Corbet, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Naveen N Rao, Mimi Zohar, Roberto Sassu,
	Dmitry Kasatkin, Eric Snowberg, Nicolas Schier, Daniel Gomez,
	Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
	Xiu Jianfeng, Martin KaFai Lau, Song Liu, Yonghong Song,
	Jiri Olsa, bpf, Fabian Grünbichler, Arnout Engelen,
	Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
	Eric Biggers, Sebastian Andrzej Siewior, linux-kbuild,
	linux-kernel, linux-arch, linux-modules, linux-security-module,
	linux-doc, linuxppc-dev, linux-integrity, debian-kernel
In-Reply-To: <8de0e6ad-987a-4729-bbd0-8399968dbb48@suse.com>

On 2026-05-26 11:47:09+0200, Petr Pavlu wrote:
> On 5/5/26 11:05 AM, Thomas Weißschuh wrote:
> > Switching the types will make some later changes cleaner.
> 
> Since the updated version drops the patch "module: Deduplicate signature
> extraction", I believe this change is no longer necessary.

Ack.

(...)

Thomas

^ permalink raw reply

* Re: [PATCH v5 11/13] ima: Support staging and deleting N measurements entries
From: Mimi Zohar @ 2026-05-26 11:08 UTC (permalink / raw)
  To: Roberto Sassu, corbet, skhan, dmitry.kasatkin, eric.snowberg,
	paul, jmorris, serge
  Cc: linux-doc, linux-kernel, linux-integrity, linux-security-module,
	gregorylumen, chenste, nramas, Roberto Sassu
In-Reply-To: <20260429160319.4162918-12-roberto.sassu@huaweicloud.com>

On Wed, 2026-04-29 at 18:03 +0200, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
> 
> Add support for sending a value N between 1 and ULONG_MAX to the IMA
> original measurement interface. This value represents the number of
> measurements that should be deleted from the current measurements list. In
> this case, measurements are staged in an internal non-user visible list,
> and immediately deleted.
> 
> This staging method allows the remote attestation agents to easily separate
> the measurements that were verified (staged and deleted) from those that
> weren't due to the race between taking a TPM quote and reading the
> measurements list.

The reason for removing records from the IMA measurement list is to free kernel
memory.  However, the level of precision in removing only those measurements
needed for the quote seems necessary only if the measurement records are not
being saved.  Upstreaming a feature to remove measurement records from the IMA
measurement list is to address the kernel memory issue — clearly not to drop
measurement records and break attestation.

> 
> In order to minimize the locking time of ima_extend_list_mutex, deleting
> N entries is realized by doing a lockless walk in the current measurements
> list to determine the N-th entry to cut, to cut the current measurements
> list under the lock, and by deleting the excess entries after releasing the
> lock.
> 
> Flushing the hash table is not supported for N entries, since it would
> require removing the N entries one by one from the hash table under the
> ima_extend_list_mutex lock, which would increase the locking time.
> 
> The ima_extend_list_mutex lock is necessary in ima_dump_measurement_list()
> because ima_queue_delete_partial() uses __list_cut_position() to modify
> ima_measurements, for which no RCU-safe variant exists. For the staging
> with prompt flavor alone, list_replace_rcu() could have been used instead,
> but since both flavors share the same kexec serialization path, the mutex
> is required regardless.

Thank you for the clear explanation for the changes and limitations required to
support this feature.

The changes needed for supporting "stage and delete N" measurement records
should be limited to this patch.  Patch 9/13 should have used
list_replace_rcu(), without the mutex_lock.

> 
> Link: https://github.com/linux-integrity/linux/issues/1
> Suggested-by: Steven Chen <chenste@linux.microsoft.com>
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>

Otherwise,

Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>

^ permalink raw reply

* Re: [PATCH v5 07/14] module: Make module authentication usable without MODULE_SIG
From: Petr Pavlu @ 2026-05-26 10:53 UTC (permalink / raw)
  To: Thomas Weißschuh
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
	Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Sami Tolvanen,
	Daniel Gomez, Paul Moore, James Morris, Serge E. Hallyn,
	Jonathan Corbet, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Naveen N Rao, Mimi Zohar, Roberto Sassu,
	Dmitry Kasatkin, Eric Snowberg, Nicolas Schier, Daniel Gomez,
	Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
	Xiu Jianfeng, Martin KaFai Lau, Song Liu, Yonghong Song,
	Jiri Olsa, bpf, Fabian Grünbichler, Arnout Engelen,
	Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
	Eric Biggers, Sebastian Andrzej Siewior, linux-kbuild,
	linux-kernel, linux-arch, linux-modules, linux-security-module,
	linux-doc, linuxppc-dev, linux-integrity, debian-kernel
In-Reply-To: <20260505-module-hashes-v5-7-e174a5a49fce@weissschuh.net>

On 5/5/26 11:05 AM, Thomas Weißschuh wrote:
> The module authentication functionality will also be used by the
> hash-based module authentication. Split it out from CONFIG_MODULE_SIG
> so it is usable by both.
> 
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> [...]
> diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
> index f535181e0d98..84297da666ff 100644
> --- a/kernel/module/Kconfig
> +++ b/kernel/module/Kconfig
> @@ -271,9 +271,12 @@ config MODULE_SIG
>  	  debuginfo strip done by some packagers (such as rpmbuild) and
>  	  inclusion into an initramfs that wants the module size reduced.
>  
> +config MODULE_AUTH
> +	def_bool MODULE_SIG
> +
>  config MODULE_SIG_FORCE
>  	bool "Require modules to be validly signed"
> -	depends on MODULE_SIG
> +	depends on MODULE_AUTH
>  	help
>  	  Reject unsigned modules or signed modules for which we don't have a
>  	  key.  Without this, such modules will simply taint the kernel.

Should MODULE_SIG_FORCE be renamed to MODULE_AUTH_FORCE, along with
renaming the sig_enforce functionality in kernel/module/auth.c to
auth_enforce?

-- 
Thanks,
Petr

^ permalink raw reply

* Re: [PATCH] firmware: arm_ffa: Treat missing FF-A feature on a platform as a probe miss
From: Yeoreum Yun @ 2026-05-26 10:51 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm, Nathan Chancellor
In-Reply-To: <20260526103649.5684-1-sudeep.holla@kernel.org>

LGTM.

Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>

On Tue, May 26, 2026 at 11:36:49AM +0100, Sudeep Holla wrote:
> When FF-A initialisation is driven from a platform device probe, systems
> that do not implement FF-A can return -EOPNOTSUPP from the early transport
> or version discovery paths. Driver core treats that as a matched probe
> failure and prints:
> 
>   |  arm-ffa arm-ffa: probe with driver arm-ffa failed with error -95
> 
> That is noisy for a firmware interface that can be absent on otherwise
> valid systems. Driver core already treats -ENODEV and -ENXIO as quiet
> rejected matches, so translate only the early unsupported discovery cases
> to -ENODEV. Keep later setup failures unchanged so real FF-A
> initialisation problems are still reported as probe failures.
> 
> Reported-by: Nathan Chancellor <nathan@kernel.org>
> Closes: https://lore.kernel.org/all/20260523001148.GA1319283@ax162
> Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
> ---
>  drivers/firmware/arm_ffa/driver.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> index 54984e1b9741..0f468362c288 100644
> --- a/drivers/firmware/arm_ffa/driver.c
> +++ b/drivers/firmware/arm_ffa/driver.c
> @@ -2109,7 +2109,7 @@ static int ffa_probe(struct platform_device *pdev)
>  
>  	ret = ffa_transport_init(&invoke_ffa_fn);
>  	if (ret)
> -		return ret;
> +		return ret == -EOPNOTSUPP ? -ENODEV : ret;
>  
>  	drv_info = kzalloc_obj(*drv_info);
>  	if (!drv_info)
> @@ -2117,8 +2117,11 @@ static int ffa_probe(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, drv_info);
>  
>  	ret = ffa_version_check(&drv_info->version);
> -	if (ret)
> +	if (ret) {
> +		if (ret == -EOPNOTSUPP)
> +			ret = -ENODEV;
>  		goto free_drv_info;
> +	}
>  
>  	if (ffa_id_get(&drv_info->vm_id)) {
>  		pr_err("failed to obtain VM id for self\n");
> -- 
> 2.43.0
> 

-- 
Sincerely,
Yeoreum Yun

^ permalink raw reply

* Re: [PATCH v2 10/17] landlock: Set audit_net.sk for socket access checks
From: Mickaël Salaün @ 2026-05-26 10:42 UTC (permalink / raw)
  To: Christian Brauner, Günther Noack, Steven Rostedt
  Cc: Jann Horn, Jeff Xu, Justin Suess, Kees Cook, Masami Hiramatsu,
	Mathieu Desnoyers, Matthieu Buffet, Mikhail Ivanov, Tingmao Wang,
	kernel-team, linux-fsdevel, linux-security-module,
	linux-trace-kernel, stable
In-Reply-To: <20260406143717.1815792-11-mic@digikod.net>

I merged this fix in the -next branch.

On Mon, Apr 06, 2026 at 04:37:08PM +0200, Mickaël Salaün wrote:
> Set audit_net.sk in current_check_access_socket() to provide the socket
> object to audit_log_lsm_data().  This makes Landlock consistent with
> AppArmor, which always sets .sk for socket operations, and with
> SELinux's generic socket permission checks.
> 
> The socket's local and foreign address information (laddr, lport, faddr,
> fport) is logged by the shared lsm_audit.c infrastructure when the
> socket has bound or connected state.  Fields with zero values are
> suppressed by print_ipv4_addr()/print_ipv6_addr(), so the audit output
> is unchanged for the common case of bind denials on unbound sockets.
> For connect denials after a prior bind, the bound local address (laddr,
> lport) appears before the existing sockaddr fields (daddr, dest).
> 
> No existing fields are removed or reordered, and the new field names
> (laddr, lport, faddr, fport) are standard audit fields already emitted
> by other LSMs through the same lsm_audit.c code path.
> 
> Add net_bind and net_connect audit tests.  The net_bind test verifies
> basic net denial auditing.  The net_connect test binds to an allowed
> port, then connects to a denied port, and verifies that the audit record
> includes laddr/lport from the socket state.
> 
> Fixes: 9f74411a40ce ("landlock: Log TCP bind and connect denials")
> Cc: stable@vger.kernel.org
> Cc: Günther Noack <gnoack@google.com>
> Signed-off-by: Mickaël Salaün <mic@digikod.net>
> ---
> 
> Changes since v1:
> - New patch.
> ---
>  security/landlock/net.c                       |   1 +
>  tools/testing/selftests/landlock/audit_test.c | 187 ++++++++++++++++++
>  2 files changed, 188 insertions(+)
> 
> diff --git a/security/landlock/net.c b/security/landlock/net.c
> index a2aefc7967a1..d8bc9e0d012a 100644
> --- a/security/landlock/net.c
> +++ b/security/landlock/net.c
> @@ -225,6 +225,7 @@ static int current_check_access_socket(struct socket *const sock,
>  		return 0;
>  
>  	audit_net.family = address->sa_family;
> +	audit_net.sk = sock->sk;
>  	landlock_log_denial(subject,
>  			    &(struct landlock_request){
>  				    .type = LANDLOCK_REQUEST_NET_ACCESS,
> diff --git a/tools/testing/selftests/landlock/audit_test.c b/tools/testing/selftests/landlock/audit_test.c
> index da0bfd06391e..65dfb272c825 100644
> --- a/tools/testing/selftests/landlock/audit_test.c
> +++ b/tools/testing/selftests/landlock/audit_test.c
> @@ -6,14 +6,17 @@
>   */
>  
>  #define _GNU_SOURCE
> +#include <arpa/inet.h>
>  #include <errno.h>
>  #include <fcntl.h>
>  #include <limits.h>
>  #include <linux/landlock.h>
> +#include <netinet/in.h>
>  #include <pthread.h>
>  #include <stdlib.h>
>  #include <sys/mount.h>
>  #include <sys/prctl.h>
> +#include <sys/socket.h>
>  #include <sys/types.h>
>  #include <sys/wait.h>
>  #include <unistd.h>
> @@ -160,6 +163,190 @@ TEST_F(audit, layers)
>  	EXPECT_EQ(0, close(ruleset_fd));
>  }
>  
> +static int matches_log_net_bind(struct __test_metadata *const _metadata,
> +				int audit_fd, __u16 port, __u64 *domain_id)
> +{
> +	/*
> +	 * The socket is unbound at bind() time, so laddr/lport/faddr/fport from
> +	 * the socket object are zero and not printed.  Only the sockaddr fields
> +	 * (src) appear.
> +	 */
> +	static const char log_template[] = REGEX_LANDLOCK_PREFIX
> +		" blockers=net\\.bind_tcp src=%u$";
> +	char log_match[sizeof(log_template) + 10];
> +
> +	snprintf(log_match, sizeof(log_match), log_template, port);
> +	return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match,
> +				  domain_id);
> +}
> +
> +/*
> + * Verifies that network denial audit records include enriched socket
> + * information (laddr/lport/faddr/fport) from the socket object.
> + */
> +TEST_F(audit, net_bind)
> +{
> +	const struct landlock_ruleset_attr ruleset_attr = {
> +		.handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP,
> +	};
> +	struct landlock_net_port_attr net_port = {
> +		.allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
> +		.port = 1024,
> +	};
> +	int status, ruleset_fd;
> +	pid_t child;
> +	__u64 denial_dom = 1;
> +
> +	ruleset_fd =
> +		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
> +	ASSERT_LE(0, ruleset_fd);
> +
> +	/* Allow port 1024 only. */
> +	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
> +				       &net_port, 0));
> +
> +	EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
> +
> +	child = fork();
> +	ASSERT_LE(0, child);
> +	if (child == 0) {
> +		struct sockaddr_in addr = {
> +			.sin_family = AF_INET,
> +			.sin_port = htons(1025),
> +			.sin_addr.s_addr = htonl(INADDR_ANY),
> +		};
> +		int sock_fd;
> +
> +		EXPECT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
> +		close(ruleset_fd);
> +
> +		/* Bind to port 1025 (not allowed). */
> +		sock_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
> +		ASSERT_LE(0, sock_fd);
> +		EXPECT_EQ(-1, bind(sock_fd, (struct sockaddr *)&addr,
> +				   sizeof(addr)));
> +		EXPECT_EQ(EACCES, errno);
> +		close(sock_fd);
> +
> +		/* Verify audit record with enriched socket info. */
> +		EXPECT_EQ(0, matches_log_net_bind(_metadata, self->audit_fd,
> +						  1025, &denial_dom));
> +		EXPECT_NE(denial_dom, 1);
> +		EXPECT_NE(denial_dom, 0);
> +
> +		_exit(_metadata->exit_code);
> +		return;
> +	}
> +
> +	ASSERT_EQ(child, waitpid(child, &status, 0));
> +	if (WIFSIGNALED(status) || !WIFEXITED(status) ||
> +	    WEXITSTATUS(status) != EXIT_SUCCESS)
> +		_metadata->exit_code = KSFT_FAIL;
> +
> +	EXPECT_EQ(0, close(ruleset_fd));
> +}
> +
> +static int matches_log_net_connect(struct __test_metadata *const _metadata,
> +				   int audit_fd, __u16 denied_port,
> +				   __u16 bound_port, __u64 *domain_id)
> +{
> +	/*
> +	 * After bind(), the socket has local address state.  The audit record
> +	 * should include laddr/lport from the socket (via audit_net.sk) and
> +	 * daddr/dest from the connect sockaddr.
> +	 */
> +	static const char log_template[] = REGEX_LANDLOCK_PREFIX
> +		" blockers=net\\.connect_tcp"
> +		" laddr=127\\.0\\.0\\.1 lport=%u"
> +		" daddr=127\\.0\\.0\\.1 dest=%u$";
> +	char log_match[sizeof(log_template) + 20];
> +
> +	snprintf(log_match, sizeof(log_match), log_template, bound_port,
> +		 denied_port);
> +	return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match,
> +				  domain_id);
> +}
> +
> +/*
> + * Verifies that network denial audit records for connect include enriched
> + * socket information (laddr/lport) from the socket object after a prior bind.
> + * This complements net_bind which tests the unbound case.
> + */
> +TEST_F(audit, net_connect)
> +{
> +	const struct landlock_ruleset_attr ruleset_attr = {
> +		.handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP |
> +				      LANDLOCK_ACCESS_NET_CONNECT_TCP,
> +	};
> +	struct landlock_net_port_attr net_port;
> +	int status, ruleset_fd;
> +	pid_t child;
> +	__u64 denial_dom = 1;
> +
> +	ruleset_fd =
> +		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
> +	ASSERT_LE(0, ruleset_fd);
> +
> +	/* Allow bind to port 1024 and connect to port 1024. */
> +	net_port.allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP |
> +				  LANDLOCK_ACCESS_NET_CONNECT_TCP;
> +	net_port.port = 1024;
> +	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
> +				       &net_port, 0));
> +
> +	EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
> +
> +	child = fork();
> +	ASSERT_LE(0, child);
> +	if (child == 0) {
> +		struct sockaddr_in bind_addr = {
> +			.sin_family = AF_INET,
> +			.sin_port = htons(1024),
> +			.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
> +		};
> +		struct sockaddr_in conn_addr = {
> +			.sin_family = AF_INET,
> +			.sin_port = htons(1025),
> +			.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
> +		};
> +		int sock_fd, optval = 1;
> +
> +		EXPECT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
> +		close(ruleset_fd);
> +
> +		sock_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
> +		ASSERT_LE(0, sock_fd);
> +		ASSERT_EQ(0, setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
> +					&optval, sizeof(optval)));
> +
> +		/* Bind to allowed port 1024 (succeeds). */
> +		ASSERT_EQ(0, bind(sock_fd, (struct sockaddr *)&bind_addr,
> +				  sizeof(bind_addr)));
> +
> +		/* Connect to denied port 1025 (fails). */
> +		EXPECT_EQ(-1, connect(sock_fd, (struct sockaddr *)&conn_addr,
> +				      sizeof(conn_addr)));
> +		EXPECT_EQ(EACCES, errno);
> +		close(sock_fd);
> +
> +		/* Verify audit record with laddr/lport from bound socket. */
> +		EXPECT_EQ(0, matches_log_net_connect(_metadata, self->audit_fd,
> +						     1025, 1024, &denial_dom));
> +		EXPECT_NE(denial_dom, 1);
> +		EXPECT_NE(denial_dom, 0);
> +
> +		_exit(_metadata->exit_code);
> +		return;
> +	}
> +
> +	ASSERT_EQ(child, waitpid(child, &status, 0));
> +	if (WIFSIGNALED(status) || !WIFEXITED(status) ||
> +	    WEXITSTATUS(status) != EXIT_SUCCESS)
> +		_metadata->exit_code = KSFT_FAIL;
> +
> +	EXPECT_EQ(0, close(ruleset_fd));
> +}
> +
>  struct thread_data {
>  	pid_t parent_pid;
>  	int ruleset_fd, pipe_child, pipe_parent;
> -- 
> 2.53.0
> 
> 

^ permalink raw reply

* [PATCH] firmware: arm_ffa: Treat missing FF-A feature on a platform as a probe miss
From: Sudeep Holla @ 2026-05-26 10:36 UTC (permalink / raw)
  To: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm
  Cc: Sudeep Holla, Yeoreum Yun, Nathan Chancellor

When FF-A initialisation is driven from a platform device probe, systems
that do not implement FF-A can return -EOPNOTSUPP from the early transport
or version discovery paths. Driver core treats that as a matched probe
failure and prints:

  |  arm-ffa arm-ffa: probe with driver arm-ffa failed with error -95

That is noisy for a firmware interface that can be absent on otherwise
valid systems. Driver core already treats -ENODEV and -ENXIO as quiet
rejected matches, so translate only the early unsupported discovery cases
to -ENODEV. Keep later setup failures unchanged so real FF-A
initialisation problems are still reported as probe failures.

Reported-by: Nathan Chancellor <nathan@kernel.org>
Closes: https://lore.kernel.org/all/20260523001148.GA1319283@ax162
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
 drivers/firmware/arm_ffa/driver.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 54984e1b9741..0f468362c288 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -2109,7 +2109,7 @@ static int ffa_probe(struct platform_device *pdev)
 
 	ret = ffa_transport_init(&invoke_ffa_fn);
 	if (ret)
-		return ret;
+		return ret == -EOPNOTSUPP ? -ENODEV : ret;
 
 	drv_info = kzalloc_obj(*drv_info);
 	if (!drv_info)
@@ -2117,8 +2117,11 @@ static int ffa_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, drv_info);
 
 	ret = ffa_version_check(&drv_info->version);
-	if (ret)
+	if (ret) {
+		if (ret == -EOPNOTSUPP)
+			ret = -ENODEV;
 		goto free_drv_info;
+	}
 
 	if (ffa_id_get(&drv_info->vm_id)) {
 		pr_err("failed to obtain VM id for self\n");
-- 
2.43.0


^ permalink raw reply related

* Re: [net-next] netlabel: validate unlabeled mask attribute length
From: Paolo Abeni @ 2026-05-26 10:35 UTC (permalink / raw)
  To: Chenguang Zhao, Paul Moore, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Simon Horman
  Cc: netdev, linux-security-module
In-Reply-To: <20260522054521.1169755-1-zhaochenguang@kylinos.cn>

On 5/22/26 7:45 AM, Chenguang Zhao wrote:
> netlbl_unlabel_addrinfo_get() checked the address length
> but allowed shorter mask attributes to pass through to
> fixed-size address reads.
> 
> Signed-off-by: Chenguang Zhao <zhaochenguang@kylinos.cn>
> ---
>  netlbl_unlabel_addrinfo_get() only rejected a mask
>  length mismatch when the address attribute length
>  was also invalid.  A crafted Generic Netlink request
>  could therefore provide a valid IPv4/IPv6 address
>  attribute with a shorter mask attribute.
>  
>  NLA_BINARY policy lengths are maximum lengths,
>  not exact lengths, so the short mask can pass
>  policy validation.  The mask is later read as
>  a full struct in_addr or struct in6_addr.
>  Require both address and mask attributes to
>  have the exact expected size.

The above should be part of the commit message. Also this looks like a
fix that should target the 'net' tree and include a 'Fixes:' tag.

Thanks,

Paolo


^ permalink raw reply

* Re: [PATCH v5 06/14] module: Switch load_info::len to size_t
From: Petr Pavlu @ 2026-05-26  9:47 UTC (permalink / raw)
  To: Thomas Weißschuh
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
	Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Sami Tolvanen,
	Daniel Gomez, Paul Moore, James Morris, Serge E. Hallyn,
	Jonathan Corbet, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Naveen N Rao, Mimi Zohar, Roberto Sassu,
	Dmitry Kasatkin, Eric Snowberg, Nicolas Schier, Daniel Gomez,
	Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
	Xiu Jianfeng, Martin KaFai Lau, Song Liu, Yonghong Song,
	Jiri Olsa, bpf, Fabian Grünbichler, Arnout Engelen,
	Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
	Eric Biggers, Sebastian Andrzej Siewior, linux-kbuild,
	linux-kernel, linux-arch, linux-modules, linux-security-module,
	linux-doc, linuxppc-dev, linux-integrity, debian-kernel
In-Reply-To: <20260505-module-hashes-v5-6-e174a5a49fce@weissschuh.net>

On 5/5/26 11:05 AM, Thomas Weißschuh wrote:
> Switching the types will make some later changes cleaner.

Since the updated version drops the patch "module: Deduplicate signature
extraction", I believe this change is no longer necessary.

> size_t is also the semantically correct type for this field.
> 
> As both 'size_t' and 'unsigned long' are always the same size, this
> should be risk-free.

The module 'len' would now start in init_module() as 'unsigned long',
then change in copy_module_from_user() to size_t, and then back to
'unsigned long' when calling copy_chunked_from_user(). The current code
is more consistent and mostly uses 'unsigned long', matching the syscall
interface.

-- 
Thanks,
Petr

^ permalink raw reply

* Re: [PATCH 2/4] firmware: arm_ffa: Register core as a platform driver
From: Sudeep Holla @ 2026-05-26  9:41 UTC (permalink / raw)
  To: Nathan Chancellor
  Cc: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm, Yeoreum Yun
In-Reply-To: <20260523001148.GA1319283@ax162>

On Fri, May 22, 2026 at 05:11:48PM -0700, Nathan Chancellor wrote:
> Hi Sudeep,
> 
> On Fri, May 08, 2026 at 06:54:16PM +0100, Sudeep Holla wrote:
> > Move the FF-A core bring-up and teardown paths into platform driver
> > probe and remove callbacks, and register a synthetic arm-ffa platform
> > device to bind the driver.
> > 
> > This makes the FF-A core lifetime follow the driver model while keeping
> > the device creation internal to the FF-A core. Use normal platform driver
> > registration so the probe path has standard driver-core semantics.
> > 
> > The synthetic platform device is a temporary bridge until ACPI and
> > devicetree describe the FF-A core device or object. Once those firmware
> > description paths are defined, the internal platform device creation can
> > be dropped and the driver can bind to the firmware-described device
> > directly.
> > 
> > Since the transport selection now happens from the platform probe path,
> > drop the __init annotation from ffa_transport_init().
> > 
> > Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
> 
> I am seeing
> 
>   arm-ffa arm-ffa: probe with driver arm-ffa failed with error -95
> 
> on my two arm64 test machines after this change landed in -next as
> commit e659fc8e537c ("firmware: arm_ffa: Register core as a platform
> driver"), is this expected? If so, perhaps it should be silenced?
> 

Yes it should be silenced, I will see how it can be done. Thanks for the
report.

-- 
Regards,
Sudeep

^ permalink raw reply

* Re: [PATCH] tpm-buf: memory-safe allocations
From: Jarkko Sakkinen @ 2026-05-26  7:53 UTC (permalink / raw)
  To: James Bottomley
  Cc: linux-integrity, Jarkko Sakkinen, Arun Menon, Daniel P. Smith,
	Alec Brown, Ross Philipson, Stefan Berger, Peter Huewe,
	Jason Gunthorpe, Mimi Zohar, David Howells, Paul Moore,
	James Morris, Serge E. Hallyn, linux-kernel, keyrings,
	linux-security-module
In-Reply-To: <33b4a34ceea0934e238c08e0256b975511ef99c8.camel@HansenPartnership.com>

On Mon, May 25, 2026 at 01:50:51PM -0400, James Bottomley wrote:
> On Fri, 2026-05-22 at 04:35 +0300, Jarkko Sakkinen wrote:
> > Decouple kzalloc from buffer creation, so that a managed allocation
> > can be
> > used:
> > 
> > 	struct tpm_buf *buf __free(kfree) buf = kzalloc(TPM_BUFSIZE,
> > 						GFP_KERNEL);
> > 	if (!buf)
> > 		return -ENOMEM;
> > 
> > 	tpm_buf_init(buf, TPM_BUFSIZE);
> > 
> > Alternatively, stack allocations are also possible:
> > 
> > 	u8 buf_data[512];
> > 	struct tpm_buf *buf = (struct tpm_buf *)buf_data;
> > 	tpm_buf_init(buf, sizeof(buf_data));
> 
> This isn't really a good idea from a security point of view.  Remember
> the buffer has to be big enough for both the sent and the received
> data.  Today we simply set TPM_BUFSIZE to the maximum amount a TPM
> requires and all the send and receives just work.  If we let callers
> set this size, we're asking for them to get it wrong (or at least
> forget about the receive part) and for us to get a DMA overrun from the
> TPM ... which might be potentially exploitable depending on how it
> occurs (think of an unseal of user chosen data overrunning).

It's one patch so you're free to remark the call sites where this
happens. This is not a majorn concern at all.

> 
> I get the desire to support some of the newer chunked commands, but
> since none of them is yet present in the kernel, why not introduce an
> API that works only for them to avoid the risk of a security cockup in
> existing code?

Multiplying amount of maintenance work with a redundant implemntation
is not something I support.

> 
> Regards,
> 
> James


BR, Jarkko

^ permalink raw reply

* Re: [PATCH 00/11] Convert moduleparams to seq_buf
From: Petr Pavlu @ 2026-05-26  6:53 UTC (permalink / raw)
  To: Kees Cook
  Cc: Luis Chamberlain, Pengpeng Hou, Richard Weinberger, Anton Ivanov,
	Johannes Berg, Rafael J. Wysocki, Len Brown, Corey Minyard,
	Gabriel Somlo, Michael S. Tsirkin, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Tvrtko Ursulin, David Airlie, Simona Vetter,
	Bart Van Assche, Jason Gunthorpe, Leon Romanovsky,
	Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
	Bjorn Helgaas, Hannes Reinecke, James E.J. Bottomley,
	Martin K. Petersen, Daniel Lezcano, Zhang Rui, Lukasz Luba,
	Greg Kroah-Hartman, Jiri Slaby, Alan Stern, Jason Wang, Xuan Zhuo,
	Eugenio Pérez, Jason Baron, Jim Cromie, Tiwei Bie,
	Benjamin Berg, Ilpo Järvinen, David E. Box,
	Maciej W. Rozycki, Srinivas Pandruvada, Peter Zijlstra,
	Heiko Carstens, Vasily Gorbik, Sean Christopherson, Paolo Bonzini,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vinod Koul, Frank Li, Daniel Gomez, Sami Tolvanen,
	Aaron Tomlin, Alexander Potapenko, Marco Elver, Dmitry Vyukov,
	Andrew Morton, John Johansen, Paul Moore, James Morris,
	Serge E. Hallyn, Andy Shevchenko, Georgia Garcia, kvm, dmaengine,
	linux-modules, kasan-dev, linux-mm, apparmor,
	linux-security-module, linux-um, linux-acpi, openipmi-developer,
	qemu-devel, intel-gfx, dri-devel, linux-rdma, linux-media,
	linux-pci, linux-scsi, linux-pm, linuxppc-dev, linux-serial,
	linux-usb, usb-storage, virtualization, linux-kernel, linux-arch,
	netdev, linux-fsdevel, linux-hardening
In-Reply-To: <20260521133315.work.845-kees@kernel.org>

On 5/21/26 3:33 PM, Kees Cook wrote:
> Hi,
> 
> I tried to trim the CC list here, but it's still pretty huge...
> 
> We've had a long-standing issue with "write to a string pointer" callbacks
> that don't bounds check the destination (and for which the bounds is
> also not part of the callback prototype, even if it is "known" to be
> PAGE_SIZE, which sysfs_emit() depends on). Both moduleparams and sysfs
> use this pattern. As a first step, and to test the migration method,
> migrate moduleparams first.
> 
> There are 2 "mechanical" treewide patches that are handled by Coccinelle:
> - treewide: Convert struct kernel_param_ops initializers to DEFINE_KERNEL_PARAM_OPS
> - treewide: Convert custom kernel_param_ops .get callbacks to seq_buf via cocci
> 
> The last treewide patch is manual, and may need to be broken up into
> per-subsystem patches, though I'd prefer to avoid this, as it would
> extend the migration from 1 relase to at least 2 releases. (1 to
> release the migration infrastructure, then 1 release to collect all the
> subsystem changes, and possibly 1 more release to remove the migration
> infrastructure.)
> 
> Thoughts, questions?

This looks reasonable to me. I added a few minor comments on the patches
but they already look solid.

-- 
Thanks,
Petr

^ permalink raw reply

* Re: [bug report] keys: request_key_auth payload use-after-free in keyctl_instantiate_key_common()
From: Shaomin Chen @ 2026-05-26  2:50 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: keyrings, linux-security-module, linux-kernel, David Howells,
	Paul Moore, James Morris, Serge E. Hallyn
In-Reply-To: <20260519144403.436694-1-eeesssooo020@gmail.com>

Thanks, I sent a candidate patch here:

https://lore.kernel.org/r/20260526024838.3368409-1-eeesssooo020@gmail.com

Shaomin

^ permalink raw reply

* [PATCH] keys: Pin request_key_auth payload in instantiate paths
From: Shaomin Chen @ 2026-05-26  2:48 UTC (permalink / raw)
  To: keyrings, linux-security-module, linux-kernel
  Cc: David Howells, Jarkko Sakkinen, Paul Moore, James Morris,
	Serge E. Hallyn

keyctl_instantiate_key_common() reads request_key_auth from the assumed
auth key before copying an instantiation payload from userspace.  The copy
can fault and sleep.  If the request completes and revokes the auth key in
that window, the auth payload can be detached and freed before the
instantiate path uses it again.

A request-key helper reproducer can trigger this race.  One helper child
blocks in KEYCTL_INSTANTIATE_IOV while the original helper instantiates the
requested key and returns.  KASAN then reports a use-after-free from the
stale request_key_auth payload in keyctl_instantiate_key_common().

Give request_key_auth payloads a refcount.  Take a payload reference while
authkey->sem stabilizes the payload and revocation state.  Hold that
reference across the instantiate and reject paths.  Drop the auth key
owning reference from revoke and destroy.

Reported-by: Shaomin Chen <eeesssooo020@gmail.com>
Closes: https://lore.kernel.org/r/20260519144403.436694-1-eeesssooo020@gmail.com
Signed-off-by: Shaomin Chen <eeesssooo020@gmail.com>
---
 include/keys/request_key_auth-type.h |  2 ++
 security/keys/internal.h             |  2 ++
 security/keys/keyctl.c               | 24 +++++++++++++++-----
 security/keys/request_key_auth.c     | 33 ++++++++++++++++++++++++++--
 4 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/include/keys/request_key_auth-type.h b/include/keys/request_key_auth-type.h
index 36b89a933310..01e42ee5f409 100644
--- a/include/keys/request_key_auth-type.h
+++ b/include/keys/request_key_auth-type.h
@@ -9,12 +9,14 @@
 #define _KEYS_REQUEST_KEY_AUTH_TYPE_H
 
 #include <linux/key.h>
+#include <linux/refcount.h>
 
 /*
  * Authorisation record for request_key().
  */
 struct request_key_auth {
 	struct rcu_head		rcu;
+	refcount_t		usage;
 	struct key		*target_key;
 	struct key		*dest_keyring;
 	const struct cred	*cred;
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 2cffa6dc8255..b7b622bc36a1 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -208,6 +208,8 @@ extern struct key *request_key_auth_new(struct key *target,
 					const void *callout_info,
 					size_t callout_len,
 					struct key *dest_keyring);
+struct request_key_auth *request_key_auth_get(struct key *authkey);
+void request_key_auth_put(struct request_key_auth *rka);
 
 extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
 
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index ef855d69c97a..d14ace88e529 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1197,9 +1197,13 @@ static long keyctl_instantiate_key_common(key_serial_t id,
 	if (!instkey)
 		goto error;
 
-	rka = instkey->payload.data[0];
-	if (rka->target_key->serial != id)
+	rka = request_key_auth_get(instkey);
+	if (!rka) {
+		ret = -EKEYREVOKED;
 		goto error;
+	}
+	if (rka->target_key->serial != id)
+		goto error_put_rka;
 
 	/* pull the payload in if one was supplied */
 	payload = NULL;
@@ -1208,7 +1212,7 @@ static long keyctl_instantiate_key_common(key_serial_t id,
 		ret = -ENOMEM;
 		payload = kvmalloc(plen, GFP_KERNEL);
 		if (!payload)
-			goto error;
+			goto error_put_rka;
 
 		ret = -EFAULT;
 		if (!copy_from_iter_full(payload, plen, from))
@@ -1234,6 +1238,8 @@ static long keyctl_instantiate_key_common(key_serial_t id,
 
 error2:
 	kvfree_sensitive(payload, plen);
+error_put_rka:
+	request_key_auth_put(rka);
 error:
 	return ret;
 }
@@ -1358,15 +1364,19 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error,
 	if (!instkey)
 		goto error;
 
-	rka = instkey->payload.data[0];
-	if (rka->target_key->serial != id)
+	rka = request_key_auth_get(instkey);
+	if (!rka) {
+		ret = -EKEYREVOKED;
 		goto error;
+	}
+	if (rka->target_key->serial != id)
+		goto error_put_rka;
 
 	/* find the destination keyring if present (which must also be
 	 * writable) */
 	ret = get_instantiation_keyring(ringid, rka, &dest_keyring);
 	if (ret < 0)
-		goto error;
+		goto error_put_rka;
 
 	/* instantiate the key and link it into a keyring */
 	ret = key_reject_and_link(rka->target_key, timeout, error,
@@ -1379,6 +1389,8 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error,
 	if (ret == 0)
 		keyctl_change_reqkey_auth(NULL);
 
+error_put_rka:
+	request_key_auth_put(rka);
 error:
 	return ret;
 }
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index a7d7538c1f70..282e09d8fa46 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -23,6 +23,7 @@ static void request_key_auth_describe(const struct key *, struct seq_file *);
 static void request_key_auth_revoke(struct key *);
 static void request_key_auth_destroy(struct key *);
 static long request_key_auth_read(const struct key *, char *, size_t);
+static void request_key_auth_rcu_disposal(struct rcu_head *);
 
 /*
  * The request-key authorisation key type definition.
@@ -115,6 +116,31 @@ static void free_request_key_auth(struct request_key_auth *rka)
 	kfree(rka);
 }
 
+/*
+ * Take a reference to the request-key authorisation payload so callers can
+ * drop authkey->sem before doing operations that may sleep.
+ */
+struct request_key_auth *request_key_auth_get(struct key *authkey)
+{
+	struct request_key_auth *rka;
+
+	down_read(&authkey->sem);
+	rka = dereference_key_locked(authkey);
+	if (rka && !test_bit(KEY_FLAG_REVOKED, &authkey->flags))
+		refcount_inc(&rka->usage);
+	else
+		rka = NULL;
+	up_read(&authkey->sem);
+
+	return rka;
+}
+
+void request_key_auth_put(struct request_key_auth *rka)
+{
+	if (rka && refcount_dec_and_test(&rka->usage))
+		call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
+}
+
 /*
  * Dispose of the request_key_auth record under RCU conditions
  */
@@ -136,8 +162,10 @@ static void request_key_auth_revoke(struct key *key)
 	struct request_key_auth *rka = dereference_key_locked(key);
 
 	kenter("{%d}", key->serial);
+	if (!rka)
+		return;
 	rcu_assign_keypointer(key, NULL);
-	call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
+	request_key_auth_put(rka);
 }
 
 /*
@@ -150,7 +178,7 @@ static void request_key_auth_destroy(struct key *key)
 	kenter("{%d}", key->serial);
 	if (rka) {
 		rcu_assign_keypointer(key, NULL);
-		call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
+		request_key_auth_put(rka);
 	}
 }
 
@@ -174,6 +202,7 @@ struct key *request_key_auth_new(struct key *target, const char *op,
 	rka = kzalloc_obj(*rka);
 	if (!rka)
 		goto error;
+	refcount_set(&rka->usage, 1);
 	rka->callout_info = kmemdup(callout_info, callout_len, GFP_KERNEL);
 	if (!rka->callout_info)
 		goto error_free_rka;
-- 
2.47.3

^ permalink raw reply related

* Re: [PATCH] tomoyo: Fix NULL pointer dereference in tomoyo_init_request_info() when domain is NULL
From: Tetsuo Handa @ 2026-05-26  2:04 UTC (permalink / raw)
  To: Jiakai Xu
  Cc: Serge E . Hallyn, James Morris, Kentaro Takeda, Paul Moore,
	linux-kernel, linux-security-module
In-Reply-To: <20260526012315.762144-1-xujiakai24@mails.ucas.ac.cn>

Thank you for a patch, but I don't think we need this change.

TOMOYO's initial domain is &tomoyo_kernel_domain, and each thread belongs to
a non-NULL domain. Therefore, tomoyo_domain() is not supposed to return NULL.

> Found by fuzzing. Here is the report:
> 
> Unable to handle kernel paging request at virtual address dfffffff00000003

Is this a NULL pointer dereference?
It seems to me that this is just a random memory corruption.


^ permalink raw reply

* [PATCH v2 2/2] security: smack: fix spelling mistake
From: fffsqian @ 2026-05-26  1:38 UTC (permalink / raw)
  To: casey, paul, jmorris, serge
  Cc: linux-security-module, linux-kernel, Qingshuang Fu

From: Qingshuang Fu <fuqingshuang@kylinos.cn>

Fix misspelling: overriden → overridden

Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>

Changes since v1:
- Split original single patch into two standalone patches,
  separate AppArmor and Smack changes for different maintainer trees.
---
 security/smack/smackfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 6e62dcb36f74..2820bd3ee72e 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -115,7 +115,7 @@ struct smack_known *smack_syslog_label;
 /*
  * Ptrace current rule
  * SMACK_PTRACE_DEFAULT    regular smack ptrace rules (/proc based)
- * SMACK_PTRACE_EXACT      labels must match, but can be overriden with
+ * SMACK_PTRACE_EXACT      labels must match, but can be overridden with
  *			   CAP_SYS_PTRACE
  * SMACK_PTRACE_DRACONIAN  labels must match, CAP_SYS_PTRACE has no effect
  */
-- 
2.25.1


^ permalink raw reply related

* [PATCH v2 1/2] security: apparmor: fix two spelling mistakes
From: fffsqian @ 2026-05-26  1:38 UTC (permalink / raw)
  To: john.johansen, paul, jmorris, serge
  Cc: apparmor, linux-security-module, linux-kernel, Qingshuang Fu

From: Qingshuang Fu <fuqingshuang@kylinos.cn>

Fix two spelling errors in comment:
- interated  →  interacted
- dont      →  don't

Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>

Changes since v1:
- Split original single patch into two standalone patches,
  separate AppArmor and Smack changes for different maintainer trees.
---
 security/apparmor/domain.c | 2 +-
 security/apparmor/lsm.c    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index f02bf770f638..7e097c40720a 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -135,7 +135,7 @@ static int label_compound_match(struct aa_profile *profile,
 	struct label_it i;
 	struct path_cond cond = { };
 
-	/* find first subcomponent that is in view and going to be interated with */
+	/* find first subcomponent that is in view and going to be interacted with */
 	label_for_each(i, label, tp) {
 		if (!aa_ns_visible(profile->ns, tp->ns, inview))
 			continue;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 3491e9f60194..51a388cfea11 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1493,7 +1493,7 @@ static int apparmor_socket_shutdown(struct socket *sock, int how)
  *
  * Note: can not sleep may be called with locks held
  *
- * dont want protocol specific in __skb_recv_datagram()
+ * don't want protocol specific in __skb_recv_datagram()
  * to deny an incoming connection  socket_sock_rcv_skb()
  */
 static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
-- 
2.25.1


^ permalink raw reply related

* [PATCH] tomoyo: Fix NULL pointer dereference in tomoyo_init_request_info() when domain is NULL
From: Jiakai Xu @ 2026-05-26  1:23 UTC (permalink / raw)
  To: linux-kernel, linux-security-module
  Cc: Serge E . Hallyn, James Morris, Kentaro Takeda, Paul Moore,
	Tetsuo Handa, Jiakai Xu

tomoyo_domain() can return NULL when the current task has no TOMOYO
domain_info set.  When this happens, tomoyo_init_request_info() sets 
r->domain = NULL and then dereferences the NULL domain via 
domain->profile and later domain->acl_info_list in tomoyo_check_acl(), 
causing a kernel page fault.

Add a NULL check after tomoyo_domain() and return TOMOYO_CONFIG_DISABLED
when domain is NULL.  All callers that can reach this path already check
for TOMOYO_CONFIG_DISABLED and bail out, so this prevents the crash
without changing the control flow for those callers.

Fixes: c3ef1500ec8338 ("TOMOYO: Split files into some pieces.")
Signed-off-by: Jiakai Xu <xujiakai24@mails.ucas.ac.cn>
---
 security/tomoyo/util.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index 6799b1122c9d8..cdc085390949c 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -1024,6 +1024,8 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r,
 	memset(r, 0, sizeof(*r));
 	if (!domain)
 		domain = tomoyo_domain();
+	if (!domain)
+		return TOMOYO_CONFIG_DISABLED;
 	r->domain = domain;
 	profile = domain->profile;
 	r->profile = profile;
-- 
2.34.1

Found by fuzzing. Here is the report:

Unable to handle kernel paging request at virtual address dfffffff00000003
Current syz-executor pgtable: 4K pagesize, 57-bit VAs, pgdp=0x000000012edec000
[dfffffff00000003] pgd=000000005fffe401, p4d=000000005fffe001, pud=0000000000000000
Oops [#1]
Modules linked in:
CPU: 0 UID: 0 PID: 3126 Comm: syz-executor Tainted: G        W           7.1.0-rc1-gdb909bd7986c #1 PREEMPT 
Tainted: [W]=WARN
Hardware name: riscv-virtio,qemu (DT)
epc : tomoyo_check_acl+0x90/0x4bc security/tomoyo/domain.c:173
 ra : tomoyo_check_acl+0x86/0x4bc security/tomoyo/domain.c:173
epc : ffffffff8149cf64 ra : ffffffff8149cf5a sp : ff200000040c7a90
 gp : ffffffff8a395420 tp : ff60000089d05040 t0 : ff200000040c7960
 t1 : 000000000000000f t2 : ffffffff86c068b0 s0 : ff200000040c7b10
 s1 : 0000000000000000 a0 : 0000000000000018 a1 : 0000000000000000
 a2 : 0000000000000002 a3 : ffffffff8149cf5a a4 : 0000000000000000
 a5 : dfffffff00000003 a6 : 0000000000000003 a7 : 000000003dfe34af
 s2 : dfffffff00000000 s3 : ff200000040c7b80 s4 : ff600000872a1510
 s5 : ffe3ffff00818f79 s6 : 0000000000000000 s7 : ffffffff814a2e18
 s8 : ff600000872a1500 s9 : ff200000040c7bc8 s10: 0000000000000002
 s11: 0000000000000000 t3 : 6a92f41f00000000 t4 : 0000000000001fff
 t5 : 00000000000000c8 t6 : 0000000000000002 ssp : 0000000000000000
status: 0000000200000120 badaddr: dfffffff00000003 cause: 000000000000000d
[<ffffffff8149cf64>] tomoyo_check_acl+0x90/0x4bc security/tomoyo/domain.c:173
[<ffffffff814a4108>] tomoyo_path_number_perm+0x384/0x5a4 security/tomoyo/file.c:738
[<ffffffff814b0cc4>] tomoyo_file_ioctl+0x28/0x34 security/tomoyo/tomoyo.c:350
[<ffffffff81454e8c>] security_file_ioctl+0xaa/0x2c2 security/security.c:2512
[<ffffffff80d45c5e>] __do_sys_ioctl fs/ioctl.c:591 [inline]
[<ffffffff80d45c5e>] __se_sys_ioctl fs/ioctl.c:583 [inline]
[<ffffffff80d45c5e>] __riscv_sys_ioctl+0xae/0x1e4 fs/ioctl.c:583
[<ffffffff80078fb2>] syscall_handler+0x94/0x118 arch/riscv/include/asm/syscall.h:112
[<ffffffff866fa9ea>] do_trap_ecall_u+0x43e/0x5de arch/riscv/kernel/traps.c:342
[<ffffffff867267f6>] handle_exception+0x15e/0x16a arch/riscv/kernel/entry.S:232
Code: 2544 1097 ff0a 80e7 e9c0 8513 0184 5793 0035 97ca (8703) 0007 
---[ end trace 0000000000000000 ]---
----------------
Code disassembly (best guess):
   0:	2544                	fld	fs1,136(a0)
   2:	ff0a1097          	auipc	ra,0xff0a1
   6:	e9c080e7          	jalr	-356(ra) # 0xffffffffff0a0e9e
   a:	01848513          	addi	a0,s1,24
   e:	00355793          	srli	a5,a0,0x3
  12:	97ca                	add	a5,a5,s2
* 14:	00078703          	lb	a4,0(a5) <-- trapping instruction

<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>


^ permalink raw reply related

* [PATCH] apparmor: fix use-after-free in rawdata dedup loop
From: Ruslan Valiyev @ 2026-05-25 22:04 UTC (permalink / raw)
  To: John Johansen
  Cc: Paul Moore, James Morris, Serge E . Hallyn, Georgia Garcia,
	Cengiz Can, Colin Ian King, apparmor, linux-security-module,
	linux-kernel, stable

aa_replace_profiles() walks ns->rawdata_list to dedup the incoming
policy blob against entries already attached to existing profiles.
Per the kernel-doc on struct aa_loaddata, list membership does not
hold a reference: profiles hold pcount, and when the last pcount
drops, do_ploaddata_rmfs() is queued on a workqueue that takes
ns->lock and removes the entry. Between dropping the last pcount
and the workqueue running, an entry remains on the list with
pcount == 0.

aa_get_profile_loaddata() is an unconditional kref_get() on
pcount, so when the dedup loop hits such an entry, refcount
hardening reports

  refcount_t: addition on 0; use-after-free.

inside aa_replace_profiles(), and the poisoned counter then
trips "saturated" and "underflow" warnings on the subsequent
uses of the same loaddata.

Before commit a0b7091c4de4 ("apparmor: fix race on rawdata
dereference") the dedup path used a get_unless_zero-style helper
on a single counter, so the existing "if (tmp)" guard was
meaningful. The split-refcount refactor introduced
aa_get_profile_loaddata(), which has plain kref_get() semantics,
and the guard quietly became a no-op.

Introduce aa_get_profile_loaddata_not0(), matching the existing
_not0 convention used by aa_get_profile_not0(), and use it for
the rawdata_list dedup lookup so dying entries are skipped.

Reproduced on x86_64 with v7.1-rc5 in QEMU+KVM running Ubuntu
24.04 + stress-ng 0.17.06:

  stress-ng --apparmor 1 --klog-check --timeout 60s

Without this patch the three refcount_t warnings fire within a
few seconds. With it the same 60 s run is clean. Coverage is a
smoke-test only; a longer soak with CONFIG_KASAN, CONFIG_KCSAN
and CONFIG_PROVE_LOCKING would be welcome from anyone with the
cycles.

Fixes: a0b7091c4de4 ("apparmor: fix race on rawdata dereference")
Reported-by: Colin Ian King <colin.i.king@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221513
Cc: stable@vger.kernel.org
Signed-off-by: Ruslan Valiyev <linuxoid@gmail.com>
---
 security/apparmor/include/policy_unpack.h | 19 +++++++++++++++++++
 security/apparmor/policy.c                |  8 ++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
index e5a95dc4da1f..b9de0fdf9ee5 100644
--- a/security/apparmor/include/policy_unpack.h
+++ b/security/apparmor/include/policy_unpack.h
@@ -163,6 +163,25 @@ aa_get_profile_loaddata(struct aa_loaddata *data)
 	return data;
 }
 
+/**
+ * aa_get_profile_loaddata_not0 - get a profile reference count if not zero
+ * @data: reference to get a count on
+ *
+ * Like aa_get_profile_loaddata(), but safe to call on an entry that may
+ * be on a list (e.g. ns->rawdata_list) where the last pcount has already
+ * dropped and the deferred cleanup has not yet run.
+ *
+ * Returns: pointer to reference, or %NULL if @data is NULL or its
+ *          profile refcount has already reached zero.
+ */
+static inline struct aa_loaddata *
+aa_get_profile_loaddata_not0(struct aa_loaddata *data)
+{
+	if (data && kref_get_unless_zero(&data->pcount))
+		return data;
+	return NULL;
+}
+
 void __aa_loaddata_update(struct aa_loaddata *data, long revision);
 bool aa_rawdata_eq(struct aa_loaddata *l, struct aa_loaddata *r);
 void aa_loaddata_kref(struct kref *kref);
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index b6a5eb4021db..e103cce6f4af 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -1223,8 +1223,12 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label,
 			if (aa_rawdata_eq(rawdata_ent, udata)) {
 				struct aa_loaddata *tmp;
 
-				tmp = aa_get_profile_loaddata(rawdata_ent);
-				/* check we didn't fail the race */
+				/*
+				 * Entries remain on rawdata_list with
+				 * pcount == 0 until do_ploaddata_rmfs()
+				 * runs; only take a live profile ref.
+				 */
+				tmp = aa_get_profile_loaddata_not0(rawdata_ent);
 				if (tmp) {
 					aa_put_profile_loaddata(udata);
 					udata = tmp;

base-commit: e7ae89a0c97ce2b68b0983cd01eda67cf373517d
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v4 0/7] landlock: Add UDP access control support
From: Mickaël Salaün @ 2026-05-25 20:28 UTC (permalink / raw)
  To: Matthieu Buffet
  Cc: Günther Noack, linux-security-module, Mikhail Ivanov,
	konstantin.meskhidze, Tingmao Wang, netdev
In-Reply-To: <20260502124306.3975990-1-matthieu@buffet.re>

FYI, I pushed this patch series in -next (except the doc patch which
conflict).

Also, some interesting (and some other not relevant) findings here:
https://sashiko.dev/#/patchset/20260502124306.3975990-1-matthieu%40buffet.re

On Sat, May 02, 2026 at 02:42:59PM +0200, Matthieu Buffet wrote:
> Hi,
> 
> This is V4 of UDP access control in Landlock. Thanks to the round of
> review of v3, access rights have changed to something that seems easier
> to use and understand. It adds only two access rights, to restrict
> configuring local and remote addresses on UDP sockets. The one that
> restricts setting a remote address also controls sending datagrams to
> explicit remote addresses -ignoring any remote address preset on the
> socket-. The one that restricts binding to a local port also applies
> when the kernel auto-binds an ephemeral port.
> v1:
> Link: https://lore.kernel.org/all/20240916122230.114800-1-matthieu@buffet.re/
> v2:
> Link: https://lore.kernel.org/all/20241214184540.3835222-1-matthieu@buffet.re/
> v3:
> Link: https://lore.kernel.org/all/20251212163704.142301-1-matthieu@buffet.re/
> 
> The limitation around allowing a process to send but not receive is
> still there, and could warrant another patch if there is a real user
> need.
> I'm just not super happy about the clarity of logs generated for denied
> autobinds ("domain=xxxxxx blockers=net.bind_udp"), due to the fact that
> addresses and ports are currently only logged if they are non-0. A later
> (coordinated LSM-wide) patch could improve readability by replacing != 0
> checks with new booleans in struct lsm_network_audit. I'm also not
> exactly happy with the integration in existing TCP selftests, but
> refactoring them has already been discussed earlier.
> 
> Changes v1->v2
> ==============
> - recvmsg hook is gone and sendmsg hook doesn't apply when sending to a
>   remote address pre-set on socket, to improve performance
> - don't add a get_addr_port() helper function, which required a weird
>   "am I in IPv4 or IPv6 context"
> - reorder hook prologue for consistency: check domain, then type and
>   family
> 
> Changes v2->v3
> ==============
> - removed support for sending datagrams with explicit destination
>   address of family AF_UNSPEC, which allowed to bypass restrictions with
>   a race condition
> - rebased on linux-mic/next => add support for auditing
> - fixed mistake in selftests when using unspec_srv variables, which were
>   implicitly of type SOCK_STREAM and did not actually test UDP code
> - add tests for IPPROTO_IP
> - improved docs, split off TCP-related refactoring
> 
> Changes v3->v4
> ==============
> - merge LANDLOCK_ACCESS_NET_CONNECT_UDP and
>   LANDLOCK_ACCESS_NET_SENDTO_UDP into
>   LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP (everything that might set the
>   destination of a datagram)
> - make LANDLOCK_ACCESS_NET_BIND_UDP apply when kernel is about to
>   auto-bind an ephemeral port for the caller. Block it if policy would
>   not allow an explicit call to bind(0)
> - only deny sending AF_UNSPEC datagrams on IPv6 sockets, where there is
>   a risk of the address family changing midway
> 
> Patch is based on https://git.kernel.org/pub/scm/linux/kernel/git/mic/linux.git
> 3457a5ccacd3 ("landlock: Document fallocate(2) as another truncation corner case")
> All lines added are covered with selftests, except the "default: return
> 0" in current_check_autobind_udp_socket() which is not currently
> reachable (net.c goes from 92.9%->94.6% line coverage).
> 
> Let me know what you think!
> 
> Closes: https://github.com/landlock-lsm/linux/issues/10
> 
> Matthieu Buffet (7):
>   landlock: Add UDP bind() access control
>   landlock: Add UDP connect() access control
>   landlock: Add UDP send access control
>   selftests/landlock: Add UDP bind/connect tests
>   selftests/landlock: Add tests for sendmsg()
>   samples/landlock: Add sandboxer UDP access control
>   landlock: Add documentation for UDP support
> 
>  Documentation/userspace-api/landlock.rst     |   89 +-
>  include/uapi/linux/landlock.h                |   35 +-
>  samples/landlock/sandboxer.c                 |   40 +-
>  security/landlock/audit.c                    |    3 +
>  security/landlock/limits.h                   |    2 +-
>  security/landlock/net.c                      |  161 ++-
>  security/landlock/syscalls.c                 |    2 +-
>  tools/testing/selftests/landlock/base_test.c |    4 +-
>  tools/testing/selftests/landlock/net_test.c  | 1146 ++++++++++++++++--
>  9 files changed, 1341 insertions(+), 141 deletions(-)
> 
> 
> base-commit: 3457a5ccacd34fdd5ebd3a4745e721b5a1239690
> -- 
> 2.39.5
> 
> 

^ permalink raw reply

* Re: [PATCH v8 3/9] landlock: Suppress logging when quiet flag is present
From: Mickaël Salaün @ 2026-05-25 20:40 UTC (permalink / raw)
  To: Tingmao Wang
  Cc: Günther Noack, Justin Suess, Jan Kara, Abhinav Saxena,
	linux-security-module
In-Reply-To: <5a253279ddbc797fa320849e46f7c88d7578a581.1775490344.git.m@maowtm.org>

On Mon, Apr 06, 2026 at 04:52:16PM +0100, Tingmao Wang wrote:
> The quietness behaviour is as documented in the previous patch.
> 
> For optional accesses, since the existing deny_masks can only store 2x4bit
> of layer index, with no way to represent "no layer", we need to either
> expand it or have another field to correctly handle quieting of those.
> This commit uses the latter approach - we add another field to store which
> optional access (of the 2) are covered by quiet rules in their respective
> layers as stored in deny_masks.
> 
> We can avoid making struct landlock_file_security larger by converting the
> existing fown_layer to a 4bit field.  This commit does that, and adds test
> to ensure that it is large enough for LANDLOCK_MAX_NUM_LAYERS-1.
> 
> Signed-off-by: Tingmao Wang <m@maowtm.org>
> ---
> 
> Changes in v8:
> - Rebase on top of mic/next
> - Populate request.rule_flags in hook_unix_find()
> 
> Changes in v7:
> - Following change in commit 1, now we need to copy rule_flags into
>   landlock_request before calling landlock_log_denial for relevant fs
>   denials
> - Remove left over param comment
> 
> Changes in v5:
> - Update code style and comment in get_layer_from_deny_masks() and
>   landlock_log_denial()
> - Now that rule_flags is moved into landlock_request, this version removes
>   the extra parameter for landlock_log_denial and gets rid of
>   no_rule_flags, simplifying some code.
> - Fix build failure without CONFIG_AUDIT (reported by Justin Suess)
> 
> Changes in v3:
> - Renamed patch title from "Check for quiet flag in landlock_log_denial"
>   to this given the growth.
> - Moved quiet bit check after domain_exec check
> - Rename, style and comment fixes suggested by Mickaël.
> - Squashed patch 6/6 from v2 "Implement quiet for optional accesses" into
>   this one.  Changes to that below:
> - Refactor the quiet flag setting in get_layer_from_deny_masks() to be
>   more clear.
> - Add KUnit tests
> - Fix comments, add WARN_ON_ONCE, use __const_hweight64() as suggested by
>   review
> - Move build_check_file_security to fs.c
> - Use a typedef for quiet_optional_accesses, add static_assert, and
>   improve docs on landlock_get_quiet_optional_accesses.
> 
> Changes in v2:
> - Supports the new quiet access masks.
> - Support quieting scope requests (but not ptrace and attempted mounting
>   for now)
> 
>  security/landlock/access.h |   5 +
>  security/landlock/audit.c  | 255 +++++++++++++++++++++++++++++++++++--
>  security/landlock/audit.h  |   3 +
>  security/landlock/domain.c |  33 +++++
>  security/landlock/domain.h |   5 +
>  security/landlock/fs.c     |  35 +++++
>  security/landlock/fs.h     |  17 ++-
>  security/landlock/net.c    |  16 +--
>  8 files changed, 340 insertions(+), 29 deletions(-)
> 
> diff --git a/security/landlock/access.h b/security/landlock/access.h
> index c19d5bc13944..2775df80c7da 100644
> --- a/security/landlock/access.h
> +++ b/security/landlock/access.h
> @@ -120,4 +120,9 @@ static inline bool access_mask_subset(access_mask_t subset,
>  	return (subset | superset) == superset;
>  }
>  
> +/* A bitmask that is large enough to hold set of optional accesses. */
> +typedef u8 optional_access_t;
> +static_assert(BITS_PER_TYPE(optional_access_t) >=
> +	      HWEIGHT(_LANDLOCK_ACCESS_FS_OPTIONAL));
> +
>  #endif /* _SECURITY_LANDLOCK_ACCESS_H */
> diff --git a/security/landlock/audit.c b/security/landlock/audit.c
> index 8d0edf94037d..2941b6d88688 100644
> --- a/security/landlock/audit.c
> +++ b/security/landlock/audit.c
> @@ -246,7 +246,8 @@ static void test_get_denied_layer(struct kunit *const test)
>  static size_t
>  get_layer_from_deny_masks(access_mask_t *const access_request,
>  			  const access_mask_t all_existing_optional_access,
> -			  const deny_masks_t deny_masks)
> +			  const deny_masks_t deny_masks,
> +			  u8 quiet_optional_accesses, bool *quiet)

optional_access_t quiet_optional_accesses

This type should be used everywhere.

>  {
>  	const unsigned long access_opt = all_existing_optional_access;
>  	const unsigned long access_req = *access_request;
> @@ -254,6 +255,7 @@ get_layer_from_deny_masks(access_mask_t *const access_request,
>  	size_t youngest_layer = 0;
>  	size_t access_index = 0;
>  	unsigned long access_bit;
> +	bool should_quiet = false;
>  
>  	/* This will require change with new object types. */
>  	WARN_ON_ONCE(access_opt != _LANDLOCK_ACCESS_FS_OPTIONAL);
> @@ -264,18 +266,29 @@ get_layer_from_deny_masks(access_mask_t *const access_request,
>  			const size_t layer =
>  				(deny_masks >> (access_index * 4)) &
>  				(LANDLOCK_MAX_NUM_LAYERS - 1);
> +			const bool layer_has_quiet =
> +				!!(quiet_optional_accesses & BIT(access_index));
>  
>  			if (layer > youngest_layer) {
>  				youngest_layer = layer;
>  				missing = BIT(access_bit);
> +				should_quiet = layer_has_quiet;
>  			} else if (layer == youngest_layer) {
>  				missing |= BIT(access_bit);
> +				/*
> +				 * Whether the layer has rules with quiet flag covering
> +				 * the file accessed does not depend on the access, and so
> +				 * the following WARN_ON_ONCE() should not fail.
> +				 */
> +				WARN_ON_ONCE(should_quiet && !layer_has_quiet);
> +				should_quiet = layer_has_quiet;
>  			}
>  		}
>  		access_index++;
>  	}
>  
>  	*access_request = missing;
> +	*quiet = should_quiet;
>  	return youngest_layer;
>  }
>  
> @@ -285,42 +298,188 @@ static void test_get_layer_from_deny_masks(struct kunit *const test)
>  {
>  	deny_masks_t deny_mask;
>  	access_mask_t access;
> +	u8 quiet_optional_accesses;

ditto

> diff --git a/security/landlock/audit.h b/security/landlock/audit.h
> index 56778331b58c..c2da854d4405 100644
> --- a/security/landlock/audit.h
> +++ b/security/landlock/audit.h
> @@ -48,6 +48,9 @@ struct landlock_request {
>  	/* Required fields for requests with deny masks. */
>  	const access_mask_t all_existing_optional_access;
>  	deny_masks_t deny_masks;
> +	u8 quiet_optional_accesses;

ditto, use optional_access_t

> +
> +	struct collected_rule_flags rule_flags;
>  };
>  
>  #ifdef CONFIG_AUDIT
> diff --git a/security/landlock/domain.c b/security/landlock/domain.c
> index 06b6bd845060..f365721050b7 100644
> --- a/security/landlock/domain.c
> +++ b/security/landlock/domain.c
> @@ -156,6 +156,39 @@ get_layer_deny_mask(const access_mask_t all_existing_optional_access,
>  	       << ((access_weight - 1) * HWEIGHT(LANDLOCK_MAX_NUM_LAYERS - 1));
>  }
>  
> +/**
> + * landlock_get_quiet_optional_accesses - Get optional accesses which are
> + * "covered" by quiet rule flags.
> + *
> + * Returns a bitmask of which optional access are denied by layers for
> + * which rule_flags.quiet_masks has the corresponding bit set.
> + */
> +optional_access_t landlock_get_quiet_optional_accesses(
> +	const access_mask_t all_existing_optional_access,
> +	const deny_masks_t deny_masks,
> +	const struct collected_rule_flags rule_flags)
> +{
> +	const unsigned long access_opt = all_existing_optional_access;
> +	size_t access_index = 0;
> +	unsigned long access_bit;
> +	optional_access_t quiet_optional_accesses = 0;

It's only correct here.

> +
> +	/* This will require change with new object types. */
> +	WARN_ON_ONCE(access_opt != _LANDLOCK_ACCESS_FS_OPTIONAL);
> +
> +	for_each_set_bit(access_bit, &access_opt,
> +			 BITS_PER_TYPE(access_mask_t)) {
> +		const u8 layer = (deny_masks >> (access_index * 4)) &
> +				 (LANDLOCK_MAX_NUM_LAYERS - 1);
> +		const bool is_quiet = !!(rule_flags.quiet_masks & BIT(layer));
> +
> +		if (is_quiet)
> +			quiet_optional_accesses |= BIT(access_index);
> +		access_index++;
> +	}
> +	return quiet_optional_accesses;
> +}
> +
>  #ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST
>  
>  static void test_get_layer_deny_mask(struct kunit *const test)

^ permalink raw reply

* Re: [PATCH v8 1/9] landlock: Add a place for flags to layer rules
From: Mickaël Salaün @ 2026-05-25 20:39 UTC (permalink / raw)
  To: Justin Suess
  Cc: Tingmao Wang, Günther Noack, Jan Kara, Abhinav Saxena,
	linux-security-module
In-Reply-To: <ahNx8CNCeqhU_Ide@zenbox>

On Sun, May 24, 2026 at 06:08:00PM -0400, Justin Suess wrote:
> On Sun, May 24, 2026 at 07:20:19PM +0100, Tingmao Wang wrote:
> > On 5/24/26 15:46, Justin Suess wrote:
> > > On Sun, May 24, 2026 at 02:29:40AM +0100, Tingmao Wang wrote:
> > >> On 5/23/26 21:48, Mickaël Salaün wrote:
> > >>> [...]
> > >>>> @@ -647,9 +648,14 @@ bool landlock_unmask_layers(const struct landlock_rule *const rule,
> > >>>>  	 */
> > >>>>  	for (size_t i = 0; i < rule->num_layers; i++) {
> > >>>>  		const struct landlock_layer *const layer = &rule->layers[i];
> > >>>> +		const layer_mask_t layer_bit = BIT_ULL(layer->level - 1);
> > >>>>  
> > >>>
> > >>>>  		/* Clear the bits where the layer in the rule grants access. */
> > >>>>  		masks->access[layer->level - 1] &= ~layer->access;
> > >>>> +
> > >>>> +		/* Collect rule flags for each layer. */
> > >>>> +		if (rule_flags && layer->flags.quiet)
> > >>>> +			rule_flags->quiet_masks |= layer_bit;
> > >>>
> > >>> Why not store the quiet bit in masks?  That would not only be "access"
> > >>> bits anymore but it makes sense to store all this bits it the same
> > >>> place.
> > >>>
> > >>> We should then probably rename struct layer_access_masks to just struct
> > >>> layer_masks.
> > >>>
> > >>> We need to be careful to not increase too much the size of this struct
> > >>> though while keeping the [LANDLOCK_MAX_NUM_LAYERS] approach if possible
> > >>> (see Günther's commit that added it).
> > >>
> > >> Most uses of struct layer_access_masks do not actually care about the rule
> > >> flags tho, e.g. in unmask_scoped_access, scope_to_request, or may_refer.
> > >> Such a rename would touch 31 places (and only a few of them would actually
> > >> touch the quiet flag).
> > >>
> > >> If we want to refactor to make this be in the layer_access_masks (then
> > >> rename it), I guess there are 3 options, which do you prefer?
> > >>
> > >> 1. Add a u16 bitfield for which layers are quieted.  Future rule flags
> > >>    will be additional bitfields.  struct layer_masks becomes 68 bytes (+4).
> > >>
> > >> struct layer_masks {
> > >> 	access_mask_t access[LANDLOCK_MAX_NUM_LAYERS];
> > >> 	layer_mask_t quiet_layers;
> > >> };
> > >>
> > >> 2. Make the [LANDLOCK_MAX_NUM_LAYERS] array store both the access mask and
> > >>    the quiet bit (or more bits for future rule flags).  Size of struct stays
> > >>    the same.
> > >>
> > > This approach seems best.
> > >> static_assert(LANDLOCK_NUM_ACCESS_NET <= LANDLOCK_NUM_ACCESS_FS);
> > >> static_assert(LANDLOCK_NUM_SCOPE <= LANDLOCK_NUM_ACCESS_FS);
> > >> struct layer_mask {
> > >> 	access_mask_t access:LANDLOCK_NUM_ACCESS_FS;
> > >> 	bool quiet:1;
> > >> };
> > > 
> > > Other way to do it could be an (anonymous?) union.
> > > 
> > > union {
> > >   access_mask_t fs_access:LANDLOCK_NUM_ACCESS_FS;
> > >   access_mask_t net_access:LANDLOCK_NUM_ACCESS_NET;
> > >   access_mask_t scope_access:LANDLOCK_NUM_SCOPE;
> > > }
> > > 
> > > The union should be sized to fit the largest field automatically.
> > > 
> > > That way you don't have to change this when adding new access rights
> > > and avoid the brittle static_asserts.
> > > 
> > > Not sure about the alignment implications here though.
> > 
> > Unfortunately this forces struct layer_mask to be 2x as large:
> > https://godbolt.org/z/5P9b4rrMW
> > 
> Yeah I guess the compiler can't pack the fields with differing types.
> 
> *In theory* you could make everything a _BitInt or something but it
> seems better to do what you had below.
> > But it turns out I could have just used MAX, seems to compile for me:
> > 
> > struct layer_mask {
> > 	access_mask_t access
> > 		: MAX(LANDLOCK_NUM_ACCESS_FS,
> > 		      MAX(LANDLOCK_NUM_ACCESS_NET, LANDLOCK_NUM_SCOPE));
> > 	bool quiet : 1;
> > };
> This works perfectly.
> 
> Mickaël's suggestion (except w/ all three access right classes like
> you have here, think he missed LANDLOCK_NUM_SCOPE) is very close
> to this.
> > struct layer_masks {
> > 	struct layer_mask layer[LANDLOCK_MAX_NUM_LAYERS];
> > };
> > 
> > Maybe we could #define LANDLOCK_NUM_ACCESS_MAX to be MAX(...) then use it
> > here.

LANDLOCK_NUM_ACCESS_MAX looks like a better name (even if it also
include scopes).

> > 
> > I'm still not sure if putting the collected rule flags in struct
> > layer_(access_)masks is a good idea tho.  Passing a separate struct
> > collected_rule_flags to the functions that needs to deal with rule flags
> > (quiet, and later, no inherit / has no inherit descendant) seems quite
> > practical to me.
> 
> (Not sure how stingy we gotta be with stack space)
> 
> There's a *slight* stack space advantage to keeping them together.
> 
> If you pass by value, (separate layer_access_masks, collected_rule_flags),
> those structs must be individually padded and aligned. Which may or may not
> make a difference, it's dependent on alignment and architecture.
> 
> Whereas if we keep them all together, we only pad once.
> 
> If you pass by pointer, you have to allocate stack space for each
> pointer, so passing it all at once saves sizeof(collected_rule_flags*)
> bytes in the pass by pointer case.
> 
> Either way it's probably a couple bytes at worst, so probably nothing to
> worry about.
> 
> The more compelling argument is that we don't know how future paths
> will use rule flags, so keeping it all together reduces churn later
> if a function ends up needing to access flags. Moreover, it makes those
> messy function signatures in fs.h/c a little less hairy, and easy to
> refactor later.

Agreed

^ permalink raw reply

* Re: [net-next] netlabel: fix IPv6 unlabeled address add error handling
From: patchwork-bot+netdevbpf @ 2026-05-25 19:10 UTC (permalink / raw)
  To: Chenguang Zhao
  Cc: paul, davem, edumazet, kuba, pabeni, horms, netdev,
	linux-security-module
In-Reply-To: <20260522022910.398416-1-zhaochenguang@kylinos.cn>

Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Fri, 22 May 2026 10:29:10 +0800 you wrote:
> netlbl_unlhsh_add_addr6() always returned zero after
> netlbl_af6list_add(), masking failures such as duplicate
> IPv6 static label entries.
> 
> Signed-off-by: Chenguang Zhao <zhaochenguang@kylinos.cn>
> ---
>  net/netlabel/netlabel_unlabeled.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Here is the summary with links:
  - [net-next] netlabel: fix IPv6 unlabeled address add error handling
    https://git.kernel.org/netdev/net-next/c/56872b930fee

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] tpm-buf: memory-safe allocations
From: James Bottomley @ 2026-05-25 17:50 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-integrity
  Cc: Jarkko Sakkinen, Arun Menon, Daniel P. Smith, Alec Brown,
	Ross Philipson, Stefan Berger, Peter Huewe, Jason Gunthorpe,
	Mimi Zohar, David Howells, Paul Moore, James Morris,
	Serge E. Hallyn, linux-kernel, keyrings, linux-security-module
In-Reply-To: <20260522013555.1063716-1-jarkko@kernel.org>

On Fri, 2026-05-22 at 04:35 +0300, Jarkko Sakkinen wrote:
> Decouple kzalloc from buffer creation, so that a managed allocation
> can be
> used:
> 
> 	struct tpm_buf *buf __free(kfree) buf = kzalloc(TPM_BUFSIZE,
> 						GFP_KERNEL);
> 	if (!buf)
> 		return -ENOMEM;
> 
> 	tpm_buf_init(buf, TPM_BUFSIZE);
> 
> Alternatively, stack allocations are also possible:
> 
> 	u8 buf_data[512];
> 	struct tpm_buf *buf = (struct tpm_buf *)buf_data;
> 	tpm_buf_init(buf, sizeof(buf_data));

This isn't really a good idea from a security point of view.  Remember
the buffer has to be big enough for both the sent and the received
data.  Today we simply set TPM_BUFSIZE to the maximum amount a TPM
requires and all the send and receives just work.  If we let callers
set this size, we're asking for them to get it wrong (or at least
forget about the receive part) and for us to get a DMA overrun from the
TPM ... which might be potentially exploitable depending on how it
occurs (think of an unseal of user chosen data overrunning).

I get the desire to support some of the newer chunked commands, but
since none of them is yet present in the kernel, why not introduce an
API that works only for them to avoid the risk of a security cockup in
existing code?

Regards,

James


^ permalink raw reply

* Re: [PATCH 08/11] params: Convert generic kernel_param_ops .get helpers to seq_buf
From: Petr Pavlu @ 2026-05-25 17:10 UTC (permalink / raw)
  To: Kees Cook
  Cc: Luis Chamberlain, Pengpeng Hou, Richard Weinberger, Anton Ivanov,
	Johannes Berg, Rafael J. Wysocki, Len Brown, Corey Minyard,
	Gabriel Somlo, Michael S. Tsirkin, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Tvrtko Ursulin, David Airlie, Simona Vetter,
	Bart Van Assche, Jason Gunthorpe, Leon Romanovsky,
	Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
	Bjorn Helgaas, Hannes Reinecke, James E.J. Bottomley,
	Martin K. Petersen, Daniel Lezcano, Zhang Rui, Lukasz Luba,
	Greg Kroah-Hartman, Jiri Slaby, Alan Stern, Jason Wang, Xuan Zhuo,
	Eugenio Pérez, Jason Baron, Jim Cromie, Tiwei Bie,
	Benjamin Berg, Ilpo Järvinen, David E. Box,
	Maciej W. Rozycki, Srinivas Pandruvada, Peter Zijlstra,
	Heiko Carstens, Vasily Gorbik, Sean Christopherson, Paolo Bonzini,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Vinod Koul, Frank Li, Daniel Gomez, Sami Tolvanen,
	Aaron Tomlin, Alexander Potapenko, Marco Elver, Dmitry Vyukov,
	Andrew Morton, John Johansen, Paul Moore, James Morris,
	Serge E. Hallyn, Andy Shevchenko, Georgia Garcia, kvm, dmaengine,
	linux-modules, kasan-dev, linux-mm, apparmor,
	linux-security-module, linux-um, linux-acpi, openipmi-developer,
	qemu-devel, intel-gfx, dri-devel, linux-rdma, linux-media,
	linux-pci, linux-scsi, linux-pm, linuxppc-dev, linux-serial,
	linux-usb, usb-storage, virtualization, linux-kernel, linux-arch,
	netdev, linux-fsdevel, linux-hardening
In-Reply-To: <20260521133326.2465264-8-kees@kernel.org>

On 5/21/26 3:33 PM, Kees Cook wrote:
> Convert the generic struct kernel_param_ops .get helpers in
> kernel/params.c directly to the seq_buf signature, drop their legacy
> "char *" form, and refresh prototypes in <linux/moduleparam.h>:
> 
>   param_get_byte/short/ushort/int/uint/long/ulong/ullong/hexint
>   param_get_charp/bool/invbool/string
>   param_array_get
> 
> The STANDARD_PARAM_DEF() macro expands to a seq_buf body for every
> numeric helper. param_array_get() now writes element output directly
> into the parent seq_buf when the element ops provide .get; it only
> allocates the per-call PAGE_SIZE bounce buffer when the element ops
> still use the legacy .get_str path. The common "rewrite the prior
> element's trailing newline as a comma" step lives outside both
> branches so the two paths share it.
> 
> The non-core changes in this commit (arch/x86/kvm, mm/kfence,
> drivers/dma/dmatest, security/apparmor) are the small set of callers that
> directly invoke one of the converted generic helpers from their own .get
> callback (e.g. an apparmor wrapper that adds a capability check and then
> delegates to param_get_bool()). Because the helpers' signature changes
> here, these wrappers must move in lockstep. Each of them is updated
> to take "struct seq_buf *" and pass it through; param_get_debug() in
> apparmor also pulls aa_print_debug_params() (and its val_mask_to_str()
> helper, in security/apparmor/lib.c) over to seq_buf, since that is the
> only consumer. No other behavioural change is intended.
> 
> Custom .get callbacks that do not delegate to a generic helper (and
> therefore still match the .get_str signature) are routed automatically
> to the .get_str field by the DEFINE_KERNEL_PARAM_OPS _Generic dispatcher
> and are deliberately left alone here, to be changed separately within
> their respective subsystems.
> 
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
> [...]
> @@ -453,36 +457,46 @@ static int param_array_set(const char *val, const struct kernel_param *kp)
>  			   arr->num ?: &temp_num);
>  }
>  
> -static int param_array_get(char *buffer, const struct kernel_param *kp)
> +static int param_array_get(struct seq_buf *s, const struct kernel_param *kp)
>  {
> -	int i, off, ret;
> -	char *elem_buf;
>  	const struct kparam_array *arr = kp->arr;
>  	struct kernel_param p = *kp;
> +	char *elem_buf = NULL;
> +	int i, ret = 0;
>  
> -	elem_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
> -	if (!elem_buf)
> -		return -ENOMEM;
> +	for (i = 0; i < (arr->num ? *arr->num : arr->max); i++) {
> +		size_t before = s->len;
>  
> -	for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
>  		p.arg = arr->elem + arr->elemsize * i;
>  		check_kparam_locked(p.mod);
> -		ret = arr->ops->get_str(elem_buf, &p);
> -		if (ret < 0)
> -			goto out;
> -		ret = min(ret, (int)(PAGE_SIZE - 1 - off));
> -		if (!ret)
> +
> +		if (arr->ops->get) {
> +			ret = arr->ops->get(s, &p);
> +			if (ret < 0)
> +				goto out;
> +		} else {
> +			if (!elem_buf) {
> +				elem_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
> +				if (!elem_buf) {
> +					ret = -ENOMEM;
> +					goto out;
> +				}
> +			}
> +			ret = arr->ops->get_str(elem_buf, &p);
> +			if (ret < 0)
> +				goto out;
> +			seq_buf_putmem(s, elem_buf, ret);
> +		}
> +
> +		/* Nothing got written (e.g. overflow) — stop. */
> +		if (s->len == before)
>  			break;
> +
>  		/* Replace the previous element's trailing newline with a comma. */
> -		if (i)
> -			buffer[off - 1] = ',';
> -		memcpy(buffer + off, elem_buf, ret);
> -		off += ret;
> -		if (off == PAGE_SIZE - 1)
> -			break;
> +		if (i && s->buffer[before - 1] == '\n')
> +			s->buffer[before - 1] = ',';
>  	}
> -	buffer[off] = '\0';
> -	ret = off;
> +	ret = 0;
>  out:
>  	kfree(elem_buf);
>  	return ret;

Since you're almost completely rewriting the logic in param_array_get(),
I suggest tightening it up a bit. The function could warn or return an
error when a kernel_param_ops::get/get_str() call adds a string that
doesn't terminate with '\n', specifically, when the call adds either
a zero-length string or a non-zero-length string that ends with
a different character (unless an overflow occurred).

The updated code silently stops the loop when a get call returns
a zero-length string. Similarly, handling of a string not terminated by
'\n' is halfway there because of the added check
"s->buffer[before - 1] == '\n'".

-- 
Thanks,
Petr

^ permalink raw reply

* Re: [PATCH] Fix various spelling mistakes
From: Casey Schaufler @ 2026-05-25 16:06 UTC (permalink / raw)
  To: fffsqian, john.johansen
  Cc: paul, jmorris, serge, linux-security-module, linux-kernel,
	Qingshuang Fu, Casey Schaufler
In-Reply-To: <20260525021500.47667-1-fffsqian@163.com>

On 5/24/2026 7:15 PM, fffsqian@163.com wrote:
> From: Qingshuang Fu <fuqingshuang@kylinos.cn>
>
> Fix three spelling errors found in code comments:
>
> - overriden  →  overridden
> - interated  →  interacted
> - dont      →  don't
>
> Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>

The AppArmor and Smack changes go in through different trees.
You should split this into two patches and submit them to the
appropriate maintainers.

> ---
>  security/apparmor/domain.c | 2 +-
>  security/apparmor/lsm.c    | 2 +-
>  security/smack/smackfs.c   | 2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
> index f02bf770f638..7e097c40720a 100644
> --- a/security/apparmor/domain.c
> +++ b/security/apparmor/domain.c
> @@ -135,7 +135,7 @@ static int label_compound_match(struct aa_profile *profile,
>  	struct label_it i;
>  	struct path_cond cond = { };
>  
> -	/* find first subcomponent that is in view and going to be interated with */
> +	/* find first subcomponent that is in view and going to be interacted with */
>  	label_for_each(i, label, tp) {
>  		if (!aa_ns_visible(profile->ns, tp->ns, inview))
>  			continue;
> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index 3491e9f60194..51a388cfea11 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -1493,7 +1493,7 @@ static int apparmor_socket_shutdown(struct socket *sock, int how)
>   *
>   * Note: can not sleep may be called with locks held
>   *
> - * dont want protocol specific in __skb_recv_datagram()
> + * don't want protocol specific in __skb_recv_datagram()
>   * to deny an incoming connection  socket_sock_rcv_skb()
>   */
>  static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
> diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
> index 6e62dcb36f74..2820bd3ee72e 100644
> --- a/security/smack/smackfs.c
> +++ b/security/smack/smackfs.c
> @@ -115,7 +115,7 @@ struct smack_known *smack_syslog_label;
>  /*
>   * Ptrace current rule
>   * SMACK_PTRACE_DEFAULT    regular smack ptrace rules (/proc based)
> - * SMACK_PTRACE_EXACT      labels must match, but can be overriden with
> + * SMACK_PTRACE_EXACT      labels must match, but can be overridden with
>   *			   CAP_SYS_PTRACE
>   * SMACK_PTRACE_DRACONIAN  labels must match, CAP_SYS_PTRACE has no effect
>   */
>
> base-commit: e7ae89a0c97ce2b68b0983cd01eda67cf373517d

^ 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