diff options
-rw-r--r-- | include/linux/audit.h | 1 | ||||
-rw-r--r-- | kernel/audit.c | 2 | ||||
-rw-r--r-- | kernel/auditsc.c | 53 |
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); |
283 | extern void audit_log_lost(const char *message); | 283 | extern void audit_log_lost(const char *message); |
284 | extern 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 */ |
113 | static DECLARE_MUTEX(audit_netlink_sem); | 113 | DECLARE_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 | ||
285 | static 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 | |||
284 | int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | 311 | int 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))) |