mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
Merge branch 'bpf-reject-arena-frees-below-the-arena-base'
Yiyang Chen says: ==================== bpf: Reject arena frees below the arena base bpf_arena_free_pages() can be called with a scalar arena address. The runtime reconstructs a full user address from the arena base and the low 32 bits before returning the range to the arena free tree. A scalar one page below the arena base can otherwise produce an out-of-domain free-tree offset and make a later allocation return an address below the arena mapping. Patch 1 rejects frees whose reconstructed full user address is below user_vm_start. Patch 2 adds verifier_arena coverage for the scalar-below-base case. Changes in v2: - Add Reviewed-by tags from Emil Tsalapatis. - Remove the empty inline asm from the selftest. v1: https://lore.kernel.org/bpf/cover.1782813442.git.chenyy23@mails.tsinghua.edu.cn/ ==================== Link: https://patch.msgid.link/20260717-c10-031-public-bpf-next-v2-b4-v2-0-54b555443a7c@mails.tsinghua.edu.cn Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This commit is contained in:
commit
deabfadbb2
|
|
@ -858,6 +858,8 @@ static void arena_free_pages(struct bpf_arena *arena, long uaddr, long page_cnt,
|
|||
uaddr &= PAGE_MASK;
|
||||
kaddr = bpf_arena_get_kern_vm_start(arena) + uaddr;
|
||||
full_uaddr = clear_lo32(arena->user_vm_start) + uaddr;
|
||||
if (full_uaddr < arena->user_vm_start)
|
||||
return;
|
||||
uaddr_end = min(arena->user_vm_end, full_uaddr + (page_cnt << PAGE_SHIFT));
|
||||
if (full_uaddr >= uaddr_end)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -12,15 +12,17 @@
|
|||
|
||||
#define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8)))
|
||||
|
||||
#ifdef __TARGET_ARCH_arm64
|
||||
#define ARENA_VM_START ((1ull << 32) | (~0u - __PAGE_SIZE * 2 + 1))
|
||||
#else
|
||||
#define ARENA_VM_START ((1ull << 44) | (~0u - __PAGE_SIZE * 2 + 1))
|
||||
#endif
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARENA);
|
||||
__uint(map_flags, BPF_F_MMAPABLE);
|
||||
__uint(max_entries, 2); /* arena of two pages close to 32-bit boundary*/
|
||||
#ifdef __TARGET_ARCH_arm64
|
||||
__ulong(map_extra, (1ull << 32) | (~0u - __PAGE_SIZE * 2 + 1)); /* start of mmap() region */
|
||||
#else
|
||||
__ulong(map_extra, (1ull << 44) | (~0u - __PAGE_SIZE * 2 + 1)); /* start of mmap() region */
|
||||
#endif
|
||||
__ulong(map_extra, ARENA_VM_START); /* start of mmap() region */
|
||||
} arena SEC(".maps");
|
||||
|
||||
SEC("socket")
|
||||
|
|
@ -93,6 +95,34 @@ int basic_alloc1(void *ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
SEC("syscall")
|
||||
__success __retval(0)
|
||||
int free_scalar_below_arena(void *ctx)
|
||||
{
|
||||
void __arena *page1, *page2, *page3;
|
||||
__u64 bad_addr = ARENA_VM_START - __PAGE_SIZE;
|
||||
|
||||
page1 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
|
||||
if (!page1)
|
||||
return 1;
|
||||
|
||||
page2 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
|
||||
if (!page2)
|
||||
return 2;
|
||||
|
||||
page3 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
|
||||
if (page3)
|
||||
return 3;
|
||||
|
||||
bpf_arena_free_pages(&arena, (void __arena *)bad_addr, 1);
|
||||
|
||||
page3 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
|
||||
if (page3)
|
||||
return 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("socket")
|
||||
__success __retval(0)
|
||||
int basic_alloc2_nosleep(void *ctx)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user