summary refs log tree commit diff
path: root/net/core
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2023-07-28 15:03:10 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-08-11 12:08:14 +0200
commitbe43c8f1c9164adc14dbcaf06bb5ab921d82586a (patch)
tree65a8719d9eb3c5feb68c0c41ac170a64760e9bfb /net/core
parent0317c8322d9ac86a2bf251f94efc7fe96643e0fb (diff)
downloadlinux-be43c8f1c9164adc14dbcaf06bb5ab921d82586a.tar.gz
net: annotate data-races around sk->sk_max_pacing_rate
[ Upstream commit ea7f45ef77b39e72244d282e47f6cb1ef4135cd2 ]

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

Fixes: 62748f32d501 ("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>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/sock.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/net/core/sock.c b/net/core/sock.c
index 77abd69c56dd..86e88de1238b 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1426,7 +1426,8 @@ set_sndbuf:
 			cmpxchg(&sk->sk_pacing_status,
 				SK_PACING_NONE,
 				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);
 		break;
 		}
@@ -1852,12 +1853,14 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
 #endif
 
 	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)) {
 			lv = sizeof(v.ulval);
-			v.ulval = sk->sk_max_pacing_rate;
+			v.ulval = READ_ONCE(sk->sk_max_pacing_rate);
 		} else {
 			/* 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;