From 55b14f37212ddf3f9cea16e72622fbe1b1e3e1b9 Mon Sep 17 00:00:00 2001 From: Maurizio Abba Date: Tue, 16 Jan 2018 16:53:51 +0000 Subject: [PATCH] decode: set pktlen of decode handler to uint32 Change the decode handler signature to increase the size of its decode handler, from uint16 to uint32. This is necessary to let suricata use interfaces with mtu > 65535 (ex: lo interface has default size 65536). It's necessary to change several primitive for Packet manipulation, to unify the parameter "packet length" whenever we are before IP decoding. Add tests before calling DecodeIPVX function to avoid a possible integer overflow over the len parameter. --- src/decode-erspan.c | 2 +- src/decode-ethernet.c | 6 ++++- src/decode-gre.c | 4 ++-- src/decode-icmpv4.c | 26 +++++++++++++++++----- src/decode-icmpv6.c | 14 +++++++++++- src/decode-mpls.c | 14 +++++++++++- src/decode-null.c | 6 ++++- src/decode-ppp.c | 14 ++++++++++-- src/decode-pppoe.c | 23 +++++++++++++------ src/decode-raw.c | 10 ++++++++- src/decode-sll.c | 8 ++++++- src/decode-template.c | 2 +- src/decode-vlan.c | 11 +++++++-- src/decode.c | 18 +++++++++------ src/decode.h | 42 +++++++++++++++++------------------ src/source-ipfw.c | 6 +++++ src/source-nflog.c | 6 +++++ src/source-nfq.c | 6 +++++ src/source-pcap-file-helper.h | 2 +- 19 files changed, 165 insertions(+), 55 deletions(-) diff --git a/src/decode-erspan.c b/src/decode-erspan.c index d4df646206..53f43fa240 100644 --- a/src/decode-erspan.c +++ b/src/decode-erspan.c @@ -43,7 +43,7 @@ * \brief Function to decode ERSPAN packets */ -int DecodeERSPAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +int DecodeERSPAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_erspan); diff --git a/src/decode-ethernet.c b/src/decode-ethernet.c index 6bdcff7414..3b55f31be8 100644 --- a/src/decode-ethernet.c +++ b/src/decode-ethernet.c @@ -39,7 +39,7 @@ #include "util-debug.h" int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, - uint8_t *pkt, uint16_t len, PacketQueue *pq) + uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_eth); @@ -48,6 +48,10 @@ int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, return TM_ECODE_FAILED; } + if (unlikely(len > ETHERNET_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } + p->ethh = (EthernetHdr *)pkt; if (unlikely(p->ethh == NULL)) return TM_ECODE_FAILED; diff --git a/src/decode-gre.c b/src/decode-gre.c index 7c7bc80490..2429cb660c 100644 --- a/src/decode-gre.c +++ b/src/decode-gre.c @@ -43,9 +43,9 @@ * \brief Function to decode GRE packets */ -int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { - uint16_t header_len = GRE_HDR_LEN; + uint32_t header_len = GRE_HDR_LEN; GRESreHdr *gsre = NULL; StatsIncr(tv, dtv->counter_gre); diff --git a/src/decode-icmpv4.c b/src/decode-icmpv4.c index 2e567b7557..00bc276308 100644 --- a/src/decode-icmpv4.c +++ b/src/decode-icmpv4.c @@ -152,7 +152,7 @@ static int DecodePartialIPV4(Packet* p, uint8_t* partial_packet, uint16_t len) /** DecodeICMPV4 * \brief Main ICMPv4 decoding function */ -int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_icmpv4); @@ -205,8 +205,12 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE); } else { // parse IP header plus 64 bytes - if (len >= ICMPV4_HEADER_PKT_OFFSET) + if (len >= ICMPV4_HEADER_PKT_OFFSET) { + if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET ); + } } break; @@ -215,8 +219,12 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE); } else { // parse IP header plus 64 bytes - if (len > ICMPV4_HEADER_PKT_OFFSET) + if (len > ICMPV4_HEADER_PKT_OFFSET) { + if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET ); + } } break; @@ -233,8 +241,12 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE); } else { // parse IP header plus 64 bytes - if (len > ICMPV4_HEADER_PKT_OFFSET) + if (len > ICMPV4_HEADER_PKT_OFFSET) { + if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET ); + } } break; @@ -243,8 +255,12 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE); } else { // parse IP header plus 64 bytes - if (len > ICMPV4_HEADER_PKT_OFFSET) + if (len > ICMPV4_HEADER_PKT_OFFSET) { + if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET ); + } } break; diff --git a/src/decode-icmpv6.c b/src/decode-icmpv6.c index d035e133b0..a6c713eb30 100644 --- a/src/decode-icmpv6.c +++ b/src/decode-icmpv6.c @@ -187,7 +187,7 @@ int ICMPv6GetCounterpart(uint8_t type) * \retval void No return value */ int DecodeICMPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, - uint8_t *pkt, uint16_t len, PacketQueue *pq) + uint8_t *pkt, uint32_t len, PacketQueue *pq) { int full_hdr = 0; StatsIncr(tv, dtv->counter_icmpv6); @@ -220,6 +220,9 @@ int DecodeICMPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, if (ICMPV6_GET_CODE(p) > ICMP6_DST_UNREACH_REJECTROUTE) { ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE); } else { + if (unlikely(len > ICMPV6_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodePartialIPV6(p, (uint8_t*) (pkt + ICMPV6_HEADER_LEN), len - ICMPV6_HEADER_LEN ); full_hdr = 1; @@ -232,6 +235,9 @@ int DecodeICMPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, if (ICMPV6_GET_CODE(p) != 0) { ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE); } else { + if (unlikely(len > ICMPV6_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } p->icmpv6vars.mtu = ICMPV6_GET_MTU(p); DecodePartialIPV6(p, (uint8_t*) (pkt + ICMPV6_HEADER_LEN), len - ICMPV6_HEADER_LEN ); @@ -245,6 +251,9 @@ int DecodeICMPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, if (ICMPV6_GET_CODE(p) > ICMP6_TIME_EXCEED_REASSEMBLY) { ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE); } else { + if (unlikely(len > ICMPV6_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodePartialIPV6(p, (uint8_t*) (pkt + ICMPV6_HEADER_LEN), len - ICMPV6_HEADER_LEN ); full_hdr = 1; @@ -257,6 +266,9 @@ int DecodeICMPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, if (ICMPV6_GET_CODE(p) > ICMP6_PARAMPROB_OPTION) { ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE); } else { + if (unlikely(len > ICMPV6_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } p->icmpv6vars.error_ptr= ICMPV6_GET_ERROR_PTR(p); DecodePartialIPV6(p, (uint8_t*) (pkt + ICMPV6_HEADER_LEN), len - ICMPV6_HEADER_LEN ); diff --git a/src/decode-mpls.c b/src/decode-mpls.c index 9694a341f4..53d7ec1882 100644 --- a/src/decode-mpls.c +++ b/src/decode-mpls.c @@ -45,7 +45,7 @@ #define MPLS_PROTO_IPV6 6 int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, - uint16_t len, PacketQueue *pq) + uint32_t len, PacketQueue *pq) { uint32_t shim; int label; @@ -65,6 +65,9 @@ int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, label = MPLS_LABEL(shim); if (label == MPLS_LABEL_IPV4) { + if (len > USHRT_MAX) { + return TM_ECODE_FAILED; + } return DecodeIPV4(tv, dtv, p, pkt, len, pq); } else if (label == MPLS_LABEL_ROUTER_ALERT) { @@ -72,6 +75,9 @@ int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, event = MPLS_BAD_LABEL_ROUTER_ALERT; } else if (label == MPLS_LABEL_IPV6) { + if (len > USHRT_MAX) { + return TM_ECODE_FAILED; + } return DecodeIPV6(tv, dtv, p, pkt, len, pq); } else if (label == MPLS_LABEL_NULL) { @@ -89,9 +95,15 @@ int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, /* Best guess at inner packet. */ switch (pkt[0] >> 4) { case MPLS_PROTO_IPV4: + if (len > USHRT_MAX) { + return TM_ECODE_FAILED; + } DecodeIPV4(tv, dtv, p, pkt, len, pq); break; case MPLS_PROTO_IPV6: + if (len > USHRT_MAX) { + return TM_ECODE_FAILED; + } DecodeIPV6(tv, dtv, p, pkt, len, pq); break; case MPLS_PROTO_ETHERNET_PW: diff --git a/src/decode-null.c b/src/decode-null.c index b3bcb0667c..1a98d00274 100644 --- a/src/decode-null.c +++ b/src/decode-null.c @@ -45,7 +45,7 @@ #define HDR_SIZE 4 -int DecodeNull(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +int DecodeNull(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_null); @@ -54,6 +54,10 @@ int DecodeNull(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, u return TM_ECODE_FAILED; } + if (unlikely(GET_PKT_LEN(p) > HDR_SIZE + USHRT_MAX)) { + return TM_ECODE_FAILED; + } + uint32_t type = *((uint32_t *)pkt); switch(type) { case AF_INET: diff --git a/src/decode-ppp.c b/src/decode-ppp.c index d5aae6bb78..f9eae736df 100644 --- a/src/decode-ppp.c +++ b/src/decode-ppp.c @@ -40,7 +40,7 @@ #include "util-unittest.h" #include "util-debug.h" -int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_ppp); @@ -53,7 +53,7 @@ int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ui if (unlikely(p->ppph == NULL)) return TM_ECODE_FAILED; - SCLogDebug("p %p pkt %p PPP protocol %04x Len: %" PRId32 "", + SCLogDebug("p %p pkt %p PPP protocol %04x Len: %" PRIu32 "", p, pkt, SCNtohs(p->ppph->protocol), len); switch (SCNtohs(p->ppph->protocol)) @@ -65,6 +65,10 @@ int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ui return TM_ECODE_FAILED; } + if (unlikely(len > PPP_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } + if (likely(IPV4_GET_RAW_VER((IPV4Hdr *)(pkt + PPP_HEADER_LEN)) == 4)) { return DecodeIPV4(tv, dtv, p, pkt + PPP_HEADER_LEN, len - PPP_HEADER_LEN, pq); } else @@ -77,6 +81,9 @@ int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ui p->ppph = NULL; return TM_ECODE_FAILED; } + if (unlikely(len > PPP_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } return DecodeIPV4(tv, dtv, p, pkt + PPP_HEADER_LEN, len - PPP_HEADER_LEN, pq); @@ -87,6 +94,9 @@ int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ui p->ppph = NULL; return TM_ECODE_FAILED; } + if (unlikely(len > PPP_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } return DecodeIPV6(tv, dtv, p, pkt + PPP_HEADER_LEN, len - PPP_HEADER_LEN, pq); diff --git a/src/decode-pppoe.c b/src/decode-pppoe.c index 7d5aeb1949..0551a5141d 100644 --- a/src/decode-pppoe.c +++ b/src/decode-pppoe.c @@ -47,7 +47,7 @@ /** * \brief Main decoding function for PPPOE Discovery packets */ -int DecodePPPOEDiscovery(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +int DecodePPPOEDiscovery(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_pppoe); @@ -81,13 +81,13 @@ int DecodePPPOEDiscovery(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8 /* parse any tags we have in the packet */ - uint16_t tag_length = 0; + uint32_t tag_length = 0; PPPOEDiscoveryTag* pppoedt = (PPPOEDiscoveryTag*) (p->pppoedh + PPPOE_DISCOVERY_HEADER_MIN_LEN); - uint16_t pppoe_length = SCNtohs(p->pppoedh->pppoe_length); - uint16_t packet_length = len - PPPOE_DISCOVERY_HEADER_MIN_LEN ; + uint32_t pppoe_length = SCNtohs(p->pppoedh->pppoe_length); + uint32_t packet_length = len - PPPOE_DISCOVERY_HEADER_MIN_LEN ; - SCLogDebug("pppoe_length %"PRIu16", packet_length %"PRIu16"", + SCLogDebug("pppoe_length %"PRIu32", packet_length %"PRIu32"", pppoe_length, packet_length); if (pppoe_length > packet_length) { @@ -103,7 +103,7 @@ int DecodePPPOEDiscovery(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8 #endif tag_length = SCNtohs(pppoedt->pppoe_tag_length); - SCLogDebug ("PPPoE Tag type %x, length %u", tag_type, tag_length); + SCLogDebug ("PPPoE Tag type %x, length %"PRIu32, tag_type, tag_length); if (pppoe_length >= (4 + tag_length)) { pppoe_length -= (4 + tag_length); @@ -126,7 +126,7 @@ int DecodePPPOEDiscovery(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8 /** * \brief Main decoding function for PPPOE Session packets */ -int DecodePPPOESession(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +int DecodePPPOESession(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_pppoe); @@ -186,6 +186,9 @@ int DecodePPPOESession(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t ENGINE_SET_INVALID_EVENT(p, PPPVJU_PKT_TOO_SMALL); return TM_ECODE_OK; } + if (unlikely(len > PPPOE_SESSION_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } if(IPV4_GET_RAW_VER((IPV4Hdr *)(pkt + PPPOE_SESSION_HEADER_LEN)) == 4) { DecodeIPV4(tv, dtv, p, pkt + PPPOE_SESSION_HEADER_LEN, len - PPPOE_SESSION_HEADER_LEN, pq ); @@ -197,6 +200,9 @@ int DecodePPPOESession(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t ENGINE_SET_INVALID_EVENT(p, PPPIPV4_PKT_TOO_SMALL); return TM_ECODE_OK; } + if (unlikely(len > PPPOE_SESSION_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodeIPV4(tv, dtv, p, pkt + PPPOE_SESSION_HEADER_LEN, len - PPPOE_SESSION_HEADER_LEN, pq ); break; @@ -207,6 +213,9 @@ int DecodePPPOESession(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t ENGINE_SET_INVALID_EVENT(p, PPPIPV6_PKT_TOO_SMALL); return TM_ECODE_OK; } + if (unlikely(len > PPPOE_SESSION_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodeIPV6(tv, dtv, p, pkt + PPPOE_SESSION_HEADER_LEN, len - PPPOE_SESSION_HEADER_LEN, pq ); break; diff --git a/src/decode-raw.c b/src/decode-raw.c index d174ab3766..f5ad077044 100644 --- a/src/decode-raw.c +++ b/src/decode-raw.c @@ -43,7 +43,7 @@ #include "host.h" -int DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +int DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_raw); @@ -53,10 +53,18 @@ int DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ui return TM_ECODE_FAILED; } + + if (IP_GET_RAW_VER(pkt) == 4) { + if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) { + return TM_ECODE_FAILED; + } SCLogDebug("IPV4 Packet"); DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else if (IP_GET_RAW_VER(pkt) == 6) { + if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) { + return TM_ECODE_FAILED; + } SCLogDebug("IPV6 Packet"); DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else { diff --git a/src/decode-sll.c b/src/decode-sll.c index d9730de2d2..c9360bfdb2 100644 --- a/src/decode-sll.c +++ b/src/decode-sll.c @@ -36,7 +36,7 @@ #include "decode-events.h" #include "util-debug.h" -int DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +int DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { StatsIncr(tv, dtv->counter_sll); @@ -53,10 +53,16 @@ int DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, ui switch (SCNtohs(sllh->sll_protocol)) { case ETHERNET_TYPE_IP: + if (unlikely(len > SLL_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodeIPV4(tv, dtv, p, pkt + SLL_HEADER_LEN, len - SLL_HEADER_LEN, pq); break; case ETHERNET_TYPE_IPV6: + if (unlikely(len > SLL_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodeIPV6(tv, dtv, p, pkt + SLL_HEADER_LEN, len - SLL_HEADER_LEN, pq); break; diff --git a/src/decode-template.c b/src/decode-template.c index 2673a2cdff..be7acfe1b1 100644 --- a/src/decode-template.c +++ b/src/decode-template.c @@ -50,7 +50,7 @@ */ int DecodeTEMPLATE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, - const uint8_t *pkt, uint16_t len, PacketQueue *pq) + const uint8_t *pkt, uint32_t len, PacketQueue *pq) { /* TODO add counter for your type of packet to DecodeThreadVars, * and register it in DecodeRegisterPerfCounters */ diff --git a/src/decode-vlan.c b/src/decode-vlan.c index e9478da255..78e257eb3a 100644 --- a/src/decode-vlan.c +++ b/src/decode-vlan.c @@ -59,7 +59,7 @@ static int DecodeIEEE8021ah(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, * \param pq pointer to the packet queue * */ -int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq) { uint32_t proto; @@ -83,7 +83,7 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, u proto = GET_VLAN_PROTO(p->vlanh[p->vlan_idx]); - SCLogDebug("p %p pkt %p VLAN protocol %04x VLAN PRI %d VLAN CFI %d VLAN ID %d Len: %" PRId32 "", + SCLogDebug("p %p pkt %p VLAN protocol %04x VLAN PRI %d VLAN CFI %d VLAN ID %d Len: %" PRIu32 "", p, pkt, proto, GET_VLAN_PRIORITY(p->vlanh[p->vlan_idx]), GET_VLAN_CFI(p->vlanh[p->vlan_idx]), GET_VLAN_ID(p->vlanh[p->vlan_idx]), len); @@ -95,10 +95,17 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, u switch (proto) { case ETHERNET_TYPE_IP: + if (unlikely(len > VLAN_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } + DecodeIPV4(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; case ETHERNET_TYPE_IPV6: + if (unlikely(len > VLAN_HEADER_LEN + USHRT_MAX)) { + return TM_ECODE_FAILED; + } DecodeIPV6(tv, dtv, p, pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN, pq); break; diff --git a/src/decode.c b/src/decode.c index e9e2f38be6..3f89e60290 100644 --- a/src/decode.c +++ b/src/decode.c @@ -68,7 +68,7 @@ #include "output-flow.h" int DecodeTunnel(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, - uint8_t *pkt, uint16_t len, PacketQueue *pq, enum DecodeTunnelProto proto) + uint8_t *pkt, uint32_t len, PacketQueue *pq, enum DecodeTunnelProto proto) { switch (proto) { case DECODE_TUNNEL_PPP: @@ -203,7 +203,7 @@ inline int PacketCallocExtPkt(Packet *p, int datalen) * \param Pointer to the data to copy * \param Length of the data to copy */ -inline int PacketCopyDataOffset(Packet *p, int offset, uint8_t *data, int datalen) +inline int PacketCopyDataOffset(Packet *p, uint32_t offset, uint8_t *data, uint32_t datalen) { if (unlikely(offset + datalen > MAX_PAYLOAD_SIZE)) { /* too big */ @@ -212,7 +212,11 @@ inline int PacketCopyDataOffset(Packet *p, int offset, uint8_t *data, int datale /* Do we have already an packet with allocated data */ if (! p->ext_pkt) { - if (offset + datalen <= (int)default_packet_size) { + uint32_t newsize = offset + datalen; + // check overflow + if (newsize < offset) + return -1; + if (newsize <= default_packet_size) { /* data will fit in memory allocated with packet */ memcpy(GET_PKT_DIRECT_DATA(p) + offset, data, datalen); } else { @@ -240,7 +244,7 @@ inline int PacketCopyDataOffset(Packet *p, int offset, uint8_t *data, int datale * \param Pointer to the data to copy * \param Length of the data to copy */ -inline int PacketCopyData(Packet *p, uint8_t *pktdata, int pktlen) +inline int PacketCopyData(Packet *p, uint8_t *pktdata, uint32_t pktlen) { SET_PKT_LEN(p, (size_t)pktlen); return PacketCopyDataOffset(p, 0, pktdata, pktlen); @@ -257,7 +261,7 @@ inline int PacketCopyData(Packet *p, uint8_t *pktdata, int pktlen) * \retval p the pseudo packet or NULL if out of memory */ Packet *PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *parent, - uint8_t *pkt, uint16_t len, enum DecodeTunnelProto proto, + uint8_t *pkt, uint32_t len, enum DecodeTunnelProto proto, PacketQueue *pq) { int ret; @@ -326,7 +330,7 @@ Packet *PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *pare * * \retval p the pseudo packet or NULL if out of memory */ -Packet *PacketDefragPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto) +Packet *PacketDefragPktSetup(Packet *parent, uint8_t *pkt, uint32_t len, uint8_t proto) { SCEnter(); @@ -537,7 +541,7 @@ void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv) * \param Pointer to the data * \param Length of the data */ -inline int PacketSetData(Packet *p, uint8_t *pktdata, int pktlen) +inline int PacketSetData(Packet *p, uint8_t *pktdata, uint32_t pktlen) { SET_PKT_LEN(p, (size_t)pktlen); if (unlikely(!pktdata)) { diff --git a/src/decode.h b/src/decode.h index 64b0103e94..8f05fd23fa 100644 --- a/src/decode.h +++ b/src/decode.h @@ -908,8 +908,8 @@ enum DecodeTunnelProto { }; Packet *PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *parent, - uint8_t *pkt, uint16_t len, enum DecodeTunnelProto proto, PacketQueue *pq); -Packet *PacketDefragPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto); + uint8_t *pkt, uint32_t len, enum DecodeTunnelProto proto, PacketQueue *pq); +Packet *PacketDefragPktSetup(Packet *parent, uint8_t *pkt, uint32_t len, uint8_t proto); void PacketDefragPktSetupParent(Packet *parent); void DecodeRegisterPerfCounters(DecodeThreadVars *, ThreadVars *); Packet *PacketGetFromQueueOrAlloc(void); @@ -918,9 +918,9 @@ void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p); void PacketFree(Packet *p); void PacketFreeOrRelease(Packet *p); int PacketCallocExtPkt(Packet *p, int datalen); -int PacketCopyData(Packet *p, uint8_t *pktdata, int pktlen); -int PacketSetData(Packet *p, uint8_t *pktdata, int pktlen); -int PacketCopyDataOffset(Packet *p, int offset, uint8_t *data, int datalen); +int PacketCopyData(Packet *p, uint8_t *pktdata, uint32_t pktlen); +int PacketSetData(Packet *p, uint8_t *pktdata, uint32_t pktlen); +int PacketCopyDataOffset(Packet *p, uint32_t offset, uint8_t *data, uint32_t datalen); const char *PktSrcToString(enum PktSrcEnum pkt_src); void PacketBypassCallback(Packet *p); @@ -930,26 +930,26 @@ void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p); /* decoder functions */ -int DecodeEthernet(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodeSll(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodePPP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodePPPOESession(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodePPPOEDiscovery(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodeTunnel(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *, enum DecodeTunnelProto) __attribute__ ((warn_unused_result)); -int DecodeNull(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodeRaw(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); +int DecodeEthernet(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodeSll(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodePPP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodePPPOESession(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodePPPOEDiscovery(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodeTunnel(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *, enum DecodeTunnelProto) __attribute__ ((warn_unused_result)); +int DecodeNull(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodeRaw(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); int DecodeIPV4(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); int DecodeIPV6(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodeICMPV4(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodeICMPV6(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); +int DecodeICMPV4(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodeICMPV6(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); int DecodeTCP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); int DecodeUDP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); int DecodeSCTP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodeGRE(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodeVLAN(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodeMPLS(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodeERSPAN(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -int DecodeTEMPLATE(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint16_t, PacketQueue *); +int DecodeGRE(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodeVLAN(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodeMPLS(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodeERSPAN(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); +int DecodeTEMPLATE(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t, PacketQueue *); #ifdef UNITTESTS void DecodeIPV6FragHeader(Packet *p, uint8_t *pkt, @@ -961,7 +961,7 @@ void AddressDebugPrint(Address *); #ifdef AFLFUZZ_DECODER typedef int (*DecoderFunc)(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, - uint8_t *pkt, uint16_t len, PacketQueue *pq); + uint8_t *pkt, uint32_t len, PacketQueue *pq); int DecoderParseDataFromFile(char *filename, DecoderFunc Decoder); int DecoderParseDataFromFileSerie(char *fileprefix, DecoderFunc Decoder); diff --git a/src/source-ipfw.c b/src/source-ipfw.c index fb89a03cc8..0081898228 100644 --- a/src/source-ipfw.c +++ b/src/source-ipfw.c @@ -457,10 +457,16 @@ TmEcode DecodeIPFW(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, Packe /* Process IP packets */ if (IPV4_GET_RAW_VER(ip4h) == 4) { + if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) { + return TM_ECODE_FAILED; + } SCLogDebug("DecodeIPFW ip4 processing"); DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else if(IPV6_GET_RAW_VER(ip6h) == 6) { + if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) { + return TM_ECODE_FAILED; + } SCLogDebug("DecodeIPFW ip6 processing"); DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); diff --git a/src/source-nflog.c b/src/source-nflog.c index b2a9199631..90cbe4ddfb 100644 --- a/src/source-nflog.c +++ b/src/source-nflog.c @@ -503,9 +503,15 @@ TmEcode DecodeNFLOG(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, Pack DecodeUpdatePacketCounters(tv, dtv, p); if (IPV4_GET_RAW_VER(ip4h) == 4) { + if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) { + return TM_ECODE_FAILED; + } SCLogDebug("IPv4 packet"); DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else if(IPV6_GET_RAW_VER(ip6h) == 6) { + if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) { + return TM_ECODE_FAILED; + } SCLogDebug("IPv6 packet"); DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else { diff --git a/src/source-nfq.c b/src/source-nfq.c index f693bccf23..3680c06e45 100644 --- a/src/source-nfq.c +++ b/src/source-nfq.c @@ -1183,9 +1183,15 @@ TmEcode DecodeNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, Packet DecodeUpdatePacketCounters(tv, dtv, p); if (IPV4_GET_RAW_VER(ip4h) == 4) { + if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) { + return TM_ECODE_FAILED; + } SCLogDebug("IPv4 packet"); DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else if(IPV6_GET_RAW_VER(ip6h) == 6) { + if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) { + return TM_ECODE_FAILED; + } SCLogDebug("IPv6 packet"); DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else { diff --git a/src/source-pcap-file-helper.h b/src/source-pcap-file-helper.h index e12005b8ad..8852b77a59 100644 --- a/src/source-pcap-file-helper.h +++ b/src/source-pcap-file-helper.h @@ -76,7 +76,7 @@ typedef struct PcapFileFileVars_ PcapFileSharedVars *shared; } PcapFileFileVars; -typedef int (*Decoder)(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); +typedef int (*Decoder)(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *); /** * Dispatch a file for processing, where the information necessary to process that -- 2.47.2