net: annotate data-races around sk->sk_tx_queue_mapping
authorEric Dumazet <edumazet@google.com>
Thu, 21 Sep 2023 20:28:17 +0000 (20:28 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 1 Oct 2023 18:09:54 +0000 (19:09 +0100)
This field can be read or written without socket lock being held.

Add annotations to avoid load-store tearing.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/sock.h

index 2800d587b08ddc93d7d190ea71dd96a1a3591c1a..a50e37af2b57d9529320b97b2f25a17b64e4d54c 100644 (file)
@@ -2007,21 +2007,33 @@ static inline void sk_tx_queue_set(struct sock *sk, int tx_queue)
        /* sk_tx_queue_mapping accept only upto a 16-bit value */
        if (WARN_ON_ONCE((unsigned short)tx_queue >= USHRT_MAX))
                return;
-       sk->sk_tx_queue_mapping = tx_queue;
+       /* Paired with READ_ONCE() in sk_tx_queue_get() and
+        * other WRITE_ONCE() because socket lock might be not held.
+        */
+       WRITE_ONCE(sk->sk_tx_queue_mapping, tx_queue);
 }
 
 #define NO_QUEUE_MAPPING       USHRT_MAX
 
 static inline void sk_tx_queue_clear(struct sock *sk)
 {
-       sk->sk_tx_queue_mapping = NO_QUEUE_MAPPING;
+       /* Paired with READ_ONCE() in sk_tx_queue_get() and
+        * other WRITE_ONCE() because socket lock might be not held.
+        */
+       WRITE_ONCE(sk->sk_tx_queue_mapping, NO_QUEUE_MAPPING);
 }
 
 static inline int sk_tx_queue_get(const struct sock *sk)
 {
-       if (sk && sk->sk_tx_queue_mapping != NO_QUEUE_MAPPING)
-               return sk->sk_tx_queue_mapping;
+       if (sk) {
+               /* Paired with WRITE_ONCE() in sk_tx_queue_clear()
+                * and sk_tx_queue_set().
+                */
+               int val = READ_ONCE(sk->sk_tx_queue_mapping);
 
+               if (val != NO_QUEUE_MAPPING)
+                       return val;
+       }
        return -1;
 }