aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-06-24 09:14:05 -0400
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-06-24 09:14:05 -0400
commit5bb289b5a0becb53ac3e1d60815ff8b779296b73 (patch)
tree0db75422d66eec857e0c05cd4cf4d014e7c0e264
parent993e2d4106e94dae6e8cfbeb32073bd12cdee203 (diff)
AUDIT: Clean up user message filtering
Don't look up the task by its pid and then use the syscall filtering helper. Just implement our own filter helper which operates solely on the information in the netlink_skb_parms. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--include/linux/audit.h5
-rw-r--r--kernel/audit.c2
-rw-r--r--kernel/auditsc.c56
3 files changed, 46 insertions, 17 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 2f56546eb248..38999f827a36 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -205,6 +205,7 @@ struct audit_sig_info {
205struct audit_buffer; 205struct audit_buffer;
206struct audit_context; 206struct audit_context;
207struct inode; 207struct inode;
208struct netlink_skb_parms;
208 209
209#define AUDITSC_INVALID 0 210#define AUDITSC_INVALID 0
210#define AUDITSC_SUCCESS 1 211#define AUDITSC_SUCCESS 1
@@ -236,7 +237,7 @@ extern int audit_socketcall(int nargs, unsigned long *args);
236extern int audit_sockaddr(int len, void *addr); 237extern int audit_sockaddr(int len, void *addr);
237extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); 238extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
238extern void audit_signal_info(int sig, struct task_struct *t); 239extern void audit_signal_info(int sig, struct task_struct *t);
239extern int audit_filter_user(int pid, int type); 240extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
240#else 241#else
241#define audit_alloc(t) ({ 0; }) 242#define audit_alloc(t) ({ 0; })
242#define audit_free(t) do { ; } while (0) 243#define audit_free(t) do { ; } while (0)
@@ -253,7 +254,7 @@ extern int audit_filter_user(int pid, int type);
253#define audit_sockaddr(len, addr) ({ 0; }) 254#define audit_sockaddr(len, addr) ({ 0; })
254#define audit_avc_path(dentry, mnt) ({ 0; }) 255#define audit_avc_path(dentry, mnt) ({ 0; })
255#define audit_signal_info(s,t) do { ; } while (0) 256#define audit_signal_info(s,t) do { ; } while (0)
256#define audit_filter_user(p,t) ({ 1; }) 257#define audit_filter_user(cb,t) ({ 1; })
257#endif 258#endif
258 259
259#ifdef CONFIG_AUDIT 260#ifdef CONFIG_AUDIT
diff --git a/kernel/audit.c b/kernel/audit.c
index 9af947a63ed1..6f1784dd80af 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -434,7 +434,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
434 if (!audit_enabled && msg_type != AUDIT_USER_AVC) 434 if (!audit_enabled && msg_type != AUDIT_USER_AVC)
435 return 0; 435 return 0;
436 436
437 err = audit_filter_user(pid, msg_type); 437 err = audit_filter_user(&NETLINK_CB(skb), msg_type);
438 if (err == 1) { 438 if (err == 1) {
439 err = 0; 439 err = 0;
440 ab = audit_log_start(NULL, GFP_KERNEL, msg_type); 440 ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 7b123f0a9481..34a990223c9e 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -40,6 +40,7 @@
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 <linux/kthread.h>
43#include <linux/netlink.h>
43#include <asm/unistd.h> 44#include <asm/unistd.h>
44 45
45/* 0 = no checking 46/* 0 = no checking
@@ -530,35 +531,62 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
530 return AUDIT_BUILD_CONTEXT; 531 return AUDIT_BUILD_CONTEXT;
531} 532}
532 533
533int audit_filter_user(int pid, int type) 534static int audit_filter_user_rules(struct netlink_skb_parms *cb,
535 struct audit_rule *rule,
536 enum audit_state *state)
537{
538 int i;
539
540 for (i = 0; i < rule->field_count; i++) {
541 u32 field = rule->fields[i] & ~AUDIT_NEGATE;
542 u32 value = rule->values[i];
543 int result = 0;
544
545 switch (field) {
546 case AUDIT_PID:
547 result = (cb->creds.pid == value);
548 break;
549 case AUDIT_UID:
550 result = (cb->creds.uid == value);
551 break;
552 case AUDIT_GID:
553 result = (cb->creds.gid == value);
554 break;
555 case AUDIT_LOGINUID:
556 result = (cb->loginuid == value);
557 break;
558 }
559
560 if (rule->fields[i] & AUDIT_NEGATE)
561 result = !result;
562 if (!result)
563 return 0;
564 }
565 switch (rule->action) {
566 case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
567 case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT; break;
568 case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
569 }
570 return 1;
571}
572
573int audit_filter_user(struct netlink_skb_parms *cb, int type)
534{ 574{
535 struct task_struct *tsk;
536 struct audit_entry *e; 575 struct audit_entry *e;
537 enum audit_state state; 576 enum audit_state state;
538 int ret = 1; 577 int ret = 1;
539 578
540 read_lock(&tasklist_lock);
541 tsk = find_task_by_pid(pid);
542 if (tsk)
543 get_task_struct(tsk);
544 read_unlock(&tasklist_lock);
545
546 if (!tsk)
547 return -ESRCH;
548
549 rcu_read_lock(); 579 rcu_read_lock();
550 list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { 580 list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
551 if (audit_filter_rules(tsk, &e->rule, NULL, &state)) { 581 if (audit_filter_user_rules(cb, &e->rule, &state)) {
552 if (state == AUDIT_DISABLED) 582 if (state == AUDIT_DISABLED)
553 ret = 0; 583 ret = 0;
554 break; 584 break;
555 } 585 }
556 } 586 }
557 rcu_read_unlock(); 587 rcu_read_unlock();
558 put_task_struct(tsk);
559 588
560 return ret; /* Audit by default */ 589 return ret; /* Audit by default */
561
562} 590}
563 591
564/* This should be called with task_lock() held. */ 592/* This should be called with task_lock() held. */