net: annotate data-races around sk->sk_max_pacing_rate

[ Upstream commit ea7f45ef77 ]

sk_getsockopt() runs locklessly. This means sk->sk_max_pacing_rate
can be read while other threads are changing its value.

Fixes: 62748f32d5 ("net: introduce SO_MAX_PACING_RATE")
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>
This commit is contained in:
Eric Dumazet
2023-07-28 15:03:10 +00:00
committed by Greg Kroah-Hartman
parent 0317c8322d
commit be43c8f1c9

View File

@@ -1426,7 +1426,8 @@ set_sndbuf:
cmpxchg(&sk->sk_pacing_status, cmpxchg(&sk->sk_pacing_status,
SK_PACING_NONE, SK_PACING_NONE,
SK_PACING_NEEDED); SK_PACING_NEEDED);
sk->sk_max_pacing_rate = ulval; /* Pairs with READ_ONCE() from sk_getsockopt() */
WRITE_ONCE(sk->sk_max_pacing_rate, ulval);
sk->sk_pacing_rate = min(sk->sk_pacing_rate, ulval); sk->sk_pacing_rate = min(sk->sk_pacing_rate, ulval);
break; break;
} }
@@ -1852,12 +1853,14 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
#endif #endif
case SO_MAX_PACING_RATE: case SO_MAX_PACING_RATE:
/* The READ_ONCE() pair with the WRITE_ONCE() in sk_setsockopt() */
if (sizeof(v.ulval) != sizeof(v.val) && len >= sizeof(v.ulval)) { if (sizeof(v.ulval) != sizeof(v.val) && len >= sizeof(v.ulval)) {
lv = sizeof(v.ulval); lv = sizeof(v.ulval);
v.ulval = sk->sk_max_pacing_rate; v.ulval = READ_ONCE(sk->sk_max_pacing_rate);
} else { } else {
/* 32bit version */ /* 32bit version */
v.val = min_t(unsigned long, sk->sk_max_pacing_rate, ~0U); v.val = min_t(unsigned long, ~0U,
READ_ONCE(sk->sk_max_pacing_rate));
} }
break; break;