diff options
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 53 |
1 files changed, 45 insertions, 8 deletions
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))) |