]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
inet: lockless IP_PKTOPTIONS implementation
authorEric Dumazet <edumazet@google.com>
Fri, 22 Sep 2023 03:42:20 +0000 (03:42 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 1 Oct 2023 18:39:19 +0000 (19:39 +0100)
Current implementation is already lockless, because the socket
lock is released before reading socket fields.

Add missing READ_ONCE() annotations.

Note that corresponding WRITE_ONCE() are needed, the order
of the patches do not really matter.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/ip_sockglue.c

index 58995526c6e965d613b8cdea61b84916d608a6fb..1ee01ff64171c94b6b244589518a53ce807a212d 100644 (file)
@@ -1633,6 +1633,43 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
                        return -ENOTCONN;
                goto copyval;
        }
+       case IP_PKTOPTIONS:
+       {
+               struct msghdr msg;
+
+               if (sk->sk_type != SOCK_STREAM)
+                       return -ENOPROTOOPT;
+
+               if (optval.is_kernel) {
+                       msg.msg_control_is_user = false;
+                       msg.msg_control = optval.kernel;
+               } else {
+                       msg.msg_control_is_user = true;
+                       msg.msg_control_user = optval.user;
+               }
+               msg.msg_controllen = len;
+               msg.msg_flags = in_compat_syscall() ? MSG_CMSG_COMPAT : 0;
+
+               if (inet_test_bit(PKTINFO, sk)) {
+                       struct in_pktinfo info;
+
+                       info.ipi_addr.s_addr = READ_ONCE(inet->inet_rcv_saddr);
+                       info.ipi_spec_dst.s_addr = READ_ONCE(inet->inet_rcv_saddr);
+                       info.ipi_ifindex = READ_ONCE(inet->mc_index);
+                       put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);
+               }
+               if (inet_test_bit(TTL, sk)) {
+                       int hlim = READ_ONCE(inet->mc_ttl);
+
+                       put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim);
+               }
+               if (inet_test_bit(TOS, sk)) {
+                       int tos = READ_ONCE(inet->rcv_tos);
+                       put_cmsg(&msg, SOL_IP, IP_TOS, sizeof(tos), &tos);
+               }
+               len -= msg.msg_controllen;
+               return copy_to_sockptr(optlen, &len, sizeof(int));
+       }
        case IP_UNICAST_IF:
                val = (__force int)htonl((__u32) READ_ONCE(inet->uc_index));
                goto copyval;
@@ -1678,45 +1715,6 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
                else
                        err = ip_get_mcast_msfilter(sk, optval, optlen, len);
                goto out;
-       case IP_PKTOPTIONS:
-       {
-               struct msghdr msg;
-
-               sockopt_release_sock(sk);
-
-               if (sk->sk_type != SOCK_STREAM)
-                       return -ENOPROTOOPT;
-
-               if (optval.is_kernel) {
-                       msg.msg_control_is_user = false;
-                       msg.msg_control = optval.kernel;
-               } else {
-                       msg.msg_control_is_user = true;
-                       msg.msg_control_user = optval.user;
-               }
-               msg.msg_controllen = len;
-               msg.msg_flags = in_compat_syscall() ? MSG_CMSG_COMPAT : 0;
-
-               if (inet_test_bit(PKTINFO, sk)) {
-                       struct in_pktinfo info;
-
-                       info.ipi_addr.s_addr = inet->inet_rcv_saddr;
-                       info.ipi_spec_dst.s_addr = inet->inet_rcv_saddr;
-                       info.ipi_ifindex = inet->mc_index;
-                       put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);
-               }
-               if (inet_test_bit(TTL, sk)) {
-                       int hlim = READ_ONCE(inet->mc_ttl);
-
-                       put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim);
-               }
-               if (inet_test_bit(TOS, sk)) {
-                       int tos = inet->rcv_tos;
-                       put_cmsg(&msg, SOL_IP, IP_TOS, sizeof(tos), &tos);
-               }
-               len -= msg.msg_controllen;
-               return copy_to_sockptr(optlen, &len, sizeof(int));
-       }
        case IP_LOCAL_PORT_RANGE:
                val = inet->local_port_range.hi << 16 | inet->local_port_range.lo;
                break;