]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: annotate lockless accesses to sk->sk_pacing_shift
authorEric Dumazet <edumazet@google.com>
Tue, 17 Dec 2019 02:51:03 +0000 (18:51 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jan 2020 09:20:07 +0000 (10:20 +0100)
[ Upstream commit 7c68fa2bddda6d942bd387c9ba5b4300737fd991 ]

sk->sk_pacing_shift can be read and written without lock
synchronization. This patch adds annotations to
document this fact and avoid future syzbot complains.

This might also avoid unexpected false sharing
in sk_pacing_shift_update(), as the compiler
could remove the conditional check and always
write over sk->sk_pacing_shift :

if (sk->sk_pacing_shift != val)
sk->sk_pacing_shift = val;

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/net/sock.h
net/core/sock.c
net/ipv4/tcp_bbr.c
net/ipv4/tcp_output.c

index e09e2886a8367a272e6b162077129ec11a09b959..6c5a3809483eaaffd39d33ca43dfa69165391d79 100644 (file)
@@ -2589,9 +2589,9 @@ static inline int sk_get_rmem0(const struct sock *sk, const struct proto *proto)
  */
 static inline void sk_pacing_shift_update(struct sock *sk, int val)
 {
-       if (!sk || !sk_fullsock(sk) || sk->sk_pacing_shift == val)
+       if (!sk || !sk_fullsock(sk) || READ_ONCE(sk->sk_pacing_shift) == val)
                return;
-       sk->sk_pacing_shift = val;
+       WRITE_ONCE(sk->sk_pacing_shift, val);
 }
 
 /* if a socket is bound to a device, check that the given device
index ac78a570e43add1ce263841212b3759dbbfd8eae..b4d1112174c168f89a358316fc41bf80cd8bb122 100644 (file)
@@ -2918,7 +2918,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
 
        sk->sk_max_pacing_rate = ~0UL;
        sk->sk_pacing_rate = ~0UL;
-       sk->sk_pacing_shift = 10;
+       WRITE_ONCE(sk->sk_pacing_shift, 10);
        sk->sk_incoming_cpu = -1;
 
        sk_rx_queue_clear(sk);
index 32772d6ded4ed359aa4d09ba67071e88a79ebdeb..a6545ef0d27b66d310b02affe14f41ab536243eb 100644 (file)
@@ -306,7 +306,8 @@ static u32 bbr_tso_segs_goal(struct sock *sk)
        /* Sort of tcp_tso_autosize() but ignoring
         * driver provided sk_gso_max_size.
         */
-       bytes = min_t(unsigned long, sk->sk_pacing_rate >> sk->sk_pacing_shift,
+       bytes = min_t(unsigned long,
+                     sk->sk_pacing_rate >> READ_ONCE(sk->sk_pacing_shift),
                      GSO_MAX_SIZE - 1 - MAX_TCP_HEADER);
        segs = max_t(u32, bytes / tp->mss_cache, bbr_min_tso_segs(sk));
 
index 0269584e9cf71513488e85a2ad3cb1c3517d0521..e4ba915c4bb52b2343a433b623b475f6ab0a63c3 100644 (file)
@@ -1728,7 +1728,7 @@ static u32 tcp_tso_autosize(const struct sock *sk, unsigned int mss_now,
        u32 bytes, segs;
 
        bytes = min_t(unsigned long,
-                     sk->sk_pacing_rate >> sk->sk_pacing_shift,
+                     sk->sk_pacing_rate >> READ_ONCE(sk->sk_pacing_shift),
                      sk->sk_gso_max_size - 1 - MAX_TCP_HEADER);
 
        /* Goal is to send at least one packet per ms,
@@ -2263,7 +2263,7 @@ static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb,
 
        limit = max_t(unsigned long,
                      2 * skb->truesize,
-                     sk->sk_pacing_rate >> sk->sk_pacing_shift);
+                     sk->sk_pacing_rate >> READ_ONCE(sk->sk_pacing_shift));
        if (sk->sk_pacing_status == SK_PACING_NONE)
                limit = min_t(unsigned long, limit,
                              sock_net(sk)->ipv4.sysctl_tcp_limit_output_bytes);