• Xu Yu's avatar
    bpf: do not restore dst_reg when cur_state is freed · 0803278b
    Xu Yu authored
    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: 979d63d5 ("bpf: prevent out of bounds speculation on pointer arithmetic")
    Signed-off-by: default avatarXu Yu <xuyu@linux.alibaba.com>
    Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    0803278b
verifier.c 228 KB