mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
ipv6: lock socket in ip6_datagram_connect()
ip6_datagram_connect() is doing a lot of socket changes without socket being locked. This looks wrong, at least for udp_lib_rehash() which could corrupt lists because of concurrent udp_sk(sk)->udp_portaddr_hash accesses. Signed-off-by: Eric Dumazet <[email protected]> Acked-by: Herbert Xu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
parent
14e4cec80c
commit
03645a11a5
3 changed files with 28 additions and 9 deletions
|
|
@ -40,7 +40,7 @@ static bool ipv6_mapped_addr_any(const struct in6_addr *a)
|
|||
return ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0);
|
||||
}
|
||||
|
||||
int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
||||
static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
||||
{
|
||||
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
|
|
@ -56,7 +56,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||
if (usin->sin6_family == AF_INET) {
|
||||
if (__ipv6_only_sock(sk))
|
||||
return -EAFNOSUPPORT;
|
||||
err = ip4_datagram_connect(sk, uaddr, addr_len);
|
||||
err = __ip4_datagram_connect(sk, uaddr, addr_len);
|
||||
goto ipv4_connected;
|
||||
}
|
||||
|
||||
|
|
@ -98,9 +98,9 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||
sin.sin_addr.s_addr = daddr->s6_addr32[3];
|
||||
sin.sin_port = usin->sin6_port;
|
||||
|
||||
err = ip4_datagram_connect(sk,
|
||||
(struct sockaddr *) &sin,
|
||||
sizeof(sin));
|
||||
err = __ip4_datagram_connect(sk,
|
||||
(struct sockaddr *) &sin,
|
||||
sizeof(sin));
|
||||
|
||||
ipv4_connected:
|
||||
if (err)
|
||||
|
|
@ -204,6 +204,16 @@ out:
|
|||
fl6_sock_release(flowlabel);
|
||||
return err;
|
||||
}
|
||||
|
||||
int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
||||
{
|
||||
int res;
|
||||
|
||||
lock_sock(sk);
|
||||
res = __ip6_datagram_connect(sk, uaddr, addr_len);
|
||||
release_sock(sk);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip6_datagram_connect);
|
||||
|
||||
int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *uaddr,
|
||||
|
|
|
|||
Loading…
Reference in a new issue