in AuditRulesMonitor.cpp [169:298]
bool AuditRulesMonitor::check_kernel_rules() {
_op_status->SetDesiredAuditRules(_desired_rules);
if (_desired_rules.empty()) {
return true;
}
std::vector<AuditRule> rules;
auto ret = NetlinkRetry([this,&rules]() {
rules.clear();
return _netlink.AuditListRules(rules);
});
if (ret != 0) {
Logger::Error("AuditRulesMonitor: Unable to fetch audit rules from kernel: %s", std::strerror(-ret));
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_KERNEL, std::string("Unable to fetch audit rules from kernel: ") + std::strerror(-ret));
_op_status->SetLoadedAuditRules({{}});
return false;
} else {
_op_status->SetLoadedAuditRules(rules);
}
auto merged_rules = MergeRules(rules);
auto diff = DiffRules(merged_rules, _desired_rules, "");
if (diff.empty()) {
_op_status->ClearErrorCondition(ErrorCategory::AUDIT_RULES_KERNEL);
return true;
}
uint32_t enabled = 0;
ret = NetlinkRetry([this,&enabled]() { return _netlink.AuditGetEnabled(enabled); });
if (ret != 0) {
Logger::Error("AuditRulesMonitor: Unable to get audit status from kernel: %s", std::strerror(-ret));
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_KERNEL, std::string("Unable to get audit status from kernel: ") + std::strerror(-ret));
return false;
}
if (enabled == 2) {
if (!_rules_immutable) {
Logger::Error("AuditRulesMonitor: Unable to add desired rules because audit rules are set to immutable");
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_KERNEL, "Unable to add desired rules because audit rules are set to immutable");
_rules_immutable = true;
}
return true;
} else {
_rules_immutable = false;
}
Logger::Info("AuditRulesMonitor: Found desired audit rules not currently loaded, loading new rules");
std::unordered_map<std::string, AuditRule> _dmap;
for (auto& rule: _desired_rules) {
_dmap.emplace(rule.CanonicalMergeKey(), rule);
}
bool failed_old = false;
bool failed_new = false;
// Delete all old auoms rules
for (auto& rule: rules) {
// Delete rule if it has AUOMS_RULE_KEY or matches any of the desired rules.
bool delete_it = rule.GetKeys().count(AUOMS_RULE_KEY) > 0;
if (!delete_it) {
auto itr = _dmap.find(rule.CanonicalMergeKey());
if (itr != _dmap.end()) {
if (rule.IsWatch()) {
// Check to see if the rule's perms is a subset of the desired rule's perms
auto dset = itr->second.GetPerms();
auto aset = rule.GetPerms();
if (is_set_intersect(dset, aset)) {
delete_it = true;
}
} else {
// Check to see if the rule's syscalls is a subset of the desired rule's syscalls
auto dset = itr->second.GetSyscalls();
auto aset = rule.GetSyscalls();
if (is_set_intersect(dset, aset)) {
delete_it = true;
}
}
}
}
if (delete_it) {
ret = _netlink.AuditDelRule(rule);
if (ret != 0) {
Logger::Warn("AuditRulesMonitor: Failed to delete audit rule (%s): %s\n", rule.CanonicalText().c_str(), strerror(-ret));
failed_old = true;
}
}
}
// refresh rules list
ret = NetlinkRetry([this,&rules]() {
rules.clear();
return _netlink.AuditListRules(rules);
});
if (ret != 0) {
Logger::Error("AuditRulesMonitor: Unable to fetch audit rules from kernel: %s", std::strerror(-ret));
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_KERNEL, std::string("Unable to fetch audit rules from kernel: ") + std::strerror(-ret));
return false;
}
merged_rules = MergeRules(rules);
// re-diff rules
diff = DiffRules(merged_rules, _desired_rules, "");
if (diff.empty()) {
_op_status->ClearErrorCondition(ErrorCategory::AUDIT_RULES_KERNEL);
return true;
}
// Add diff rules
for (auto& rule: diff) {
ret = _netlink.AuditAddRule(rule);
if (ret != 0) {
Logger::Warn("AuditRulesMonitor: Failed to load audit rule (%s): %s\n", rule.CanonicalText().c_str(), strerror(-ret));
failed_new = true;
}
}
if (failed_new && !failed_old) {
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_KERNEL, "Failed to add new rule(s)");
} else if (!failed_new && failed_old) {
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_KERNEL, "Failed to delete old rule(s)");
} else if (failed_new && failed_old) {
_op_status->SetErrorCondition(ErrorCategory::AUDIT_RULES_KERNEL, "Failed to delete old rule(s) and failed to add new rule(s)");
} else {
_op_status->ClearErrorCondition(ErrorCategory::AUDIT_RULES_KERNEL);
}
return true;
}