mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 14:24:11 +08:00
ipv6: fix source address selection with route leak
commit252442f2ae
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:0d240e7811
("net: vrf: Implement get_saddr for IPv6") Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Link: https://patch.msgid.link/20240710081521.3809742-3-nicolas.dichtel@6wind.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ebb124228e
commit
ce1268b5ad
@ -127,18 +127,26 @@ void rt6_age_exceptions(struct fib6_info *f6i, struct fib6_gc_args *gc_args,
|
||||
|
||||
static inline int ip6_route_get_saddr(struct net *net, struct fib6_info *f6i,
|
||||
const struct in6_addr *daddr,
|
||||
unsigned int prefs,
|
||||
unsigned int prefs, int l3mdev_index,
|
||||
struct in6_addr *saddr)
|
||||
{
|
||||
struct net_device *l3mdev;
|
||||
struct net_device *dev;
|
||||
bool same_vrf;
|
||||
int err = 0;
|
||||
|
||||
if (f6i && f6i->fib6_prefsrc.plen) {
|
||||
*saddr = f6i->fib6_prefsrc.addr;
|
||||
} else {
|
||||
struct net_device *dev = f6i ? fib6_info_nh_dev(f6i) : NULL;
|
||||
rcu_read_lock();
|
||||
|
||||
err = ipv6_dev_get_saddr(net, dev, daddr, prefs, saddr);
|
||||
}
|
||||
l3mdev = dev_get_by_index_rcu(net, l3mdev_index);
|
||||
if (!f6i || !f6i->fib6_prefsrc.plen || l3mdev)
|
||||
dev = f6i ? fib6_info_nh_dev(f6i) : NULL;
|
||||
same_vrf = !l3mdev || l3mdev_master_dev_rcu(dev) == l3mdev;
|
||||
if (f6i && f6i->fib6_prefsrc.plen && same_vrf)
|
||||
*saddr = f6i->fib6_prefsrc.addr;
|
||||
else
|
||||
err = ipv6_dev_get_saddr(net, same_vrf ? dev : l3mdev, daddr, prefs, saddr);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1124,6 +1124,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk,
|
||||
from = rt ? rcu_dereference(rt->from) : NULL;
|
||||
err = ip6_route_get_saddr(net, from, &fl6->daddr,
|
||||
sk ? READ_ONCE(inet6_sk(sk)->srcprefs) : 0,
|
||||
fl6->flowi6_l3mdev,
|
||||
&fl6->saddr);
|
||||
rcu_read_unlock();
|
||||
|
||||
|
@ -5689,7 +5689,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
||||
goto nla_put_failure;
|
||||
} else if (dest) {
|
||||
struct in6_addr saddr_buf;
|
||||
if (ip6_route_get_saddr(net, rt, dest, 0, &saddr_buf) == 0 &&
|
||||
if (ip6_route_get_saddr(net, rt, dest, 0, 0, &saddr_buf) == 0 &&
|
||||
nla_put_in6_addr(skb, RTA_PREFSRC, &saddr_buf))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user