[PATCH net 1/2] pfcp: fix metadata_dst leak in pfcp_encap_recv()
From: Haishuang Yan
Date: Wed Sep 30 2026 - 11:20:09 EST
pfcp_encap_recv() allocates tun_dst with udp_tun_rx_dst() but only
attaches it to the skb after iptunnel_pull_header() has succeeded.
When iptunnel_pull_header() fails, the code jumps to the drop label,
which frees the skb but not tun_dst, so the metadata_dst is leaked.
iptunnel_pull_header() can fail for a GSO skb that is cloned, when
skb_unclone() cannot allocate a new header with GFP_ATOMIC.
The dst cannot simply be attached earlier, since skb_scrub_packet() in
iptunnel_pull_header() drops it for cross-netns devices. Release it
explicitly on the error paths instead. The !md check can never be true,
but route it through the same label for consistency.
Fixes: 6dd514f48110 ("pfcp: always set pfcp metadata")
Signed-off-by: Haishuang Yan <yanhaishuang@xxxxxxxxxxxxxxxxxxxx>
---
drivers/net/pfcp.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/pfcp.c b/drivers/net/pfcp.c
index e1cca779d2ec..1d14baf27c64 100644
--- a/drivers/net/pfcp.c
+++ b/drivers/net/pfcp.c
@@ -74,7 +74,7 @@ static int pfcp_encap_recv(struct sock *sk, struct sk_buff *skb)
md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
if (unlikely(!md))
- goto drop;
+ goto drop_dst;
if (unparsed->flags & PFCP_SEID_FLAG)
pfcp_session_recv(pfcp, skb, md);
@@ -87,7 +87,7 @@ static int pfcp_encap_recv(struct sock *sk, struct sk_buff *skb)
if (unlikely(iptunnel_pull_header(skb, PFCP_HLEN, skb->protocol,
!net_eq(sock_net(sk),
dev_net(pfcp->dev)))))
- goto drop;
+ goto drop_dst;
skb_dst_set(skb, (struct dst_entry *)tun_dst);
@@ -98,6 +98,8 @@ static int pfcp_encap_recv(struct sock *sk, struct sk_buff *skb)
gro_cells_receive(&pfcp->gro_cells, skb);
return 0;
+drop_dst:
+ dst_release(&tun_dst->dst);
drop:
kfree_skb(skb);
return 0;
--
2.43.0