mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
selftests/bpf: Run arena_mmap serially and test MAP_FIXED addresses
Each arena reserves 4 GiB of vmalloc space. The KASAN shadow of arenas from parallel tests can exhaust the memory of a CI VM. Thus commita14f9ba080("selftests/bpf: Run arena tests serially") made arena_* and libarena* serial. Do the same for arena_mmap, which the commit below added later. Add four subtests for "bpf: Don't move a MAP_FIXED address in arena_get_unmapped_area()". Test that mmap() with MAP_FIXED or MAP_FIXED_NOREPLACE fails with EINVAL if the range crosses a 4 GiB boundary. Test that mmap() with MAP_FIXED also fails for a range that wraps and for a map_extra range that ends above TASK_SIZE. Today arena_map_alloc() accepts such a map_extra. map_extra_last_pages also passes if the kernel refuses the map, because no task can map this range. The arch code gets a range before the arena code tests it for a crossing. For the last two ranges LoongArch returns -EINVAL, and powerpc with the hash MMU returns -ENOMEM. There the two subtests do not reach that test. On the other architectures with arenas, the arena code returns -EINVAL or __get_unmapped_area() returns -ENOMEM. Thus the two subtests accept both errnos. All these errors occur before mmap() changes a mapping. Two other changes of that patch have no subtest. With MAP_FIXED the arch code gets len and not 2 * len. A 64-bit task on x86, arm64 or riscv does not see this. LoongArch, s390 and powerpc with the hash MMU compare the end of the range with different limits. In arena_mmap the unsigned ret changes only the errno of map_extra_last_pages, which accepts both. Fixes:14d3e5bf9f("selftests/bpf: Test the length and the address of an arena mmap()") Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261102064231.2153879-3-alexei.starovoitov@gmail.com
This commit is contained in:
parent
92b5ce3ca5
commit
c08b50dd17
|
|
@ -5,9 +5,12 @@
|
|||
|
||||
#define ARENA_PAGES 8
|
||||
|
||||
static void test_refused(int pages, int flags, int err)
|
||||
/* err == 0: the range ends above TASK_SIZE. EINVAL or ENOMEM, this depends on the arch */
|
||||
static void test_refused(__u64 map_extra, __u64 addr, int pages, int flags, int err)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_MMAPABLE);
|
||||
LIBBPF_OPTS(bpf_map_create_opts, opts,
|
||||
.map_flags = BPF_F_MMAPABLE,
|
||||
.map_extra = map_extra);
|
||||
void *area;
|
||||
int fd;
|
||||
|
||||
|
|
@ -16,22 +19,35 @@ static void test_refused(int pages, int flags, int err)
|
|||
test__skip();
|
||||
return;
|
||||
}
|
||||
/* No task can map this range, so the kernel can also refuse the map. */
|
||||
if (fd < 0 && map_extra)
|
||||
return;
|
||||
if (!ASSERT_GE(fd, 0, "bpf_map_create"))
|
||||
return;
|
||||
|
||||
area = mmap(NULL, pages * getpagesize(), PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | flags, fd, 0);
|
||||
if (ASSERT_EQ(area, MAP_FAILED, "mmap"))
|
||||
ASSERT_EQ(errno, err, "errno");
|
||||
else
|
||||
area = mmap((void *)(unsigned long)addr, pages * getpagesize(),
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED | flags, fd, 0);
|
||||
if (!ASSERT_EQ(area, MAP_FAILED, "mmap"))
|
||||
munmap(area, pages * getpagesize());
|
||||
else if (err || errno != ENOMEM)
|
||||
ASSERT_EQ(errno, err ?: EINVAL, "errno");
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void test_arena_mmap(void)
|
||||
void serial_test_arena_mmap(void)
|
||||
{
|
||||
__u64 page = getpagesize(), last = -(ARENA_PAGES * page);
|
||||
|
||||
if (test__start_subtest("long"))
|
||||
test_refused(ARENA_PAGES + 1, 0, E2BIG);
|
||||
test_refused(0, 0, ARENA_PAGES + 1, 0, E2BIG);
|
||||
if (test__start_subtest("address_0"))
|
||||
test_refused(ARENA_PAGES, MAP_FIXED, EINVAL);
|
||||
test_refused(0, 0, ARENA_PAGES, MAP_FIXED, EINVAL);
|
||||
if (test__start_subtest("crosses_4g"))
|
||||
test_refused(0, (1ULL << 32) - page, ARENA_PAGES, MAP_FIXED, EINVAL);
|
||||
if (test__start_subtest("crosses_4g_noreplace"))
|
||||
test_refused(0, (1ULL << 32) - page, ARENA_PAGES, MAP_FIXED_NOREPLACE, EINVAL);
|
||||
if (test__start_subtest("wraps"))
|
||||
test_refused(0, -page, ARENA_PAGES, MAP_FIXED, 0);
|
||||
if (test__start_subtest("map_extra_last_pages"))
|
||||
test_refused(last, last, ARENA_PAGES, MAP_FIXED, 0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user