Commit ff083a2
perf: Protect perf_guest_cbs with RCU
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.com1 parent fa55b7d commit ff083a2
File tree
9 files changed
+82
-35
lines changed- arch
- arm64/kernel
- arm/kernel
- csky/kernel
- nds32/kernel
- riscv/kernel
- x86/events
- intel
- include/linux
- kernel/events
9 files changed
+82
-35
lines changed| 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 | |
|---|---|---|---|
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
| 59 | + | |
59 | 60 | | |
60 | 61 | | |
61 | 62 | | |
62 | | - | |
| 63 | + | |
63 | 64 | | |
64 | 65 | | |
65 | 66 | | |
| |||
78 | 79 | | |
79 | 80 | | |
80 | 81 | | |
| 82 | + | |
| 83 | + | |
81 | 84 | | |
82 | | - | |
| 85 | + | |
83 | 86 | | |
84 | 87 | | |
85 | 88 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2768 | 2768 | | |
2769 | 2769 | | |
2770 | 2770 | | |
| 2771 | + | |
2771 | 2772 | | |
2772 | 2773 | | |
2773 | 2774 | | |
2774 | | - | |
| 2775 | + | |
2775 | 2776 | | |
2776 | 2777 | | |
2777 | 2778 | | |
| |||
2871 | 2872 | | |
2872 | 2873 | | |
2873 | 2874 | | |
| 2875 | + | |
2874 | 2876 | | |
2875 | 2877 | | |
2876 | 2878 | | |
2877 | | - | |
| 2879 | + | |
2878 | 2880 | | |
2879 | 2881 | | |
2880 | 2882 | | |
| |||
2951 | 2953 | | |
2952 | 2954 | | |
2953 | 2955 | | |
2954 | | - | |
2955 | | - | |
| 2956 | + | |
| 2957 | + | |
| 2958 | + | |
| 2959 | + | |
2956 | 2960 | | |
2957 | 2961 | | |
2958 | 2962 | | |
2959 | 2963 | | |
2960 | 2964 | | |
2961 | 2965 | | |
| 2966 | + | |
2962 | 2967 | | |
2963 | 2968 | | |
2964 | | - | |
2965 | | - | |
| 2969 | + | |
| 2970 | + | |
2966 | 2971 | | |
2967 | 2972 | | |
2968 | 2973 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2837 | 2837 | | |
2838 | 2838 | | |
2839 | 2839 | | |
| 2840 | + | |
2840 | 2841 | | |
2841 | 2842 | | |
2842 | 2843 | | |
| |||
2903 | 2904 | | |
2904 | 2905 | | |
2905 | 2906 | | |
2906 | | - | |
2907 | | - | |
2908 | | - | |
| 2907 | + | |
| 2908 | + | |
| 2909 | + | |
| 2910 | + | |
| 2911 | + | |
2909 | 2912 | | |
2910 | 2913 | | |
2911 | 2914 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1240 | 1240 | | |
1241 | 1241 | | |
1242 | 1242 | | |
1243 | | - | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
| 1250 | + | |
| 1251 | + | |
| 1252 | + | |
| 1253 | + | |
| 1254 | + | |
1244 | 1255 | | |
1245 | 1256 | | |
1246 | 1257 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6526 | 6526 | | |
6527 | 6527 | | |
6528 | 6528 | | |
6529 | | - | |
| 6529 | + | |
6530 | 6530 | | |
6531 | 6531 | | |
6532 | 6532 | | |
6533 | | - | |
| 6533 | + | |
| 6534 | + | |
| 6535 | + | |
| 6536 | + | |
6534 | 6537 | | |
6535 | 6538 | | |
6536 | 6539 | | |
6537 | 6540 | | |
6538 | 6541 | | |
6539 | 6542 | | |
6540 | | - | |
| 6543 | + | |
| 6544 | + | |
| 6545 | + | |
| 6546 | + | |
| 6547 | + | |
6541 | 6548 | | |
6542 | 6549 | | |
6543 | 6550 | | |
| |||
0 commit comments