UAF bug caused by rose_t0timer_expiry

Bug #1991142 reported by Cengiz Can
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
linux (Ubuntu)
In Progress
Low
Cengiz Can
Xenial
In Progress
Low
Cengiz Can
Bionic
In Progress
Low
Cengiz Can
Focal
In Progress
Low
Cengiz Can
Jammy
In Progress
Low
Cengiz Can
Kinetic
In Progress
Low
Cengiz Can

Bug Description

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

Revision history for this message
Cengiz Can (cengizcan) wrote :

This fix landed on upstream with 148ca04518070910739dfc4eeda765057856403d

Changed in linux (Ubuntu Xenial):
importance: Undecided → High
Changed in linux (Ubuntu Bionic):
importance: Undecided → High
Changed in linux (Ubuntu Focal):
importance: Undecided → High
Changed in linux (Ubuntu Jammy):
importance: Undecided → High
Changed in linux (Ubuntu Kinetic):
importance: Undecided → High
Changed in linux (Ubuntu Xenial):
status: New → In Progress
Changed in linux (Ubuntu Bionic):
status: New → In Progress
Changed in linux (Ubuntu Focal):
status: New → In Progress
Changed in linux (Ubuntu Jammy):
status: New → In Progress
Changed in linux (Ubuntu Kinetic):
status: New → In Progress
Changed in linux (Ubuntu Xenial):
assignee: nobody → Cengiz Can (cengizcan)
Changed in linux (Ubuntu Bionic):
assignee: nobody → Cengiz Can (cengizcan)
Changed in linux (Ubuntu Focal):
assignee: nobody → Cengiz Can (cengizcan)
Changed in linux (Ubuntu Jammy):
assignee: nobody → Cengiz Can (cengizcan)
Changed in linux (Ubuntu Kinetic):
assignee: nobody → Cengiz Can (cengizcan)
Changed in linux (Ubuntu Kinetic):
importance: High → Low
Changed in linux (Ubuntu Jammy):
importance: High → Low
Changed in linux (Ubuntu Focal):
importance: High → Low
Changed in linux (Ubuntu Bionic):
importance: High → Low
Changed in linux (Ubuntu Xenial):
importance: High → Low
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.