* [PATCH v5 1/2] ALSA: control: tidy up whitespaces @ 2026-07-06 14:14 Maciej Strozek 2026-07-06 14:14 ` [PATCH v5 2/2] ALSA: control: add ioctl to retrieve full card components Maciej Strozek 0 siblings, 1 reply; 3+ messages in thread From: Maciej Strozek @ 2026-07-06 14:14 UTC (permalink / raw) To: Takashi Iwai, Jaroslav Kysela Cc: linux-sound, linux-kernel, alsa-devel, patches, Maciej Strozek Clean up trailing whitespace in preparation for the card components changes. Signed-off-by: Maciej Strozek <mstrozek@opensource.cirrus.com> --- added in v3, no changes since then --- sound/core/control_compat.c | 2 +- sound/core/init.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 16bc80555f26..4ad571087ff5 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -417,7 +417,7 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, break; } return snd_ctl_elem_add(file, data, replace); -} +} enum { SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct snd_ctl_elem_list32), diff --git a/sound/core/init.c b/sound/core/init.c index 56dde5bd73c4..1ff340ee6884 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -722,7 +722,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src, int len, loops; bool is_default = false; char *id; - + copy_valid_id_string(card, src, nid); id = card->id; @@ -1031,7 +1031,7 @@ int __init snd_card_info_init(void) * * Return: Zero otherwise a negative error code. */ - + int snd_component_add(struct snd_card *card, const char *component) { char *ptr; -- 2.48.1 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v5 2/2] ALSA: control: add ioctl to retrieve full card components 2026-07-06 14:14 [PATCH v5 1/2] ALSA: control: tidy up whitespaces Maciej Strozek @ 2026-07-06 14:14 ` Maciej Strozek 2026-07-15 14:51 ` Takashi Iwai 0 siblings, 1 reply; 3+ messages in thread From: Maciej Strozek @ 2026-07-06 14:14 UTC (permalink / raw) To: Takashi Iwai, Jaroslav Kysela Cc: linux-sound, linux-kernel, alsa-devel, patches, Maciej Strozek The fixed-size components field in SNDRV_CTL_IOCTL_CARD_INFO can be too small on systems with many audio devices. Keep the existing struct snd_ctl_card_info ABI intact and add a new ioctl SNDRV_CTL_IOCTL_CARD_BYTES that carries a variable-length payload selected by a type discriminator. The first defined type SND_CTL_CARD_BTYPE_COMPONENTS returns the full components string. The ioctl is designed to be reused for other variable-length card payloads in the future. The user-space caller may set data_allocated == 0 (or data == NULL) to query the required length; otherwise the kernel copies the payload into the user buffer and writes back the actual length in data_len. When the legacy components field in struct snd_ctl_card_info is truncated, '>' is written just before the NUL terminator to signal to user-space that the full string is available via the new ioctl. card->components is now dynamically allocated and grown in 32 byte increments via krealloc(), capped at 512 bytes. Link: https://github.com/alsa-project/alsa-lib/pull/494 Suggested-by: Jaroslav Kysela <perex@perex.cz> Suggested-by: Takashi Iwai <tiwai@suse.com> Signed-off-by: Maciej Strozek <mstrozek@opensource.cirrus.com> --- Changes for v5: - use __u64 and u64_to_user_ptr() instead of 32bit compat layer - handle a NULL card->components Changes for v4: - replaced snd_ctl_card_components with snd_ctl_card_bytes for possible future extensions - support query mode (data_allocated == 0 or data == NULL) - added compat 32-bit - renamed card->components_ptr / components_ptr_alloc_size to card->components / components_alloc_size Changes for v3: - change components field to a dynamic array resizable in 32 byte increments - removed SNDRV_CTL_COMPONENTS_LEN define - sanity check if 'components' requests more than 512 bytes - added a commit to clean up trailing whitespaces - alsa-utils link no longer needed Changes for v2: - do not modify existing card->components field - add a new ioctl and struct to keep the full components string - handle the split/trim in snd_ctl_card_info() --- include/sound/core.h | 4 +-- include/uapi/sound/asound.h | 22 ++++++++++++- sound/core/control.c | 62 ++++++++++++++++++++++++++++++++++++- sound/core/control_compat.c | 1 + sound/core/init.c | 34 +++++++++++++++++--- 5 files changed, 114 insertions(+), 9 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index 404785b7d885..2ca24ac7e37f 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -108,8 +108,8 @@ struct snd_card { char longname[80]; /* name of this soundcard */ char irq_descr[32]; /* Interrupt description */ char mixername[80]; /* mixer name */ - char components[128]; /* card components delimited with - space */ + char *components; /* card components, space-delimited */ + unsigned int components_alloc_size; /* current allocation size of components */ struct module *module; /* top-level module */ void *private_data; /* private data for soundcard */ diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index d3ce75ba938a..500599213f93 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -1058,7 +1058,7 @@ struct snd_timer_tread { * * ****************************************************************************/ -#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 9) +#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10) struct snd_ctl_card_info { int card; /* card number */ @@ -1072,6 +1072,25 @@ struct snd_ctl_card_info { unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */ }; +/* + * Card components can exceed the fixed 128 bytes in snd_ctl_card_info. + * Use SNDRV_CTL_IOCTL_CARD_BYTES with type SND_CTL_CARD_BTYPE_COMPONENTS + * to retrieve the full string. + */ + +/* Type values for struct snd_ctl_card_bytes::type */ +enum { + SND_CTL_CARD_BTYPE_COMPONENTS = 1, /* full card components string */ +}; + +struct snd_ctl_card_bytes { + __u32 type; /* SND_CTL_CARD_BTYPE_* */ + __u32 data_allocated; /* size of @data buffer in bytes */ + __u32 data_len; /* in/out: actual data length in bytes */ + __u32 reserved; /* explicit pad */ + __u64 data; /* user buffer (pointer stored as __u64) */ +}; + typedef int __bitwise snd_ctl_elem_type_t; #define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */ #define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */ @@ -1198,6 +1217,7 @@ struct snd_ctl_tlv { #define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int) #define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info) +#define SNDRV_CTL_IOCTL_CARD_BYTES _IOWR('U', 0x02, struct snd_ctl_card_bytes) #define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list) #define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info) #define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value) diff --git a/sound/core/control.c b/sound/core/control.c index 7a8dc506221e..5e9f68c96f4b 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -876,23 +876,81 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, { struct snd_ctl_card_info *info __free(kfree) = kzalloc(sizeof(*info), GFP_KERNEL); + ssize_t n; if (! info) return -ENOMEM; + + static_assert(sizeof(info->components) >= 2); + scoped_guard(rwsem_read, &snd_ioctl_rwsem) { + const char *components = card->components; + + if (!components) + components = ""; + info->card = card->number; strscpy(info->id, card->id, sizeof(info->id)); strscpy(info->driver, card->driver, sizeof(info->driver)); strscpy(info->name, card->shortname, sizeof(info->name)); strscpy(info->longname, card->longname, sizeof(info->longname)); strscpy(info->mixername, card->mixername, sizeof(info->mixername)); - strscpy(info->components, card->components, sizeof(info->components)); + n = strscpy(info->components, components, sizeof(info->components)); + if (n < 0) // mark the truncation with '>' before NULL terminator + info->components[sizeof(info->components) - 2] = '>'; } if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) return -EFAULT; return 0; } +static int snd_ctl_card_bytes(struct snd_card *card, + struct snd_ctl_card_bytes *info, + unsigned int __user *data_len_out) +{ + unsigned int data_len; + + switch (info->type) { + case SND_CTL_CARD_BTYPE_COMPONENTS: + scoped_guard(rwsem_read, &snd_ioctl_rwsem) { + const char *components = card->components; + + if (!components) + components = ""; + + data_len = strlen(components) + 1; + + if (!info->data || info->data_allocated == 0) + break; + + if (info->data_allocated < data_len) + return -ENOMEM; + + if (copy_to_user(u64_to_user_ptr(info->data), components, data_len)) + return -EFAULT; + } + break; + default: + return -EINVAL; + } + + if (put_user(data_len, data_len_out)) + return -EFAULT; + + return 0; +} + +static int snd_ctl_card_bytes_user(struct snd_card *card, + struct snd_ctl_card_bytes __user *_info) +{ + struct snd_ctl_card_bytes info; + + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + + return snd_ctl_card_bytes(card, &info, &_info->data_len); +} + static int snd_ctl_elem_list(struct snd_card *card, struct snd_ctl_elem_list *list) { @@ -1990,6 +2048,8 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0; case SNDRV_CTL_IOCTL_CARD_INFO: return snd_ctl_card_info(card, ctl, cmd, argp); + case SNDRV_CTL_IOCTL_CARD_BYTES: + return snd_ctl_card_bytes_user(card, argp); case SNDRV_CTL_IOCTL_ELEM_LIST: return snd_ctl_elem_list_user(card, argp); case SNDRV_CTL_IOCTL_ELEM_INFO: diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 4ad571087ff5..f14d9f5e94be 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -446,6 +446,7 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns switch (cmd) { case SNDRV_CTL_IOCTL_PVERSION: case SNDRV_CTL_IOCTL_CARD_INFO: + case SNDRV_CTL_IOCTL_CARD_BYTES: case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: case SNDRV_CTL_IOCTL_POWER: case SNDRV_CTL_IOCTL_POWER_STATE: diff --git a/sound/core/init.c b/sound/core/init.c index 1ff340ee6884..15a8209469c7 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -590,6 +590,9 @@ static int snd_card_do_free(struct snd_card *card) snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE); #endif snd_device_free_all(card); + kfree(card->components); + card->components = NULL; + card->components_alloc_size = 0; if (card->private_free) card->private_free(card); #ifdef CONFIG_SND_CTL_DEBUG @@ -1036,16 +1039,37 @@ int snd_component_add(struct snd_card *card, const char *component) { char *ptr; int len = strlen(component); + unsigned int cur_len, need_len; - ptr = strstr(card->components, component); - if (ptr != NULL) { - if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */ - return 1; + if (card->components) { + ptr = strstr(card->components, component); + if (ptr) { + if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */ + return 1; + } + cur_len = strlen(card->components) + 1; + } else { + cur_len = 0; } - if (strlen(card->components) + 1 + len + 1 > sizeof(card->components)) { + + need_len = cur_len + len + 1; + if (need_len > 512) { snd_BUG(); return -ENOMEM; } + + if (need_len > card->components_alloc_size) { + unsigned int new_alloc = roundup(need_len, 32); + + ptr = krealloc(card->components, new_alloc, GFP_KERNEL); + if (!ptr) + return -ENOMEM; + if (!card->components) + ptr[0] = '\0'; + card->components = ptr; + card->components_alloc_size = new_alloc; + } + if (card->components[0] != '\0') strcat(card->components, " "); strcat(card->components, component); -- 2.48.1 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v5 2/2] ALSA: control: add ioctl to retrieve full card components 2026-07-06 14:14 ` [PATCH v5 2/2] ALSA: control: add ioctl to retrieve full card components Maciej Strozek @ 2026-07-15 14:51 ` Takashi Iwai 0 siblings, 0 replies; 3+ messages in thread From: Takashi Iwai @ 2026-07-15 14:51 UTC (permalink / raw) To: Maciej Strozek Cc: Takashi Iwai, Jaroslav Kysela, linux-sound, linux-kernel, alsa-devel, patches On Mon, 06 Jul 2026 16:14:57 +0200, Maciej Strozek wrote: > > The fixed-size components field in SNDRV_CTL_IOCTL_CARD_INFO can be too > small on systems with many audio devices. > > Keep the existing struct snd_ctl_card_info ABI intact and add a new > ioctl SNDRV_CTL_IOCTL_CARD_BYTES that carries a variable-length payload > selected by a type discriminator. The first defined type > SND_CTL_CARD_BTYPE_COMPONENTS returns the full components string. The > ioctl is designed to be reused for other variable-length card payloads > in the future. > > The user-space caller may set data_allocated == 0 (or data == NULL) to > query the required length; otherwise the kernel copies the payload into > the user buffer and writes back the actual length in data_len. > > When the legacy components field in struct snd_ctl_card_info is > truncated, '>' is written just before the NUL terminator to signal to > user-space that the full string is available via the new ioctl. > > card->components is now dynamically allocated and grown in 32 byte > increments via krealloc(), capped at 512 bytes. > > Link: https://github.com/alsa-project/alsa-lib/pull/494 > Suggested-by: Jaroslav Kysela <perex@perex.cz> > Suggested-by: Takashi Iwai <tiwai@suse.com> > Signed-off-by: Maciej Strozek <mstrozek@opensource.cirrus.com> > --- > Changes for v5: > - use __u64 and u64_to_user_ptr() instead of 32bit compat layer > - handle a NULL card->components > Changes for v4: > - replaced snd_ctl_card_components with snd_ctl_card_bytes for possible > future extensions > - support query mode (data_allocated == 0 or data == NULL) > - added compat 32-bit > - renamed card->components_ptr / components_ptr_alloc_size to > card->components / components_alloc_size > Changes for v3: > - change components field to a dynamic array resizable in 32 byte > increments > - removed SNDRV_CTL_COMPONENTS_LEN define > - sanity check if 'components' requests more than 512 bytes > - added a commit to clean up trailing whitespaces > - alsa-utils link no longer needed > Changes for v2: > - do not modify existing card->components field > - add a new ioctl and struct to keep the full components string > - handle the split/trim in snd_ctl_card_info() > --- > include/sound/core.h | 4 +-- > include/uapi/sound/asound.h | 22 ++++++++++++- > sound/core/control.c | 62 ++++++++++++++++++++++++++++++++++++- > sound/core/control_compat.c | 1 + > sound/core/init.c | 34 +++++++++++++++++--- > 5 files changed, 114 insertions(+), 9 deletions(-) > > diff --git a/include/sound/core.h b/include/sound/core.h > index 404785b7d885..2ca24ac7e37f 100644 > --- a/include/sound/core.h > +++ b/include/sound/core.h > @@ -108,8 +108,8 @@ struct snd_card { > char longname[80]; /* name of this soundcard */ > char irq_descr[32]; /* Interrupt description */ > char mixername[80]; /* mixer name */ > - char components[128]; /* card components delimited with > - space */ > + char *components; /* card components, space-delimited */ > + unsigned int components_alloc_size; /* current allocation size of components */ > struct module *module; /* top-level module */ > > void *private_data; /* private data for soundcard */ > diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h > index d3ce75ba938a..500599213f93 100644 > --- a/include/uapi/sound/asound.h > +++ b/include/uapi/sound/asound.h > @@ -1058,7 +1058,7 @@ struct snd_timer_tread { > * * > ****************************************************************************/ > > -#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 9) > +#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10) > > struct snd_ctl_card_info { > int card; /* card number */ > @@ -1072,6 +1072,25 @@ struct snd_ctl_card_info { > unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */ > }; > > +/* > + * Card components can exceed the fixed 128 bytes in snd_ctl_card_info. > + * Use SNDRV_CTL_IOCTL_CARD_BYTES with type SND_CTL_CARD_BTYPE_COMPONENTS > + * to retrieve the full string. > + */ > + > +/* Type values for struct snd_ctl_card_bytes::type */ > +enum { > + SND_CTL_CARD_BTYPE_COMPONENTS = 1, /* full card components string */ > +}; > + > +struct snd_ctl_card_bytes { > + __u32 type; /* SND_CTL_CARD_BTYPE_* */ > + __u32 data_allocated; /* size of @data buffer in bytes */ > + __u32 data_len; /* in/out: actual data length in bytes */ > + __u32 reserved; /* explicit pad */ > + __u64 data; /* user buffer (pointer stored as __u64) */ > +}; > + > typedef int __bitwise snd_ctl_elem_type_t; > #define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */ > #define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */ > @@ -1198,6 +1217,7 @@ struct snd_ctl_tlv { > > #define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int) > #define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info) > +#define SNDRV_CTL_IOCTL_CARD_BYTES _IOWR('U', 0x02, struct snd_ctl_card_bytes) > #define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list) > #define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info) > #define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value) > diff --git a/sound/core/control.c b/sound/core/control.c > index 7a8dc506221e..5e9f68c96f4b 100644 > --- a/sound/core/control.c > +++ b/sound/core/control.c > @@ -876,23 +876,81 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, > { > struct snd_ctl_card_info *info __free(kfree) = > kzalloc(sizeof(*info), GFP_KERNEL); > + ssize_t n; > > if (! info) > return -ENOMEM; > + > + static_assert(sizeof(info->components) >= 2); > + > scoped_guard(rwsem_read, &snd_ioctl_rwsem) { > + const char *components = card->components; > + > + if (!components) > + components = ""; > + > info->card = card->number; > strscpy(info->id, card->id, sizeof(info->id)); > strscpy(info->driver, card->driver, sizeof(info->driver)); > strscpy(info->name, card->shortname, sizeof(info->name)); > strscpy(info->longname, card->longname, sizeof(info->longname)); > strscpy(info->mixername, card->mixername, sizeof(info->mixername)); > - strscpy(info->components, card->components, sizeof(info->components)); > + n = strscpy(info->components, components, sizeof(info->components)); > + if (n < 0) // mark the truncation with '>' before NULL terminator > + info->components[sizeof(info->components) - 2] = '>'; > } > if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) > return -EFAULT; > return 0; > } > > +static int snd_ctl_card_bytes(struct snd_card *card, > + struct snd_ctl_card_bytes *info, > + unsigned int __user *data_len_out) > +{ > + unsigned int data_len; > + > + switch (info->type) { > + case SND_CTL_CARD_BTYPE_COMPONENTS: > + scoped_guard(rwsem_read, &snd_ioctl_rwsem) { > + const char *components = card->components; > + > + if (!components) > + components = ""; > + > + data_len = strlen(components) + 1; > + > + if (!info->data || info->data_allocated == 0) > + break; > + > + if (info->data_allocated < data_len) > + return -ENOMEM; > + > + if (copy_to_user(u64_to_user_ptr(info->data), components, data_len)) > + return -EFAULT; > + } > + break; > + default: > + return -EINVAL; > + } > + > + if (put_user(data_len, data_len_out)) > + return -EFAULT; > + > + return 0; > +} > + > +static int snd_ctl_card_bytes_user(struct snd_card *card, > + struct snd_ctl_card_bytes __user *_info) > +{ > + struct snd_ctl_card_bytes info; > + > + if (copy_from_user(&info, _info, sizeof(info))) > + return -EFAULT; > + > + return snd_ctl_card_bytes(card, &info, &_info->data_len); > +} > + > static int snd_ctl_elem_list(struct snd_card *card, > struct snd_ctl_elem_list *list) > { > @@ -1990,6 +2048,8 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg > return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0; > case SNDRV_CTL_IOCTL_CARD_INFO: > return snd_ctl_card_info(card, ctl, cmd, argp); > + case SNDRV_CTL_IOCTL_CARD_BYTES: > + return snd_ctl_card_bytes_user(card, argp); > case SNDRV_CTL_IOCTL_ELEM_LIST: > return snd_ctl_elem_list_user(card, argp); > case SNDRV_CTL_IOCTL_ELEM_INFO: > diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c > index 4ad571087ff5..f14d9f5e94be 100644 > --- a/sound/core/control_compat.c > +++ b/sound/core/control_compat.c > @@ -446,6 +446,7 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns > switch (cmd) { > case SNDRV_CTL_IOCTL_PVERSION: > case SNDRV_CTL_IOCTL_CARD_INFO: > + case SNDRV_CTL_IOCTL_CARD_BYTES: > case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: > case SNDRV_CTL_IOCTL_POWER: > case SNDRV_CTL_IOCTL_POWER_STATE: > diff --git a/sound/core/init.c b/sound/core/init.c > index 1ff340ee6884..15a8209469c7 100644 > --- a/sound/core/init.c > +++ b/sound/core/init.c > @@ -590,6 +590,9 @@ static int snd_card_do_free(struct snd_card *card) > snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE); > #endif > snd_device_free_all(card); > + kfree(card->components); > + card->components = NULL; > + card->components_alloc_size = 0; > if (card->private_free) > card->private_free(card); > #ifdef CONFIG_SND_CTL_DEBUG > @@ -1036,16 +1039,37 @@ int snd_component_add(struct snd_card *card, const char *component) > { > char *ptr; > int len = strlen(component); > + unsigned int cur_len, need_len; > > - ptr = strstr(card->components, component); > - if (ptr != NULL) { > - if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */ > - return 1; > + if (card->components) { > + ptr = strstr(card->components, component); > + if (ptr) { > + if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */ > + return 1; > + } > + cur_len = strlen(card->components) + 1; > + } else { > + cur_len = 0; > } > - if (strlen(card->components) + 1 + len + 1 > sizeof(card->components)) { > + > + need_len = cur_len + len + 1; > + if (need_len > 512) { > snd_BUG(); > return -ENOMEM; > } > + > + if (need_len > card->components_alloc_size) { > + unsigned int new_alloc = roundup(need_len, 32); > + > + ptr = krealloc(card->components, new_alloc, GFP_KERNEL); > + if (!ptr) > + return -ENOMEM; > + if (!card->components) > + ptr[0] = '\0'; > + card->components = ptr; > + card->components_alloc_size = new_alloc; > + } > + > if (card->components[0] != '\0') > strcat(card->components, " "); > strcat(card->components, component); I believe we need to protect snd_component_add() against the racy ioctl? Otherwise the existing guard in your patch makes no sense. thanks, Takashi ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-15 14:52 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-06 14:14 [PATCH v5 1/2] ALSA: control: tidy up whitespaces Maciej Strozek 2026-07-06 14:14 ` [PATCH v5 2/2] ALSA: control: add ioctl to retrieve full card components Maciej Strozek 2026-07-15 14:51 ` Takashi Iwai
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.