Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

inetpeer: avoid false sharing in inet_peer_xrlim_allow()

Under DOS, inet_peer_xrlim_allow() might be called millions
of times per second from different cpus.

Make sure to write over peer->rate_tokens and peer->rate_last
only when really needed.

Note the inherent races of this function are still there,
we do not care of precise ICMP rate limiting.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20241219150330.3159027-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
05dd04b2 710aebda

+11 -7
+11 -7
net/ipv4/inetpeer.c
··· 246 246 #define XRLIM_BURST_FACTOR 6 247 247 bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout) 248 248 { 249 - unsigned long now, token; 249 + unsigned long now, token, otoken, delta; 250 250 bool rc = false; 251 251 252 252 if (!peer) 253 253 return true; 254 254 255 - token = peer->rate_tokens; 255 + token = otoken = READ_ONCE(peer->rate_tokens); 256 256 now = jiffies; 257 - token += now - peer->rate_last; 258 - peer->rate_last = now; 259 - if (token > XRLIM_BURST_FACTOR * timeout) 260 - token = XRLIM_BURST_FACTOR * timeout; 257 + delta = now - READ_ONCE(peer->rate_last); 258 + if (delta) { 259 + WRITE_ONCE(peer->rate_last, now); 260 + token += delta; 261 + if (token > XRLIM_BURST_FACTOR * timeout) 262 + token = XRLIM_BURST_FACTOR * timeout; 263 + } 261 264 if (token >= timeout) { 262 265 token -= timeout; 263 266 rc = true; 264 267 } 265 - peer->rate_tokens = token; 268 + if (token != otoken) 269 + WRITE_ONCE(peer->rate_tokens, token); 266 270 return rc; 267 271 } 268 272 EXPORT_SYMBOL(inet_peer_xrlim_allow);