mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
Merge branch 'bpf-follow-ups-for-the-arena-mmap-fixes'
Alexei Starovoitov says: ==================== bpf: Follow-ups for the arena mmap() fixes From: Alexei Starovoitov <ast@kernel.org> Two follow-ups for the arena patches of the series "bpf: Fixes for the verifier, arena, skb and lwt helpers", merge commit714b711201. They answer review comments on that series. Commitca580b0343("bpf: Refuse to map an arena at address 0") tests for address 0 in front of round_up(), and round_up() can wrap to 0. Patch 1 does not move a MAP_FIXED address at all. Patch 2 makes arena_mmap serial, as the other arena tests are, and adds subtests for patch 1. Signed-off-by: Alexei Starovoitov <ast@kernel.org> ==================== Link: https://patch.msgid.link/20261102064231.2153879-1-alexei.starovoitov@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
03b0138974
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/irq_work.h>
|
||||
#include "linux/filter.h"
|
||||
#include <linux/llist.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/btf_ids.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
|
@ -630,7 +631,7 @@ static unsigned long arena_get_unmapped_area(struct file *filp, unsigned long ad
|
|||
{
|
||||
struct bpf_map *map = filp->private_data;
|
||||
struct bpf_arena *arena = container_of(map, struct bpf_arena, map);
|
||||
long ret;
|
||||
unsigned long ret;
|
||||
|
||||
if (pgoff)
|
||||
return -EINVAL;
|
||||
|
|
@ -647,7 +648,13 @@ static unsigned long arena_get_unmapped_area(struct file *filp, unsigned long ad
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mm_get_unmapped_area(filp, addr, len * 2, 0, flags);
|
||||
/*
|
||||
* Without MAP_FIXED the mm finds a free range. Ask for twice the
|
||||
* length, so that there is room for round_up(). With MAP_FIXED the mm
|
||||
* does no search, and the caller wants this address. Thus the range
|
||||
* cannot move.
|
||||
*/
|
||||
ret = mm_get_unmapped_area(filp, addr, flags & MAP_FIXED ? len : len * 2, 0, flags);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
if (!ret)
|
||||
|
|
@ -655,6 +662,8 @@ static unsigned long arena_get_unmapped_area(struct file *filp, unsigned long ad
|
|||
return -EINVAL;
|
||||
if ((ret >> 32) == ((ret + len - 1) >> 32))
|
||||
return ret;
|
||||
if (flags & MAP_FIXED)
|
||||
return -EINVAL;
|
||||
return round_up(ret, SZ_4G);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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