mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 22:02:02 +00:00
net: annotate data-races around sk->sk_lingertime
[ Upstream commitbc1fb82ae1
] 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:1da177e4c3
("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>
This commit is contained in:
parent
844d60cc5e
commit
9257a1d6f2
5 changed files with 13 additions and 13 deletions
|
@ -1394,7 +1394,7 @@ static int iso_sock_release(struct socket *sock)
|
||||||
|
|
||||||
iso_sock_close(sk);
|
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)) {
|
!(current->flags & PF_EXITING)) {
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
|
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
|
||||||
|
|
|
@ -1255,7 +1255,7 @@ static int sco_sock_release(struct socket *sock)
|
||||||
|
|
||||||
sco_sock_close(sk);
|
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)) {
|
!(current->flags & PF_EXITING)) {
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
|
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
|
||||||
|
|
|
@ -793,7 +793,7 @@ EXPORT_SYMBOL(sock_set_reuseport);
|
||||||
void sock_no_linger(struct sock *sk)
|
void sock_no_linger(struct sock *sk)
|
||||||
{
|
{
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
sk->sk_lingertime = 0;
|
WRITE_ONCE(sk->sk_lingertime, 0);
|
||||||
sock_set_flag(sk, SOCK_LINGER);
|
sock_set_flag(sk, SOCK_LINGER);
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
}
|
}
|
||||||
|
@ -1219,15 +1219,15 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!ling.l_onoff)
|
if (!ling.l_onoff) {
|
||||||
sock_reset_flag(sk, SOCK_LINGER);
|
sock_reset_flag(sk, SOCK_LINGER);
|
||||||
else {
|
} else {
|
||||||
#if (BITS_PER_LONG == 32)
|
unsigned long t_sec = ling.l_linger;
|
||||||
if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
|
|
||||||
sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT;
|
if (t_sec >= MAX_SCHEDULE_TIMEOUT / HZ)
|
||||||
|
WRITE_ONCE(sk->sk_lingertime, MAX_SCHEDULE_TIMEOUT);
|
||||||
else
|
else
|
||||||
#endif
|
WRITE_ONCE(sk->sk_lingertime, t_sec * HZ);
|
||||||
sk->sk_lingertime = (unsigned int)ling.l_linger * HZ;
|
|
||||||
sock_set_flag(sk, SOCK_LINGER);
|
sock_set_flag(sk, SOCK_LINGER);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1678,7 +1678,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
|
||||||
case SO_LINGER:
|
case SO_LINGER:
|
||||||
lv = sizeof(v.ling);
|
lv = sizeof(v.ling);
|
||||||
v.ling.l_onoff = sock_flag(sk, SOCK_LINGER);
|
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;
|
break;
|
||||||
|
|
||||||
case SO_BSDCOMPAT:
|
case SO_BSDCOMPAT:
|
||||||
|
|
|
@ -502,7 +502,7 @@ META_COLLECTOR(int_sk_lingertime)
|
||||||
*err = -1;
|
*err = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dst->value = sk->sk_lingertime / HZ;
|
dst->value = READ_ONCE(sk->sk_lingertime) / HZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
META_COLLECTOR(int_sk_err_qlen)
|
META_COLLECTOR(int_sk_err_qlen)
|
||||||
|
|
|
@ -1807,7 +1807,7 @@ void smc_close_non_accepted(struct sock *sk)
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
if (!sk->sk_lingertime)
|
if (!sk->sk_lingertime)
|
||||||
/* wait for peer closing */
|
/* 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);
|
__smc_release(smc);
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
sock_put(sk); /* sock_hold above */
|
sock_put(sk); /* sock_hold above */
|
||||||
|
|
Loading…
Reference in a new issue