mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-20 16:54:02 +00:00
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
This commit is contained in:
parent
b9d2b617ca
commit
27725229dc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=294137
|
@ -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 @@ audit_record_write(struct vnode *vp, struct ucred *cred, void *data,
|
|||
* 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 @@ audit_record_write(struct vnode *vp, struct ucred *cred, void *data,
|
|||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue