Phonet: fix race for port number in concurrent bind()

Allocating a port number to a socket and hashing that socket shall be
an atomic operation with regards to other port allocation. Otherwise,
we could allocate a port that is already being allocated to another
socket.

Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Rémi Denis-Courmont and committed by
David S. Miller
582b0b61 ef87979c

+8 -8
+8 -8
net/phonet/socket.c
··· 113 113 } 114 114 EXPORT_SYMBOL(pn_sock_unhash); 115 115 116 + static DEFINE_MUTEX(port_mutex); 117 + 116 118 static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) 117 119 { 118 120 struct sock *sk = sock->sk; ··· 142 140 err = -EINVAL; /* attempt to rebind */ 143 141 goto out; 144 142 } 143 + WARN_ON(sk_hashed(sk)); 144 + mutex_lock(&port_mutex); 145 145 err = sk->sk_prot->get_port(sk, pn_port(handle)); 146 146 if (err) 147 - goto out; 147 + goto out_port; 148 148 149 149 /* get_port() sets the port, bind() sets the address if applicable */ 150 150 pn->sobject = pn_object(saddr, pn_port(pn->sobject)); ··· 154 150 155 151 /* Enable RX on the socket */ 156 152 sk->sk_prot->hash(sk); 153 + out_port: 154 + mutex_unlock(&port_mutex); 157 155 out: 158 156 release_sock(sk); 159 157 return err; ··· 363 357 }; 364 358 EXPORT_SYMBOL(phonet_stream_ops); 365 359 366 - static DEFINE_MUTEX(port_mutex); 367 - 368 360 /* allocate port for a socket */ 369 361 int pn_sock_get_port(struct sock *sk, unsigned short sport) 370 362 { ··· 374 370 375 371 memset(&try_sa, 0, sizeof(struct sockaddr_pn)); 376 372 try_sa.spn_family = AF_PHONET; 377 - 378 - mutex_lock(&port_mutex); 379 - 373 + WARN_ON(!mutex_is_locked(&port_mutex)); 380 374 if (!sport) { 381 375 /* search free port */ 382 376 int port, pmin, pmax; ··· 403 401 else 404 402 sock_put(tmpsk); 405 403 } 406 - mutex_unlock(&port_mutex); 407 - 408 404 /* the port must be in use already */ 409 405 return -EADDRINUSE; 410 406