lkml.org 
[lkml]   [2019]   [Apr]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 87/92] bpf: do not restore dst_reg when cur_state is freed
    Date
    From: Xu Yu <xuyu@linux.alibaba.com>

    commit 0803278b0b4d8eeb2b461fb698785df65a725d9e upstream.

    Syzkaller hit 'KASAN: use-after-free Write in sanitize_ptr_alu' bug.

    Call trace:

    dump_stack+0xbf/0x12e
    print_address_description+0x6a/0x280
    kasan_report+0x237/0x360
    sanitize_ptr_alu+0x85a/0x8d0
    adjust_ptr_min_max_vals+0x8f2/0x1ca0
    adjust_reg_min_max_vals+0x8ed/0x22e0
    do_check+0x1ca6/0x5d00
    bpf_check+0x9ca/0x2570
    bpf_prog_load+0xc91/0x1030
    __se_sys_bpf+0x61e/0x1f00
    do_syscall_64+0xc8/0x550
    entry_SYSCALL_64_after_hwframe+0x49/0xbe

    Fault injection trace:

     kfree+0xea/0x290
     free_func_state+0x4a/0x60
     free_verifier_state+0x61/0xe0
     push_stack+0x216/0x2f0 <- inject failslab
     sanitize_ptr_alu+0x2b1/0x8d0
     adjust_ptr_min_max_vals+0x8f2/0x1ca0
     adjust_reg_min_max_vals+0x8ed/0x22e0
     do_check+0x1ca6/0x5d00
     bpf_check+0x9ca/0x2570
     bpf_prog_load+0xc91/0x1030
     __se_sys_bpf+0x61e/0x1f00
     do_syscall_64+0xc8/0x550
     entry_SYSCALL_64_after_hwframe+0x49/0xbe

    When kzalloc() fails in push_stack(), free_verifier_state() will free
    current verifier state. As push_stack() returns, dst_reg was restored
    if ptr_is_dst_reg is false. However, as member of the cur_state,
    dst_reg is also freed, and error occurs when dereferencing dst_reg.
    Simply fix it by testing ret of push_stack() before restoring dst_reg.

    Fixes: 979d63d50c0c ("bpf: prevent out of bounds speculation on pointer arithmetic")
    Signed-off-by: Xu Yu <xuyu@linux.alibaba.com>
    Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    kernel/bpf/verifier.c | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)

    --- a/kernel/bpf/verifier.c
    +++ b/kernel/bpf/verifier.c
    @@ -2118,7 +2118,7 @@ do_sim:
    *dst_reg = *ptr_reg;
    }
    ret = push_stack(env, env->insn_idx + 1, env->insn_idx, true);
    - if (!ptr_is_dst_reg)
    + if (!ptr_is_dst_reg && ret)
    *dst_reg = tmp;
    return !ret ? -EFAULT : 0;
    }

    \
     
     \ /
      Last update: 2019-04-18 20:24    [W:4.264 / U:0.072 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site