• Duoming Zhou's avatar
    net: rose: fix UAF bugs caused by timer handler · 9cc02ede
    Duoming Zhou authored
    There are UAF bugs in rose_heartbeat_expiry(), rose_timer_expiry()
    and rose_idletimer_expiry(). The root cause is that del_timer()
    could not stop the timer handler that is running and the refcount
    of sock is not managed properly.
    
    One of the UAF bugs is shown below:
    
        (thread 1)          |        (thread 2)
                            |  rose_bind
                            |  rose_connect
                            |    rose_start_heartbeat
    rose_release            |    (wait a time)
      case ROSE_STATE_0     |
      rose_destroy_socket   |  rose_heartbeat_expiry
        rose_stop_heartbeat |
        sock_put(sk)        |    ...
      sock_put(sk) // FREE  |
                            |    bh_lock_sock(sk) // USE
    
    The sock is deallocated by sock_put() in rose_release() and
    then used by bh_lock_sock() in rose_heartbeat_expiry().
    
    Although rose_destroy_socket() calls rose_stop_heartbeat(),
    it could not stop the timer that is running.
    
    The KASAN report triggered by POC is shown below:
    
    BUG: KASAN: use-after-free in _raw_spin_lock+0x5a/0x110
    Write of size 4 at addr ffff88800ae59098 by task swapper/3/0
    ...
    Call Trace:
     <IRQ>
     dump_stack_lvl+0xbf/0xee
     print_address_description+0x7b/0x440
     print_report+0x101/0x230
     ? irq_work_single+0xbb/0x140
     ? _raw_spin_lock+0x5a/0x110
     kasan_report+0xed/0x120
     ? _raw_spin_lock+0x5a/0x110
     kasan_check_range+0x2bd/0x2e0
     _raw_spin_lock+0x5a/0x110
     rose_heartbeat_expiry+0x39/0x370
     ? rose_start_heartbeat+0xb0/0xb0
     call_timer_fn+0x2d/0x1c0
     ? rose_start_heartbeat+0xb0/0xb0
     expire_timers+0x1f3/0x320
     __run_timers+0x3ff/0x4d0
     run_timer_softirq+0x41/0x80
     __do_softirq+0x233/0x544
     irq_exit_rcu+0x41/0xa0
     sysvec_apic_timer_interrupt+0x8c/0xb0
     </IRQ>
     <TASK>
     asm_sysvec_apic_timer_interrupt+0x1b/0x20
    RIP: 0010:default_idle+0xb/0x10
    RSP: 0018:ffffc9000012fea0 EFLAGS: 00000202
    RAX: 000000000000bcae RBX: ffff888006660f00 RCX: 000000000000bcae
    RDX: 0000000000000001 RSI: ffffffff843a11c0 RDI: ffffffff843a1180
    RBP: dffffc0000000000 R08: dffffc0000000000 R09: ffffed100da36d46
    R10: dfffe9100da36d47 R11: ffffffff83cf0950 R12: 0000000000000000
    R13: 1ffff11000ccc1e0 R14: ffffffff8542af28 R15: dffffc0000000000
    ...
    Allocated by task 146:
     __kasan_kmalloc+0xc4/0xf0
     sk_prot_alloc+0xdd/0x1a0
     sk_alloc+0x2d/0x4e0
     rose_create+0x7b/0x330
     __sock_create+0x2dd/0x640
     __sys_socket+0xc7/0x270
     __x64_sys_socket+0x71/0x80
     do_syscall_64+0x43/0x90
     entry_SYSCALL_64_after_hwframe+0x46/0xb0
    
    Freed by task 152:
     kasan_set_track+0x4c/0x70
     kasan_set_free_info+0x1f/0x40
     ____kasan_slab_free+0x124/0x190
     kfree+0xd3/0x270
     __sk_destruct+0x314/0x460
     rose_release+0x2fa/0x3b0
     sock_close+0xcb/0x230
     __fput+0x2d9/0x650
     task_work_run+0xd6/0x160
     exit_to_user_mode_loop+0xc7/0xd0
     exit_to_user_mode_prepare+0x4e/0x80
     syscall_exit_to_user_mode+0x20/0x40
     do_syscall_64+0x4f/0x90
     entry_SYSCALL_64_after_hwframe+0x46/0xb0
    
    This patch adds refcount of sock when we use functions
    such as rose_start_heartbeat() and so on to start timer,
    and decreases the refcount of sock when timer is finished
    or deleted by functions such as rose_stop_heartbeat()
    and so on. As a result, the UAF bugs could be mitigated.
    
    Fixes: 1da177e4 ("Linux-2.6.12-rc2")
    Signed-off-by: default avatarDuoming Zhou <duoming@zju.edu.cn>
    Tested-by: default avatarDuoming Zhou <duoming@zju.edu.cn>
    Link: https://lore.kernel.org/r/20220629002640.5693-1-duoming@zju.edu.cnSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
    9cc02ede
rose_timer.c 4.81 KB