mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ipv6: make IPV6_FREEBIND and IPV6_TRANSPARENT setsockopt lockless
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 <luoxuanqiang@kylinos.cn> Reviewed-by: Hangbin Liu <liuhangbin@kylinos.cn> Link: https://patch.msgid.link/20260912134040.215664-1-xuanqiang.luo@linux.dev Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
859e40055c
commit
546f109fdb
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user