55#include < signal.h>
66#include < sys/mman.h>
77#include < sys/resource.h>
8+ #include < sys/socket.h>
89#include < unistd.h>
910
1011#include < algorithm>
1718#include < utility>
1819#include < vector>
1920
21+ #include < linux/audit.h>
22+ #include < linux/netlink.h>
23+
24+ constexpr int NETLINK_BUF_SIZE = 4096 ;
25+
26+ ssize_t ReceiveNetlinkMessage (int fd, void * buf, size_t len)
27+ {
28+ return recv (fd, buf, len, 0 );
29+ }
30+
31+ ssize_t SendNetlinkMessage (int fd, const void * buf, size_t len)
32+ {
33+ return send (fd, buf, len, 0 );
34+ }
35+
2036inline std::ostream& operator <<(std::ostream& ss, const rpc::ExecRequestRawT& req)
2137{
2238 return ss << " id=" << req.id
@@ -109,7 +125,7 @@ class Proc
109125{
110126public:
111127 Proc (Connection& conn, const char * bin, ProcIDPool& proc_id_pool, int & restarting, const bool & corpus_triaged, int max_signal_fd,
112- int cover_filter_fd, ProcOpts opts)
128+ int cover_filter_fd, ProcOpts opts, int audit_sock )
113129 : conn_(conn),
114130 bin_ (bin),
115131 proc_id_pool_(proc_id_pool),
@@ -121,7 +137,8 @@ class Proc
121137 opts_(opts),
122138 req_shmem_(kMaxInput ),
123139 resp_shmem_(kMaxOutput ),
124- resp_mem_(static_cast <OutputData*>(resp_shmem_.Mem()))
140+ resp_mem_(static_cast <OutputData*>(resp_shmem_.Mem())),
141+ audit_sock_(audit_sock)
125142 {
126143 Start ();
127144 }
@@ -237,6 +254,7 @@ class Proc
237254 uint64 exec_start_ = 0 ;
238255 uint64 wait_start_ = 0 ;
239256 uint64 wait_end_ = 0 ;
257+ int audit_sock_ = 0 ;
240258
241259 friend std::ostream& operator <<(std::ostream& ss, const Proc& proc)
242260 {
@@ -251,6 +269,63 @@ class Proc
251269 return ss;
252270 }
253271
272+ ssize_t SendUserAuditMessage (const std::string_view message_text) {
273+ const size_t payload_len = message_text.length () + 1 ;
274+ const size_t buf_len = NLMSG_SPACE (payload_len);
275+ std::vector<char > buf (buf_len);
276+ memset (buf.data (), 0 , buf_len);
277+
278+ auto * nlh = reinterpret_cast <struct nlmsghdr *>(buf.data ());
279+ nlh->nlmsg_len = NLMSG_LENGTH ((int )payload_len);
280+ nlh->nlmsg_type = AUDIT_USER_AVC;
281+ nlh->nlmsg_flags = NLM_F_REQUEST;
282+
283+ char * data = static_cast <char *>(NLMSG_DATA (nlh));
284+ strncpy (data, message_text.data (), payload_len);
285+ return SendNetlinkMessage (audit_sock_, nlh, nlh->nlmsg_len );
286+ }
287+
288+ void drainAuditBacklog (std::vector<uint8_t >* output)
289+ {
290+ bool prefixed = false ;
291+ ssize_t slen = 0 ;
292+ char buf[NETLINK_BUF_SIZE];
293+ struct nlmsghdr * header;
294+
295+ if (SendUserAuditMessage (" PROC END" ) < 0 )
296+ return ;
297+
298+ // Drain the audit backlog until there is no other message
299+ do {
300+ slen = ReceiveNetlinkMessage (audit_sock_, buf, sizeof (buf));
301+ if (errno == EINTR) {
302+ continue ;
303+ }
304+ if (slen < NLMSG_LENGTH (0 )) {
305+ fprintf (stderr, " audit: message too short\n " );
306+ continue ;
307+ }
308+ header = (struct nlmsghdr *)buf;
309+ if (header->nlmsg_type != AUDIT_AVC && header->nlmsg_type != AUDIT_USER_AVC) {
310+ continue ;
311+ }
312+ if (header->nlmsg_type == AUDIT_AVC) {
313+ if (!prefixed) {
314+ char tmp[128 ];
315+ // Add prefix to the audit messages.
316+ snprintf (tmp, sizeof (tmp), " \n Audit messages:\n " );
317+ output->insert (output->end (), tmp, tmp + strlen (tmp));
318+ prefixed = true ;
319+ }
320+ std::string message ((char *)NLMSG_DATA (header),
321+ (char *)NLMSG_DATA (header) +
322+ (slen - sizeof (*header)));
323+ message.append (" \n " );
324+ output->insert (output->end (), message.c_str (), message.c_str () + strlen (message.c_str ()));
325+ }
326+ } while (header->nlmsg_type != AUDIT_USER_AVC);
327+ }
328+
254329 void ChangeState (State state)
255330 {
256331 if (state_ == State::Handshaking)
@@ -454,6 +529,10 @@ class Proc
454529 output_.insert (output_.end (), tmp, tmp + strlen (tmp));
455530 }
456531 }
532+ if (IsSet (msg_->flags , rpc::RequestFlag::ReturnAudit)) {
533+ output = &output_;
534+ drainAuditBacklog (output);
535+ }
457536 uint32 num_calls = 0 ;
458537 if (msg_->type == rpc::RequestType::Program)
459538 num_calls = read_input (&prog_data);
@@ -556,9 +635,13 @@ class Runner
556635 proc_id_pool_.emplace (num_procs);
557636 int max_signal_fd = max_signal_ ? max_signal_->FD () : -1 ;
558637 int cover_filter_fd = cover_filter_ ? cover_filter_->FD () : -1 ;
638+ int audit_sock = 0 ;
639+ if (audit) {
640+ audit_sock = registerForAudit ();
641+ }
559642 for (int i = 0 ; i < num_procs; i++)
560643 procs_.emplace_back (new Proc (conn, bin, *proc_id_pool_, restarting_, corpus_triaged_,
561- max_signal_fd, cover_filter_fd, proc_opts_));
644+ max_signal_fd, cover_filter_fd, proc_opts_, audit_sock ));
562645
563646 for (;;)
564647 Loop ();
@@ -574,6 +657,7 @@ class Runner
574657 std::deque<rpc::ExecRequestRawT> requests_;
575658 std::vector<std::string> leak_frames_;
576659 int restarting_ = 0 ;
660+ bool audit = false ;
577661 bool corpus_triaged_ = false ;
578662 ProcOpts proc_opts_{};
579663
@@ -595,6 +679,71 @@ class Runner
595679 return ss;
596680 }
597681
682+ // Helper function to open a Netlink socket for Audit
683+ int OpenNetlinkAuditSocket ()
684+ {
685+ return socket (AF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
686+ }
687+
688+ int registerForAudit ()
689+ {
690+ struct {
691+ struct nlmsghdr nlh;
692+ struct audit_status status;
693+ } req;
694+ memset (&req, 0 , sizeof (req));
695+
696+ int fd = OpenNetlinkAuditSocket ();
697+ if (fd < 0 ) {
698+ return -1 ;
699+ }
700+
701+ req.nlh .nlmsg_len = NLMSG_LENGTH (sizeof (struct audit_status ));
702+ req.nlh .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
703+ req.nlh .nlmsg_seq = 1 ;
704+ req.nlh .nlmsg_type = AUDIT_SET;
705+ req.status .pid = getpid ();
706+ req.status .backlog_limit = 0 ;
707+ req.status .rate_limit = 0 ;
708+ req.status .backlog_wait_time = 0 ;
709+ req.status .mask = AUDIT_STATUS_PID | AUDIT_STATUS_BACKLOG_LIMIT | AUDIT_STATUS_RATE_LIMIT | AUDIT_STATUS_BACKLOG_WAIT_TIME;
710+
711+ ssize_t sent = SendNetlinkMessage (fd, &req, req.nlh .nlmsg_len );
712+ if (sent != req.nlh .nlmsg_len ) {
713+ close (fd);
714+ return -1 ;
715+ }
716+
717+ ssize_t slen = 0 ;
718+ char buf[NETLINK_BUF_SIZE];
719+ struct nlmsghdr * header;
720+ do {
721+ slen = ReceiveNetlinkMessage (fd, buf, sizeof (buf));
722+ if (errno == EAGAIN || errno == EINTR) {
723+ continue ;
724+ }
725+ if (slen < NLMSG_LENGTH (0 )) {
726+ fprintf (stderr, " audit: message too short\n " );
727+ continue ;
728+ }
729+ header = (struct nlmsghdr *)buf;
730+ } while (header->nlmsg_type != NLMSG_ERROR);
731+
732+ struct nlmsgerr * err;
733+ if ((size_t )slen < NLMSG_LENGTH (sizeof (*err))) {
734+ fprintf (stderr, " audit_listener: error message too short\n " );
735+ close (fd);
736+ return -1 ;
737+ }
738+ err = (struct nlmsgerr *)NLMSG_DATA (header);
739+ if (err->error != 0 ) {
740+ fprintf (stderr, " audit_listener: received error %d\n " , -err->error );
741+ close (fd);
742+ return -1 ;
743+ }
744+ return fd;
745+ }
746+
598747 void Loop ()
599748 {
600749 Select select;
@@ -661,6 +810,12 @@ class Runner
661810 conn_.Recv (conn_reply);
662811 if (conn_reply.debug )
663812 flag_debug = true ;
813+ if (conn_reply.audit ) {
814+ if (conn_reply.procs > 1 )
815+ debug (" audit only supported with one proc" );
816+ audit = conn_reply.procs == 1 ;
817+ }
818+
664819 debug (" connected to manager: procs=%d cover_edges=%d kernel_64_bit=%d slowdown=%d syscall_timeout=%u"
665820 " program_timeout=%u features=0x%llx\n " ,
666821 conn_reply.procs , conn_reply.cover_edges , conn_reply.kernel_64_bit ,
0 commit comments