From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-vk1-f174.google.com (mail-vk1-f174.google.com [209.85.221.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 97FF014F9FB for ; Sat, 11 Apr 2026 17:58:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=209.85.221.174 ARC-Seal:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775930303; cv=pass; b=E8eL6gxUdpfwpaUxZUNyQVQB/G0Uyq9uTFoFW953e6vvGginH8b2itBdEMgDJcIlHhHQrdx7Gj2fIbbQezgWe+U5XOFHf7h4yUIR6BxRazd/LXNyszlVc1Ig5A+ieI0daeGVnK8SPaZ8r9sg4GZBRJMwBST4VJ1uc6efTHzMtqo= ARC-Message-Signature:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775930303; c=relaxed/simple; bh=K9cNahQL7sU3k6YTlTe4h+cxu2W+ZHClkJ+CtHxghjQ=; h=MIME-Version:From:Date:Message-ID:Subject:To:Cc:Content-Type; b=B89iMI8S7tuXitUYooCO1LqCMzc56VgwXUrlnK0550NIjNHFOw/1iZLJ5RCkgX2BqebRIecXYQqnqbd9sgQV+mzOYjW1aLO4fd/zI/LllLiSz/k2n1I8nfa7cRPXwnAtLHVraXuSgN21M9a09V3alMMyBeBE8Y1EKB/MYYMdj20= ARC-Authentication-Results:i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kndfICZh; arc=pass smtp.client-ip=209.85.221.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kndfICZh" Received: by mail-vk1-f174.google.com with SMTP id 71dfb90a1353d-56d93883b64so155166e0c.3 for ; Sat, 11 Apr 2026 10:58:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1775930300; cv=none; d=google.com; s=arc-20240605; b=SpbWfp8T+d+HuxyFb8iAcMJDekyioHTxcZhSK+wOGx3wH4EgbX/tukJwSPo4m9pYt9 IWiRYkXTRBiwvadh0pk5ohio/RuOc+AFUIEM3Mlef00yW6sa41szzQxAV/xfIZsgo532 qdf4JlF5CG0vlLOWeaZ1gTQPe6Ix7WBGJ+C0NWsW21XFRhJNJgWHgzzdPatkeSTr67Zn Ci8Ylo9Zg2WOOY4sAkVpcjZ/VZ9iQbbrYsyrd21jpSDcozOsA5y+wGyEDodLcCD1efwa m4h2lJTW+N/1LjTaIIfeJCo8qee1hvaC/DnSdca/tl13iotCLR0ys7k9p9w+0vZRUrjD 9R8A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :mime-version:dkim-signature; bh=FQ9FMt2GgCLKM11biLesryR+G33OllgKjO21lfayfy8=; fh=LbyECID7Vqfey87gwvlXEYVkD01aGeIuYMobEYVwG0M=; b=HC1BviO7HXkTbfiwW5WAwVPpXUPG/pUsk0ASxLYwqU4pPaeZzjl1B7paEgJQeS08q9 Su2l3iWmvbcvDv7Y2O5GLub9m7pAOZ020HFzWxLrKbAWSd6WSCf37yTpxI0EkW7Mvy0b dTUGR52X9EZBa7RR4oEz59/6cuy1cPvxmAEcal+RYS5Kj2a3oFlDhBP/qYVldaAlyQPQ 2I3On6neE2A3PHkzG837bqpWWpTMgECduZYHqpCzQsp1vSOabJRz2Mlx0MP3m5Q5/wZh +AUhzc/hP2/QIeaezV2oEECYcfhJlvXaxXZyCMnspQJJWGDFISs/3TkppMzWwPIJVrgu 3bIw==; darn=vger.kernel.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775930300; x=1776535100; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=FQ9FMt2GgCLKM11biLesryR+G33OllgKjO21lfayfy8=; b=kndfICZhttip+fX8FmKYYHNFF5k4HaUFdTaQOab8uOiFuPyvsd1+fALtpa1GJzzZEb qB/vx4yQIQjEXTMFoN7K+MgCpKRwVgWJjN63ihh8l3P+mspcwVSsC0zGecN9LUP2P8hu JDHi0uyTW8NSOYj8afPfGwi4hO56oi1c581yCLqz3KcMGTigbj8YPQag4VddSz7RxP59 v1bX+1eG3VxkGKy3T87h/4isic7WEYfmYynhUUNYBUQETWJLp4Ybtfh5FOdKR7dQD8om d6oCU6u9Tsz8kPR6rW1ltgPk037SoQ3bNuuYnwJwaY0zvYU+d3pBLXc0xpQgsu0znMOM 7ULA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775930300; x=1776535100; h=content-transfer-encoding:cc:to:subject:message-id:date:from :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=FQ9FMt2GgCLKM11biLesryR+G33OllgKjO21lfayfy8=; b=X4XjY/1Wx0W5Z34jdYJOq1Cf6d3+OBmOjGPZwcwPpmVLyNZ6aJCbBDVpd3TEndNIyE KjAzf922PkcVnA9US8+oOJBbp++OGnESK3gPyTbkE1Un1MCBvP/zKv/5MgKITQrjwYfC usZUWaHXyC6mNgqUcda1LhzTHMkkWpN7Q0YnVn4gB9l/WIrxJwnoz3S4YFR4ILJ039HJ S+XDISNBj5/WbBZSV3/ybIZsZOU+rFcEZc7EgwYpHAx34rNIR/8l8Gr0SxLswG7GZ6wV YrYbfmXl+kUCWIceOY/eZRwPFYnRJTmUac2Iu3LI+xhQLxjrgTMaFhaVtUikVHagkhof 6o9w== X-Forwarded-Encrypted: i=1; AJvYcCWfLUyRdqNq7QV3ifqiy4Gtu1rNiGZdy4g903c2dgVxhHgcz1RdeNY5uW7db2BI42py9E4KmLZHT0HyBsw=@vger.kernel.org X-Gm-Message-State: AOJu0YzNN4YMQpfhpAMgpfkN0Eb69sH975+nWWHYu3L0x1qV3r7EJmE7 LTonSanSkwGFz1G5qQOKEK4r0HRN/reHQgXUTPzC96PSSUXxJVaqd8UZmCRaJxGqktDm4+WYiru R3BpGRN2uwtfqV6VTdj3tg8Kjrqx5auE= X-Gm-Gg: AeBDietKnv2ByV1lzqLjLsSXdm0p4PZ2HtKeGVzl785sEH6bRPLALNLPQvfY0izUKI1 Ugo6sRY/qKY8hU55tt2xw8ktTSaXGDbn+DIcC+5fdRryRt1oXuj5sth276g4O80sHoksZAbg1RD FiL29dvqiTZ0/TGPYfBht3Z7GoDDTny2GXositGwp7O4IQ9XxE4ZlkpfutEPnIW5JbtNH6erRKh oMqgASnaYerGfh8/3Uk4wfvDPMk9+nYvYUOwUG+RDOMXyohZg7sPHNmRPJFtKm7OmJOPzC69vVh HhFhrs++jv/QDt7PctE3PHyewEOK9nAHB5o6UzgAigMAOnZtHg== X-Received: by 2002:a05:6122:3a01:b0:56f:4a47:6c9e with SMTP id 71dfb90a1353d-56f4a478d9dmr853373e0c.2.1775930300446; Sat, 11 Apr 2026 10:58:20 -0700 (PDT) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Pavitra Jha Date: Sat, 11 Apr 2026 23:28:08 +0530 X-Gm-Features: AQROBzC2X93QqIGjFT303XQHdrnkn9J_7FXOpIDUFvz6B4Lnw5sv8iW1g1B5zBA Message-ID: Subject: MAX3420 UDC: out-of-bounds read/write via unvalidated wIndex in USB SETUP packet To: linux-usb@vger.kernel.org Cc: Greg KH , stable@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hello, I am reporting an out-of-bounds read and write in the MAX3420 USB Device Controller driver. The issue arises from using a host-controlled wIndex field from a USB SETUP packet as a direct index into a fixed-size endpoint array without validating that the index is within bounds. The driver handles USB control requests originating from an external USB host and therefore must treat all request fields as untrusted. 1. VERSION AND ENVIRONMENT Research kernel: v7.0.0-rc7 Architecture: x86_64 Observed unpatched as of April 11, 2026 2. VULNERABILITY PATH USB host (attacker-controlled SETUP packet) -> MAX3420 hardware (SUDFIFO register) -> max3420_handle_irqs() -> max3420_handle_setup() -> spi_rd_buf(..., MAX3420_REG_SUDFIFO, ...) -> udc->setup =3D setup udc->setup.wIndex =3D cpu_to_le16(setup.wIndex) -> dispatch: -> max3420_getstatus() -> max3420_set_clear_feature() -> wIndex masked and used as endpoint index -> out-of-bounds access into udc->ep[] when the derived index exceeds the array bounds No validation of the derived index is observed along this path. 3. VULNERABILITY DESCRIPTION The endpoint index is derived as: id =3D udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK; USB_ENDPOINT_NUMBER_MASK is 0x0f, producing values in the range 0=E2=80=931= 5. The backing storage is: struct max3420_ep ep[MAX3420_MAX_EPS]; where: MAX3420_MAX_EPS =3D 4 Valid indices are therefore 0=E2=80=933. Values >=3D 4 will index beyond th= e bounds of the array. 4. SOURCE CODE ANALYSIS 4.1 Untrusted input propagation spi_rd_buf(udc, MAX3420_REG_SUDFIFO, (void *)&setup, 8); udc->setup =3D setup; udc->setup.wIndex =3D cpu_to_le16(setup.wIndex); The SETUP packet contents are populated by the USB host and copied into driver state without validation. The wIndex field is later used in control flow and memory access decisions. 4.2 Direct indexing into fixed-size array ep =3D &udc->ep[udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK]; and: id =3D udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK; ep =3D &udc->ep[id]; There is no check ensuring the derived index is less than MAX3420_MAX_EPS before dereferencing. 4.3 Affected call sites The pattern appears in: - max3420_getstatus() - max3420_set_clear_feature() Both paths derive an index from wIndex and use it to access udc->ep[]. 4.4 Existing checks are not sufficient if (udc->setup.wIndex & USB_DIR_IN) This condition only evaluates the direction bit and does not constrain the endpoint number. It does not prevent out-of-bounds indexing. 4.5 Invariant violation Regardless of protocol expectations, memory safety requires that any externally influenced index used for array access be validated against the array bounds. Here, the code assumes the masked value is valid without enforcing that constraint, which can lead to out-of-bounds access if unexpected values are received. 5. IMPACT Out-of-bounds read: In max3420_getstatus(), fields are read from ep. If the index is out-of-bounds, this may result in reading adjacent memory. Out-of-bounds write: In max3420_set_clear_feature(), fields within ep are modified (including locking and state flags). If ep is out-of-bounds, this may result in writes to unrelated memory. Memory corruption characteristics: Because ep[] is embedded within struct max3420_udc as a fixed-size array: - out-of-bounds indexing accesses memory beyond the array within the same s= truct - this may overlap adjacent struct members depending on layout - further out-of-bounds accesses may extend beyond the struct into surrounding memory depending on allocation context Trigger: A malformed USB control request can supply an out-of-range wIndex value, for example: bmRequestType =3D 0x02 (TYPE_STANDARD | RECIP_ENDPOINT) bRequest =3D SET_FEATURE wValue =3D ENDPOINT_HALT wIndex =3D 0x0007 wLength =3D 0 This produces an index of 7, which exceeds the valid range [0=E2=80=933]. 6. VALIDATION EXPECTATION The driver processes externally supplied USB control requests and should validate fields before using them in memory access operations. Other UDC drivers typically constrain endpoint indices or validate request parameters before indexing fixed-size arrays. The absence of such validation here suggests a missing bounds check. 7. SUGGESTED FIX Validate the derived endpoint index before accessing the array: id =3D udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK; if (id >=3D MAX3420_MAX_EPS) goto stall; This check should be applied consistently in both: - max3420_getstatus() - max3420_set_clear_feature() 8. AFFECTED VERSIONS Affected: all kernels including the MAX3420 UDC driver Fixed in: not yet patched 9. REACHABILITY ANALYSIS (CODE-LEVEL) The vulnerable access is reachable through the standard USB control request handling path. 9.1 Interrupt entry point USB SETUP packet handling is triggered from the IRQ path: max3420_handle_irqs() Relevant code: if (epirq & SUDAVIRQ) { spi_wr8(udc, MAX3420_REG_EPIRQ, SUDAVIRQ); max3420_handle_setup(udc); return true; } Receipt of a SETUP packet (SUDAVIRQ) directly invokes max3420_handle_setup(= ). 9.2 SETUP packet ingestion from hardware The SETUP packet is read directly from hardware: spi_rd_buf(udc, MAX3420_REG_SUDFIFO, (void *)&setup, 8); udc->setup =3D setup; udc->setup.wValue =3D cpu_to_le16(setup.wValue); udc->setup.wIndex =3D cpu_to_le16(setup.wIndex); udc->setup.wLength =3D cpu_to_le16(setup.wLength); No validation or bounds checking is performed on wIndex before storing it. 9.3 Dispatch into request handlers Standard USB requests are dispatched as follows: case USB_REQ_GET_STATUS: return max3420_getstatus(udc); case USB_REQ_CLEAR_FEATURE: case USB_REQ_SET_FEATURE: return max3420_set_clear_feature(udc); This dispatch occurs without validating the endpoint index derived from wIn= dex. 9.4 Out-of-bounds access in max3420_getstatus() ep =3D &udc->ep[udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK]; No bounds check is performed before dereferencing ep. 9.5 Out-of-bounds access in max3420_set_clear_feature() id =3D udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK; ep =3D &udc->ep[id]; No validation ensures id < MAX3420_MAX_EPS. 9.6 Array bounds vs index range Array definition: struct max3420_ep ep[MAX3420_MAX_EPS]; #define MAX3420_MAX_EPS 4 Valid indices: 0=E2=80=933. Index derivation produces values 0=E2=80=9315. = Values >=3D 4 result in out-of-bounds access. 9.7 End-to-end reachability USB host =E2=86=92 SETUP packet =E2=86=92 MAX3420_REG_SUDFIFO =E2=86=92 spi_rd_buf(...) =E2=86=92 udc->setup.wIndex (unvalidated) =E2=86=92 max3420_getstatus() / max3420_set_clear_feature() =E2=86=92 ep =3D &udc->ep[id] =E2=86=92 out-of-bounds access when id >=3D 4 This path requires only a valid USB control request targeting an endpoint and does not rely on undefined behavior or malformed packet structure. 10. RUNTIME EVIDENCE (USERSPACE HARNESS) Hardware emulation for the MAX3420 SPI controller is unavailable in QEMU. A userspace harness was constructed that reconstructs the vulnerable struct layout and control flow from max3420_udc.c verbatim, feeding attacker-controlled SETUP packet fields directly into the dispatch path. AddressSanitizer confirms the out-of-bounds write at the exact offset predicted by the struct layout analysis. Build: gcc -fsanitize=3Daddress,undefined -g -O0 -o max3420_poc max3420_oob_ha= rness.c Trigger packet (wIndex=3D0x0007, derived id=3D7): bmRequestType =3D 0x02 bRequest =3D SET_FEATURE wValue =3D ENDPOINT_HALT wIndex =3D 0x0007 wLength =3D 0x0000 ASan output: max3420_oob_harness.c:154:26: runtime error: index 7 out of bounds for type 'max3420_ep [4]' ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7c78019e0680 WRITE of size 1 at 0x7c78019e0680 thread T0 #0 max3420_set_clear_feature max3420_oob_harness.c:163 #1 run_test max3420_oob_harness.c:223 #2 main max3420_oob_harness.c:282 0x7c78019e0680 is located 168 bytes after 280-byte region SUMMARY: AddressSanitizer: heap-buffer-overflow in max3420_set_clear_fe= ature Struct layout confirms ep[4] overlaps irq_registered at offset 256. ep[7] lands 168 bytes past the struct boundary. The harness source is available on request. Regards, Pavitra Jha jhapavitra98@gmail.com