mirror of
https://github.com/torvalds/linux.git
synced 2026-05-14 01:08:22 +02:00
ALSA: caiaq: Handle probe errors properly
The probe procedure of setup_card() in caiaq driver doesn't treat the
error cases gracefully, e.g. the error from snd_card_register() calls
snd_card_free() but continues. This would lead to a UAF for the
further calls like snd_usb_caiaq_control_init(), as Berk suggested in
another patch in the link below.
However, the problem is not only that; in general, this function drops
the all error handlings (as it's a void function) although its caller
can propagate an error to snd_probe(), which eventually calls
snd_card_free() as a proper error path. That said, we should treat
each error case in setup_card(), and just return the error code
promptly, which is then handled later as a fatal error in snd_probe().
This patch achieves it by changing the setup_card() to return an error
code. Also, the superfluous snd_card_free() call is removed, too.
Note that card->private_free can be set still safely at returning an
error. All called functions in card_free() have checks of the
unassigned resources or NULL checks.
Fixes: 8e3cd08ed8 ("[ALSA] caiaq - add control API and more input features")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/20260413034941.1131465-2-berkcgoksel@gmail.com
Link: https://patch.msgid.link/20260414105916.364073-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
e0da8a8cac
commit
28abd224db
|
|
@ -290,7 +290,7 @@ int snd_usb_caiaq_set_auto_msg(struct snd_usb_caiaqdev *cdev,
|
|||
tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static void setup_card(struct snd_usb_caiaqdev *cdev)
|
||||
static int setup_card(struct snd_usb_caiaqdev *cdev)
|
||||
{
|
||||
int ret;
|
||||
char val[4];
|
||||
|
|
@ -325,8 +325,10 @@ static void setup_card(struct snd_usb_caiaqdev *cdev)
|
|||
snd_usb_caiaq_send_command(cdev, EP1_CMD_READ_IO, NULL, 0);
|
||||
|
||||
if (!wait_event_timeout(cdev->ep1_wait_queue,
|
||||
cdev->control_state[0] != 0xff, HZ))
|
||||
return;
|
||||
cdev->control_state[0] != 0xff, HZ)) {
|
||||
dev_err(dev, "Read timeout for control state\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* fix up some defaults */
|
||||
if ((cdev->control_state[1] != 2) ||
|
||||
|
|
@ -347,33 +349,43 @@ static void setup_card(struct snd_usb_caiaqdev *cdev)
|
|||
cdev->spec.num_digital_audio_out +
|
||||
cdev->spec.num_digital_audio_in > 0) {
|
||||
ret = snd_usb_caiaq_audio_init(cdev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Unable to set up audio system (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (cdev->spec.num_midi_in +
|
||||
cdev->spec.num_midi_out > 0) {
|
||||
ret = snd_usb_caiaq_midi_init(cdev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Unable to set up MIDI system (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_USB_CAIAQ_INPUT
|
||||
ret = snd_usb_caiaq_input_init(cdev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Unable to set up input system (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* finally, register the card and all its sub-instances */
|
||||
ret = snd_card_register(cdev->chip.card);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "snd_card_register() returned %d\n", ret);
|
||||
snd_card_free(cdev->chip.card);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_usb_caiaq_control_init(cdev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Unable to set up control system (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void card_free(struct snd_card *card)
|
||||
|
|
@ -499,8 +511,11 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
|
|||
scnprintf(card->longname, sizeof(card->longname), "%s %s (%s)",
|
||||
cdev->vendor_name, cdev->product_name, usbpath);
|
||||
|
||||
setup_card(cdev);
|
||||
card->private_free = card_free;
|
||||
err = setup_card(cdev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
|
||||
err_kill_urb:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user