Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 19 Mar 2006 20:22:22 GMT
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 93595 for review
Message-ID:  <200603192022.k2JKMMg1023301@repoman.freebsd.org>

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

Change 93595 by rwatson@rwatson_peppercorn on 2006/03/19 20:22:12

	Pull BSM conversion logic out of audit_record_write(), as well as
	knowledge of user vs. kernel audit records into
	audit_worker_process_record().  This largely confines vnode
	knowledge to audit_record_write(), but avoids that logic knowing
	about BSM as opposed to byte streams.  This will allow us to
	improve our ability to support real-time audit stream processing
	by audit pipe consumers while auditing is disabled, but this
	support is not yet complete.

Affected files ...

.. //depot/projects/trustedbsd/audit3/sys/security/audit/audit_worker.c#7 edit

Differences ...

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

@@ -109,16 +109,18 @@
  * we accounted for.
  */
 static int
-audit_record_write(struct vnode *vp, struct kaudit_record *ar,
-    struct ucred *cred, struct thread *td)
+audit_record_write(struct vnode *vp, struct ucred *cred, struct thread *td,
+    void *data, size_t len)
 {
 	int ret;
 	long temp;
-	struct au_record *bsm;
 	struct vattr vattr;
 	struct statfs *mnt_stat = &vp->v_mount->mnt_stat;
 	int vfslocked;
 
+	if (vp == NULL)
+		return (0);
+
 	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 
 	/*
@@ -214,75 +216,9 @@
 		audit_in_failure = 1;
 	}
 
-	/*
-	 * If there is a user audit record attached to the kernel record,
-	 * then write the user record.
-	 *
-	 * XXX Need to decide a few things here: IF the user audit record is
-	 * written, but the write of the kernel record fails, what to do?
-	 * Should the kernel record come before or after the user record?
-	 * For now, we write the user record first, and we ignore errors.
-	 */
-	if (ar->k_ar_commit & AR_COMMIT_USER) {
-		/*
-		 * Try submitting the record to any active audit pipes.
-		 */
-		audit_pipe_submit((void *)ar->k_udata, ar->k_ulen);
-
-		/*
-		 * And to disk.
-		 */
-		ret = vn_rdwr(UIO_WRITE, vp, (void *)ar->k_udata, ar->k_ulen,
-		    (off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, cred, NULL,
-		    NULL, td);
-		if (ret)
-			goto out;
-	}
-
-	/*
-	 * Convert the internal kernel record to BSM format and write it out
-	 * if everything's OK.
-	 */
-	if (!(ar->k_ar_commit & AR_COMMIT_KERNEL)) {
-		ret = 0;
-		goto out;
-	}
-
-	/*
-	 * XXXAUDIT: Should we actually allow this conversion to fail?  With
-	 * sleeping memory allocation and invariants checks, perhaps not.
-	 */
-	ret = kaudit_to_bsm(ar, &bsm);
-	if (ret == BSM_NOAUDIT) {
-		ret = 0;
-		goto out;
-	}
-
-	/*
-	 * XXX: We drop the record on BSM conversion failure, but really this
-	 * is an assertion failure.
-	 */
-	if (ret == BSM_FAILURE) {
-		AUDIT_PRINTF(("BSM conversion failure\n"));
-		ret = EINVAL;
-		goto out;
-	}
-
-	/*
-	 * Try submitting the record to any active audit pipes.
-	 */
-	audit_pipe_submit((void *)bsm->data, bsm->len);
+	ret = vn_rdwr(UIO_WRITE, vp, data, len, (off_t)0, UIO_SYSSPACE,
+	    IO_APPEND|IO_UNIT, cred, NULL, NULL, td);
 
-	/*
-	 * XXX We should break the write functionality away from the BSM
-	 * record generation and have the BSM generation done before this
-	 * function is called. This function will then take the BSM record as
-	 * a parameter.
-	 */
-	ret = (vn_rdwr(UIO_WRITE, vp, (void *)bsm->data, bsm->len, (off_t)0,
-	    UIO_SYSSPACE, IO_APPEND|IO_UNIT, cred, NULL, NULL, td));
-	kau_free(bsm);
-
 out:
 	/*
 	 * When we're done processing the current record, we have to check to
@@ -386,27 +322,55 @@
 }
 
 /*
- * Given a kernel audit record, process as required.  Currently, that means
- * passing it to audit_record_write(), but in the future it will mean
- * converting it to BSM and then routing it to various possible output
- * streams, including the audit trail and audit pipes.  The caller will free
- * the record.
+ * Given a kernel audit record, process as required.  Kernel audit records
+ * are converted to one, or possibly two, BSM records, depending on whether
+ * there is a user audit record present also.  Kernel records need be
+ * converted to BSM before they can be written out.  Both types will be
+ * written to disk, and audit pipes.
  */
 static void
 audit_worker_process_record(struct vnode *audit_vp, struct ucred *audit_cred,
     struct thread *audit_td, struct kaudit_record *ar)
 {
-	int error;
+	struct au_record *bsm;
+	int error, ret;
 
-	if (audit_vp == NULL)
-		return;
-
-	error = audit_record_write(audit_vp, ar, audit_cred, audit_td);
-	if (error) {
-		if (audit_panic_on_write_fail)
+	if (ar->k_ar_commit & AR_COMMIT_USER) {
+		error = audit_record_write(audit_vp, audit_cred, audit_td,
+		    ar->k_udata, ar->k_ulen);
+		if (error && audit_panic_on_write_fail)
 			panic("audit_worker: write error %d\n", error);
-		else
+		else if (error)
 			printf("audit_worker: write error %d\n", error);
+		audit_pipe_submit(ar->k_udata, ar->k_ulen);
+	}
+
+	if (ar->k_ar_commit & AR_COMMIT_KERNEL) {
+		ret = kaudit_to_bsm(ar, &bsm);
+		switch (ret) {
+		case BSM_NOAUDIT:
+			break;
+
+		case BSM_FAILURE:
+			printf("audit_worker_process_record: BSM_FAILURE\n");
+			break;
+
+		case BSM_SUCCESS:
+			error = audit_record_write(audit_vp, audit_cred,
+			    audit_td, bsm->data, bsm->len);
+			if (error && audit_panic_on_write_fail)
+				panic("audit_worker: write error %d\n",
+				    error);
+			else if (error)
+				printf("audit_worker: write error %d\n",
+				    error);
+			audit_pipe_submit(bsm->data, bsm->len);
+			kau_free(bsm);
+			break;
+
+		default:
+			panic("kaudit_to_bsm returned %d", ret);
+		}
 	}
 }
 



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