[PATCH v2] ALSA: jack: Fix jack control cleanup on error paths
From: Sreeraj S Kurup
Date: Sun Nov 15 2026 - 06:43:54 EST
snd_jack_new() creates an ALSA jack control before allocating
the jack structure.
If a later allocation or device registration fails, the
function returns without removing the previously created
control. This leaves the control attached to the sound card
and can cause invalid list operations during card teardown.
Initialize the control list in snd_jack_kctl_new() so that
the private_free callback can safely remove the list entry.
Route all failure paths in snd_jack_new() through common
cleanup labels to remove the control and free allocated
resources.
Fixes: 4e3f0dc65883 ("ALSA: jack: extend snd_jack_new to support phantom jack")
Signed-off-by: Sreeraj S Kurup <sreekuttan2156239@xxxxxxxxx>
---
v2:
- Initialize the jack control list to prevent invalid list operations during cleanup.
- Handle cleanup of the jack control on all error paths in "snd_jack_new()".
sound/core/jack.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/sound/core/jack.c b/sound/core/jack.c
index af2dc2cfbe19..c35a92390527 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -487,6 +487,7 @@ static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const cha
jack_kctl->kctl = kctl;
jack_kctl->mask_bits = mask;
+ INIT_LIST_HEAD(&jack_kctl->list);
kctl->private_data = jack_kctl;
kctl->private_free = snd_jack_kctl_private_free;
@@ -555,13 +556,15 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
}
jack = kzalloc_obj(struct snd_jack);
- if (jack == NULL)
- return -ENOMEM;
+ if (!jack) {
+ err = -ENOMEM;
+ goto fail_kctl;
+ }
jack->id = kstrdup(id, GFP_KERNEL);
if (jack->id == NULL) {
- kfree(jack);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto fail_jack;
}
#ifdef CONFIG_SND_JACK_INPUT_DEV
@@ -607,8 +610,13 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
#ifdef CONFIG_SND_JACK_INPUT_DEV
input_free_device(jack->input_dev);
#endif
+fail_jack:
kfree(jack->id);
kfree(jack);
+fail_kctl:
+ if (jack_kctl)
+ snd_ctl_remove(card, jack_kctl->kctl);
+
return err;
}
EXPORT_SYMBOL(snd_jack_new);
--
2.55.0