ALSA: usb-audio: Copy string more safely

Replace strcpy() and sprintf() usages in the USB audio drivers with
the safer versions (strscpy() and scnprintf()) with the proper max
size evaluation.  Only for safety, no actual behavior change.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20250710100727.22653-103-tiwai@suse.de
This commit is contained in:
Takashi Iwai
2025-07-10 12:07:24 +02:00
parent f15be4dca2
commit 53beb4d0ed
7 changed files with 48 additions and 38 deletions

View File

@@ -616,9 +616,10 @@ static void usb_audio_make_shortname(struct usb_device *dev,
usb_string(dev, dev->descriptor.iProduct,
card->shortname, sizeof(card->shortname)) <= 0) {
/* no name available from anywhere, so use ID */
sprintf(card->shortname, "USB Device %#04x:%#04x",
USB_ID_VENDOR(chip->usb_id),
USB_ID_PRODUCT(chip->usb_id));
scnprintf(card->shortname, sizeof(card->shortname),
"USB Device %#04x:%#04x",
USB_ID_VENDOR(chip->usb_id),
USB_ID_PRODUCT(chip->usb_id));
}
strim(card->shortname);
@@ -757,8 +758,8 @@ static int snd_usb_audio_create(struct usb_interface *intf,
card->private_free = snd_usb_audio_free;
strscpy(card->driver, "USB-Audio");
sprintf(component, "USB%04x:%04x",
USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));
scnprintf(component, sizeof(component), "USB%04x:%04x",
USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));
snd_component_add(card, component);
usb_audio_make_shortname(dev, chip, quirk);

View File

@@ -1058,7 +1058,8 @@ static void set_fallback_rawmidi_names(struct snd_usb_midi2_interface *umidi)
fill_ump_ep_name(ump, dev, dev->descriptor.iProduct);
/* fill fallback name */
if (!*ump->info.name)
sprintf(ump->info.name, "USB MIDI %d", rmidi->index);
scnprintf(ump->info.name, sizeof(ump->info.name),
"USB MIDI %d", rmidi->index);
/* copy as rawmidi name if not set */
if (!*ump->core.name)
strscpy(ump->core.name, ump->info.name,

View File

@@ -674,40 +674,40 @@ static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iter
return 0;
switch (iterm->type >> 16) {
case UAC3_SELECTOR_UNIT:
strcpy(name, "Selector");
strscpy(name, "Selector", maxlen);
return 8;
case UAC3_PROCESSING_UNIT:
strcpy(name, "Process Unit");
strscpy(name, "Process Unit", maxlen);
return 12;
case UAC3_EXTENSION_UNIT:
strcpy(name, "Ext Unit");
strscpy(name, "Ext Unit", maxlen);
return 8;
case UAC3_MIXER_UNIT:
strcpy(name, "Mixer");
strscpy(name, "Mixer", maxlen);
return 5;
default:
return sprintf(name, "Unit %d", iterm->id);
return scnprintf(name, maxlen, "Unit %d", iterm->id);
}
}
switch (iterm->type & 0xff00) {
case 0x0100:
strcpy(name, "PCM");
strscpy(name, "PCM", maxlen);
return 3;
case 0x0200:
strcpy(name, "Mic");
strscpy(name, "Mic", maxlen);
return 3;
case 0x0400:
strcpy(name, "Headset");
strscpy(name, "Headset", maxlen);
return 7;
case 0x0500:
strcpy(name, "Phone");
strscpy(name, "Phone", maxlen);
return 5;
}
for (names = iterm_names; names->type; names++) {
if (names->type == iterm->type) {
strcpy(name, names->name);
strscpy(name, names->name, maxlen);
return strlen(names->name);
}
}
@@ -2804,7 +2804,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
len = get_term_name(state->chip, &iterm, namelist[i],
MAX_ITEM_NAME_LEN, 0);
if (! len)
sprintf(namelist[i], "Input %u", i);
scnprintf(namelist[i], MAX_ITEM_NAME_LEN, "Input %u", i);
}
kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval);

View File

@@ -357,21 +357,21 @@ static int scarlett_ctl_put(struct snd_kcontrol *kctl,
return changed;
}
static void scarlett_generate_name(int i, char *dst, int offsets[])
static void scarlett_generate_name(int i, char *dst, size_t size, int offsets[])
{
if (i > offsets[SCARLETT_OFFSET_MIX])
sprintf(dst, "Mix %c",
'A'+(i - offsets[SCARLETT_OFFSET_MIX] - 1));
scnprintf(dst, size, "Mix %c",
'A'+(i - offsets[SCARLETT_OFFSET_MIX] - 1));
else if (i > offsets[SCARLETT_OFFSET_ADAT])
sprintf(dst, "ADAT %d", i - offsets[SCARLETT_OFFSET_ADAT]);
scnprintf(dst, size, "ADAT %d", i - offsets[SCARLETT_OFFSET_ADAT]);
else if (i > offsets[SCARLETT_OFFSET_SPDIF])
sprintf(dst, "SPDIF %d", i - offsets[SCARLETT_OFFSET_SPDIF]);
scnprintf(dst, size, "SPDIF %d", i - offsets[SCARLETT_OFFSET_SPDIF]);
else if (i > offsets[SCARLETT_OFFSET_ANALOG])
sprintf(dst, "Analog %d", i - offsets[SCARLETT_OFFSET_ANALOG]);
scnprintf(dst, size, "Analog %d", i - offsets[SCARLETT_OFFSET_ANALOG]);
else if (i > offsets[SCARLETT_OFFSET_PCM])
sprintf(dst, "PCM %d", i - offsets[SCARLETT_OFFSET_PCM]);
scnprintf(dst, size, "PCM %d", i - offsets[SCARLETT_OFFSET_PCM]);
else
sprintf(dst, "Off");
scnprintf(dst, size, "Off");
}
static int scarlett_ctl_enum_dynamic_info(struct snd_kcontrol *kctl,
@@ -391,6 +391,7 @@ static int scarlett_ctl_enum_dynamic_info(struct snd_kcontrol *kctl,
/* generate name dynamically based on item number and offset info */
scarlett_generate_name(uinfo->value.enumerated.item,
uinfo->value.enumerated.name,
sizeof(uinfo->value.enumerated.name),
opt->offsets);
return 0;
@@ -876,7 +877,8 @@ static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer,
return err;
break;
case SCARLETT_SWITCH_IMPEDANCE:
sprintf(mx, "Input %d Impedance Switch", ctl->num);
scnprintf(mx, sizeof(mx),
"Input %d Impedance Switch", ctl->num);
err = add_new_ctl(mixer, &usb_scarlett_ctl_enum,
scarlett_ctl_enum_resume, 0x01,
0x09, ctl->num, USB_MIXER_S16, 1, mx,
@@ -885,7 +887,8 @@ static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer,
return err;
break;
case SCARLETT_SWITCH_PAD:
sprintf(mx, "Input %d Pad Switch", ctl->num);
scnprintf(mx, sizeof(mx),
"Input %d Pad Switch", ctl->num);
err = add_new_ctl(mixer, &usb_scarlett_ctl_enum,
scarlett_ctl_enum_resume, 0x01,
0x0b, ctl->num, USB_MIXER_S16, 1, mx,
@@ -894,7 +897,8 @@ static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer,
return err;
break;
case SCARLETT_SWITCH_GAIN:
sprintf(mx, "Input %d Gain Switch", ctl->num);
scnprintf(mx, sizeof(mx),
"Input %d Gain Switch", ctl->num);
err = add_new_ctl(mixer, &usb_scarlett_ctl_enum,
scarlett_ctl_enum_resume, 0x01,
0x08, ctl->num, USB_MIXER_S16, 1, mx,
@@ -960,8 +964,9 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer)
return err;
for (o = 0; o < info->matrix_out; o++) {
sprintf(mx, "Matrix %02d Mix %c Playback Volume", i+1,
o+'A');
scnprintf(mx, sizeof(mx),
"Matrix %02d Mix %c Playback Volume", i+1,
o+'A');
err = add_new_ctl(mixer, &usb_scarlett_ctl,
scarlett_ctl_resume, 0x3c, 0x00,
(i << 3) + (o & 0x07), USB_MIXER_S16,

View File

@@ -7396,13 +7396,15 @@ static int scarlett2_mux_src_enum_ctl_info(struct snd_kcontrol *kctl,
if (port_type == SCARLETT2_PORT_TYPE_MIX &&
item >= private->num_mix_out)
sprintf(uinfo->value.enumerated.name,
port->dsp_src_descr,
item - private->num_mix_out + 1);
scnprintf(uinfo->value.enumerated.name,
sizeof(uinfo->value.enumerated.name),
port->dsp_src_descr,
item - private->num_mix_out + 1);
else
sprintf(uinfo->value.enumerated.name,
port->src_descr,
item + port->src_num_offset);
scnprintf(uinfo->value.enumerated.name,
sizeof(uinfo->value.enumerated.name),
port->src_descr,
item + port->src_num_offset);
return 0;
}

View File

@@ -231,7 +231,7 @@ void snd_usb_proc_pcm_format_add(struct snd_usb_stream *stream)
char name[32];
struct snd_card *card = stream->chip->card;
sprintf(name, "stream%d", stream->pcm_index);
scnprintf(name, sizeof(name), "stream%d", stream->pcm_index);
snd_card_ro_proc_new(card, name, stream, proc_pcm_format_read);
}

View File

@@ -536,7 +536,8 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
pcm->private_free = snd_usb_audio_pcm_free;
pcm->info_flags = 0;
if (chip->pcm_devs > 0)
sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
scnprintf(pcm->name, sizeof(pcm->name), "USB Audio #%d",
chip->pcm_devs);
else
strscpy(pcm->name, "USB Audio");