[PATCH 1/2] ALSA: hwdep: Serialize DSP load requests

From: YuanZhe Liu

Date: Thu Oct 29 2026 - 04:48:45 EST


The check of the loaded DSP indices and the call of the driver's
dsp_load callback in snd_hwdep_dsp_load() are not serialized. A hwdep
file descriptor can be shared among threads, or inherited across fork,
so two SNDRV_HWDEP_IOCTL_DSP_LOAD requests for the same index can both
observe the index as unloaded and enter the driver's callback
concurrently, even though the device itself is opened exclusively.

This breaks the assumption behind hw->dsp_loaded that a firmware index
is loaded only once. For example, snd-usb-usx2y hits
WARN_ON(usx2y->as04.buffer) in usx2y_async_seq04_init() and may
allocate the US-428 sequence URBs twice.

Serialize the check, the callback invocation and the bookkeeping with a
per-hwdep mutex, so that the second request returns -EBUSY.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@xxxxxxxxxxxxxxx
Co-developed-by: Bin Yu <byu@xxxxxxxxxxxxx>
Signed-off-by: Bin Yu <byu@xxxxxxxxxxxxx>
Co-developed-by: Cheng Wen <wencheng@xxxxxxxxxxxxx>
Signed-off-by: Cheng Wen <wencheng@xxxxxxxxxxxxx>
Signed-off-by: YuanZhe Liu <25031212351@xxxxxxxxxxxxxxxxx>
---
include/sound/hwdep.h | 1 +
sound/core/hwdep.c | 2 ++
2 files changed, 3 insertions(+)

diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h
index b0da633184cd..7357727f0660 100644
--- a/include/sound/hwdep.h
+++ b/include/sound/hwdep.h
@@ -57,6 +57,7 @@ struct snd_hwdep {

struct mutex open_mutex;
int used; /* reference counter */
+ struct mutex dsp_mutex; /* serializes DSP load requests */
unsigned int dsp_loaded; /* bit fields of loaded dsp indices */
unsigned int exclusive:1; /* exclusive access mode */
};
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index c6de5345e946..fb9034897c56 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -212,6 +212,7 @@ static int snd_hwdep_dsp_load(struct snd_hwdep *hw,
return -ENXIO;
if (info->index >= 32)
return -EINVAL;
+ guard(mutex)(&hw->dsp_mutex);
/* check whether the dsp was already loaded */
if (hw->dsp_loaded & (1u << info->index))
return -EBUSY;
@@ -380,6 +381,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,

init_waitqueue_head(&hwdep->open_wait);
mutex_init(&hwdep->open_mutex);
+ mutex_init(&hwdep->dsp_mutex);
hwdep->card = card;
hwdep->device = device;
if (id)
--
2.34.1