* [PATCH v3 1/7] ALSA: seq: Fix missing direction and ump_group handling in 32bit compat ioctl
2026-10-07 17:25 [PATCH v3 0/7] ALSA: Fix yet more bugs reported by Sashiko Takashi Iwai
@ 2026-10-07 17:25 ` Takashi Iwai
2026-10-07 17:25 ` [PATCH v3 2/7] ALSA: pcmtest: Fix leak at probe error Takashi Iwai
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Takashi Iwai @ 2026-10-07 17:25 UTC (permalink / raw)
To: linux-sound; +Cc: linux-kernel
I forgot to cover the two new fields, direction and ump_group, in
struct snd_seq_port_info for the 32bit compat ioctls of
SNDRV_SEQ_IOCTL_GET_PORT_INFO & co, which ended up with the garbage
copies in those fields. Add the handling of those two fields in the
compat layer.
Also, avoid over-copying the 64bit snd_seq_port_info but only the first
part (before the field kernel); this avoids the copy of kernel-space
garbage value in the reserved field.
Fixes: ff166a9d19fa ("ALSA: seq: Add port direction to snd_seq_port_info")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/core/seq/seq_compat.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
index 80110501da6f..57aaa39afb9d 100644
--- a/sound/core/seq/seq_compat.c
+++ b/sound/core/seq/seq_compat.c
@@ -25,7 +25,9 @@ struct snd_seq_port_info32 {
u32 kernel; /* reserved for kernel use (must be NULL) */
u32 flags; /* misc. conditioning */
unsigned char time_queue; /* queue # for timestamping */
- char reserved[59]; /* for future use */
+ unsigned char direction; /* port usage direction (r/w/bidir) */
+ unsigned char ump_group; /* 0 = UMP EP (no conversion), 1-16 = UMP group number */
+ char reserved[57]; /* for future use */
};
static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned int cmd,
@@ -40,7 +42,9 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned
if (copy_from_user(data, data32, sizeof(*data32)) ||
get_user(data->flags, &data32->flags) ||
- get_user(data->time_queue, &data32->time_queue))
+ get_user(data->time_queue, &data32->time_queue) ||
+ get_user(data->direction, &data32->direction) ||
+ get_user(data->ump_group, &data32->ump_group))
return -EFAULT;
data->kernel = NULL;
@@ -50,9 +54,12 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned
if (err < 0)
return err;
- if (copy_to_user(data32, data, sizeof(*data32)) ||
+ if (copy_to_user(data32, data,
+ offsetof(struct snd_seq_port_info32, kernel)) ||
put_user(data->flags, &data32->flags) ||
- put_user(data->time_queue, &data32->time_queue))
+ put_user(data->time_queue, &data32->time_queue) ||
+ put_user(data->direction, &data32->direction) ||
+ put_user(data->ump_group, &data32->ump_group))
return -EFAULT;
return err;
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 2/7] ALSA: pcmtest: Fix leak at probe error
2026-10-07 17:25 [PATCH v3 0/7] ALSA: Fix yet more bugs reported by Sashiko Takashi Iwai
2026-10-07 17:25 ` [PATCH v3 1/7] ALSA: seq: Fix missing direction and ump_group handling in 32bit compat ioctl Takashi Iwai
@ 2026-10-07 17:25 ` Takashi Iwai
2026-10-07 17:25 ` [PATCH v3 3/7] ALSA: pcmtest: Use platform_device_register_simple() Takashi Iwai
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Takashi Iwai @ 2026-10-07 17:25 UTC (permalink / raw)
To: linux-sound; +Cc: linux-kernel
When an error happens at probe of pcmtest driver before
snd_card_register() succeeds, we have to release the card explicitly,
but it's not done, leading to a potential memory leak.
Also, pcmtest driver manages struct pcmtst object unnecessarily
complicatedly by a dynamic allocation and release.
This patch fixes and cleans up the resource management:
- Use card's private_data allocation for struct sndpcmtst at the card
creation, which is released automatically together with the card
- Since the allocation of pcmtest is gone, snd_pcmtst_create() is
rather pointless, so just directly calling snd_pcmtst_new_pcm()
- Use the new auto-clean mechanism to handle the error case at probe.
- Many release handlers became superfluous and dropped
In the end we got a good amount of code reduction.
Fixes: 315a3d57c64c ("ALSA: Implement the new Virtual PCM Test Driver")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/drivers/pcmtest.c | 66 +++++++----------------------------------
1 file changed, 10 insertions(+), 56 deletions(-)
diff --git a/sound/drivers/pcmtest.c b/sound/drivers/pcmtest.c
index fea9580593e6..b4e333b4c438 100644
--- a/sound/drivers/pcmtest.c
+++ b/sound/drivers/pcmtest.c
@@ -446,20 +446,6 @@ static snd_pcm_uframes_t snd_pcmtst_pcm_pointer(struct snd_pcm_substream *substr
return bytes_to_frames(substream->runtime, v_iter->buf_pos);
}
-static int snd_pcmtst_free(struct pcmtst *pcmtst)
-{
- if (!pcmtst)
- return 0;
- kfree(pcmtst);
- return 0;
-}
-
-// These callbacks are required, but empty - all freeing occurs in pdev_remove
-static int snd_pcmtst_dev_free(struct snd_device *device)
-{
- return 0;
-}
-
static void pcmtst_pdev_release(struct device *dev)
{
}
@@ -563,40 +549,9 @@ static int snd_pcmtst_new_pcm(struct pcmtst *pcmtst)
return err;
}
-static int snd_pcmtst_create(struct snd_card *card, struct platform_device *pdev,
- struct pcmtst **r_pcmtst)
-{
- struct pcmtst *pcmtst;
- int err;
- static const struct snd_device_ops ops = {
- .dev_free = snd_pcmtst_dev_free,
- };
-
- pcmtst = kzalloc_obj(*pcmtst);
- if (!pcmtst)
- return -ENOMEM;
- pcmtst->card = card;
- pcmtst->pdev = pdev;
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pcmtst, &ops);
- if (err < 0)
- goto _err_free_chip;
-
- err = snd_pcmtst_new_pcm(pcmtst);
- if (err < 0)
- goto _err_free_chip;
-
- *r_pcmtst = pcmtst;
- return 0;
-
-_err_free_chip:
- snd_pcmtst_free(pcmtst);
- return err;
-}
-
static int pcmtst_probe(struct platform_device *pdev)
{
- struct snd_card *card;
+ struct snd_card *card __free(snd_card_free) = NULL;
struct pcmtst *pcmtst;
int err;
@@ -604,10 +559,16 @@ static int pcmtst_probe(struct platform_device *pdev)
if (err)
return err;
- err = snd_devm_card_new(&pdev->dev, index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(&pdev->dev, index, id, THIS_MODULE,
+ sizeof(*pcmtst), &card);
if (err < 0)
return err;
- err = snd_pcmtst_create(card, pdev, &pcmtst);
+
+ pcmtst = card->private_data;
+ pcmtst->card = card;
+ pcmtst->pdev = pdev;
+
+ err = snd_pcmtst_new_pcm(pcmtst);
if (err < 0)
return err;
@@ -620,17 +581,11 @@ static int pcmtst_probe(struct platform_device *pdev)
return err;
platform_set_drvdata(pdev, pcmtst);
+ card = NULL; /* probe succeeded, don't release as error */
return 0;
}
-static void pdev_remove(struct platform_device *pdev)
-{
- struct pcmtst *pcmtst = platform_get_drvdata(pdev);
-
- snd_pcmtst_free(pcmtst);
-}
-
static struct platform_device pcmtst_pdev = {
.name = "pcmtest",
.dev.release = pcmtst_pdev_release,
@@ -638,7 +593,6 @@ static struct platform_device pcmtst_pdev = {
static struct platform_driver pcmtst_pdrv = {
.probe = pcmtst_probe,
- .remove = pdev_remove,
.driver = {
.name = "pcmtest",
},
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 3/7] ALSA: pcmtest: Use platform_device_register_simple()
2026-10-07 17:25 [PATCH v3 0/7] ALSA: Fix yet more bugs reported by Sashiko Takashi Iwai
2026-10-07 17:25 ` [PATCH v3 1/7] ALSA: seq: Fix missing direction and ump_group handling in 32bit compat ioctl Takashi Iwai
2026-10-07 17:25 ` [PATCH v3 2/7] ALSA: pcmtest: Fix leak at probe error Takashi Iwai
@ 2026-10-07 17:25 ` Takashi Iwai
2026-10-07 17:25 ` [PATCH v3 4/7] ALSA: info: Fix memory leak at card removal Takashi Iwai
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Takashi Iwai @ 2026-10-07 17:25 UTC (permalink / raw)
To: linux-sound; +Cc: linux-kernel
It's more standard for this kind of device that doesn't need any
special handling. This allows us to delete the stub release callback.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/drivers/pcmtest.c | 23 ++++++++++-------------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/sound/drivers/pcmtest.c b/sound/drivers/pcmtest.c
index b4e333b4c438..393f132a438b 100644
--- a/sound/drivers/pcmtest.c
+++ b/sound/drivers/pcmtest.c
@@ -446,10 +446,6 @@ static snd_pcm_uframes_t snd_pcmtst_pcm_pointer(struct snd_pcm_substream *substr
return bytes_to_frames(substream->runtime, v_iter->buf_pos);
}
-static void pcmtst_pdev_release(struct device *dev)
-{
-}
-
static int snd_pcmtst_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -586,15 +582,14 @@ static int pcmtst_probe(struct platform_device *pdev)
return 0;
}
-static struct platform_device pcmtst_pdev = {
- .name = "pcmtest",
- .dev.release = pcmtst_pdev_release,
-};
+#define SND_PCMTEST_DRIVER "pcmtest"
+
+static struct platform_device *pcmtst_pdev;
static struct platform_driver pcmtst_pdrv = {
.probe = pcmtst_probe,
.driver = {
- .name = "pcmtest",
+ .name = SND_PCMTEST_DRIVER,
},
};
@@ -706,12 +701,14 @@ static int __init mod_init(void)
err = init_debug_files(buf_allocated);
if (err)
goto err_free_patterns;
- err = platform_device_register(&pcmtst_pdev);
- if (err)
+ pcmtst_pdev = platform_device_register_simple(SND_PCMTEST_DRIVER, -1, NULL, 0);
+ if (IS_ERR(pcmtst_pdev)) {
+ err = PTR_ERR(pcmtst_pdev);
goto err_clear_debug;
+ }
err = platform_driver_register(&pcmtst_pdrv);
if (err) {
- platform_device_unregister(&pcmtst_pdev);
+ platform_device_unregister(pcmtst_pdev);
goto err_clear_debug;
}
@@ -730,7 +727,7 @@ static void __exit mod_exit(void)
free_pattern_buffers();
platform_driver_unregister(&pcmtst_pdrv);
- platform_device_unregister(&pcmtst_pdev);
+ platform_device_unregister(pcmtst_pdev);
}
MODULE_DESCRIPTION("Virtual ALSA driver for PCM testing/fuzzing");
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 4/7] ALSA: info: Fix memory leak at card removal
2026-10-07 17:25 [PATCH v3 0/7] ALSA: Fix yet more bugs reported by Sashiko Takashi Iwai
` (2 preceding siblings ...)
2026-10-07 17:25 ` [PATCH v3 3/7] ALSA: pcmtest: Use platform_device_register_simple() Takashi Iwai
@ 2026-10-07 17:25 ` Takashi Iwai
2026-10-07 17:25 ` [PATCH v3 5/7] ALSA: aloop: Avoid a bad mixure of guard() and goto Takashi Iwai
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Takashi Iwai @ 2026-10-07 17:25 UTC (permalink / raw)
To: linux-sound; +Cc: linux-kernel
The fix for potential deadlock at disconnection by the commit
c7a606519533 ("ALSA: info: Fix potential deadlock at disconnection")
clears card->proc_root pointer at snd_info_card_disconnect(), in order
just to be sure. But this leads to a memory leak of card->proc_root
content that should have been released at a later call of
snd_info_card_free().
For addressing the memory leak, simply drop the card->proc_root
clearance at snd_info_card_disconnect().
Since card->proc_root might be still looked at in
snd_info_card_id_change() that may be running concurrently during the
connection procedure, add a sanity check there, too.
Fixes: c7a606519533 ("ALSA: info: Fix potential deadlock at disconnection")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20261006174002.703431-1-tiwai%40suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/core/info.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/core/info.c b/sound/core/info.c
index 3b8ccda04e1a..c4d57d0809ad 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -528,6 +528,8 @@ int snd_info_card_register(struct snd_card *card)
void snd_info_card_id_change(struct snd_card *card)
{
guard(mutex)(&info_mutex);
+ if (card->shutdown)
+ return;
if (card->proc_root_link) {
proc_remove(card->proc_root_link);
card->proc_root_link = NULL;
@@ -555,7 +557,6 @@ void snd_info_card_disconnect(struct snd_card *card)
if (card->proc_root)
snd_info_clear_entries(card->proc_root);
card->proc_root_link = NULL;
- card->proc_root = NULL;
}
/*
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 5/7] ALSA: aloop: Avoid a bad mixure of guard() and goto
2026-10-07 17:25 [PATCH v3 0/7] ALSA: Fix yet more bugs reported by Sashiko Takashi Iwai
` (3 preceding siblings ...)
2026-10-07 17:25 ` [PATCH v3 4/7] ALSA: info: Fix memory leak at card removal Takashi Iwai
@ 2026-10-07 17:25 ` Takashi Iwai
2026-10-07 17:25 ` [PATCH v3 6/7] ALSA: core: Fix leaks at snd_card_init() error paths Takashi Iwai
2026-10-07 17:25 ` [PATCH v3 7/7] ALSA: seq: Don't lose partial read failure Takashi Iwai
6 siblings, 0 replies; 8+ messages in thread
From: Takashi Iwai @ 2026-10-07 17:25 UTC (permalink / raw)
To: linux-sound; +Cc: linux-kernel
The rewrite of aloop driver code using guard() leaded to a mixture of
guard() and some goto; although it currently works, it isn't really a
good match.
For avoiding the bad match, just move the code using goto into a
function and wrap it with guard().
Fixes: ebd9b6c91d4e ("ALSA: aloop: Use guard() for mutex locks")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/drivers/aloop.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 5f0e2dc96769..0aaa64b189da 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -1375,7 +1375,7 @@ static const struct loopback_ops loopback_snd_timer_ops = {
.dpcm_info = loopback_snd_timer_dpcm_info,
};
-static int loopback_open(struct snd_pcm_substream *substream)
+static int __loopback_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct loopback *loopback = substream->private_data;
@@ -1384,7 +1384,6 @@ static int loopback_open(struct snd_pcm_substream *substream)
int err = 0;
int dev = get_cable_index(substream);
- guard(mutex)(&loopback->cable_lock);
dpcm = kzalloc_obj(*dpcm);
if (!dpcm)
return -ENOMEM;
@@ -1479,6 +1478,14 @@ static int loopback_open(struct snd_pcm_substream *substream)
return err;
}
+static int loopback_open(struct snd_pcm_substream *substream)
+{
+ struct loopback *loopback = substream->private_data;
+
+ guard(mutex)(&loopback->cable_lock);
+ return __loopback_open(substream);
+}
+
static int loopback_close(struct snd_pcm_substream *substream)
{
struct loopback *loopback = substream->private_data;
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 6/7] ALSA: core: Fix leaks at snd_card_init() error paths
2026-10-07 17:25 [PATCH v3 0/7] ALSA: Fix yet more bugs reported by Sashiko Takashi Iwai
` (4 preceding siblings ...)
2026-10-07 17:25 ` [PATCH v3 5/7] ALSA: aloop: Avoid a bad mixure of guard() and goto Takashi Iwai
@ 2026-10-07 17:25 ` Takashi Iwai
2026-10-07 17:25 ` [PATCH v3 7/7] ALSA: seq: Don't lose partial read failure Takashi Iwai
6 siblings, 0 replies; 8+ messages in thread
From: Takashi Iwai @ 2026-10-07 17:25 UTC (permalink / raw)
To: linux-sound; +Cc: linux-kernel
When the snd_card object is initialized internally in snd_card_init(),
the error path of card->value_buf allocation returns straightly as an
error without invoking the destructor, which would leak resources.
Also, the other error paths in snd_card_init() release the card object
only via put_device(), and this misses the cleanups that are done in
snd_card_disconnect(); namely, the reserved slot bit in snd_cards_lock
is never cleared, so the card index remains occupied, and the debugfs
directory created for the card is left over.
Fix them by calling snd_card_free() at the error path, which performs
both the disconnection and the release properly. As snd_card_free()
calls snd_device_free_all() internally, the explicit call is dropped,
and the error labels are unified.
Fixes: 84446536f63d ("ALSA: control: Verify put() result when in debug mode")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/core/init.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/sound/core/init.c b/sound/core/init.c
index dbe2acfa59fe..9deb5e920d0d 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -334,7 +334,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
err = snd_info_card_create(card);
if (err < 0) {
dev_err(parent, "unable to create card info\n");
- goto __error_ctl;
+ goto __error;
}
#ifdef CONFIG_SND_DEBUG
@@ -343,16 +343,16 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
#endif
#ifdef CONFIG_SND_CTL_DEBUG
card->value_buf = kmalloc_obj(*card->value_buf);
- if (!card->value_buf)
- return -ENOMEM;
+ if (!card->value_buf) {
+ err = -ENOMEM;
+ goto __error;
+ }
#endif
return 0;
- __error_ctl:
- snd_device_free_all(card);
__error:
- put_device(&card->card_dev);
- return err;
+ snd_card_free(card);
+ return err;
}
/**
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 7/7] ALSA: seq: Don't lose partial read failure
2026-10-07 17:25 [PATCH v3 0/7] ALSA: Fix yet more bugs reported by Sashiko Takashi Iwai
` (5 preceding siblings ...)
2026-10-07 17:25 ` [PATCH v3 6/7] ALSA: core: Fix leaks at snd_card_init() error paths Takashi Iwai
@ 2026-10-07 17:25 ` Takashi Iwai
6 siblings, 0 replies; 8+ messages in thread
From: Takashi Iwai @ 2026-10-07 17:25 UTC (permalink / raw)
To: linux-sound; +Cc: linux-kernel
snd_seq_read() returns an error even if one or more events have been
successfully read before the error (except for -EAGAIN case), but this
rather doesn't follow the POSIX standard that wants the processed
bytes. Change the behavior to return the processed bytes when it's
positive, instead.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/core/seq/seq_clientmgr.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index ba5619d0b0b0..0711a9e23b5f 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -480,11 +480,11 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
if (err < 0) {
if (cell)
snd_seq_fifo_cell_putback(fifo, cell);
- if (err == -EAGAIN && result > 0)
- err = 0;
}
- return (err < 0) ? err : result;
+ if (result > 0)
+ return result;
+ return err < 0 ? err : 0;
}
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread