[PATCH] nfc: llcp: validate TLV bounds when parsing CONNECT service name
From: Naveed Khan
Date: Mon Jun 22 2026 - 06:58:04 EST
nfc_llcp_connect_sn() walks the TLV array of a received LLCP CONNECT PDU
to locate the service name (SN) parameter, but it never checks that a TLV
stays within the packet. The two-byte TLV header is read as soon as
offset < tlv_array_len, so when only a single byte is left the length byte
tlv[1] is read past the end of skb->data. When an SN TLV is found its
declared length is stored in *sn_len and a pointer just past the length
byte is returned, again without verifying that 'length' value bytes are
present. The caller hands the result to nfc_llcp_sock_from_sn(), which does
memcmp(sn, service_name, sn_len), reading up to 255 bytes out of bounds.
A remote peer can trigger this by sending a CONNECT PDU addressed to the
SDP SAP that carries a truncated SN TLV, or a TLV whose declared length
exceeds the remaining frame.
Make sure two bytes are available before reading the TLV header and that
the whole type/length/value triplet fits in the remaining buffer before
using or skipping it. tlv_array_len and offset are size_t and offset is
only advanced when the TLV fits, so the subtractions cannot wrap.
Signed-off-by: Naveed Khan <naveed@xxxxxxxxxxxxxx>
---
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
index dc65c719f3..f437d82b3d 100644
--- a/net/nfc/llcp_core.c
+++ b/net/nfc/llcp_core.c
@@ -853,11 +853,17 @@ static const u8 *nfc_llcp_connect_sn(const struct sk_buff *skb, size_t *sn_len)
size_t tlv_array_len = skb->len - LLCP_HEADER_SIZE, offset = 0;
while (offset < tlv_array_len) {
+ if (tlv_array_len - offset < 2)
+ break;
+
type = tlv[0];
length = tlv[1];
pr_debug("type 0x%x length %d\n", type, length);
+ if (tlv_array_len - offset < length + 2U)
+ break;
+
if (type == LLCP_TLV_SN) {
*sn_len = length;
return &tlv[2];
--
2.52.0