public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] nfc: llcp: fix u8 offset truncation in LLCP TLV parsers
@ 2026-04-05 10:59 Lekë Hapçiu
  2026-04-09 16:41 ` Simon Horman
  0 siblings, 1 reply; 6+ messages in thread
From: Lekë Hapçiu @ 2026-04-05 10:59 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, kuba, pabeni, horms, stable, linux-kernel,
	Lekë Hapçiu

From: Lekë Hapçiu <framemain@outlook.com>

nfc_llcp_parse_gb_tlv() and nfc_llcp_parse_connection_tlv() declare
'offset' as u8, but compare it against a u16 tlv_array_len:

    u8 type, length, offset = 0;
    while (offset < tlv_array_len) {   /* tlv_array_len is u16 */
        ...
        offset += length + 2;          /* wraps at 256 */
        tlv    += length + 2;
    }

When tlv_array_len > 255 -- possible in nfc_llcp_parse_connection_tlv()
when the peer has negotiated MIUX = 0x7FF (MIU = 2175 bytes), so that
a CONNECT PDU can carry a TLV array of up to 2173 bytes -- the u8
offset wraps back below tlv_array_len after every 128 zero-length TLV
entries and the loop never terminates.  The 'tlv' pointer meanwhile
advances without bound into adjacent kernel heap, causing:

  * an OOB read of kernel heap content past the skb end;
  * a kernel page fault / oops once 'tlv' leaves mapped memory.

This is reachable from any NFC P2P peer device within ~4 cm without
requiring compromised NFCC firmware.

Fix: promote 'offset' from u8 to u16 in both parsers, matching the
type of their tlv_array_len parameter.

nfc_llcp_parse_gb_tlv() takes GB bytes from the ATR_RES (max 44 bytes),
so the wrap cannot occur in practice there.  Change it anyway for
correctness and to prevent copy-paste reintroduction.

Cc: stable@vger.kernel.org
Signed-off-by: Lekë Hapçiu <framemain@outlook.com>
---
 net/nfc/llcp_commands.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c
index 291f26fac..6937dcb3b 100644
--- a/net/nfc/llcp_commands.c
+++ b/net/nfc/llcp_commands.c
@@ -193,7 +193,8 @@ int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
 			  const u8 *tlv_array, u16 tlv_array_len)
 {
 	const u8 *tlv = tlv_array;
-	u8 type, length, offset = 0;
+	u8 type, length;
+	u16 offset = 0;
 
 	pr_debug("TLV array length %d\n", tlv_array_len);
 
@@ -243,7 +244,8 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
 				  const u8 *tlv_array, u16 tlv_array_len)
 {
 	const u8 *tlv = tlv_array;
-	u8 type, length, offset = 0;
+	u8 type, length;
+	u16 offset = 0;
 
 	pr_debug("TLV array length %d\n", tlv_array_len);
 
-- 
2.51.0


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

end of thread, other threads:[~2026-04-09 19:01 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-05 10:59 [PATCH] nfc: llcp: fix u8 offset truncation in LLCP TLV parsers Lekë Hapçiu
2026-04-09 16:41 ` Simon Horman
2026-04-09 18:59   ` [PATCH net v2 0/3] nfc: fix chained TLV parsing and integer underflow vulnerabilities Lekë Hapçiu
2026-04-09 18:59     ` [PATCH net v2 1/3] nfc: nci: fix u8 underflow in nci_store_general_bytes_nfc_dep Lekë Hapçiu
2026-04-09 18:59     ` [PATCH net v2 2/3] nfc: llcp: add TLV length bounds checks in parse_gb_tlv and parse_connection_tlv Lekë Hapçiu
2026-04-09 18:59     ` [PATCH net v2 3/3] nfc: llcp: fix TLV parsing OOB and length underflow in nfc_llcp_recv_snl Lekë Hapçiu

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