All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
Cc: linux-security-module@vger.kernel.org
Subject: Re: [PATCH 5/6] selftests/landlock: Test capability checks outside the capable hook
Date: Tue, 10 Nov 2026 20:54:14 +0000	[thread overview]
Message-ID: <sashiko-outbox-207736@kernel.org> (raw)
In-Reply-To: <20261110202436.2408244-6-mic@digikod.net>

Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Medium] selftests/landlock: unaccounted swap space in
  set_admin_reserve()
- [Low] selftests/landlock: commit message omits CAP_SETPCAP in
  _init_caps()
- [Low] selftests/landlock: MAP_FIXED at NULL fails arch_mmap_check() on
  32-bit ARM
It also noticed 1 related pre-existing issue this patch does not
introduce:
- [Medium] selftests/landlock: null pointer dereference in _change_cap()
  [1]
--

commit 1b0a2ef8af3441bc1c12e3659de9a61de2c9490f
Author: Mickaël Salaün <mic@digikod.net>

selftests/landlock: Test capability checks outside the capable hook

This commit adds selftests covering Landlock capability restrictions and
auditing for commoncap checks performed in the mmap_addr, capset, and
vm_enough_memory LSM hooks.

> diff --git a/tools/testing/selftests/landlock/cap_test.c b/tools/testing/selftests/landlock/cap_test.c
> index 3d7fd02e21ed9..c79bb42c6282b 100644
> --- a/tools/testing/selftests/landlock/cap_test.c
> +++ b/tools/testing/selftests/landlock/cap_test.c
[ ... ]
> +TEST_F(cap_other_hooks, mmap_min_addr)
> +{
> +	const size_t page_size = sysconf(_SC_PAGESIZE);
> +	void *addr;
> +
> +	if (read_sysctl(_metadata, "/proc/sys/vm/mmap_min_addr") == 0)
> +		SKIP(return, "vm.mmap_min_addr is 0");
> +
> +	enforce_cap_variant(_metadata, variant, CAP_SYS_RAWIO);
> +
> +	addr = mmap(NULL, page_size, PROT_READ,
> +		    MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
> +	EXPECT_EQ(MAP_FAILED, addr);
> +	EXPECT_EQ(EPERM, errno);
> +
> +	set_cap(_metadata, CAP_SYS_RAWIO);
> +	addr = mmap(NULL, page_size, PROT_READ,
> +		    MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);

[Severity: Low]
Does mapping at NULL with MAP_FIXED fail with EINVAL on 32-bit ARM before
reaching security_mmap_addr()?

In mm/mmap.c:__get_unmapped_area(), arch_mmap_check() runs before
security_mmap_addr().  On 32-bit ARM, FIRST_USER_ADDRESS is 2 * PAGE_SIZE
and arch_mmap_check() rejects MAP_FIXED mappings below FIRST_USER_ADDRESS
with -EINVAL:

arch/arm/include/uapi/asm/mman.h:
#define arch_mmap_check(addr, len, flags) \
	(((flags) & MAP_FIXED && (addr) < FIRST_USER_ADDRESS) ? -EINVAL : 0)

As a result, mmap_min_addr, cap_audit.other_hooks, and
cap_audit.other_hooks_allowed will get EINVAL instead of EPERM or NULL on
32-bit ARM, and cap_audit.other_hooks will not generate the expected
CAP_SYS_RAWIO audit record.

[ ... ]
> +static unsigned long read_committed_kb(struct __test_metadata *const _metadata)
> +{
> +	unsigned long committed = 0;
> +	char line[128];
> +	FILE *file;
> +
> +	file = fopen("/proc/meminfo", "re");
> +	ASSERT_NE(NULL, file);
> +
> +	while (fgets(line, sizeof(line), file))
> +		if (sscanf(line, "Committed_AS: %lu kB", &committed) == 1)
> +			break;
> +
> +	EXPECT_EQ(0, fclose(file));
> +	EXPECT_NE(0, committed);
> +	return committed;
> +}
[ ... ]
> +static void set_admin_reserve(struct __test_metadata *const _metadata,
> +			      FIXTURE_DATA(cap_admin_reserve) *const self)
> +{
> +	set_root_euid(_metadata);
> +	self->is_set = true;
> +	ASSERT_EQ(0, write_sysctl(OVERCOMMIT_PATH "admin_reserve_kbytes",
> +				  ADMIN_RESERVE_KB));
> +	ASSERT_EQ(0, write_sysctl(OVERCOMMIT_PATH "overcommit_kbytes",
> +				  self->committed + ADMIN_RESERVE_KB +
> +					  HEADROOM_KB));
> +	ASSERT_EQ(0, write_sysctl(OVERCOMMIT_PATH "overcommit_memory", 2));
> +	restore_euid(_metadata);
> +}
[ ... ]
> +TEST_F(cap_admin_reserve, mmap)
> +{
> +	set_admin_reserve(_metadata, self);
> +
> +	EXPECT_EQ(ENOMEM, test_admin_reserve(variant, false));
> +	EXPECT_EQ(variant->is_allowed ? 0 : ENOMEM,
> +		  test_admin_reserve(variant, true));
> +}

[Severity: Medium]
Does set_admin_reserve() need to account for active swap when computing the
commit limit?

In mm/util.c:vm_commit_limit(), the kernel adds total_swap_pages on top of
sysctl_overcommit_kbytes:

mm/util.c:vm_commit_limit() {
	if (sysctl_overcommit_kbytes)
		allowed = sysctl_overcommit_kbytes >> (PAGE_SHIFT - 10);
	else
		allowed = ((totalram_pages() - hugetlb_total_pages())
			   * sysctl_overcommit_ratio / 100);
	allowed += total_swap_pages;

	return allowed;
}

When SwapTotal is 96 MiB (MAPPING_KB - HEADROOM_KB) or larger, the
unprivileged commit limit (CommitLimit - admin_reserve_kbytes) still has
room for the 160 MiB mapping, so test_admin_reserve() succeeds and returns 0
instead of ENOMEM.

> diff --git a/tools/testing/selftests/landlock/common.h b/tools/testing/selftests/landlock/common.h
> index e29406900c04a..a6fdfb422fad5 100644
> --- a/tools/testing/selftests/landlock/common.h
> +++ b/tools/testing/selftests/landlock/common.h
> @@ -36,7 +36,7 @@ static const char bin_wait_pipe_sandbox[] = "./wait-pipe-sandbox";
>  static void _init_caps(struct __test_metadata *const _metadata, bool drop_all)
>  {
>  	cap_t cap_p;
> -	/* Only these three capabilities are useful for the tests. */
> +	/* Only these capabilities are useful for the tests. */
>  	const cap_value_t caps[] = {
>  		/* clang-format off */
>  		CAP_AUDIT_CONTROL,
> @@ -44,9 +44,11 @@ static void _init_caps(struct __test_metadata *const _metadata, bool drop_all)
>  		CAP_MKNOD,
>  		CAP_NET_ADMIN,
>  		CAP_NET_BIND_SERVICE,
> +		CAP_SETPCAP,
>  		CAP_SETUID,
>  		CAP_SYS_ADMIN,
>  		CAP_SYS_CHROOT,
> +		CAP_SYS_RAWIO,
>  		/* clang-format on */
>  	};
>  	const unsigned int noroot = SECBIT_NOROOT | SECBIT_NOROOT_LOCKED;

[Severity: Low]
This isn't a bug, but the commit message says "Add CAP_SYS_RAWIO to the
capabilities that the tests may raise" while _init_caps() adds both
CAP_SETPCAP and CAP_SYS_RAWIO.

[Severity: Medium]
This problem wasn't introduced by this patch, but _init_caps() and
_change_cap() [1] check the return value of cap_get_proc() with
EXPECT_NE(NULL, cap_p) instead of ASSERT_NE(NULL, cap_p):

tools/testing/selftests/landlock/common.h:_change_cap() {
	cap_t cap_p;

	cap_p = cap_get_proc();
	EXPECT_NE(NULL, cap_p);
	EXPECT_NE(-1, cap_set_flag(cap_p, flag, 1, &cap, value));
	...
}

Because EXPECT_NE() does not abort the test on failure, a NULL return from
cap_get_proc() is passed directly to cap_clear() or cap_set_flag(), causing
a NULL pointer dereference.

[1] https://sashiko.dev/#/bug/linux-78e86289-9899-4c8f-a69a-109bbe06ac40

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261110202436.2408244-1-mic@digikod.net?part=5

  reply	other threads:[~2026-11-10 20:54 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 20:24 [PATCH 0/6] Fix Landlock mediation of commoncap's capability checks Mickaël Salaün
2026-11-10 20:24 ` [PATCH 1/6] landlock: Factor out capability denial checks Mickaël Salaün
2026-11-10 20:28   ` sashiko-bot
2026-11-10 20:24 ` [PATCH 2/6] landlock: Mediate CAP_SYS_RAWIO for mappings below mmap_min_addr Mickaël Salaün
2026-11-10 20:33   ` sashiko-bot
2026-11-10 20:24 ` [PATCH 3/6] landlock: Mediate CAP_SETPCAP for inheritable capabilities Mickaël Salaün
2026-11-10 20:36   ` sashiko-bot
2026-11-10 20:24 ` [PATCH 4/6] landlock: Mediate CAP_SYS_ADMIN for the admin memory reserve Mickaël Salaün
2026-11-10 20:40   ` sashiko-bot
2026-11-10 20:24 ` [PATCH 5/6] selftests/landlock: Test capability checks outside the capable hook Mickaël Salaün
2026-11-10 20:54   ` sashiko-bot [this message]
2026-11-10 20:24 ` [PATCH 6/6] landlock: Fix capability restriction documentation Mickaël Salaün
2026-11-10 20:55   ` sashiko-bot
2026-11-11 18:28 ` [PATCH 0/6] Fix Landlock mediation of commoncap's capability checks Serge Hallyn (AMD)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-207736@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.