Commit 3666f666 authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by David S. Miller

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: 1da177e4 ("Linux-2.6.12-rc2")
Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3d72bb41
...@@ -1236,8 +1236,8 @@ static struct sock *chtls_recv_sock(struct sock *lsk, ...@@ -1236,8 +1236,8 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
csk->sndbuf = newsk->sk_sndbuf; csk->sndbuf = newsk->sk_sndbuf;
csk->smac_idx = ((struct port_info *)netdev_priv(ndev))->smt_idx; csk->smac_idx = ((struct port_info *)netdev_priv(ndev))->smt_idx;
RCV_WSCALE(tp) = select_rcv_wscale(tcp_full_space(newsk), RCV_WSCALE(tp) = select_rcv_wscale(tcp_full_space(newsk),
sock_net(newsk)-> READ_ONCE(sock_net(newsk)->
ipv4.sysctl_tcp_window_scaling, ipv4.sysctl_tcp_window_scaling),
tp->window_clamp); tp->window_clamp);
neigh_release(n); neigh_release(n);
inet_inherit_port(&tcp_hashinfo, lsk, newsk); inet_inherit_port(&tcp_hashinfo, lsk, newsk);
...@@ -1384,7 +1384,7 @@ static void chtls_pass_accept_request(struct sock *sk, ...@@ -1384,7 +1384,7 @@ static void chtls_pass_accept_request(struct sock *sk,
#endif #endif
} }
if (req->tcpopt.wsf <= 14 && 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)->wscale_ok = 1;
inet_rsk(oreq)->snd_wscale = req->tcpopt.wsf; inet_rsk(oreq)->snd_wscale = req->tcpopt.wsf;
} }
......
...@@ -64,7 +64,7 @@ u32 secure_tcpv6_ts_off(const struct net *net, ...@@ -64,7 +64,7 @@ u32 secure_tcpv6_ts_off(const struct net *net,
.daddr = *(struct in6_addr *)daddr, .daddr = *(struct in6_addr *)daddr,
}; };
if (net->ipv4.sysctl_tcp_timestamps != 1) if (READ_ONCE(net->ipv4.sysctl_tcp_timestamps) != 1)
return 0; return 0;
ts_secret_init(); ts_secret_init();
...@@ -120,7 +120,7 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral); ...@@ -120,7 +120,7 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
#ifdef CONFIG_INET #ifdef CONFIG_INET
u32 secure_tcp_ts_off(const struct net *net, __be32 saddr, __be32 daddr) 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; return 0;
ts_secret_init(); ts_secret_init();
......
...@@ -247,12 +247,12 @@ bool cookie_timestamp_decode(const struct net *net, ...@@ -247,12 +247,12 @@ bool cookie_timestamp_decode(const struct net *net,
return true; return true;
} }
if (!net->ipv4.sysctl_tcp_timestamps) if (!READ_ONCE(net->ipv4.sysctl_tcp_timestamps))
return false; return false;
tcp_opt->sack_ok = (options & TS_OPT_SACK) ? TCP_SACK_SEEN : 0; 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; return false;
if ((options & TS_OPT_WSCALE_MASK) == TS_OPT_WSCALE_MASK) if ((options & TS_OPT_WSCALE_MASK) == TS_OPT_WSCALE_MASK)
...@@ -261,7 +261,7 @@ bool cookie_timestamp_decode(const struct net *net, ...@@ -261,7 +261,7 @@ bool cookie_timestamp_decode(const struct net *net,
tcp_opt->wscale_ok = 1; tcp_opt->wscale_ok = 1;
tcp_opt->snd_wscale = options & TS_OPT_WSCALE_MASK; 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); EXPORT_SYMBOL(cookie_timestamp_decode);
......
...@@ -4060,7 +4060,7 @@ void tcp_parse_options(const struct net *net, ...@@ -4060,7 +4060,7 @@ void tcp_parse_options(const struct net *net,
break; break;
case TCPOPT_WINDOW: case TCPOPT_WINDOW:
if (opsize == TCPOLEN_WINDOW && th->syn && 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; __u8 snd_wscale = *(__u8 *)ptr;
opt_rx->wscale_ok = 1; opt_rx->wscale_ok = 1;
if (snd_wscale > TCP_MAX_WSCALE) { if (snd_wscale > TCP_MAX_WSCALE) {
...@@ -4076,7 +4076,7 @@ void tcp_parse_options(const struct net *net, ...@@ -4076,7 +4076,7 @@ void tcp_parse_options(const struct net *net,
case TCPOPT_TIMESTAMP: case TCPOPT_TIMESTAMP:
if ((opsize == TCPOLEN_TIMESTAMP) && if ((opsize == TCPOLEN_TIMESTAMP) &&
((estab && opt_rx->tstamp_ok) || ((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->saw_tstamp = 1;
opt_rx->rcv_tsval = get_unaligned_be32(ptr); opt_rx->rcv_tsval = get_unaligned_be32(ptr);
opt_rx->rcv_tsecr = get_unaligned_be32(ptr + 4); opt_rx->rcv_tsecr = get_unaligned_be32(ptr + 4);
...@@ -4084,7 +4084,7 @@ void tcp_parse_options(const struct net *net, ...@@ -4084,7 +4084,7 @@ void tcp_parse_options(const struct net *net,
break; break;
case TCPOPT_SACK_PERM: case TCPOPT_SACK_PERM:
if (opsize == TCPOLEN_SACK_PERM && th->syn && 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; opt_rx->sack_ok = TCP_SACK_SEEN;
tcp_sack_reset(opt_rx); tcp_sack_reset(opt_rx);
} }
......
...@@ -791,18 +791,18 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb, ...@@ -791,18 +791,18 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
opts->mss = tcp_advertise_mss(sk); opts->mss = tcp_advertise_mss(sk);
remaining -= TCPOLEN_MSS_ALIGNED; 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->options |= OPTION_TS;
opts->tsval = tcp_skb_timestamp(skb) + tp->tsoffset; opts->tsval = tcp_skb_timestamp(skb) + tp->tsoffset;
opts->tsecr = tp->rx_opt.ts_recent; opts->tsecr = tp->rx_opt.ts_recent;
remaining -= TCPOLEN_TSTAMP_ALIGNED; 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->ws = tp->rx_opt.rcv_wscale;
opts->options |= OPTION_WSCALE; opts->options |= OPTION_WSCALE;
remaining -= TCPOLEN_WSCALE_ALIGNED; 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; opts->options |= OPTION_SACK_ADVERTISE;
if (unlikely(!(OPTION_TS & opts->options))) if (unlikely(!(OPTION_TS & opts->options)))
remaining -= TCPOLEN_SACKPERM_ALIGNED; remaining -= TCPOLEN_SACKPERM_ALIGNED;
...@@ -3647,7 +3647,7 @@ static void tcp_connect_init(struct sock *sk) ...@@ -3647,7 +3647,7 @@ static void tcp_connect_init(struct sock *sk)
* See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT. * See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
*/ */
tp->tcp_header_len = sizeof(struct tcphdr); 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; tp->tcp_header_len += TCPOLEN_TSTAMP_ALIGNED;
#ifdef CONFIG_TCP_MD5SIG #ifdef CONFIG_TCP_MD5SIG
...@@ -3683,7 +3683,7 @@ static void tcp_connect_init(struct sock *sk) ...@@ -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->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
&tp->rcv_wnd, &tp->rcv_wnd,
&tp->window_clamp, &tp->window_clamp,
sock_net(sk)->ipv4.sysctl_tcp_window_scaling, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_window_scaling),
&rcv_wscale, &rcv_wscale,
rcv_wnd); rcv_wnd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment