Re: [PATCH] nfc: llcp: fix integer underflow and missing bounds checks in TLV parsing
David Heidelberg <[email protected]> Tue, 2 Jun 2026 13:12:52 +0200
| Newsgroups | dev.linux.lists.oe-linux-nfc,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
On 25/05/2026 22:24, Doruk Tan Ozturk wrote: > Multiple out-of-bounds read vulnerabilities exist in the NFC LLCP TLV > parsers: > > 1. In nfc_llcp_recv_snl(), when an SDREQ TLV has length == 0, > service_name_len = length - 1 underflows to SIZE_MAX (size_t is > unsigned). The subsequent strncmp() and nfc_llcp_sock_from_sn() > calls then read unbounded kernel heap memory. > > 2. All LLCP TLV parsing loops (nfc_llcp_recv_snl, nfc_llcp_connect_sn, > nfc_llcp_parse_gb_tlv, nfc_llcp_parse_connection_tlv) read tlv[0] > and tlv[1] without first verifying that at least 2 bytes remain in > the buffer. > > A nearby malicious NFC device can trigger these without authentication -- > LLCP link activation happens automatically after NFC-DEP. > > Fix by adding a minimum length check before the subtraction in the > SDREQ case, and adding bounds validation at the top of each TLV loop > iteration. > > Found by pwnkit (https://github.com/0sec-labs/pwnkit), an automated > kernel source review tool by 0sec (https://0sec.ai). > > Signed-off-by: Doruk Tan Ozturk <[email protected]> > --- > net/nfc/llcp_core.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c > index XXXXXXX..YYYYYYY 100644 Hello Doruk, thank you for your patch. The patch won't apply cleanly, could you please resent patch based against recent https://codeberg.org/linux-nfc/linux/commits/branch/for-next ? > --- a/net/nfc/llcp_core.c > +++ b/net/nfc/llcp_core.c > @@ -1300,6 +1300,9 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, > > while (offset < tlv_len) { > + if (offset + 2 > tlv_len) I think it would be more descriptive use define, thus (offset + LLCP_HEADER_SIZE > tlv_len) David > + break; > + > type = tlv[0]; > length = tlv[1]; > > @@ -1307,6 +1310,9 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, > switch (type) { > case LLCP_TLV_SDREQ: > + if (length < 1) > + break; > + > tid = tlv[2]; > service_name = (char *) &tlv[3]; > service_name_len = length - 1; -- David Heidelberg