[PATCH net] atm: br2684: validate IP header length before filtering

From: Yizhou Zhao

Date: Sun Jun 14 2026 - 04:40:56 EST


When CONFIG_ATM_BR2684_IPFILTER is enabled, packet_fails_filter()
treats skb->data as an IPv4 header whenever the packet protocol is
ETH_P_IP and then reads iph->daddr. That read is not protected by a
check that the pulled skb still contains a full IPv4 header.

This is reachable through the receive path. An LLC-routed IPv4 PDU can
contain only the 8-byte LLC/SNAP header; br2684_push() accepts it,
sets skb->protocol to ETH_P_IP, pulls the LLC header, and leaves
skb->len as 0 before the filter runs. The VC-routed path also reads
iph->version before checking that the skb contains an IPv4 header, so a
2-byte PDU starting with an IPv4 version nibble can reach the same
filter decision.

In both cases the filter can make its pass/drop decision from bytes
outside the packet data. A reproducer using a dummy ATM receive device
filled the skb tailroom with 0xa5 and showed that an 8-byte LLC-routed
PDU and a 2-byte VC-routed PDU were forwarded when the filter prefix was
0xa5a5a5a5, even though neither packet contained an IPv4 destination
address.

Drop IPv4 packets that are shorter than struct iphdr in
packet_fails_filter(), before reading iph->daddr. Also reject
VC-routed packets shorter than struct iphdr before br2684_push() reads
iph->version. Such packets cannot contain a valid IPv4 header, while
normal minimum-sized IPv4 packets continue through the existing filter
logic.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Yizhou Zhao <zhaoyz24@xxxxxxxxxxxxxxxxxxxxx>
Reported-by: Yuxiang Yang <yangyx22@xxxxxxxxxxxxxxxxxxxxx>
Reported-by: Ao Wang <wangao@xxxxxxxxxx>
Reported-by: Xuewei Feng <fengxw06@xxxxxxx>
Reported-by: Qi Li <qli01@xxxxxxxxxxxxxxx>
Reported-by: Ke Xu <xuke@xxxxxxxxxxxxxxx>
Assisted-by: GLM:GLM-5.1
Signed-off-by: Yizhou Zhao <zhaoyz24@xxxxxxxxxxxxxxxxxxxxx>
---
net/atm/br2684.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 6580d67c3456..fa4b1852d72b 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -393,6 +393,7 @@ packet_fails_filter(__be16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
if (brvcc->filter.netmask == 0)
return 0; /* no filter in place */
if (type == htons(ETH_P_IP) &&
+ skb->len >= sizeof(struct iphdr) &&
(((struct iphdr *)(skb->data))->daddr & brvcc->filter.
netmask) == brvcc->filter.prefix)
return 0;
@@ -482,6 +483,8 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)

skb_reset_network_header(skb);
iph = ip_hdr(skb);
+ if (skb->len < sizeof(struct iphdr))
+ goto error;
if (iph->version == 4)
skb->protocol = htons(ETH_P_IP);
else if (iph->version == 6)

--
2.43.0