Add NCP::max_frame_size tuning option

This helps prevent excessive allocations based on message lengths
taken from NCP headers.
This commit is contained in:
Jon Siwek 2018-05-22 18:27:52 -05:00
parent e35da5f592
commit 58864c358c
7 changed files with 487 additions and 15 deletions

View file

@ -5,6 +5,6 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI
bro_plugin_begin(Bro NCP)
bro_plugin_cc(NCP.cc Plugin.cc)
bro_plugin_bif(events.bif)
bro_plugin_bif(events.bif consts.bif)
bro_plugin_pac(ncp.pac)
bro_plugin_end()

View file

@ -9,6 +9,7 @@
#include "NCP.h"
#include "events.bif.h"
#include "consts.bif.h"
using namespace std;
using namespace analyzer::ncp;
@ -105,13 +106,12 @@ void FrameBuffer::Reset()
msg_len = 0;
}
// Returns true if we have a complete frame
bool FrameBuffer::Deliver(int &len, const u_char* &data)
int FrameBuffer::Deliver(int &len, const u_char* &data)
{
ASSERT(buf_len >= hdr_len);
if ( len == 0 )
return false;
return -1;
if ( buf_n < hdr_len )
{
@ -123,13 +123,16 @@ bool FrameBuffer::Deliver(int &len, const u_char* &data)
}
if ( buf_n < hdr_len )
return false;
return -1;
compute_msg_length();
if ( msg_len > buf_len )
{
buf_len = msg_len * 2;
if ( msg_len > BifConst::NCP::max_frame_size )
return 1;
buf_len = msg_len;
u_char* new_buf = new u_char[buf_len];
memcpy(new_buf, msg_buf, buf_n);
delete [] msg_buf;
@ -143,7 +146,13 @@ bool FrameBuffer::Deliver(int &len, const u_char* &data)
++buf_n; ++data; --len;
}
return buf_n >= msg_len;
if ( buf_n < msg_len )
return -1;
if ( buf_n == msg_len )
return 0;
return 1;
}
void NCP_FrameBuffer::compute_msg_length()
@ -203,10 +212,27 @@ void Contents_NCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig
resync = false;
}
while ( buffer.Deliver(len, data) )
for ( ; ; )
{
session->Deliver(IsOrig(), buffer.Len(), buffer.Data());
buffer.Reset();
auto result = buffer.Deliver(len, data);
if ( result < 0 )
break;
if ( result == 0 )
{
session->Deliver(IsOrig(), buffer.Len(), buffer.Data());
buffer.Reset();
}
else
{
// The rest of the data available in this delivery will
// be discarded and will need to resync to a new frame header.
Weird("ncp_large_frame");
buffer.Reset();
resync = true;
break;
}
}
}

View file

@ -54,8 +54,9 @@ public:
explicit FrameBuffer(int header_length);
virtual ~FrameBuffer();
// Returns true if a frame is ready
bool Deliver(int& len, const u_char* &data);
// Returns -1 if frame is not ready, 0 if it else, and 1 if
// the frame would require too large of a buffer allocation.
int Deliver(int& len, const u_char* &data);
void Reset();
@ -68,9 +69,9 @@ protected:
int hdr_len;
u_char* msg_buf;
int msg_len;
int buf_n; // number of bytes in msg_buf
int buf_len; // size off msg_buf
uint64 msg_len;
size_t buf_n; // number of bytes in msg_buf
size_t buf_len; // size off msg_buf
};
#define NCP_TCPIP_HEADER_LENGTH 8

View file

@ -0,0 +1 @@
const NCP::max_frame_size: count;