summaryrefslogtreecommitdiffstats
path: root/sys/security
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2016-01-23 07:35:29 +0000
committerkib <kib@FreeBSD.org>2016-01-23 07:35:29 +0000
commit7908c6241f1c59bddddadbccb54a51812e494702 (patch)
tree7f73650f22a1691c279659c4e4d5437a7717a7eb /sys/security
parent00ce898270eae44f059f68b2848af2ad68dd93ec (diff)
downloadFreeBSD-src-7908c6241f1c59bddddadbccb54a51812e494702.zip
FreeBSD-src-7908c6241f1c59bddddadbccb54a51812e494702.tar.gz
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.
Diffstat (limited to 'sys/security')
-rw-r--r--sys/security/audit/audit_worker.c60
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);
}
/*
OpenPOWER on IntegriCloud