static void AUDIT_assembler(benchmark::State& state) { AuditAssembler asmb; asmb.start( 20, {AUDIT_SYSCALL, AUDIT_EXECVE, AUDIT_PATH, AUDIT_CWD}, &ProcessUpdate); std::vector<struct audit_reply> replies = { getMockReply(kBenchmarkMessages[0]), getMockReply(kBenchmarkMessages[1]), getMockReply(kBenchmarkMessages[2]), getMockReply(kBenchmarkMessages[3]), getMockReply(kBenchmarkMessages[4]), getMockReply(kBenchmarkMessages[5]), }; std::vector<AuditEventContextRef> contexts; for (const auto& r : replies) { auto ec = std::make_shared<AuditEventContext>(); handleAuditReply(r, ec); contexts.push_back(ec); } size_t i = 0; while (state.KeepRunning()) { const auto& ec = contexts[i++ % 6]; asmb.add(ec->audit_id, ec->type, ec->fields); } for (auto& r : replies) { free((void*)r.message); } }
TEST_F(AuditTests, test_handle_reply) { // Create the input structures. struct audit_reply reply; auto ec = std::make_shared<AuditEventContext>(); // A 'fake' audit message. std::string message = "audit(1440542781.644:403030): argc=3 a0=\"/bin/sh\" a1=\"-c\" a2=\"h\""; reply.type = 1; reply.len = message.size(); reply.message = (char*)malloc(sizeof(char) * (message.size() + 1)); memset((void*)reply.message, 0, message.size() + 1); memcpy((void*)reply.message, message.c_str(), message.size()); // Perform the parsing. handleAuditReply(reply, ec); free((char*)reply.message); EXPECT_EQ(reply.type, ec->type); EXPECT_EQ(ec->fields.size(), 4); EXPECT_EQ(ec->fields.count("argc"), 1); EXPECT_EQ(ec->fields["argc"], "3"); EXPECT_EQ(ec->fields["a0"], "\"/bin/sh\""); }
static void AUDIT_handleReply(benchmark::State& state) { auto reply = getMockReply(kBenchmarkMessages[0]); while (state.KeepRunning()) { auto ec = std::make_shared<AuditEventContext>(); // Perform the parsing. handleAuditReply(reply, ec); } free((void*)reply.message); }
Status AuditEventPublisher::run() { if (!FLAGS_disable_audit && (count_ == 0 || count_++ % 10 == 0)) { // Request an update to the audit status. // This will also fill in the status on first run. audit_request_status(handle_); } // Reset the reply data. int result = 0; bool handle_reply = false; while (true) { handle_reply = false; // Request a reply in a non-blocking mode. // This allows the publisher's run loop to periodically request an audit // status update. These updates can check for other processes attempting to // gain control over the audit sink. // This non-blocking also allows faster receipt of multi-message events. result = audit_get_reply(handle_, &reply_, GET_REPLY_NONBLOCKING, 0); if (result > 0) { switch (reply_.type) { case NLMSG_NOOP: case NLMSG_DONE: case NLMSG_ERROR: // Not handled, request another reply. break; case AUDIT_LIST_RULES: // Build rules cache. handleListRules(); break; case AUDIT_GET: // Make a copy of the status reply and store as the most-recent. if (reply_.status != nullptr) { memcpy(&status_, reply_.status, sizeof(struct audit_status)); } break; case (AUDIT_GET + 1)...(AUDIT_LIST_RULES - 1): case (AUDIT_LIST_RULES + 1)... AUDIT_LAST_USER_MSG: // Not interested in handling meta-commands and actions. break; case AUDIT_DAEMON_START... AUDIT_DAEMON_CONFIG: // 1200 - 1203 case AUDIT_CONFIG_CHANGE: handleAuditConfigChange(reply_); break; case AUDIT_SYSCALL: // 1300 // A monitored syscall was issued, most likely part of a multi-record. handle_reply = true; break; case AUDIT_CWD: // 1307 case AUDIT_PATH: // 1302 case AUDIT_EXECVE: // // 1309 (execve arguments). handle_reply = true; case AUDIT_EOE: // 1320 (multi-record event). break; default: // All other cases, pass to reply. handle_reply = true; } } else { // Fall through to the run loop cool down. break; } // Replies are 'handled' as potential events for several audit types. if (handle_reply) { auto ec = createEventContext(); // Build the event context from the reply type and parse the message. if (handleAuditReply(reply_, ec)) { fire(ec); } } }