VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-46088

CVE-2026-46088

Description

In the Linux kernel, the following vulnerability has been resolved:

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

snd_ctl_elem_init_enum_names() advances pointer p through the names buffer while decrementing buf_len. If buf_len reaches zero but items remain, the next iteration calls strnlen(p, 0).

While strnlen(p, 0) returns 0 and would hit the existing name_len == 0 error path, CONFIG_FORTIFY_SOURCE's fortified strnlen() first checks maxlen against __builtin_dynamic_object_size(). When Clang loses track of p's object size inside the loop, this triggers a BRK exception panic before the return value is examined.

Add a buf_len == 0 guard at the loop entry to prevent calling fortified strnlen() on an exhausted buffer.

Found by kernel fuzz testing through Xiaomi Smartphone.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Missing buf_len validation in snd_ctl_elem_init_enum_names() triggers a panic when fortified strnlen() is called on an exhausted buffer.

Vulnerability

In the Linux kernel, the function snd_ctl_elem_init_enum_names() in sound/core/control.c iterates through a names buffer while decrementing buf_len. If buf_len reaches zero but items remain, the next iteration calls strnlen(p, 0). Under CONFIG_FORTIFY_SOURCE, the fortified strnlen() checks maxlen against __builtin_dynamic_object_size(), which can trigger a BRK exception panic if the compiler loses track of the object size. This affects versions prior to the patched commit e0da8a8cac74 (introduced during the 6.1-rc cycle).

Exploitation

An attacker would need the ability to trigger the vulnerable code path through a crafted SNDRV_CTL_IOCTL_ELEM_ADD or SNDRV_CTL_IOCTL_ELEM_REPLACE ioctl call that provides an enumeration control with a names buffer whose size is exactly exhausted by the parsing loop. This requires local access to the ALSA control interface and the ability to create or modify control elements (typically root or CAP_SYS_ADMIN). The fuzz testing scenario that discovered the bug required repeated manipulation of control element names to force buf_len to zero at the loop entry.

Impact

A successful exploit causes a kernel panic (BRK exception) due to the fortified strnlen() check, leading to a denial of service (system crash). There is no evidence of privilege escalation or data corruption. The panic occurs before the existing name_len == 0 error path can return gracefully.

Mitigation

The fix is included in commit e0da8a8cac74 ("ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()"), which adds a buf_len == 0 guard at the loop entry. This commit has been backported to stable kernel trees as of May 2026 [1]. Users should update to a kernel containing this fix. No workaround is available short of applying the patch or disabling CONFIG_FORTIFY_SOURCE (not recommended).

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

10
e0da8a8cac74

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZiqing ChenApr 14, 2026Fixed in 7.1-rc1via kernel-cna
1 file changed · +4 1
  • sound/core/control.c+4 1 modified
    diff --git a/sound/core/control.c b/sound/core/control.c
    index 374e703d15a91c..5e51857635e62a 100644
    --- a/sound/core/control.c
    +++ b/sound/core/control.c
    @@ -1648,6 +1648,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
     	/* check that there are enough valid names */
     	p = names;
     	for (i = 0; i < ue->info.value.enumerated.items; ++i) {
    +		if (buf_len == 0) {
    +			kvfree(names);
    +			return -EINVAL;
    +		}
     		name_len = strnlen(p, buf_len);
     		if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
     			kvfree(names);
    -- 
    cgit 1.3-korg
    
    
    
1fbe46d2b727

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZiqing ChenApr 14, 2026Fixed in 6.6.140via kernel-cna
1 file changed · +4 1
  • sound/core/control.c+4 1 modified
    diff --git a/sound/core/control.c b/sound/core/control.c
    index dd4bdb39782cda..3b464260795e9d 100644
    --- a/sound/core/control.c
    +++ b/sound/core/control.c
    @@ -1672,6 +1672,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
     	/* check that there are enough valid names */
     	p = names;
     	for (i = 0; i < ue->info.value.enumerated.items; ++i) {
    +		if (buf_len == 0) {
    +			kvfree(names);
    +			return -EINVAL;
    +		}
     		name_len = strnlen(p, buf_len);
     		if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
     			kvfree(names);
    -- 
    cgit 1.3-korg
    
    
    
8ba0214c3dd3

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZiqing ChenApr 14, 2026Fixed in 6.12.86via kernel-cna
1 file changed · +4 1
  • sound/core/control.c+4 1 modified
    diff --git a/sound/core/control.c b/sound/core/control.c
    index 0ddade871b524a..6ceb5f977fcddb 100644
    --- a/sound/core/control.c
    +++ b/sound/core/control.c
    @@ -1574,6 +1574,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
     	/* check that there are enough valid names */
     	p = names;
     	for (i = 0; i < ue->info.value.enumerated.items; ++i) {
    +		if (buf_len == 0) {
    +			kvfree(names);
    +			return -EINVAL;
    +		}
     		name_len = strnlen(p, buf_len);
     		if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
     			kvfree(names);
    -- 
    cgit 1.3-korg
    
    
    
654c818a69c2

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZiqing ChenApr 14, 2026Fixed in 6.18.27via kernel-cna
1 file changed · +4 1
  • sound/core/control.c+4 1 modified
    diff --git a/sound/core/control.c b/sound/core/control.c
    index 9c3fd5113a6173..c714f2e5596b38 100644
    --- a/sound/core/control.c
    +++ b/sound/core/control.c
    @@ -1574,6 +1574,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
     	/* check that there are enough valid names */
     	p = names;
     	for (i = 0; i < ue->info.value.enumerated.items; ++i) {
    +		if (buf_len == 0) {
    +			kvfree(names);
    +			return -EINVAL;
    +		}
     		name_len = strnlen(p, buf_len);
     		if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
     			kvfree(names);
    -- 
    cgit 1.3-korg
    
    
    
82012fd3e78a

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZiqing ChenApr 14, 2026Fixed in 7.0.4via kernel-cna
1 file changed · +4 1
  • sound/core/control.c+4 1 modified
    diff --git a/sound/core/control.c b/sound/core/control.c
    index 934e84e9383806..0b594f89bfb299 100644
    --- a/sound/core/control.c
    +++ b/sound/core/control.c
    @@ -1574,6 +1574,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
     	/* check that there are enough valid names */
     	p = names;
     	for (i = 0; i < ue->info.value.enumerated.items; ++i) {
    +		if (buf_len == 0) {
    +			kvfree(names);
    +			return -EINVAL;
    +		}
     		name_len = strnlen(p, buf_len);
     		if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
     			kvfree(names);
    -- 
    cgit 1.3-korg
    
    
    
1fbe46d2b727

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

1 file changed · +4 1
  • sound/core/control.c+4 1 modified
    diff --git a/sound/core/control.c b/sound/core/control.c
    index dd4bdb39782cda..3b464260795e9d 100644
    --- a/sound/core/control.c
    +++ b/sound/core/control.c
    @@ -1672,6 +1672,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
     	/* check that there are enough valid names */
     	p = names;
     	for (i = 0; i < ue->info.value.enumerated.items; ++i) {
    +		if (buf_len == 0) {
    +			kvfree(names);
    +			return -EINVAL;
    +		}
     		name_len = strnlen(p, buf_len);
     		if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
     			kvfree(names);
    -- 
    cgit 1.3-korg
    
    
    
654c818a69c2

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

1 file changed · +4 1
  • sound/core/control.c+4 1 modified
    diff --git a/sound/core/control.c b/sound/core/control.c
    index 9c3fd5113a6173..c714f2e5596b38 100644
    --- a/sound/core/control.c
    +++ b/sound/core/control.c
    @@ -1574,6 +1574,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
     	/* check that there are enough valid names */
     	p = names;
     	for (i = 0; i < ue->info.value.enumerated.items; ++i) {
    +		if (buf_len == 0) {
    +			kvfree(names);
    +			return -EINVAL;
    +		}
     		name_len = strnlen(p, buf_len);
     		if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
     			kvfree(names);
    -- 
    cgit 1.3-korg
    
    
    
82012fd3e78a

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

1 file changed · +4 1
  • sound/core/control.c+4 1 modified
    diff --git a/sound/core/control.c b/sound/core/control.c
    index 934e84e9383806..0b594f89bfb299 100644
    --- a/sound/core/control.c
    +++ b/sound/core/control.c
    @@ -1574,6 +1574,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
     	/* check that there are enough valid names */
     	p = names;
     	for (i = 0; i < ue->info.value.enumerated.items; ++i) {
    +		if (buf_len == 0) {
    +			kvfree(names);
    +			return -EINVAL;
    +		}
     		name_len = strnlen(p, buf_len);
     		if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
     			kvfree(names);
    -- 
    cgit 1.3-korg
    
    
    
8ba0214c3dd3

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

1 file changed · +4 1
  • sound/core/control.c+4 1 modified
    diff --git a/sound/core/control.c b/sound/core/control.c
    index 0ddade871b524a..6ceb5f977fcddb 100644
    --- a/sound/core/control.c
    +++ b/sound/core/control.c
    @@ -1574,6 +1574,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
     	/* check that there are enough valid names */
     	p = names;
     	for (i = 0; i < ue->info.value.enumerated.items; ++i) {
    +		if (buf_len == 0) {
    +			kvfree(names);
    +			return -EINVAL;
    +		}
     		name_len = strnlen(p, buf_len);
     		if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
     			kvfree(names);
    -- 
    cgit 1.3-korg
    
    
    
e0da8a8cac74

ALSA: control: Validate buf_len before strnlen() in snd_ctl_elem_init_enum_names()

1 file changed · +4 1
  • sound/core/control.c+4 1 modified
    diff --git a/sound/core/control.c b/sound/core/control.c
    index 374e703d15a91c..5e51857635e62a 100644
    --- a/sound/core/control.c
    +++ b/sound/core/control.c
    @@ -1648,6 +1648,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
     	/* check that there are enough valid names */
     	p = names;
     	for (i = 0; i < ue->info.value.enumerated.items; ++i) {
    +		if (buf_len == 0) {
    +			kvfree(names);
    +			return -EINVAL;
    +		}
     		name_len = strnlen(p, buf_len);
     		if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
     			kvfree(names);
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing buf_len == 0 guard before strnlen() in snd_ctl_elem_init_enum_names() allows fortified strnlen() to trigger a BRK exception panic when the buffer is exhausted."

Attack vector

An attacker can trigger this bug by supplying a crafted ENUMERATED user-space control via the ALSA control interface where the total length of the concatenated enumeration names is exactly exhausted by the number of items declared. When `buf_len` reaches zero but items remain, the loop calls `strnlen(p, 0)`. With `CONFIG_FORTIFY_SOURCE` enabled and Clang as the compiler, the fortified `strnlen()` checks `maxlen` against `__builtin_dynamic_object_size()` before evaluating the return value; if Clang loses track of `p`'s object size, this check triggers a BRK exception panic, causing a kernel crash. The precondition is that the attacker can submit a `SNDRV_CTL_IOCTL_ELEM_ADD` or similar ioctl with crafted enumeration data [patch_id=2659803].

Affected code

The vulnerability resides in the function `snd_ctl_elem_init_enum_names()` in `sound/core/control.c` [patch_id=2659803]. The loop advances pointer `p` through the names buffer while decrementing `buf_len`, but lacks a check for `buf_len == 0` before calling `strnlen(p, buf_len)` on the next iteration.

What the fix does

The patch adds a `buf_len == 0` guard at the top of the loop body in `snd_ctl_elem_init_enum_names()`. If `buf_len` is zero before calling `strnlen()`, the function immediately frees the names buffer and returns `-EINVAL`. This prevents the fortified `strnlen()` from ever being invoked with a zero `maxlen` argument when the compiler cannot track the object size, thereby avoiding the BRK exception panic [patch_id=2659803].

Preconditions

  • configCONFIG_FORTIFY_SOURCE must be enabled and the kernel compiled with Clang (which may lose track of the pointer's object size inside the loop)
  • inputAttacker must be able to submit an ALSA control ioctl (e.g. SNDRV_CTL_IOCTL_ELEM_ADD) with a crafted ENUMERATED user-space control where the total name buffer length is exactly consumed by the declared number of items

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.