Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH v3 0/2] Input: apple_z2 - bound device-reported packet length and finger count
@ 2026-06-15 18:20 Bryam Vargas via B4 Relay
  2026-06-15 18:20 ` [PATCH v3 1/2] Input: apple_z2 - bound the device-reported packet length Bryam Vargas via B4 Relay
  2026-06-15 18:20 ` [PATCH v3 2/2] Input: apple_z2 - bound the device-reported finger count Bryam Vargas via B4 Relay
  0 siblings, 2 replies; 5+ messages in thread
From: Bryam Vargas via B4 Relay @ 2026-06-15 18:20 UTC (permalink / raw)
  To: Sasha Finkelstein, Dmitry Torokhov
  Cc: linux-arm-kernel, linux-kernel, Neal Gompa, asahi, Sven Peter,
	linux-input, Janne Grunau

The Apple Z2 touch controller is across an SPI bus and its reports are not
trusted: a malicious, malfunctioning or counterfeit controller (or an
interposer on the bus) can put arbitrary values in the report header.  Two
such device-supplied fields are used as sizes without being bounded against
the fixed 4000-byte receive buffer, giving the device a heap out-of-bounds
write and a heap out-of-bounds read.  This series bounds both.

Patch 1 bounds the 16-bit packet length before the second SPI transfer
(spi_read() into the 4000-byte rx_buf) -- the OOB write.

Patch 2 bounds the device-reported finger count in apple_z2_parse_touches()
-- the OOB read that is then forwarded to userspace as input events.

The two are paired because, as Dmitry noted on v2 of patch 2, the finger
count alone is not enough: msg_len is itself derived from the device length,
so patch 1 is what makes the patch 2 bound meaningful.  Patch 1 was posted
standalone first and carries Sasha Finkelstein's Reviewed-by; it is unchanged
here.

This v3 series supersedes the two separate postings:
  - packet length (standalone): https://lore.kernel.org/all/20260613-b4-disp-b1926f1a-v1-1-3a277b7c0cfa@proton.me/
  - finger count v1:            https://lore.kernel.org/all/20260613-b4-disp-f0148c89-v1-1-868a48b2a187@proton.me/
  - finger count v2:            https://lore.kernel.org/all/20260613-b4-disp-4ebcbd68-v2-1-0161acfbd688@proton.me/

Changes since the v2 finger-count patch (Dmitry Torokhov review,
https://lore.kernel.org/all/ai8U0QiwpBH8qNS3@google.com/):
- Patch 2: instead of clamping the finger count to what the packet holds
  (v2 used min_t and reported the fingers that fit), drop the whole packet
  when the device claims more fingers than it can hold, with a
  dev_warn_ratelimited(), per Dmitry's "I'd drop such packet" suggestion.
  A legitimate zero-finger ("all lifted") report (nfingers == 0) is still
  passed through to input_mt_sync_frame()/input_sync(), so lifting all
  fingers is not lost.  (Dropped Joshua Peisach's v2 Reviewed-by, as the
  fix shape changed materially from clamp to drop.)
- Patch 2 bound uses the multiplication form
  (msg_len < FINGERS_OFFSET + nfingers * sizeof(*fingers)) rather than a
  (msg_len - FINGERS_OFFSET) subtraction, so there is no unsigned underflow
  when msg_len < FINGERS_OFFSET (which would otherwise re-open the read).
- Patch 1 folded into the series unchanged (Reviewed-by Sasha Finkelstein).

Note on patch 1 (Sasha Finkelstein, on the standalone thread): rejecting an
over-long packet desyncs the SPI datastream and the device then needs a reset
before it operates again.  That is the intended outcome for a controller that
is already misbehaving or hostile -- a recoverable desync is preferable to a
~61 KiB heap overflow -- so the reject is kept.

Verification (in-kernel KASAN, CONFIG_KASAN=y kasan.fault=panic, plus userspace
ASan models of the exact parse arithmetic on x86_64 and i386):
  Patch 1 (packet length): reported length -> pkt_len 65540:
    Arm A (no patch): KASAN slab-out-of-bounds / ASan heap-buffer-overflow WRITE,
      both ABIs.
    Arm B (patch): rejected, clean.   Arm C (benign): clean.
  Patch 2 (finger count, drop shape): nfingers 255 in a short packet (msg_len 19):
    Arm A (no patch): BUG: KASAN: slab-out-of-bounds, Read of size 2, 1 byte to
      the right of the allocated 4000-byte region (cache kmalloc-4k) -> panic;
      ASan heap-buffer-overflow READ, both ABIs.
    Arm B (patch): packet dropped, zero reads, clean, not synced.
    Arm C (benign 3 fingers, msg_len 114): parsed in-bounds, clean, synced.
    Arm D (zero-finger all-lifted, nfingers 0, msg_len 19): clean, synced.
Reproducers and full logs available on request.

---
Bryam Vargas (2):
      Input: apple_z2 - bound the device-reported packet length
      Input: apple_z2 - bound the device-reported finger count

 drivers/input/touchscreen/apple_z2.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)
---
base-commit: 8e65320d91cdc3b241d4b94855c88459b91abf66
change-id: 20260615-b4-disp-05943ee1-9dc5cce670fe

Best regards,
-- 
Bryam Vargas <hexlabsecurity@proton.me>



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-06-15 18:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-15 18:20 [PATCH v3 0/2] Input: apple_z2 - bound device-reported packet length and finger count Bryam Vargas via B4 Relay
2026-06-15 18:20 ` [PATCH v3 1/2] Input: apple_z2 - bound the device-reported packet length Bryam Vargas via B4 Relay
2026-06-15 18:32   ` sashiko-bot
2026-06-15 18:20 ` [PATCH v3 2/2] Input: apple_z2 - bound the device-reported finger count Bryam Vargas via B4 Relay
2026-06-15 18:32   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox