CVE-2023-35846: Insufficient Information (NVD-CWE-noinfo)
value: VirtualSquare picoTCP (aka PicoTCP-NG) through 2.1 does not check the transport layer length in a frame before performing port filtering.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 7.5
Published: 2023-06-19T03:15Z
Repository: https://github.com/virtualsquare/picotcp
Language: C
Files changed: modules/pico_ipfilter.c
Commit date: 2023-05-14 12:46:45 +0200
Commit message: [ipfilter] Check transport layer length in frame before filtering ports

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

Diff: diff --git a/modules/pico_ipfilter.c b/modules/pico_ipfilter.c
index 1bb4621c..a97114af 100644
--- a/modules/pico_ipfilter.c
+++ b/modules/pico_ipfilter.c
@@ -459,22 +459,22 @@ int ipfilter(struct pico_frame *f)
     memset(&temp, 0u, sizeof(struct filter_node));
 
     temp.fdev = f->dev;
     temp.out_addr = ipv4_hdr->dst.addr;
     temp.in_addr = ipv4_hdr->src.addr;
-    if ((ipv4_hdr->proto == PICO_PROTO_TCP) || (ipv4_hdr->proto == PICO_PROTO_UDP)) {
-        trans = (struct pico_trans *) f->transport_hdr;
-        temp.out_port = short_be(trans->dport);
-        temp.in_port = short_be(trans->sport);
-    }
-    else if(ipv4_hdr->proto == PICO_PROTO_ICMP4) {
-        icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
-        if(icmp_hdr->type == PICO_ICMP_UNREACH && icmp_hdr->code == PICO_ICMP_UNREACH_FILTER_PROHIB)
-            return 0;
+    if ((f->transport_hdr + sizeof(struct pico_trans)) <= (f->buffer + f->buffer_len)) {
+        if ((ipv4_hdr->proto == PICO_PROTO_TCP) || (ipv4_hdr->proto == PICO_PROTO_UDP)) {
+                trans = (struct pico_trans *) f->transport_hdr;
+                temp.out_port = short_be(trans->dport);
+                temp.in_port = short_be(trans->sport);
+        } else if(ipv4_hdr->proto == PICO_PROTO_ICMP4) {
+            icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
+            if(icmp_hdr->type == PICO_ICMP_UNREACH && icmp_hdr->code == PICO_ICMP_UNREACH_FILTER_PROHIB)
+                return 0;
+        }
+        temp.proto = ipv4_hdr->proto;
     }
-
-    temp.proto = ipv4_hdr->proto;
     temp.priority = f->priority;
     temp.tos = ipv4_hdr->tos;
     return ipfilter_apply_filter(f, &temp);
 }
 

Vulnerable code:     if ((ipv4_hdr->proto == PICO_PROTO_TCP) || (ipv4_hdr->proto == PICO_PROTO_UDP)) {
        trans = (struct pico_trans *) f->transport_hdr;
        temp.out_port = short_be(trans->dport);
        temp.in_port = short_be(trans->sport);
    }
    else if(ipv4_hdr->proto == PICO_PROTO_ICMP4) {
        icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
        if(icmp_hdr->type == PICO_ICMP_UNREACH && icmp_hdr->code == PICO_ICMP_UNREACH_FILTER_PROHIB)
            return 0;

    temp.proto = ipv4_hdr->proto;
Fixed code:     if ((f->transport_hdr + sizeof(struct pico_trans)) <= (f->buffer + f->buffer_len)) {
        if ((ipv4_hdr->proto == PICO_PROTO_TCP) || (ipv4_hdr->proto == PICO_PROTO_UDP)) {
                trans = (struct pico_trans *) f->transport_hdr;
                temp.out_port = short_be(trans->dport);
                temp.in_port = short_be(trans->sport);
        } else if(ipv4_hdr->proto == PICO_PROTO_ICMP4) {
            icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
            if(icmp_hdr->type == PICO_ICMP_UNREACH && icmp_hdr->code == PICO_ICMP_UNREACH_FILTER_PROHIB)
                return 0;
        }
        temp.proto = ipv4_hdr->proto;