[PATCH] usb: gadget: f_uac1_legacy: reject req_buf_size above audio_buf_size

From: Noah Weinberger

Date: Sun Nov 08 2026 - 18:59:53 EST


Hello,

f_uac1_legacy allocates the playback copy buffer with the
audio_buf_size option and the OUT request buffers with the
independent req_buf_size option, and never cross-validates them.
In the playback completion handler, a request larger than the
remaining copy-buffer space flushes the current buffer and allocates
a fresh one, then copies the whole request into it:

if (audio_buf_size - copy_buf->actual < req->actual) {
... flush, copy_buf = f_audio_buffer_alloc(audio_buf_size);
}
memcpy(copy_buf->buf + copy_buf->actual, req->buf, req->actual);

With req_buf_size > audio_buf_size (both are free configfs
attributes; the defaults 200 and 48000 are safe) and a hostile host
that streams full-length packets, this is a linear heap overflow of
req_buf_size - audio_buf_size bytes with host-controlled content and
pacing. The patch rejects the combination when the streaming
alt-setting is selected, failing closed.

Affected version/commit: mainline 8a65162514fbad21a2c58ffed65f42b27e92b163 (v7.4-rc2 window, 2026-11-08), drivers/usb/gadget/function/f_uac1_legacy.c:338-349 (playback completion: the 'if (audio_buf_size - copy_buf->actual < req->actual)' flush logic, then memcpy(copy_buf->buf + copy_buf->actual, req->buf, req->actual)), :605-657 (f_audio_set_alt: copy_buf = f_audio_buffer_alloc(audio_buf_size); req buffers kzalloc(req_buf_size), req->length = req_buf_size), :893-895 (independent opts attributes)
Longstanding legacy gadget.

This was found during an assisted (AI-supported) static source review of
mainline 8a65162514fbad21a2c58ffed65f42b27e92b163 (v7.4-rc2 window, 2026-11-08). The patch below has NOT been compiled and has
NOT been runtime tested, and no reproducer was produced - the triggering
conditions are described above instead. Please treat this as a report for
verification rather than a battle-tested fix.

---
diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c
index 7c8d60c7e8..7e046ae806 100644
--- a/drivers/usb/gadget/function/f_uac1_legacy.c
+++ b/drivers/usb/gadget/function/f_uac1_legacy.c
@@ -615,6 +615,11 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
req_count = opts->req_count;
audio_buf_size = opts->audio_buf_size;

+ /* A request buffer larger than the copy buffer would overflow it. */
+ if (req_buf_size > audio_buf_size) {
+ ERROR(cdev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
/* No i/f has more than 2 alt settings */
if (alt > 1) {
ERROR(cdev, "%s:%d Error!\n", __func__, __LINE__);