Author: kib
Date: Sat Jan 16 10:06:33 2016
New Revision: 294137
URL: https://svnweb.freebsd.org/changeset/base/294137

Log:
  Busy the mount point which is the owner of the audit vnode, around
  audit_record_write().  This is important so that VFS_STATFS() is not
  done on the NULL or freed mp and the check for free space is
  consistent with the vnode used for write.
  
  Add vn_start_write() braces around VOP_FSYNC() calls on the audit vnode.
  
  Move repeated code to fsync vnode and panic to the helper
  audit_worker_sync_vp().
  
  Reviewed by:  rwatson
  Tested by:    pho
  Sponsored by: The FreeBSD Foundation
  MFC after:    1 week

Modified:
  head/sys/security/audit/audit_worker.c

Modified: head/sys/security/audit/audit_worker.c
==============================================================================
--- head/sys/security/audit/audit_worker.c      Sat Jan 16 07:56:49 2016        
(r294136)
+++ head/sys/security/audit/audit_worker.c      Sat Jan 16 10:06:33 2016        
(r294137)
@@ -71,6 +71,8 @@ __FBSDID("$FreeBSD$");
 
 #include <vm/uma.h>
 
+#include <machine/stdarg.h>
+
 /*
  * Worker thread that will schedule disk I/O, etc.
  */
@@ -98,6 +100,26 @@ static struct sx     audit_worker_lock;
 #define        AUDIT_WORKER_LOCK()             sx_xlock(&audit_worker_lock)
 #define        AUDIT_WORKER_UNLOCK()           sx_xunlock(&audit_worker_lock)
 
+static void
+audit_worker_sync_vp(struct vnode *vp, struct mount *mp, const char *fmt, ...)
+{
+       struct mount *mp1;
+       int error;
+       va_list va;
+
+       va_start(va, fmt);
+       error = vn_start_write(vp, &mp1, 0);
+       if (error == 0) {
+               VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
+               (void)VOP_FSYNC(vp, MNT_WAIT, curthread);
+               VOP_UNLOCK(vp, 0);
+               vn_finished_write(mp1);
+       }
+       vfs_unbusy(mp);
+       vpanic(fmt, va);
+       va_end(va);
+}
+
 /*
  * Write an audit record to a file, performed as the last stage after both
  * preselection and BSM conversion.  Both space management and write failures
@@ -114,6 +136,7 @@ audit_record_write(struct vnode *vp, str
        static struct timeval last_fail;
        static int cur_lowspace_trigger;
        struct statfs *mnt_stat;
+       struct mount *mp;
        int error;
        static int cur_fail;
        long temp;
@@ -123,15 +146,25 @@ audit_record_write(struct vnode *vp, str
        if (vp == NULL)
                return;
 
-       mnt_stat = &vp->v_mount->mnt_stat;
+       mp = vp->v_mount;
+       if (mp == NULL) {
+               error = EINVAL;
+               goto fail;
+       }
+       error = vfs_busy(mp, 0);
+       if (error != 0) {
+               mp = NULL;
+               goto fail;
+       }
+       mnt_stat = &mp->mnt_stat;
 
        /*
         * First, gather statistics on the audit log file and file system so
         * that we know how we're doing on space.  Consider failure of these
         * operations to indicate a future inability to write to the file.
         */
-       error = VFS_STATFS(vp->v_mount, mnt_stat);
-       if (error)
+       error = VFS_STATFS(mp, mnt_stat);
+       if (error != 0)
                goto fail;
 
        /*
@@ -246,13 +279,12 @@ audit_record_write(struct vnode *vp, str
         */
        if (audit_in_failure) {
                if (audit_q_len == 0 && audit_pre_q_len == 0) {
-                       VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
-                       (void)VOP_FSYNC(vp, MNT_WAIT, curthread);
-                       VOP_UNLOCK(vp, 0);
-                       panic("Audit store overflow; record queue drained.");
+                       audit_worker_sync_vp(vp, mp,
+                           "Audit store overflow; record queue drained.");
                }
        }
 
+       vfs_unbusy(mp);
        return;
 
 fail_enospc:
@@ -262,10 +294,8 @@ fail_enospc:
         * space, or ENOSPC returned by the vnode write call.
         */
        if (audit_fail_stop) {
-               VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
-               (void)VOP_FSYNC(vp, MNT_WAIT, curthread);
-               VOP_UNLOCK(vp, 0);
-               panic("Audit log space exhausted and fail-stop set.");
+               audit_worker_sync_vp(vp, mp,
+                   "Audit log space exhausted and fail-stop set.");
        }
        (void)audit_send_trigger(AUDIT_TRIGGER_NO_SPACE);
        audit_suspended = 1;
@@ -277,12 +307,12 @@ fail:
         * lost, which may require an immediate system halt.
         */
        if (audit_panic_on_write_fail) {
-               VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
-               (void)VOP_FSYNC(vp, MNT_WAIT, curthread);
-               VOP_UNLOCK(vp, 0);
-               panic("audit_worker: write error %d\n", error);
+               audit_worker_sync_vp(vp, mp,
+                   "audit_worker: write error %d\n", error);
        } else if (ppsratecheck(&last_fail, &cur_fail, 1))
                printf("audit_worker: write error %d\n", error);
+       if (mp != NULL)
+               vfs_unbusy(mp);
 }
 
 /*
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to