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