aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2008-04-18 10:02:28 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-04-28 06:19:04 -0400
commitf3d357b092956959563398b59ef2fdd10aea387d (patch)
treeb797d759fb81aa461bf0d7734e2f5be7b5e75288 /kernel
parent2532386f480eefbdd67b48be55fb4fb3e5a6081c (diff)
Audit: save audit_backlog_limit audit messages in case auditd comes back
This patch causes the kernel audit subsystem to store up to audit_backlog_limit messages for use by auditd if it ever appears sometime in the future in userspace. This is useful to collect audit messages during bootup and even when auditd is stopped. This is NOT a reliable mechanism, it does not ever call audit_panic, nor should it. audit_log_lost()/audit_panic() are called during the normal delivery mechanism. The messages are still sent to printk/syslog as usual and if too many messages appear to be queued they will be silently discarded. I liked doing it by default, but this patch only uses the queue in question if it was booted with audit=1 or if the kernel was built enabling audit by default. Signed-off-by: Eric Paris <eparis@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/audit.c102
1 files changed, 81 insertions, 21 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index ad6d1abfa1d2..fee9052eb5cf 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -126,6 +126,8 @@ static int audit_freelist_count;
126static LIST_HEAD(audit_freelist); 126static LIST_HEAD(audit_freelist);
127 127
128static struct sk_buff_head audit_skb_queue; 128static struct sk_buff_head audit_skb_queue;
129/* queue of skbs to send to auditd when/if it comes back */
130static struct sk_buff_head audit_skb_hold_queue;
129static struct task_struct *kauditd_task; 131static struct task_struct *kauditd_task;
130static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); 132static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
131static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); 133static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
@@ -347,30 +349,83 @@ static int audit_set_failure(int state, uid_t loginuid, u32 sessionid, u32 sid)
347 loginuid, sessionid, sid); 349 loginuid, sessionid, sid);
348} 350}
349 351
352/*
353 * Queue skbs to be sent to auditd when/if it comes back. These skbs should
354 * already have been sent via prink/syslog and so if these messages are dropped
355 * it is not a huge concern since we already passed the audit_log_lost()
356 * notification and stuff. This is just nice to get audit messages during
357 * boot before auditd is running or messages generated while auditd is stopped.
358 * This only holds messages is audit_default is set, aka booting with audit=1
359 * or building your kernel that way.
360 */
361static void audit_hold_skb(struct sk_buff *skb)
362{
363 if (audit_default &&
364 skb_queue_len(&audit_skb_hold_queue) < audit_backlog_limit)
365 skb_queue_tail(&audit_skb_hold_queue, skb);
366 else
367 kfree_skb(skb);
368}
369
370static void kauditd_send_skb(struct sk_buff *skb)
371{
372 int err;
373 /* take a reference in case we can't send it and we want to hold it */
374 skb_get(skb);
375 err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0);
376 if (err < 0) {
377 BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
378 printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
379 audit_log_lost("auditd dissapeared\n");
380 audit_pid = 0;
381 /* we might get lucky and get this in the next auditd */
382 audit_hold_skb(skb);
383 } else
384 /* drop the extra reference if sent ok */
385 kfree_skb(skb);
386}
387
350static int kauditd_thread(void *dummy) 388static int kauditd_thread(void *dummy)
351{ 389{
352 struct sk_buff *skb; 390 struct sk_buff *skb;
353 391
354 set_freezable(); 392 set_freezable();
355 while (!kthread_should_stop()) { 393 while (!kthread_should_stop()) {
394 /*
395 * if auditd just started drain the queue of messages already
396 * sent to syslog/printk. remember loss here is ok. we already
397 * called audit_log_lost() if it didn't go out normally. so the
398 * race between the skb_dequeue and the next check for audit_pid
399 * doesn't matter.
400 *
401 * if you ever find kauditd to be too slow we can get a perf win
402 * by doing our own locking and keeping better track if there
403 * are messages in this queue. I don't see the need now, but
404 * in 5 years when I want to play with this again I'll see this
405 * note and still have no friggin idea what i'm thinking today.
406 */
407 if (audit_default && audit_pid) {
408 skb = skb_dequeue(&audit_skb_hold_queue);
409 if (unlikely(skb)) {
410 while (skb && audit_pid) {
411 kauditd_send_skb(skb);
412 skb = skb_dequeue(&audit_skb_hold_queue);
413 }
414 }
415 }
416
356 skb = skb_dequeue(&audit_skb_queue); 417 skb = skb_dequeue(&audit_skb_queue);
357 wake_up(&audit_backlog_wait); 418 wake_up(&audit_backlog_wait);
358 if (skb) { 419 if (skb) {
359 if (audit_pid) { 420 if (audit_pid)
360 int err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0); 421 kauditd_send_skb(skb);
361 if (err < 0) { 422 else {
362 BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
363 printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
364 audit_log_lost("auditd dissapeared\n");
365 audit_pid = 0;
366 }
367 } else {
368 if (printk_ratelimit()) 423 if (printk_ratelimit())
369 printk(KERN_NOTICE "%s\n", skb->data + 424 printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0));
370 NLMSG_SPACE(0));
371 else 425 else
372 audit_log_lost("printk limit exceeded\n"); 426 audit_log_lost("printk limit exceeded\n");
373 kfree_skb(skb); 427
428 audit_hold_skb(skb);
374 } 429 }
375 } else { 430 } else {
376 DECLARE_WAITQUEUE(wait, current); 431 DECLARE_WAITQUEUE(wait, current);
@@ -885,6 +940,7 @@ static int __init audit_init(void)
885 audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; 940 audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
886 941
887 skb_queue_head_init(&audit_skb_queue); 942 skb_queue_head_init(&audit_skb_queue);
943 skb_queue_head_init(&audit_skb_hold_queue);
888 audit_initialized = 1; 944 audit_initialized = 1;
889 audit_enabled = audit_default; 945 audit_enabled = audit_default;
890 audit_ever_enabled |= !!audit_default; 946 audit_ever_enabled |= !!audit_default;
@@ -1363,19 +1419,23 @@ void audit_log_end(struct audit_buffer *ab)
1363 audit_log_lost("rate limit exceeded"); 1419 audit_log_lost("rate limit exceeded");
1364 } else { 1420 } else {
1365 struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); 1421 struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
1422 nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
1423
1366 if (audit_pid) { 1424 if (audit_pid) {
1367 nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
1368 skb_queue_tail(&audit_skb_queue, ab->skb); 1425 skb_queue_tail(&audit_skb_queue, ab->skb);
1369 ab->skb = NULL;
1370 wake_up_interruptible(&kauditd_wait); 1426 wake_up_interruptible(&kauditd_wait);
1371 } else if (nlh->nlmsg_type != AUDIT_EOE) { 1427 } else {
1372 if (printk_ratelimit()) { 1428 if (nlh->nlmsg_type != AUDIT_EOE) {
1373 printk(KERN_NOTICE "type=%d %s\n", 1429 if (printk_ratelimit()) {
1374 nlh->nlmsg_type, 1430 printk(KERN_NOTICE "type=%d %s\n",
1375 ab->skb->data + NLMSG_SPACE(0)); 1431 nlh->nlmsg_type,
1376 } else 1432 ab->skb->data + NLMSG_SPACE(0));
1377 audit_log_lost("printk limit exceeded\n"); 1433 } else
1434 audit_log_lost("printk limit exceeded\n");
1435 }
1436 audit_hold_skb(ab->skb);
1378 } 1437 }
1438 ab->skb = NULL;
1379 } 1439 }
1380 audit_buffer_free(ab); 1440 audit_buffer_free(ab);
1381} 1441}