Linux USB
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: "HE WEI (ギカク)" <skyexpoc@gmail.com>
Cc: Israel Cepeda <israel.a.cepeda.lopez@intel.com>,
	Hans de Goede <hansg@kernel.org>,
	Andi Shyti <andi.shyti@kernel.org>,
	Sakari Ailus <sakari.ailus@linux.intel.com>,
	linux-usb@vger.kernel.org, linux-i2c@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 0/3] usbio: fix two out-of-bounds accesses and a hang
Date: Sun, 26 Jul 2026 13:09:54 +0200	[thread overview]
Message-ID: <2026072622-refusing-smasher-6eed@gregkh> (raw)
In-Reply-To: <20260726080129.44969-1-skyexpoc@gmail.com>

On Sun, Jul 26, 2026 at 04:59:10PM +0900, HE WEI (ギカク) wrote:
> This is variant analysis around 8c6314489550 ("usb: misc: usbio: bound
> bulk IN response length to the received transfer"), which fixed a slab
> out-of-bounds read in usbio_bulk_msg().  Re-reading that function,
> usbio_ctrl_msg() and the I2C client built on top of them turned up three
> further issues.
> 
> Patch 1 fixes the length checks in usbio_ctrl_msg() and
> usbio_bulk_msg().  They are computed as "<buf>_len - sizeof(*pkt)", u16
> minus size_t, which wraps for any endpoint smaller than the protocol
> header.  usb_parse_endpoint() only clamps wMaxPacketSize downwards, so
> a device can advertise 1 and turn the check off entirely; the first I2C
> transfer then overflows a one byte slab object.  The overflow completes
> before usb_bulk_msg() is reached, so it does not depend on the host
> controller accepting the transfer.  Fixed by validating the three
> lengths once in usbio_probe(), which is the only place that assigns
> them.
> 
> Patch 2 is the equivalent arithmetic in i2c-usbio.c, where the overhead
> is 10 rather than 5.  The interesting value there is exactly 10: the
> chunk size is then 0 and the split loop in usbio_i2c_read() never
> advances, so a device that keeps answering keeps the loop alive
> uninterruptibly while holding usbio->bulk_mutex.  That is a hang rather
> than memory corruption, and patch 1 does not address it.  This is also
> the one patch in the series with a behaviour change -- a bridge whose
> bulk wMaxPacketSize is below 11 no longer gets an I2C adapter -- and the
> commit message spells out why such an adapter could never have
> completed a transfer in the first place.
> 
> Patch 3 is a different bug from the two above, and the one that affects
> existing hardware.  usbio_ctrl_msg() and usbio_bulk_msg() hex dump the
> reply with "%*phN" using a length the device supplied and that has not
> been validated yet.  hex_string() caps the field width at 64, not at
> the buffer size, so the dump reads up to byte 67 of ctrlbuf and byte 68
> of rxbuf: out of bounds for every low, full and high speed ep0 packet
> size and for the bulk sizes these bridges actually use.  It needs no
> malformed descriptor at all, only the dev_dbg() calls enabled.
> 
> The new probe checks do not reject any supported bridge: the low, full
> and high speed devices this driver binds to have an ep0 packet size of
> at least 8, and they use bulk endpoints of 64, or 63 via
> USBIO_QUIRK_BULK_MAXP_63.
> 
> What was verified, and what was not:
> 
>  - All three build cleanly with x86_64 gcc 14.2.0 at W=1, with
>    CONFIG_DYNAMIC_DEBUG both disabled and enabled.
> 
>  - The out-of-bounds accesses in patches 1 and 3, and the
>    non-terminating loop in patch 2, reproduce against a userspace model
>    that copies the struct definitions from usbio.h and the checks and
>    stores from usbio.c and i2c-usbio.c verbatim, with only
>    devm_kzalloc(), usb_bulk_msg() and usb_control_msg() replaced; the
>    memory errors are reported by AddressSanitizer.  The same source
>    built with the patches applied is clean, and both a normal device
>    (ep0 64, bulk 64/64) and the USBIO_QUIRK_BULK_MAXP_63 path still
>    work.
> 
>  - The decision space was swept exhaustively, endpoint sizes 0..2048
>    against caller lengths 0..4101: the mainline bulk check can be
>    bypassed for exactly 0..4 and the control check for exactly 0..3.
>    After patch 1 no accepted endpoint size admits an overflow, and no
>    size that could carry a payload byte is rejected.
> 
>  - I have not run any of this on hardware or on dummy_hcd.  The
>    reachability arguments are read from usbcore and from
>    lib/vsprintf.c, not observed at runtime.  I am happy to build a
>    raw-gadget reproducer if that would help review.
> 
> Patches 1 and 3 touch drivers/usb/misc/usbio.c and patch 2 touches
> drivers/i2c/busses/i2c-usbio.c; MAINTAINERS lists all three files under
> the same INTEL USBIO entry, so they are sent as one series.  They apply
> to mainline 3dab139d4795, to usb-next and to usb-testing.
> 
> HE WEI (ギカク) (3):
>   usb: misc: usbio: reject endpoints smaller than the packet header
>   i2c: usbio: reject bridges with undersized transfer buffers
>   usb: misc: usbio: bound the debug hex dumps by the received length
> 
>  drivers/i2c/busses/i2c-usbio.c | 14 ++++++++++++
>  drivers/usb/misc/usbio.c       | 50 ++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 60 insertions(+), 4 deletions(-)

As you obviously used a LLM for these, why did it not properly tag the
changes with an "Assisted-by:" tag?  That is required.

thanks,

greg k-h

  parent reply	other threads:[~2026-07-26 11:11 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-26  7:59 [PATCH 0/3] usbio: fix two out-of-bounds accesses and a hang HE WEI (ギカク)
2026-07-26  7:59 ` [PATCH 1/3] usb: misc: usbio: reject endpoints smaller than the packet header HE WEI (ギカク)
2026-07-26  7:59 ` [PATCH 2/3] i2c: usbio: reject bridges with undersized transfer buffers HE WEI (ギカク)
2026-07-26  7:59 ` [PATCH 3/3] usb: misc: usbio: bound the debug hex dumps by the received length HE WEI (ギカク)
2026-07-26 11:09 ` Greg Kroah-Hartman [this message]
2026-07-26 11:32   ` [PATCH 0/3] usbio: fix two out-of-bounds accesses and a hang skyexpoc
2026-07-26 11:43     ` Greg Kroah-Hartman
2026-07-26 11:59       ` HE WEI(ギカク)
2026-07-26 12:18         ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2026072622-refusing-smasher-6eed@gregkh \
    --to=gregkh@linuxfoundation.org \
    --cc=andi.shyti@kernel.org \
    --cc=hansg@kernel.org \
    --cc=israel.a.cepeda.lopez@intel.com \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=sakari.ailus@linux.intel.com \
    --cc=skyexpoc@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox