|
@@ -432,30 +432,37 @@ EXPORT_SYMBOL(inet_release);
|
|
|
|
|
|
int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
|
|
{
|
|
|
- struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
|
|
|
struct sock *sk = sock->sk;
|
|
|
- struct inet_sock *inet = inet_sk(sk);
|
|
|
- struct net *net = sock_net(sk);
|
|
|
- unsigned short snum;
|
|
|
- int chk_addr_ret;
|
|
|
- u32 tb_id = RT_TABLE_LOCAL;
|
|
|
int err;
|
|
|
|
|
|
/* If the socket has its own bind function then use it. (RAW) */
|
|
|
if (sk->sk_prot->bind) {
|
|
|
- err = sk->sk_prot->bind(sk, uaddr, addr_len);
|
|
|
- goto out;
|
|
|
+ return sk->sk_prot->bind(sk, uaddr, addr_len);
|
|
|
}
|
|
|
- err = -EINVAL;
|
|
|
if (addr_len < sizeof(struct sockaddr_in))
|
|
|
- goto out;
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
/* BPF prog is run before any checks are done so that if the prog
|
|
|
* changes context in a wrong way it will be caught.
|
|
|
*/
|
|
|
err = BPF_CGROUP_RUN_PROG_INET4_BIND(sk, uaddr);
|
|
|
if (err)
|
|
|
- goto out;
|
|
|
+ return err;
|
|
|
+
|
|
|
+ return __inet_bind(sk, uaddr, addr_len, false, true);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(inet_bind);
|
|
|
+
|
|
|
+int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
|
|
|
+ bool force_bind_address_no_port, bool with_lock)
|
|
|
+{
|
|
|
+ struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
|
|
|
+ struct inet_sock *inet = inet_sk(sk);
|
|
|
+ struct net *net = sock_net(sk);
|
|
|
+ unsigned short snum;
|
|
|
+ int chk_addr_ret;
|
|
|
+ u32 tb_id = RT_TABLE_LOCAL;
|
|
|
+ int err;
|
|
|
|
|
|
if (addr->sin_family != AF_INET) {
|
|
|
/* Compatibility games : accept AF_UNSPEC (mapped to AF_INET)
|
|
@@ -499,7 +506,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
|
|
* would be illegal to use them (multicast/broadcast) in
|
|
|
* which case the sending device address is used.
|
|
|
*/
|
|
|
- lock_sock(sk);
|
|
|
+ if (with_lock)
|
|
|
+ lock_sock(sk);
|
|
|
|
|
|
/* Check these errors (active socket, double bind). */
|
|
|
err = -EINVAL;
|
|
@@ -511,7 +519,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
|
|
inet->inet_saddr = 0; /* Use device */
|
|
|
|
|
|
/* Make sure we are allowed to bind here. */
|
|
|
- if ((snum || !inet->bind_address_no_port) &&
|
|
|
+ if ((snum || !(inet->bind_address_no_port ||
|
|
|
+ force_bind_address_no_port)) &&
|
|
|
sk->sk_prot->get_port(sk, snum)) {
|
|
|
inet->inet_saddr = inet->inet_rcv_saddr = 0;
|
|
|
err = -EADDRINUSE;
|
|
@@ -528,11 +537,11 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
|
|
sk_dst_reset(sk);
|
|
|
err = 0;
|
|
|
out_release_sock:
|
|
|
- release_sock(sk);
|
|
|
+ if (with_lock)
|
|
|
+ release_sock(sk);
|
|
|
out:
|
|
|
return err;
|
|
|
}
|
|
|
-EXPORT_SYMBOL(inet_bind);
|
|
|
|
|
|
int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
|
|
|
int addr_len, int flags)
|