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.

net: annotate data-races around sk->sk_lingertime

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

Other reads also happen without socket lock being held,
and must be annotated.

Remove preprocessor logic using BITS_PER_LONG, compilers
are smart enough to figure this by themselves.

v2: fixed a clang W=1 (-Wtautological-constant-out-of-range-compare) warning
(Jakub)

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Eric Dumazet and committed by
David S. Miller
bc1fb82a b4672c73

+13 -13
+1 -1
net/bluetooth/iso.c
··· 1475 1475 1476 1476 iso_sock_close(sk); 1477 1477 1478 - if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && 1478 + if (sock_flag(sk, SOCK_LINGER) && READ_ONCE(sk->sk_lingertime) && 1479 1479 !(current->flags & PF_EXITING)) { 1480 1480 lock_sock(sk); 1481 1481 err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
+1 -1
net/bluetooth/sco.c
··· 1245 1245 1246 1246 sco_sock_close(sk); 1247 1247 1248 - if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && 1248 + if (sock_flag(sk, SOCK_LINGER) && READ_ONCE(sk->sk_lingertime) && 1249 1249 !(current->flags & PF_EXITING)) { 1250 1250 lock_sock(sk); 1251 1251 err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
+9 -9
net/core/sock.c
··· 797 797 void sock_no_linger(struct sock *sk) 798 798 { 799 799 lock_sock(sk); 800 - sk->sk_lingertime = 0; 800 + WRITE_ONCE(sk->sk_lingertime, 0); 801 801 sock_set_flag(sk, SOCK_LINGER); 802 802 release_sock(sk); 803 803 } ··· 1230 1230 ret = -EFAULT; 1231 1231 break; 1232 1232 } 1233 - if (!ling.l_onoff) 1233 + if (!ling.l_onoff) { 1234 1234 sock_reset_flag(sk, SOCK_LINGER); 1235 - else { 1236 - #if (BITS_PER_LONG == 32) 1237 - if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ) 1238 - sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT; 1235 + } else { 1236 + unsigned long t_sec = ling.l_linger; 1237 + 1238 + if (t_sec >= MAX_SCHEDULE_TIMEOUT / HZ) 1239 + WRITE_ONCE(sk->sk_lingertime, MAX_SCHEDULE_TIMEOUT); 1239 1240 else 1240 - #endif 1241 - sk->sk_lingertime = (unsigned int)ling.l_linger * HZ; 1241 + WRITE_ONCE(sk->sk_lingertime, t_sec * HZ); 1242 1242 sock_set_flag(sk, SOCK_LINGER); 1243 1243 } 1244 1244 break; ··· 1692 1692 case SO_LINGER: 1693 1693 lv = sizeof(v.ling); 1694 1694 v.ling.l_onoff = sock_flag(sk, SOCK_LINGER); 1695 - v.ling.l_linger = sk->sk_lingertime / HZ; 1695 + v.ling.l_linger = READ_ONCE(sk->sk_lingertime) / HZ; 1696 1696 break; 1697 1697 1698 1698 case SO_BSDCOMPAT:
+1 -1
net/sched/em_meta.c
··· 502 502 *err = -1; 503 503 return; 504 504 } 505 - dst->value = sk->sk_lingertime / HZ; 505 + dst->value = READ_ONCE(sk->sk_lingertime) / HZ; 506 506 } 507 507 508 508 META_COLLECTOR(int_sk_err_qlen)
+1 -1
net/smc/af_smc.c
··· 1840 1840 lock_sock(sk); 1841 1841 if (!sk->sk_lingertime) 1842 1842 /* wait for peer closing */ 1843 - sk->sk_lingertime = SMC_MAX_STREAM_WAIT_TIMEOUT; 1843 + WRITE_ONCE(sk->sk_lingertime, SMC_MAX_STREAM_WAIT_TIMEOUT); 1844 1844 __smc_release(smc); 1845 1845 release_sock(sk); 1846 1846 sock_put(sk); /* sock_hold above */