If a cpu hotplug callback fails on CPU_UP_PREPARE, all callbacks will be called with CPU_UP_CANCELED. A few of these callbacks assume that on CPU_UP_PREPARE a pointer to task has been stored in a percpu array. This assumption is not true if CPU_UP_PREPARE fails and the following calls to kthread_bind() in CPU_UP_CANCELED will cause an addressing exception because of passing a NULL pointer.
Showing the changes to kernel/workqueue.c (1 of 4 files). Show all
Unified · Split
| @@ -590,6 +590,8 @@ static int workqueue_cpu_callback(struct notifier_block *nfb, · 589 unmodified lines | ||
| 590 | 590 | |
| 591 | 591 | case CPU_UP_CANCELED: |
| 592 | 592 | list_for_each_entry(wq, &workqueues, list) { |
| 593 | + if (!per_cpu_ptr(wq->cpu_wq, hotcpu)->thread) | |
| 594 | + continue; | |
| 593 | 595 | /* Unbind so it can run. */ |
| 594 | 596 | kthread_bind(per_cpu_ptr(wq->cpu_wq, hotcpu)->thread, |
| 595 | 597 | any_online_cpu(cpu_online_map)); |