]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
icmpv4: harden embedded packet handling
authorVictor Julien <victor@inliniac.net>
Wed, 16 Dec 2015 09:50:50 +0000 (10:50 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 17 Dec 2015 14:19:58 +0000 (15:19 +0100)
src/decode-icmpv4.c

index 5af012ce9ac8026f54ed534f31e02670f75f6c06..45b213f6704ecde3219ceb0435295ce05419407e 100644 (file)
 /**
  * Note, this is the IP header, plus a bit of the original packet, not the whole thing!
  */
-void DecodePartialIPV4( Packet* p, uint8_t* partial_packet, uint16_t len )
+int DecodePartialIPV4( Packet* p, uint8_t* partial_packet, uint16_t len )
 {
     /** Check the sizes, the header must fit at least */
     if (len < IPV4_HEADER_LEN) {
         SCLogDebug("DecodePartialIPV4: ICMPV4_IPV4_TRUNC_PKT");
         ENGINE_SET_INVALID_EVENT(p, ICMPV4_IPV4_TRUNC_PKT);
-        return;
+        return -1;
     }
 
     IPV4Hdr *icmp4_ip4h = (IPV4Hdr*)partial_packet;
@@ -64,7 +64,7 @@ void DecodePartialIPV4( Packet* p, uint8_t* partial_packet, uint16_t len )
         SCLogDebug("DecodePartialIPV4: ICMPv4 contains Unknown IPV4 version "
                    "ICMPV4_IPV4_UNKNOWN_VER");
         ENGINE_SET_INVALID_EVENT(p, ICMPV4_IPV4_UNKNOWN_VER);
-        return;
+        return -1;
     }
 
     /** We need to fill icmpv4vars */
@@ -125,12 +125,14 @@ void DecodePartialIPV4( Packet* p, uint8_t* partial_packet, uint16_t len )
 
             break;
         case IPPROTO_ICMP:
-            p->icmpv4vars.emb_icmpv4h = (ICMPV4Hdr*)(partial_packet + IPV4_HEADER_LEN);
-            p->icmpv4vars.emb_sport = 0;
-            p->icmpv4vars.emb_dport = 0;
-            p->icmpv4vars.emb_ip4_proto = IPPROTO_ICMP;
+            if (len >= IPV4_HEADER_LEN + ICMPV4_HEADER_LEN ) {
+                p->icmpv4vars.emb_icmpv4h = (ICMPV4Hdr*)(partial_packet + IPV4_HEADER_LEN);
+                p->icmpv4vars.emb_sport = 0;
+                p->icmpv4vars.emb_dport = 0;
+                p->icmpv4vars.emb_ip4_proto = IPPROTO_ICMP;
 
-            SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->ICMP header");
+                SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->ICMP header");
+            }
 
             break;
     }
@@ -144,8 +146,7 @@ void DecodePartialIPV4( Packet* p, uint8_t* partial_packet, uint16_t len )
             IPV4_GET_RAW_IPPROTO(icmp4_ip4h), IPV4_GET_RAW_IPID(icmp4_ip4h));
 #endif
 
-    return;
-
+    return 0;
 }
 
 /** DecodeICMPV4
@@ -188,11 +189,13 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt,
             } else {
                 /* parse IP header plus 64 bytes */
                 if (len > ICMPV4_HEADER_PKT_OFFSET) {
-                    DecodePartialIPV4( p, (uint8_t *)(pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
-
-                    /* ICMP ICMP_DEST_UNREACH influence TCP/UDP flows */
-                    if (ICMPV4_DEST_UNREACH_IS_VALID(p)) {
-                        FlowHandlePacket(tv, dtv, p);
+                    if (DecodePartialIPV4(p, (uint8_t *)(pkt + ICMPV4_HEADER_PKT_OFFSET),
+                                             len - ICMPV4_HEADER_PKT_OFFSET ) == 0)
+                    {
+                        /* ICMP ICMP_DEST_UNREACH influence TCP/UDP flows */
+                        if (ICMPV4_DEST_UNREACH_IS_VALID(p)) {
+                            FlowHandlePacket(tv, dtv, p);
+                        }
                     }
                 }
             }