Medium · published February 27, 2025
In the Linux kernel, the following vulnerability has been resolved:
clocksource: Use migrate_disable() to avoid calling get_random_u32() in atomic context
The following bug report happened with a PREEMPT_RT kernel:
BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:48
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 2012, name: kwatchdog
preempt_count: 1, expected: 0
RCU nest depth: 0, expected: 0
get_random_u32+0x4f/0x110
clocksource_verify_choose_cpus+0xab/0x1a0
clocksource_verify_percpu.part.0+0x6b/0x330
clocksource_watchdog_kthread+0x193/0x1a0
It is due to the fact that clocksource_verify_choose_cpus() is invoked with
preemption disabled. This function invokes get_random_u32() to obtain
random numbers for choosing CPUs. The batched_entropy_32 local lock and/or
the base_crng.lock spinlock in driver/char/random.c will be acquired during
the call. In PREEMPT_RT kernel, they are both sleeping locks and so cannot
be acquired in atomic context.
Fix this problem by using migrate_disable() to allow smp_processor_id() to
be reliably used without introducing atomic context. preempt_disable() is
then called after clocksource_verify_choose_cpus() but before the
clocksource measurement is being run to avoid introducing unexpected
latency.
| Product | Versions | Fixed in |
|---|---|---|
| linux/linux_kernel | ≥ 5.10.50, < 5.10.235 | 5.10.235 |
| linux/linux_kernel | ≥ 5.12.17, < 5.13 | 5.13 |
| linux/linux_kernel | ≥ 5.13.2, < 5.15.179 | 5.15.179 |
| linux/linux_kernel | ≥ 5.16, < 6.1.129 | 6.1.129 |
| linux/linux_kernel | ≥ 6.2, < 6.6.79 | 6.6.79 |
| linux/linux_kernel | ≥ 6.7, < 6.12.16 | 6.12.16 |
| linux/linux_kernel | ≥ 6.13, < 6.13.4 | 6.13.4 |
| linux/linux_kernel | all versions | — |