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>