mirror of
https://github.com/zeek/zeek.git
synced 2025-10-08 17:48:21 +00:00
GH-998: Fix Reporter::conn_weird() to handle expired connections
This introduces a new sampling state-map for expired connections to fix segfaults that previously occured when passing in a `connection` record to `Reporter::conn_weird()` for which the internal `Connection` object had already been expired and deleted. This also introduces a new event called `expired_conn_weird`, which is similar to `conn_weird`, except the full `connection` record is no longer available, just the `conn_id` and UID string.
This commit is contained in:
parent
8d9e85b842
commit
51e738a1c0
9 changed files with 163 additions and 5 deletions
|
@ -273,6 +273,21 @@ public:
|
|||
IPPair endpoints;
|
||||
};
|
||||
|
||||
class ConnTupleWeirdTimer final : public Timer {
|
||||
public:
|
||||
using ConnTuple = Reporter::ConnTuple;
|
||||
|
||||
ConnTupleWeirdTimer(double t, ConnTuple id, double timeout)
|
||||
: Timer(t + timeout, TIMER_CONN_TUPLE_WEIRD_EXPIRE),
|
||||
conn_id(std::move(id))
|
||||
{}
|
||||
|
||||
void Dispatch(double t, bool is_expire) override
|
||||
{ reporter->ResetExpiredConnWeird(conn_id); }
|
||||
|
||||
ConnTuple conn_id;
|
||||
};
|
||||
|
||||
void Reporter::ResetNetWeird(const std::string& name)
|
||||
{
|
||||
net_weird_state.erase(name);
|
||||
|
@ -283,6 +298,11 @@ void Reporter::ResetFlowWeird(const IPAddr& orig, const IPAddr& resp)
|
|||
flow_weird_state.erase(std::make_pair(orig, resp));
|
||||
}
|
||||
|
||||
void Reporter::ResetExpiredConnWeird(const ConnTuple& id)
|
||||
{
|
||||
expired_conn_weird_state.erase(id);
|
||||
}
|
||||
|
||||
bool Reporter::PermitNetWeird(const char* name)
|
||||
{
|
||||
auto& count = net_weird_state[name];
|
||||
|
@ -325,6 +345,35 @@ bool Reporter::PermitFlowWeird(const char* name,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Reporter::PermitExpiredConnWeird(const char* name, const RecordVal& conn_id)
|
||||
{
|
||||
auto conn_tuple = std::make_tuple(conn_id.GetField("orig_h")->AsAddr(),
|
||||
conn_id.GetField("resp_h")->AsAddr(),
|
||||
conn_id.GetField("orig_p")->AsPortVal()->Port(),
|
||||
conn_id.GetField("resp_p")->AsPortVal()->Port(),
|
||||
conn_id.GetField("resp_p")->AsPortVal()->PortType());
|
||||
|
||||
auto& map = expired_conn_weird_state[conn_tuple];
|
||||
|
||||
if ( map.empty() )
|
||||
timer_mgr->Add(new ConnTupleWeirdTimer(network_time,
|
||||
std::move(conn_tuple),
|
||||
weird_sampling_duration));
|
||||
|
||||
auto& count = map[name];
|
||||
++count;
|
||||
|
||||
if ( count <= weird_sampling_threshold )
|
||||
return true;
|
||||
|
||||
auto num_above_threshold = count - weird_sampling_threshold;
|
||||
|
||||
if ( weird_sampling_rate )
|
||||
return num_above_threshold % weird_sampling_rate == 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void Reporter::Weird(const char* name, const char* addl)
|
||||
{
|
||||
UpdateWeirdStats(name);
|
||||
|
@ -368,6 +417,22 @@ void Reporter::Weird(Connection* conn, const char* name, const char* addl)
|
|||
"%s", name);
|
||||
}
|
||||
|
||||
void Reporter::Weird(IntrusivePtr<RecordVal> conn_id, IntrusivePtr<StringVal> uid,
|
||||
const char* name, const char* addl)
|
||||
{
|
||||
UpdateWeirdStats(name);
|
||||
|
||||
if ( ! WeirdOnSamplingWhiteList(name) )
|
||||
{
|
||||
if ( ! PermitExpiredConnWeird(name, *conn_id) )
|
||||
return;
|
||||
}
|
||||
|
||||
WeirdHelper(expired_conn_weird,
|
||||
{conn_id.release(), uid.release(), new StringVal(addl)},
|
||||
"%s", name);
|
||||
}
|
||||
|
||||
void Reporter::Weird(const IPAddr& orig, const IPAddr& resp, const char* name, const char* addl)
|
||||
{
|
||||
UpdateWeirdStats(name);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue