inet: move inet->freebind to inet->inet_flags
authorEric Dumazet <edumazet@google.com>
Wed, 16 Aug 2023 08:15:37 +0000 (08:15 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 16 Aug 2023 10:09:17 +0000 (11:09 +0100)
IP_FREEBIND socket option can now be set/read
without locking the socket.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/inet_sock.h
include/net/ipv6.h
net/ipv4/inet_diag.c
net/ipv4/ip_sockglue.c
net/ipv6/ipv6_sockglue.c
net/mptcp/sockopt.c
net/sctp/protocol.c

index c01f1f6..d6ba963 100644 (file)
@@ -231,7 +231,6 @@ struct inet_sock {
        __u8                    mc_ttl;
        __u8                    pmtudisc;
        __u8                    is_icsk:1,
-                               freebind:1,
                                hdrincl:1,
                                mc_loop:1,
                                transparent:1,
@@ -271,6 +270,7 @@ enum {
 
        INET_FLAGS_RECVERR      = 9,
        INET_FLAGS_RECVERR_RFC4884 = 10,
+       INET_FLAGS_FREEBIND     = 11,
 };
 
 /* cmsg flags for inet */
@@ -423,7 +423,8 @@ static inline bool inet_can_nonlocal_bind(struct net *net,
                                          struct inet_sock *inet)
 {
        return READ_ONCE(net->ipv4.sysctl_ip_nonlocal_bind) ||
-               inet->freebind || inet->transparent;
+               test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
+               inet->transparent;
 }
 
 static inline bool inet_addr_valid_or_nonlocal(struct net *net,
index 22643ff..fd570d7 100644 (file)
@@ -937,7 +937,8 @@ static inline bool ipv6_can_nonlocal_bind(struct net *net,
                                          struct inet_sock *inet)
 {
        return net->ipv6.sysctl.ip_nonlocal_bind ||
-               inet->freebind || inet->transparent;
+               test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
+               inet->transparent;
 }
 
 /* Sysctl settings for net ipv6.auto_flowlabels */
index 6255d6f..5a96f4f 100644 (file)
@@ -184,7 +184,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
        memset(&inet_sockopt, 0, sizeof(inet_sockopt));
        inet_sockopt.recverr    = inet_test_bit(RECVERR, sk);
        inet_sockopt.is_icsk    = inet->is_icsk;
-       inet_sockopt.freebind   = inet->freebind;
+       inet_sockopt.freebind   = inet_test_bit(FREEBIND, sk);
        inet_sockopt.hdrincl    = inet->hdrincl;
        inet_sockopt.mc_loop    = inet->mc_loop;
        inet_sockopt.transparent = inet->transparent;
index f75f44a..6af8431 100644 (file)
@@ -608,9 +608,7 @@ EXPORT_SYMBOL(ip_sock_set_tos);
 
 void ip_sock_set_freebind(struct sock *sk)
 {
-       lock_sock(sk);
-       inet_sk(sk)->freebind = true;
-       release_sock(sk);
+       inet_set_bit(FREEBIND, sk);
 }
 EXPORT_SYMBOL(ip_sock_set_freebind);
 
@@ -985,6 +983,11 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
                        return -EINVAL;
                inet_assign_bit(RECVERR_RFC4884, sk, val);
                return 0;
+       case IP_FREEBIND:
+               if (optlen < 1)
+                       return -EINVAL;
+               inet_assign_bit(FREEBIND, sk, val);
+               return 0;
        }
 
        err = 0;
@@ -1310,12 +1313,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
                inet->mc_all = val;
                break;
 
-       case IP_FREEBIND:
-               if (optlen < 1)
-                       goto e_inval;
-               inet->freebind = !!val;
-               break;
-
        case IP_IPSEC_POLICY:
        case IP_XFRM_POLICY:
                err = -EPERM;
@@ -1578,6 +1575,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
        case IP_RECVERR_RFC4884:
                val = inet_test_bit(RECVERR_RFC4884, sk);
                goto copyval;
+       case IP_FREEBIND:
+               val = inet_test_bit(FREEBIND, sk);
+               goto copyval;
        }
 
        if (needs_rtnl)
@@ -1737,9 +1737,6 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
                len -= msg.msg_controllen;
                return copy_to_sockptr(optlen, &len, sizeof(int));
        }
-       case IP_FREEBIND:
-               val = inet->freebind;
-               break;
        case IP_TRANSPARENT:
                val = inet->transparent;
                break;
index ca37715..3eb3843 100644 (file)
@@ -641,7 +641,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                if (optlen < sizeof(int))
                        goto e_inval;
                /* we also don't have a separate freebind bit for IPV6 */
-               inet_sk(sk)->freebind = valbool;
+               inet_assign_bit(FREEBIND, sk, valbool);
                retv = 0;
                break;
 
@@ -1334,7 +1334,7 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                break;
 
        case IPV6_FREEBIND:
-               val = inet_sk(sk)->freebind;
+               val = inet_test_bit(FREEBIND, sk);
                break;
 
        case IPV6_RECVORIGDSTADDR:
index 21bc46a..ffbe2f5 100644 (file)
@@ -419,7 +419,8 @@ static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
                        inet_sk(sk)->transparent = inet_sk(ssk)->transparent;
                        break;
                case IPV6_FREEBIND:
-                       inet_sk(sk)->freebind = inet_sk(ssk)->freebind;
+                       inet_assign_bit(FREEBIND, sk,
+                                       inet_test_bit(FREEBIND, ssk));
                        break;
                }
 
@@ -704,7 +705,7 @@ static int mptcp_setsockopt_sol_ip_set_transparent(struct mptcp_sock *msk, int o
 
        switch (optname) {
        case IP_FREEBIND:
-               issk->freebind = inet_sk(sk)->freebind;
+               inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
                break;
        case IP_TRANSPARENT:
                issk->transparent = inet_sk(sk)->transparent;
@@ -1441,7 +1442,7 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
        __tcp_sock_set_nodelay(ssk, !!msk->nodelay);
 
        inet_sk(ssk)->transparent = inet_sk(sk)->transparent;
-       inet_sk(ssk)->freebind = inet_sk(sk)->freebind;
+       inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
 }
 
 static void __mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
index 33c0895..2185f44 100644 (file)
@@ -360,7 +360,7 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
        ret = inet_addr_type_table(net, addr->v4.sin_addr.s_addr, tb_id);
        if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
           ret != RTN_LOCAL &&
-          !sp->inet.freebind &&
+          !inet_test_bit(FREEBIND, sk) &&
            !READ_ONCE(net->ipv4.sysctl_ip_nonlocal_bind))
                return 0;