Skip to content

Commit c8d98a5

Browse files
committed
Merge: ping: fix address binding wrt vrf
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/5020 JIRA: https://issues.redhat.com/browse/RHEL-50920 Upstream Status: linux.git Conflicts:\ - Code differences due to missing upstream commit 8ff978b ("ipv4/raw: support binding to nonlocal addresses"); but the overall logic is the same. commit e1a7ac6 Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> Date: Wed May 4 11:07:38 2022 +0200 ping: fix address binding wrt vrf When ping_group_range is updated, 'ping' uses the DGRAM ICMP socket, instead of an IP raw socket. In this case, 'ping' is unable to bind its socket to a local address owned by a vrflite. Before the patch: $ sysctl -w net.ipv4.ping_group_range='0 2147483647' $ ip link add blue type vrf table 10 $ ip link add foo type dummy $ ip link set foo master blue $ ip link set foo up $ ip addr add 192.168.1.1/24 dev foo $ ip addr add 2001::1/64 dev foo $ ip vrf exec blue ping -c1 -I 192.168.1.1 192.168.1.2 ping: bind: Cannot assign requested address $ ip vrf exec blue ping6 -c1 -I 2001::1 2001::2 ping6: bind icmp socket: Cannot assign requested address CC: stable@vger.kernel.org Fixes: 1b69c6d ("net: Introduce L3 Master device abstraction") Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Reviewed-by: David Ahern <dsahern@kernel.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Antoine Tenart <atenart@redhat.com> Approved-by: Florian Westphal <fwestpha@redhat.com> Approved-by: Hangbin Liu <haliu@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Rado Vrbovsky <rvrbovsk@redhat.com>
2 parents 94005b5 + cb8b399 commit c8d98a5

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

net/ipv4/ping.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
321321
struct net *net = sock_net(sk);
322322
if (sk->sk_family == AF_INET) {
323323
struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
324+
u32 tb_id = RT_TABLE_LOCAL;
324325
int chk_addr_ret;
325326

326327
if (addr_len < sizeof(*addr))
@@ -336,8 +337,10 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
336337

337338
if (addr->sin_addr.s_addr == htonl(INADDR_ANY))
338339
chk_addr_ret = RTN_LOCAL;
339-
else
340-
chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr);
340+
else {
341+
tb_id = l3mdev_fib_table_by_index(net, sk->sk_bound_dev_if) ? : tb_id;
342+
chk_addr_ret = inet_addr_type_table(net, addr->sin_addr.s_addr, tb_id);
343+
}
341344

342345
if ((!inet_can_nonlocal_bind(net, isk) &&
343346
chk_addr_ret != RTN_LOCAL) ||
@@ -375,6 +378,14 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
375378
return -ENODEV;
376379
}
377380
}
381+
382+
if (!dev && sk->sk_bound_dev_if) {
383+
dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
384+
if (!dev) {
385+
rcu_read_unlock();
386+
return -ENODEV;
387+
}
388+
}
378389
has_addr = pingv6_ops.ipv6_chk_addr(net, &addr->sin6_addr, dev,
379390
scoped);
380391
rcu_read_unlock();

0 commit comments

Comments
 (0)