mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00:00
tcp: Fix data-races around sysctl knobs related to SYN option.
While reading these knobs, they can be changed concurrently.
Thus, we need to add READ_ONCE() to their readers.
- tcp_sack
- tcp_window_scaling
- tcp_timestamps
Fixes: 1da177e4c3
("Linux-2.6.12-rc2")
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
3d72bb4188
commit
3666f666e9
@ -1236,8 +1236,8 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
|
||||
csk->sndbuf = newsk->sk_sndbuf;
|
||||
csk->smac_idx = ((struct port_info *)netdev_priv(ndev))->smt_idx;
|
||||
RCV_WSCALE(tp) = select_rcv_wscale(tcp_full_space(newsk),
|
||||
sock_net(newsk)->
|
||||
ipv4.sysctl_tcp_window_scaling,
|
||||
READ_ONCE(sock_net(newsk)->
|
||||
ipv4.sysctl_tcp_window_scaling),
|
||||
tp->window_clamp);
|
||||
neigh_release(n);
|
||||
inet_inherit_port(&tcp_hashinfo, lsk, newsk);
|
||||
@ -1384,7 +1384,7 @@ static void chtls_pass_accept_request(struct sock *sk,
|
||||
#endif
|
||||
}
|
||||
if (req->tcpopt.wsf <= 14 &&
|
||||
sock_net(sk)->ipv4.sysctl_tcp_window_scaling) {
|
||||
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_window_scaling)) {
|
||||
inet_rsk(oreq)->wscale_ok = 1;
|
||||
inet_rsk(oreq)->snd_wscale = req->tcpopt.wsf;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ u32 secure_tcpv6_ts_off(const struct net *net,
|
||||
.daddr = *(struct in6_addr *)daddr,
|
||||
};
|
||||
|
||||
if (net->ipv4.sysctl_tcp_timestamps != 1)
|
||||
if (READ_ONCE(net->ipv4.sysctl_tcp_timestamps) != 1)
|
||||
return 0;
|
||||
|
||||
ts_secret_init();
|
||||
@ -120,7 +120,7 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
|
||||
#ifdef CONFIG_INET
|
||||
u32 secure_tcp_ts_off(const struct net *net, __be32 saddr, __be32 daddr)
|
||||
{
|
||||
if (net->ipv4.sysctl_tcp_timestamps != 1)
|
||||
if (READ_ONCE(net->ipv4.sysctl_tcp_timestamps) != 1)
|
||||
return 0;
|
||||
|
||||
ts_secret_init();
|
||||
|
@ -247,12 +247,12 @@ bool cookie_timestamp_decode(const struct net *net,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!net->ipv4.sysctl_tcp_timestamps)
|
||||
if (!READ_ONCE(net->ipv4.sysctl_tcp_timestamps))
|
||||
return false;
|
||||
|
||||
tcp_opt->sack_ok = (options & TS_OPT_SACK) ? TCP_SACK_SEEN : 0;
|
||||
|
||||
if (tcp_opt->sack_ok && !net->ipv4.sysctl_tcp_sack)
|
||||
if (tcp_opt->sack_ok && !READ_ONCE(net->ipv4.sysctl_tcp_sack))
|
||||
return false;
|
||||
|
||||
if ((options & TS_OPT_WSCALE_MASK) == TS_OPT_WSCALE_MASK)
|
||||
@ -261,7 +261,7 @@ bool cookie_timestamp_decode(const struct net *net,
|
||||
tcp_opt->wscale_ok = 1;
|
||||
tcp_opt->snd_wscale = options & TS_OPT_WSCALE_MASK;
|
||||
|
||||
return net->ipv4.sysctl_tcp_window_scaling != 0;
|
||||
return READ_ONCE(net->ipv4.sysctl_tcp_window_scaling) != 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cookie_timestamp_decode);
|
||||
|
||||
|
@ -4060,7 +4060,7 @@ void tcp_parse_options(const struct net *net,
|
||||
break;
|
||||
case TCPOPT_WINDOW:
|
||||
if (opsize == TCPOLEN_WINDOW && th->syn &&
|
||||
!estab && net->ipv4.sysctl_tcp_window_scaling) {
|
||||
!estab && READ_ONCE(net->ipv4.sysctl_tcp_window_scaling)) {
|
||||
__u8 snd_wscale = *(__u8 *)ptr;
|
||||
opt_rx->wscale_ok = 1;
|
||||
if (snd_wscale > TCP_MAX_WSCALE) {
|
||||
@ -4076,7 +4076,7 @@ void tcp_parse_options(const struct net *net,
|
||||
case TCPOPT_TIMESTAMP:
|
||||
if ((opsize == TCPOLEN_TIMESTAMP) &&
|
||||
((estab && opt_rx->tstamp_ok) ||
|
||||
(!estab && net->ipv4.sysctl_tcp_timestamps))) {
|
||||
(!estab && READ_ONCE(net->ipv4.sysctl_tcp_timestamps)))) {
|
||||
opt_rx->saw_tstamp = 1;
|
||||
opt_rx->rcv_tsval = get_unaligned_be32(ptr);
|
||||
opt_rx->rcv_tsecr = get_unaligned_be32(ptr + 4);
|
||||
@ -4084,7 +4084,7 @@ void tcp_parse_options(const struct net *net,
|
||||
break;
|
||||
case TCPOPT_SACK_PERM:
|
||||
if (opsize == TCPOLEN_SACK_PERM && th->syn &&
|
||||
!estab && net->ipv4.sysctl_tcp_sack) {
|
||||
!estab && READ_ONCE(net->ipv4.sysctl_tcp_sack)) {
|
||||
opt_rx->sack_ok = TCP_SACK_SEEN;
|
||||
tcp_sack_reset(opt_rx);
|
||||
}
|
||||
|
@ -791,18 +791,18 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
|
||||
opts->mss = tcp_advertise_mss(sk);
|
||||
remaining -= TCPOLEN_MSS_ALIGNED;
|
||||
|
||||
if (likely(sock_net(sk)->ipv4.sysctl_tcp_timestamps && !*md5)) {
|
||||
if (likely(READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_timestamps) && !*md5)) {
|
||||
opts->options |= OPTION_TS;
|
||||
opts->tsval = tcp_skb_timestamp(skb) + tp->tsoffset;
|
||||
opts->tsecr = tp->rx_opt.ts_recent;
|
||||
remaining -= TCPOLEN_TSTAMP_ALIGNED;
|
||||
}
|
||||
if (likely(sock_net(sk)->ipv4.sysctl_tcp_window_scaling)) {
|
||||
if (likely(READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_window_scaling))) {
|
||||
opts->ws = tp->rx_opt.rcv_wscale;
|
||||
opts->options |= OPTION_WSCALE;
|
||||
remaining -= TCPOLEN_WSCALE_ALIGNED;
|
||||
}
|
||||
if (likely(sock_net(sk)->ipv4.sysctl_tcp_sack)) {
|
||||
if (likely(READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_sack))) {
|
||||
opts->options |= OPTION_SACK_ADVERTISE;
|
||||
if (unlikely(!(OPTION_TS & opts->options)))
|
||||
remaining -= TCPOLEN_SACKPERM_ALIGNED;
|
||||
@ -3647,7 +3647,7 @@ static void tcp_connect_init(struct sock *sk)
|
||||
* See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
|
||||
*/
|
||||
tp->tcp_header_len = sizeof(struct tcphdr);
|
||||
if (sock_net(sk)->ipv4.sysctl_tcp_timestamps)
|
||||
if (READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_timestamps))
|
||||
tp->tcp_header_len += TCPOLEN_TSTAMP_ALIGNED;
|
||||
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
@ -3683,7 +3683,7 @@ static void tcp_connect_init(struct sock *sk)
|
||||
tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
|
||||
&tp->rcv_wnd,
|
||||
&tp->window_clamp,
|
||||
sock_net(sk)->ipv4.sysctl_tcp_window_scaling,
|
||||
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_window_scaling),
|
||||
&rcv_wscale,
|
||||
rcv_wnd);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user