CVE-2022-50144
Publication date:
18/06/2025
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
soundwire: revisit driver bind/unbind and callbacks<br />
<br />
In the SoundWire probe, we store a pointer from the driver ops into<br />
the &#39;slave&#39; structure. This can lead to kernel oopses when unbinding<br />
codec drivers, e.g. with the following sequence to remove machine<br />
driver and codec driver.<br />
<br />
/sbin/modprobe -r snd_soc_sof_sdw<br />
/sbin/modprobe -r snd_soc_rt711<br />
<br />
The full details can be found in the BugLink below, for reference the<br />
two following examples show different cases of driver ops/callbacks<br />
being invoked after the driver .remove().<br />
<br />
kernel: BUG: kernel NULL pointer dereference, address: 0000000000000150<br />
kernel: Workqueue: events cdns_update_slave_status_work [soundwire_cadence]<br />
kernel: RIP: 0010:mutex_lock+0x19/0x30<br />
kernel: Call Trace:<br />
kernel: ? sdw_handle_slave_status+0x426/0xe00 [soundwire_bus 94ff184bf398570c3f8ff7efe9e32529f532e4ae]<br />
kernel: ? newidle_balance+0x26a/0x400<br />
kernel: ? cdns_update_slave_status_work+0x1e9/0x200 [soundwire_cadence 1bcf98eebe5ba9833cd433323769ac923c9c6f82]<br />
<br />
kernel: BUG: unable to handle page fault for address: ffffffffc07654c8<br />
kernel: Workqueue: pm pm_runtime_work<br />
kernel: RIP: 0010:sdw_bus_prep_clk_stop+0x6f/0x160 [soundwire_bus]<br />
kernel: Call Trace:<br />
kernel: <br />
kernel: sdw_cdns_clock_stop+0xb5/0x1b0 [soundwire_cadence 1bcf98eebe5ba9833cd433323769ac923c9c6f82]<br />
kernel: intel_suspend_runtime+0x5f/0x120 [soundwire_intel aca858f7c87048d3152a4a41bb68abb9b663a1dd]<br />
kernel: ? dpm_sysfs_remove+0x60/0x60<br />
<br />
This was not detected earlier in Intel tests since the tests first<br />
remove the parent PCI device and shut down the bus. The sequence<br />
above is a corner case which keeps the bus operational but without a<br />
driver bound.<br />
<br />
While trying to solve this kernel oopses, it became clear that the<br />
existing SoundWire bus does not deal well with the unbind case.<br />
<br />
Commit 528be501b7d4a ("soundwire: sdw_slave: add probe_complete structure and new fields")<br />
added a &#39;probed&#39; status variable and a &#39;probe_complete&#39;<br />
struct completion. This status is however not reset on remove and<br />
likewise the &#39;probe complete&#39; is not re-initialized, so the<br />
bind/unbind/bind test cases would fail. The timeout used before the<br />
&#39;update_status&#39; callback was also a bad idea in hindsight, there<br />
should really be no timing assumption as to if and when a driver is<br />
bound to a device.<br />
<br />
An initial draft was based on device_lock() and device_unlock() was<br />
tested. This proved too complicated, with deadlocks created during the<br />
suspend-resume sequences, which also use the same device_lock/unlock()<br />
as the bind/unbind sequences. On a CometLake device, a bad DSDT/BIOS<br />
caused spurious resumes and the use of device_lock() caused hangs<br />
during suspend. After multiple weeks or testing and painful<br />
reverse-engineering of deadlocks on different devices, we looked for<br />
alternatives that did not interfere with the device core.<br />
<br />
A bus notifier was used successfully to keep track of DRIVER_BOUND and<br />
DRIVER_UNBIND events. This solved the bind-unbind-bind case in tests,<br />
but it can still be defeated with a theoretical corner case where the<br />
memory is freed by a .remove while the callback is in use. The<br />
notifier only helps make sure the driver callbacks are valid, but not<br />
that the memory allocated in probe remains valid while the callbacks<br />
are invoked.<br />
<br />
This patch suggests the introduction of a new &#39;sdw_dev_lock&#39; mutex<br />
protecting probe/remove and all driver callbacks. Since this mutex is<br />
&#39;local&#39; to SoundWire only, it does not interfere with existing locks<br />
and does not create deadlocks. In addition, this patch removes the<br />
&#39;probe_complete&#39; completion, instead we directly invoke the<br />
&#39;update_status&#39; from the probe routine. That removes any sort of<br />
timing dependency and a much better support for the device/driver<br />
model, the driver could be bound before the bus started, or eons after<br />
the bus started and the hardware would be properly initialized in all<br />
cases.<br />
<br />
BugLink: https://github.com/thesofproject/linux/is<br />
---truncated---
Severity CVSS v4.0: Pending analysis
Last modification:
20/11/2025