PERFORCE change 96570 for review

Robert Watson rwatson at FreeBSD.org
Tue May 2 22:03:25 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=96570

Change 96570 by rwatson at rwatson_peppercorn on 2006/05/02 22:03:11

	Early pass at per-pipe preselection:
	
	- Add new fields to struct audit_pipe to describe the preselection
	  preferences for the pipe.  Currently, this consists of two masks,
	  flags and naflags, with similar meanings to those used for
	  trails.  In addition, a linked list of audit_pipe_preselect
	  structures provides similar functionality to audit_user,
	  assigning masks to specific auids.  The details here need
	  refinement.
	
	- Add two new functions, audit_pipe_preselect_check(), which
	  checks whether a record with the passed {auid, event, class,
	  sorf} is matched, and audit_pipe_preselect(), which iterates
	  over available pipes.  This will be called by the system
	  preselection mechanisms to poll the audit pipe subsystem for
	  interest in a particular record.
	
	- Modify audit_pipe_submit() to accept additional fields auid,
	  class, sorf for a BSM record, so that preselection can be
	  performed when delivering to pipes.  The old preselection-free
	  audit_pipe_submit() continues to exist, for now, as
	  audit_pipe_submit_user(), to be called on user records since we
	  don't currently extract sufficient information from user
	  submitted records to perform full preselection.
	
	- Modify audit worker code to pass additional record properties
	  into audit_pipe_submit().
	
	This almost certainly doesn't work yet.

Affected files ...

.. //depot/projects/trustedbsd/audit3/sys/security/audit/audit_pipe.c#14 edit
.. //depot/projects/trustedbsd/audit3/sys/security/audit/audit_private.h#25 edit
.. //depot/projects/trustedbsd/audit3/sys/security/audit/audit_worker.c#9 edit

Differences ...

==== //depot/projects/trustedbsd/audit3/sys/security/audit/audit_pipe.c#14 (text+ko) ====

@@ -82,6 +82,19 @@
 };
 
 /*
+ * Audit pipes allow processes to express "interest" in the set of records
+ * that are delivered via the pipe.  They do this in a similar manner to the
+ * mechanism for audit trail configuration, by expressing two global masks,
+ * and optionally expressing per-auid masks.  The following data structures
+ * define by the global masks for each pipe, and a list of per-auid masks.
+ */
+struct audit_pipe_preselect {
+	au_id_t					 app_auid;
+	au_mask_t				 app_mask;
+	TAILQ_ENTRY(audit_pipe_preselect)	 app_list;
+};
+
+/*
  * Description of an individual audit_pipe.  Consists largely of a bounded
  * length queue.
  */
@@ -102,8 +115,24 @@
 	u_int64_t			 ap_drops;	/* Records dropped. */
 	u_int64_t			 ap_truncates;	/* Records too long. */
 
+
+	/*
+	 * Fields relating to pipe interest: global masks for unmatched
+	 * processes (attributable, non-attributable), and a list of specific
+	 * interest specifications by auid.
+	 */
+	au_mask_t			 ap_preselect_flags;
+	au_mask_t			 ap_preselect_naflags;
+	TAILQ_HEAD(, audit_pipe_preselect)	ap_preselect_list;
+
+	/*
+	 * Record list.
+	 */
 	TAILQ_HEAD(, audit_pipe_entry)	 ap_queue;
 
+	/*
+	 * Global pipe list.
+	 */
 	TAILQ_ENTRY(audit_pipe)		 ap_list;
 };
 
@@ -167,6 +196,49 @@
 }
 
 /*
+ * Determine whether a specific audit pipe matches a record with these
+ * properties.
+ */
+static int
+audit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid,
+    au_event_t event, au_class_t class, int sorf)
+{
+	struct audit_pipe_preselect *app;
+
+	TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) {
+		if (app->app_auid == auid)
+			break;
+	}
+	if (app == NULL) {
+		if (auid == AU_DEFAUDITID)
+			return (au_preselect(event, &ap->ap_preselect_naflags,
+			    sorf));
+		else
+			return (au_preselect(event, &ap->ap_preselect_flags,
+			    sorf));
+	} else
+		return (au_preselect(event, &app->app_mask, sorf));
+	return (0);
+}
+
+/*
+ * Determine whether there exists a pipe interested in a record with these
+ * properties.
+ */
+int
+audit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class,
+    int sorf)
+{
+	struct audit_pipe *ap;
+
+	TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) {
+		if (audit_pipe_preselect_check(ap, auid, event, class, sorf))
+			return (1);
+	}
+	return (0);
+}
+
+/*
  * Apparent individual record to a queue -- allocate queue-local buffer, and
  * add to the queue.  We try to drop from the head of the queue so that more
  * recent events take precedence over older ones, but if allocation fails we
@@ -219,7 +291,37 @@
  * interface, which arranges for them to be delivered to pipe queues.
  */
 void
-audit_pipe_submit(void *record, u_int record_len)
+audit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf,
+    void *record, u_int record_len)
+{
+	struct audit_pipe *ap;
+
+	/*
+	 * Lockless read to avoid mutex overhead if pipes are not in use.
+	 */
+	if (TAILQ_FIRST(&audit_pipe_list) == NULL)
+		return;
+
+	mtx_lock(&audit_pipe_mtx);
+	TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) {
+		if (audit_pipe_preselect_check(ap, auid, event, class, sorf))
+			audit_pipe_append(ap, record, record_len);
+	}
+	audit_pipe_records++;
+	mtx_unlock(&audit_pipe_mtx);
+	cv_signal(&audit_pipe_cv);
+}
+
+/*
+ * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that
+ * since we don't currently have selection information available, it is
+ * delivered to the pipe unconditionally.
+ *
+ * XXXRW: This is a bug.  The BSM check routine for submitting a user record
+ * should parse that information and return it.
+ */
+void
+audit_pipe_submit_user(void *record, u_int record_len)
 {
 	struct audit_pipe *ap;
 
@@ -237,6 +339,7 @@
 	cv_signal(&audit_pipe_cv);
 }
 
+
 /*
  * Read the next record off of an audit pipe.
  */
@@ -273,9 +376,14 @@
 		return (NULL);
 	ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT;
 	TAILQ_INIT(&ap->ap_queue);
+	bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags));
+	bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags));
+	TAILQ_INIT(&ap->ap_preselect_list);
+
 	TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list);
 	audit_pipe_count++;
 	audit_pipe_ever++;
+
 	return (ap);
 }
 

==== //depot/projects/trustedbsd/audit3/sys/security/audit/audit_private.h#25 (text+ko) ====

@@ -337,6 +337,10 @@
 /*
  * Audit pipe functions.
  */
-void	 audit_pipe_submit(void *record, u_int record_len);
+int	 audit_pipe_preselect(au_id_t auid, au_event_t event,
+	    au_class_t class, int sorf);
+void	 audit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class,
+	    int sorf, void *record, u_int record_len);
+void	 audit_pipe_submit_user(void *record, u_int record_len);
 
 #endif /* ! _SECURITY_AUDIT_PRIVATE_H_ */

==== //depot/projects/trustedbsd/audit3/sys/security/audit/audit_worker.c#9 (text+ko) ====

@@ -315,7 +315,11 @@
     struct thread *audit_td, struct kaudit_record *ar)
 {
 	struct au_record *bsm;
+	au_class_t class;
+	au_event_t event;
 	int error, ret;
+	au_id_t auid;
+	int sorf;
 
 	if (ar->k_ar_commit & AR_COMMIT_USER) {
 		error = audit_record_write(audit_vp, audit_cred, audit_td,
@@ -324,10 +328,18 @@
 			panic("audit_worker: write error %d\n", error);
 		else if (error)
 			printf("audit_worker: write error %d\n", error);
-		audit_pipe_submit(ar->k_udata, ar->k_ulen);
+		audit_pipe_submit_user(ar->k_udata, ar->k_ulen);
 	}
 
 	if (ar->k_ar_commit & AR_COMMIT_KERNEL) {
+		auid = ar->k_ar.ar_subj_auid;
+		event = ar->k_ar.ar_event;
+		class = au_event_class(event);
+		if (ar->k_ar.ar_errno == 0)
+			sorf = AU_PRS_SUCCESS;
+		else
+			sorf = AU_PRS_FAILURE;
+
 		ret = kaudit_to_bsm(ar, &bsm);
 		switch (ret) {
 		case BSM_NOAUDIT:
@@ -346,7 +358,8 @@
 			else if (error)
 				printf("audit_worker: write error %d\n",
 				    error);
-			audit_pipe_submit(bsm->data, bsm->len);
+			audit_pipe_submit(auid, event, class, sorf,
+			    bsm->data, bsm->len);
 			kau_free(bsm);
 			break;
 


More information about the trustedbsd-cvs mailing list