in RawEventProcessor.cpp [139:738]
bool RawEventProcessor::process_syscall_event(const Event& event) {
using namespace std::string_view_literals;
static auto SV_ZERO = "0"sv;
static auto SV_TYPE = "type"sv;
static auto SV_ITEMS = "items"sv;
static auto SV_ITEM = "item"sv;
static auto SV_NODE = "node"sv;
static auto SV_ARGC = "argc"sv;
static auto SV_CWD = "cwd"sv;
static auto SV_SADDR = "saddr"sv;
static auto SV_INTEGRITY_HASH = "hash"sv;
static auto SV_NAME = "name"sv;
static auto SV_NAMETYPE = "nametype"sv;
static auto SV_OBJTYPE = "objtype"sv;
static auto SV_MODE = "mode"sv;
static auto SV_OUID = "ouid"sv;
static auto SV_OGID = "ogid"sv;
static auto SV_PATH_NAME = "path_name"sv;
static auto SV_PATH_NAMETYPE = "path_nametype"sv;
static auto SV_PATH_MODE = "path_mode"sv;
static auto SV_PATH_OUID = "path_ouid"sv;
static auto SV_PATH_OGID = "path_ogid"sv;
static auto SV_EMPTY = ""sv;
static auto SV_CMDLINE = "cmdline"sv;
static auto SV_REDACTORS = "redactors"sv;
static auto SV_CONTAINERID = "containerid"sv;
static auto SV_DROPPED = "dropped_"sv;
static auto SV_PID = "pid"sv;
static auto SV_PPID = "ppid"sv;
static auto SV_SYSCALL = "syscall"sv;
static auto SV_PROCTITLE = "proctitle"sv;
static auto S_EXECVE = std::string("execve");
static auto SV_JSON_ARRAY_START = "[\""sv;
static auto SV_JSON_ARRAY_SEP = "\",\""sv;
static auto SV_JSON_ARRAY_END = "\"]"sv;
static auto auoms_syscall_name = RecordTypeToName(RecordType::AUOMS_SYSCALL);
static auto auoms_syscall_fragment_name = RecordTypeToName(RecordType::AUOMS_SYSCALL_FRAGMENT);
static auto auoms_execve_name = RecordTypeToName(RecordType::AUOMS_EXECVE);
static auto SV_AUOMSVERSION_NAME = "auoms_version"sv;
static std::string S_AUOMS_VERSION = AUOMS_VERSION;
static std::string_view SV_AUOMS_VERSION = S_AUOMS_VERSION;
int num_fields = 0;
int num_path = 0;
int num_execve = 0;
int uid;
int gid;
std::string exe;
std::string syscall;
auto rec_type = RecordType::AUOMS_SYSCALL_FRAGMENT;
auto rec_type_name = auoms_syscall_fragment_name;
EventRecord syscall_rec;
EventRecordField syscall_field;
EventRecord cwd_rec;
EventRecordField cwd_field;
EventRecord path_rec;
std::vector<EventRecord> path_recs;
std::vector<EventRecord> execve_recs;
EventRecord argc_rec;
EventRecordField argc_field;
EventRecord sockaddr_rec;
EventRecordField sockaddr_field;
EventRecord integrity_rec;
EventRecordField integrity_field;
EventRecord proctitle_rec;
EventRecordField proctitle_field;
EventRecord dropped_rec;
std::vector<EventRecord> other_recs;
for (auto& rec: event) {
switch(static_cast<RecordType>(rec.RecordType())) {
case RecordType::SYSCALL:
if (!syscall_rec) {
rec_type = RecordType::AUOMS_SYSCALL;
rec_type_name = auoms_syscall_name;
for (auto &f : rec) {
auto fname = f.FieldName();
switch (fname[0]) {
case 't': {
if (fname != SV_TYPE) {
num_fields += 1;
}
break;
}
case 'i': {
if (fname != SV_ITEMS) {
num_fields += 1;
}
break;
}
case 's': {
if (fname == SV_SYSCALL) {
syscall_field = f;
}
num_fields += 1;
break;
}
default:
num_fields += 1;
break;
}
}
syscall_rec = rec;
}
break;
case RecordType::EXECVE: {
if (rec.NumFields() > 0) {
if (num_execve == 0) {
num_fields += 1;
if (!argc_rec) {
// the argc field should be the first (or second if node field is present) field in the record but check the first four just in case
for(uint16_t i = 0; i < rec.NumFields() && i < 4 ; i++) {
auto field = rec.FieldAt(i);
if (field.FieldName() == SV_ARGC) {
num_fields += 1;
argc_rec = rec;
argc_field = field;
break;
}
}
}
}
num_execve += 1;
execve_recs.emplace_back(rec);
}
break;
}
case RecordType::CWD:
if (!cwd_rec) {
for (int i = 0; i < rec.NumFields(); ++i) {
auto field = rec.FieldAt(i);
if (field.FieldName() == SV_CWD) {
num_fields += 1;
cwd_rec = rec;
cwd_field = field;
break;
}
}
}
break;
case RecordType::PATH:
if (rec.NumFields() > 0) {
if (num_path == 0) {
// This assumes there will only be a nametype field or an objtype field but never both
num_fields += 5; // name, mode, ouid, ogid, (nametype or objtype)
}
num_path += 1;
path_recs.emplace_back(rec);
if (!path_rec) {
bool isItemZero = false;
unsigned int numNodeFields = 0;
for (auto& f: rec) {
if (f.FieldName() == SV_ITEM && f.RawValue() == SV_ZERO) {
isItemZero = true;
} else if (f.FieldName() == SV_NODE) {
numNodeFields++;
}
}
if (isItemZero) {
num_fields += rec.NumFields() - 1 - numNodeFields; // exclude item and node fields
path_rec = rec;
}
}
}
break;
case RecordType::SOCKADDR:
if (!sockaddr_rec) {
for (int i = 0; i < rec.NumFields(); ++i) {
auto field = rec.FieldAt(i);
if (field.FieldName() == SV_SADDR) {
sockaddr_rec = rec;
sockaddr_field = field;
num_fields += 1;
break;
}
}
}
break;
case RecordType::INTEGRITY_RULE:
if (!integrity_rec) {
for (int i = 0; i < rec.NumFields(); ++i) {
auto field = rec.FieldAt(i);
if (field.FieldName() == SV_INTEGRITY_HASH) {
integrity_rec = rec;
integrity_field = field;
num_fields += 1;
}
}
}
break;
case RecordType::PROCTITLE:
if (!proctitle_rec) {
for (int i = 0; i < rec.NumFields(); ++i) {
auto field = rec.FieldAt(i);
if (field.FieldName() == SV_PROCTITLE) {
num_fields += 1;
proctitle_rec = rec;
proctitle_field = field;
break;
}
}
}
break;
case RecordType::AUOMS_DROPPED_RECORDS:
dropped_rec = rec;
num_fields += dropped_rec->NumFields();
break;
default:
if (rec.NumFields() > 0) {
num_fields += rec.NumFields();
other_recs.emplace_back(rec);
}
break;
}
}
// Sort PATH records by item field
std::sort(path_recs.begin(), path_recs.end(), [](const EventRecord& a, const EventRecord& b) -> int {
auto fa = a.FieldByName(SV_ITEM);
auto fb = b.FieldByName(SV_ITEM);
int a_num = INT32_MAX; // PATH records with a missing or invalid item value should be sorted to the end;
int b_num = INT32_MAX;
if (fa) {
try {
a_num = std::stoi(std::string(fa.FieldName()));
} catch (std::logic_error&) {
// Ignore
}
}
if (fb) {
try {
b_num = std::stoi(std::string(fb.FieldName()));
} catch (std::logic_error&) {
// Ignore
}
}
return a_num > b_num;
});
if (syscall_rec && syscall_field) {
if (InterpretField(_tmp_val, syscall_rec, syscall_field, field_type_t::SYSCALL)) {
if (starts_with(_tmp_val, S_EXECVE)) {
rec_type = RecordType::AUOMS_EXECVE;
rec_type_name = auoms_execve_name;
}
}
_syscall = _tmp_val;
}
// Exclude proctitle if EXECVE is present
if (execve_recs.size() > 0 && proctitle_rec && proctitle_field) {
num_fields -= 1;
}
if (execve_recs.size() > 0 || (proctitle_rec && proctitle_field)) {
// for redactors field
num_fields += 1;
}
if (num_fields == 0) {
return false;
}
// For containerid and auoms_version
num_fields += 2;
if (!_builder->BeginEvent(event.Seconds(), event.Milliseconds(), event.Serial(), 1)) {
throw std::runtime_error("Queue closed");
}
_event_flags = EVENT_FLAG_IS_AUOMS_EVENT;
if (!_builder->BeginRecord(static_cast<uint32_t>(rec_type), rec_type_name, SV_EMPTY, num_fields)) {
throw std::runtime_error("Queue closed");
}
if (!_builder->AddField(SV_AUOMSVERSION_NAME, SV_AUOMS_VERSION, nullptr, field_type_t::UNCLASSIFIED)) {
throw std::runtime_error("Queue closed");
}
if (syscall_rec) {
for (auto &f : syscall_rec) {
auto fname = f.FieldName();
bool add_field = false;
switch (fname[0]) {
case 't': {
if (fname != SV_TYPE) {
add_field = true;
}
break;
}
case 'i': {
if (fname != SV_ITEMS) {
add_field = true;
}
break;
}
case 'p':
if (fname == SV_PID) {
_pid = atoi(f.RawValuePtr());
_builder->SetEventPid(_pid);
}
if (fname == SV_PPID) {
_ppid = atoi(f.RawValuePtr());
}
add_field = true;
break;
case 'u':
if (fname == "uid") {
uid = atoi(f.RawValuePtr());
}
add_field = true;
break;
case 'g':
if (fname == "gid") {
gid = atoi(f.RawValuePtr());
}
add_field = true;
break;
case 'e':
if (fname == "exe") {
exe = std::string(f.RawValuePtr());
}
add_field = true;
break;
default:
add_field = true;
break;
}
if (add_field) {
if (!process_field(syscall_rec, f, 0)) {
cancel_event();
return false;
}
}
}
}
if (cwd_rec && cwd_field) {
if (!process_field(cwd_rec, cwd_field, 0)) {
cancel_event();
return false;
}
}
if (path_rec) {
for (auto &f : path_rec) {
auto fname = f.FieldName();
if (fname != SV_ITEM && fname != SV_NODE) {
if (!process_field(path_rec, f, 0)) {
cancel_event();
return false;
}
}
}
}
_path_name.resize(0);
_path_nametype.resize(0);
_path_mode.resize(0);
_path_ouid.resize(0);
_path_ogid.resize(0);
if (path_recs.size() > 0) {
_path_name = SV_JSON_ARRAY_START;
_path_nametype = SV_JSON_ARRAY_START;
_path_mode = SV_JSON_ARRAY_START;
_path_ouid = SV_JSON_ARRAY_START;
_path_ogid = SV_JSON_ARRAY_START;
int path_num = 0;
for (auto& rec: path_recs) {
bool found_nametype = false;
for (auto &f : rec) {
auto fname = f.FieldName();
if (fname.size() >= 2) {
switch (fname[0]) {
case 'm': {
if (fname == SV_MODE) {
if (path_num != 0) {
_path_mode.append(SV_JSON_ARRAY_SEP);
}
_path_mode.append(f.RawValuePtr(), f.RawValueSize());
}
break;
}
case 'n': {
if (fname == SV_NAME) {
if (path_num != 0) {
_path_name.append(SV_JSON_ARRAY_SEP);
}
// name might be escaped
unescape_raw_field(_unescaped_val, f.RawValuePtr(), f.RawValueSize());
// Path names might have non-ASCII/non-printable chars, escape the name before adding it.
json_escape_string(_tmp_val, _unescaped_val.data(), _unescaped_val.size());
_path_name.append(_tmp_val);
} else if (fname == SV_NAMETYPE && !found_nametype) {
if (path_num != 0) {
_path_nametype.append(SV_JSON_ARRAY_SEP);
}
_path_nametype.append(f.RawValuePtr(), f.RawValueSize());
found_nametype = true;
}
break;
}
case 'o': {
switch (fname[1]) {
case 'b':
if (fname == SV_OBJTYPE && !found_nametype) {
if (path_num != 0) {
_path_nametype.append(SV_JSON_ARRAY_SEP);
}
_path_nametype.append(f.RawValuePtr(), f.RawValueSize());
found_nametype = true;
}
break;
case 'g':
if (fname == SV_OGID) {
if (path_num != 0) {
_path_ogid.append(SV_JSON_ARRAY_SEP);
}
_path_ogid.append(f.RawValuePtr(), f.RawValueSize());
}
break;
case 'u':
if (fname == SV_OUID) {
if (path_num != 0) {
_path_ouid.append(SV_JSON_ARRAY_SEP);
}
_path_ouid.append(f.RawValuePtr(), f.RawValueSize());
}
break;
}
break;
}
}
}
}
path_num += 1;
}
_path_name.append(SV_JSON_ARRAY_END);
_path_nametype.append(SV_JSON_ARRAY_END);
_path_mode.append(SV_JSON_ARRAY_END);
_path_ouid.append(SV_JSON_ARRAY_END);
_path_ogid.append(SV_JSON_ARRAY_END);
if (!_builder->AddField(SV_PATH_NAME, _path_name, nullptr, field_type_t::UNCLASSIFIED)) {
throw std::runtime_error("Queue closed");
}
if (!_builder->AddField(SV_PATH_NAMETYPE, _path_nametype, nullptr, field_type_t::UNCLASSIFIED)) {
throw std::runtime_error("Queue closed");
}
if (!_builder->AddField(SV_PATH_MODE, _path_mode, nullptr, field_type_t::UNCLASSIFIED)) {
throw std::runtime_error("Queue closed");
}
if (!_builder->AddField(SV_PATH_OUID, _path_ouid, nullptr, field_type_t::UNCLASSIFIED)) {
throw std::runtime_error("Queue closed");
}
if (!_builder->AddField(SV_PATH_OGID, _path_ogid, nullptr, field_type_t::UNCLASSIFIED)) {
throw std::runtime_error("Queue closed");
}
}
if (argc_rec && argc_field) {
if (!process_field(argc_rec, argc_field, 0)) {
cancel_event();
return false;
}
}
if (execve_recs.size() > 0) {
// Exclude proctitle since we have EXECVE
proctitle_rec = EventRecord();
proctitle_field = EventRecordField();
_execve_converter.Convert(execve_recs, _cmdline);
_cmdline_redactor->ApplyRules(_cmdline, _tmp_val);
if (!_builder->AddField(SV_CMDLINE, _cmdline, nullptr, field_type_t::UNESCAPED)) {
throw std::runtime_error("Queue closed");
}
if (!_builder->AddField(SV_REDACTORS, _tmp_val, nullptr, field_type_t::UNCLASSIFIED)) {
throw std::runtime_error("Queue closed");
}
} else {
_cmdline.resize(0);
}
if (sockaddr_rec && sockaddr_field) {
if (!process_field(sockaddr_rec, sockaddr_field, 0)) {
cancel_event();
return false;
}
}
if (integrity_rec && integrity_field) {
if (!process_field(integrity_rec, integrity_field, 0)) {
cancel_event();
return false;
}
}
if (proctitle_rec && proctitle_field) {
unescape_raw_field(_unescaped_val, proctitle_field.RawValuePtr(), proctitle_field.RawValueSize());
ExecveConverter::ConvertRawCmdline(_unescaped_val, _cmdline);
_cmdline_redactor->ApplyRules(_cmdline, _tmp_val);
if (!_builder->AddField(SV_PROCTITLE, _cmdline, nullptr, field_type_t::PROCTITLE)) {
throw std::runtime_error("Queue closed");
}
if (!_builder->AddField(SV_REDACTORS, _tmp_val, nullptr, field_type_t::UNCLASSIFIED)) {
throw std::runtime_error("Queue closed");
}
}
if (other_recs.size() > 0) {
_other_tag += 1;
for (auto& rec : other_recs) {
auto r = _other_rtype_counts.emplace(std::make_pair(rec.RecordType(), std::make_pair(_other_tag, 1)));
if (!r.second) {
if (r.first->second.first != _other_tag) {
r.first->second.first = _other_tag;
r.first->second.second = 1;
}
}
for (auto &field: rec) {
if (!process_field(rec, field, r.first->second.second)) {
cancel_event();
return false;
}
}
r.first->second.second += 1;
}
}
if (dropped_rec) {
for (auto& field: dropped_rec) {
_field_name.assign(SV_DROPPED);
_field_name.append(field.FieldName());
if (!_builder->AddField(_field_name, field.RawValue(), nullptr, field_type_t::UNCLASSIFIED)) {
throw std::runtime_error("Queue closed");
}
}
}
std::shared_ptr<ProcessTreeItem> p;
std::string cmdline;
std::string containerid;
if (_processTree) {
if (!_syscall.empty() && starts_with(_syscall, "execve")) {
if (!exe.empty() && exe.front() == '"' && exe.back() == '"') {
exe = exe.substr(1, exe.length() - 2);
}
p = _processTree->AddProcess(ProcessTreeSource_execve, _pid, _ppid, uid, gid, exe, _cmdline);
} else if (!_syscall.empty()) {
p = _processTree->GetInfoForPid(_pid);
}
if (p) {
containerid = p->containerid();
}
}
if (!_builder->AddField(SV_CONTAINERID, containerid, nullptr, field_type_t::UNCLASSIFIED)) {
throw std::runtime_error("Queue closed");
}
if (!_builder->EndRecord()) {
throw std::runtime_error("Queue closed");
}
bool filtered = false;
if (_filtersEngine && p && _filtersEngine->IsEventFiltered(_syscall, p, _filtersEngine->GetCommonFlagsMask())) {
filtered = true;
}
if (!filtered) {
end_event();
} else {
cancel_event();
}
return true;
}