[PATCH v3 3/5] selftests/landlock: Drain stale audit records on init

Günther Noack gnoack3000 at gmail.com
Thu Apr 2 20:28:35 UTC 2026


On Thu, Apr 02, 2026 at 09:26:04PM +0200, Mickaël Salaün wrote:
> Non-audit Landlock tests generate audit records as side effects when
> audit_enabled is non-zero (e.g. from boot configuration).  These records
> accumulate in the kernel audit backlog while no audit daemon socket is
> open.  When the next test opens a new netlink socket and registers as
> the audit daemon, the stale backlog is delivered, causing baseline
> record count checks to fail spuriously.
> 
> Fix this by draining all pending records in audit_init() right after
> setting the receive timeout.  The 1-usec SO_RCVTIMEO causes audit_recv()
> to return -EAGAIN once the backlog is empty, naturally terminating the
> drain loop.
> 
> Domain deallocation records are emitted asynchronously from a work
> queue, so they may still arrive after the drain.  Remove records.domain
> == 0 checks that are not preceded by audit_match_record() calls, which
> would otherwise consume stale records before the count.  Document this
> constraint above audit_count_records().
> 
> Increasing the drain timeout to catch in-flight deallocation records was
> considered but rejected: a longer timeout adds latency to every
> audit_init() call even when no stale record is pending, and any fixed
> timeout is still not guaranteed to catch all records under load.
> Removing the unprotected checks is simpler and avoids the spurious
> failures.
> 
> Cc: Günther Noack <gnoack at google.com>
> Cc: stable at vger.kernel.org
> Fixes: 6a500b22971c ("selftests/landlock: Add tests for audit flags and domain IDs")
> Signed-off-by: Mickaël Salaün <mic at digikod.net>
> ---
> 
> Changes since v1:
> https://lore.kernel.org/r/20260312100444.2609563-8-mic@digikod.net
> - Also remove domain checks from audit.trace and
>   scoped_audit.connect_to_child.
> - Document records.domain == 0 constraint above
>   audit_count_records().
> - Explain why a longer drain timeout was rejected.
> - Drop Reviewed-by (new code comment not in v1).
> - Split snprintf and fd leak fixes into separate patches.
> ---
>  tools/testing/selftests/landlock/audit.h      | 19 +++++++++++++++++++
>  tools/testing/selftests/landlock/audit_test.c |  2 --
>  .../testing/selftests/landlock/ptrace_test.c  |  1 -
>  .../landlock/scoped_abstract_unix_test.c      |  1 -
>  4 files changed, 19 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/testing/selftests/landlock/audit.h b/tools/testing/selftests/landlock/audit.h
> index 6422943fc69e..74e1c3d763be 100644
> --- a/tools/testing/selftests/landlock/audit.h
> +++ b/tools/testing/selftests/landlock/audit.h
> @@ -338,6 +338,15 @@ struct audit_records {
>  	size_t domain;
>  };
>  
> +/*
> + * WARNING: Do not assert records.domain == 0 without a preceding
> + * audit_match_record() call.  Domain deallocation records are emitted
> + * asynchronously from kworker threads and can arrive after the drain in
> + * audit_init(), corrupting the domain count.  A preceding audit_match_record()
> + * call consumes stale records while scanning, making the assertion safe in
> + * practice because stale deallocation records arrive before the expected access
> + * records.
> + */
>  static int audit_count_records(int audit_fd, struct audit_records *records)
>  {
>  	struct audit_message msg;
> @@ -393,6 +402,16 @@ static int audit_init(void)
>  		goto err_close;
>  	}
>  
> +	/*
> +	 * Drains stale audit records that accumulated in the kernel backlog
> +	 * while no audit daemon socket was open.  This happens when non-audit
> +	 * Landlock tests generate records while audit_enabled is non-zero (e.g.
> +	 * from boot configuration), or when domain deallocation records arrive
> +	 * asynchronously after a previous test's socket was closed.
> +	 */
> +	while (audit_recv(fd, NULL) == 0)
> +		;
> +
>  	return fd;
>  
>  err_close:
> diff --git a/tools/testing/selftests/landlock/audit_test.c b/tools/testing/selftests/landlock/audit_test.c
> index 46d02d49835a..f92ba6774faa 100644
> --- a/tools/testing/selftests/landlock/audit_test.c
> +++ b/tools/testing/selftests/landlock/audit_test.c
> @@ -412,7 +412,6 @@ TEST_F(audit_flags, signal)
>  		} else {
>  			EXPECT_EQ(1, records.access);
>  		}
> -		EXPECT_EQ(0, records.domain);
>  
>  		/* Updates filter rules to match the drop record. */
>  		set_cap(_metadata, CAP_AUDIT_CONTROL);
> @@ -601,7 +600,6 @@ TEST_F(audit_exec, signal_and_open)
>  	/* Tests that there was no denial until now. */
>  	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
>  	EXPECT_EQ(0, records.access);
> -	EXPECT_EQ(0, records.domain);
>  
>  	/*
>  	 * Wait for the child to do a first denied action by layer1 and
> diff --git a/tools/testing/selftests/landlock/ptrace_test.c b/tools/testing/selftests/landlock/ptrace_test.c
> index 4f64c90583cd..1b6c8b53bf33 100644
> --- a/tools/testing/selftests/landlock/ptrace_test.c
> +++ b/tools/testing/selftests/landlock/ptrace_test.c
> @@ -342,7 +342,6 @@ TEST_F(audit, trace)
>  	/* Makes sure there is no superfluous logged records. */
>  	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
>  	EXPECT_EQ(0, records.access);
> -	EXPECT_EQ(0, records.domain);
>  
>  	yama_ptrace_scope = get_yama_ptrace_scope();
>  	ASSERT_LE(0, yama_ptrace_scope);
> diff --git a/tools/testing/selftests/landlock/scoped_abstract_unix_test.c b/tools/testing/selftests/landlock/scoped_abstract_unix_test.c
> index 72f97648d4a7..c47491d2d1c1 100644
> --- a/tools/testing/selftests/landlock/scoped_abstract_unix_test.c
> +++ b/tools/testing/selftests/landlock/scoped_abstract_unix_test.c
> @@ -312,7 +312,6 @@ TEST_F(scoped_audit, connect_to_child)
>  	/* Makes sure there is no superfluous logged records. */
>  	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
>  	EXPECT_EQ(0, records.access);
> -	EXPECT_EQ(0, records.domain);
>  
>  	ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
>  	ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
> -- 
> 2.53.0
> 

Reviewed-by: Günther Noack <gnoack3000 at gmail.com>



More information about the Linux-security-module-archive mailing list