diff --git a/NEWS b/NEWS index 22fc74a36c..7c3af61571 100644 --- a/NEWS +++ b/NEWS @@ -117,6 +117,14 @@ Changed Functionality - Passing non-string ``sep`` and ``def`` arguments to ``cat_sep()`` isn't a fatal error anymore. More descriptive error messages are produced, too. +- The number of analyzer violation events that can be raised by protocol + analyzer instances is now capped by the const ``max_analyzer_violation_events``. + Its default is 1000 and the main purpose is to prevent analyzers from + scheduling too many ``analyzer_violation_info`` events before the + DPD ``max_violations`` script-level logic has a chance to run and disable + the problematic analyzer. + + Deprecated Functionality ------------------------ diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index b7f6c67167..519db3922d 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -2312,6 +2312,19 @@ type AnalyzerViolationInfo: record { data: string &optional; }; +## The maximum number of analyzer violations the core generates before +## suppressing them for a given analyzer instance. A weird providing +## information about the analyzer and connection is generated once the +## limit is reached. +## +## An analyzer generating this many violations is unlikely parsing +## the right protocol or potentially buggy. +## +## See also :zeek:see:`DPD::max_violations` which controls disabling +## analyzers through script logic after a certain number of violations +## was observed. +const max_analyzer_violations = 1000 &redef; + module NFS3; diff --git a/src/analyzer/Analyzer.cc b/src/analyzer/Analyzer.cc index 60203bf000..ec9d729295 100644 --- a/src/analyzer/Analyzer.cc +++ b/src/analyzer/Analyzer.cc @@ -754,6 +754,16 @@ void Analyzer::AnalyzerViolation(const char* reason, const char* data, int len, { const auto& effective_tag = arg_tag ? arg_tag : tag; + ++analyzer_violations; + + if ( analyzer_violations > BifConst::max_analyzer_violations ) + { + if ( analyzer_violations == BifConst::max_analyzer_violations + 1 ) + Weird("too_many_analyzer_violations"); + + return; + } + if ( analyzer_violation_info ) EnqueueAnalyzerViolationInfo(reason, data, len, effective_tag); diff --git a/src/analyzer/Analyzer.h b/src/analyzer/Analyzer.h index f5387a2f4a..54dd61bc73 100644 --- a/src/analyzer/Analyzer.h +++ b/src/analyzer/Analyzer.h @@ -750,6 +750,8 @@ private: bool finished; bool removing; + uint64_t analyzer_violations = 0; + static ID id_counter; }; diff --git a/src/const.bif b/src/const.bif index b8e71e98e8..2658376817 100644 --- a/src/const.bif +++ b/src/const.bif @@ -9,6 +9,7 @@ const detect_filtered_trace: bool; const report_gaps_for_partial: bool; const exit_only_after_terminate: bool; const digest_salt: string; +const max_analyzer_violations: count; const NFS3::return_data: bool; const NFS3::return_data_max: count;