summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-06-24 14:14:05 +0100
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-06-24 14:14:05 +0100
commit5bb289b5a0becb53ac3e1d60815ff8b779296b73 (patch)
tree0db75422d66eec857e0c05cd4cf4d014e7c0e264 /kernel
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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/audit.c2
-rw-r--r--kernel/auditsc.c56
2 files changed, 43 insertions, 15 deletions
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)
if (!audit_enabled && msg_type != AUDIT_USER_AVC)
return 0;
- err = audit_filter_user(pid, msg_type);
+ err = audit_filter_user(&NETLINK_CB(skb), msg_type);
if (err == 1) {
err = 0;
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 @@
#include <linux/personality.h>
#include <linux/time.h>
#include <linux/kthread.h>
+#include <linux/netlink.h>
#include <asm/unistd.h>
/* 0 = no checking
@@ -530,35 +531,62 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
return AUDIT_BUILD_CONTEXT;
}
-int audit_filter_user(int pid, int type)
+static int audit_filter_user_rules(struct netlink_skb_parms *cb,
+ struct audit_rule *rule,
+ enum audit_state *state)
+{
+ int i;
+
+ for (i = 0; i < rule->field_count; i++) {
+ u32 field = rule->fields[i] & ~AUDIT_NEGATE;
+ u32 value = rule->values[i];
+ int result = 0;
+
+ switch (field) {
+ case AUDIT_PID:
+ result = (cb->creds.pid == value);
+ break;
+ case AUDIT_UID:
+ result = (cb->creds.uid == value);
+ break;
+ case AUDIT_GID:
+ result = (cb->creds.gid == value);
+ break;
+ case AUDIT_LOGINUID:
+ result = (cb->loginuid == value);
+ break;
+ }
+
+ if (rule->fields[i] & AUDIT_NEGATE)
+ result = !result;
+ if (!result)
+ return 0;
+ }
+ switch (rule->action) {
+ case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
+ case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT; break;
+ case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
+ }
+ return 1;
+}
+
+int audit_filter_user(struct netlink_skb_parms *cb, int type)
{
- struct task_struct *tsk;
struct audit_entry *e;
enum audit_state state;
int ret = 1;
- read_lock(&tasklist_lock);
- tsk = find_task_by_pid(pid);
- if (tsk)
- get_task_struct(tsk);
- read_unlock(&tasklist_lock);
-
- if (!tsk)
- return -ESRCH;
-
rcu_read_lock();
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
- if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+ if (audit_filter_user_rules(cb, &e->rule, &state)) {
if (state == AUDIT_DISABLED)
ret = 0;
break;
}
}
rcu_read_unlock();
- put_task_struct(tsk);
return ret; /* Audit by default */
-
}
/* This should be called with task_lock() held. */