From 6853238c8b6ed7ae6d1bbcbb465e5316ac86e0b2 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Thu, 26 Dec 2024 12:12:48 +0100 Subject: [PATCH] picotcp: Discard incoming TCP segments with zero-len options upstream https://github.com/virtualsquare/picotcp/commit/7aa288510a033691c3f09e2c43e10f07e24434b7 --- core/deps/picotcp/modules/pico_tcp.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/core/deps/picotcp/modules/pico_tcp.c b/core/deps/picotcp/modules/pico_tcp.c index b16b92f33..f7b7f7866 100644 --- a/core/deps/picotcp/modules/pico_tcp.c +++ b/core/deps/picotcp/modules/pico_tcp.c @@ -882,7 +882,7 @@ static inline void tcp_parse_option_timestamp(struct pico_socket_tcp *t, struct t->ts_nxt = long_be(tsval); } -static void tcp_parse_options(struct pico_frame *f) +static int tcp_parse_options(struct pico_frame *f) { struct pico_socket_tcp *t = (struct pico_socket_tcp *)f->sock; uint8_t *opt = f->transport_hdr + PICO_SIZE_TCPHDR; @@ -899,6 +899,10 @@ static void tcp_parse_options(struct pico_frame *f) if (f->payload && ((opt + i) > f->payload)) break; + if (len == 0) { + return -1; + } + tcp_dbg_options("Received option '%d', len = %d \n", type, len); switch (type) { case PICO_TCP_OPTION_NOOP: @@ -926,6 +930,7 @@ static void tcp_parse_options(struct pico_frame *f) i = i + len - 2; } } + return 0; } static inline void tcp_send_add_tcpflags(struct pico_socket_tcp *ts, struct pico_frame *f) @@ -1757,7 +1762,8 @@ static int tcp_data_in(struct pico_socket *s, struct pico_frame *f) (void)hdr; if (((hdr->len & 0xf0u) >> 2u) <= f->transport_len) { - tcp_parse_options(f); + if (tcp_parse_options(f) < 0) + return -1; f->payload = f->transport_hdr + ((hdr->len & 0xf0u) >> 2u); f->payload_len = payload_len; tcp_dbg("TCP> Received segment. (exp: %x got: %x)\n", t->rcv_nxt, SEQN(f)); @@ -2132,7 +2138,8 @@ static int tcp_ack(struct pico_socket *s, struct pico_frame *f) tcp_ack_dbg(s, f); #endif - tcp_parse_options(f); + if (tcp_parse_options(f) < 0) + return -1; t->recv_wnd = short_be(hdr->rwnd); acked = (uint16_t)tcp_ack_advance_una(t, f, &acked_timestamp); @@ -2448,7 +2455,8 @@ static int tcp_syn(struct pico_socket *s, struct pico_frame *f) f->sock = &new->sock; mtu = (uint16_t)pico_socket_get_mss(&new->sock); new->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR); - tcp_parse_options(f); + if (tcp_parse_options(f) < 0) + return -1; new->tcpq_in.max_size = PICO_DEFAULT_SOCKETQ; new->tcpq_out.max_size = PICO_DEFAULT_SOCKETQ; new->tcpq_hold.max_size = 2u * mtu; @@ -2866,6 +2874,11 @@ int pico_tcp_input(struct pico_socket *s, struct pico_frame *f) // tcp_dbg("[sam] TCP> s->state >> 8 = %u\n", s->state >> 8); tcp_dbg("[tcp input] socket: %p state: %d <-- local port:%u remote port: %u seq: 0x%08x ack: 0x%08x flags: 0x%02x t_len: %u, hdr: %u payload: %d\n", s, s->state >> 8, short_be(hdr->trans.dport), short_be(hdr->trans.sport), SEQN(f), ACKN(f), hdr->flags, f->transport_len, (hdr->len & 0xf0) >> 2, f->payload_len ); + if ((f->payload + f->payload_len) > (f->buffer + f->buffer_len)) { + tcp_dbg("TCP> Invalid payload len %04x\n", f->payload_len); + pico_frame_discard(f); + return -1; + } /* This copy of the frame has the current socket as owner */ f->sock = s; s->timestamp = TCP_TIME;