aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-06-21 11:22:01 -0400
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-06-21 11:22:01 -0400
commitf6a789d19858a951e7ff9e297a44b377c21b6c33 (patch)
tree5e54f1460bc048706ad6df8c5cb5bf748f067f13
parentae7b961b1c943367dfe179411f120d7bf8eaba89 (diff)
AUDIT: Spawn kernel thread to list filter rules.
If we have enough rules to fill the netlink buffer space, it'll deadlock because auditctl isn't ever actually going to read from the socket until we return, and we aren't going to return until it reads... so we spawn a kernel thread to spew out the list and then exit. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--include/linux/audit.h1
-rw-r--r--kernel/audit.c2
-rw-r--r--kernel/auditsc.c53
3 files changed, 47 insertions, 9 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 5f812e4d01e4..5d1a9dda5acb 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -281,6 +281,7 @@ extern void audit_send_reply(int pid, int seq, int type,
281 int done, int multi, 281 int done, int multi,
282 void *payload, int size); 282 void *payload, int size);
283extern void audit_log_lost(const char *message); 283extern void audit_log_lost(const char *message);
284extern struct semaphore audit_netlink_sem;
284#else 285#else
285#define audit_log(c,t,f,...) do { ; } while (0) 286#define audit_log(c,t,f,...) do { ; } while (0)
286#define audit_log_start(c,t) ({ NULL; }) 287#define audit_log_start(c,t) ({ NULL; })
diff --git a/kernel/audit.c b/kernel/audit.c
index ab6ac560cfe5..c1ab8dbbb67b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -110,7 +110,7 @@ static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
110/* The netlink socket is only to be read by 1 CPU, which lets us assume 110/* The netlink socket is only to be read by 1 CPU, which lets us assume
111 * that list additions and deletions never happen simultaneously in 111 * that list additions and deletions never happen simultaneously in
112 * auditsc.c */ 112 * auditsc.c */
113static DECLARE_MUTEX(audit_netlink_sem); 113DECLARE_MUTEX(audit_netlink_sem);
114 114
115/* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting 115/* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting
116 * audit records. Since printk uses a 1024 byte buffer, this buffer 116 * audit records. Since printk uses a 1024 byte buffer, this buffer
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 031f979019d1..cb8a44945157 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -39,6 +39,7 @@
39#include <linux/audit.h> 39#include <linux/audit.h>
40#include <linux/personality.h> 40#include <linux/personality.h>
41#include <linux/time.h> 41#include <linux/time.h>
42#include <linux/kthread.h>
42#include <asm/unistd.h> 43#include <asm/unistd.h>
43 44
44/* 0 = no checking 45/* 0 = no checking
@@ -281,24 +282,60 @@ static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
281 return 0; 282 return 0;
282} 283}
283 284
285static int audit_list_rules(void *_dest)
286{
287 int pid, seq;
288 int *dest = _dest;
289 struct audit_entry *entry;
290 int i;
291
292 pid = dest[0];
293 seq = dest[1];
294 kfree(dest);
295
296 down(&audit_netlink_sem);
297
298 /* The *_rcu iterators not needed here because we are
299 always called with audit_netlink_sem held. */
300 for (i=0; i<AUDIT_NR_FILTERS; i++) {
301 list_for_each_entry(entry, &audit_filter_list[i], list)
302 audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
303 &entry->rule, sizeof(entry->rule));
304 }
305 audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
306
307 up(&audit_netlink_sem);
308 return 0;
309}
310
284int audit_receive_filter(int type, int pid, int uid, int seq, void *data, 311int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
285 uid_t loginuid) 312 uid_t loginuid)
286{ 313{
287 struct audit_entry *entry; 314 struct audit_entry *entry;
315 struct task_struct *tsk;
316 int *dest;
288 int err = 0; 317 int err = 0;
289 int i;
290 unsigned listnr; 318 unsigned listnr;
291 319
292 switch (type) { 320 switch (type) {
293 case AUDIT_LIST: 321 case AUDIT_LIST:
294 /* The *_rcu iterators not needed here because we are 322 /* We can't just spew out the rules here because we might fill
295 always called with audit_netlink_sem held. */ 323 * the available socket buffer space and deadlock waiting for
296 for (i=0; i<AUDIT_NR_FILTERS; i++) { 324 * auditctl to read from it... which isn't ever going to
297 list_for_each_entry(entry, &audit_filter_list[i], list) 325 * happen if we're actually running in the context of auditctl
298 audit_send_reply(pid, seq, AUDIT_LIST, 0, 1, 326 * trying to _send_ the stuff */
299 &entry->rule, sizeof(entry->rule)); 327
328 dest = kmalloc(2 * sizeof(int), GFP_KERNEL);
329 if (!dest)
330 return -ENOMEM;
331 dest[0] = pid;
332 dest[1] = seq;
333
334 tsk = kthread_run(audit_list_rules, dest, "audit_list_rules");
335 if (IS_ERR(tsk)) {
336 kfree(dest);
337 err = PTR_ERR(tsk);
300 } 338 }
301 audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
302 break; 339 break;
303 case AUDIT_ADD: 340 case AUDIT_ADD:
304 if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL))) 341 if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))