lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <CACkBjsZGEUaRCHsmaX=h-efVogsRfK1FPxmkgb0Os_frnHiNdw@mail.gmail.com>
Date:   Mon, 27 Nov 2023 15:07:07 +0100
From:   Hao Sun <sunhao.th@...il.com>
To:     Andrei Matei <andreimatei1@...il.com>,
        Alexei Starovoitov <ast@...nel.org>,
        Daniel Borkmann <daniel@...earbox.net>,
        bpf <bpf@...r.kernel.org>
Cc:     Linux Kernel Mailing List <linux-kernel@...r.kernel.org>
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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ