[PATCH v1 0/3] usb: gadget: fix WebUSB landing page handling
From: Aristo Chen
Date: Mon Aug 31 2026 - 15:13:36 EST
Three fixes for the WebUSB landing page path, found while reading
webusb_landingPage_store() and the descriptor emission that consumes
what it stores. The first two are bugs, the third is the cleanup that
made the second one easier to see.
Patch 1 stores the landing page without a NUL terminator when the URL
is exactly WEBUSB_URL_RAW_MAX_LENGTH bytes, because the buffer is sized
to hold the longest legal URL and nothing more. webusb_landingPage_show()
then reads past the end of that array. It currently stops in the zeroed
padding before the next member, so nothing is disclosed, but the
terminator that ought to stop it is simply absent. A 260 byte URL is
legitimate, since after the "https://" prefix is stripped it is exactly
a 255 byte descriptor, so the buffer gains a byte for the terminator
rather than the limit losing one.
Patch 2 fixes the emission side. The strnlen() bound subtracts the
descriptor header from a field that already excludes it, and the host's
w_length is folded into the URL length, which conflates how much URL
there is, how large the descriptor is, and how many bytes were asked
for. The result is a URL copy bounded by the request rather than by
URL[], a u8 bLength that wraps for w_length 256..259, a bLength that
describes the transfer instead of the descriptor, and a reply longer
than the data stage for w_length below 3. Computing the URL length
once and clamping only the reply removes all four.
Patch 3 drops a dead store in webusb_landingPage_store() and renames the
variable to what it actually holds. No functional change.
The two fixes are independent; patch 2 is correct with or without patch
1 applied. Only patch 3 depends on ordering, and it is last.
I do not have a WebUSB host handy, so the descriptor arithmetic in patch
2 was checked by transcribing the before and after logic into userspace
and sweeping every (URL, w_length) pair up to USB_COMP_EP0_BUFSIZ: no
copy past URL[], no bLength wrap, no reply exceeding w_length, and
bLength always equal to the true descriptor size. The store side was
modelled the same way, with the existing behaviour first read off the
webusb/landingPage attribute of a running kernel so the model could be
checked against it: patch 3 changes nothing observable, and patch 1
changes nothing but the terminator.
Aristo Chen (3):
usb: gadget: configfs: fix WebUSB landing page missing NUL terminator
usb: gadget: composite: fix WebUSB URL descriptor length handling
usb: gadget: configfs: drop dead store in webusb_landingPage_store()
drivers/usb/gadget/composite.c | 33 ++++++++++++++++++---------------
drivers/usb/gadget/configfs.c | 22 ++++++++++------------
include/linux/usb/composite.h | 2 +-
include/linux/usb/webusb.h | 5 ++++-
4 files changed, 33 insertions(+), 29 deletions(-)
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
--
2.53.0