From: Vijendar Mukunda Vijendar.Mukunda@amd.com
[ Upstream commit f93b697ed98e3c85d1973ea170d4f4e7a6b2b45d ]
During remove sequence, cancel the pending slave status update workqueue.
Signed-off-by: Vijendar Mukunda Vijendar.Mukunda@amd.com Link: https://lore.kernel.org/r/20250530054447.1645807-4-Vijendar.Mukunda@amd.com Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
## Backport Status: YES
This commit should be backported to stable kernel trees. Here's the extensive analysis:
### 1. **Bug Fix Nature** This commit fixes a potential **use-after-free (UAF)** vulnerability during driver removal. The workqueue `amd_sdw_work` (initialized at line 1074 in `amd_sdw_manager_probe()`) can be scheduled by interrupts (line 946 in the interrupt handler). Without cancelling this work during removal, the following race condition can occur:
- **CPU 0**: Driver removal begins, calls `amd_sdw_manager_remove()` - **CPU 1**: Interrupt arrives, schedules `amd_sdw_work` - **CPU 0**: Continues removal, frees the `amd_sdw_manager` structure via `sdw_bus_master_delete()` - **CPU 1**: Work handler executes, accesses freed memory → **UAF**
### 2. **Small and Contained Fix** The fix is minimal - just one line adding `cancel_work_sync(&amd_manager->amd_sdw_work)` at the right place in the removal sequence. This is placed: - After `pm_runtime_disable()` (ensures no new runtime PM operations) - Before `amd_disable_sdw_interrupts()` (ensures work can complete if running) - Before any cleanup/freeing operations
### 3. **Common Pattern in Driver Code** This follows an established pattern seen across the kernel. The recent commit 984836621aad ("spi: mpc52xx: Add cancel_work_sync before module remove") fixed an identical issue. The soundwire cadence driver also uses `cancel_work_sync()` in similar contexts (line 1259 in cadence_master.c).
### 4. **Part of a Broader Fix Series** This commit is part of a series addressing multiple issues in the AMD soundwire driver: - Commit 86a4371b7697 fixed slave alert handling after link down (already includes `cancel_work_sync()` in suspend paths) - This commit extends the fix to the removal path, ensuring complete coverage
### 5. **Real-World Impact** The commit message from the related fix (86a4371b7697) shows actual error logs from systems experiencing issues: ``` soundwire sdw-master-0-0: trf on Slave 1 failed:-110 read addr 0 count 1 rt722-sdca sdw:0:0:025d:0722:01: SDW_DP0_INT recheck read failed:-110 ``` These errors occur when the workqueue tries to access hardware after it's been disabled/freed.
### 6. **No Architectural Changes** This is a pure bug fix with no feature additions or architectural changes. It simply ensures proper cleanup ordering during driver removal.
### 7. **Minimal Risk** The `cancel_work_sync()` call is safe and standard practice. It waits for any pending work to complete and prevents new work from being scheduled. There's no risk of introducing new bugs or changing behavior - it only prevents a race condition.
### 8. **Critical for System Stability** Use-after-free bugs can lead to: - Kernel crashes/panics - Security vulnerabilities (potential for exploitation) - System instability during module unload/reload - Issues during system shutdown/reboot
The fix prevents these issues in production systems using AMD soundwire hardware, particularly important for laptops and systems with audio peripherals that may be dynamically loaded/unloaded.
drivers/soundwire/amd_manager.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c index 3b335d6eaa94..7ed9c8c0b4c8 100644 --- a/drivers/soundwire/amd_manager.c +++ b/drivers/soundwire/amd_manager.c @@ -1074,6 +1074,7 @@ static void amd_sdw_manager_remove(struct platform_device *pdev) int ret;
pm_runtime_disable(&pdev->dev); + cancel_work_sync(&amd_manager->amd_sdw_work); amd_disable_sdw_interrupts(amd_manager); sdw_bus_master_delete(&amd_manager->bus); ret = amd_disable_sdw_manager(amd_manager);