summary refs log tree commit diff stats
path: root/results/classifier/zero-shot/118/unknown/1911666
blob: 34be17f396e45b1ddb626b033963bbeebddd238c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
user-level: 0.902
VMM: 0.860
register: 0.857
hypervisor: 0.842
mistranslation: 0.842
x86: 0.841
device: 0.838
ppc: 0.834
vnc: 0.829
TCG: 0.827
KVM: 0.821
architecture: 0.815
permissions: 0.814
debug: 0.807
assembly: 0.806
i386: 0.794
graphic: 0.790
performance: 0.790
virtual: 0.788
semantic: 0.787
peripherals: 0.786
arm: 0.785
kernel: 0.783
PID: 0.772
network: 0.760
files: 0.752
risc-v: 0.751
boot: 0.727
socket: 0.726

ZDI-CAN-10904: QEMU Plan 9 File System TOCTOU Privilege Escalation Vulnerability

-- CVSS -----------------------------------------

7.5: AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H

-- ABSTRACT -------------------------------------

Trend Micro's Zero Day Initiative has identified a vulnerability affecting the following products:
QEMU - QEMU

-- VULNERABILITY DETAILS ------------------------

Version tested:5.0.0-rc3
Installer file:qemu-5.0.0-rc3.tar.xz
Platform tested:ubuntu 18.04 x64 desktop
Analysis Basically v9fs* functions called from guest kernel are executed under specific thread(I call it main thread later). But when it calls some file related system calls, qemu uses its own coroutine thread(worker thread). Then it returns(yield return) without waiting result of system call and start to execute next v9fs* function.

In v9fsmarkfidsunreclaim() function, it stores fidlist member (head of singly linked list) to its stack.

 -> https://github.com/qemu/qemu/blob/f3bac27cc1e303e1860cc55b9b6889ba39dee587/hw/9pfs/9p.c#L506

And if it uses coroutine, it restore fid_list from stack and restart whole loop.

 -> https://github.com/qemu/qemu/blob/f3bac27cc1e303e1860cc55b9b6889ba39dee587/hw/9pfs/9p.c#L526

v9fsclunk() function calls clunkfid() which unlink fid from list, and free it.

 -> https://github.com/qemu/qemu/blob/f3bac27cc1e303e1860cc55b9b6889ba39dee587/hw/9pfs/9p.c#L2060-L2091

So if v9fsclunk() is called while v9fsmarkfidsunreclaim()'s coroutine is being executed, it restores "FREED" fidp from stack and use it.

it can be reproduced with the qemu binary, which is given
it can also be reproduced with own ASAN build (5.0.0-rc3 and 4.2.0 are tested)

../qemu-5.0.0-rc3/x86_64-softmmu/qemu-system-x86_64 -M pc -kernel ./bzImage -initrd ./rootfs.cpio -append "root=/dev/ram console=tty1 console=ttyS0 rdinit=/bin/sh" -nographic -enable-kvm -fsdev local,id=test_dev,path=/home/xxx/sandbox,security_model=none -device virtio-9p-pci,fsdev=test_dev,mount_tag=victim_tag

$ ./do.sh
expected ASAN report is printed
the race is in coroutine, so the threads are the same one

=================================================================
 ==46645==ERROR: AddressSanitizer: heap-use-after-free on address 0x610000047948 at pc 0x5563d8c28f0f bp0
READ of size 2 at 0x610000047948 thread T0

   #0 0x5563d8c28f0e in v9fs_mark_fids_unreclaim hw/9pfs/9p.c:508
   #1 0x5563d8c3e9e3 in v9fs_remove hw/9pfs/9p.c:2988
   #2 0x5563d98d310d in coroutine_trampoline util/coroutine-ucontext.c:115
   #3 0x7fadac6396af  (/lib/x86_64-linux-gnu/libc.so.6+0x586af)

   0x610000047948 is located 8 bytes inside of 192-byte region [0x610000047940,0x610000047a00) freed by thread T0 here:

  #0 0x7fadafa5f7a8 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xde7a8)
  #1 0x5563d8c27a60 in free_fid hw/9pfs/9p.c:371
  #2 0x5563d8c27fcc in put_fid hw/9pfs/9p.c:396
  #3 0x5563d8c37267 in v9fs_clunk hw/9pfs/9p.c:2085
  #4 0x5563d98d310d in coroutine_trampoline util/coroutine-ucontext.c:115
  #5 0x7fadac6396af  (/lib/x86_64-linux-gnu/libc.so.6+0x586af)

previously allocated by thread T0 here:
   #0 0x7fadafa5fd28 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded28)
   #1 0x7fadaf0c8b10 in g_malloc0 (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x51b10)
   #2 0x5563d8c30ecc in v9fs_attach hw/9pfs/9p.c:1412
   #3 0x5563d98d310d in coroutine_trampoline util/coroutine-ucontext.c:115
   #4 0x7fadac6396af  (/lib/x86_64-linux-gnu/libc.so.6+0x586af)


This vulnerability was discovered by:

Ryota Shiga(@Garyo) of Flatt Security working with Trend Micro Zero Day Initiative

Requesting a CVE...

'CVE-2021-20181' is assigned to this issue by Red Hat Inc.

Fixed by commit 89fbea8737e ("9pfs: Fully restart unreclaim loop (CVE-2021-20181)").