Squashed commit of the following:
commit
218596bc8e12000e2757d7fd66f5feeeb3c7643e
Author: Silviu Minut <sminut@cisco.com>
Date: Fri Oct 1 15:24:07 2021 -0400
protocols: prevent infinite loop over tcp options
#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;
TcpOptIteratorIter TcpOptIterator::begin() const
{
- return TcpOptIteratorIter(reinterpret_cast<const TcpOption*>(start_ptr));
+ return TcpOptIteratorIter(reinterpret_cast<const TcpOption*>(start_ptr), this);
}
TcpOptIteratorIter TcpOptIterator::end() const
{
- return TcpOptIteratorIter(reinterpret_cast<const TcpOption*>(end_ptr));
+ return TcpOptIteratorIter(reinterpret_cast<const TcpOption*>(end_ptr), this);
}
} // namespace ip
} // namespace snort
}
};
+class TcpOptIterator;
+
/*
* Use TcpOptIterator ... this should NOT be called directly
* unless you want to an actual iterator or some buggy code.
class SO_PUBLIC TcpOptIteratorIter
{
public:
- TcpOptIteratorIter(const TcpOption*);
+ TcpOptIteratorIter(const TcpOption*, const TcpOptIterator*);
bool operator==(const TcpOptIteratorIter& rhs)
{ return opt == rhs.opt; }
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;
};
/*
{ 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 }
};
PegCount partial_fallbacks;
PegCount max_segs;
PegCount max_bytes;
+ PegCount zero_len_tcp_opt;
};
extern THREAD_LOCAL struct TcpStats tcpStats;