Fwd: Re: Fw: Audit records for start/stop auditd

Steve Grubb sgrubb at redhat.com
Tue Apr 5 21:54:01 UTC 2005


Hello,

This is the discussion about meeting the CAPP requirement to log the real 
user's ID that initiated a shutdown. The core issue is that shutdown sequence 
is started by a SIGTERM. I can use sigaction to get some additional 
information delivered to the signal handler. All you get is pid. It would be 
racy to trace that back to the caller and see what their loginuid is.

Klaus proposed the following patch. Its an OK solution, but I was wanting to 
see if there are alternatives. The problems I see is that this will always 
require adding some rules, you will always have to start the audit daemon 
from the init script to make sure the pid is captured, its racy on 
termination - it waits a finite amount of time hoping the record makes it to 
disk, people may accidentally delete the rule not knowing what it does, 
there's a race getting the pid of the audit daemon - it forks starting up, it 
slows down performance because it adds a another rule the audit system has to 
evaluate each time there's a potential audit event, it occupies memory, etc.

Some other ideas I've pondered:
*adding user information to sigaction signal delivery
*having the kernel recognize kill to the audit daemon and auto generate an 
event before delivering the signal

We need some ideas to pick the best way to solve the problem.

-Steve

----------  Forwarded Message  ----------

Subject: Re: Fw: Audit records for start/stop auditd
Date: Thursday 17 March 2005 19:04
From: Klaus Weidner <klaus at atsec.com>
To: Kris Wilson <krisw at us.ibm.com>, Steve Grubb <sgrubb at redhat.com>

Hello,

I've worked around the problem in the following way - it's a bit of a
hack but I think easier than completely restructuring the code:

- dynamically add an audit rule from /etc/init.d/audit to monitor
  signals sent to the auditd pid

- change auditd to keep processing kernel messages for two seconds
  after getting the shutdown signal so that it has a chance to save
  the "signal" event record.

This is what it looks like (i386, syscall 37 is "kill"):

  type=KERNEL msg=audit(1111114589.580:4100282): syscall=37 exit=0
  a0=469d a1=f a2=469d a3=469d items=0 pid=18094 loginuid=500 uid=0 gid=0
  euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0

  type=DAEMON msg=auditd(1111114591) auditd normal halt, pid=18077, uid=0

I think this way the CAPP requirement is covered, even though it's not
pretty.

The patch contains one separate change - /etc/init.d/audit did not
actually reload the audit rules when run with the "reload" argument,
this caused me some head scratching while testing. The change adds the
reload.

-Klaus

On Thu, Mar 17, 2005 at 01:16:49PM -0600, Kris Wilson wrote:
> What needs to be done?  Here is the currrent record when auditd is stopped:
>
> type=DAEMON msg=auditd(1110848990) auditd normal halt, pid=12552, uid=0
>
> ----- Forwarded by Kris Wilson/Austin/IBM on 03/17/2005 01:14 PM -----
>
>              Steve Grubb
>              <sgrubb at redhat.co
>              m>                                                         To
>                                        Kris Wilson/Austin/IBM at IBMUS
>              03/17/2005 12:44                                           cc
>              PM
>                                                                    Subject
>                                        Re: Fw: Audit records for
>                                        start/stop auditd
>
> On Thursday 17 March 2005 13:23, you wrote:
> > Is there any way for the auditd stop record to include auid?
>
> The shutdown comes from a signal. The sigaction call can send extra
> information upon signal delivery. It has a field for the Real User ID.
> However, the audit daemon runs as root, so only root can send it a signal.
> So, I can go ahead and put root as the user that sent the shutdown
> message...however, I can't get the loginuid. That's out of reach.
>
> So, do you want me to "fake it" or leave it as is?
>
> -Steve

-------------------------------------------------------
-------------- next part --------------
diff -ur audit-0.6.8/init.d/auditd.init audit-0.6.8-kw/init.d/auditd.init
--- audit-0.6.8/init.d/auditd.init	2005-02-10 16:26:43.000000000 -0600
+++ audit-0.6.8-kw/init.d/auditd.init	2005-03-17 19:19:00.844633032 -0600
@@ -63,6 +63,10 @@
     fi
     # Load the default rules
     test -f /etc/audit.rules && /sbin/auditctl -R /etc/audit.rules >/dev/null
+
+    # Add a rule to monitor signals to auditd
+    /sbin/auditctl -a entry,always -S kill -F a0=$(pidof auditd) >/dev/null
+
     return $RETVAL
 }
 
@@ -80,6 +84,7 @@
     killproc $prog -HUP
     RETVAL=$?
     echo
+    test -f /etc/audit.rules && /sbin/auditctl -R /etc/audit.rules >/dev/null
     return $RETVAL
 }
 
diff -ur audit-0.6.8/src/auditd-event.c audit-0.6.8-kw/src/auditd-event.c
--- audit-0.6.8/src/auditd-event.c	2005-03-09 17:24:36.000000000 -0600
+++ audit-0.6.8-kw/src/auditd-event.c	2005-03-17 20:20:27.498176504 -0600
@@ -193,7 +193,7 @@
 			data->tail = NULL;
 		free(data->head);
 		data->head = next;
-		if (next == NULL && stop) {
+		if (next == NULL && stop==3) {
 			pthread_mutex_unlock(&data->queue_lock);
 			return NULL;
 		}
diff -ur audit-0.6.8/src/auditd.c audit-0.6.8-kw/src/auditd.c
--- audit-0.6.8/src/auditd.c	2005-03-08 16:15:07.000000000 -0600
+++ audit-0.6.8-kw/src/auditd.c	2005-03-17 20:55:54.454829944 -0600
@@ -41,6 +41,17 @@
 #define DMSG_SIZE 100
 
 /* Global Data */
+
+/* Stopping is done via a state machine for orderly shutdown.
+ *
+ * When receiving a stop signal, continue processing kernel messages for a few
+ * seconds so that the kill signal itself has a chance to be logged.
+ *
+ *  stop==0: normal operation
+ *  stop==1: signal received
+ *  stop==2: in grace period to handle incoming messages while shutting down
+ *  stop==3: done with grace period, exit
+ */
 volatile int stop = 0;
 
 /* Local data */
@@ -128,6 +139,7 @@
 	struct sigaction sa;
 	fd_set read_mask;
 	struct auditd_reply_list *rep = NULL;
+	time_t stop_time;
 
 	/* Get params && set mode */
 	if (argc > 2)
@@ -225,16 +237,31 @@
 			}
 		}
 		
-		/* This will pause for 30 seconds */
+		/* This will pause for 30 seconds normally, less if stopping */
 		do {
-			tv.tv_sec = 30;
-			tv.tv_usec = 0;
+			if (stop==0) {
+				tv.tv_sec = 30;
+				tv.tv_usec = 0;
+			} else if (stop==1) {
+				/*
+				 * Initialize the wait time once only,
+				 * then let it count down, to achieve a total
+				 * n-second wait.
+				 *
+				 * FIXME: This depends on the Linux select(2)
+				 * semantics, but this code is Linux specific
+				 * anyway.
+				 */
+				tv.tv_sec = 2;
+				tv.tv_usec = 0;
+				stop = 2;
+			}
 			FD_ZERO(&read_mask);
 			FD_SET(fd, &read_mask);
 			retval = select(fd+1, &read_mask, NULL, NULL, &tv);
 		} while (retval == -1 && errno == EINTR && !stop);
 
-		if (!stop && retval > 0) {
+		if (retval > 0) {
 			if (audit_get_reply(fd, &rep->reply, 
 					GET_REPLY_NONBLOCKING) > 0) {
 				switch (rep->reply.type)
@@ -252,10 +279,11 @@
 				}
 			}
 		}
-		if (stop) {
+		if (stop==2 && tv.tv_sec==0 && tv.tv_usec==0) {
 			/* Write message to log that we are going down */
 			send_audit_event("auditd normal halt");
 			free(rep);
+			stop = 3;
 			break;
 		}
 	}


More information about the Linux-audit mailing list