From 53f3be2013735c10ae3d0542c78f2ed9d473e403 Mon Sep 17 00:00:00 2001 From: cathugger Date: Wed, 12 Jun 2019 02:42:05 +0300 Subject: [PATCH 1/2] net/ip: skip IPv6 option headers --- llarp/net/ip.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/llarp/net/ip.cpp b/llarp/net/ip.cpp index 33c4b022d..48e8866e7 100644 --- a/llarp/net/ip.cpp +++ b/llarp/net/ip.cpp @@ -337,7 +337,7 @@ namespace llarp void IPPacket::UpdateIPv6Address(huint128_t src, huint128_t dst) { - const size_t ihs = 40; + const size_t ihs = 4 + 4 + 16 + 16; // XXX should've been checked at upper level? if(sz <= ihs) @@ -357,11 +357,55 @@ namespace llarp const uint32_t *nDstIP = hdr->dstaddr.s6_addr32; // TODO IPv6 header options - auto pld = buf + ihs; - auto psz = sz - ihs; - const size_t fragoff = 0; + auto pld = buf + ihs; + auto psz = sz - ihs; - switch(hdr->proto) + size_t fragoff = 0; + auto nextproto = hdr->proto; + for(;;) + { + switch(nextproto) + { + case 0: // Hop-by-Hop Options + case 43: // Routing Header + case 60: // Destination Options + { + nextproto = pld[0]; + auto addlen = (size_t(pld[1]) + 1) * 8; + if(psz < addlen) + return; + pld += addlen; + psz -= addlen; + break; + } + + case 44: // Fragment Header + /* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Reserved | Fragment Offset |Res|M| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identification | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + nextproto = pld[0]; + fragoff = (uint16_t(pld[2]) << (8 - 3)) | (uint16_t(pld[3]) >> 3); + if(psz < 8) + return; + pld += 8; + psz -= 8; + + // jump straight to payload processing + if(fragoff != 0) + goto endprotohdrs; + break; + + default: + goto endprotohdrs; + } + } + endprotohdrs:; + + switch(nextproto) { case 6: // TCP deltaChecksumIPv6TCP(pld, psz, fragoff, 16, oSrcIP, oDstIP, nSrcIP, From ddaf0834e2d1a938654ab5a17d1889d968593af6 Mon Sep 17 00:00:00 2001 From: cathugger Date: Wed, 12 Jun 2019 03:04:05 +0300 Subject: [PATCH 2/2] net/ip: correct IPv6 fragment processing, also check for length before modifying --- llarp/net/ip.cpp | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/llarp/net/ip.cpp b/llarp/net/ip.cpp index 48e8866e7..38123fc29 100644 --- a/llarp/net/ip.cpp +++ b/llarp/net/ip.cpp @@ -196,11 +196,11 @@ namespace llarp #undef SUB32CS static void - deltaChecksumIPv4TCP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz, - size_t fragoff, size_t chksumoff, nuint32_t oSrcIP, - nuint32_t oDstIP, nuint32_t nSrcIP, nuint32_t nDstIP) + deltaChecksumIPv4TCP(byte_t *pld, size_t psz, size_t fragoff, + size_t chksumoff, nuint32_t oSrcIP, nuint32_t oDstIP, + nuint32_t nSrcIP, nuint32_t nDstIP) { - if(fragoff > chksumoff) + if(fragoff > chksumoff || psz < chksumoff - fragoff + 2) return; auto check = (nuint16_t *)(pld + chksumoff - fragoff); @@ -215,12 +215,12 @@ namespace llarp } static void - deltaChecksumIPv6TCP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz, - size_t fragoff, size_t chksumoff, - const uint32_t oSrcIP[4], const uint32_t oDstIP[4], - const uint32_t nSrcIP[4], const uint32_t nDstIP[4]) + deltaChecksumIPv6TCP(byte_t *pld, size_t psz, size_t fragoff, + size_t chksumoff, const uint32_t oSrcIP[4], + const uint32_t oDstIP[4], const uint32_t nSrcIP[4], + const uint32_t nDstIP[4]) { - if(fragoff > chksumoff) + if(fragoff > chksumoff || psz < chksumoff - fragoff + 2) return; auto check = (nuint16_t *)(pld + chksumoff - fragoff); @@ -235,11 +235,11 @@ namespace llarp } static void - deltaChecksumIPv4UDP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz, - size_t fragoff, nuint32_t oSrcIP, nuint32_t oDstIP, - nuint32_t nSrcIP, nuint32_t nDstIP) + deltaChecksumIPv4UDP(byte_t *pld, size_t psz, size_t fragoff, + nuint32_t oSrcIP, nuint32_t oDstIP, nuint32_t nSrcIP, + nuint32_t nDstIP) { - if(fragoff > 6) + if(fragoff > 6 || psz < 6 + 2) return; auto check = (nuint16_t *)(pld + 6); @@ -258,12 +258,11 @@ namespace llarp } static void - deltaChecksumIPv6UDP(byte_t *pld, ABSL_ATTRIBUTE_UNUSED size_t psz, - size_t fragoff, const uint32_t oSrcIP[4], - const uint32_t oDstIP[4], const uint32_t nSrcIP[4], - const uint32_t nDstIP[4]) + deltaChecksumIPv6UDP(byte_t *pld, size_t psz, size_t fragoff, + const uint32_t oSrcIP[4], const uint32_t oDstIP[4], + const uint32_t nSrcIP[4], const uint32_t nDstIP[4]) { - if(fragoff > 6) + if(fragoff > 6 || psz < 6 + 2) return; auto check = (nuint16_t *)(pld + 6); @@ -388,7 +387,7 @@ namespace llarp +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ nextproto = pld[0]; - fragoff = (uint16_t(pld[2]) << (8 - 3)) | (uint16_t(pld[3]) >> 3); + fragoff = (uint16_t(pld[2]) << 8) | (uint16_t(pld[3]) & 0xFC); if(psz < 8) return; pld += 8; @@ -403,7 +402,7 @@ namespace llarp goto endprotohdrs; } } - endprotohdrs:; + endprotohdrs: switch(nextproto) {