Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Aug 2008 03:23:53 GMT
From:      Diego Giagio <diego@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 147626 for review
Message-ID:  <200808170323.m7H3Nrpe032034@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=147626

Change 147626 by diego@diego_black on 2008/08/17 03:23:45

	Many many changes, including:
	
	- Add audit_pfil_enter and audit_pfil_exit like their syscall
	  equivalents.
	- Add support for creating records inside locks and by ithreads by
	  preallocating records using M_NOWAIT
	- Add support for network statefull records (flow records) on ipfw
	- Add support for nested record generation, specially usefull on
	  ithreads context.
	- Improve admin records generation.
	- We don't need audit_pfil.c anymore, remove it.
	- We don't need AUDIT_CALL macro anymore, remove it.
	- More to come.

Affected files ...

.. //depot/projects/soc2008/diego-audit/src/sys/conf/files#8 edit
.. //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw.h#4 edit
.. //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw2.c#7 edit
.. //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw_pfil.c#4 edit
.. //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit.c#7 edit
.. //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit_private.h#5 edit
.. //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit_syscalls.c#2 edit

Differences ...

==== //depot/projects/soc2008/diego-audit/src/sys/conf/files#8 (text+ko) ====

@@ -2115,7 +2115,6 @@
 security/audit/audit_bsm.c	optional audit
 security/audit/audit_bsm_klib.c	optional audit
 security/audit/audit_bsm_token.c	optional audit
-security/audit/audit_pfil.c	optional audit
 security/audit/audit_pipe.c	optional audit
 security/audit/audit_syscalls.c	standard
 security/audit/audit_trigger.c	optional audit

==== //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw.h#4 (text+ko) ====

@@ -102,6 +102,7 @@
 
 	O_PROBE_STATE,		/* none				*/
 	O_KEEP_STATE,		/* none				*/
+	//O_AUDIT,		/* none				*/
 	O_LIMIT,		/* ipfw_insn_limit		*/
 	O_LIMIT_PARENT,		/* dyn_type, not an opcode.	*/
 

==== //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw2.c#7 (text+ko) ====

@@ -104,6 +104,8 @@
 
 #include <machine/in_cksum.h>	/* XXX for in_cksum */
 
+#include <bsm/audit_kevents.h>
+
 #include <security/audit/audit.h>
 #include <security/mac/mac_framework.h>
 
@@ -1036,27 +1038,57 @@
 	return i;
 }
 
+static void
+addr_port_to_sin(u_int32_t addr, u_int16_t port, struct sockaddr_in *sin)
+{
+	sin->sin_len = sizeof(struct sockaddr_in);
+	sin->sin_family = PF_INET;
+	sin->sin_port = port;
+	sin->sin_addr.s_addr = addr;
+}
+
 /**
  * unlink a dynamic rule from a chain. prev is a pointer to
  * the previous one, q is a pointer to the rule to delete,
  * head is a pointer to the head of the queue.
  * Modifies q and potentially also head.
  */
-#define UNLINK_DYN_RULE(prev, head, q) {				\
+#define UNLINK_DYN_RULE(prev, head, q)					\
+{									\
 	ipfw_dyn_rule *old_q = q;					\
+	struct ipfw_flow_id *id = &q->id;				\
+	struct thread *td = curthread;					\
+	struct sockaddr_in lsin;					\
+	struct sockaddr_in rsin;					\
+	int error = 0;							\
 									\
 	/* remove a refcount to the parent */				\
 	if (q->dyn_type == O_LIMIT)					\
 		q->parent->count--;					\
-	DEB(printf("ipfw: unlink entry 0x%08x %d -> 0x%08x %d, %d left\n",\
-		(q->id.src_ip), (q->id.src_port),			\
-		(q->id.dst_ip), (q->id.dst_port), dyn_count-1 ); )	\
-	if (prev != NULL)						\
-		prev->next = q = q->next;				\
-	else								\
-		head = q = q->next;					\
-	dyn_count--;							\
-	uma_zfree(ipfw_dyn_rule_zone, old_q); }
+	/*if (q->dyn_type == O_AUDIT) {	*/				\
+		AUDIT_PFIL_ENTER(AUE_PFIL_FLOW_END, td, error);		\
+		if (error == 0) {					\
+			AUDIT_ARG(text, "ipfw");			\
+			addr_port_to_sin(id->src_ip, id->src_port, &lsin);   \
+			addr_port_to_sin(id->dst_ip, id->dst_port, &rsin);   \
+			AUDIT_ARG(socket_ex, AF_INET, SOCK_STREAM,	     \
+		    	(struct sockaddr *)&lsin, (struct sockaddr *)&rsin); \
+		}							\
+	/*}*/								\
+	if (!error) {							\
+		DEB(printf(						\
+		    "ipfw: unlink entry 0x%08x %d -> 0x%08x %d, %d left\n", \
+		    (q->id.src_ip), (q->id.src_port),			\
+		    (q->id.dst_ip), (q->id.dst_port), dyn_count-1 );) 	\
+		if (prev != NULL)					\
+		    prev->next = q = q->next;				\
+		else							\
+		    head = q = q->next;					\
+		dyn_count--;						\
+		uma_zfree(ipfw_dyn_rule_zone, old_q);			\
+	}								\
+	AUDIT_PFIL_EXIT(error, td);					\
+}									\
 
 #define TIME_LEQ(a,b)       ((int)((a)-(b)) <= 0)
 
@@ -1153,6 +1185,7 @@
 #define MATCH_FORWARD	1
 #define MATCH_NONE	2
 #define MATCH_UNKNOWN	3
+
 	int i, dir = MATCH_NONE;
 	ipfw_dyn_rule *prev, *q=NULL;
 
@@ -1224,21 +1257,13 @@
 #define BOTH_SYN	(TH_SYN | (TH_SYN << 8))
 #define BOTH_FIN	(TH_FIN | (TH_FIN << 8))
 		q->state |= (dir == MATCH_FORWARD ) ? flags : (flags << 8);
+
 		switch (q->state) {
 		case TH_SYN:				/* opening */
 			q->expire = time_uptime + dyn_syn_lifetime;
 			break;
 
 		case BOTH_SYN:			/* move to established */
-			if (IS_IP6_FLOW_ID(pkt)) {
-				AUDIT_CALL(audit_ipfw_flow6_begin(&pkt->src_ip6,
-				    pkt->src_port, &pkt->dst_ip6,
-				    pkt->dst_port, 0));
-			} else {
-				AUDIT_CALL(audit_ipfw_flow4_begin(pkt->src_ip,
-				    pkt->src_port, pkt->dst_ip, pkt->dst_port,
-				    0));
-			}
 		case BOTH_SYN | TH_FIN :	/* one side tries to close */
 		case BOTH_SYN | (TH_FIN << 8) :
  			if (tcp) {
@@ -1349,23 +1374,42 @@
 static ipfw_dyn_rule *
 add_dyn_rule(struct ipfw_flow_id *id, u_int8_t dyn_type, struct ip_fw *rule)
 {
-	ipfw_dyn_rule *r;
+	ipfw_dyn_rule *r = NULL;
+	struct thread *td = curthread;
+	struct sockaddr_in lsin;
+	struct sockaddr_in rsin;
 	int i;
+	int error = 0;
 
 	IPFW_DYN_LOCK_ASSERT();
 
+	//if (dyn_type == O_AUDIT)
+	{
+		AUDIT_PFIL_ENTER(AUE_PFIL_FLOW_BEGIN, td, error);
+		if (error != 0)
+			goto done;
+		AUDIT_ARG(text, "ipfw");
+		addr_port_to_sin(id->src_ip, id->src_port, &lsin);
+		addr_port_to_sin(id->dst_ip, id->dst_port, &rsin);
+		AUDIT_ARG(socket_ex, AF_INET, SOCK_STREAM,
+		    (struct sockaddr *)&lsin, (struct sockaddr *)&rsin);
+	}
+
 	if (ipfw_dyn_v == NULL ||
 	    (dyn_count == 0 && dyn_buckets != curr_dyn_buckets)) {
 		realloc_dynamic_table();
-		if (ipfw_dyn_v == NULL)
-			return NULL; /* failed ! */
+		if (ipfw_dyn_v == NULL) {
+			error = ENOMEM;
+			goto done;
+		}
 	}
 	i = hash_packet(id);
 
 	r = uma_zalloc(ipfw_dyn_rule_zone, M_NOWAIT | M_ZERO);
 	if (r == NULL) {
 		printf ("ipfw: sorry cannot allocate state\n");
-		return NULL;
+		error = ENOMEM;
+		goto done;
 	}
 
 	/* increase refcount on parent, and set pointer */
@@ -1393,7 +1437,11 @@
 	   dyn_type,
 	   (r->id.src_ip), (r->id.src_port),
 	   (r->id.dst_ip), (r->id.dst_port),
-	   dyn_count ); )
+	   dyn_count)); 
+
+done:
+	//if (dyn_type == O_AUDIT)
+		AUDIT_PFIL_EXIT(error, td);
 	return r;
 }
 
@@ -3165,6 +3213,7 @@
 				     &dyn_dir, proto == IPPROTO_TCP ?
 					TCP(ulp) : NULL))
 					!= NULL) {
+
 					/*
 					 * Found dynamic entry, update stats
 					 * and jump to the 'action' part of
@@ -3403,18 +3452,12 @@
 	struct ip_fw *rule, *f, *prev;
 	int l = RULESIZE(input_rule);
 
-	if (chain->rules == NULL && input_rule->rulenum != IPFW_DEFAULT_RULE) {
-		AUDIT_CALL(audit_ipfw_addrule(input_rule->set,
-		    input_rule->rulenum, EINVAL));
+	if (chain->rules == NULL && input_rule->rulenum != IPFW_DEFAULT_RULE)
 		return (EINVAL);
-	}
 
 	rule = malloc(l, M_IPFW, M_NOWAIT | M_ZERO);
-	if (rule == NULL) {
-		AUDIT_CALL(audit_ipfw_addrule(input_rule->set,
-		    input_rule->rulenum, ENOSPC));
+	if (rule == NULL)
 		return (ENOSPC);
-	}
 
 	bcopy(input_rule, rule, l);
 
@@ -3474,7 +3517,6 @@
 	static_count++;
 	static_len += l;
 	IPFW_WUNLOCK(chain);
-	AUDIT_CALL(audit_ipfw_addrule(rule->set, rule->rulenum, 0));
 	DEB(printf("ipfw: installed rule %d, static count now %d\n",
 		rule->rulenum, static_count);)
 	return (0);
@@ -3571,6 +3613,7 @@
 del_entry(struct ip_fw_chain *chain, u_int32_t arg)
 {
 	struct ip_fw *prev = NULL, *rule;
+	struct thread *td = curthread;
 	u_int16_t rulenum;	/* rule or old_set */
 	u_int8_t cmd, new_set;
 
@@ -3578,18 +3621,13 @@
 	cmd = (arg >> 24) & 0xff;
 	new_set = (arg >> 16) & 0xff;
 
-	if (cmd > 5 || new_set > RESVD_SET) {
-		AUDIT_CALL(audit_ipfw_delrule(new_set, rulenum, EINVAL));
+	if (cmd > 5 || new_set > RESVD_SET)
 		return EINVAL;
-	}
 	if (cmd == 0 || cmd == 2 || cmd == 5) {
-		if (rulenum >= IPFW_DEFAULT_RULE) {
-			AUDIT_CALL(audit_ipfw_delrule(-1, rulenum, EINVAL));
+		if (rulenum >= IPFW_DEFAULT_RULE)
 			return EINVAL;
-		}
 	} else {
 		if (rulenum > RESVD_SET) {	/* old_set */
-			AUDIT_CALL(audit_ipfw_delrule(rulenum, -1, EINVAL));
 			return EINVAL;
 		}
 	}
@@ -3599,6 +3637,8 @@
 	chain->reap = NULL;
 	switch (cmd) {
 	case 0:	/* delete rules with given number */
+		AUDIT_ARG(text, "ipfw: rule=%05u", rulenum);
+
 		/*
 		 * locate first rule to delete
 		 */
@@ -3616,19 +3656,17 @@
 		flush_rule_ptrs(chain);
 		while (rule->rulenum == rulenum) {
 			rule = remove_rule(chain, rule, prev);
-			AUDIT_CALL(audit_ipfw_delrule(rule->set, rule->rulenum,
-			    0));
 		}
 		break;
 
 	case 1:	/* delete all rules with given set number */
+		AUDIT_ARG(text, "ipfw: set=%02u", rulenum);
+
 		flush_rule_ptrs(chain);
 		rule = chain->rules;
 		while (rule->rulenum < IPFW_DEFAULT_RULE) {
 			if (rule->set == rulenum) {
 				rule = remove_rule(chain, rule, prev);
-				AUDIT_CALL(audit_ipfw_delrule(rule->set,
-				    rule->rulenum, 0));
 			} else {
 				prev = rule;
 				rule = rule->next;
@@ -3637,50 +3675,45 @@
 		break;
 
 	case 2:	/* move rules with given number to new set */
+		AUDIT_ARG(text, "ipfw: move rule=%05u, set=%02u", rulenum,
+		    new_set);
+
 		rule = chain->rules;
 		for (; rule->rulenum < IPFW_DEFAULT_RULE; rule = rule->next) {
 			if (rule->rulenum == rulenum) {
-				AUDIT_CALL(audit_ipfw_delrule(rule->set,
-				    rule->rulenum, 0));
 				rule->set = new_set;
-				AUDIT_CALL(audit_ipfw_addrule(rule->set,
-				    rule->rulenum, 0));
 			}
 		}
 		break;
 
 	case 3: /* move rules with given set number to new set */
+		AUDIT_ARG(text, "ipfw: move set=%02u, newset=%02u", rulenum,
+		    new_set);
+
 		for (; rule->rulenum < IPFW_DEFAULT_RULE; rule = rule->next) {
 			if (rule->set == rulenum) {
-				AUDIT_CALL(audit_ipfw_delrule(rule->set,
-				    rule->rulenum, 0));
 				rule->set = new_set;
-				AUDIT_CALL(audit_ipfw_addrule(rule->set,
-				    rule->rulenum, 0));
 			}
 		}
 		break;
 
 	case 4: /* swap two sets */
+		AUDIT_ARG(text, "ipfw: swap set=%02u, set=%02u", rulenum,
+		    new_set);
+
 		for (; rule->rulenum < IPFW_DEFAULT_RULE; rule = rule->next)
 			if (rule->set == rulenum) {
-				AUDIT_CALL(audit_ipfw_delrule(rule->set,
-				    rule->rulenum, 0));
 				rule->set = new_set;
-				AUDIT_CALL(audit_ipfw_addrule(rule->set,
-				    rule->rulenum, 0));
 			} else if (rule->set == new_set) {
-				AUDIT_CALL(audit_ipfw_delrule(rule->set,
-				    rule->rulenum, 0));
 				rule->set = rulenum;
-				AUDIT_CALL(audit_ipfw_addrule(rule->set,
-				    rule->rulenum, 0));
 			}
 		break;
 	case 5: /* delete rules with given number and with given set number.
 		 * rulenum - given rule number;
 		 * new_set - given set number.
 		 */
+		AUDIT_ARG(text, "ipfw: set=%02u, rule=%05u", new_set, rulenum);
+
 		for (; rule->rulenum < rulenum; prev = rule, rule = rule->next)
 			;
 		if (rule->rulenum != rulenum) {
@@ -3691,8 +3724,6 @@
 		while (rule->rulenum == rulenum) {
 			if (rule->set == new_set) {
 				rule = remove_rule(chain, rule, prev);
-				AUDIT_CALL(audit_ipfw_delrule(rule->set,
-				    rule->rulenum, 0));
 			} else {
 				prev = rule;
 				rule = rule->next;
@@ -4190,9 +4221,9 @@
 {
 #define	RULE_MAXSIZE	(256*sizeof(u_int32_t))
 	int error;
-	int set;
 	size_t size;
 	struct ip_fw *buf, *rule;
+	struct thread *td = curthread;
 	u_int32_t rulenum[2];
 
 	error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
@@ -4254,15 +4285,18 @@
 		 * the old list without the need for a lock.
 		 */
 
-		IPFW_WLOCK(&layer3_chain);
-		layer3_chain.reap = NULL;
-		free_chain(&layer3_chain, 0 /* keep default rule */);
-		rule = layer3_chain.reap;
-		layer3_chain.reap = NULL;
-		IPFW_WUNLOCK(&layer3_chain);
-		if (rule != NULL)
-			reap_rules(rule);
-		AUDIT_CALL(audit_ipfw_flush(error));
+		AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_FLUSH, td, error);
+		if (error == 0) {
+			IPFW_WLOCK(&layer3_chain);
+			layer3_chain.reap = NULL;
+			free_chain(&layer3_chain, 0 /* keep default rule */);
+			rule = layer3_chain.reap;
+			layer3_chain.reap = NULL;
+			IPFW_WUNLOCK(&layer3_chain);
+			if (rule != NULL)
+				reap_rules(rule);
+		}
+		AUDIT_PFIL_EXIT(error, td);
 		break;
 
 	case IP_FW_ADD:
@@ -4272,10 +4306,16 @@
 		if (error == 0)
 			error = check_ipfw_struct(rule, sopt->sopt_valsize);
 		if (error == 0) {
-			error = add_rule(&layer3_chain, rule);
-			size = RULESIZE(rule);
-			if (!error && sopt->sopt_dir == SOPT_GET)
-				error = sooptcopyout(sopt, rule, size);
+			AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_ADDRULE, td, error);
+			if (error == 0) {
+				AUDIT_ARG(text, "ipfw: set=%02u, rule=%05u",
+				    rule->set, rule->rulenum);
+				error = add_rule(&layer3_chain, rule);
+				size = RULESIZE(rule);
+				if (!error && sopt->sopt_dir == SOPT_GET)
+					error = sooptcopyout(sopt, rule, size);
+			}
+			AUDIT_PFIL_EXIT(error, td);
 		}
 		free(rule, M_TEMP);
 		break;
@@ -4298,26 +4338,26 @@
 		if (error)
 			break;
 		size = sopt->sopt_valsize;
-		if (size == sizeof(u_int32_t))	/* delete or reassign */
-			error = del_entry(&layer3_chain, rulenum[0]);
-		else if (size == 2*sizeof(u_int32_t)) { /* set enable/disable */
-			set_disable =
-			    (set_disable | rulenum[0]) & ~rulenum[1] &
-			    ~(1<<RESVD_SET); /* set RESVD_SET always enabled */
+		if (size == sizeof(u_int32_t)) { /* delete or reassign */
+			AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_DELRULE, td, error);
+			if (error == 0)
+				error = del_entry(&layer3_chain, rulenum[0]);
+			AUDIT_PFIL_EXIT(error, td);
+		} else if (size == 2*sizeof(u_int32_t)) { /*set enable/disable*/
+			AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_DELRULE, td, error);
+			if (error == 0) {
+				u_int32_t new_set_disable;
+				new_set_disable =
+				    (set_disable | rulenum[0]) & ~rulenum[1] &
+				    ~(1<<RESVD_SET);
+ 				    /* set RESVD_SET always enabled */
 
-			/* Audit newly disabled sets */
-			for (set = 0; rulenum[0] != 0; set++, rulenum[0]>>=1) {
-				if (rulenum[0] & 1)
-					AUDIT_CALL(audit_ipfw_delrule(set, -1,
-					    0));
+				AUDIT_ARG(text,
+				    "ipfw: oldsets=0x%x, newsets=0x%x",
+				    set_disable, new_set_disable);
+				set_disable = new_set_disable;
 			}
-
-			/* Audit newly enabled sets */
-			for (set = 0; rulenum[1] != 0; set++, rulenum[1]>>=1) {
-				if (rulenum[1] & 1)
-					AUDIT_CALL(audit_ipfw_addrule(set, -1,
-					    0));
-			}
+			AUDIT_PFIL_EXIT(error, td);
 		} else
 			error = EINVAL;
 		break;
@@ -4343,9 +4383,13 @@
 			    sizeof(ent), sizeof(ent));
 			if (error)
 				break;
-			error = add_table_entry(&layer3_chain, ent.tbl,
-			    ent.addr, ent.masklen, ent.value);
-			AUDIT_CALL(audit_ipfw_addtable(ent.tbl, error));
+			AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_ADDTABLE, td, error);
+			if (error == 0) {
+				AUDIT_ARG(text, "ipfw: table=%u", ent.tbl);
+				error = add_table_entry(&layer3_chain, ent.tbl,
+				    ent.addr, ent.masklen, ent.value);
+			}
+			AUDIT_PFIL_EXIT(error, td);
 		}
 		break;
 
@@ -4357,9 +4401,13 @@
 			    sizeof(ent), sizeof(ent));
 			if (error)
 				break;
-			error = del_table_entry(&layer3_chain, ent.tbl,
-			    ent.addr, ent.masklen);
-			AUDIT_CALL(audit_ipfw_deltable(ent.tbl, error));
+			AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_DELTABLE, td, error);
+			if (error == 0) {
+				AUDIT_ARG(text, "ipfw: table=%u", ent.tbl);
+				error = del_table_entry(&layer3_chain, ent.tbl,
+			    	    ent.addr, ent.masklen);
+			}
+			AUDIT_PFIL_EXIT(error, td);
 		}
 		break;
 
@@ -4371,10 +4419,14 @@
 			    sizeof(tbl), sizeof(tbl));
 			if (error)
 				break;
-			IPFW_WLOCK(&layer3_chain);
-			error = flush_table(&layer3_chain, tbl);
-			IPFW_WUNLOCK(&layer3_chain);
-			AUDIT_CALL(audit_ipfw_flushtable(tbl, error));
+			AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_FLUSHTABLE, td, error);
+			if (error == 0) {
+				AUDIT_ARG(text, "ipfw: table=%u", tbl);
+				IPFW_WLOCK(&layer3_chain);
+				error = flush_table(&layer3_chain, tbl);
+				IPFW_WUNLOCK(&layer3_chain);
+			}
+			AUDIT_PFIL_EXIT(error, td);
 		}
 		break;
 

==== //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw_pfil.c#4 (text+ko) ====

@@ -43,6 +43,7 @@
 #include <sys/mbuf.h>
 #include <sys/module.h>
 #include <sys/kernel.h>
+#include <sys/proc.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
@@ -65,6 +66,7 @@
 
 #include <machine/in_cksum.h>
 
+#include <bsm/audit_kevents.h>
 #include <security/audit/audit.h>
 
 int fw_enable = 1;
@@ -526,10 +528,15 @@
 static int
 ipfw_modevent(module_t mod, int type, void *unused)
 {
+	struct thread *td = curthread;
 	int err = 0;
 
 	switch (type) {
 	case MOD_LOAD:
+		AUDIT_PFIL_ENTER(AUE_PFIL_ENABLE, td, err);
+		if (err != 0)
+			break;
+
 		if ((err = ipfw_init()) != 0) {
 			printf("ipfw_init() error\n");
 			break;
@@ -544,10 +551,13 @@
 			break;
 		}
 #endif
-		AUDIT_CALL(audit_ipfw_enable(err));
 		break;
 
 	case MOD_UNLOAD:
+		AUDIT_PFIL_ENTER(AUE_PFIL_DISABLE, td, err);
+		if (err != 0)
+			break;
+
 		if ((err = ipfw_unhook()) > 0)
 			break;
 #ifdef INET6
@@ -555,13 +565,14 @@
 			break;
 #endif
 		ipfw_destroy();
-		AUDIT_CALL(audit_ipfw_disable(err));
 		break;
 
 	default:
 		return EOPNOTSUPP;
 		break;
 	}
+	AUDIT_ARG(text, "ipfw");
+	AUDIT_PFIL_EXIT(err, td);
 	return err;
 }
 

==== //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit.c#7 (text) ====

@@ -298,43 +298,62 @@
  * XXXAUDIT: Shouldn't there be logic here to sleep waiting on available
  * pre_q space, suspending the system call until there is room?
  */
-struct kaudit_record *
-audit_new(int event, struct thread *td)
+int
+audit_new(struct kaudit_record **arp, int event, struct thread *td, int flags)
 {
 	struct kaudit_record *ar;
 	int no_record;
+	char **textp;
 
 	mtx_lock(&audit_mtx);
 	no_record = (audit_suspended || !audit_enabled);
 	mtx_unlock(&audit_mtx);
-	if (no_record)
-		return (NULL);
+	if (no_record) {
+		*arp = NULL;
+		return (0);
+	}
+
+	if (flags & AR_WAITOK) {
+		ar = uma_zalloc_arg(audit_record_zone, td, M_WAITOK);
+	} else if (flags & AR_NOWAIT) {
+		ar = uma_zalloc_arg(audit_record_zone, td, M_NOWAIT);
+		if (ar == NULL)
+			return (ENOMEM);
+
+		/*
+		 * XXXDG: Perhaps we should preallocate other dynamic allocated
+		 * args also.
+		 */
+		textp = &ar->k_ar.ar_arg_text;
+		*textp = malloc(MAXPATHLEN, M_AUDITTEXT, M_NOWAIT);
+		if (*textp == NULL) {
+			free(ar, M_AUDITTEXT);
+			return (ENOMEM);
+		}
+	} else
+		return (EINVAL);
 
-	/*
-	 * Note: the number of outstanding uncommitted audit records is
-	 * limited to the number of concurrent threads servicing system calls
-	 * in the kernel.
-	 */
-	ar = uma_zalloc_arg(audit_record_zone, td, M_WAITOK);
 	ar->k_ar.ar_event = event;
+	*arp = ar;
 
 	mtx_lock(&audit_mtx);
 	audit_pre_q_len++;
 	mtx_unlock(&audit_mtx);
 
-	return (ar);
+	return (0);
 }
 
 /*
- * Allocate a new record if preselection allows it. Otherwise, return NULL.
+ * Allocate a new record if preselection allows it.
  */
-struct kaudit_record *
-audit_begin(int event, struct thread *td)
+static int
+audit_begin(struct kaudit_record **arp, int event, struct thread *td, int flags)
 {
 	struct		kaudit_record *ar;
 	struct		au_mask *aumask;
 	au_class_t	class;
 	au_id_t		auid;
+	int		error;
 
 	KASSERT(event != AUE_NULL, ("audit_begin: event == AUE_NULL"));
 
@@ -370,13 +389,16 @@
 			cv_wait(&audit_fail_cv, &audit_mtx);
 			panic("audit_failing_stop: thread continued");
 		}
-		ar = audit_new(event, td);
-	} else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0))
-		ar = audit_new(event, td);
-	else
+		error = audit_new(&ar, event, td, flags);
+	} else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) {
+		error = audit_new(&ar, event, td, flags);
+	} else {
 		ar = NULL;
+		error = 0;
+	}
 
-	return (ar);
+	*arp = ar;
+	return (error);
 }
 
 void
@@ -484,20 +506,19 @@
 }
 
 /*
- * Check if there's already a record being constructed. If true, save it 
- * into thread's record queue.
+ * Save the current thread's record (if there's one) into thread's record queue
+ * and establish a new record.
  */
 static void
-audit_enter(struct thread *td)
+audit_enter(struct kaudit_record *ar, struct thread *td)
 {
 	if (td->td_ar != NULL)
 		TAILQ_INSERT_TAIL(td->td_arq, td->td_ar, k_q);
-	td->td_ar = NULL;
+	td->td_ar = ar;
 }
 
 /*
- * Check if there were a previous record being constructed. If true, make it
- * the current record and remove it from thread's record queue.
+ * Turn the previous saved record (if there's one) into thread's current record.
  */
 static void
 audit_exit(struct thread *td)
@@ -534,16 +555,9 @@
 	if (event == AUE_NULL)
 		return;
 
-	ar = audit_begin(event, td);
-	if (ar != NULL) {
-		/*
-	 	* Save the current record into thread's record queue and
-		* create a new record.
-	 	*/
-
-		audit_enter(td);
-		td->td_ar = ar;
-	}
+	(void)audit_begin(&ar, event, td, AR_WAITOK);
+	if (ar != NULL)
+		audit_enter(ar, td);
 }
 
 /*
@@ -568,29 +582,20 @@
 	else
 		retval = td->td_retval[0];
 
-	/*
-	 * Commit the current record. Turn the previous saved record into the
-	 * current one.
-	 */
 	audit_commit(td->td_ar, error, retval);
 	audit_exit(td);
 }
 
-void
+int
 audit_pfil_enter(unsigned short event, struct thread *td)
 {
 	struct	kaudit_record *ar;
+	int	error;
 
-	ar = audit_begin(event, td);
-	if (ar != NULL) {
-		/*
-	 	* Save the current record into thread's record queue and
-		* create a new record.
-	 	*/
-
-		audit_enter(td);
-		td->td_ar = ar;
-	}
+	error = audit_begin(&ar, event, td, AR_NOWAIT);
+	if (error == 0 && ar != NULL)
+		audit_enter(ar, td);
+	return (error);
 }
 
 void
@@ -603,10 +608,6 @@
 	else
 		retval = 0;
 
-	/*
-	 * Commit the current record. Turn the previous saved record into the
-	 * current one.
-	 */
 	audit_commit(td->td_ar, error, retval);
 	audit_exit(td);
 }
@@ -706,7 +707,7 @@
 	 * Where possible coredump records should contain a pathname and arg32
 	 * (signal) tokens.
 	 */
-	ar = audit_new(AUE_CORE, td);
+	(void)audit_new(&ar, AUE_CORE, td, AR_WAITOK);
 	if (path != NULL) {
 		pathp = &ar->k_ar.ar_arg_upath1;
 		*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK);

==== //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit_private.h#5 (text) ====

@@ -87,6 +87,12 @@
 #define	AR_PRESELECT_USER_PIPE	0x00008000U
 
 /*
+ * Flags to indicate which allocation scheme to use for allocating records.
+ */
+#define AR_WAITOK		0x00000001U
+#define AR_NOWAIT		0x00000002U
+
+/*
  * Audit data is generated as a stream of struct audit_record structures,
  * linked by struct kaudit_record, and contain storage for possible audit so
  * that it will not need to be allocated during the processing of a system
@@ -248,11 +254,10 @@
  * Functions to manage the allocation, release, and commit of kernel audit
  * records.
  */
-void			 audit_abort(struct kaudit_record *ar);
-void			 audit_commit(struct kaudit_record *ar, int error,
-			    int retval);
-struct kaudit_record	*audit_new(int event, struct thread *td);
-struct kaudit_record	*audit_begin(int event, struct thread *td);
+void	audit_abort(struct kaudit_record *ar);
+void	audit_commit(struct kaudit_record *ar, int error, int retval);
+int	audit_new(struct kaudit_record **arp, int event, struct thread *td,
+		int flags);
 
 /* Functions to add arguments to kernel audit records.
  */

==== //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit_syscalls.c#2 (text) ====

@@ -93,10 +93,10 @@
 		 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and
 		 * special pre-select handling?
 		 */
-		td->td_ar = audit_new(AUE_NULL, td);
+		(void)audit_new(&ar, AUE_NULL, td, AR_WAITOK);
+		td->td_ar = ar;
 		if (td->td_ar == NULL)
 			return (ENOTSUP);
-		ar = td->td_ar;
 	}
 
 	if (uap->length > MAX_AUDIT_RECORD_SIZE)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200808170323.m7H3Nrpe032034>