summaryrefslogtreecommitdiff
path: root/drivers/net/gtp.c
diff options
context:
space:
mode:
authorXiang Mei (Microsoft) <xmei5@asu.edu>2026-07-10 23:07:24 +0000
committerJakub Kicinski <kuba@kernel.org>2026-07-21 15:02:29 -0700
commitcd170f051dba9ac146fabcd1b91726487c0cb9fa (patch)
treeb1c177e61bb58220185313c2ea35889a145e1046 /drivers/net/gtp.c
parente5f9476960085496533420eb59d70a2bef7e1d60 (diff)
downloadlinux-next-cd170f051dba9ac146fabcd1b91726487c0cb9fa.tar.gz
linux-next-cd170f051dba9ac146fabcd1b91726487c0cb9fa.zip
gtp: check skb_pull_data() return in gtp1u_send_echo_resp()
gtp1u_send_echo_resp() ignores skb_pull_data()'s return value. Its caller gtp1u_udp_encap_recv() only guarantees 16 bytes (udphdr + gtp1_header), but the pull requests 20 (gtp1_header_long + udphdr). For a 16-19 byte echo request the pull fails and returns NULL without advancing skb->data; execution continues, and the following skb_push() plus the IP header pushed by iptunnel_xmit() move skb->data below skb->head, tripping skb_under_panic(). Fix it by dropping the packet when skb_pull_data() fails. skbuff: skb_under_panic: ... kernel BUG at net/core/skbuff.c:214! Call Trace: skb_push (net/core/skbuff.c:2648) iptunnel_xmit (net/ipv4/ip_tunnel_core.c:82) gtp_encap_recv (drivers/net/gtp.c:701 drivers/net/gtp.c:808 drivers/net/gtp.c:920) udp_queue_rcv_one_skb (net/ipv4/udp.c:2388) ... Kernel panic - not syncing: Fatal exception in interrupt Fixes: 9af41cc33471 ("gtp: Implement GTP echo response") Reported-by: AutonomousCodeSecurity@microsoft.com Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu> Link: https://patch.msgid.link/20260710230724.942574-1-xmei5@asu.edu Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/gtp.c')
-rw-r--r--drivers/net/gtp.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index c0e38878af51..9a12cc53da00 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -669,8 +669,9 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb)
return -1;
/* pull GTP and UDP headers */
- skb_pull_data(skb,
- sizeof(struct gtp1_header_long) + sizeof(struct udphdr));
+ if (!skb_pull_data(skb, sizeof(struct gtp1_header_long) +
+ sizeof(struct udphdr)))
+ return -1;
gtp_pkt = skb_push(skb, sizeof(struct gtp1u_packet));
memset(gtp_pkt, 0, sizeof(struct gtp1u_packet));