[PATCH net v2] nfc: llcp: drop truncated I/RR/RNR PDUs in nfc_llcp_recv_hdlc()

From: Aamir Ahmed

Date: Tue Sep 15 2026 - 14:57:38 EST


nfc_llcp_recv_hdlc() reads the sequence byte skb->data[2], via
nfc_llcp_ns()/nfc_llcp_nr(), before any length check. The receive path
only guarantees the two-byte LLCP header -- __nfc_llcp_recv() checks it
with pskb_may_pull() and nfc_llcp_recv_agf() admits two-byte inner PDUs
-- so a two-byte I, RR or RNR PDU reads one byte of uninitialised skb
tailroom. The byte becomes N(R)/N(S); a peer can already set those with
a well-formed PDU, so this is acting on uninitialised memory, not new
peer control.

Guard the read with pskb_may_pull(), as commit 95674f506c63 ("nfc: llcp:
reject PDUs shorter than the LLCP header") did for the two-byte header,
so the sequence byte is present and linear before it is read. RR and RNR
PDUs are LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE bytes and an I PDU is
longer, so no valid frame is rejected; a truncated PDU is malformed, so
return without a DM reply.

Fixes: d646960f7986 ("NFC: Initial LLCP support")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Signed-off-by: Aamir Ahmed <elb12345@xxxxxxxxxxxxx>
---

Notes:
v2:
- scope to nfc_llcp_recv_hdlc() only; the recv_dm() half duplicated
Lekë Hapçiu's pending fix (20260729011547.19191-2-snowwlake@xxxxxxxxxx)
- return silently instead of answering DM(NOCONN) as v1 did, which would
close an established peer connection (Sashiko)
- guard with pskb_may_pull(), matching commit 95674f506c63
- add Assisted-by, target net, Cc the right lists, reword the changelog
v1: https://lore.kernel.org/netdev/AS8P251MB0001E8602F36054CDD8979A2C8B32@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

Built net/nfc/llcp_core.o on v7.3-rc1 with KASAN and W=1, no warnings.
No NFC hardware; not runtime-tested.

net/nfc/llcp_core.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
index cac1b54..c553123 100644
--- a/net/nfc/llcp_core.c
+++ b/net/nfc/llcp_core.c
@@ -1074,6 +1074,9 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
struct sock *sk;
u8 dsap, ssap, ptype, ns, nr;

+ if (!pskb_may_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE))
+ return;
+
ptype = nfc_llcp_ptype(skb);
dsap = nfc_llcp_dsap(skb);
ssap = nfc_llcp_ssap(skb);
--
2.53.0.windows.1