CVE-2023-35847: Use of Uninitialized Resource (CWE-908)
value: VirtualSquare picoTCP (aka PicoTCP-NG) through 2.1 does not have an MSS lower bound (e.g., it could be zero).
CWE description: The product uses or accesses a resource that has not been initialized.
CVSS v3 base score: 7.5
Published: 2023-06-19T03:15Z
Repository: https://github.com/virtualsquare/picotcp
Language: C
Files changed: modules/pico_tcp.c, modules/pico_tcp.h
Commit date: 2023-05-14 12:45:52 +0200
Commit message: TCP: Fixed MSS size calculation. Set MSS lower bound.

Reported-by: "P. Amsuo, Purdue University"

Diff: diff --git a/modules/pico_tcp.c b/modules/pico_tcp.c
index d2ca607b..53725be1 100644
--- a/modules/pico_tcp.c
+++ b/modules/pico_tcp.c
@@ -1083,11 +1083,15 @@ struct pico_socket *pico_tcp_open(struct pico_stack *S, uint16_t family)
         return NULL;
 
     t->sock.stack = S;
     t->sock.timestamp = TCP_TIME;
     pico_socket_set_family(&t->sock, family);
-    t->mss = (uint16_t)(pico_socket_get_mss(&t->sock) - PICO_SIZE_TCPHDR);
+    t->mss = (uint16_t)(pico_socket_get_mss(&t->sock));
+    if (t->mss > PICO_SIZE_TCPHDR + PICO_TCP_MIN_MSS)
+        t->mss -= (uint16_t)PICO_SIZE_TCPHDR;
+    else
+        t->mss = PICO_TCP_MIN_MSS;
     t->tcpq_in.pool.root = t->tcpq_hold.pool.root = t->tcpq_out.pool.root = &LEAF;
     t->tcpq_hold.pool.compare = t->tcpq_out.pool.compare = segment_compare;
     t->tcpq_in.pool.compare = input_segment_compare;
     t->tcpq_in.max_size = PICO_DEFAULT_SOCKETQ;
     t->tcpq_out.max_size = PICO_DEFAULT_SOCKETQ;
@@ -1252,11 +1256,14 @@ int pico_tcp_initconn(struct pico_socket *s)
         ts->snd_nxt = long_be(pico_paws());
 
     ts->snd_last = ts->snd_nxt;
     ts->cwnd = PICO_TCP_IW;
     mtu = (uint16_t)pico_socket_get_mss(s);
-    ts->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR);
+    if (mtu > PICO_SIZE_TCPHDR + PICO_TCP_MIN_MSS)
+        ts->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR);
+    else
+        ts->mss = PICO_TCP_MIN_MSS;
     ts->ssthresh = (uint16_t)((uint16_t)(PICO_DEFAULT_SOCKETQ / ts->mss) -  (((uint16_t)(PICO_DEFAULT_SOCKETQ / ts->mss)) >> 3u));
     syn->sock = s;
     hdr->seq = long_be(ts->snd_nxt);
     hdr->len = (uint8_t)((PICO_SIZE_TCPHDR + opt_len) << 2);
     hdr->flags = PICO_TCP_SYN;
@@ -2444,11 +2451,14 @@ static int tcp_syn(struct pico_socket *s, struct pico_frame *f)
     }
 
 #endif
     f->sock = &new->sock;
     mtu = (uint16_t)pico_socket_get_mss(&new->sock);
-    new->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR);
+    if (mtu > PICO_SIZE_TCPHDR + PICO_TCP_MIN_MSS)
+        new->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR);
+    else
+        new->mss = PICO_TCP_MIN_MSS;
     if (tcp_parse_options(f) < 0)
         return -1;
     new->sock.stack = s->stack;
     new->tcpq_in.max_size = PICO_DEFAULT_SOCKETQ;
     new->tcpq_out.max_size = PICO_DEFAULT_SOCKETQ;
diff --git a/modules/pico_tcp.h b/modules/pico_tcp.h
index 3bd1a11e..f598be84 100644
--- a/modules/pico_tcp.h
+++ b/modules/pico_tcp.h
@@ -53,10 +53,11 @@ PACKED_STRUCT_DEF tcp_pseudo_hdr_ipv4
 };
 
 #define PICO_TCPHDR_SIZE 20
 #define PICO_SIZE_TCPOPT_SYN 20
 #define PICO_SIZE_TCPHDR (uint32_t)(sizeof(struct pico_tcp_hdr))
+#define PICO_TCP_MIN_MSS (64 - PICO_SIZE_TCPHDR)
 
 /* TCP options */
 #define PICO_TCP_OPTION_END         0x00
 #define PICO_TCPOPTLEN_END        1u
 #define PICO_TCP_OPTION_NOOP        0x01

Vulnerable code:     t->mss = (uint16_t)(pico_socket_get_mss(&t->sock) - PICO_SIZE_TCPHDR);
    ts->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR);
    new->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR);
Fixed code:     t->mss = (uint16_t)(pico_socket_get_mss(&t->sock));
    if (t->mss > PICO_SIZE_TCPHDR + PICO_TCP_MIN_MSS)
        t->mss -= (uint16_t)PICO_SIZE_TCPHDR;
    else
        t->mss = PICO_TCP_MIN_MSS;
    if (mtu > PICO_SIZE_TCPHDR + PICO_TCP_MIN_MSS)
        ts->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR);
    else
        ts->mss = PICO_TCP_MIN_MSS;
    if (mtu > PICO_SIZE_TCPHDR + PICO_TCP_MIN_MSS)
        new->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR);
    else
        new->mss = PICO_TCP_MIN_MSS;
#define PICO_TCP_MIN_MSS (64 - PICO_SIZE_TCPHDR)