diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit.c | 2 | ||||
-rw-r--r-- | kernel/auditsc.c | 56 |
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. */ |