From: sashiko-bot@kernel.org
To: "Vicki Pfau" <vi@endrift.com>
Cc: linux-input@vger.kernel.org, dmitry.torokhov@gmail.com
Subject: Re: [PATCH v5 06/12] Input: xbox_gip - Allow sending fragmented and ACME messages
Date: Wed, 02 Sep 2026 01:19:46 +0000 [thread overview]
Message-ID: <20260902011947.5607D1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260902010237.865772-7-vi@endrift.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] Unconditional dereference of NULL fragment pointer on error path for non-fragmented messages.
- [High] Missing synchronization when allocating and initializing `out_fragments` slots.
- [High] Unsynchronized read-modify-write of the `intf->has_pending_out` bitmask.
- [High] Dropped ACKs permanently leak `out_fragments` slots.
--
commit 317888ee9cccdc0f09f7f1c8d616d2664382777a
Author: Vicki Pfau <vi@endrift.com>
Input: xbox_gip - Allow sending fragmented and ACME messages
This commit introduces support for sending fragmented messages that exceed the
MTU length and messages requiring ACKs using the ACME flag in the GIP protocol.
It adds queuing, processing, and acknowledgment handling logic to the xbox_gip
driver.
> diff --git a/drivers/input/joystick/gip/gip-core.c b/drivers/input/joystick/gip/gip-core.c
> index 57d638408daf4..544becf8badd6 100644
> --- a/drivers/input/joystick/gip/gip-core.c
> +++ b/drivers/input/joystick/gip/gip-core.c
[ ... ]
> +static void gip_free_fragment(struct gip_out_fragment *fragment)
> +{
> + kfree(fragment->data);
> + memset(fragment, 0, sizeof(*fragment));
> +}
[ ... ]
> static int gip_send_raw_message(struct gip_attachment *attachment,
> uint8_t message_type, uint8_t flags, uint8_t seq, const uint8_t *bytes,
> int num_bytes)
> @@ -486,20 +529,25 @@ static int gip_send_raw_message(struct gip_attachment *attachment,
> struct gip_interface *intf;
> int offset = 3;
> struct gip_urb *urb = NULL;
> + struct gip_out_fragment *fragment = NULL;
> int i;
> int rc = 0;
[ ... ]
> + if (num_bytes > reduced_mtu ||
> + (flags & (GIP_FLAG_ACME | GIP_FLAG_FRAGMENT)) == GIP_FLAG_ACME) {
> + for (i = 0; i < MAX_OUT_FRAGMENTS; i++) {
> + if (attachment->out_fragments[i].active)
> + continue;
> +
> + fragment = &attachment->out_fragments[i];
> + break;
> + }
[Severity: High]
Does this code have a missing synchronization issue?
The fragment slot is claimed and initialized locklessly here. If concurrent
callers (like force feedback workers, sysfs, or incoming message handlers)
pick the same inactive slot, could this lead to double-allocation (a memory
leak) and state corruption?
> +
> + if (!fragment) {
> + gip_err(attachment, "Fragmented message queue is full; dropping message\n");
> + return -EALREADY;
> + }
> +
> + fragment->data = kmalloc(num_bytes, GFP_KERNEL);
> + if (!fragment->data)
> + return -ENOMEM;
> + fragment->active = true;
[Severity: High]
Can these out_fragments slots permanently leak if ACKs are dropped?
When an outgoing message requires an ACK, the slot is marked active here and
relies entirely on a device-initiated ACK to be freed. Because there is no
timeout mechanism, if the device drops the message or fails to respond, could
the slot remain locked forever? Since MAX_OUT_FRAGMENTS is only 2, a couple
of dropped packets might permanently exhaust the queue.
[ ... ]
> guard(spinlock_irqsave)(&attachment->device->message_lock);
> for (i = 0; i < MAX_OUT_MESSAGES && !urb; i++) {
> if (!intf->out_queue[i].urb)
[ ... ]
> + if (fragment) {
> + /*
> + * Sending further fragments is handled in gip_urb_out if this fragment doesn't need
> + * ACKing or in gip_handle_command_protocol_control if it does. The flag should also
> + * be cleared if we're done sending this packet.
> + */
> + if (fragment->total_length > reduced_mtu && !(flags & GIP_FLAG_ACME))
> + intf->has_pending_out |= gip_fragment_id(attachment, fragment);
> + else
> + intf->has_pending_out &= ~gip_fragment_id(attachment, fragment);
> }
>
> return rc;
> +
> +err_free_fragment:
> + gip_free_fragment(fragment);
> + return rc;
> +}
[Severity: Critical]
Does this error path unconditionally dereference a NULL pointer?
If gip_send_raw_message() is called for a standard, non-fragmented message,
the fragment pointer remains NULL. If the output queue is full or
usb_submit_urb() fails, the function jumps to err_free_fragment and calls
gip_free_fragment().
Since gip_free_fragment() unconditionally accesses fragment->data and calls
memset(fragment, ...), won't this immediately crash the kernel when fragment
is NULL?
[ ... ]
> +static int gip_send_next_fragment(struct gip_attachment *attachment,
> + struct gip_out_fragment *fragment)
> +{
> + struct gip_interface *intf;
[ ... ]
> + if (fragment->fragment_offset == fragment->total_length) {
> + if ((fragment->message & GIP_DATA_CLASS_MASK) == GIP_DATA_CLASS_AUDIO)
> + intf = &attachment->device->audio;
> + else
> + intf = &attachment->device->data;
> +
> + next_bytes = 0;
> + intf->has_pending_out &= ~gip_fragment_id(attachment, fragment);
[Severity: High]
Is there an unsynchronized read-modify-write data race here?
Here in gip_send_next_fragment(), intf->has_pending_out is updated without
holding message_lock. However, as seen in gip_send_raw_message(), this shared
bitmask is also modified under message_lock.
Could concurrent updates to this shared variable cause lost updates,
permanently stalling fragment transmission for any attachments whose bits get
lost?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260902010237.865772-1-vi@endrift.com?part=6
next prev parent reply other threads:[~2026-09-02 1:19 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-02 1:02 [PATCH v5 00/12] Input: xbox_gip - Add new driver for Xbox GIP Vicki Pfau
2026-09-02 1:02 ` [PATCH v5 01/12] " Vicki Pfau
2026-09-02 1:28 ` sashiko-bot
2026-09-02 1:02 ` [PATCH v5 02/12] Input: xpad - Remove Xbox One support Vicki Pfau
2026-09-02 1:02 ` [PATCH v5 03/12] Input: xbox_gip - Add controllable LED support Vicki Pfau
2026-09-02 1:20 ` sashiko-bot
2026-09-02 1:02 ` [PATCH v5 04/12] Input: xbox_gip - Add HID relaying Vicki Pfau
2026-09-02 1:22 ` sashiko-bot
2026-09-02 1:02 ` [PATCH v5 05/12] Input: xbox_gip - Add battery support Vicki Pfau
2026-09-02 1:20 ` sashiko-bot
2026-09-02 1:02 ` [PATCH v5 06/12] Input: xbox_gip - Allow sending fragmented and ACME messages Vicki Pfau
2026-09-02 1:19 ` sashiko-bot [this message]
2026-09-02 1:02 ` [PATCH v5 07/12] Input: xbox_gip - Add security implementation from xone Vicki Pfau
2026-09-02 1:20 ` sashiko-bot
2026-09-02 1:02 ` [PATCH v5 08/12] Input: xbox_gip - Add arcade stick support Vicki Pfau
2026-09-02 1:24 ` sashiko-bot
2026-09-02 1:02 ` [PATCH v5 09/12] Input: xbox_gip - Add support for PDP guitar controllers Vicki Pfau
2026-09-02 1:02 ` [PATCH v5 10/12] Input: Add ABS_CLUTCH, HANDBRAKE, and SHIFTER Vicki Pfau
2026-09-02 1:23 ` sashiko-bot
2026-09-02 1:02 ` [PATCH v5 11/12] HID: Map more automobile simulation inputs Vicki Pfau
2026-09-02 1:02 ` [PATCH v5 12/12] Input: xbox_gip - Add wheel support Vicki Pfau
2026-09-02 1:33 ` sashiko-bot
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=20260902011947.5607D1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dmitry.torokhov@gmail.com \
--cc=linux-input@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=vi@endrift.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.