netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net] net: vxlan: prevent NULL deref in vxlan_xmit_one
@ 2025-11-24 16:30 Antoine Tenart
  2025-11-25  3:51 ` Jakub Kicinski
  2025-11-25  5:56 ` kernel test robot
  0 siblings, 2 replies; 4+ messages in thread
From: Antoine Tenart @ 2025-11-24 16:30 UTC (permalink / raw)
  To: davem, kuba, pabeni, edumazet, andrew+netdev
  Cc: Antoine Tenart, netdev, Liang Li, Beniamino Galvani

Neither sock4 nor sock6 pointers are guaranteed to be non-NULL in
vxlan_xmit_one, e.g. if the iface is brought down. This can lead to the
following NULL dereference:

  BUG: kernel NULL pointer dereference, address: 0000000000000010
  Oops: Oops: 0000 [#1] SMP NOPTI
  RIP: 0010:vxlan_xmit_one+0xbb3/0x1580
  Call Trace:
   vxlan_xmit+0x429/0x610
   dev_hard_start_xmit+0x55/0xa0
   __dev_queue_xmit+0x6d0/0x7f0
   ip_finish_output2+0x24b/0x590
   ip_output+0x63/0x110

Mentioned commits changed the code path in vxlan_xmit_one and as a side
effect the sock4/6 pointer validity checks in vxlan(6)_get_route were
lost. Fix this by adding back checks.

Since both commits being fixed were released in the same version (v6.7)
and are strongly related, bundle the fixes in a single commit.

Reported-by: Liang Li <liali@redhat.com>
Fixes: 6f19b2c136d9 ("vxlan: use generic function for tunnel IPv4 route lookup")
Fixes: 2aceb896ee18 ("vxlan: use generic function for tunnel IPv6 route lookup")
Cc: Beniamino Galvani <b.galvani@gmail.com>
Signed-off-by: Antoine Tenart <atenart@kernel.org>
---
 drivers/net/vxlan/vxlan_core.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index a5c55e7e4d79..137ebdf354a4 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -2454,12 +2454,18 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 
 	rcu_read_lock();
 	if (addr_family == AF_INET) {
-		struct vxlan_sock *sock4 = rcu_dereference(vxlan->vn4_sock);
+		struct vxlan_sock *sock4;
 		u16 ipcb_flags = 0;
 		struct rtable *rt;
 		__be16 df = 0;
 		__be32 saddr;
 
+		sock4 = rcu_dereference(vxlan->vn4_sock);
+		if (unlikely(!sock4)) {
+			reason = SKB_DROP_REASON_DEV_READY;
+			goto tx_error;
+		}
+
 		if (!ifindex)
 			ifindex = sock4->sock->sk->sk_bound_dev_if;
 
@@ -2534,10 +2540,16 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 				    ipcb_flags);
 #if IS_ENABLED(CONFIG_IPV6)
 	} else {
-		struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
+		struct vxlan_sock *sock6;
 		struct in6_addr saddr;
 		u16 ip6cb_flags = 0;
 
+		sock6 = rcu_dereference(vxlan->vn6_sock);
+		if (unlikely(!sock6)) {
+			reason = SKB_DROP_REASON_DEV_READY;
+			goto tx_error;
+		}
+
 		if (!ifindex)
 			ifindex = sock6->sock->sk->sk_bound_dev_if;
 
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net] net: vxlan: prevent NULL deref in vxlan_xmit_one
  2025-11-24 16:30 [PATCH net] net: vxlan: prevent NULL deref in vxlan_xmit_one Antoine Tenart
@ 2025-11-25  3:51 ` Jakub Kicinski
  2025-11-25  8:26   ` Antoine Tenart
  2025-11-25  5:56 ` kernel test robot
  1 sibling, 1 reply; 4+ messages in thread
From: Jakub Kicinski @ 2025-11-25  3:51 UTC (permalink / raw)
  To: Antoine Tenart
  Cc: davem, pabeni, edumazet, andrew+netdev, netdev, Liang Li,
	Beniamino Galvani

On Mon, 24 Nov 2025 17:30:59 +0100 Antoine Tenart wrote:
> Neither sock4 nor sock6 pointers are guaranteed to be non-NULL in
> vxlan_xmit_one, e.g. if the iface is brought down. This can lead to the
> following NULL dereference:
> 
>   BUG: kernel NULL pointer dereference, address: 0000000000000010
>   Oops: Oops: 0000 [#1] SMP NOPTI
>   RIP: 0010:vxlan_xmit_one+0xbb3/0x1580
>   Call Trace:
>    vxlan_xmit+0x429/0x610
>    dev_hard_start_xmit+0x55/0xa0
>    __dev_queue_xmit+0x6d0/0x7f0
>    ip_finish_output2+0x24b/0x590
>    ip_output+0x63/0x110
> 
> Mentioned commits changed the code path in vxlan_xmit_one and as a side
> effect the sock4/6 pointer validity checks in vxlan(6)_get_route were
> lost. Fix this by adding back checks.
> 
> Since both commits being fixed were released in the same version (v6.7)
> and are strongly related, bundle the fixes in a single commit.
> 
> Reported-by: Liang Li <liali@redhat.com>
> Fixes: 6f19b2c136d9 ("vxlan: use generic function for tunnel IPv4 route lookup")
> Fixes: 2aceb896ee18 ("vxlan: use generic function for tunnel IPv6 route lookup")
> Cc: Beniamino Galvani <b.galvani@gmail.com>
> Signed-off-by: Antoine Tenart <atenart@kernel.org>

clang sayeth:

../drivers/net/vxlan/vxlan_core.c:2548:7: warning: variable 'err' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
 2548 |                 if (unlikely(!sock6)) {
      |                     ^~~~~~~~~~~~~~~~
../include/linux/compiler.h:77:22: note: expanded from macro 'unlikely'
   77 | # define unlikely(x)    __builtin_expect(!!(x), 0)
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/net/vxlan/vxlan_core.c:2631:6: note: uninitialized use occurs here
 2631 |         if (err == -ELOOP)
      |             ^~~
../drivers/net/vxlan/vxlan_core.c:2548:3: note: remove the 'if' if its condition is always false
 2548 |                 if (unlikely(!sock6)) {
      |                 ^~~~~~~~~~~~~~~~~~~~~~~
 2549 |                         reason = SKB_DROP_REASON_DEV_READY;
      |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2550 |                         goto tx_error;
      |                         ~~~~~~~~~~~~~~
 2551 |                 }
      |                 ~
../drivers/net/vxlan/vxlan_core.c:2464:7: warning: variable 'err' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
 2464 |                 if (unlikely(!sock4)) {
      |                     ^~~~~~~~~~~~~~~~
../include/linux/compiler.h:77:22: note: expanded from macro 'unlikely'
   77 | # define unlikely(x)    __builtin_expect(!!(x), 0)
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~
../drivers/net/vxlan/vxlan_core.c:2631:6: note: uninitialized use occurs here
 2631 |         if (err == -ELOOP)
      |             ^~~
../drivers/net/vxlan/vxlan_core.c:2464:3: note: remove the 'if' if its condition is always false
 2464 |                 if (unlikely(!sock4)) {
      |                 ^~~~~~~~~~~~~~~~~~~~~~~
 2465 |                         reason = SKB_DROP_REASON_DEV_READY;
      |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2466 |                         goto tx_error;
      |                         ~~~~~~~~~~~~~~
 2467 |                 }
      |                 ~
../drivers/net/vxlan/vxlan_core.c:2352:9: note: initialize the variable 'err' to silence this warning
 2352 |         int err;
      |                ^
      |                 = 0
-- 
pw-bot: cr

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net] net: vxlan: prevent NULL deref in vxlan_xmit_one
  2025-11-24 16:30 [PATCH net] net: vxlan: prevent NULL deref in vxlan_xmit_one Antoine Tenart
  2025-11-25  3:51 ` Jakub Kicinski
@ 2025-11-25  5:56 ` kernel test robot
  1 sibling, 0 replies; 4+ messages in thread
From: kernel test robot @ 2025-11-25  5:56 UTC (permalink / raw)
  To: Antoine Tenart, davem, kuba, pabeni, edumazet, andrew+netdev
  Cc: llvm, oe-kbuild-all, Antoine Tenart, netdev, Liang Li,
	Beniamino Galvani

Hi Antoine,

kernel test robot noticed the following build warnings:

[auto build test WARNING on net/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Antoine-Tenart/net-vxlan-prevent-NULL-deref-in-vxlan_xmit_one/20251125-003536
base:   net/main
patch link:    https://lore.kernel.org/r/20251124163103.23131-1-atenart%40kernel.org
patch subject: [PATCH net] net: vxlan: prevent NULL deref in vxlan_xmit_one
config: loongarch-defconfig (https://download.01.org/0day-ci/archive/20251125/202511251305.hL5BkEXK-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251125/202511251305.hL5BkEXK-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511251305.hL5BkEXK-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/net/vxlan/vxlan_core.c:2548:7: warning: variable 'err' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
    2548 |                 if (unlikely(!sock6)) {
         |                     ^~~~~~~~~~~~~~~~
   include/linux/compiler.h:77:22: note: expanded from macro 'unlikely'
      77 | # define unlikely(x)    __builtin_expect(!!(x), 0)
         |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/vxlan/vxlan_core.c:2631:6: note: uninitialized use occurs here
    2631 |         if (err == -ELOOP)
         |             ^~~
   drivers/net/vxlan/vxlan_core.c:2548:3: note: remove the 'if' if its condition is always false
    2548 |                 if (unlikely(!sock6)) {
         |                 ^~~~~~~~~~~~~~~~~~~~~~~
    2549 |                         reason = SKB_DROP_REASON_DEV_READY;
         |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    2550 |                         goto tx_error;
         |                         ~~~~~~~~~~~~~~
    2551 |                 }
         |                 ~
   drivers/net/vxlan/vxlan_core.c:2464:7: warning: variable 'err' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
    2464 |                 if (unlikely(!sock4)) {
         |                     ^~~~~~~~~~~~~~~~
   include/linux/compiler.h:77:22: note: expanded from macro 'unlikely'
      77 | # define unlikely(x)    __builtin_expect(!!(x), 0)
         |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/vxlan/vxlan_core.c:2631:6: note: uninitialized use occurs here
    2631 |         if (err == -ELOOP)
         |             ^~~
   drivers/net/vxlan/vxlan_core.c:2464:3: note: remove the 'if' if its condition is always false
    2464 |                 if (unlikely(!sock4)) {
         |                 ^~~~~~~~~~~~~~~~~~~~~~~
    2465 |                         reason = SKB_DROP_REASON_DEV_READY;
         |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    2466 |                         goto tx_error;
         |                         ~~~~~~~~~~~~~~
    2467 |                 }
         |                 ~
   drivers/net/vxlan/vxlan_core.c:2352:9: note: initialize the variable 'err' to silence this warning
    2352 |         int err;
         |                ^
         |                 = 0
   2 warnings generated.


vim +2548 drivers/net/vxlan/vxlan_core.c

  2334	
  2335	void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
  2336			    __be32 default_vni, struct vxlan_rdst *rdst, bool did_rsc)
  2337	{
  2338		struct dst_cache *dst_cache;
  2339		struct ip_tunnel_info *info;
  2340		struct ip_tunnel_key *pkey;
  2341		struct ip_tunnel_key key;
  2342		struct vxlan_dev *vxlan = netdev_priv(dev);
  2343		const struct iphdr *old_iph;
  2344		struct vxlan_metadata _md;
  2345		struct vxlan_metadata *md = &_md;
  2346		unsigned int pkt_len = skb->len;
  2347		__be16 src_port = 0, dst_port;
  2348		struct dst_entry *ndst = NULL;
  2349		int addr_family;
  2350		__u8 tos, ttl;
  2351		int ifindex;
  2352		int err;
  2353		u32 flags = vxlan->cfg.flags;
  2354		bool use_cache;
  2355		bool udp_sum = false;
  2356		bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev));
  2357		enum skb_drop_reason reason;
  2358		bool no_eth_encap;
  2359		__be32 vni = 0;
  2360	
  2361		no_eth_encap = flags & VXLAN_F_GPE && skb->protocol != htons(ETH_P_TEB);
  2362		reason = skb_vlan_inet_prepare(skb, no_eth_encap);
  2363		if (reason)
  2364			goto drop;
  2365	
  2366		reason = SKB_DROP_REASON_NOT_SPECIFIED;
  2367		old_iph = ip_hdr(skb);
  2368	
  2369		info = skb_tunnel_info(skb);
  2370		use_cache = ip_tunnel_dst_cache_usable(skb, info);
  2371	
  2372		if (rdst) {
  2373			memset(&key, 0, sizeof(key));
  2374			pkey = &key;
  2375	
  2376			if (vxlan_addr_any(&rdst->remote_ip)) {
  2377				if (did_rsc) {
  2378					/* short-circuited back to local bridge */
  2379					vxlan_encap_bypass(skb, vxlan, vxlan,
  2380							   default_vni, true);
  2381					return;
  2382				}
  2383				goto drop;
  2384			}
  2385	
  2386			addr_family = vxlan->cfg.saddr.sa.sa_family;
  2387			dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;
  2388			vni = (rdst->remote_vni) ? : default_vni;
  2389			ifindex = rdst->remote_ifindex;
  2390	
  2391			if (addr_family == AF_INET) {
  2392				key.u.ipv4.src = vxlan->cfg.saddr.sin.sin_addr.s_addr;
  2393				key.u.ipv4.dst = rdst->remote_ip.sin.sin_addr.s_addr;
  2394			} else {
  2395				key.u.ipv6.src = vxlan->cfg.saddr.sin6.sin6_addr;
  2396				key.u.ipv6.dst = rdst->remote_ip.sin6.sin6_addr;
  2397			}
  2398	
  2399			dst_cache = &rdst->dst_cache;
  2400			md->gbp = skb->mark;
  2401			if (flags & VXLAN_F_TTL_INHERIT) {
  2402				ttl = ip_tunnel_get_ttl(old_iph, skb);
  2403			} else {
  2404				ttl = vxlan->cfg.ttl;
  2405				if (!ttl && vxlan_addr_multicast(&rdst->remote_ip))
  2406					ttl = 1;
  2407			}
  2408			tos = vxlan->cfg.tos;
  2409			if (tos == 1)
  2410				tos = ip_tunnel_get_dsfield(old_iph, skb);
  2411			if (tos && !info)
  2412				use_cache = false;
  2413	
  2414			if (addr_family == AF_INET)
  2415				udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX);
  2416			else
  2417				udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
  2418	#if IS_ENABLED(CONFIG_IPV6)
  2419			switch (vxlan->cfg.label_policy) {
  2420			case VXLAN_LABEL_FIXED:
  2421				key.label = vxlan->cfg.label;
  2422				break;
  2423			case VXLAN_LABEL_INHERIT:
  2424				key.label = ip_tunnel_get_flowlabel(old_iph, skb);
  2425				break;
  2426			default:
  2427				DEBUG_NET_WARN_ON_ONCE(1);
  2428				goto drop;
  2429			}
  2430	#endif
  2431		} else {
  2432			if (!info) {
  2433				WARN_ONCE(1, "%s: Missing encapsulation instructions\n",
  2434					  dev->name);
  2435				goto drop;
  2436			}
  2437			pkey = &info->key;
  2438			addr_family = ip_tunnel_info_af(info);
  2439			dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
  2440			vni = tunnel_id_to_key32(info->key.tun_id);
  2441			ifindex = 0;
  2442			dst_cache = &info->dst_cache;
  2443			if (test_bit(IP_TUNNEL_VXLAN_OPT_BIT, info->key.tun_flags)) {
  2444				if (info->options_len < sizeof(*md))
  2445					goto drop;
  2446				md = ip_tunnel_info_opts(info);
  2447			}
  2448			ttl = info->key.ttl;
  2449			tos = info->key.tos;
  2450			udp_sum = test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags);
  2451		}
  2452		src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
  2453					     vxlan->cfg.port_max, true);
  2454	
  2455		rcu_read_lock();
  2456		if (addr_family == AF_INET) {
  2457			struct vxlan_sock *sock4;
  2458			u16 ipcb_flags = 0;
  2459			struct rtable *rt;
  2460			__be16 df = 0;
  2461			__be32 saddr;
  2462	
  2463			sock4 = rcu_dereference(vxlan->vn4_sock);
  2464			if (unlikely(!sock4)) {
  2465				reason = SKB_DROP_REASON_DEV_READY;
  2466				goto tx_error;
  2467			}
  2468	
  2469			if (!ifindex)
  2470				ifindex = sock4->sock->sk->sk_bound_dev_if;
  2471	
  2472			rt = udp_tunnel_dst_lookup(skb, dev, vxlan->net, ifindex,
  2473						   &saddr, pkey, src_port, dst_port,
  2474						   tos, use_cache ? dst_cache : NULL);
  2475			if (IS_ERR(rt)) {
  2476				err = PTR_ERR(rt);
  2477				reason = SKB_DROP_REASON_IP_OUTNOROUTES;
  2478				goto tx_error;
  2479			}
  2480	
  2481			if (flags & VXLAN_F_MC_ROUTE)
  2482				ipcb_flags |= IPSKB_MCROUTE;
  2483	
  2484			if (!info) {
  2485				/* Bypass encapsulation if the destination is local */
  2486				err = encap_bypass_if_local(skb, dev, vxlan, AF_INET,
  2487							    dst_port, ifindex, vni,
  2488							    &rt->dst, rt->rt_flags);
  2489				if (err)
  2490					goto out_unlock;
  2491	
  2492				if (vxlan->cfg.df == VXLAN_DF_SET) {
  2493					df = htons(IP_DF);
  2494				} else if (vxlan->cfg.df == VXLAN_DF_INHERIT) {
  2495					struct ethhdr *eth = eth_hdr(skb);
  2496	
  2497					if (ntohs(eth->h_proto) == ETH_P_IPV6 ||
  2498					    (ntohs(eth->h_proto) == ETH_P_IP &&
  2499					     old_iph->frag_off & htons(IP_DF)))
  2500						df = htons(IP_DF);
  2501				}
  2502			} else if (test_bit(IP_TUNNEL_DONT_FRAGMENT_BIT,
  2503					    info->key.tun_flags)) {
  2504				df = htons(IP_DF);
  2505			}
  2506	
  2507			ndst = &rt->dst;
  2508			err = skb_tunnel_check_pmtu(skb, ndst, vxlan_headroom(flags & VXLAN_F_GPE),
  2509						    netif_is_any_bridge_port(dev));
  2510			if (err < 0) {
  2511				goto tx_error;
  2512			} else if (err) {
  2513				if (info) {
  2514					struct ip_tunnel_info *unclone;
  2515	
  2516					unclone = skb_tunnel_info_unclone(skb);
  2517					if (unlikely(!unclone))
  2518						goto tx_error;
  2519	
  2520					unclone->key.u.ipv4.src = pkey->u.ipv4.dst;
  2521					unclone->key.u.ipv4.dst = saddr;
  2522				}
  2523				vxlan_encap_bypass(skb, vxlan, vxlan, vni, false);
  2524				dst_release(ndst);
  2525				goto out_unlock;
  2526			}
  2527	
  2528			tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
  2529			ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
  2530			err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
  2531					      vni, md, flags, udp_sum);
  2532			if (err < 0) {
  2533				reason = SKB_DROP_REASON_NOMEM;
  2534				goto tx_error;
  2535			}
  2536	
  2537			udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, saddr,
  2538					    pkey->u.ipv4.dst, tos, ttl, df,
  2539					    src_port, dst_port, xnet, !udp_sum,
  2540					    ipcb_flags);
  2541	#if IS_ENABLED(CONFIG_IPV6)
  2542		} else {
  2543			struct vxlan_sock *sock6;
  2544			struct in6_addr saddr;
  2545			u16 ip6cb_flags = 0;
  2546	
  2547			sock6 = rcu_dereference(vxlan->vn6_sock);
> 2548			if (unlikely(!sock6)) {
  2549				reason = SKB_DROP_REASON_DEV_READY;
  2550				goto tx_error;
  2551			}
  2552	
  2553			if (!ifindex)
  2554				ifindex = sock6->sock->sk->sk_bound_dev_if;
  2555	
  2556			ndst = udp_tunnel6_dst_lookup(skb, dev, vxlan->net, sock6->sock,
  2557						      ifindex, &saddr, pkey,
  2558						      src_port, dst_port, tos,
  2559						      use_cache ? dst_cache : NULL);
  2560			if (IS_ERR(ndst)) {
  2561				err = PTR_ERR(ndst);
  2562				ndst = NULL;
  2563				reason = SKB_DROP_REASON_IP_OUTNOROUTES;
  2564				goto tx_error;
  2565			}
  2566	
  2567			if (flags & VXLAN_F_MC_ROUTE)
  2568				ip6cb_flags |= IP6SKB_MCROUTE;
  2569	
  2570			if (!info) {
  2571				u32 rt6i_flags = dst_rt6_info(ndst)->rt6i_flags;
  2572	
  2573				err = encap_bypass_if_local(skb, dev, vxlan, AF_INET6,
  2574							    dst_port, ifindex, vni,
  2575							    ndst, rt6i_flags);
  2576				if (err)
  2577					goto out_unlock;
  2578			}
  2579	
  2580			err = skb_tunnel_check_pmtu(skb, ndst,
  2581						    vxlan_headroom((flags & VXLAN_F_GPE) | VXLAN_F_IPV6),
  2582						    netif_is_any_bridge_port(dev));
  2583			if (err < 0) {
  2584				goto tx_error;
  2585			} else if (err) {
  2586				if (info) {
  2587					struct ip_tunnel_info *unclone;
  2588	
  2589					unclone = skb_tunnel_info_unclone(skb);
  2590					if (unlikely(!unclone))
  2591						goto tx_error;
  2592	
  2593					unclone->key.u.ipv6.src = pkey->u.ipv6.dst;
  2594					unclone->key.u.ipv6.dst = saddr;
  2595				}
  2596	
  2597				vxlan_encap_bypass(skb, vxlan, vxlan, vni, false);
  2598				dst_release(ndst);
  2599				goto out_unlock;
  2600			}
  2601	
  2602			tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
  2603			ttl = ttl ? : ip6_dst_hoplimit(ndst);
  2604			skb_scrub_packet(skb, xnet);
  2605			err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
  2606					      vni, md, flags, udp_sum);
  2607			if (err < 0) {
  2608				reason = SKB_DROP_REASON_NOMEM;
  2609				goto tx_error;
  2610			}
  2611	
  2612			udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev,
  2613					     &saddr, &pkey->u.ipv6.dst, tos, ttl,
  2614					     pkey->label, src_port, dst_port, !udp_sum,
  2615					     ip6cb_flags);
  2616	#endif
  2617		}
  2618		vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX, pkt_len);
  2619	out_unlock:
  2620		rcu_read_unlock();
  2621		return;
  2622	
  2623	drop:
  2624		dev_dstats_tx_dropped(dev);
  2625		vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0);
  2626		kfree_skb_reason(skb, reason);
  2627		return;
  2628	
  2629	tx_error:
  2630		rcu_read_unlock();
  2631		if (err == -ELOOP)
  2632			DEV_STATS_INC(dev, collisions);
  2633		else if (err == -ENETUNREACH)
  2634			DEV_STATS_INC(dev, tx_carrier_errors);
  2635		dst_release(ndst);
  2636		DEV_STATS_INC(dev, tx_errors);
  2637		vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_ERRORS, 0);
  2638		kfree_skb_reason(skb, reason);
  2639	}
  2640	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net] net: vxlan: prevent NULL deref in vxlan_xmit_one
  2025-11-25  3:51 ` Jakub Kicinski
@ 2025-11-25  8:26   ` Antoine Tenart
  0 siblings, 0 replies; 4+ messages in thread
From: Antoine Tenart @ 2025-11-25  8:26 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, pabeni, edumazet, andrew+netdev, netdev, Liang Li,
	Beniamino Galvani

On Mon, Nov 24, 2025 at 07:51:19PM -0800, Jakub Kicinski wrote:
> On Mon, 24 Nov 2025 17:30:59 +0100 Antoine Tenart wrote:
> > Neither sock4 nor sock6 pointers are guaranteed to be non-NULL in
> > vxlan_xmit_one, e.g. if the iface is brought down. This can lead to the
> > following NULL dereference:
> > 
> >   BUG: kernel NULL pointer dereference, address: 0000000000000010
> >   Oops: Oops: 0000 [#1] SMP NOPTI
> >   RIP: 0010:vxlan_xmit_one+0xbb3/0x1580
> >   Call Trace:
> >    vxlan_xmit+0x429/0x610
> >    dev_hard_start_xmit+0x55/0xa0
> >    __dev_queue_xmit+0x6d0/0x7f0
> >    ip_finish_output2+0x24b/0x590
> >    ip_output+0x63/0x110
> > 
> > Mentioned commits changed the code path in vxlan_xmit_one and as a side
> > effect the sock4/6 pointer validity checks in vxlan(6)_get_route were
> > lost. Fix this by adding back checks.
> > 
> > Since both commits being fixed were released in the same version (v6.7)
> > and are strongly related, bundle the fixes in a single commit.
> > 
> > Reported-by: Liang Li <liali@redhat.com>
> > Fixes: 6f19b2c136d9 ("vxlan: use generic function for tunnel IPv4 route lookup")
> > Fixes: 2aceb896ee18 ("vxlan: use generic function for tunnel IPv6 route lookup")
> > Cc: Beniamino Galvani <b.galvani@gmail.com>
> > Signed-off-by: Antoine Tenart <atenart@kernel.org>
> 
> clang sayeth:
> 
> ../drivers/net/vxlan/vxlan_core.c:2548:7: warning: variable 'err' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
>  2548 |                 if (unlikely(!sock6)) {
>       |                     ^~~~~~~~~~~~~~~~
> ../include/linux/compiler.h:77:22: note: expanded from macro 'unlikely'
>    77 | # define unlikely(x)    __builtin_expect(!!(x), 0)
>       |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~
> ../drivers/net/vxlan/vxlan_core.c:2631:6: note: uninitialized use occurs here
>  2631 |         if (err == -ELOOP)
>       |             ^~~
> ../drivers/net/vxlan/vxlan_core.c:2548:3: note: remove the 'if' if its condition is always false
>  2548 |                 if (unlikely(!sock6)) {
>       |                 ^~~~~~~~~~~~~~~~~~~~~~~
>  2549 |                         reason = SKB_DROP_REASON_DEV_READY;
>       |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>  2550 |                         goto tx_error;
>       |                         ~~~~~~~~~~~~~~
>  2551 |                 }
>       |                 ~
> ../drivers/net/vxlan/vxlan_core.c:2464:7: warning: variable 'err' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
>  2464 |                 if (unlikely(!sock4)) {
>       |                     ^~~~~~~~~~~~~~~~
> ../include/linux/compiler.h:77:22: note: expanded from macro 'unlikely'
>    77 | # define unlikely(x)    __builtin_expect(!!(x), 0)
>       |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~
> ../drivers/net/vxlan/vxlan_core.c:2631:6: note: uninitialized use occurs here
>  2631 |         if (err == -ELOOP)
>       |             ^~~
> ../drivers/net/vxlan/vxlan_core.c:2464:3: note: remove the 'if' if its condition is always false
>  2464 |                 if (unlikely(!sock4)) {
>       |                 ^~~~~~~~~~~~~~~~~~~~~~~
>  2465 |                         reason = SKB_DROP_REASON_DEV_READY;
>       |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>  2466 |                         goto tx_error;
>       |                         ~~~~~~~~~~~~~~
>  2467 |                 }
>       |                 ~
> ../drivers/net/vxlan/vxlan_core.c:2352:9: note: initialize the variable 'err' to silence this warning
>  2352 |         int err;
>       |                ^
>       |                 = 0

I missed that somehow... will fix in v2. Thanks!

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-11-25  8:26 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-24 16:30 [PATCH net] net: vxlan: prevent NULL deref in vxlan_xmit_one Antoine Tenart
2025-11-25  3:51 ` Jakub Kicinski
2025-11-25  8:26   ` Antoine Tenart
2025-11-25  5:56 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).