packet_analysis: Do not raise analyzer_confirmation per-packet for tunnels

There's a logic error in the packet analyzer's AnalyzerConfirmation()
method that causes analyzer_confirmation() events to be raised for every
packet rather than stopping after the first confirmation which appears to
have been the intention. This affects, for example, VXLAN and Geneve tunnels.

The optional arg_tag parameter was used for short-circuit'ing, but the return
value of GetAnalyzerTag() used for setting the session state causing the
disconnect.

In scenarios where Zeek receives purely tunneled monitoring traffic, this may
result in a non-negligible performance impact.

Somewhat related, ensure the session state is set to violated before
short-circuiting if no analyzer_violations are installed.

Suggesting this as a 5.0.3 candidate.
This commit is contained in:
Arne Welzel 2022-09-26 17:02:59 +02:00
parent 19ba30d77a
commit 3a320fc6b6
6 changed files with 57 additions and 8 deletions

View file

@ -168,26 +168,30 @@ void Analyzer::Weird(const char* name, Packet* packet, const char* addl) const
void Analyzer::AnalyzerConfirmation(session::Session* session, zeek::Tag arg_tag)
{
if ( session->AnalyzerState(arg_tag) == session::AnalyzerConfirmationState::CONFIRMED )
const auto& effective_tag = arg_tag ? arg_tag : GetAnalyzerTag();
if ( session->AnalyzerState(effective_tag) == session::AnalyzerConfirmationState::CONFIRMED )
return;
session->SetAnalyzerState(GetAnalyzerTag(), session::AnalyzerConfirmationState::CONFIRMED);
session->SetAnalyzerState(effective_tag, session::AnalyzerConfirmationState::CONFIRMED);
if ( ! analyzer_confirmation )
return;
const auto& tval = arg_tag ? arg_tag.AsVal() : tag.AsVal();
event_mgr.Enqueue(analyzer_confirmation, session->GetVal(), tval, val_mgr->Count(0));
event_mgr.Enqueue(analyzer_confirmation, session->GetVal(), effective_tag.AsVal(),
val_mgr->Count(0));
}
void Analyzer::AnalyzerViolation(const char* reason, session::Session* session, const char* data,
int len, zeek::Tag arg_tag)
{
const auto& effective_tag = arg_tag ? arg_tag : GetAnalyzerTag();
session->SetAnalyzerState(effective_tag, session::AnalyzerConfirmationState::VIOLATED);
if ( ! analyzer_violation )
return;
session->SetAnalyzerState(GetAnalyzerTag(), session::AnalyzerConfirmationState::VIOLATED);
StringValPtr r;
if ( data && len )
@ -200,8 +204,8 @@ void Analyzer::AnalyzerViolation(const char* reason, session::Session* session,
else
r = make_intrusive<StringVal>(reason);
const auto& tval = arg_tag ? arg_tag.AsVal() : tag.AsVal();
event_mgr.Enqueue(analyzer_violation, session->GetVal(), tval, val_mgr->Count(0), std::move(r));
event_mgr.Enqueue(analyzer_violation, session->GetVal(), effective_tag.AsVal(),
val_mgr->Count(0), std::move(r));
}
} // namespace zeek::packet_analysis