summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPiyush Paliwal <[email protected]>2026-06-12 13:17:30 +0530
committerJerome Forissier <[email protected]>2026-06-23 13:13:16 +0200
commit91d5e0ee3e857c76bb05f0c69c21f3d4a150a2e6 (patch)
treea87e57ed546c7838f7be897824b12dbfb9f1efdc
parent9f7906a58cf194fc43484f5be4b65e368fa59040 (diff)
net: cdp: reject CDP TLVs with a length below the 4-byte header
cdp_receive() reads a 16-bit TLV length (tlen) from the packet and only checks that it does not exceed the remaining buffer (tlen > len). It then unconditionally does "tlen -= 4" to skip the TLV header. As tlen is a u16, a crafted TLV with a length of 0..3 underflows tlen to ~65532-65535. For a CDP_APPLIANCE_VLAN_TLV the underflowed length then drives the inner "while (tlen > 0)" loop, which walks ~64KB past the receive buffer reading *ss each step -> out-of-bounds read (crash / info-influence). A length of 0 additionally fails to advance pkt/len, hanging the parse loop. Reject any TLV whose declared length is smaller than its own 4-byte header. This is the same class of bug as the recent bootp/dhcpv6/sntp/nfs fixes (unchecked length field), in a sibling LAN parser that was missed. Verified with a standalone AddressSanitizer harness using the verbatim cdp_receive()/cdp_compute_csum() routines: a 16-byte CDP frame with an appliance-VLAN TLV of length 3 triggers a heap-buffer-overflow READ that the check eliminates. Fixes: f575ae1f7d39 ("net: Move CDP out of net.c") Cc: [email protected] Signed-off-by: Piyush Paliwal <[email protected]> Reviewed-by: Jerome Forissier <[email protected]>
-rw-r--r--net/cdp.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/net/cdp.c b/net/cdp.c
index 6e404981d4a..300b3d5c409 100644
--- a/net/cdp.c
+++ b/net/cdp.c
@@ -276,7 +276,13 @@ void cdp_receive(const uchar *pkt, unsigned len)
ss = (const ushort *)pkt;
type = ntohs(ss[0]);
tlen = ntohs(ss[1]);
- if (tlen > len)
+ /*
+ * tlen includes the 4-byte TLV header, so it must be at
+ * least 4. Without this check a crafted tlen < 4 makes the
+ * "tlen -= 4" below underflow (tlen is a ushort), and a tlen
+ * of 0 also fails to advance pkt/len, hanging the loop.
+ */
+ if (tlen < 4 || tlen > len)
goto pkt_short;
pkt += tlen;