]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
tcp: Fix data-races around sysctl_tcp_reflect_tos.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Fri, 22 Jul 2022 18:22:04 +0000 (11:22 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Aug 2022 10:05:26 +0000 (12:05 +0200)
[ Upstream commit 870e3a634b6a6cb1543b359007aca73fe6a03ac5 ]

While reading sysctl_tcp_reflect_tos, it can be changed concurrently.
Thus, we need to add READ_ONCE() to its readers.

Fixes: ac8f1710c12b ("tcp: reflect tos value received in SYN to the socket")
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Acked-by: Wei Wang <weiwan@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/ipv4/tcp_ipv4.c
net/ipv6/tcp_ipv6.c

index a57f96b868741ed4e3784bdec75a0dbecc297dfb..1db9938163c436a02589262b73750f0610ba0fbf 100644 (file)
@@ -1007,7 +1007,7 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
        if (skb) {
                __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr);
 
-               tos = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ?
+               tos = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_reflect_tos) ?
                                (tcp_rsk(req)->syn_tos & ~INET_ECN_MASK) |
                                (inet_sk(sk)->tos & INET_ECN_MASK) :
                                inet_sk(sk)->tos;
@@ -1527,7 +1527,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
        /* Set ToS of the new socket based upon the value of incoming SYN.
         * ECT bits are set later in tcp_init_transfer().
         */
-       if (sock_net(sk)->ipv4.sysctl_tcp_reflect_tos)
+       if (READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_reflect_tos))
                newinet->tos = tcp_rsk(req)->syn_tos & ~INET_ECN_MASK;
 
        if (!dst) {
index 5185c11dc444728ef06cf47e368e7bbbc2b8c6e6..979e0d7b21195737f162e81df03bc43af70655c9 100644 (file)
@@ -546,7 +546,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
                if (np->repflow && ireq->pktopts)
                        fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
 
-               tclass = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ?
+               tclass = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_reflect_tos) ?
                                (tcp_rsk(req)->syn_tos & ~INET_ECN_MASK) |
                                (np->tclass & INET_ECN_MASK) :
                                np->tclass;
@@ -1314,7 +1314,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
        /* Set ToS of the new socket based upon the value of incoming SYN.
         * ECT bits are set later in tcp_init_transfer().
         */
-       if (sock_net(sk)->ipv4.sysctl_tcp_reflect_tos)
+       if (READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_reflect_tos))
                newnp->tclass = tcp_rsk(req)->syn_tos & ~INET_ECN_MASK;
 
        /* Clone native IPv6 options from listening socket (if any)