Analyzer: Do not add child analyzers when finished

Depending on an analyzer's implementation, its Done() method may
attempt to access analyzer or connection state when executing.
When this happens in the destructor of the parent analyzer during
the process of destructing a connection, this state may have been
deleted, resulting in use-after-free crashes or worse memory
corruption.

The following cases have been observed in the wild for when this happens.

  * PIA matching during Done() for undelivered TCP data enables a Spicy
    based analyzer which in turn attempts to raise an analyzer violation
    during Done()->EndOfData().

  * Spicy analyzers attaching new analyzers during their Done() processing
    which in turn attempt to use TCP() (to call FindChild()) during Done()
    while the analyzer tree / connection is being destructed.

The second scenario was previously found to happen in the HTTP analyzer
and fixed with 6ef9423f3c.

Plug these scenarios by short-circuiting AddChildAnalyzer() if the analyzer
or connection have finished or are being finished.
This commit is contained in:
Arne Welzel 2024-08-21 23:58:41 +02:00
parent 4a4cbf2576
commit be9f170561
2 changed files with 28 additions and 13 deletions

View file

@ -195,6 +195,9 @@ public:
bool PermitWeird(const char* name, uint64_t threshold, uint64_t rate, double duration);
// Returns true once Done() is called.
bool IsFinished() { return finished; }
private:
friend class session::detail::Timer;