[BUG] nfc: llcp: u16 size truncation in nfc_llcp_allocate_snl() leads to skb_over_panic

From: Guikun Yang

Date: Sat Oct 24 2026 - 11:59:05 EST


Hi David,

nfc_llcp_allocate_snl() computes the SNL skb size in a u16 while taking
the TLV payload length as size_t:

static struct sk_buff *nfc_llcp_allocate_snl(struct nfc_llcp_local *local,
size_t tlv_length)
{
struct sk_buff *skb;
struct nfc_dev *dev;
u16 size = 0;
...
size += LLCP_HEADER_SIZE;
size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
size += tlv_length;

skb = alloc_skb(size, GFP_KERNEL);

The addition silently wraps when tlv_length + the constant part exceeds
65535. The caller then writes the full tlv_length bytes into the
undersized skb:

hlist_for_each_entry_safe(sdreq, n, tlv_list, node) {
skb_put_data(skb, sdreq->tlv, sdreq->tlv_len);
...
}

skb_put() detects the overrun and calls skb_over_panic(), i.e. BUG().

tlv_length originates from a control-plane request and is not bounded
anywhere on this path:

nfc_genl_llc_sdreq() walks every NFC_SDP_ATTR_URI sub-attribute of the
NFC_ATTR_LLC_SDP nest, builds one TLV per URI and accumulates its length:

uri_len = nla_len(sdp_attrs[NFC_SDP_ATTR_URI]);
...
sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len);
...
tlvs_len += sdreq->tlv_len;

tlvs_len is a size_t, so the accumulation itself is fine; only the
conversion to u16 in nfc_llcp_allocate_snl() truncates.

Reachability: nfc_llcp_build_sdreq_tlv() caps a single TLV at 254 bytes
(uri_len <= U8_MAX - 4 = 251, plus 3 bytes of TLV header). The only
limit on the number of TLVs is the netlink message size, which
netlink_sendmsg() bounds by sk_sndbuf - 32 (212992 - 32 by default), so
a message of roughly 66 KB is accepted. With N SDP attributes carrying
251-byte URIs (256 bytes each on the wire), N = 259 yields

tlvs_len = 259 * 254 = 65786
size = 12 + 65786 = 65798, which truncates to 294

alloc_skb(294) succeeds, and the second skb_put_data() already walks past
skb->end.

NFC_CMD_LLC_SDREQ is GENL_ADMIN_PERM, so this needs CAP_NET_ADMIN in the
netns where the request is issued, plus an NFC device with an activated
LLCP link (dev->dep_link_up must be set). nfcsim provides such a device
from software, with tx_headroom = DIGITAL_MAX_HEADER_LEN (7) and
tx_tailroom = DIGITAL_CRC_LEN (2), which is exactly the constant part
used above.

Suggested fix: declare the accumulator as size_t (or unsigned int) and
let alloc_skb() fail cleanly for absurd sizes, e.g.

- u16 size = 0;
+ size_t size = 0;

The same u16 pattern exists in nfc_llcp_send_symm() and
nfc_llcp_send_dm(), but there the payload is a fixed 0 or 1 bytes, so
only nfc_llcp_allocate_snl() is affected by a large tlv_length.

Checked against 7.3.0-rc7 and linux-next (2026-10-24); both are
unchanged. syzbot has no matching report (its NFC coverage shows no
llcp entries), and I found no prior report of this particular overflow
on lore/marc. The earlier SNL TLV work (27256cdb290e, and the follow-up
"bound the remaining LLCP TLV parsers to their buffers") addresses
out-of-bounds reads while parsing received TLV lists and does not touch
the size computation here.

Best,
Guikun Yang