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

v2: removed unused issk variable in mptcp_setsockopt_sol_ip_set_transparent()
v4: rebased after commit 3f326a821b99 ("mptcp: change the mpc check helper to return a sk")

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.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
include/net/route.h
include/net/tcp.h
net/ipv4/inet_diag.c
net/ipv4/inet_timewait_sock.c
net/ipv4/ip_sockglue.c
net/ipv4/tcp_input.c
net/ipv4/tcp_minisocks.c
net/ipv6/ipv6_sockglue.c
net/mptcp/sockopt.c

index fffd34f..cefd9a6 100644 (file)
@@ -231,7 +231,6 @@ struct inet_sock {
        __u8                    mc_ttl;
        __u8                    pmtudisc;
        __u8                    is_icsk:1,
-                               transparent:1,
                                nodefrag:1;
        __u8                    bind_address_no_port:1,
                                defer_connect:1; /* Indicates that fastopen_connect is set
@@ -271,6 +270,7 @@ enum {
        INET_FLAGS_HDRINCL      = 12,
        INET_FLAGS_MC_LOOP      = 13,
        INET_FLAGS_MC_ALL       = 14,
+       INET_FLAGS_TRANSPARENT  = 15,
 };
 
 /* cmsg flags for inet */
@@ -397,7 +397,7 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
 {
        __u8 flags = 0;
 
-       if (inet_sk(sk)->transparent || inet_test_bit(HDRINCL, sk))
+       if (inet_test_bit(TRANSPARENT, sk) || inet_test_bit(HDRINCL, sk))
                flags |= FLOWI_FLAG_ANYSRC;
        return flags;
 }
@@ -424,7 +424,7 @@ static inline bool inet_can_nonlocal_bind(struct net *net,
 {
        return READ_ONCE(net->ipv4.sysctl_ip_nonlocal_bind) ||
                test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
-               inet->transparent;
+               test_bit(INET_FLAGS_TRANSPARENT, &inet->inet_flags);
 }
 
 static inline bool inet_addr_valid_or_nonlocal(struct net *net,
index fd570d7..d40d823 100644 (file)
@@ -938,7 +938,7 @@ static inline bool ipv6_can_nonlocal_bind(struct net *net,
 {
        return net->ipv6.sysctl.ip_nonlocal_bind ||
                test_bit(INET_FLAGS_FREEBIND, &inet->inet_flags) ||
-               inet->transparent;
+               test_bit(INET_FLAGS_TRANSPARENT, &inet->inet_flags);
 }
 
 /* Sysctl settings for net ipv6.auto_flowlabels */
index d9ca98d..51a45b1 100644 (file)
@@ -298,7 +298,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst,
 {
        __u8 flow_flags = 0;
 
-       if (inet_sk(sk)->transparent)
+       if (inet_test_bit(TRANSPARENT, sk))
                flow_flags |= FLOWI_FLAG_ANYSRC;
 
        flowi4_init_output(fl4, oif, READ_ONCE(sk->sk_mark), ip_sock_rt_tos(sk),
index 6d77c08..07b21d9 100644 (file)
@@ -2031,7 +2031,7 @@ static inline bool inet_sk_transparent(const struct sock *sk)
        case TCP_NEW_SYN_RECV:
                return inet_rsk(inet_reqsk(sk))->no_srccheck;
        }
-       return inet_sk(sk)->transparent;
+       return inet_test_bit(TRANSPARENT, sk);
 }
 
 /* Determines whether this is a thin stream (which may suffer from
index e009dab..45fefd2 100644 (file)
@@ -187,7 +187,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
        inet_sockopt.freebind   = inet_test_bit(FREEBIND, sk);
        inet_sockopt.hdrincl    = inet_test_bit(HDRINCL, sk);
        inet_sockopt.mc_loop    = inet_test_bit(MC_LOOP, sk);
-       inet_sockopt.transparent = inet->transparent;
+       inet_sockopt.transparent = inet_test_bit(TRANSPARENT, sk);
        inet_sockopt.mc_all     = inet_test_bit(MC_ALL, sk);
        inet_sockopt.nodefrag   = inet->nodefrag;
        inet_sockopt.bind_address_no_port = inet->bind_address_no_port;
index 2c1b245..dd37a5b 100644 (file)
@@ -203,7 +203,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
                tw->tw_reuseport    = sk->sk_reuseport;
                tw->tw_hash         = sk->sk_hash;
                tw->tw_ipv6only     = 0;
-               tw->tw_transparent  = inet->transparent;
+               tw->tw_transparent  = inet_test_bit(TRANSPARENT, sk);
                tw->tw_prot         = sk->sk_prot_creator;
                atomic64_set(&tw->tw_cookie, atomic64_read(&sk->sk_cookie));
                twsk_net_set(tw, sock_net(sk));
index 2f27c30..3f5323a 100644 (file)
@@ -1005,7 +1005,16 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
                        return -EINVAL;
                inet_assign_bit(MC_ALL, sk, val);
                return 0;
-
+       case IP_TRANSPARENT:
+               if (!!val && !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
+                   !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
+                       err = -EPERM;
+                       break;
+               }
+               if (optlen < 1)
+                       goto e_inval;
+               inet_assign_bit(TRANSPARENT, sk, val);
+               return 0;
        }
 
        err = 0;
@@ -1319,17 +1328,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
                err = xfrm_user_policy(sk, optname, optval, optlen);
                break;
 
-       case IP_TRANSPARENT:
-               if (!!val && !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
-                   !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
-                       err = -EPERM;
-                       break;
-               }
-               if (optlen < 1)
-                       goto e_inval;
-               inet->transparent = !!val;
-               break;
-
        case IP_MINTTL:
                if (optlen < 1)
                        goto e_inval;
@@ -1585,6 +1583,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
        case IP_MULTICAST_ALL:
                val = inet_test_bit(MC_ALL, sk);
                goto copyval;
+       case IP_TRANSPARENT:
+               val = inet_test_bit(TRANSPARENT, sk);
+               goto copyval;
        }
 
        if (needs_rtnl)
@@ -1735,9 +1736,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_TRANSPARENT:
-               val = inet->transparent;
-               break;
        case IP_MINTTL:
                val = inet->min_ttl;
                break;
index d34d52f..06fe1cf 100644 (file)
@@ -7000,7 +7000,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
 
        tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
        tcp_openreq_init(req, &tmp_opt, skb, sk);
-       inet_rsk(req)->no_srccheck = inet_sk(sk)->transparent;
+       inet_rsk(req)->no_srccheck = inet_test_bit(TRANSPARENT, sk);
 
        /* Note: tcp_v6_init_req() might override ir_iif for link locals */
        inet_rsk(req)->ir_iif = inet_request_bound_dev_if(sk, skb);
index 13ee129..b98d476 100644 (file)
@@ -289,9 +289,8 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
        if (tw) {
                struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
                const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
-               struct inet_sock *inet = inet_sk(sk);
 
-               tw->tw_transparent      = inet->transparent;
+               tw->tw_transparent      = inet_test_bit(TRANSPARENT, sk);
                tw->tw_mark             = sk->sk_mark;
                tw->tw_priority         = sk->sk_priority;
                tw->tw_rcv_wscale       = tp->rx_opt.rcv_wscale;
index 3eb3843..eb33412 100644 (file)
@@ -633,7 +633,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                if (optlen < sizeof(int))
                        goto e_inval;
                /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
-               inet_sk(sk)->transparent = valbool;
+               inet_assign_bit(TRANSPARENT, sk, valbool);
                retv = 0;
                break;
 
@@ -1330,7 +1330,7 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
        }
 
        case IPV6_TRANSPARENT:
-               val = inet_sk(sk)->transparent;
+               val = inet_test_bit(TRANSPARENT, sk);
                break;
 
        case IPV6_FREEBIND:
index ffbe2f5..8260202 100644 (file)
@@ -416,7 +416,8 @@ static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
                        sk->sk_ipv6only = ssk->sk_ipv6only;
                        break;
                case IPV6_TRANSPARENT:
-                       inet_sk(sk)->transparent = inet_sk(ssk)->transparent;
+                       inet_assign_bit(TRANSPARENT, sk,
+                                       inet_test_bit(TRANSPARENT, ssk));
                        break;
                case IPV6_FREEBIND:
                        inet_assign_bit(FREEBIND, sk,
@@ -685,7 +686,6 @@ static int mptcp_setsockopt_sol_ip_set_transparent(struct mptcp_sock *msk, int o
                                                   sockptr_t optval, unsigned int optlen)
 {
        struct sock *sk = (struct sock *)msk;
-       struct inet_sock *issk;
        struct sock *ssk;
        int err;
 
@@ -701,14 +701,13 @@ static int mptcp_setsockopt_sol_ip_set_transparent(struct mptcp_sock *msk, int o
                return PTR_ERR(ssk);
        }
 
-       issk = inet_sk(ssk);
-
        switch (optname) {
        case IP_FREEBIND:
                inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
                break;
        case IP_TRANSPARENT:
-               issk->transparent = inet_sk(sk)->transparent;
+               inet_assign_bit(TRANSPARENT, ssk,
+                               inet_test_bit(TRANSPARENT, sk));
                break;
        default:
                release_sock(sk);
@@ -1441,7 +1440,7 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
        __tcp_sock_set_cork(ssk, !!msk->cork);
        __tcp_sock_set_nodelay(ssk, !!msk->nodelay);
 
-       inet_sk(ssk)->transparent = inet_sk(sk)->transparent;
+       inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
        inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
 }