+ /* KVV maybe we should take a context as a param to audit_write? */
+ struct vfs_context context;
+ off_t file_size;
+
+ mach_port_t audit_port;
+
+ /*
+ * First, gather statistics on the audit log file and file system
+ * so that we know how we're doing on space. In both cases,
+ * if we're unable to perform the operation, we drop the record
+ * and return. However, this is arguably an assertion failure.
+ */
+ context.vc_proc = p;
+ context.vc_ucred = cred;
+ ret = vfs_update_vfsstat(vp->v_mount, &context);
+ if (ret)
+ goto out;
+
+ /* update the global stats struct */
+ if ((ret = vnode_size(vp, &file_size, &context)) != 0)
+ goto out;
+ audit_fstat.af_currsz = file_size;
+
+ /*
+ * Send a message to the audit daemon when disk space is getting
+ * low.
+ * XXX Need to decide what to do if the trigger to the audit daemon
+ * fails.
+ */
+ if(host_get_audit_control_port(host_priv_self(), &audit_port)
+ != KERN_SUCCESS)
+ printf("Cannot get audit control port\n");
+
+ if (audit_port != MACH_PORT_NULL) {
+ uint64_t temp;
+
+ /*
+ * If we fall below percent free blocks, then trigger the
+ * audit daemon to do something about it.
+ */
+ if (audit_qctrl.aq_minfree != 0) {
+ temp = mnt_stat->f_blocks / (100 / audit_qctrl.aq_minfree);
+ if (mnt_stat->f_bfree < temp) {
+ ret = audit_triggers(audit_port,
+ AUDIT_TRIGGER_LOW_SPACE);
+ if (ret != KERN_SUCCESS) {
+ printf(
+ "Failed audit_triggers(AUDIT_TRIGGER_LOW_SPACE): %d\n", ret);
+ /*
+ * XXX: What to do here? Disable auditing?
+ * panic?
+ */
+ }
+ }
+ }
+ /* Check if the current log file is full; if so, call for
+ * a log rotate. This is not an exact comparison; we may
+ * write some records over the limit. If that's not
+ * acceptable, then add a fudge factor here.
+ */
+ if ((audit_fstat.af_filesz != 0) &&
+ (audit_file_rotate_wait == 0) &&
+ (file_size >= audit_fstat.af_filesz)) {
+ audit_file_rotate_wait = 1;
+ ret = audit_triggers(audit_port,
+ AUDIT_TRIGGER_FILE_FULL);
+ if (ret != KERN_SUCCESS) {
+ printf(
+ "Failed audit_triggers(AUDIT_TRIGGER_FILE_FULL): %d\n", ret);
+ /* XXX what to do here? */
+ }
+ }
+ }
+
+ /*
+ * If the estimated amount of audit data in the audit event queue
+ * (plus records allocated but not yet queued) has reached the
+ * amount of free space on the disk, then we need to go into an
+ * audit fail stop state, in which we do not permit the
+ * allocation/committing of any new audit records. We continue to
+ * process packets but don't allow any activities that might
+ * generate new records. In the future, we might want to detect
+ * when space is available again and allow operation to continue,
+ * but this behavior is sufficient to meet fail stop requirements
+ * in CAPP.
+ */
+ if (audit_fail_stop &&
+ (unsigned long)
+ ((audit_q_len + audit_pre_q_len + 1) * MAX_AUDIT_RECORD_SIZE) /
+ mnt_stat->f_bsize >= (unsigned long)(mnt_stat->f_bfree)) {
+ printf(
+ "audit_worker: free space below size of audit queue, failing stop\n");
+ audit_in_failure = 1;
+ }