diff options
author | Renato Botelho <renato@netgate.com> | 2016-01-25 08:56:15 -0200 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2016-01-25 08:56:15 -0200 |
commit | eb84e0723f3b4bc5e40024f66fe21c14b09e9ec4 (patch) | |
tree | fec6b99d018e13f1fccbe31478aaf29a28a55642 /sys/security/audit/audit_worker.c | |
parent | c50df8e1b90c4f9b8bbffa592477c129854776ce (diff) | |
parent | 94b1bbbd44bd88b6db1c00d795cdf7675b3ae254 (diff) | |
download | FreeBSD-src-eb84e0723f3b4bc5e40024f66fe21c14b09e9ec4.zip FreeBSD-src-eb84e0723f3b4bc5e40024f66fe21c14b09e9ec4.tar.gz |
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'sys/security/audit/audit_worker.c')
-rw-r--r-- | sys/security/audit/audit_worker.c | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/sys/security/audit/audit_worker.c b/sys/security/audit/audit_worker.c index caad5ac..f526cd4 100644 --- a/sys/security/audit/audit_worker.c +++ b/sys/security/audit/audit_worker.c @@ -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, struct ucred *cred, void *data, 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, struct ucred *cred, void *data, 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, struct ucred *cred, void *data, */ 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); } /* |