From b8ce7f2885cea0ea31c45e9c3dbad4785ae69397 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Fri, 15 Mar 2019 17:13:00 -0600 Subject: [PATCH] mpls: check buffer length before peeking at next header Check that we have enough bytes before peaking into the MPLS packet payload. Redmine issue: https://redmine.openinfosecfoundation.org/issues/2884 --- src/decode-events.c | 1 + src/decode-events.h | 1 + src/decode-mpls.c | 57 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/decode-events.c b/src/decode-events.c index 4da27aee30..7bb48deef8 100644 --- a/src/decode-events.c +++ b/src/decode-events.c @@ -170,6 +170,7 @@ const struct DecodeEvents_ DEvents[] = { /* MPLS events */ { "decoder.mpls.header_too_small", MPLS_HEADER_TOO_SMALL, }, + { "decoder.mpls.pkt_too_small", MPLS_PKT_TOO_SMALL, }, { "decoder.mpls.bad_label_router_alert", MPLS_BAD_LABEL_ROUTER_ALERT, }, { "decoder.mpls.bad_label_implicit_null", MPLS_BAD_LABEL_IMPLICIT_NULL, }, { "decoder.mpls.bad_label_reserved", MPLS_BAD_LABEL_RESERVED, }, diff --git a/src/decode-events.h b/src/decode-events.h index 3afe4b51f4..b9cceb6793 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -177,6 +177,7 @@ enum { /* MPLS decode events. */ MPLS_HEADER_TOO_SMALL, + MPLS_PKT_TOO_SMALL, MPLS_BAD_LABEL_ROUTER_ALERT, MPLS_BAD_LABEL_IMPLICIT_NULL, MPLS_BAD_LABEL_RESERVED, diff --git a/src/decode-mpls.c b/src/decode-mpls.c index e5bcea39f6..2867601752 100644 --- a/src/decode-mpls.c +++ b/src/decode-mpls.c @@ -92,6 +92,13 @@ int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, goto end; } + // Make sure we still have enough data. While we only need 1 byte to test + // for IPv4 and IPv4, we need for to check for ethernet. + if (len < MPLS_PW_LEN) { + ENGINE_SET_INVALID_EVENT(p, MPLS_PKT_TOO_SMALL); + return TM_ECODE_FAILED; + } + /* Best guess at inner packet. */ switch (pkt[0] >> 4) { case MPLS_PROTO_IPV4: @@ -154,6 +161,54 @@ static int DecodeMPLSTestHeaderTooSmall(void) return ret; } +static int DecodeMPLSTestPacketTooSmall(void) +{ + ThreadVars tv; + DecodeThreadVars dtv; + + memset(&dtv, 0, sizeof(DecodeThreadVars)); + memset(&tv, 0, sizeof(ThreadVars)); + + Packet *p0 = SCCalloc(1, SIZE_OF_PACKET); + memset(p0, 0, SIZE_OF_PACKET); + uint8_t pkt0[] = { 0x00, 0x01, 0x51, 0xff }; + DecodeMPLS(&tv, &dtv, p0, pkt0, sizeof(pkt0), NULL); + FAIL_IF_NOT(ENGINE_ISSET_EVENT(p0, MPLS_PKT_TOO_SMALL)); + SCFree(p0); + + Packet *p1 = SCCalloc(1, SIZE_OF_PACKET); + FAIL_IF_NULL(p1); + uint8_t pkt1[] = { 0x00, 0x01, 0x51, 0xff, 0x45 }; + DecodeMPLS(&tv, &dtv, p1, pkt1, sizeof(pkt1), NULL); + FAIL_IF_NOT(ENGINE_ISSET_EVENT(p1, MPLS_PKT_TOO_SMALL)); + SCFree(p1); + + Packet *p2 = SCCalloc(1, SIZE_OF_PACKET); + FAIL_IF_NULL(p2); + uint8_t pkt2[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01 }; + DecodeMPLS(&tv, &dtv, p2, pkt2, sizeof(pkt2), NULL); + FAIL_IF_NOT(ENGINE_ISSET_EVENT(p2, MPLS_PKT_TOO_SMALL)); + SCFree(p2); + + Packet *p3 = SCCalloc(1, SIZE_OF_PACKET); + FAIL_IF_NULL(p3); + uint8_t pkt3[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01, 0x02 }; + DecodeMPLS(&tv, &dtv, p3, pkt3, sizeof(pkt3), NULL); + FAIL_IF_NOT(ENGINE_ISSET_EVENT(p3, MPLS_PKT_TOO_SMALL)); + SCFree(p3); + + // This should not create a too small event is it has one more byte + // than required. + Packet *p4 = SCCalloc(1, SIZE_OF_PACKET); + FAIL_IF_NULL(p4); + uint8_t pkt4[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01, 0x02, 0x03 }; + DecodeMPLS(&tv, &dtv, p4, pkt4, sizeof(pkt4), NULL); + FAIL_IF(ENGINE_ISSET_EVENT(p4, MPLS_PKT_TOO_SMALL)); + SCFree(p4); + + PASS; +} + static int DecodeMPLSTestBadLabelRouterAlert(void) { int ret = 1; @@ -325,6 +380,8 @@ void DecodeMPLSRegisterTests(void) #ifdef UNITTESTS UtRegisterTest("DecodeMPLSTestHeaderTooSmall", DecodeMPLSTestHeaderTooSmall); + UtRegisterTest("DecodeMPLSTestPacketTooSmall", + DecodeMPLSTestPacketTooSmall); UtRegisterTest("DecodeMPLSTestBadLabelRouterAlert", DecodeMPLSTestBadLabelRouterAlert); UtRegisterTest("DecodeMPLSTestBadLabelImplicitNull", -- 2.47.2