summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 {
struct audit_buffer;
struct audit_context;
struct inode;
+struct netlink_skb_parms;
#define AUDITSC_INVALID 0
#define AUDITSC_SUCCESS 1
@@ -236,7 +237,7 @@ extern int audit_socketcall(int nargs, unsigned long *args);
extern int audit_sockaddr(int len, void *addr);
extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
extern void audit_signal_info(int sig, struct task_struct *t);
-extern int audit_filter_user(int pid, int type);
+extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
@@ -253,7 +254,7 @@ extern int audit_filter_user(int pid, int type);
#define audit_sockaddr(len, addr) ({ 0; })
#define audit_avc_path(dentry, mnt) ({ 0; })
#define audit_signal_info(s,t) do { ; } while (0)
-#define audit_filter_user(p,t) ({ 1; })
+#define audit_filter_user(cb,t) ({ 1; })
#endif
#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)
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. */