From adbc5b5f716d108966bcf606e61de60b83f525a5 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 5 Mar 2020 21:20:35 +0100 Subject: [PATCH] tcp: tighten up checks for received SYN Any malicous segment could contain a SYN up to now (no check). A SYN in the wrong segment could break OOSEQ queueing. Fix this by allowing SYN only in states where it is required. See bug #56397: Assert "tcp_receive: ooseq tcplen > rcv_wnd" Signed-off-by: Simon Goldschmidt --- src/core/tcp_in.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 4bfba85f..90061281 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -852,6 +852,13 @@ tcp_process(struct tcp_pcb *pcb) tcp_parseopt(pcb); + if (flags & TCP_SYN) { + /* accept SYN only in 2 states: */ + if ((pcb->state != SYN_SENT) && (pcb->state != SYN_RCVD)) { + return ERR_OK; + } + } + /* Do different things depending on the TCP state. */ switch (pcb->state) { case SYN_SENT: @@ -924,7 +931,12 @@ tcp_process(struct tcp_pcb *pcb) } break; case SYN_RCVD: - if (flags & TCP_ACK) { + if (flags & TCP_SYN) { + if (seqno == pcb->rcv_nxt - 1) { + /* Looks like another copy of the SYN - retransmit our SYN-ACK */ + tcp_rexmit(pcb); + } + } else if (flags & TCP_ACK) { /* expected ACK number? */ if (TCP_SEQ_BETWEEN(ackno, pcb->lastack + 1, pcb->snd_nxt)) { pcb->state = ESTABLISHED; @@ -975,9 +987,6 @@ tcp_process(struct tcp_pcb *pcb) tcp_rst(pcb, ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), tcphdr->dest, tcphdr->src); } - } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { - /* Looks like another copy of the SYN - retransmit our SYN-ACK */ - tcp_rexmit(pcb); } break; case CLOSE_WAIT: