summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhixing Chen <running910@gmail.com>2026-07-08 12:22:44 +0800
committerPaolo Abeni <pabeni@redhat.com>2026-07-21 11:23:30 +0200
commit96e37e2f618e931aa97af95e707dcdfb1ec41264 (patch)
treef744ea907ca82115562a629e60ae2a76b1758eea
parent5521ae71e32a8069ed4ca6e792179dc57bc43ab2 (diff)
downloadlinux-96e37e2f618e931aa97af95e707dcdfb1ec41264.tar.gz
linux-96e37e2f618e931aa97af95e707dcdfb1ec41264.zip
gtp: parse extension headers before reading inner protocol
GTPv1-U packets may carry a chain of extension headers before the inner IP packet. The receive path already parses and skips these extension headers, but it currently reads the inner protocol before doing so. As a result, the first extension header byte is interpreted as the inner IP version. Packets with extension headers are then dropped before PDP lookup. Parse the extension header chain before calling gtp_inner_proto(), so the inner protocol is read from the actual inner IP header. Fixes: c75fc0b9e5be ("gtp: identify tunnel via GTP device + GTP version + TEID + family") Signed-off-by: Zhixing Chen <running910@gmail.com> Link: https://patch.msgid.link/20260708042244.120898-1-running910@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r--drivers/net/gtp.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index a60ef32b35b8..c0e38878af51 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -826,13 +826,17 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
if (!pskb_may_pull(skb, hdrlen))
return -1;
+ gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr));
+
+ if (gtp1->flags & GTP1_F_EXTHDR &&
+ gtp_parse_exthdrs(skb, &hdrlen) < 0)
+ return -1;
+
if (gtp_inner_proto(skb, hdrlen, &inner_proto) < 0) {
netdev_dbg(gtp->dev, "GTP packet does not encapsulate an IP packet\n");
return -1;
}
- gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr));
-
pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid),
gtp_proto_to_family(inner_proto));
if (!pctx) {
@@ -840,10 +844,6 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
return 1;
}
- if (gtp1->flags & GTP1_F_EXTHDR &&
- gtp_parse_exthdrs(skb, &hdrlen) < 0)
- return -1;
-
return gtp_rx(pctx, skb, hdrlen, gtp->role, inner_proto);
}