Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Jan 2016 07:35:29 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r294619 - stable/10/sys/security/audit
Message-ID:  <201601230735.u0N7ZTGv012063@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sat Jan 23 07:35:29 2016
New Revision: 294619
URL: https://svnweb.freebsd.org/changeset/base/294619

Log:
  MFC r294137:
  Do not panic when the filesystem which carries the audit files, is unmounted
  and audit is active.  Do not write to the suspended fs.

Modified:
  stable/10/sys/security/audit/audit_worker.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/security/audit/audit_worker.c
==============================================================================
--- stable/10/sys/security/audit/audit_worker.c	Sat Jan 23 07:33:02 2016	(r294618)
+++ stable/10/sys/security/audit/audit_worker.c	Sat Jan 23 07:35:29 2016	(r294619)
@@ -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);
 }
 
 /*



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