Commit a2db672aa305a045404615e5222ba681bab6cf58
Committed by
Paul E. McKenney
1 parent
5d18023294
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Use get_online_cpus to avoid races involving CPU hotplug
If arch/x86/kernel/msr.c is a module, a CPU might offline or online between the for_each_online_cpu(i) loop and the call to register_hotcpu_notifier in msr_init or the call to unregister_hotcpu_notifier in msr_exit. The potential races can lead to leaks/duplicates, attempts to destroy non-existant devices, or random pointer dereferences. For example, in msr_init if: for_each_online_cpu(i) { err = msr_device_create(i); if (err != 0) goto out_class; } <----- CPU offlines register_hotcpu_notifier(&msr_class_cpu_notifier); and the CPU never onlines before msr_exit, then the module will never call msr_device_destroy for the associated CPU. This fix surrounds for_each_online_cpu and register_hotcpu_notifier or unregister_hotcpu_notifier with get_online_cpus+put_online_cpus. Tested on a VM. Signed-off-by: Silas Boyd-Wickizer <sbw@mit.edu> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Showing 1 changed file with 5 additions and 0 deletions Side-by-side Diff
arch/x86/kernel/msr.c
... | ... | @@ -257,12 +257,14 @@ |
257 | 257 | goto out_chrdev; |
258 | 258 | } |
259 | 259 | msr_class->devnode = msr_devnode; |
260 | + get_online_cpus(); | |
260 | 261 | for_each_online_cpu(i) { |
261 | 262 | err = msr_device_create(i); |
262 | 263 | if (err != 0) |
263 | 264 | goto out_class; |
264 | 265 | } |
265 | 266 | register_hotcpu_notifier(&msr_class_cpu_notifier); |
267 | + put_online_cpus(); | |
266 | 268 | |
267 | 269 | err = 0; |
268 | 270 | goto out; |
... | ... | @@ -271,6 +273,7 @@ |
271 | 273 | i = 0; |
272 | 274 | for_each_online_cpu(i) |
273 | 275 | msr_device_destroy(i); |
276 | + put_online_cpus(); | |
274 | 277 | class_destroy(msr_class); |
275 | 278 | out_chrdev: |
276 | 279 | __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); |
277 | 280 | |
... | ... | @@ -281,11 +284,13 @@ |
281 | 284 | static void __exit msr_exit(void) |
282 | 285 | { |
283 | 286 | int cpu = 0; |
287 | + get_online_cpus(); | |
284 | 288 | for_each_online_cpu(cpu) |
285 | 289 | msr_device_destroy(cpu); |
286 | 290 | class_destroy(msr_class); |
287 | 291 | __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); |
288 | 292 | unregister_hotcpu_notifier(&msr_class_cpu_notifier); |
293 | + put_online_cpus(); | |
289 | 294 | } |
290 | 295 | |
291 | 296 | module_init(msr_init); |