Skip to content

Commit

Permalink
net: annotate data-races around sk->sk_lingertime
Browse files Browse the repository at this point in the history
[ Upstream commit bc1fb82 ]

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: 1da177e ("Linux-2.6.12-rc2")
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>
  • Loading branch information
Eric Dumazet authored and gregkh committed Sep 13, 2023
1 parent 844d60c commit 9257a1d
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 13 deletions.
2 changes: 1 addition & 1 deletion net/bluetooth/iso.c
Expand Up @@ -1394,7 +1394,7 @@ static int iso_sock_release(struct socket *sock)

iso_sock_close(sk);

if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
if (sock_flag(sk, SOCK_LINGER) && READ_ONCE(sk->sk_lingertime) &&
!(current->flags & PF_EXITING)) {
lock_sock(sk);
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/sco.c
Expand Up @@ -1255,7 +1255,7 @@ static int sco_sock_release(struct socket *sock)

sco_sock_close(sk);

if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
if (sock_flag(sk, SOCK_LINGER) && READ_ONCE(sk->sk_lingertime) &&
!(current->flags & PF_EXITING)) {
lock_sock(sk);
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
Expand Down
18 changes: 9 additions & 9 deletions net/core/sock.c
Expand Up @@ -793,7 +793,7 @@ EXPORT_SYMBOL(sock_set_reuseport);
void sock_no_linger(struct sock *sk)
{
lock_sock(sk);
sk->sk_lingertime = 0;
WRITE_ONCE(sk->sk_lingertime, 0);
sock_set_flag(sk, SOCK_LINGER);
release_sock(sk);
}
Expand Down Expand Up @@ -1219,15 +1219,15 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
ret = -EFAULT;
break;
}
if (!ling.l_onoff)
if (!ling.l_onoff) {
sock_reset_flag(sk, SOCK_LINGER);
else {
#if (BITS_PER_LONG == 32)
if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT;
} else {
unsigned long t_sec = ling.l_linger;

if (t_sec >= MAX_SCHEDULE_TIMEOUT / HZ)
WRITE_ONCE(sk->sk_lingertime, MAX_SCHEDULE_TIMEOUT);
else
#endif
sk->sk_lingertime = (unsigned int)ling.l_linger * HZ;
WRITE_ONCE(sk->sk_lingertime, t_sec * HZ);
sock_set_flag(sk, SOCK_LINGER);
}
break;
Expand Down Expand Up @@ -1678,7 +1678,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
case SO_LINGER:
lv = sizeof(v.ling);
v.ling.l_onoff = sock_flag(sk, SOCK_LINGER);
v.ling.l_linger = sk->sk_lingertime / HZ;
v.ling.l_linger = READ_ONCE(sk->sk_lingertime) / HZ;
break;

case SO_BSDCOMPAT:
Expand Down
2 changes: 1 addition & 1 deletion net/sched/em_meta.c
Expand Up @@ -502,7 +502,7 @@ META_COLLECTOR(int_sk_lingertime)
*err = -1;
return;
}
dst->value = sk->sk_lingertime / HZ;
dst->value = READ_ONCE(sk->sk_lingertime) / HZ;
}

META_COLLECTOR(int_sk_err_qlen)
Expand Down
2 changes: 1 addition & 1 deletion net/smc/af_smc.c
Expand Up @@ -1807,7 +1807,7 @@ void smc_close_non_accepted(struct sock *sk)
lock_sock(sk);
if (!sk->sk_lingertime)
/* wait for peer closing */
sk->sk_lingertime = SMC_MAX_STREAM_WAIT_TIMEOUT;
WRITE_ONCE(sk->sk_lingertime, SMC_MAX_STREAM_WAIT_TIMEOUT);
__smc_release(smc);
release_sock(sk);
sock_put(sk); /* sock_hold above */
Expand Down

0 comments on commit 9257a1d

Please sign in to comment.