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"