diff options
| author | Zhixing Chen <running910@gmail.com> | 2026-07-08 12:22:44 +0800 |
|---|---|---|
| committer | Paolo Abeni <pabeni@redhat.com> | 2026-07-21 11:23:30 +0200 |
| commit | 96e37e2f618e931aa97af95e707dcdfb1ec41264 (patch) | |
| tree | f744ea907ca82115562a629e60ae2a76b1758eea | |
| parent | 5521ae71e32a8069ed4ca6e792179dc57bc43ab2 (diff) | |
| download | linux-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.c | 12 |
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); } |
