--- //depot/vendor/freebsd/src/sys/security/audit/audit.c	2008/04/14 02:00:29
+++ //depot/projects/soc2008/snagg-audit/sys/security/audit/audit.c	2008/05/29 23:48:40
@@ -385,7 +385,7 @@
 	if (au_preselect(event, class, aumask, sorf) != 0)
 		ar->k_ar_commit |= AR_PRESELECT_TRAIL;
 	if (audit_pipe_preselect(auid, event, class, sorf,
-	    ar->k_ar_commit & AR_PRESELECT_TRAIL) != 0)
+	    ar->k_ar_commit & AR_PRESELECT_TRAIL, ar->k_ar.ar_subj_pid) != 0)
 		ar->k_ar_commit |= AR_PRESELECT_PIPE;
 	if ((ar->k_ar_commit & (AR_PRESELECT_TRAIL | AR_PRESELECT_PIPE |
 	    AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE)) == 0) {
@@ -491,7 +491,8 @@
 			panic("audit_failing_stop: thread continued");
 		}
 		td->td_ar = audit_new(event, td);
-	} else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0))
+	} else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0, 
+			    td->td_proc->p_pid))
 		td->td_ar = audit_new(event, td);
 	else
 		td->td_ar = NULL;
--- //depot/vendor/freebsd/src/sys/security/audit/audit_ioctl.h	2007/04/29 16:23:02
+++ //depot/projects/soc2008/snagg-audit/sys/security/audit/audit_ioctl.h	2008/05/29 23:48:40
@@ -38,16 +38,31 @@
  * structures, add new revised ones to be used by new ioctls, and keep the
  * old structures and ioctls for backwards compatibility.
  */
+struct auditpipe_ioctl_preselect_event {
+	int		app_event; 
+	int		app_flag;	
+};
+
 struct auditpipe_ioctl_preselect {
 	au_id_t		aip_auid;
 	au_mask_t	aip_mask;
+	pid_t		app_pid;
+	struct 	auditpipe_ioctl_preselect_event *app_auevents;
+	int		app_event_len;
 };
 
+struct auditpipe_ioctl_preselect_old {
+	au_id_t		aip_auid;
+	au_mask_t	aip_mask;
+};
+
 /*
  * Possible modes of operation for audit pipe preselection.
  */
 #define	AUDITPIPE_PRESELECT_MODE_TRAIL	1	/* Global audit trail. */
 #define	AUDITPIPE_PRESELECT_MODE_LOCAL	2	/* Local audit trail. */
+#define	AUDITPIPE_PRESELECT_MODE_EVENT	3	/* Events-pid based audit trail */
+#define	AUDITPIPE_PRESELECT_MODE_PID	4	/*Pid based audit trail*/
 
 /*
  * Ioctls to read and control the behavior of individual audit pipe devices.
@@ -71,6 +86,12 @@
 #define	AUDITPIPE_SET_PRESELECT_MODE	_IOW(AUDITPIPE_IOBASE, 15, int)
 #define	AUDITPIPE_FLUSH			_IO(AUDITPIPE_IOBASE, 16)
 #define	AUDITPIPE_GET_MAXAUDITDATA	_IOR(AUDITPIPE_IOBASE, 17, u_int)
+#define	AUDITPIPE_GET_PRESELECT_EVENT_LIST	_IOWR(AUDITPIPE_IOBASE, 18,	\
+		    struct auditpipe_ioctl_preselect)
+#define	AUDITPIPE_SET_PRESELECT_EVENTS	_IOW(AUDITPIPE_IOBASE, 19,	\
+		    struct auditpipe_ioctl_preselect)
+#define	AUDITPIPE_DELETE_PRESELECT_PID	_IOW(AUDITPIPE_IOBASE, 20, pid_t)
+#define	AUDITPIPE_FLUSH_PRESELECT_EVENTS	_IO(AUDITPIPE_IOBASE, 21)
 
 /*
  * Ioctls to retrieve audit pipe statistics.
--- //depot/vendor/freebsd/src/sys/security/audit/audit_pipe.c	2008/04/14 02:00:29
+++ //depot/projects/soc2008/snagg-audit/sys/security/audit/audit_pipe.c	2008/06/02 13:20:53
@@ -68,6 +68,8 @@
     "Audit pipe entries and buffers");
 static MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT, "audit_pipe_presel",
     "Audit pipe preselection structure");
+static MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT_EVENT, 
+	"Audit_pipe_preselection", "Audit pipe preselection events structure");
 
 /*
  * Audit pipe buffer parameters.
@@ -75,6 +77,7 @@
 #define	AUDIT_PIPE_QLIMIT_DEFAULT	(128)
 #define	AUDIT_PIPE_QLIMIT_MIN		(0)
 #define	AUDIT_PIPE_QLIMIT_MAX		(1024)
+#define	AUDIT_NEVENTS				(256)
 
 /*
  * Description of an entry in an audit_pipe.
@@ -96,9 +99,17 @@
  * We may want to consider a more space/time-efficient data structure once
  * usage patterns for per-auid specifications are clear.
  */
+struct audit_pipe_preselect_event {
+	int		app_event; 
+	int		app_flag;	
+};
+
 struct audit_pipe_preselect {
-	au_id_t					 app_auid;
-	au_mask_t				 app_mask;
+	au_id_t		app_auid;
+	au_mask_t	app_mask;
+	pid_t		app_pid;
+	struct 	audit_pipe_preselect_event *app_auevents;
+	int		app_event_len;
 	TAILQ_ENTRY(audit_pipe_preselect)	 app_list;
 };
 
@@ -217,6 +228,60 @@
 }
 
 /*
+ * The event array is sorted in ascending order, needed for the binary search
+ */
+static int 
+audit_pipe_compare_preselect_event(const void *a, const void *b)
+{
+	const struct audit_pipe_preselect_event *entrya, *entryb;
+	
+	entrya = a;
+	entryb = b;
+	if(entrya->app_event > entryb->app_event)
+		return (1);
+	else if (entrya->app_event < entryb->app_event)
+		return (-1);
+	else
+		return (0);
+}
+			
+/*
+ * Find an audit pipe preselection specification for an event and flag, 
+ * if any.
+ */
+static struct audit_pipe_preselect *
+audit_pipe_preselect_find_event(struct audit_pipe *ap, int app_event, 
+	pid_t app_pid, int event_flag)
+{
+	struct audit_pipe_preselect *app;
+	struct audit_pipe_preselect_event *event, ev_a;
+	
+	mtx_assert(&audit_pipe_mtx, MA_OWNED);
+
+	ev_a.app_event = app_event;
+	ev_a.app_flag = event_flag;
+	TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) {
+		if(app->app_pid == app_pid) {
+			
+			/* Just skip if we are interested only in the pid. */
+			if(app_event != -1 && app->app_event_len > 0)  {
+				event = bsearch(&ev_a, (app->app_auevents), app->app_event_len,
+				    sizeof(struct audit_pipe_preselect_event), 
+				    audit_pipe_compare_preselect_event);
+				if(event != NULL) {
+					if(event_flag != -1)
+						 if (!(event->app_flag & event_flag))
+							app = NULL;
+				} else
+					app = NULL;
+			}
+			break;
+		}
+	}
+	return (app);
+}
+
+/*
  * Find an audit pipe preselection specification for an auid, if any.
  */
 static struct audit_pipe_preselect *
@@ -234,6 +299,28 @@
 }
 
 /*
+ * Query the per-pipe events list for a specific pid.
+ */
+static int
+audit_pipe_preselect_get_events_list(struct audit_pipe *ap, 
+    pid_t app_pid, struct audit_pipe_preselect_event *app_events, int app_len)
+{
+	struct audit_pipe_preselect *app;
+	int error;
+
+	mtx_lock(&audit_pipe_mtx);
+	app = audit_pipe_preselect_find_event(ap, -1, app_pid, -1);
+	if (app != NULL)
+		error = copyout(app->app_auevents, app_events, 
+		    sizeof(struct audit_pipe_preselect_event)*
+		    ((app_len > app->app_event_len) ? app->app_event_len : app_len));
+	else
+		error = ENOENT;
+	mtx_unlock(&audit_pipe_mtx);
+	return (error);
+}
+
+/*
  * Query the per-pipe mask for a specific auid.
  */
 static int
@@ -255,7 +342,76 @@
 }
 
 /*
- * Set the per-pipe mask for a specific auid.  Add a new entry if needed;
+ * Add a new entry for a specifc event.  Add a new entry if needed;
+ * otherwise, update the current entry.
+ */
+static void
+audit_pipe_preselect_set_events(struct audit_pipe *ap, pid_t app_pid, 
+	struct audit_pipe_preselect_event *events, int num)
+{
+	struct audit_pipe_preselect *app, *app_new;
+	int i, found;
+	
+	/*
+	 * Pessimistically assume that the entry for this pid doesn't 
+	 * exist, and allocate.  We will free it if it is unneeded.
+	 */
+	KASSERT(num >= 0, ("Number of events is out of range"));
+	
+	/* Max number allowed */
+	KASSERT(num <= AUDIT_NEVENTS, ("Number of events is out of range"));
+	
+	app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK);
+	if(num)
+		app_new->app_auevents= malloc(sizeof(struct audit_pipe_preselect_event) *
+	    	num, M_AUDIT_PIPE_PRESELECT_EVENT, M_WAITOK);
+		
+	mtx_lock(&audit_pipe_mtx);
+	
+	/*
+	 * First search for the entry by its pid
+	 */
+	app = audit_pipe_preselect_find_event(ap, -1, app_pid, -1);
+	found = (app != NULL) ? 1: 0;
+	if(found) {
+		if(app->app_event_len)
+			free(app->app_auevents,  M_AUDIT_PIPE_PRESELECT_EVENT);
+		app->app_auevents = app_new->app_auevents;
+		app_new = NULL;
+		app->app_event_len = num;
+		for (i = 0; i < num; i++) {
+			(app->app_auevents + i)->app_event = (events + i)->app_event;
+			(app->app_auevents + i)->app_flag  = (events + i)->app_flag;
+		}
+		qsort((app->app_auevents), app->app_event_len, 
+		    sizeof(struct audit_pipe_preselect_event), 
+		    audit_pipe_compare_preselect_event);
+	} else {	
+		app = app_new;
+		app_new = NULL;
+		app->app_pid = app_pid;
+		app->app_event_len = num;
+		for (i = 0; i < num; i++) {
+			(app->app_auevents + i)->app_event = (events + i)->app_event;
+			(app->app_auevents + i)->app_flag  = (events + i)->app_flag;
+		}
+		qsort((app->app_auevents), app->app_event_len, 
+		    sizeof(struct audit_pipe_preselect_event), 
+		    audit_pipe_compare_preselect_event);
+		TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list);
+	}	
+	
+	
+	mtx_unlock(&audit_pipe_mtx);
+	if (app_new != NULL) {
+		free(app_new, M_AUDIT_PIPE_PRESELECT);
+		if(num)
+			free(app_new->app_auevents, M_AUDIT_PIPE_PRESELECT_EVENT);
+	}	
+}
+
+/*
+ * Set the per-pipe mask for a specific event.  Add a new entry if needed;
  * otherwise, update the current entry.
  */
 static void
@@ -283,6 +439,60 @@
 }
 
 /*
+ * Delete a per-event entry on an audit pipe. DON'T KNOW WHETHER IT IS USEFUL OR NOT
+ */
+/*
+static int
+audit_pipe_preselect_delete_event(struct audit_pipe *ap, int app_event, pid_t pid, 
+	int app_flag)
+{
+	struct audit_pipe_preselect *app;
+	int i;
+	
+	mtx_lock(&audit_pipe_mtx);
+	app = audit_pipe_preselect_find_event(ap, app_event, pid, -1);
+	if (app != NULL) {
+		for( i = 0; i < app->app_event_len; i++) {
+			if((app->app_auevents + i)->app_event == app_event  && 
+				(app->app_auevents + i)->app_flag == app_flag) {
+				free((app->app_auevents + i), M_AUDIT_PIPE_PRESELECT_EVENT);
+				break;
+			}
+		}
+		mtx_unlock(&audit_pipe_mtx);		
+		return(0);
+	} 
+	mtx_unlock(&audit_pipe_mtx);
+	
+	return (ENOENT);
+
+}
+*/
+
+/*
+ * Delete a per-pid entry on an audit pipe wiping the whole entry.
+ */
+static int
+audit_pipe_preselect_delete_pid(struct audit_pipe *ap, pid_t pid)
+{
+	struct audit_pipe_preselect *app;
+	
+	mtx_lock(&audit_pipe_mtx);
+	app = audit_pipe_preselect_find_event(ap, -1, pid, -1);
+	if (app != NULL) {
+		TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list);
+		mtx_unlock(&audit_pipe_mtx);
+		if(app->app_auevents != NULL)		
+			free(app->app_auevents, M_AUDIT_PIPE_PRESELECT_EVENT);
+		free(app, M_AUDIT_PIPE_PRESELECT);	
+		return (0);
+	} else
+		mtx_unlock(&audit_pipe_mtx);
+		
+	return (ENOENT);
+}
+
+/*
  * Delete a per-auid mask on an audit pipe.
  */
 static int
@@ -305,6 +515,35 @@
 }
 
 /*
+ * Delete all per-events entry on an audit pipe.
+ */
+static void
+audit_pipe_preselect_events_flush_locked(struct audit_pipe *ap)
+{
+	struct audit_pipe_preselect *app;
+	
+	mtx_assert(&audit_pipe_mtx, MA_OWNED);
+
+	while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) {
+		TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list);
+		if (app != NULL) {
+				if(app->app_auevents != NULL)
+					free(app->app_auevents , M_AUDIT_PIPE_PRESELECT_EVENT);
+			free(app, M_AUDIT_PIPE_PRESELECT);	
+		}
+	}
+}
+
+static void
+audit_pipe_preselect_events_flush(struct audit_pipe *ap)
+{
+
+	mtx_lock(&audit_pipe_mtx);
+	audit_pipe_preselect_events_flush_locked(ap);
+	mtx_unlock(&audit_pipe_mtx);
+}
+
+/*
  * Delete all per-auid masks on an audit pipe.
  */
 static void
@@ -341,7 +580,8 @@
  */
 static int
 audit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid,
-    au_event_t event, au_class_t class, int sorf, int trail_preselect)
+    au_event_t event, au_class_t class, int sorf, int trail_preselect, 
+    pid_t app_pid)
 {
 	struct audit_pipe_preselect *app;
 
@@ -364,6 +604,20 @@
 			return (au_preselect(event, class, &app->app_mask,
 			    sorf));
 
+	case AUDITPIPE_PRESELECT_MODE_EVENT: 
+		app = audit_pipe_preselect_find_event(ap, event, app_pid, sorf);
+		if(app != NULL)
+			return (1);
+		else
+			break;
+			
+	case AUDITPIPE_PRESELECT_MODE_PID:
+		app = audit_pipe_preselect_find_event(ap, -1, app_pid, -1);
+		if(app != NULL)
+			return (1);
+		else
+			break;
+			
 	default:
 		panic("audit_pipe_preselect_check: mode %d",
 		    ap->ap_preselect_mode);
@@ -378,14 +632,14 @@
  */
 int
 audit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class,
-    int sorf, int trail_preselect)
+    int sorf, int trail_preselect, pid_t app_pid)
 {
 	struct audit_pipe *ap;
 
 	mtx_lock(&audit_pipe_mtx);
 	TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) {
 		if (audit_pipe_preselect_check(ap, auid, event, class, sorf,
-		    trail_preselect)) {
+		    trail_preselect, app_pid)) {
 			mtx_unlock(&audit_pipe_mtx);
 			return (1);
 		}
@@ -449,7 +703,7 @@
  */
 void
 audit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf,
-    int trail_select, void *record, u_int record_len)
+    int trail_select, void *record, u_int record_len, pid_t app_pid)
 {
 	struct audit_pipe *ap;
 
@@ -462,7 +716,7 @@
 	mtx_lock(&audit_pipe_mtx);
 	TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) {
 		if (audit_pipe_preselect_check(ap, auid, event, class, sorf,
-		    trail_select))
+		    trail_select, app_pid))
 			audit_pipe_append(ap, record, record_len);
 	}
 	audit_pipe_records++;
@@ -692,6 +946,7 @@
 	au_mask_t *maskp;
 	int error, mode;
 	au_id_t auid;
+	pid_t app_pid;
 
 	ap = dev->si_drv1;
 	KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL"));
@@ -809,7 +1064,22 @@
 		error = audit_pipe_preselect_get(ap, aip->aip_auid,
 		    &aip->aip_mask);
 		break;
+	
+	case AUDITPIPE_GET_PRESELECT_EVENT_LIST:
+		aip = (struct auditpipe_ioctl_preselect *)data;
+		error = audit_pipe_preselect_get_events_list(ap, aip->app_pid,
+		    (struct audit_pipe_preselect_event *)aip->app_auevents, 
+		    aip->app_event_len);
+		break;
 
+	case AUDITPIPE_SET_PRESELECT_EVENTS:
+		aip = (struct auditpipe_ioctl_preselect *)data;
+		audit_pipe_preselect_set_events(ap, aip->app_pid, 
+			(struct audit_pipe_preselect_event *)aip->app_auevents, 
+			aip->app_event_len);
+		error = 0;
+		break;
+	
 	case AUDITPIPE_SET_PRESELECT_AUID:
 		aip = (struct auditpipe_ioctl_preselect *)data;
 		audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask);
@@ -821,11 +1091,21 @@
 		error = audit_pipe_preselect_delete(ap, auid);
 		break;
 
+	case AUDITPIPE_DELETE_PRESELECT_PID:
+		app_pid = *(pid_t *)data;
+		error = audit_pipe_preselect_delete_pid(ap, app_pid);
+		break;
+	
 	case AUDITPIPE_FLUSH_PRESELECT_AUID:
 		audit_pipe_preselect_flush(ap);
 		error = 0;
 		break;
 
+	case AUDITPIPE_FLUSH_PRESELECT_EVENTS:
+		audit_pipe_preselect_events_flush(ap);
+		error = 0;
+		break;
+
 	case AUDITPIPE_GET_PRESELECT_MODE:
 		mtx_lock(&audit_pipe_mtx);
 		*(int *)data = ap->ap_preselect_mode;
@@ -838,6 +1118,8 @@
 		switch (mode) {
 		case AUDITPIPE_PRESELECT_MODE_TRAIL:
 		case AUDITPIPE_PRESELECT_MODE_LOCAL:
+		case AUDITPIPE_PRESELECT_MODE_EVENT:
+		case AUDITPIPE_PRESELECT_MODE_PID:
 			mtx_lock(&audit_pipe_mtx);
 			ap->ap_preselect_mode = mode;
 			mtx_unlock(&audit_pipe_mtx);
--- //depot/vendor/freebsd/src/sys/security/audit/audit_private.h	2008/03/01 11:41:27
+++ //depot/projects/soc2008/snagg-audit/sys/security/audit/audit_private.h	2008/05/12 15:39:07
@@ -331,9 +331,9 @@
  * Audit pipe functions.
  */
 int	 audit_pipe_preselect(au_id_t auid, au_event_t event,
-	    au_class_t class, int sorf, int trail_select);
+	    au_class_t class, int sorf, int trail_select, pid_t app_pid);
 void	 audit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class,
-	    int sorf, int trail_select, void *record, u_int record_len);
+	    int sorf, int trail_select, void *record, u_int record_len, pid_t app_pid);
 void	 audit_pipe_submit_user(void *record, u_int record_len);
 
 #endif /* ! _SECURITY_AUDIT_PRIVATE_H_ */
--- //depot/vendor/freebsd/src/sys/security/audit/audit_worker.c	2008/05/21 14:00:16
+++ //depot/projects/soc2008/snagg-audit/sys/security/audit/audit_worker.c	2008/05/23 18:56:46
@@ -365,7 +365,7 @@
 	if (ar->k_ar_commit & AR_PRESELECT_PIPE)
 		audit_pipe_submit(auid, event, class, sorf,
 		    ar->k_ar_commit & AR_PRESELECT_TRAIL, bsm->data,
-		    bsm->len);
+		    bsm->len, ar->k_ar.ar_subj_pid);
 
 	kau_free(bsm);
 out:
