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
next prev parent reply other threads:[~2026-11-10 20:54 UTC|newest]
Thread overview: 13+ 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
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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox