kvm: use-after-free in kvm_irqfd_release

35 views
Skip to first unread message

Dmitry Vyukov

unread,
Jun 21, 2016, 9:20:13 AM6/21/16
to Paolo Bonzini, mtos...@redhat.com, yoshikawa...@lab.ntt.co.jp, guangro...@linux.intel.com, Steve Rutherford, rkr...@redhat.com, KVM list, LKML, syzkaller, Alexander Potapenko, Kostya Serebryany, Sasha Levin
Hello,

The following program triggers use-after-free in kvm_irqfd_release:

BUG: KASAN: use-after-free in do_raw_spin_lock+0x281/0x2b0 at addr
ffff880060888c64
Read of size 4 by task a.out/7084
page:ffffea0001822200 count:0 mapcount:-127 mapping: (null) index:0x0
flags: 0x4fffe0000000000()
page dumped because: kasan: bad access detected
CPU: 2 PID: 7084 Comm: a.out Tainted: G D 4.7.0-rc4+ #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
ffffffff880b58e0 ffff880060b77b78 ffffffff82cc62cf ffffffff60b77c08
fffffbfff1016b1c ffff880060b77c08 ffff880060888c64 ffff880060888c98
ffff88003ad2d6a8 ffff880060888c60 ffff880060b77bf8 ffffffff817bdfb2
Call Trace:
[<ffffffff817be09e>] __asan_report_load4_noabort+0x3e/0x40
mm/kasan/report.c:318
[< inline >] debug_spin_lock_before kernel/locking/spinlock_debug.c:83
[<ffffffff81484e81>] do_raw_spin_lock+0x281/0x2b0
kernel/locking/spinlock_debug.c:135
[< inline >] __raw_spin_lock_irq include/linux/spinlock_api_smp.h:131
[<ffffffff86a969df>] _raw_spin_lock_irq+0x6f/0x80 kernel/locking/spinlock.c:167
[< inline >] spin_lock_irq include/linux/spinlock.h:332
[<ffffffff81073eff>] kvm_irqfd_release+0x2f/0x120
arch/x86/kvm/../../../virt/kvm/eventfd.c:584
[<ffffffff8105dfca>] kvm_vm_release+0x3a/0x50
arch/x86/kvm/../../../virt/kvm/kvm_main.c:752
[<ffffffff81819ee6>] __fput+0x236/0x780 fs/file_table.c:208
[<ffffffff8181a4b5>] ____fput+0x15/0x20 fs/file_table.c:244
[<ffffffff813d0826>] task_work_run+0xf6/0x170 kernel/task_work.c:115
[< inline >] exit_task_work include/linux/task_work.h:21
[<ffffffff8137aed2>] do_exit+0xa62/0x2c80 kernel/exit.c:748
[< inline >] SYSC_exit kernel/exit.c:847
[<ffffffff8137d152>] SyS_exit+0x22/0x30 kernel/exit.c:845
[<ffffffff86a96fc0>] entry_SYSCALL_64_fastpath+0x23/0xc1
arch/x86/entry/entry_64.S:207
Memory state around the buggy address:
ffff880060888b00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff880060888b80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>ffff880060888c00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff880060888c80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff880060888d00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
==================================================================
BUG: unable to handle kernel paging request at ffff880060888c64
IP: [< inline >] debug_spin_lock_before
kernel/locking/spinlock_debug.c:83
IP: [<ffffffff81484c3e>] do_raw_spin_lock+0x3e/0x2b0
kernel/locking/spinlock_debug.c:135
PGD a3bc067 PUD a3bf067 PMD 7fdfc067 PTE 8000000060888060
Oops: 0000 [#2] SMP DEBUG_PAGEALLOC KASAN
Modules linked in:
CPU: 2 PID: 7084 Comm: a.out Tainted: G B D 4.7.0-rc4+ #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: ffff880060a517c0 ti: ffff880060b70000 task.ti: ffff880060b70000
RIP: 0010:[<ffffffff81484c3e>] [<ffffffff81484c3e>] do_raw_spin_lock+0x3e/0x2b0
RSP: 0018:ffff880060b77c40 EFLAGS: 00010092
RAX: ffff880060a517c0 RBX: ffff880060888c60 RCX: 0000000000000000
RDX: 0000000000000004 RSI: 0000000000000001 RDI: 0000000000000000
RBP: ffff880060b77c68 R08: 0000000000000001 R09: 0000000000000000
R10: ffff880060b77bce R11: 0000000000000000 R12: ffff880063813174
R13: ffff880060888c98 R14: ffff88003ad2d6a8 R15: ffff880060888c60
FS: 00007f34165a4700(0000) GS:ffff88006d400000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffff880060888c64 CR3: 0000000060013000 CR4: 00000000000026e0
Stack:
ffff880060888c60 ffff880063813174 ffff880060888c98 ffff88003ad2d6a8
ffff880060888c60 ffff880060b77c88 ffffffff86a969df ffffffff81073eff
ffff880060888000 ffff880060b77cc8 ffffffff81073eff 00000000000000c0
Call Trace:
[< inline >] __raw_spin_lock_irq include/linux/spinlock_api_smp.h:131
[<ffffffff86a969df>] _raw_spin_lock_irq+0x6f/0x80 kernel/locking/spinlock.c:167
[< inline >] spin_lock_irq include/linux/spinlock.h:332
[<ffffffff81073eff>] kvm_irqfd_release+0x2f/0x120
arch/x86/kvm/../../../virt/kvm/eventfd.c:584
[<ffffffff8105dfca>] kvm_vm_release+0x3a/0x50
arch/x86/kvm/../../../virt/kvm/kvm_main.c:752
[<ffffffff81819ee6>] __fput+0x236/0x780 fs/file_table.c:208
[<ffffffff8181a4b5>] ____fput+0x15/0x20 fs/file_table.c:244
[<ffffffff813d0826>] task_work_run+0xf6/0x170 kernel/task_work.c:115
[< inline >] exit_task_work include/linux/task_work.h:21
[<ffffffff8137aed2>] do_exit+0xa62/0x2c80 kernel/exit.c:748
[< inline >] SYSC_exit kernel/exit.c:847
[<ffffffff8137d152>] SyS_exit+0x22/0x30 kernel/exit.c:845
[<ffffffff86a96fc0>] entry_SYSCALL_64_fastpath+0x23/0xc1
arch/x86/entry/entry_64.S:207
Code: 55 41 54 53 48 89 fb 48 83 c7 04 48 89 fa 48 c1 ea 03 0f b6 14
02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 3e 02 00 00 <81>
7b 04 ad 4e ad de 0f 85 b9 01 00 00 4c 8d 63 10 48 b8 00 00
RIP [< inline >] debug_spin_lock_before
kernel/locking/spinlock_debug.c:83
RIP [<ffffffff81484c3e>] do_raw_spin_lock+0x3e/0x2b0
kernel/locking/spinlock_debug.c:135
RSP <ffff880060b77c40>
CR2: ffff880060888c64
---[ end trace 423f749510e6178a ]---
Fixing recursive fault but reboot is needed!
BUG: scheduling while atomic: a.out/7084/0x00000002
lockdep is turned off.
Modules linked in:
irq event stamp: 0
hardirqs last enabled at (0): [< (null)>] (null)
hardirqs last disabled at (0): [<ffffffff813664cd>]
copy_process.part.38+0x11dd/0x5b20 kernel/fork.c:1428
softirqs last enabled at (0): [<ffffffff8136656e>]
copy_process.part.38+0x127e/0x5b20 kernel/fork.c:1431
softirqs last disabled at (0): [< (null)>] (null)
CPU: 2 PID: 7084 Comm: a.out Tainted: G B D 4.7.0-rc4+ #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
ffffffff880b58e0 ffff880060b776d8 ffffffff82cc62cf ffffffff60a517c0
fffffbfff1016b1c ffff880060a517c0 0000000000000002 ffff880060b70000
0000000000000009 ffff88006d421580 ffff880060b776f8 ffffffff813ee349
Call Trace:
[< inline >] __dump_stack lib/dump_stack.c:15
[<ffffffff82cc62cf>] dump_stack+0x12e/0x18f lib/dump_stack.c:51
[<ffffffff813ee349>] __schedule_bug+0xb9/0xe0 kernel/sched/core.c:3163
[< inline >] schedule_debug kernel/sched/core.c:3178
[<ffffffff86a8730a>] __schedule+0x128a/0x1ca0 kernel/sched/core.c:3289
[<ffffffff86a87db7>] schedule+0x97/0x1c0 kernel/sched/core.c:3375
[<ffffffff8137c230>] do_exit+0x1dc0/0x2c80 kernel/exit.c:698
[<ffffffff812041c1>] oops_end+0xa1/0xd0 arch/x86/kernel/dumpstack.c:252
[<ffffffff8128fa51>] no_context+0x2d1/0x8f0 arch/x86/mm/fault.c:795
[<ffffffff8129026c>] __bad_area_nosemaphore+0x1fc/0x3e0 arch/x86/mm/fault.c:881
[<ffffffff81290483>] bad_area_nosemaphore+0x33/0x40 arch/x86/mm/fault.c:888
[<ffffffff81290ca3>] __do_page_fault+0x193/0xbb0 arch/x86/mm/fault.c:1298
[<ffffffff8129180f>] trace_do_page_fault+0xdf/0x5b0 arch/x86/mm/fault.c:1449
[<ffffffff81281c14>] do_async_page_fault+0x14/0xd0 arch/x86/kernel/kvm.c:265
[<ffffffff86a99178>] async_page_fault+0x28/0x30 arch/x86/entry/entry_64.S:923
[< inline >] __raw_spin_lock_irq include/linux/spinlock_api_smp.h:131
[<ffffffff86a969df>] _raw_spin_lock_irq+0x6f/0x80 kernel/locking/spinlock.c:167
[< inline >] spin_lock_irq include/linux/spinlock.h:332
[<ffffffff81073eff>] kvm_irqfd_release+0x2f/0x120
arch/x86/kvm/../../../virt/kvm/eventfd.c:584
[<ffffffff8105dfca>] kvm_vm_release+0x3a/0x50
arch/x86/kvm/../../../virt/kvm/kvm_main.c:752
[<ffffffff81819ee6>] __fput+0x236/0x780 fs/file_table.c:208
[<ffffffff8181a4b5>] ____fput+0x15/0x20 fs/file_table.c:244
[<ffffffff813d0826>] task_work_run+0xf6/0x170 kernel/task_work.c:115
[< inline >] exit_task_work include/linux/task_work.h:21
[<ffffffff8137aed2>] do_exit+0xa62/0x2c80 kernel/exit.c:748
[< inline >] SYSC_exit kernel/exit.c:847
[<ffffffff8137d152>] SyS_exit+0x22/0x30 kernel/exit.c:845
[<ffffffff86a96fc0>] entry_SYSCALL_64_fastpath+0x23/0xc1
arch/x86/entry/entry_64.S:207


Run in a parallel loop:

// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include <pthread.h>
#include <stdint.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>

long r[9];

void* thr(void* arg)
{
switch ((long)arg) {
case 0:
r[0] = syscall(SYS_mmap, 0x20000000ul, 0x16000ul, 0x3ul, 0x32ul,
0xfffffffffffffffful, 0x0ul);
break;
case 1:
r[2] = syscall(SYS_open, "/dev/kvm", 0x540ul, 0, 0, 0);
break;
case 2:
r[3] = syscall(SYS_ioctl, r[2], 0xae01ul, 0x0ul, 0, 0, 0);
break;
case 3:
r[4] = syscall(SYS_ioctl, r[3], 0xae41ul, 0x1ul, 0, 0, 0);
break;
case 4:
r[5] = syscall(SYS_ioctl, r[4], 0xae80ul, 0, 0, 0, 0);
break;
case 5:
r[6] = syscall(SYS_ioctl, r[4], 0xae80ul, 0, 0, 0, 0);
break;
case 6:
r[7] = syscall(SYS_ioctl, r[4], 0xae80ul, 0, 0, 0, 0);
break;
case 7:
r[8] =
syscall(SYS_ioctl, r[4], 0x8040ae9ful, 0x20014fe4ul, 0, 0, 0);
break;
}
return 0;
}

int main()
{
long i;
pthread_t th[8];

syscall(SYS_mmap, 0x20000000ul, 0x16000ul, 0x3ul, 0x32ul,
0xfffffffffffffffful, 0x0ul);

srand(getpid());
memset(r, -1, sizeof(r));
for (i = 0; i < 8; i++) {
pthread_create(&th[i], 0, thr, (void*)i);
}
for (i = 0; i < 8; i++) {
pthread_join(th[i], 0);
}
for (i = 0; i < 8; i++) {
pthread_create(&th[i], 0, thr, (void*)i);
if ((rand() % 2) == 0)
usleep(rand() % 10000);
}
for (i = 0; i < 8; i++) {
pthread_join(th[i], 0);
}
return 0;
}


On commit 67016f6cdfd079e632bbc49e33178b2d558c120a (Jun 20).
Reply all
Reply to author
Forward
0 new messages