On Tue, 2017-03-28 at 16:11 -0700, Eric Dumazet wrote: > Yes, this looks better. > > Although you probably need to change a bit later this part : > > if (!inet->inet_saddr) > inet->inet_saddr = fl4->saddr; /* Update source address */ >
I came up with the following tested patch for IPv4 diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index f915abff1350a86af8d5bb89725b751c061b0fb5..1454b6191e0d38ffae0ae260578858285bc5f77b 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -40,7 +40,7 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len sk_dst_reset(sk); oif = sk->sk_bound_dev_if; - saddr = inet->inet_saddr; + saddr = (sk->sk_userlocks & SOCK_BINDADDR_LOCK) ? inet->inet_saddr : 0; if (ipv4_is_multicast(usin->sin_addr.s_addr)) { if (!oif) oif = inet->mc_index; @@ -64,9 +64,8 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len err = -EACCES; goto out; } - if (!inet->inet_saddr) + if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) { inet->inet_saddr = fl4->saddr; /* Update source address */ - if (!inet->inet_rcv_saddr) { inet->inet_rcv_saddr = fl4->saddr; if (sk->sk_prot->rehash) sk->sk_prot->rehash(sk);