Linux Input/HID development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Griffin Kroah-Hartman" <griffin@kroah.com>
Cc: linux-input@vger.kernel.org, dmitry.torokhov@gmail.com
Subject: Re: [PATCH 3/3] Input: xpad - add sdata_check() to xpad360 branches
Date: Mon, 03 Aug 2026 16:05:11 +0000	[thread overview]
Message-ID: <20260803160512.730DF1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260803-xpadone_packet_fix-v1-3-280da203f15c@kroah.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [Medium] Zero-length packets incorrectly pass validation and are processed as valid empty states, spuriously releasing all controller buttons.

Pre-existing issues:
- [High] Blocking USB APIs and GFP_KERNEL allocations are unsafely invoked from the atomic URB completion handler.
- [High] Error paths during initialization destroy the input device while leaving a dangling pointer for presence_work to dereference.
- [Medium] 16-bit multi-byte reads and direct array modifications completely bypass the new length validation, leading to stale data leakage.
--

--- Patch [3]: [PATCH 3/3] Input: xpad - add sdata_check() to xpad360 branches ---
commit 0a84609d4ff81bead2c2c2c26f83c5c8f9cc506a
Author: Griffin Kroah-Hartman <griffin@kroah.com>

Input: xpad - add sdata_check() to xpad360 branches

This commit adds the sdata_check() safety wrapper to the xpad360_process_packet()
and xpad360w_process_packet() functions. It bounds-checks array accesses to prevent
out-of-bounds reads on the controller data buffer.

> diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
> index 319a4c4a695fe..304229782e455 100644
> --- a/drivers/input/joystick/xpad.c
> +++ b/drivers/input/joystick/xpad.c
> @@ -891,19 +891,24 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
>   */
>  
>  static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
> -				   u16 cmd, unsigned char *data)
> +				   u16 cmd, unsigned char *data, u32 len)
>  {
> +	struct safe_data sdata;
> +
> +	sdata.data = data;
> +	sdata.len = len;
> +
>  	/* valid pad data */
> -	if (data[0] != 0x00)
> +	if (sdata_check(&sdata, 0) != 0x00)
>  		return;

[Severity: Medium]
Does this inadvertently allow zero-length packets to be treated as valid
pad data? Because sdata_check() safely returns 0 when the index is out of
bounds, a zero-length packet will successfully pass this != 0x00 check
and spuriously release all controller buttons.

>  
>  	/* digital pad */
>  	if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {

[ ... ]

> @@ -915,27 +920,29 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
>  	if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) ||
>  	    xpad->xtype == XTYPE_XBOX360W) {

[ ... ]

>  	/* buttons A,B,X,Y,TL,TR and MODE */
> -	input_report_key(dev, BTN_A,	data[3] & BIT(4));
> -	input_report_key(dev, BTN_B,	data[3] & BIT(5));
> -	input_report_key(dev, BTN_X,	data[3] & BIT(6));
> -	input_report_key(dev, BTN_Y,	data[3] & BIT(7));
> -	input_report_key(dev, BTN_TL,	data[3] & BIT(0));
> -	input_report_key(dev, BTN_TR,	data[3] & BIT(1));
> -	input_report_key(dev, BTN_MODE,	data[3] & BIT(2));
> +	input_report_key(dev, BTN_A,	sdata_check(&sdata, 3) & BIT(4));
> +	input_report_key(dev, BTN_B,	sdata_check(&sdata, 3) & BIT(5));
> +	input_report_key(dev, BTN_X,	sdata_check(&sdata, 3) & BIT(6));
> +	input_report_key(dev, BTN_Y,	sdata_check(&sdata, 3) & BIT(7));
> +	input_report_key(dev, BTN_TL,	sdata_check(&sdata, 3) & BIT(0));
> +	input_report_key(dev, BTN_TR,	sdata_check(&sdata, 3) & BIT(1));
> +	input_report_key(dev, BTN_MODE,	sdata_check(&sdata, 3) & BIT(2));
>  
>  	if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
>  		/* left stick */

[Severity: Medium]
This isn't a bug introduced by this patch, but will the 16-bit stick axis 
reads immediately following this code bypass the new length checks?

xpad_process_packet(), xpad360_process_packet(), and xpadone_process_packet()
read multi-byte values using le16_to_cpup() directly against the raw data
buffer:

    input_report_abs(dev, ABS_X,
                     (__s16) le16_to_cpup((__le16 *)(data + 6)));

A short packet would still cause out-of-bounds reads here since these
accesses completely bypass the sdata_check() wrapper, potentially leaking
uninitialized DMA memory into input events.

[ ... ]

> @@ -1019,14 +1026,18 @@ static void xpad_presence_work(struct work_struct *work)
>   * 01.1 - Pad state (Bytes 4+) valid
>   *
>   */
> -static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
> +static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data, u32 len)
>  {
>  	struct input_dev *dev;
> +	struct safe_data sdata;
>  	bool present;
>  
> +	sdata.data = data;
> +	sdata.len = len;
> +
>  	/* Presence change */
> -	if (data[0] & 0x08) {
> -		present = (data[1] & 0x80) != 0;
> +	if (sdata_check(&sdata, 0) & 0x08) {
> +		present = (sdata_check(&sdata, 1) & 0x80) != 0;
>  
>  		if (xpad->pad_present != present) {
>  			xpad->pad_present = present;
>  			schedule_work(&xpad->work);

[Severity: High]
This is a pre-existing issue, but can the xpad_presence_work thread
dereference a freed pointer if initialization fails?

If xpad_init_input() encounters an error (like during device registration),
it takes the err_free_input path:

xpad_init_input() {
    ...
err_free_input:
    input_free_device(input_dev);
    return error;
}

This frees the device but leaves xpad->dev pointing to the freed memory.
When xpad_presence_work() processes the failure, it logs the error:

xpad_presence_work() {
    ...
    dev_err(&xpad->dev->dev, "unable to init device: %d\n", error);
}

Could this use-after-free lead to memory corruption or a crash?

[ ... ]

> @@ -1262,10 +1273,10 @@ static void xpad_irq_in(struct urb *urb)
>  
>  	switch (xpad->xtype) {
>  	case XTYPE_XBOX360:
> -		xpad360_process_packet(xpad, xpad->dev, 0, xpad->idata);
> +		xpad360_process_packet(xpad, xpad->dev, 0, xpad->idata, urb->actual_length);
>  		break;
>  	case XTYPE_XBOX360W:
> -		xpad360w_process_packet(xpad, 0, xpad->idata);
> +		xpad360w_process_packet(xpad, 0, xpad->idata, urb->actual_length);
>  		break;
>  	case XTYPE_XBOXONE:
>  		xpadone_process_packet(xpad, 0, xpad->idata, urb->actual_length);

[Severity: High]
This is a pre-existing issue, but does xpadone_process_packet() execute
blocking calls and GFP_KERNEL allocations from an atomic context?

When xpad_irq_in() processes an Xbox One GIP_CMD_ANNOUNCE packet from
interrupt context, it follows this call chain:

xpad_irq_in()
  xpadone_process_packet()
    xpad_start_input()
      usb_submit_urb(xpad->irq_in, GFP_KERNEL)

xpad_start_input() also calls xpad_start_xbox_one(), which invokes
usb_set_interface(), a synchronous and blocking USB API. Calling these
from the atomic URB completion handler could lead to scheduling while
atomic warnings and potential deadlocks.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260803-xpadone_packet_fix-v1-0-280da203f15c@kroah.com?part=3

      reply	other threads:[~2026-08-03 16:05 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-03 15:07 [PATCH 0/3] XPAD safety strengthening Griffin Kroah-Hartman
2026-08-03 15:07 ` [PATCH 1/3] Input: xpad - add safer data access framework Griffin Kroah-Hartman
2026-08-03 15:27   ` sashiko-bot
2026-08-03 16:23   ` Dmitry Torokhov
2026-08-04  8:02     ` Griffin Kroah-Hartman
2026-08-03 15:07 ` [PATCH 2/3] Input: xpad - add sdata_check() to xpad controllers Griffin Kroah-Hartman
2026-08-03 15:46   ` sashiko-bot
2026-08-03 15:07 ` [PATCH 3/3] Input: xpad - add sdata_check() to xpad360 branches Griffin Kroah-Hartman
2026-08-03 16:05   ` sashiko-bot [this message]

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=20260803160512.730DF1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=griffin@kroah.com \
    --cc=linux-input@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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