2023-11-27 14:28:40

by Hao Sun

[permalink] [raw]
Subject: [Bug Report] bpf: zero access_size of stack causes array indix oob in check_stack_range_initialized()

Hi,

The following program (reduced) can cause array OOB during verifying time.

What happening is that we pass a stack pointer
fp(smin=smin32=-7,smax=smax32=248), and a size reg whose min value
could be zero, to a helper. In check_mem_size_reg(), we have:

if (reg->umin_value == 0) {
err = check_helper_mem_access(env, regno - 1, 0,
zero_size_allowed,
meta);
if (err)
return err;
}

The stack pointer with smax=248 should be rejected, but it's not
because in check_stack_access_within_bound():

if (access_size > 0)
max_off = reg->smax_value + off + access_size - 1;
else
max_off = min_off;

The max_off is set to min_off because access_size is zero. In
check_stack_range_initialized(), the slot could be -1 when `i` is 0:
for (i = min_off; i < max_off + access_size; i++) {
u8 *stype;

slot = -i - 1;
spi = slot / BPF_REG_SIZE;

Andrei, sorry to email you again, but this is introduced in
`01f810ace9ed3`. Should we handle zero access_size correctly in
check_stack_access_within_bound()?

Here are the reduced program, the verifier log after removing the
guilty instruction, and the kernel config I used:

C repro: https://pastebin.com/raw/Dx653LrQ
Verifier log: https://pastebin.com/raw/q19gaMdr
Build config: https://pastebin.com/raw/41uDYmYr

================================================================================
UBSAN: array-index-out-of-bounds in kernel/bpf/verifier.c:7051:39
index -1 is out of range for type 'u8 [8]'
CPU: 0 PID: 8339 Comm: poc Not tainted 6.7.0-rc2-g727d3a2bd1b6 #34
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0x8e/0xb0 lib/dump_stack.c:106
ubsan_epilogue lib/ubsan.c:217 [inline]
__ubsan_handle_out_of_bounds+0xa0/0xe0 lib/ubsan.c:348
check_stack_range_initialized+0xb06/0x1080 kernel/bpf/verifier.c:7051
check_helper_mem_access+0x139/0x960 kernel/bpf/verifier.c:7156
check_mem_size_reg+0x11d/0x1e0 kernel/bpf/verifier.c:7230
check_func_arg kernel/bpf/verifier.c:8633 [inline]
check_helper_call.isra.0+0xfc9/0x8530 kernel/bpf/verifier.c:9972
do_check kernel/bpf/verifier.c:17356 [inline]
do_check_common+0x4991/0xddb0 kernel/bpf/verifier.c:19899
do_check_main kernel/bpf/verifier.c:19990 [inline]
bpf_check+0x3f02/0xa6a0 kernel/bpf/verifier.c:20627
bpf_prog_load+0x110e/0x1b20 kernel/bpf/syscall.c:2717
__sys_bpf+0xfc8/0x4400 kernel/bpf/syscall.c:5384
__do_sys_bpf kernel/bpf/syscall.c:5488 [inline]
__se_sys_bpf kernel/bpf/syscall.c:5486 [inline]
__x64_sys_bpf+0x73/0xb0 kernel/bpf/syscall.c:5486
do_syscall_x64 arch/x86/entry/common.c:51 [inline]
do_syscall_64+0x3f/0x110 arch/x86/entry/common.c:82
entry_SYSCALL_64_after_hwframe+0x63/0x6b


2023-11-28 02:37:24

by Andrei Matei

[permalink] [raw]