CVE-2024-27004: clk: Get runtime PM before walking tree during disable_unused
In the Linux kernel, the following vulnerability has been resolved:
clk: Get runtime PM before walking tree during disableunused
Doug reported [1] the following hung task:
INFO: task swapper/0:1 blocked for more than 122 seconds. Not tainted 5.15.149-21875-gf795ebc40eb8 #1 "echo 0 > /proc/sys/kernel/hungtasktimeoutsecs" disables this message. task:swapper/0 state:D stack: 0 pid: 1 ppid: 0 flags:0x00000008 Call trace: switchto+0xf4/0x1f4 schedule+0x418/0xb80 schedule+0x5c/0x10c rpmresume+0xe0/0x52c rpmresume+0x178/0x52c pmruntimeresume+0x58/0x98 clkpmruntimeget+0x30/0xb0 clkdisableunusedsubtree+0x58/0x208 clkdisableunusedsubtree+0x38/0x208 clkdisableunusedsubtree+0x38/0x208 clkdisableunusedsubtree+0x38/0x208 clkdisableunusedsubtree+0x38/0x208 clkdisableunused+0x4c/0xe4 dooneinitcall+0xcc/0x2d8 doinitcalllevel+0xa4/0x148 doinitcalls+0x5c/0x9c dobasicsetup+0x24/0x30 kernelinitfreeable+0xec/0x164 kernelinit+0x28/0x120 retfromfork+0x10/0x20 INFO: task kworker/u16:0:9 blocked for more than 122 seconds. Not tainted 5.15.149-21875-gf795ebc40eb8 #1 "echo 0 > /proc/sys/kernel/hungtasktimeoutsecs" disables this message. task:kworker/u16:0 state:D stack: 0 pid: 9 ppid: 2 flags:0x00000008 Workqueue: eventsunbound deferredprobeworkfunc Call trace: switchto+0xf4/0x1f4 schedule+0x418/0xb80 schedule+0x5c/0x10c schedulepreemptdisabled+0x2c/0x48 mutexlock+0x238/0x488 mutexlockslowpath+0x1c/0x28 mutexlock+0x50/0x74 clkpreparelock+0x7c/0x9c clkcorepreparelock+0x20/0x44 clkprepare+0x24/0x30 clkbulkprepare+0x40/0xb0 mdssruntimeresume+0x54/0x1c8 pmgenericruntimeresume+0x30/0x44 genpdruntimeresume+0x68/0x7c genpdruntimeresume+0x108/0x1f4 rpmcallback+0x84/0x144 rpmcallback+0x30/0x88 rpmresume+0x1f4/0x52c rpmresume+0x178/0x52c pmruntimeresume+0x58/0x98 deviceattach+0xe0/0x170 deviceinitialprobe+0x1c/0x28 busprobedevice+0x3c/0x9c deviceadd+0x644/0x814 mipidsideviceregisterfull+0xe4/0x170 devmmipidsideviceregisterfull+0x28/0x70 tisnbridgeprobe+0x1dc/0x2c0 auxiliarybusprobe+0x4c/0x94 reallyprobe+0xcc/0x2c8 driverprobedevice+0xa8/0x130 driverprobedevice+0x48/0x110 deviceattachdriver+0xa4/0xcc busforeachdrv+0x8c/0xd8 deviceattach+0xf8/0x170 deviceinitialprobe+0x1c/0x28 busprobedevice+0x3c/0x9c deferredprobeworkfunc+0x9c/0xd8 processonework+0x148/0x518 workerthread+0x138/0x350 kthread+0x138/0x1e0 retfromfork+0x10/0x20
The first thread is walking the clk tree and calling clkpmruntimeget() to power on devices required to read the clk hardware via struct clkops::isenabled(). This thread holds the clk preparelock, and is trying to runtime PM resume a device, when it finds that the device is in the process of resuming so the thread schedule()s away waiting for the device to finish resuming before continuing. The second thread is runtime PM resuming the same device, but the runtime resume callback is calling clkprepare(), trying to grab the preparelock waiting on the first thread.
This is a classic ABBA deadlock. To properly fix the deadlock, we must never runtime PM resume or suspend a device with the clk preparelock held. Actually doing that is near impossible today because the global preparelock would have to be dropped in the middle of the tree, the device runtime PM resumed/suspended, and then the preparelock grabbed again to ensure consistency of the clk tree topology. If anything changes with the clk tree in the meantime, we've lost and will need to start the operation all over again.
Luckily, most of the time we're simply incrementing or decrementing the runtime PM count on an active device, so we don't have the chance to schedule away with the preparelock held. Let's fix this immediate problem that can be ---truncated---
Other sources
In the Linux kernel, the following vulnerability has been resolved:
clk: Get runtime PM before walking tree during disableunused
The Linux kernel CVE team has assigned CVE-2024-27004 to this issue.
Upstream advisory: https://lore.kernel.org/linux-cve-announce/2024050147-CVE-2024-27004-c429@gregkh/T
— Red Hat
Affected Software
Remediation
Event History
Frequently Asked Questions
What is the severity of CVE-2024-27004?
CVE-2024-27004 has a medium severity rating due to its potential to cause hung tasks in the Linux kernel.
How do I fix CVE-2024-27004?
To fix CVE-2024-27004, update the kernel to versions 5.15.157, 6.1.88, 6.6.29, 6.8.8, or 6.9 for Red Hat, or certain specified versions for Debian.
What systems are affected by CVE-2024-27004?
CVE-2024-27004 affects Linux kernel versions prior to the mentioned remedial updates from Red Hat and Debian.
What is the impact of CVE-2024-27004?
The impact of CVE-2024-27004 includes potential system hangs, making critical tasks unresponsive for extended periods.
Who reported CVE-2024-27004?
CVE-2024-27004 was reported by a user named Doug, highlighting issues with hung tasks.