| From f0b3eb493bf21fdddb7a5382e85ccec784d6314f Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Wed, 18 Mar 2020 19:21:02 -0700 |
| Subject: [PATCH] tcp: repair: fix TCP_QUEUE_SEQ implementation |
| |
| commit 6cd6cbf593bfa3ae6fc3ed34ac21da4d35045425 upstream. |
| |
| When application uses TCP_QUEUE_SEQ socket option to |
| change tp->rcv_next, we must also update tp->copied_seq. |
| |
| Otherwise, stuff relying on tcp_inq() being precise can |
| eventually be confused. |
| |
| For example, tcp_zerocopy_receive() might crash because |
| it does not expect tcp_recv_skb() to return NULL. |
| |
| We could add tests in various places to fix the issue, |
| or simply make sure tcp_inq() wont return a random value, |
| and leave fast path as it is. |
| |
| Note that this fixes ioctl(fd, SIOCINQ, &val) at the same |
| time. |
| |
| Fixes: ee9952831cfd ("tcp: Initial repair mode") |
| Fixes: 05255b823a61 ("tcp: add TCP_ZEROCOPY_RECEIVE support for zerocopy receive") |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Reported-by: syzbot <syzkaller@googlegroups.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c |
| index 2abb74276ef9..cea071def651 100644 |
| --- a/net/ipv4/tcp.c |
| +++ b/net/ipv4/tcp.c |
| @@ -2918,8 +2918,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level, |
| err = -EPERM; |
| else if (tp->repair_queue == TCP_SEND_QUEUE) |
| WRITE_ONCE(tp->write_seq, val); |
| - else if (tp->repair_queue == TCP_RECV_QUEUE) |
| + else if (tp->repair_queue == TCP_RECV_QUEUE) { |
| WRITE_ONCE(tp->rcv_nxt, val); |
| + WRITE_ONCE(tp->copied_seq, val); |
| + } |
| else |
| err = -EINVAL; |
| break; |
| -- |
| 2.7.4 |
| |