• C
    binder: fix UAF caused by faulty buffer cleanup · 4877859f
    Carlos Llamas 提交于
    stable inclusion
    from stable-v5.10.182
    commit 2218752325a98861dfb10f59a9b0270d6d4abe21
    category: bugfix
    bugzilla: https://gitee.com/src-openeuler/kernel/issues/I7L0Z9
    CVE: CVE-2023-21255
    
    Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=2218752325a98861dfb10f59a9b0270d6d4abe21
    
    --------------------------------
    
    commit bdc1c5fa upstream.
    
    In binder_transaction_buffer_release() the 'failed_at' offset indicates
    the number of objects to clean up. However, this function was changed by
    commit 44d8047f ("binder: use standard functions to allocate fds"),
    to release all the objects in the buffer when 'failed_at' is zero.
    
    This introduced an issue when a transaction buffer is released without
    any objects having been processed so far. In this case, 'failed_at' is
    indeed zero yet it is misinterpreted as releasing the entire buffer.
    
    This leads to use-after-free errors where nodes are incorrectly freed
    and subsequently accessed. Such is the case in the following KASAN
    report:
    
      ==================================================================
      BUG: KASAN: slab-use-after-free in binder_thread_read+0xc40/0x1f30
      Read of size 8 at addr ffff4faf037cfc58 by task poc/474
    
      CPU: 6 PID: 474 Comm: poc Not tainted 6.3.0-12570-g7df047b3 #5
      Hardware name: linux,dummy-virt (DT)
      Call trace:
       dump_backtrace+0x94/0xec
       show_stack+0x18/0x24
       dump_stack_lvl+0x48/0x60
       print_report+0xf8/0x5b8
       kasan_report+0xb8/0xfc
       __asan_load8+0x9c/0xb8
       binder_thread_read+0xc40/0x1f30
       binder_ioctl+0xd9c/0x1768
       __arm64_sys_ioctl+0xd4/0x118
       invoke_syscall+0x60/0x188
      [...]
    
      Allocated by task 474:
       kasan_save_stack+0x3c/0x64
       kasan_set_track+0x2c/0x40
       kasan_save_alloc_info+0x24/0x34
       __kasan_kmalloc+0xb8/0xbc
       kmalloc_trace+0x48/0x5c
       binder_new_node+0x3c/0x3a4
       binder_transaction+0x2b58/0x36f0
       binder_thread_write+0x8e0/0x1b78
       binder_ioctl+0x14a0/0x1768
       __arm64_sys_ioctl+0xd4/0x118
       invoke_syscall+0x60/0x188
      [...]
    
      Freed by task 475:
       kasan_save_stack+0x3c/0x64
       kasan_set_track+0x2c/0x40
       kasan_save_free_info+0x38/0x5c
       __kasan_slab_free+0xe8/0x154
       __kmem_cache_free+0x128/0x2bc
       kfree+0x58/0x70
       binder_dec_node_tmpref+0x178/0x1fc
       binder_transaction_buffer_release+0x430/0x628
       binder_transaction+0x1954/0x36f0
       binder_thread_write+0x8e0/0x1b78
       binder_ioctl+0x14a0/0x1768
       __arm64_sys_ioctl+0xd4/0x118
       invoke_syscall+0x60/0x188
      [...]
      ==================================================================
    
    In order to avoid these issues, let's always calculate the intended
    'failed_at' offset beforehand. This is renamed and wrapped in a helper
    function to make it clear and convenient.
    
    Fixes: 32e9f56a ("binder: don't detect sender/target during buffer cleanup")
    Reported-by: NZi Fan Tan <zifantan@google.com>
    Cc: stable@vger.kernel.org
    Signed-off-by: NCarlos Llamas <cmllamas@google.com>
    Acked-by: NTodd Kjos <tkjos@google.com>
    Link: https://lore.kernel.org/r/20230505203020.4101154-1-cmllamas@google.com
    [cmllamas: resolve trivial conflict due to missing commit 9864bb48]
    Signed-off-by: NCarlos Llamas <cmllamas@google.com>
    Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: NWang Hai <wanghai38@huawei.com>
    Signed-off-by: NLonglong Xia <xialonglong1@huawei.com>
    (cherry picked from commit 83bfcd1e)
    4877859f
binder.c 187.9 KB