[PATCH net-next v2] ipv6: make IPV6_FREEBIND and IPV6_TRANSPARENT setsockopt lockless
From: Xuanqiang Luo <hidden>
Date: 2026-09-12 13:40:58
Also in:
lkml
Subsystem:
networking [general], networking [ipv4/ipv6], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Ido Schimmel, Linus Torvalds
From: Xuanqiang Luo <redacted>
IPV6_FREEBIND and IPV6_TRANSPARENT still take the socket lock despite
using inet_assign_bit() to update the flags shared with IP_FREEBIND
and IP_TRANSPARENT. IPv6 TCP and UDP sockets can already update these
flags without the lock through the corresponding SOL_IP options.
Move both options to the lockless setsockopt path.
Signed-off-by: Xuanqiang Luo <redacted>
---
Changes:
v2:
- Squash the two patches into one and drop the cover letter.
(Eric Dumazet.)
v1: https://lore.kernel.org/all/20260911102418.157071-1-xuanqiang.luo@linux.dev/ (local)
net/ipv6/ipv6_sockglue.c | 36 +++++++++++++++---------------------
1 file changed, 15 insertions(+), 21 deletions(-)
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 1f68fb64a43ef..4b3536571c980 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c@@ -398,6 +398,21 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname, /* Handle options that can be set without locking the socket. */ switch (optname) { + case IPV6_FREEBIND: + if (optlen < sizeof(int)) + return -EINVAL; + /* Shared with IP_FREEBIND. */ + inet_assign_bit(FREEBIND, sk, valbool); + return 0; + case IPV6_TRANSPARENT: + if (valbool && !sockopt_ns_capable(net->user_ns, CAP_NET_RAW) && + !sockopt_ns_capable(net->user_ns, CAP_NET_ADMIN)) + return -EPERM; + if (optlen < sizeof(int)) + return -EINVAL; + /* Shared with IP_TRANSPARENT. */ + inet_assign_bit(TRANSPARENT, sk, valbool); + return 0; case IPV6_UNICAST_HOPS: if (optlen < sizeof(int)) return -EINVAL;
@@ -666,27 +681,6 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname, retv = 0; break; - case IPV6_TRANSPARENT: - if (valbool && !sockopt_ns_capable(net->user_ns, CAP_NET_RAW) && - !sockopt_ns_capable(net->user_ns, CAP_NET_ADMIN)) { - retv = -EPERM; - break; - } - 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_assign_bit(TRANSPARENT, sk, valbool); - retv = 0; - break; - - case IPV6_FREEBIND: - if (optlen < sizeof(int)) - goto e_inval; - /* we also don't have a separate freebind bit for IPV6 */ - inet_assign_bit(FREEBIND, sk, valbool); - retv = 0; - break; - case IPV6_RECVORIGDSTADDR: if (optlen < sizeof(int)) goto e_inval;
base-commit: 348ea4642f56ab3dc93621c8e3ab0ccd0e5f1782 -- 2.43.0