lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <3cb73dae8e8ac1a29c856dc5c86064d568003316.camel@opensource.cirrus.com>
Date: Mon, 27 Oct 2025 11:50:32 +0000
From: Maciej Strozek <mstrozek@...nsource.cirrus.com>
To: Takashi Iwai <tiwai@...e.de>, Jaroslav Kysela <perex@...ex.cz>
Cc: alsa-devel@...a-project.org, patches@...nsource.cirrus.com,
        linux-sound@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH] ALSA: sound: Increase max size of components field

W dniu pon, 27.10.2025 o godzinie 10∶04 +0100, użytkownik Takashi Iwai
napisał:
> On Thu, 23 Oct 2025 13:56:26 +0200,
> Jaroslav Kysela wrote:
> > 
> > Or, we may introduce a separate ioctl for the components string.
> > The
> > stripped components string in struct snd_ctl_card_info may have a
> > special ASCII mark like '>' at the end of string specifying the
> > availability of the complete string through another ioctl. I would
> > prefer this solution.
> > 
> > Also, the components string may be dynamic in the kernel structure
> > (pointer) to save some space. 256 bytes is not small number.
> 
> As Jaroslav suggested, we need a different solution to keep the
> compatibility.
> 
> My gut feeling is for the option to provide a new ioctl as it can be
> most straightforward, but we can discuss further which is the good
> choice.
> 

Thank you for the advice! Not sure if I understand Jaroslav's new ioctl
approach properly, can you have a look at the quick draft below and say
if this is (more or less) what you would expect? If it is OK then I
will prepare a proper V2 patch here with a corresponding change for
alsa-lib repo too.


diff --git a/include/sound/core.h b/include/sound/core.h
index 0eb2e3ee0dd5..c4e52fb1704b 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -88,7 +88,9 @@ struct snd_card {
        char irq_descr[32];             /* Interrupt description */
        char mixername[80];             /* mixer name */
        char components[256];           /* card components delimited
with
-                                                               space
*/
+                                                       space */
+       char *components_pointer;       /* full components string */
+       size_t components_pointer_len;  /* length of full components
string */
        struct module *module;          /* top-level module */
 
        void *private_data;             /* private data for soundcard
*/
@@ -297,6 +299,7 @@ int snd_card_info_init(void);
 int snd_card_add_dev_attr(struct snd_card *card,
                          const struct attribute_group *group);
 int snd_component_add(struct snd_card *card, const char *component);
+int snd_card_add_components(struct snd_card *card, const char
*component);
 int snd_card_file_add(struct snd_card *card, struct file *file);
 int snd_card_file_remove(struct snd_card *card, struct file *file);
 
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index c302698fb685..7d53f6da59e2 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -1069,7 +1069,12 @@ struct snd_ctl_card_info {
        unsigned char longname[80];     /* name + info text about
soundcard */
        unsigned char reserved_[16];    /* reserved for future (was ID
of mixer) */
        unsigned char mixername[80];    /* visual mixer identification
*/
-       unsigned char components[256];  /* card components / fine
identification, delimited with one space (AC97 etc..) */
+       unsigned char components[128];  /* card components / fine
identification, delimited with one space (AC97 etc..) */
+};
+
+struct snd_ctl_card_components {
+       int len;
+       unsigned char *components;
 };
 
 typedef int __bitwise snd_ctl_elem_type_t;
@@ -1198,6 +1203,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_COMPONENTS        _IOWR('U', 0x02, struct
snd_ctl_card_components)
 #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 9c3fd5113a61..5a96a2ed4a45 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -886,6 +886,23 @@ static int snd_ctl_card_info(struct snd_card
*card, struct snd_ctl_file * ctl,
        return 0;
 }
 
+static int snd_ctl_card_components(struct snd_card *card, void __user
*arg)
+{
+       struct snd_ctl_card_components *info __free(kfree) = NULL;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       scoped_guard(rwsem_read, &snd_ioctl_rwsem) {
+               strscpy(info->components, card->components, info->len);
+       }
+
+       if (copy_to_user(arg, info, sizeof(struct
snd_ctl_card_components)))
+               return -EFAULT;
+       return 0;
+}
+
 static int snd_ctl_elem_list(struct snd_card *card,
                             struct snd_ctl_elem_list *list)
 {
@@ -1914,6 +1931,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_COMPONENTS:
+               return snd_ctl_card_components(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 6459809ed364..edb7b28d8177 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -416,7 +416,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),
@@ -445,6 +445,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_COMPONENTS:
        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 c372b3228785..a7ac62ace1dc 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -587,6 +587,9 @@ static int snd_card_do_free(struct snd_card *card)
        snd_device_free_all(card);
        if (card->private_free)
                card->private_free(card);
+       kfree(card->components_pointer);
+       card->components_pointer = NULL;
+       card->components_pointer_len = 0;
        if (snd_info_card_free(card) < 0) {
                dev_warn(card->dev, "unable to free card info\n");
                /* Not fatal error */
@@ -714,7 +717,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;
 
@@ -1023,11 +1026,13 @@ 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;
        int len = strlen(component);
+       int new_len;
+       char *buffer;
 
        ptr = strstr(card->components, component);
        if (ptr != NULL) {
@@ -1035,8 +1040,28 @@ int snd_component_add(struct snd_card *card,
const char *component)
                        return 1;
        }
        if (strlen(card->components) + 1 + len + 1 > sizeof(card-
>components)) {
-               snd_BUG();
-               return -ENOMEM;
+               if (card->components[sizeof(card->components) - 2] !=
'>') {
+                       // TODO: figure out if it is not deleting a
character from an existing component
+                       card->components[sizeof(card->components) - 2]
= '>';
+                       card->components[sizeof(card->components) - 1]
= '\0';
+               }
+
+               if (card->components_pointer) {
+                       new_len = strlen(card->components_pointer) + 1
+ len;
+                       buffer = krealloc(card->components_pointer,
new_len, GFP_KERNEL);
+               } else {
+                       new_len = strlen(card->components) + 1 + len;
+                       buffer = kmalloc(new_len, GFP_KERNEL);
+                       memcpy(buffer, card->components, strlen(card-
>components));
+               }
+               if (!buffer)
+                       return -ENOMEM;
+
+               strcat(buffer, component);
+
+               card->components_pointer = buffer;
+               card->components_pointer_len = new_len;
+
        }
        if (card->components[0] != '\0')
                strcat(card->components, " ");

-- 
Regards,
Maciej

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ