[RFC PATCH 1/8] ALSA: core: keep non-ASCII bytes out of the card id

From: Luca Rodenhäuser

Date: Tue Sep 15 2026 - 12:11:01 EST


copy_valid_id_string() filters the source string through safe_ascii_char()
everywhere but one place. When the name it derives the id from starts with
a digit, it prepends a letter taken from the original string, guarded only
by isalpha():

if (isdigit(*nid))
*id++ = isalpha(*src) ? *src : 'D';

The kernel ctype table classifies the Latin-1 high bytes as letters, so
isalpha(0xc3) is true, and that byte is copied into card->id unchanged.

A USB device is enough to trigger it: usb_audio_make_shortname() copies
dev->product into card->shortname, so a product name whose first
ASCII-alphanumeric byte is a digit, such as "\xc3\x84" "3000", leaves
card->id starting with 0xc3.

That matters because card->id is an identifier, not a display name. It
becomes a directory name under /proc/asound, it is handed to user space in
snd_ctl_card_info::id, and it is the handle in alsa-lib's hw:CARD=<id>.
The sysfs id_store() path rejects anything outside
safe_ascii_char() || '_' || '-', so the kernel currently produces ids that
it refuses to accept from user space.

Guard the byte with isascii() as well. A non-ASCII first byte then falls
back to 'D', which is what the same line already does for anything that is
not a letter.

Assisted-by: LLM
Signed-off-by: Luca Rodenhäuser <otzelot2021@xxxxxxxxxx>
---
sound/core/init.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/sound/core/init.c b/sound/core/init.c
index 9693e646b3..2b33dd7b42 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -707,8 +707,13 @@ static void copy_valid_id_string(struct snd_card *card, const char *src,

while (*nid && !safe_ascii_char(*nid))
nid++;
- if (isdigit(*nid))
- *id++ = isalpha(*src) ? *src : 'D';
+ if (isdigit(*nid)) {
+ /* isalpha() alone is not enough: the ctype table classifies the
+ * Latin-1 high bytes as letters, so a non-ASCII first byte would
+ * end up in the id, which must stay alphanumeric ASCII.
+ */
+ *id++ = isascii(*src) && isalpha(*src) ? *src : 'D';
+ }
while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) {
if (safe_ascii_char(*nid))
*id++ = *nid;
--
2.43.0