[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: audit 0.9.12 released



On Thu, 2005-06-23 at 15:16 -0400, Steve Grubb wrote:
> However...I looked at the user filtering and it is not working. I think I know 
> why. netlink is an async interface. This means that the task may not be alive 
> when the user message is processed. It currently detects the and returns 
> -ESRCH, but the sender is long gone.
> 
> This means that the generic audit_filter_rules() cannot be used. You can only 
> filter based on the credentials that netlink gathered from the caller at 
> reception of message, or move the filtering to the message entry point after 
> permission checks.

Although this is never actually a problem in practice, it turns out that
to 'fix' it is actually also a cleanup of the code, because it means we
don't have to find the task by its pid. I was concerned about
duplicating audit_filter_rules() but in fact we don't have to copy much
of it because there are so few criteria we can filter on. So here
goes...

--- linux-2.6.9/include/linux/audit.h.p20054	2005-06-24 14:04:23.000000000 +0100
+++ linux-2.6.9/include/linux/audit.h	2005-06-24 14:05:17.000000000 +0100
@@ -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, u
 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)
@@ -252,7 +253,7 @@ extern int audit_filter_user(int pid, in
 #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
--- linux-2.6.9/kernel/audit.c	2005-06-24 12:41:15.000000000 +0100
+++ linux-2.6.9/kernel/audit.c	2005-06-24 12:31:13.000000000 +0100
@@ -465,7 +465,7 @@ static int audit_receive_msg(struct sk_b
 		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);
--- linux-2.6.9/kernel/auditsc.c	2005-06-24 12:41:15.000000000 +0100
+++ linux-2.6.9/kernel/auditsc.c	2005-06-24 12:41:59.000000000 +0100
@@ -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
@@ -541,35 +542,62 @@ static enum audit_state audit_filter_sys
 	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. */


-- 
dwmw2


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]