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

audit.59 kernel



Uploading now, patch attached.

* Fri Jun 17 2005 David Woodhouse <dwmw2 redhat com> audit.59
- Add filters for user messages and watches

* Fri Jun 17 2005 David Woodhouse <dwmw2 redhat com> audit.58
- Fix auditfs error handling, memory leak, watch removal (Tim)

-- 
dwmw2

--- linux-2.6.9/./include/linux/audit.h~	2005-06-17 15:19:09.000000000 +0100
+++ linux-2.6.9/./include/linux/audit.h	2005-06-17 16:40:47.000000000 +0100
@@ -84,10 +84,15 @@ struct atomic_t;
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
 /* Rule flags */
-#define AUDIT_PER_TASK 0x01	/* Apply rule at task creation (not syscall) */
-#define AUDIT_AT_ENTRY 0x02	/* Apply rule at syscall entry */
-#define AUDIT_AT_EXIT  0x04	/* Apply rule at syscall exit */
-#define AUDIT_PREPEND  0x10	/* Prepend to front of list */
+#define AUDIT_FILTER_USER	0x00	/* Apply rule to user-generated messages */
+#define AUDIT_FILTER_TASK	0x01	/* Apply rule at task creation (not syscall) */
+#define AUDIT_FILTER_ENTRY	0x02	/* Apply rule at syscall entry */
+#define AUDIT_FILTER_WATCH	0x03	/* Apply rule to file system watches */
+#define AUDIT_FILTER_EXIT	0x04	/* Apply rule at syscall exit */
+
+#define AUDIT_NR_FILTERS	5
+
+#define AUDIT_FILTER_PREPEND	0x10	/* Prepend to front of list */
 
 /* Rule actions */
 #define AUDIT_NEVER    0	/* Do not build context if rule matches */
@@ -281,6 +286,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(struct task_struct *tsk, int type);
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
@@ -297,6 +303,7 @@ extern void audit_signal_info(int sig, s
 #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(struct ({ 1; })
 #endif
 
 #ifdef CONFIG_AUDITFILESYSTEM
--- linux-2.6.9/./kernel/audit.c~	2005-06-07 14:42:12.000000000 +0100
+++ linux-2.6.9/./kernel/audit.c	2005-06-17 16:47:40.000000000 +0100
@@ -107,13 +107,6 @@ static struct sk_buff_head audit_skb_que
 static struct task_struct *kauditd_task;
 static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
 
-/* There are three lists of rules -- one to search at task creation
- * time, one to search at syscall entry time, and another to search at
- * syscall exit time. */
-static LIST_HEAD(audit_tsklist);
-static LIST_HEAD(audit_entlist);
-static LIST_HEAD(audit_extlist);
-
 /* The netlink socket is only to be read by 1 CPU, which lets us assume
  * that list additions and deletions, and watch insertions never happen
  * simultaneiously in auditsc.c and auditfs.c respectively.
@@ -385,6 +378,7 @@ static int audit_receive_msg(struct sk_b
 	u16			msg_type = nlh->nlmsg_type;
 	uid_t			loginuid; /* loginuid of sender */
 	struct audit_sig_info   sig_data;
+	struct task_struct *tsk;
 
 	err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
 	if (err)
@@ -444,15 +438,25 @@ static int audit_receive_msg(struct sk_b
 		break;
 	case AUDIT_USER:
 	case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
-		ab = audit_log_start(NULL, msg_type);
-		if (!ab)
-			break;	/* audit_panic has been called */
-		audit_log_format(ab,
-				 "user pid=%d uid=%u auid=%u"
-				 " msg='%.1024s'",
-				 pid, uid, loginuid, (char *)data);
-		audit_set_pid(ab, pid);
-		audit_log_end(ab);
+		read_lock(&tasklist_lock);
+		tsk = find_task_by_pid(pid);
+		if (tsk)
+			get_task_struct(tsk);
+		read_unlock(&tasklist_lock);
+		if (!tsk)
+			return -ESRCH;
+
+		if (audit_filter_user(tsk, msg_type)) {
+			    ab = audit_log_start(NULL, msg_type);
+			    if (ab) {
+				    audit_log_format(ab,
+						     "user pid=%d uid=%u auid=%u msg='%.1024s'",
+						     pid, uid, loginuid, (char *)data);
+				    audit_set_pid(ab, pid);
+				    audit_log_end(ab);
+			    }
+		}
+		put_task_struct(tsk);
 		break;
 	case AUDIT_ADD:
 	case AUDIT_DEL:
--- linux-2.6.9/./kernel/auditsc.c~	2005-06-17 15:19:09.000000000 +0100
+++ linux-2.6.9/./kernel/auditsc.c	2005-06-17 17:32:47.000000000 +0100
@@ -176,9 +176,16 @@ struct audit_context {
 /* There are three lists of rules -- one to search at task creation
  * time, one to search at syscall entry time, and another to search at
  * syscall exit time. */
-static LIST_HEAD(audit_tsklist);
-static LIST_HEAD(audit_entlist);
-static LIST_HEAD(audit_extlist);
+static struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
+	LIST_HEAD_INIT(audit_filter_list[0]),
+	LIST_HEAD_INIT(audit_filter_list[1]),
+	LIST_HEAD_INIT(audit_filter_list[2]),
+	LIST_HEAD_INIT(audit_filter_list[3]),
+	LIST_HEAD_INIT(audit_filter_list[4]),
+#if AUDIT_NR_FILTERS != 5
+#error Fix audit_filter_list initialiser
+#endif
+};
 
 struct audit_entry {
 	struct list_head  list;
@@ -219,16 +226,15 @@ static int audit_compare_rule(struct aud
 /* Note that audit_add_rule and audit_del_rule are called via
  * audit_receive() in audit.c, and are protected by
  * audit_netlink_sem. */
-static inline int audit_add_rule(struct audit_entry *entry,
-				 struct list_head *list)
+static inline void audit_add_rule(struct audit_entry *entry,
+				  struct list_head *list)
 {
-	if (entry->rule.flags & AUDIT_PREPEND) {
-		entry->rule.flags &= ~AUDIT_PREPEND;
+	if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
+		entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
 		list_add_rcu(&entry->list, list);
 	} else {
 		list_add_tail_rcu(&entry->list, list);
 	}
-	return 0;
 }
 
 static void audit_free_rule(struct rcu_head *head)
@@ -254,7 +260,7 @@ static inline int audit_del_rule(struct 
 			return 0;
 		}
 	}
-	return -EFAULT;		/* No matching rule */
+	return -ENOENT;		/* No matching rule */
 }
 
 #ifdef CONFIG_NET
@@ -270,6 +276,8 @@ static int audit_copy_rule(struct audit_
 		return -1;
 	if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
 		return -1;
+	if ((s->flags & ~AUDIT_FILTER_PREPEND) >= AUDIT_NR_FILTERS)
+		return -1;
 
 	d->flags	= s->flags;
 	d->action	= s->action;
@@ -285,23 +293,20 @@ static int audit_copy_rule(struct audit_
 int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
 							uid_t loginuid)
 {
-	u32		   flags;
 	struct audit_entry *entry;
 	int		   err = 0;
+	int i;
+	unsigned listnr;
 
 	switch (type) {
 	case AUDIT_LIST:
 		/* The *_rcu iterators not needed here because we are
 		   always called with audit_netlink_sem held. */
-		list_for_each_entry(entry, &audit_tsklist, list)
-			audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
-					 &entry->rule, sizeof(entry->rule));
-		list_for_each_entry(entry, &audit_entlist, list)
-			audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
-					 &entry->rule, sizeof(entry->rule));
-		list_for_each_entry(entry, &audit_extlist, list)
-			audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
-					 &entry->rule, sizeof(entry->rule));
+		for (i=0; i<AUDIT_NR_FILTERS; i++) {
+			list_for_each_entry(entry, &audit_filter_list[i], list)
+				audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
+						 &entry->rule, sizeof(entry->rule));
+		}
 		audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
 		break;
 	case AUDIT_ADD:
@@ -311,26 +316,20 @@ int audit_receive_filter(int type, int p
 			kfree(entry);
 			return -EINVAL;
 		}
-		flags = entry->rule.flags;
-		if (!err && (flags & AUDIT_PER_TASK))
-			err = audit_add_rule(entry, &audit_tsklist);
-		if (!err && (flags & AUDIT_AT_ENTRY))
-			err = audit_add_rule(entry, &audit_entlist);
-		if (!err && (flags & AUDIT_AT_EXIT))
-			err = audit_add_rule(entry, &audit_extlist);
+		listnr = entry->rule.flags & ~AUDIT_FILTER_PREPEND;
+		audit_add_rule(entry, &audit_filter_list[listnr]);
 		audit_log(NULL, AUDIT_CONFIG_CHANGE, 
 				"auid=%u added an audit rule\n", loginuid);
 		break;
 	case AUDIT_DEL:
-		flags =((struct audit_rule *)data)->flags;
-		if (!err && (flags & AUDIT_PER_TASK))
-			err = audit_del_rule(data, &audit_tsklist);
-		if (!err && (flags & AUDIT_AT_ENTRY))
-			err = audit_del_rule(data, &audit_entlist);
-		if (!err && (flags & AUDIT_AT_EXIT))
-			err = audit_del_rule(data, &audit_extlist);
-		audit_log(NULL, AUDIT_CONFIG_CHANGE,
-				"auid=%u removed an audit rule\n", loginuid);
+		listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
+		if (listnr >= AUDIT_NR_FILTERS)
+			return -EINVAL;
+
+		err = audit_del_rule(data, &audit_filter_list[listnr]);
+		if (!err)
+			audit_log(NULL, AUDIT_CONFIG_CHANGE,
+				  "auid=%u removed an audit rule\n", loginuid);
 		break;
 	default:
 		return -EINVAL;
@@ -465,7 +464,7 @@ static enum audit_state audit_filter_tas
 	enum audit_state   state;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(e, &audit_tsklist, list) {
+	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
 		if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
 			rcu_read_unlock();
 			return state;
@@ -501,6 +500,23 @@ static enum audit_state audit_filter_sys
 	return AUDIT_BUILD_CONTEXT;
 }
 
+int audit_filter_user(struct task_struct *tsk, int type)
+{
+	struct audit_entry *e;
+	enum audit_state   state;
+
+	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)) {
+			rcu_read_unlock();
+			return state != AUDIT_DISABLED;
+		}
+	}
+	rcu_read_unlock();
+	return 1; /* Audit by default */
+
+}
+
 /* This should be called with task_lock() held. */
 static inline struct audit_context *audit_get_context(struct task_struct *tsk,
 						      int return_valid,
@@ -515,7 +531,7 @@ static inline struct audit_context *audi
 
 	if (context->in_syscall && !context->auditable) {
 		enum audit_state state;
-		state = audit_filter_syscall(tsk, context, &audit_extlist);
+		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
 		if (state == AUDIT_RECORD_CONTEXT)
 			context->auditable = 1;
 	}
@@ -924,7 +940,7 @@ void audit_syscall_entry(struct task_str
 
 	state = context->state;
 	if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)
-		state = audit_filter_syscall(tsk, context, &audit_entlist);
+		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);
 	if (likely(state == AUDIT_DISABLED))
 		return;
 
@@ -1228,8 +1244,10 @@ int auditfs_attach_wdata(struct inode *i
 	if (!ax)
 		return -ENOMEM;
 
-	if (context->in_syscall && !context->auditable)
-		context->auditable = 1;
+	if (context->in_syscall && !context->auditable &&
+		 AUDIT_DISABLED != audit_filter_syscall(current, context,
+							&audit_filter_list[AUDIT_FILTER_WATCH]))
+		 context->auditable = 1;
 
 	INIT_HLIST_HEAD(&ax->watches);
 

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