From: Masud Hasan (mashasan) Date: Thu, 7 Oct 2021 15:58:25 +0000 (+0000) Subject: Merge pull request #3085 in SNORT/snort3 from ~SMINUT/snort3:tcp_opt_iter to master X-Git-Tag: 3.1.15.0~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=011947bcde60ced7ed80ae63a777378e5b63b689;p=thirdparty%2Fsnort3.git Merge pull request #3085 in SNORT/snort3 from ~SMINUT/snort3:tcp_opt_iter to master Squashed commit of the following: commit 218596bc8e12000e2757d7fd66f5feeeb3c7643e Author: Silviu Minut Date: Fri Oct 1 15:24:07 2021 -0400 protocols: prevent infinite loop over tcp options --- diff --git a/src/protocols/tcp_options.cc b/src/protocols/tcp_options.cc index 75dc1abfc..1cf66aa20 100644 --- a/src/protocols/tcp_options.cc +++ b/src/protocols/tcp_options.cc @@ -23,17 +23,33 @@ #include "tcp_options.h" +#include "stream/tcp/tcp_module.h" + #include "packet.h" #include "tcp.h" +extern THREAD_LOCAL TcpStats tcpStats; + namespace snort { namespace tcp { -TcpOptIteratorIter::TcpOptIteratorIter(const TcpOption* first_opt) : opt(first_opt) { } +TcpOptIteratorIter::TcpOptIteratorIter(const TcpOption* first_opt, const TcpOptIterator* it) : opt(first_opt), iter(it) { } const TcpOption& TcpOptIteratorIter::operator*() const { return *opt; } +const TcpOptIteratorIter& TcpOptIteratorIter::operator++() +{ + const auto* old_opt = opt; + opt = &opt->next(); + if (opt == old_opt) // defend against option length = 0 + { + *this = iter->end(); + tcpStats.zero_len_tcp_opt++; + } + return *this; +} + TcpOptIterator::TcpOptIterator(const TCPHdr* const tcp_header, const Packet* const p) { const uint8_t* const hdr = (const uint8_t*)tcp_header; @@ -68,12 +84,12 @@ TcpOptIterator::TcpOptIterator(const TCPHdr* const tcp_header, const uint32_t va TcpOptIteratorIter TcpOptIterator::begin() const { - return TcpOptIteratorIter(reinterpret_cast(start_ptr)); + return TcpOptIteratorIter(reinterpret_cast(start_ptr), this); } TcpOptIteratorIter TcpOptIterator::end() const { - return TcpOptIteratorIter(reinterpret_cast(end_ptr)); + return TcpOptIteratorIter(reinterpret_cast(end_ptr), this); } } // namespace ip } // namespace snort diff --git a/src/protocols/tcp_options.h b/src/protocols/tcp_options.h index 80feebbb7..fad010281 100644 --- a/src/protocols/tcp_options.h +++ b/src/protocols/tcp_options.h @@ -124,6 +124,8 @@ struct TcpOption } }; +class TcpOptIterator; + /* * Use TcpOptIterator ... this should NOT be called directly * unless you want to an actual iterator or some buggy code. @@ -131,7 +133,7 @@ struct TcpOption class SO_PUBLIC TcpOptIteratorIter { public: - TcpOptIteratorIter(const TcpOption*); + TcpOptIteratorIter(const TcpOption*, const TcpOptIterator*); bool operator==(const TcpOptIteratorIter& rhs) { return opt == rhs.opt; } @@ -139,16 +141,12 @@ public: bool operator!=(const TcpOptIteratorIter& rhs) { return opt != rhs.opt; } - TcpOptIteratorIter& operator++() - { - opt = &opt->next(); - return *this; - } - + const TcpOptIteratorIter& operator++(); const TcpOption& operator*() const; private: const TcpOption* opt; + const TcpOptIterator* iter; }; /* diff --git a/src/stream/tcp/tcp_module.cc b/src/stream/tcp/tcp_module.cc index d8dfdef48..e0037fdf5 100644 --- a/src/stream/tcp/tcp_module.cc +++ b/src/stream/tcp/tcp_module.cc @@ -114,6 +114,7 @@ const PegInfo tcp_pegs[] = { CountType::SUM, "partial_fallbacks", "count of fallbacks from assigned service stream splitter" }, { CountType::MAX, "max_segs", "maximum number of segments queued in any flow" }, { CountType::MAX, "max_bytes", "maximum number of bytes queued in any flow" }, + { CountType::SUM, "zero_len_tcp_opt", "number of zero length tcp options" }, { CountType::END, nullptr, nullptr } }; diff --git a/src/stream/tcp/tcp_module.h b/src/stream/tcp/tcp_module.h index 9d9cad9f8..cb0e95eae 100644 --- a/src/stream/tcp/tcp_module.h +++ b/src/stream/tcp/tcp_module.h @@ -112,6 +112,7 @@ struct TcpStats PegCount partial_fallbacks; PegCount max_segs; PegCount max_bytes; + PegCount zero_len_tcp_opt; }; extern THREAD_LOCAL struct TcpStats tcpStats;