Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipvs: fix uninit-value for saddr in do_output_route4

syzbot reports for uninit-value for the saddr argument [1].
commit 4754957f04f5 ("ipvs: do not use random local source address for
tunnels") already implies that the input value of saddr
should be ignored but the code is still reading it which can prevent
to connect the route. Fix it by changing the argument to ret_saddr.

[1]
BUG: KMSAN: uninit-value in do_output_route4+0x42c/0x4d0 net/netfilter/ipvs/ip_vs_xmit.c:147
do_output_route4+0x42c/0x4d0 net/netfilter/ipvs/ip_vs_xmit.c:147
__ip_vs_get_out_rt+0x403/0x21d0 net/netfilter/ipvs/ip_vs_xmit.c:330
ip_vs_tunnel_xmit+0x205/0x2380 net/netfilter/ipvs/ip_vs_xmit.c:1136
ip_vs_in_hook+0x1aa5/0x35b0 net/netfilter/ipvs/ip_vs_core.c:2063
nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline]
nf_hook_slow+0xf7/0x400 net/netfilter/core.c:626
nf_hook include/linux/netfilter.h:269 [inline]
__ip_local_out+0x758/0x7e0 net/ipv4/ip_output.c:118
ip_local_out net/ipv4/ip_output.c:127 [inline]
ip_send_skb+0x6a/0x3c0 net/ipv4/ip_output.c:1501
udp_send_skb+0xfda/0x1b70 net/ipv4/udp.c:1195
udp_sendmsg+0x2fe3/0x33c0 net/ipv4/udp.c:1483
inet_sendmsg+0x1fc/0x280 net/ipv4/af_inet.c:851
sock_sendmsg_nosec net/socket.c:712 [inline]
__sock_sendmsg+0x267/0x380 net/socket.c:727
____sys_sendmsg+0x91b/0xda0 net/socket.c:2566
___sys_sendmsg+0x28d/0x3c0 net/socket.c:2620
__sys_sendmmsg+0x41d/0x880 net/socket.c:2702
__compat_sys_sendmmsg net/compat.c:360 [inline]
__do_compat_sys_sendmmsg net/compat.c:367 [inline]
__se_compat_sys_sendmmsg net/compat.c:364 [inline]
__ia32_compat_sys_sendmmsg+0xc8/0x140 net/compat.c:364
ia32_sys_call+0x3ffa/0x41f0 arch/x86/include/generated/asm/syscalls_32.h:346
do_syscall_32_irqs_on arch/x86/entry/syscall_32.c:83 [inline]
__do_fast_syscall_32+0xb0/0x110 arch/x86/entry/syscall_32.c:306
do_fast_syscall_32+0x38/0x80 arch/x86/entry/syscall_32.c:331
do_SYSENTER_32+0x1f/0x30 arch/x86/entry/syscall_32.c:369
entry_SYSENTER_compat_after_hwframe+0x84/0x8e

Uninit was created at:
slab_post_alloc_hook mm/slub.c:4167 [inline]
slab_alloc_node mm/slub.c:4210 [inline]
__kmalloc_cache_noprof+0x8fa/0xe00 mm/slub.c:4367
kmalloc_noprof include/linux/slab.h:905 [inline]
ip_vs_dest_dst_alloc net/netfilter/ipvs/ip_vs_xmit.c:61 [inline]
__ip_vs_get_out_rt+0x35d/0x21d0 net/netfilter/ipvs/ip_vs_xmit.c:323
ip_vs_tunnel_xmit+0x205/0x2380 net/netfilter/ipvs/ip_vs_xmit.c:1136
ip_vs_in_hook+0x1aa5/0x35b0 net/netfilter/ipvs/ip_vs_core.c:2063
nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline]
nf_hook_slow+0xf7/0x400 net/netfilter/core.c:626
nf_hook include/linux/netfilter.h:269 [inline]
__ip_local_out+0x758/0x7e0 net/ipv4/ip_output.c:118
ip_local_out net/ipv4/ip_output.c:127 [inline]
ip_send_skb+0x6a/0x3c0 net/ipv4/ip_output.c:1501
udp_send_skb+0xfda/0x1b70 net/ipv4/udp.c:1195
udp_sendmsg+0x2fe3/0x33c0 net/ipv4/udp.c:1483
inet_sendmsg+0x1fc/0x280 net/ipv4/af_inet.c:851
sock_sendmsg_nosec net/socket.c:712 [inline]
__sock_sendmsg+0x267/0x380 net/socket.c:727
____sys_sendmsg+0x91b/0xda0 net/socket.c:2566
___sys_sendmsg+0x28d/0x3c0 net/socket.c:2620
__sys_sendmmsg+0x41d/0x880 net/socket.c:2702
__compat_sys_sendmmsg net/compat.c:360 [inline]
__do_compat_sys_sendmmsg net/compat.c:367 [inline]
__se_compat_sys_sendmmsg net/compat.c:364 [inline]
__ia32_compat_sys_sendmmsg+0xc8/0x140 net/compat.c:364
ia32_sys_call+0x3ffa/0x41f0 arch/x86/include/generated/asm/syscalls_32.h:346
do_syscall_32_irqs_on arch/x86/entry/syscall_32.c:83 [inline]
__do_fast_syscall_32+0xb0/0x110 arch/x86/entry/syscall_32.c:306
do_fast_syscall_32+0x38/0x80 arch/x86/entry/syscall_32.c:331
do_SYSENTER_32+0x1f/0x30 arch/x86/entry/syscall_32.c:369
entry_SYSENTER_compat_after_hwframe+0x84/0x8e

CPU: 0 UID: 0 PID: 22408 Comm: syz.4.5165 Not tainted 6.15.0-rc3-syzkaller-00019-gbc3372351d0c #0 PREEMPT(undef)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2025

Reported-by: syzbot+04b9a82855c8aed20860@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/68138dfa.050a0220.14dd7d.0017.GAE@google.com/
Fixes: 4754957f04f5 ("ipvs: do not use random local source address for tunnels")
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Acked-by: Simon Horman <horms@kernel.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Julian Anastasov and committed by
Pablo Neira Ayuso
e34090d7 9540984d

+8 -19
+8 -19
net/netfilter/ipvs/ip_vs_xmit.c
··· 119 119 return false; 120 120 } 121 121 122 - /* Get route to daddr, update *saddr, optionally bind route to saddr */ 122 + /* Get route to daddr, optionally bind route to saddr */ 123 123 static struct rtable *do_output_route4(struct net *net, __be32 daddr, 124 - int rt_mode, __be32 *saddr) 124 + int rt_mode, __be32 *ret_saddr) 125 125 { 126 126 struct flowi4 fl4; 127 127 struct rtable *rt; 128 - bool loop = false; 129 128 130 129 memset(&fl4, 0, sizeof(fl4)); 131 130 fl4.daddr = daddr; ··· 134 135 retry: 135 136 rt = ip_route_output_key(net, &fl4); 136 137 if (IS_ERR(rt)) { 137 - /* Invalid saddr ? */ 138 - if (PTR_ERR(rt) == -EINVAL && *saddr && 139 - rt_mode & IP_VS_RT_MODE_CONNECT && !loop) { 140 - *saddr = 0; 141 - flowi4_update_output(&fl4, 0, daddr, 0); 142 - goto retry; 143 - } 144 138 IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", &daddr); 145 139 return NULL; 146 - } else if (!*saddr && rt_mode & IP_VS_RT_MODE_CONNECT && fl4.saddr) { 140 + } 141 + if (rt_mode & IP_VS_RT_MODE_CONNECT && fl4.saddr) { 147 142 ip_rt_put(rt); 148 - *saddr = fl4.saddr; 149 143 flowi4_update_output(&fl4, 0, daddr, fl4.saddr); 150 - loop = true; 144 + rt_mode = 0; 151 145 goto retry; 152 146 } 153 - *saddr = fl4.saddr; 147 + if (ret_saddr) 148 + *ret_saddr = fl4.saddr; 154 149 return rt; 155 150 } 156 151 ··· 337 344 if (ret_saddr) 338 345 *ret_saddr = dest_dst->dst_saddr.ip; 339 346 } else { 340 - __be32 saddr = htonl(INADDR_ANY); 341 - 342 347 noref = 0; 343 348 344 349 /* For such unconfigured boxes avoid many route lookups 345 350 * for performance reasons because we do not remember saddr 346 351 */ 347 352 rt_mode &= ~IP_VS_RT_MODE_CONNECT; 348 - rt = do_output_route4(net, daddr, rt_mode, &saddr); 353 + rt = do_output_route4(net, daddr, rt_mode, ret_saddr); 349 354 if (!rt) 350 355 goto err_unreach; 351 - if (ret_saddr) 352 - *ret_saddr = saddr; 353 356 } 354 357 355 358 local = (rt->rt_flags & RTCF_LOCAL) ? 1 : 0;