Commit 723acd7
perf: Protect perf_guest_cbs with RCU
commit ff083a2 upstream.
Protect perf_guest_cbs with RCU to fix multiple possible errors. Luckily,
all paths that read perf_guest_cbs already require RCU protection, e.g. to
protect the callback chains, so only the direct perf_guest_cbs touchpoints
need to be modified.
Bug #1 is a simple lack of WRITE_ONCE/READ_ONCE behavior to ensure
perf_guest_cbs isn't reloaded between a !NULL check and a dereference.
Fixed via the READ_ONCE() in rcu_dereference().
Bug #2 is that on weakly-ordered architectures, updates to the callbacks
themselves are not guaranteed to be visible before the pointer is made
visible to readers. Fixed by the smp_store_release() in
rcu_assign_pointer() when the new pointer is non-NULL.
Bug #3 is that, because the callbacks are global, it's possible for
readers to run in parallel with an unregisters, and thus a module
implementing the callbacks can be unloaded while readers are in flight,
resulting in a use-after-free. Fixed by a synchronize_rcu() call when
unregistering callbacks.
Bug #1 escaped notice because it's extremely unlikely a compiler will
reload perf_guest_cbs in this sequence. perf_guest_cbs does get reloaded
for future derefs, e.g. for ->is_user_mode(), but the ->is_in_guest()
guard all but guarantees the consumer will win the race, e.g. to nullify
perf_guest_cbs, KVM has to completely exit the guest and teardown down
all VMs before KVM start its module unload / unregister sequence. This
also makes it all but impossible to encounter bug #3.
Bug #2 has not been a problem because all architectures that register
callbacks are strongly ordered and/or have a static set of callbacks.
But with help, unloading kvm_intel can trigger bug #1 e.g. wrapping
perf_guest_cbs with READ_ONCE in perf_misc_flags() while spamming
kvm_intel module load/unload leads to:
BUG: kernel NULL pointer dereference, address: 0000000000000000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 0 P4D 0
Oops: 0000 [#1] PREEMPT SMP
CPU: 6 PID: 1825 Comm: stress Not tainted 5.14.0-rc2+ #459
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
RIP: 0010:perf_misc_flags+0x1c/0x70
Call Trace:
perf_prepare_sample+0x53/0x6b0
perf_event_output_forward+0x67/0x160
__perf_event_overflow+0x52/0xf0
handle_pmi_common+0x207/0x300
intel_pmu_handle_irq+0xcf/0x410
perf_event_nmi_handler+0x28/0x50
nmi_handle+0xc7/0x260
default_do_nmi+0x6b/0x170
exc_nmi+0x103/0x130
asm_exc_nmi+0x76/0xbf
Fixes: 39447b3 ("perf: Enhance perf to allow for guest statistic collection from host")
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20211111020738.2512932-2-seanjc@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>1 parent eadde28 commit 723acd7
9 files changed
Lines changed: 82 additions & 35 deletions
File tree
- arch
- arm64/kernel
- arm/kernel
- csky/kernel
- nds32/kernel
- riscv/kernel
- x86/events
- intel
- include/linux
- kernel/events
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
| 65 | + | |
65 | 66 | | |
66 | 67 | | |
67 | | - | |
| 68 | + | |
68 | 69 | | |
69 | 70 | | |
70 | 71 | | |
| |||
98 | 99 | | |
99 | 100 | | |
100 | 101 | | |
| 102 | + | |
101 | 103 | | |
102 | 104 | | |
103 | | - | |
| 105 | + | |
104 | 106 | | |
105 | 107 | | |
106 | 108 | | |
| |||
111 | 113 | | |
112 | 114 | | |
113 | 115 | | |
114 | | - | |
115 | | - | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
116 | 120 | | |
117 | 121 | | |
118 | 122 | | |
119 | 123 | | |
120 | 124 | | |
121 | 125 | | |
| 126 | + | |
122 | 127 | | |
123 | 128 | | |
124 | | - | |
125 | | - | |
| 129 | + | |
| 130 | + | |
126 | 131 | | |
127 | 132 | | |
128 | 133 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
102 | 102 | | |
103 | 103 | | |
104 | 104 | | |
105 | | - | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
106 | 108 | | |
107 | 109 | | |
108 | 110 | | |
| |||
147 | 149 | | |
148 | 150 | | |
149 | 151 | | |
| 152 | + | |
150 | 153 | | |
151 | 154 | | |
152 | | - | |
| 155 | + | |
153 | 156 | | |
154 | 157 | | |
155 | 158 | | |
| |||
160 | 163 | | |
161 | 164 | | |
162 | 165 | | |
163 | | - | |
164 | | - | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
165 | 170 | | |
166 | 171 | | |
167 | 172 | | |
168 | 173 | | |
169 | 174 | | |
170 | 175 | | |
| 176 | + | |
171 | 177 | | |
172 | 178 | | |
173 | | - | |
174 | | - | |
| 179 | + | |
| 180 | + | |
175 | 181 | | |
176 | 182 | | |
177 | 183 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
| 89 | + | |
89 | 90 | | |
90 | 91 | | |
91 | 92 | | |
92 | | - | |
| 93 | + | |
93 | 94 | | |
94 | 95 | | |
95 | 96 | | |
| |||
110 | 111 | | |
111 | 112 | | |
112 | 113 | | |
| 114 | + | |
113 | 115 | | |
114 | 116 | | |
115 | 117 | | |
116 | | - | |
| 118 | + | |
117 | 119 | | |
118 | 120 | | |
119 | 121 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1363 | 1363 | | |
1364 | 1364 | | |
1365 | 1365 | | |
| 1366 | + | |
1366 | 1367 | | |
1367 | 1368 | | |
1368 | 1369 | | |
| |||
1371 | 1372 | | |
1372 | 1373 | | |
1373 | 1374 | | |
1374 | | - | |
| 1375 | + | |
1375 | 1376 | | |
1376 | 1377 | | |
1377 | 1378 | | |
| |||
1479 | 1480 | | |
1480 | 1481 | | |
1481 | 1482 | | |
| 1483 | + | |
1482 | 1484 | | |
1483 | 1485 | | |
1484 | | - | |
| 1486 | + | |
1485 | 1487 | | |
1486 | 1488 | | |
1487 | 1489 | | |
| |||
1493 | 1495 | | |
1494 | 1496 | | |
1495 | 1497 | | |
| 1498 | + | |
| 1499 | + | |
1496 | 1500 | | |
1497 | | - | |
1498 | | - | |
| 1501 | + | |
| 1502 | + | |
1499 | 1503 | | |
1500 | 1504 | | |
1501 | 1505 | | |
1502 | 1506 | | |
1503 | 1507 | | |
1504 | 1508 | | |
| 1509 | + | |
1505 | 1510 | | |
1506 | 1511 | | |
1507 | 1512 | | |
1508 | | - | |
1509 | | - | |
| 1513 | + | |
| 1514 | + | |
1510 | 1515 | | |
1511 | 1516 | | |
1512 | 1517 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
| 63 | + | |
63 | 64 | | |
64 | 65 | | |
65 | 66 | | |
66 | | - | |
| 67 | + | |
67 | 68 | | |
68 | 69 | | |
69 | 70 | | |
| |||
84 | 85 | | |
85 | 86 | | |
86 | 87 | | |
| 88 | + | |
| 89 | + | |
87 | 90 | | |
88 | | - | |
| 91 | + | |
89 | 92 | | |
90 | 93 | | |
91 | 94 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2545 | 2545 | | |
2546 | 2546 | | |
2547 | 2547 | | |
| 2548 | + | |
2548 | 2549 | | |
2549 | 2550 | | |
2550 | 2551 | | |
2551 | | - | |
| 2552 | + | |
2552 | 2553 | | |
2553 | 2554 | | |
2554 | 2555 | | |
| |||
2648 | 2649 | | |
2649 | 2650 | | |
2650 | 2651 | | |
| 2652 | + | |
2651 | 2653 | | |
2652 | 2654 | | |
2653 | 2655 | | |
2654 | | - | |
| 2656 | + | |
2655 | 2657 | | |
2656 | 2658 | | |
2657 | 2659 | | |
| |||
2728 | 2730 | | |
2729 | 2731 | | |
2730 | 2732 | | |
2731 | | - | |
2732 | | - | |
| 2733 | + | |
| 2734 | + | |
| 2735 | + | |
| 2736 | + | |
2733 | 2737 | | |
2734 | 2738 | | |
2735 | 2739 | | |
2736 | 2740 | | |
2737 | 2741 | | |
2738 | 2742 | | |
| 2743 | + | |
2739 | 2744 | | |
2740 | 2745 | | |
2741 | | - | |
2742 | | - | |
| 2746 | + | |
| 2747 | + | |
2743 | 2748 | | |
2744 | 2749 | | |
2745 | 2750 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2586 | 2586 | | |
2587 | 2587 | | |
2588 | 2588 | | |
| 2589 | + | |
2589 | 2590 | | |
2590 | 2591 | | |
2591 | 2592 | | |
| |||
2651 | 2652 | | |
2652 | 2653 | | |
2653 | 2654 | | |
2654 | | - | |
2655 | | - | |
2656 | | - | |
| 2655 | + | |
| 2656 | + | |
| 2657 | + | |
| 2658 | + | |
| 2659 | + | |
2657 | 2660 | | |
2658 | 2661 | | |
2659 | 2662 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1235 | 1235 | | |
1236 | 1236 | | |
1237 | 1237 | | |
1238 | | - | |
| 1238 | + | |
| 1239 | + | |
| 1240 | + | |
| 1241 | + | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
1239 | 1250 | | |
1240 | 1251 | | |
1241 | 1252 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6395 | 6395 | | |
6396 | 6396 | | |
6397 | 6397 | | |
6398 | | - | |
| 6398 | + | |
6399 | 6399 | | |
6400 | 6400 | | |
6401 | 6401 | | |
6402 | | - | |
| 6402 | + | |
| 6403 | + | |
| 6404 | + | |
| 6405 | + | |
6403 | 6406 | | |
6404 | 6407 | | |
6405 | 6408 | | |
6406 | 6409 | | |
6407 | 6410 | | |
6408 | 6411 | | |
6409 | | - | |
| 6412 | + | |
| 6413 | + | |
| 6414 | + | |
| 6415 | + | |
| 6416 | + | |
6410 | 6417 | | |
6411 | 6418 | | |
6412 | 6419 | | |
| |||
0 commit comments