LVS
lvs-devel
Google
 
Web LinuxVirtualServer.org

[PATCH net] ipvs: fix ipv4 null-ptr-deref in route error path

To: horms@xxxxxxxxxxxx, ja@xxxxxx
Subject: [PATCH net] ipvs: fix ipv4 null-ptr-deref in route error path
Cc: pablo@xxxxxxxxxxxxx, kadlec@xxxxxxxxxxxxx, fw@xxxxxxxxx, phil@xxxxxx, davem@xxxxxxxxxxxxx, edumazet@xxxxxxxxxx, kuba@xxxxxxxxxx, pabeni@xxxxxxxxxx, netdev@xxxxxxxxxxxxxxx, lvs-devel@xxxxxxxxxxxxxxx, netfilter-devel@xxxxxxxxxxxxxxx, coreteam@xxxxxxxxxxxxx
From: Slavin Liu <slavin452@xxxxxxxxx>
Date: Fri, 21 Nov 2025 03:03:13 +0800
The IPv4 code path in __ip_vs_get_out_rt() calls dst_link_failure()
without ensuring skb->dev is set, leading to a NULL pointer dereference
in fib_compute_spec_dst() when ipv4_link_failure() attempts to send
ICMP destination unreachable messages.

The bug was introduced in commit 4115ded13164 ("ipvs: consolidate all
dst checks on transmit in one place") which added the err_unreach error
path with a dst_link_failure(skb) call to both __ip_vs_get_out_rt() and
__ip_vs_get_out_rt_v6(). The IPv6 version was subsequently fixed by
commit 326bf17ea5d4 ("ipvs: fix ipv6 route unreach panic"), but the
fix was never applied to the IPv4 code path.

The crash occurs when:
1. IPVS processes a packet in NAT mode with a misconfigured destination
2. Route lookup fails in __ip_vs_get_out_rt() before establishing a route
3. The error path calls dst_link_failure(skb) with skb->dev == NULL
4. ipv4_link_failure() → ipv4_send_dest_unreach() →
   __ip_options_compile() → fib_compute_spec_dst()
5. fib_compute_spec_dst() dereferences NULL skb->dev

Apply the same fix used for IPv6: set skb->dev from skb_dst(skb)->dev
before calling dst_link_failure().

KASAN: null-ptr-deref in range [0x0000000000000328-0x000000000000032f]
CPU: 1 PID: 12732 Comm: syz.1.3469 Not tainted 6.6.114 #2
RIP: 0010:__in_dev_get_rcu include/linux/inetdevice.h:233
RIP: 0010:fib_compute_spec_dst+0x17a/0x9f0 net/ipv4/fib_frontend.c:285
Call Trace:
  <TASK>
  spec_dst_fill net/ipv4/ip_options.c:232
  spec_dst_fill net/ipv4/ip_options.c:229
  __ip_options_compile+0x13a1/0x17d0 net/ipv4/ip_options.c:330
  ipv4_send_dest_unreach net/ipv4/route.c:1252
  ipv4_link_failure+0x702/0xb80 net/ipv4/route.c:1265
  dst_link_failure include/net/dst.h:437
  __ip_vs_get_out_rt+0x15fd/0x19e0 net/netfilter/ipvs/ip_vs_xmit.c:412
  ip_vs_nat_xmit+0x1d8/0xc80 net/netfilter/ipvs/ip_vs_xmit.c:764

Fixes: 4115ded13164 ("ipvs: consolidate all dst checks on transmit in one 
place")
Signed-off-by: Slavin Liu <slavin452@xxxxxxxxx>
---
 net/netfilter/ipvs/ip_vs_xmit.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 95af252b2939..618fbe1240b5 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -409,6 +409,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, 
struct sk_buff *skb,
        return -1;
 
 err_unreach:
+       if (!skb->dev)
+               skb->dev = skb_dst(skb)->dev;
+
        dst_link_failure(skb);
        return -1;
 }
-- 
2.43.0



<Prev in Thread] Current Thread [Next in Thread>