CVE-2026-46184
Description
In the Linux kernel, the following vulnerability has been resolved:
sound: ua101: fix division by zero at probe
Add a missing sanity check for bNrChannels in detect_usb_format() to prevent a division by zero in playback_urb_complete() and capture_urb_complete().
USB core does not validate class-specific descriptor fields such as bNrChannels, so drivers must verify them before use. If a device provides bNrChannels = 0, frame_bytes becomes zero and is later used as a divisor in the URB completion handlers, leading to a kernel crash.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A missing check for bNrChannels=0 in the Linux kernel's UA-101 audio driver causes division by zero at probe, leading to a crash.
Vulnerability
In the Linux kernel's sound/usb/ua101 driver, the function detect_usb_format() does not validate the bNrChannels field from class-specific USB descriptors before using it to compute frame_bytes. A malicious or malformed USB audio device reporting bNrChannels = 0 causes the divisor to become zero in playback_urb_complete() and capture_urb_complete(), resulting in a division-by-zero crash. All kernel versions before the fix are affected [1].
Exploitation
An attacker needs physical access to the system (or the ability to plug in a crafted USB device) with the targeted system configured to use the UA-101 audio driver. No authentication or user interaction beyond plugging in the device is required; the probe sequence occurs automatically when the device is enumerated.
Impact
Successful exploitation triggers a division-by-zero in kernel context, causing a denial of service (system crash or hang). There is no indication of information disclosure, privilege escalation, or code execution from this bug [1].
Mitigation
The fix was committed to the Linux kernel stable tree as commit f1862dbf09080254c52175a448290c784dd7d3de [1]. Users should update to a kernel version containing this commit or apply the patch manually. No workaround is available short of avoiding use of the UA-101 driver or unplugging affected devices.
AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
100ff2b713f406sound: ua101: fix division by zero at probe
2 files changed · +14 −2
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 76b6eb55dcc221..99e98b5e3241f9 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 76b6eb55dcc221..99e98b5e3241f9 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
6162e8212e88sound: ua101: fix division by zero at probe
2 files changed · +14 −2
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 4f6b20ed29dd70..303c7a00489eb0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -994,6 +994,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 4f6b20ed29dd70..303c7a00489eb0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -994,6 +994,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
593dd7e6c890sound: ua101: fix division by zero at probe
2 files changed · +14 −2
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 4f6b20ed29dd70..303c7a00489eb0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -994,6 +994,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 4f6b20ed29dd70..303c7a00489eb0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -994,6 +994,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
f1862dbf0908sound: ua101: fix division by zero at probe
2 files changed · +14 −2
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 49b3dd8d827dae..d129b42eb979d0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 49b3dd8d827dae..d129b42eb979d0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
d1f73f169c10sound: ua101: fix division by zero at probe
2 files changed · +14 −2
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 49b3dd8d827dae..d129b42eb979d0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 49b3dd8d827dae..d129b42eb979d0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
f1862dbf0908sound: ua101: fix division by zero at probe
2 files changed · +14 −2
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 49b3dd8d827dae..d129b42eb979d0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 49b3dd8d827dae..d129b42eb979d0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
0ff2b713f406sound: ua101: fix division by zero at probe
2 files changed · +14 −2
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 76b6eb55dcc221..99e98b5e3241f9 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 76b6eb55dcc221..99e98b5e3241f9 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
6162e8212e88sound: ua101: fix division by zero at probe
2 files changed · +14 −2
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 4f6b20ed29dd70..303c7a00489eb0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -994,6 +994,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 4f6b20ed29dd70..303c7a00489eb0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -994,6 +994,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
d1f73f169c10sound: ua101: fix division by zero at probe
2 files changed · +14 −2
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 49b3dd8d827dae..d129b42eb979d0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 49b3dd8d827dae..d129b42eb979d0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -974,6 +974,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
593dd7e6c890sound: ua101: fix division by zero at probe
2 files changed · +14 −2
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 4f6b20ed29dd70..303c7a00489eb0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -994,6 +994,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
sound/usb/misc/ua101.c+7 −1 modifieddiff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 4f6b20ed29dd70..303c7a00489eb0 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -994,6 +994,13 @@ static int detect_usb_format(struct ua101 *ua) ua->capture.channels = fmt_capture->bNrChannels; ua->playback.channels = fmt_playback->bNrChannels; + if (!ua->capture.channels || !ua->playback.channels) { + dev_err(&ua->dev->dev, + "invalid channel count: capture %u, playback %u\n", + ua->capture.channels, ua->playback.channels); + return -EINVAL; + } + ua->capture.frame_bytes = fmt_capture->bSubframeSize * ua->capture.channels; ua->playback.frame_bytes = -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing input validation for bNrChannels in detect_usb_format() allows a malicious USB device to set channel count to zero, causing frame_bytes to be zero and later used as a divisor in URB completion handlers."
Attack vector
An attacker with physical USB access plugs a malicious device (or a compromised UA-101-compatible device) that reports bNrChannels = 0 in its class-specific audio-streaming descriptors. The USB core does not validate this field [patch_id=2897963]. When the ua101 driver probes the device, detect_usb_format() stores the zero channel count and computes frame_bytes = bSubframeSize * 0 = 0. Later, playback_urb_complete() and capture_urb_complete() divide by frame_bytes, triggering a division-by-zero kernel crash (denial of service).
Affected code
The vulnerable code is in sound/usb/misc/ua101.c in the detect_usb_format() function. The function reads fmt_capture->bNrChannels and fmt_playback->bNrChannels from USB class-specific descriptors without validating that they are non-zero, then uses them to compute frame_bytes which later serves as a divisor in playback_urb_complete() and capture_urb_complete() [patch_id=2897963].
What the fix does
The patch adds a sanity check in detect_usb_format() immediately after assigning ua->capture.channels and ua->playback.channels from the USB descriptors. If either channel count is zero, the function logs an error and returns -EINVAL, causing probe to fail before frame_bytes is computed or any URBs are submitted [patch_id=2897963]. This prevents the division by zero that would otherwise occur in the URB completion callbacks.
Preconditions
- networkAttacker must have physical USB access to plug a malicious or malformed device.
- inputThe malicious device must present a USB audio streaming descriptor with bNrChannels = 0.
- configThe ua101 driver must be loaded and probe the device.
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/0ff2b713f406e9ecadb406014d74e7a020ac12b1nvd
- git.kernel.org/stable/c/593dd7e6c890d8e4ca21b3e2f796b7cb8e8da983nvd
- git.kernel.org/stable/c/6162e8212e88c39492d981b248b5e37002486c66nvd
- git.kernel.org/stable/c/d1f73f169c1014463b5060e3f60813e13ddc7b87nvd
- git.kernel.org/stable/c/f1862dbf09080254c52175a448290c784dd7d3denvd
News mentions
0No linked articles in our index yet.