From 961ab59067e69bf1755b886472e2df94ff84b913 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 12 Mar 2021 11:02:53 +0100 Subject: [PATCH] 4.19-stable patches added patches: tcp-add-sanity-tests-to-tcp_queue_seq.patch tcp-annotate-tp-copied_seq-lockless-reads.patch tcp-annotate-tp-write_seq-lockless-reads.patch --- queue-4.19/series | 3 + ...cp-add-sanity-tests-to-tcp_queue_seq.patch | 82 ++++++ ...nnotate-tp-copied_seq-lockless-reads.patch | 196 ++++++++++++++ ...annotate-tp-write_seq-lockless-reads.patch | 243 ++++++++++++++++++ 4 files changed, 524 insertions(+) create mode 100644 queue-4.19/tcp-add-sanity-tests-to-tcp_queue_seq.patch create mode 100644 queue-4.19/tcp-annotate-tp-copied_seq-lockless-reads.patch create mode 100644 queue-4.19/tcp-annotate-tp-write_seq-lockless-reads.patch diff --git a/queue-4.19/series b/queue-4.19/series index 603919bf24c..02a7c7db7e8 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -8,5 +8,8 @@ can-flexcan-assert-frz-bit-in-flexcan_chip_freeze.patch can-flexcan-enable-rx-fifo-after-frz-halt-valid.patch netfilter-x_tables-gpf-inside-xt_find_revision.patch mt76-dma-do-not-report-truncated-frames-to-mac80211.patch +tcp-annotate-tp-copied_seq-lockless-reads.patch +tcp-annotate-tp-write_seq-lockless-reads.patch +tcp-add-sanity-tests-to-tcp_queue_seq.patch net-check-if-protocol-extracted-by-virtio_net_hdr_set_proto-is-correct.patch net-avoid-infinite-loop-in-mpls_gso_segment-when-mpls_hlen-0.patch diff --git a/queue-4.19/tcp-add-sanity-tests-to-tcp_queue_seq.patch b/queue-4.19/tcp-add-sanity-tests-to-tcp_queue_seq.patch new file mode 100644 index 00000000000..3e8d2802f3d --- /dev/null +++ b/queue-4.19/tcp-add-sanity-tests-to-tcp_queue_seq.patch @@ -0,0 +1,82 @@ +From foo@baz Fri Mar 12 10:50:45 AM CET 2021 +From: Eric Dumazet +Date: Fri, 12 Mar 2021 00:33:23 -0800 +Subject: tcp: add sanity tests to TCP_QUEUE_SEQ +To: Greg Kroah-Hartman +Cc: "David S . Miller" , netdev , Eric Dumazet , Eric Dumazet , stable@vger.kernel.org, Pavel Emelyanov , Qingyu Li +Message-ID: <20210312083323.3720479-3-eric.dumazet@gmail.com> + +From: Eric Dumazet + +[ Upstream commit 8811f4a9836e31c14ecdf79d9f3cb7c5d463265d ] + +Qingyu Li reported a syzkaller bug where the repro +changes RCV SEQ _after_ restoring data in the receive queue. + +mprotect(0x4aa000, 12288, PROT_READ) = 0 +mmap(0x1ffff000, 4096, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x1ffff000 +mmap(0x20000000, 16777216, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x20000000 +mmap(0x21000000, 4096, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x21000000 +socket(AF_INET6, SOCK_STREAM, IPPROTO_IP) = 3 +setsockopt(3, SOL_TCP, TCP_REPAIR, [1], 4) = 0 +connect(3, {sa_family=AF_INET6, sin6_port=htons(0), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_scope_id=0}, 28) = 0 +setsockopt(3, SOL_TCP, TCP_REPAIR_QUEUE, [1], 4) = 0 +sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="0x0000000000000003\0\0", iov_len=20}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 20 +setsockopt(3, SOL_TCP, TCP_REPAIR, [0], 4) = 0 +setsockopt(3, SOL_TCP, TCP_QUEUE_SEQ, [128], 4) = 0 +recvfrom(3, NULL, 20, 0, NULL, NULL) = -1 ECONNRESET (Connection reset by peer) + +syslog shows: +[ 111.205099] TCP recvmsg seq # bug 2: copied 80, seq 0, rcvnxt 80, fl 0 +[ 111.207894] WARNING: CPU: 1 PID: 356 at net/ipv4/tcp.c:2343 tcp_recvmsg_locked+0x90e/0x29a0 + +This should not be allowed. TCP_QUEUE_SEQ should only be used +when queues are empty. + +This patch fixes this case, and the tx path as well. + +Fixes: ee9952831cfd ("tcp: Initial repair mode") +Signed-off-by: Eric Dumazet +Cc: Pavel Emelyanov +Link: https://bugzilla.kernel.org/show_bug.cgi?id=212005 +Reported-by: Qingyu Li +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2886,16 +2886,23 @@ static int do_tcp_setsockopt(struct sock + break; + + case TCP_QUEUE_SEQ: +- if (sk->sk_state != TCP_CLOSE) ++ if (sk->sk_state != TCP_CLOSE) { + err = -EPERM; +- else if (tp->repair_queue == TCP_SEND_QUEUE) +- WRITE_ONCE(tp->write_seq, val); +- else if (tp->repair_queue == TCP_RECV_QUEUE) { +- WRITE_ONCE(tp->rcv_nxt, val); +- WRITE_ONCE(tp->copied_seq, val); +- } +- else ++ } else if (tp->repair_queue == TCP_SEND_QUEUE) { ++ if (!tcp_rtx_queue_empty(sk)) ++ err = -EPERM; ++ else ++ WRITE_ONCE(tp->write_seq, val); ++ } else if (tp->repair_queue == TCP_RECV_QUEUE) { ++ if (tp->rcv_nxt != tp->copied_seq) { ++ err = -EPERM; ++ } else { ++ WRITE_ONCE(tp->rcv_nxt, val); ++ WRITE_ONCE(tp->copied_seq, val); ++ } ++ } else { + err = -EINVAL; ++ } + break; + + case TCP_REPAIR_OPTIONS: diff --git a/queue-4.19/tcp-annotate-tp-copied_seq-lockless-reads.patch b/queue-4.19/tcp-annotate-tp-copied_seq-lockless-reads.patch new file mode 100644 index 00000000000..18f6c033dfd --- /dev/null +++ b/queue-4.19/tcp-annotate-tp-copied_seq-lockless-reads.patch @@ -0,0 +1,196 @@ +From foo@baz Fri Mar 12 10:50:45 AM CET 2021 +From: Eric Dumazet +Date: Fri, 12 Mar 2021 00:33:21 -0800 +Subject: tcp: annotate tp->copied_seq lockless reads +To: Greg Kroah-Hartman +Cc: "David S . Miller" , netdev , Eric Dumazet , Eric Dumazet , stable@vger.kernel.org +Message-ID: <20210312083323.3720479-1-eric.dumazet@gmail.com> + +From: Eric Dumazet + +[ Upstream commit 7db48e983930285b765743ebd665aecf9850582b ] + +There are few places where we fetch tp->copied_seq while +this field can change from IRQ or other cpu. + +We need to add READ_ONCE() annotations, and also make +sure write sides use corresponding WRITE_ONCE() to avoid +store-tearing. + +Note that tcp_inq_hint() was already using READ_ONCE(tp->copied_seq) + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp.c | 18 +++++++++--------- + net/ipv4/tcp_diag.c | 3 ++- + net/ipv4/tcp_input.c | 6 +++--- + net/ipv4/tcp_ipv4.c | 2 +- + net/ipv4/tcp_minisocks.c | 2 +- + net/ipv4/tcp_output.c | 2 +- + net/ipv6/tcp_ipv6.c | 2 +- + 7 files changed, 18 insertions(+), 17 deletions(-) + +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -567,7 +567,7 @@ __poll_t tcp_poll(struct file *file, str + (state != TCP_SYN_RECV || tp->fastopen_rsk)) { + int target = sock_rcvlowat(sk, 0, INT_MAX); + +- if (tp->urg_seq == tp->copied_seq && ++ if (tp->urg_seq == READ_ONCE(tp->copied_seq) && + !sock_flag(sk, SOCK_URGINLINE) && + tp->urg_data) + target++; +@@ -628,7 +628,7 @@ int tcp_ioctl(struct sock *sk, int cmd, + unlock_sock_fast(sk, slow); + break; + case SIOCATMARK: +- answ = tp->urg_data && tp->urg_seq == tp->copied_seq; ++ answ = tp->urg_data && tp->urg_seq == READ_ONCE(tp->copied_seq); + break; + case SIOCOUTQ: + if (sk->sk_state == TCP_LISTEN) +@@ -1696,9 +1696,9 @@ int tcp_read_sock(struct sock *sk, read_ + sk_eat_skb(sk, skb); + if (!desc->count) + break; +- tp->copied_seq = seq; ++ WRITE_ONCE(tp->copied_seq, seq); + } +- tp->copied_seq = seq; ++ WRITE_ONCE(tp->copied_seq, seq); + + tcp_rcv_space_adjust(sk); + +@@ -1835,7 +1835,7 @@ static int tcp_zerocopy_receive(struct s + out: + up_read(¤t->mm->mmap_sem); + if (length) { +- tp->copied_seq = seq; ++ WRITE_ONCE(tp->copied_seq, seq); + tcp_rcv_space_adjust(sk); + + /* Clean up data we have read: This will do ACK frames. */ +@@ -2112,7 +2112,7 @@ int tcp_recvmsg(struct sock *sk, struct + if (urg_offset < used) { + if (!urg_offset) { + if (!sock_flag(sk, SOCK_URGINLINE)) { +- ++*seq; ++ WRITE_ONCE(*seq, *seq + 1); + urg_hole++; + offset++; + used--; +@@ -2134,7 +2134,7 @@ int tcp_recvmsg(struct sock *sk, struct + } + } + +- *seq += used; ++ WRITE_ONCE(*seq, *seq + used); + copied += used; + len -= used; + +@@ -2163,7 +2163,7 @@ skip_copy: + + found_fin_ok: + /* Process the FIN. */ +- ++*seq; ++ WRITE_ONCE(*seq, *seq + 1); + if (!(flags & MSG_PEEK)) + sk_eat_skb(sk, skb); + break; +@@ -2578,7 +2578,7 @@ int tcp_disconnect(struct sock *sk, int + + tcp_clear_xmit_timers(sk); + __skb_queue_purge(&sk->sk_receive_queue); +- tp->copied_seq = tp->rcv_nxt; ++ WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); + tp->urg_data = 0; + tcp_write_queue_purge(sk); + tcp_fastopen_active_disable_ofo_check(sk); +--- a/net/ipv4/tcp_diag.c ++++ b/net/ipv4/tcp_diag.c +@@ -30,7 +30,8 @@ static void tcp_diag_get_info(struct soc + } else if (sk->sk_type == SOCK_STREAM) { + const struct tcp_sock *tp = tcp_sk(sk); + +- r->idiag_rqueue = max_t(int, READ_ONCE(tp->rcv_nxt) - tp->copied_seq, 0); ++ r->idiag_rqueue = max_t(int, READ_ONCE(tp->rcv_nxt) - ++ READ_ONCE(tp->copied_seq), 0); + r->idiag_wqueue = tp->write_seq - tp->snd_una; + } + if (info) +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -5889,7 +5889,7 @@ static int tcp_rcv_synsent_state_process + /* Remember, tcp_poll() does not lock socket! + * Change state from SYN-SENT only after copied_seq + * is initialized. */ +- tp->copied_seq = tp->rcv_nxt; ++ WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); + + smc_check_reset_syn(tp); + +@@ -5964,7 +5964,7 @@ discard: + } + + WRITE_ONCE(tp->rcv_nxt, TCP_SKB_CB(skb)->seq + 1); +- tp->copied_seq = tp->rcv_nxt; ++ WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); + tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1; + + /* RFC1323: The window in SYN & SYN/ACK segments is +@@ -6126,7 +6126,7 @@ int tcp_rcv_state_process(struct sock *s + tcp_rearm_rto(sk); + } else { + tcp_init_transfer(sk, BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB); +- tp->copied_seq = tp->rcv_nxt; ++ WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); + } + smp_mb(); + tcp_set_state(sk, TCP_ESTABLISHED); +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -2340,7 +2340,7 @@ static void get_tcp4_sock(struct sock *s + * we might find a transient negative value. + */ + rx_queue = max_t(int, READ_ONCE(tp->rcv_nxt) - +- tp->copied_seq, 0); ++ READ_ONCE(tp->copied_seq), 0); + + seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " + "%08X %5u %8d %lu %d %pK %lu %lu %u %u %d", +--- a/net/ipv4/tcp_minisocks.c ++++ b/net/ipv4/tcp_minisocks.c +@@ -470,7 +470,7 @@ struct sock *tcp_create_openreq_child(co + + seq = treq->rcv_isn + 1; + newtp->rcv_wup = seq; +- newtp->copied_seq = seq; ++ WRITE_ONCE(newtp->copied_seq, seq); + WRITE_ONCE(newtp->rcv_nxt, seq); + newtp->segs_in = 1; + +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -3381,7 +3381,7 @@ static void tcp_connect_init(struct sock + else + tp->rcv_tstamp = tcp_jiffies32; + tp->rcv_wup = tp->rcv_nxt; +- tp->copied_seq = tp->rcv_nxt; ++ WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); + + inet_csk(sk)->icsk_rto = tcp_timeout_init(sk); + inet_csk(sk)->icsk_retransmits = 0; +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1839,7 +1839,7 @@ static void get_tcp6_sock(struct seq_fil + * we might find a transient negative value. + */ + rx_queue = max_t(int, READ_ONCE(tp->rcv_nxt) - +- tp->copied_seq, 0); ++ READ_ONCE(tp->copied_seq), 0); + + seq_printf(seq, + "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " diff --git a/queue-4.19/tcp-annotate-tp-write_seq-lockless-reads.patch b/queue-4.19/tcp-annotate-tp-write_seq-lockless-reads.patch new file mode 100644 index 00000000000..53767d46025 --- /dev/null +++ b/queue-4.19/tcp-annotate-tp-write_seq-lockless-reads.patch @@ -0,0 +1,243 @@ +From foo@baz Fri Mar 12 10:50:45 AM CET 2021 +From: Eric Dumazet +Date: Fri, 12 Mar 2021 00:33:22 -0800 +Subject: tcp: annotate tp->write_seq lockless reads +To: Greg Kroah-Hartman +Cc: "David S . Miller" , netdev , Eric Dumazet , Eric Dumazet , stable@vger.kernel.org +Message-ID: <20210312083323.3720479-2-eric.dumazet@gmail.com> + +From: Eric Dumazet + +[ Upstream commit 0f31746452e6793ad6271337438af8f4defb8940 ] + +There are few places where we fetch tp->write_seq while +this field can change from IRQ or other cpu. + +We need to add READ_ONCE() annotations, and also make +sure write sides use corresponding WRITE_ONCE() to avoid +store-tearing. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/tcp.h | 2 +- + net/ipv4/tcp.c | 20 ++++++++++++-------- + net/ipv4/tcp_diag.c | 2 +- + net/ipv4/tcp_ipv4.c | 21 ++++++++++++--------- + net/ipv4/tcp_minisocks.c | 2 +- + net/ipv4/tcp_output.c | 4 ++-- + net/ipv6/tcp_ipv6.c | 13 +++++++------ + 7 files changed, 36 insertions(+), 28 deletions(-) + +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -1880,7 +1880,7 @@ static inline u32 tcp_notsent_lowat(cons + static inline bool tcp_stream_memory_free(const struct sock *sk) + { + const struct tcp_sock *tp = tcp_sk(sk); +- u32 notsent_bytes = tp->write_seq - tp->snd_nxt; ++ u32 notsent_bytes = READ_ONCE(tp->write_seq) - tp->snd_nxt; + + return notsent_bytes < tcp_notsent_lowat(tp); + } +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -637,7 +637,7 @@ int tcp_ioctl(struct sock *sk, int cmd, + if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) + answ = 0; + else +- answ = tp->write_seq - tp->snd_una; ++ answ = READ_ONCE(tp->write_seq) - tp->snd_una; + break; + case SIOCOUTQNSD: + if (sk->sk_state == TCP_LISTEN) +@@ -646,7 +646,7 @@ int tcp_ioctl(struct sock *sk, int cmd, + if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) + answ = 0; + else +- answ = tp->write_seq - tp->snd_nxt; ++ answ = READ_ONCE(tp->write_seq) - tp->snd_nxt; + break; + default: + return -ENOIOCTLCMD; +@@ -1037,7 +1037,7 @@ new_segment: + sk->sk_wmem_queued += copy; + sk_mem_charge(sk, copy); + skb->ip_summed = CHECKSUM_PARTIAL; +- tp->write_seq += copy; ++ WRITE_ONCE(tp->write_seq, tp->write_seq + copy); + TCP_SKB_CB(skb)->end_seq += copy; + tcp_skb_pcount_set(skb, 0); + +@@ -1391,7 +1391,7 @@ new_segment: + if (!copied) + TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH; + +- tp->write_seq += copy; ++ WRITE_ONCE(tp->write_seq, tp->write_seq + copy); + TCP_SKB_CB(skb)->end_seq += copy; + tcp_skb_pcount_set(skb, 0); + +@@ -2556,6 +2556,7 @@ int tcp_disconnect(struct sock *sk, int + struct inet_connection_sock *icsk = inet_csk(sk); + struct tcp_sock *tp = tcp_sk(sk); + int old_state = sk->sk_state; ++ u32 seq; + + if (old_state != TCP_CLOSE) + tcp_set_state(sk, TCP_CLOSE); +@@ -2593,9 +2594,12 @@ int tcp_disconnect(struct sock *sk, int + sock_reset_flag(sk, SOCK_DONE); + tp->srtt_us = 0; + tp->rcv_rtt_last_tsecr = 0; +- tp->write_seq += tp->max_window + 2; +- if (tp->write_seq == 0) +- tp->write_seq = 1; ++ ++ seq = tp->write_seq + tp->max_window + 2; ++ if (!seq) ++ seq = 1; ++ WRITE_ONCE(tp->write_seq, seq); ++ + tp->snd_cwnd = 2; + icsk->icsk_probes_out = 0; + tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; +@@ -2885,7 +2889,7 @@ static int do_tcp_setsockopt(struct sock + if (sk->sk_state != TCP_CLOSE) + err = -EPERM; + else if (tp->repair_queue == TCP_SEND_QUEUE) +- tp->write_seq = val; ++ WRITE_ONCE(tp->write_seq, val); + else if (tp->repair_queue == TCP_RECV_QUEUE) { + WRITE_ONCE(tp->rcv_nxt, val); + WRITE_ONCE(tp->copied_seq, val); +--- a/net/ipv4/tcp_diag.c ++++ b/net/ipv4/tcp_diag.c +@@ -32,7 +32,7 @@ static void tcp_diag_get_info(struct soc + + r->idiag_rqueue = max_t(int, READ_ONCE(tp->rcv_nxt) - + READ_ONCE(tp->copied_seq), 0); +- r->idiag_wqueue = tp->write_seq - tp->snd_una; ++ r->idiag_wqueue = READ_ONCE(tp->write_seq) - tp->snd_una; + } + if (info) + tcp_get_info(sk, info); +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -169,9 +169,11 @@ int tcp_twsk_unique(struct sock *sk, str + * without appearing to create any others. + */ + if (likely(!tp->repair)) { +- tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2; +- if (tp->write_seq == 0) +- tp->write_seq = 1; ++ u32 seq = tcptw->tw_snd_nxt + 65535 + 2; ++ ++ if (!seq) ++ seq = 1; ++ WRITE_ONCE(tp->write_seq, seq); + tp->rx_opt.ts_recent = tcptw->tw_ts_recent; + tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp; + } +@@ -258,7 +260,7 @@ int tcp_v4_connect(struct sock *sk, stru + tp->rx_opt.ts_recent = 0; + tp->rx_opt.ts_recent_stamp = 0; + if (likely(!tp->repair)) +- tp->write_seq = 0; ++ WRITE_ONCE(tp->write_seq, 0); + } + + inet->inet_dport = usin->sin_port; +@@ -296,10 +298,11 @@ int tcp_v4_connect(struct sock *sk, stru + + if (likely(!tp->repair)) { + if (!tp->write_seq) +- tp->write_seq = secure_tcp_seq(inet->inet_saddr, +- inet->inet_daddr, +- inet->inet_sport, +- usin->sin_port); ++ WRITE_ONCE(tp->write_seq, ++ secure_tcp_seq(inet->inet_saddr, ++ inet->inet_daddr, ++ inet->inet_sport, ++ usin->sin_port)); + tp->tsoffset = secure_tcp_ts_off(sock_net(sk), + inet->inet_saddr, + inet->inet_daddr); +@@ -2345,7 +2348,7 @@ static void get_tcp4_sock(struct sock *s + seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " + "%08X %5u %8d %lu %d %pK %lu %lu %u %u %d", + i, src, srcp, dest, destp, state, +- tp->write_seq - tp->snd_una, ++ READ_ONCE(tp->write_seq) - tp->snd_una, + rx_queue, + timer_active, + jiffies_delta_to_clock_t(timer_expires - jiffies), +--- a/net/ipv4/tcp_minisocks.c ++++ b/net/ipv4/tcp_minisocks.c +@@ -510,7 +510,7 @@ struct sock *tcp_create_openreq_child(co + newtp->app_limited = ~0U; + + tcp_init_xmit_timers(newsk); +- newtp->write_seq = newtp->pushed_seq = treq->snt_isn + 1; ++ WRITE_ONCE(newtp->write_seq, newtp->pushed_seq = treq->snt_isn + 1); + + newtp->rx_opt.saw_tstamp = 0; + +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1175,7 +1175,7 @@ static void tcp_queue_skb(struct sock *s + struct tcp_sock *tp = tcp_sk(sk); + + /* Advance write_seq and place onto the write_queue. */ +- tp->write_seq = TCP_SKB_CB(skb)->end_seq; ++ WRITE_ONCE(tp->write_seq, TCP_SKB_CB(skb)->end_seq); + __skb_header_release(skb); + tcp_add_write_queue_tail(sk, skb); + sk->sk_wmem_queued += skb->truesize; +@@ -3397,7 +3397,7 @@ static void tcp_connect_queue_skb(struct + __skb_header_release(skb); + sk->sk_wmem_queued += skb->truesize; + sk_mem_charge(sk, skb->truesize); +- tp->write_seq = tcb->end_seq; ++ WRITE_ONCE(tp->write_seq, tcb->end_seq); + tp->packets_out += tcp_skb_pcount(skb); + } + +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -206,7 +206,7 @@ static int tcp_v6_connect(struct sock *s + !ipv6_addr_equal(&sk->sk_v6_daddr, &usin->sin6_addr)) { + tp->rx_opt.ts_recent = 0; + tp->rx_opt.ts_recent_stamp = 0; +- tp->write_seq = 0; ++ WRITE_ONCE(tp->write_seq, 0); + } + + sk->sk_v6_daddr = usin->sin6_addr; +@@ -304,10 +304,11 @@ static int tcp_v6_connect(struct sock *s + + if (likely(!tp->repair)) { + if (!tp->write_seq) +- tp->write_seq = secure_tcpv6_seq(np->saddr.s6_addr32, +- sk->sk_v6_daddr.s6_addr32, +- inet->inet_sport, +- inet->inet_dport); ++ WRITE_ONCE(tp->write_seq, ++ secure_tcpv6_seq(np->saddr.s6_addr32, ++ sk->sk_v6_daddr.s6_addr32, ++ inet->inet_sport, ++ inet->inet_dport)); + tp->tsoffset = secure_tcpv6_ts_off(sock_net(sk), + np->saddr.s6_addr32, + sk->sk_v6_daddr.s6_addr32); +@@ -1850,7 +1851,7 @@ static void get_tcp6_sock(struct seq_fil + dest->s6_addr32[0], dest->s6_addr32[1], + dest->s6_addr32[2], dest->s6_addr32[3], destp, + state, +- tp->write_seq - tp->snd_una, ++ READ_ONCE(tp->write_seq) - tp->snd_una, + rx_queue, + timer_active, + jiffies_delta_to_clock_t(timer_expires - jiffies), -- 2.47.3