From: Eric Dumazet Date: Wed, 16 Aug 2023 08:15:37 +0000 (+0000) Subject: inet: move inet->freebind to inet->inet_flags X-Git-Tag: v6.6.17~4098^2~103^2~10 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3f7e753206bb20fc098b44ec40001befd1fe18d1;p=platform%2Fkernel%2Flinux-rpi.git inet: move inet->freebind to inet->inet_flags IP_FREEBIND socket option can now be set/read without locking the socket. Signed-off-by: Eric Dumazet Acked-by: Soheil Hassas Yeganeh Reviewed-by: Simon Horman Reviewed-by: Matthieu Baerts Signed-off-by: David S. Miller --- diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index c01f1f6..d6ba963 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -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, diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 22643ff..fd570d7 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -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 */ diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 6255d6f..5a96f4f 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -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; diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index f75f44a..6af8431 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -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; diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index ca37715..3eb3843 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -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: diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index 21bc46a..ffbe2f5 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -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) diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 33c0895..2185f44 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -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;