summaryrefslogtreecommitdiff
path: root/net/ipv4
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2024-07-10 11:14:27 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-08-03 10:00:31 +0300
commita9e9686a84fac8f42a9210efe866edc87bdda8b4 (patch)
treefbbee197f67f093b14fd2b9d936c5909e8fa44c4 /net/ipv4
parentce1268b5adbe2fec354aede0e00098e97e987aa4 (diff)
downloadlinux-a9e9686a84fac8f42a9210efe866edc87bdda8b4.tar.xz
ipv4: fix source address selection with route leak
commit 6807352353561187a718e87204458999dbcbba1b upstream. By default, an address assigned to the output interface is selected when the source address is not specified. This is problematic when a route, configured in a vrf, uses an interface from another vrf (aka route leak). The original vrf does not own the selected source address. Let's add a check against the output interface and call the appropriate function to select the source address. CC: stable@vger.kernel.org Fixes: 8cbb512c923d ("net: Add source address lookup op for VRF") Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://patch.msgid.link/20240710081521.3809742-2-nicolas.dichtel@6wind.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/fib_semantics.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index f669da98d11d..8956026bc0a2 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -2270,6 +2270,15 @@ void fib_select_path(struct net *net, struct fib_result *res,
fib_select_default(fl4, res);
check_saddr:
- if (!fl4->saddr)
- fl4->saddr = fib_result_prefsrc(net, res);
+ if (!fl4->saddr) {
+ struct net_device *l3mdev;
+
+ l3mdev = dev_get_by_index_rcu(net, fl4->flowi4_l3mdev);
+
+ if (!l3mdev ||
+ l3mdev_master_dev_rcu(FIB_RES_DEV(*res)) == l3mdev)
+ fl4->saddr = fib_result_prefsrc(net, res);
+ else
+ fl4->saddr = inet_select_addr(l3mdev, 0, RT_SCOPE_LINK);
+ }
}