svn commit: r244324 - in stable/9/sys: kern security/audit
Pawel Jakub Dawidek
pjd at FreeBSD.org
Sun Dec 16 23:41:36 UTC 2012
Author: pjd
Date: Sun Dec 16 23:41:34 2012
New Revision: 244324
URL: http://svnweb.freebsd.org/changeset/base/244324
Log:
MFC r243719,r243720,r243722,r243723,r243726,r243727,r243746:
r243719:
IFp4 @208450:
Remove redundant call to AUDIT_ARG_UPATH1().
Path will be remembered by the following NDINIT(AUDITVNODE1) call.
Sponsored by: The FreeBSD Foundation (auditdistd)
r243720:
IFp4 @208381:
For VOP_GETATTR() we just need vnode to be shared-locked.
Sponsored by: The FreeBSD Foundation (auditdistd)
r243722:
IFp4 @208382:
Currently on each record write we call VFS_STATFS() to get available space
on the file system as well as VOP_GETATTR() to get trail file size.
We can assume that trail file is only updated by the audit worker, so instead
of asking for file size on every write, get file size on trail switch only
(it should be zero, but it's not expensive) and use global variable audit_size
protected by the audit worker lock to keep track of trail file's size.
This eliminates VOP_GETATTR() call for every write. VFS_STATFS() is satisfied
from in-memory data (mount->mnt_stat), so shouldn't be expensive.
Sponsored by: The FreeBSD Foundation (auditdistd)
r243723:
IFp4 @208383:
Currently when we discover that trail file is greater than configured
limit we send AUDIT_TRIGGER_ROTATE_KERNEL trigger to the auditd daemon
once. If for some reason auditd didn't rotate trail file it will never
be rotated.
Change it by sending the trigger when trail file size grows by the
configured limit. For example if the limit is 1MB, we will send trigger
on 1MB, 2MB, 3MB, etc.
This is also needed for the auditd change that will be committed soon
where auditd may ignore the trigger - it might be ignored if kernel
requests the trail file to be rotated too quickly (often than once a second)
which would result in overwriting previous trail file.
Sponsored by: The FreeBSD Foundation (auditdistd)
r243726:
IFp4 @208451:
Fix path handling for *at() syscalls.
Before the change directory descriptor was totally ignored,
so the relative path argument was appended to current working
directory path and not to the path provided by descriptor, thus
wrong paths were stored in audit logs.
Now that we use directory descriptor in vfs_lookup, move
AUDIT_ARG_UPATH1() and AUDIT_ARG_UPATH2() calls to the place where
we hold file descriptors table lock, so we are sure paths will
be resolved according to the same directory in audit record and
in actual operation.
Sponsored by: The FreeBSD Foundation (auditdistd)
Reviewed by: rwatson
r243727:
IFp4 @208452:
Audit handling for missing events:
- AUE_READLINKAT
- AUE_FACCESSAT
- AUE_MKDIRAT
- AUE_MKFIFOAT
- AUE_MKNODAT
- AUE_SYMLINKAT
Sponsored by: FreeBSD Foundation (auditdistd)
r243746:
Fix one more compilation issue.
Sponsored by: FreeBSD Foundation (auditdistd)
Modified:
stable/9/sys/kern/vfs_lookup.c
stable/9/sys/kern/vfs_mount.c
stable/9/sys/security/audit/audit.c
stable/9/sys/security/audit/audit.h
stable/9/sys/security/audit/audit_arg.c
stable/9/sys/security/audit/audit_bsm.c
stable/9/sys/security/audit/audit_bsm_klib.c
stable/9/sys/security/audit/audit_private.h
stable/9/sys/security/audit/audit_worker.c
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/kern/vfs_lookup.c
==============================================================================
--- stable/9/sys/kern/vfs_lookup.c Sun Dec 16 23:29:56 2012 (r244323)
+++ stable/9/sys/kern/vfs_lookup.c Sun Dec 16 23:41:34 2012 (r244324)
@@ -163,17 +163,6 @@ namei(struct nameidata *ndp)
error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
MAXPATHLEN, (size_t *)&ndp->ni_pathlen);
- if (error == 0) {
- /*
- * If we are auditing the kernel pathname, save the user
- * pathname.
- */
- if (cnp->cn_flags & AUDITVNODE1)
- AUDIT_ARG_UPATH1(td, cnp->cn_pnbuf);
- if (cnp->cn_flags & AUDITVNODE2)
- AUDIT_ARG_UPATH2(td, cnp->cn_pnbuf);
- }
-
/*
* Don't allow empty pathnames.
*/
@@ -216,6 +205,14 @@ namei(struct nameidata *ndp)
ndp->ni_rootdir = fdp->fd_rdir;
ndp->ni_topdir = fdp->fd_jdir;
+ /*
+ * If we are auditing the kernel pathname, save the user pathname.
+ */
+ if (cnp->cn_flags & AUDITVNODE1)
+ AUDIT_ARG_UPATH1(td, ndp->ni_dirfd, cnp->cn_pnbuf);
+ if (cnp->cn_flags & AUDITVNODE2)
+ AUDIT_ARG_UPATH2(td, ndp->ni_dirfd, cnp->cn_pnbuf);
+
dp = NULL;
if (cnp->cn_pnbuf[0] != '/') {
if (ndp->ni_startdir != NULL) {
Modified: stable/9/sys/kern/vfs_mount.c
==============================================================================
--- stable/9/sys/kern/vfs_mount.c Sun Dec 16 23:29:56 2012 (r244323)
+++ stable/9/sys/kern/vfs_mount.c Sun Dec 16 23:41:34 2012 (r244324)
@@ -1169,7 +1169,6 @@ sys_unmount(td, uap)
}
mtx_unlock(&mountlist_mtx);
} else {
- AUDIT_ARG_UPATH1(td, pathbuf);
/*
* Try to find global path for path argument.
*/
Modified: stable/9/sys/security/audit/audit.c
==============================================================================
--- stable/9/sys/security/audit/audit.c Sun Dec 16 23:29:56 2012 (r244323)
+++ stable/9/sys/security/audit/audit.c Sun Dec 16 23:41:34 2012 (r244324)
@@ -691,7 +691,7 @@ audit_proc_coredump(struct thread *td, c
if (path != NULL) {
pathp = &ar->k_ar.ar_arg_upath1;
*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK);
- audit_canon_path(td, path, *pathp);
+ audit_canon_path(td, AT_FDCWD, path, *pathp);
ARG_SET_VALID(ar, ARG_UPATH1);
}
ar->k_ar.ar_arg_signum = td->td_proc->p_sig;
Modified: stable/9/sys/security/audit/audit.h
==============================================================================
--- stable/9/sys/security/audit/audit.h Sun Dec 16 23:29:56 2012 (r244323)
+++ stable/9/sys/security/audit/audit.h Sun Dec 16 23:41:34 2012 (r244324)
@@ -99,8 +99,8 @@ void audit_arg_sockaddr(struct thread *
void audit_arg_auid(uid_t auid);
void audit_arg_auditinfo(struct auditinfo *au_info);
void audit_arg_auditinfo_addr(struct auditinfo_addr *au_info);
-void audit_arg_upath1(struct thread *td, char *upath);
-void audit_arg_upath2(struct thread *td, char *upath);
+void audit_arg_upath1(struct thread *td, int dirfd, char *upath);
+void audit_arg_upath2(struct thread *td, int dirfd, char *upath);
void audit_arg_vnode1(struct vnode *vp);
void audit_arg_vnode2(struct vnode *vp);
void audit_arg_text(char *text);
@@ -276,14 +276,14 @@ void audit_thread_free(struct thread *t
audit_arg_uid((uid)); \
} while (0)
-#define AUDIT_ARG_UPATH1(td, upath) do { \
+#define AUDIT_ARG_UPATH1(td, dirfd, upath) do { \
if (AUDITING_TD(curthread)) \
- audit_arg_upath1((td), (upath)); \
+ audit_arg_upath1((td), (dirfd), (upath)); \
} while (0)
-#define AUDIT_ARG_UPATH2(td, upath) do { \
+#define AUDIT_ARG_UPATH2(td, dirfd, upath) do { \
if (AUDITING_TD(curthread)) \
- audit_arg_upath2((td), (upath)); \
+ audit_arg_upath2((td), (dirfd), (upath)); \
} while (0)
#define AUDIT_ARG_VALUE(value) do { \
@@ -356,8 +356,8 @@ void audit_thread_free(struct thread *t
#define AUDIT_ARG_SUID(suid)
#define AUDIT_ARG_TEXT(text)
#define AUDIT_ARG_UID(uid)
-#define AUDIT_ARG_UPATH1(td, upath)
-#define AUDIT_ARG_UPATH2(td, upath)
+#define AUDIT_ARG_UPATH1(td, dirfd, upath)
+#define AUDIT_ARG_UPATH2(td, dirfd, upath)
#define AUDIT_ARG_VALUE(value)
#define AUDIT_ARG_VNODE1(vp)
#define AUDIT_ARG_VNODE2(vp)
Modified: stable/9/sys/security/audit/audit_arg.c
==============================================================================
--- stable/9/sys/security/audit/audit_arg.c Sun Dec 16 23:29:56 2012 (r244323)
+++ stable/9/sys/security/audit/audit_arg.c Sun Dec 16 23:41:34 2012 (r244324)
@@ -463,7 +463,8 @@ audit_arg_sockaddr(struct thread *td, st
break;
case AF_UNIX:
- audit_arg_upath1(td, ((struct sockaddr_un *)sa)->sun_path);
+ audit_arg_upath1(td, AT_FDCWD,
+ ((struct sockaddr_un *)sa)->sun_path);
ARG_SET_VALID(ar, ARG_SADDRUNIX);
break;
/* XXXAUDIT: default:? */
@@ -710,16 +711,16 @@ audit_arg_file(struct proc *p, struct fi
* freed when the audit record is freed.
*/
static void
-audit_arg_upath(struct thread *td, char *upath, char **pathp)
+audit_arg_upath(struct thread *td, int dirfd, char *upath, char **pathp)
{
if (*pathp == NULL)
*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK);
- audit_canon_path(td, upath, *pathp);
+ audit_canon_path(td, dirfd, upath, *pathp);
}
void
-audit_arg_upath1(struct thread *td, char *upath)
+audit_arg_upath1(struct thread *td, int dirfd, char *upath)
{
struct kaudit_record *ar;
@@ -727,12 +728,12 @@ audit_arg_upath1(struct thread *td, char
if (ar == NULL)
return;
- audit_arg_upath(td, upath, &ar->k_ar.ar_arg_upath1);
+ audit_arg_upath(td, dirfd, upath, &ar->k_ar.ar_arg_upath1);
ARG_SET_VALID(ar, ARG_UPATH1);
}
void
-audit_arg_upath2(struct thread *td, char *upath)
+audit_arg_upath2(struct thread *td, int dirfd, char *upath)
{
struct kaudit_record *ar;
@@ -740,7 +741,7 @@ audit_arg_upath2(struct thread *td, char
if (ar == NULL)
return;
- audit_arg_upath(td, upath, &ar->k_ar.ar_arg_upath2);
+ audit_arg_upath(td, dirfd, upath, &ar->k_ar.ar_arg_upath2);
ARG_SET_VALID(ar, ARG_UPATH2);
}
Modified: stable/9/sys/security/audit/audit_bsm.c
==============================================================================
--- stable/9/sys/security/audit/audit_bsm.c Sun Dec 16 23:29:56 2012 (r244323)
+++ stable/9/sys/security/audit/audit_bsm.c Sun Dec 16 23:41:34 2012 (r244324)
@@ -724,13 +724,6 @@ kaudit_to_bsm(struct kaudit_record *kar,
*/
break;
- case AUE_MKFIFO:
- if (ARG_IS_VALID(kar, ARG_MODE)) {
- tok = au_to_arg32(2, "mode", ar->ar_arg_mode);
- kau_write(rec, tok);
- }
- /* FALLTHROUGH */
-
case AUE_CHDIR:
case AUE_CHROOT:
case AUE_FSTATAT:
@@ -743,6 +736,7 @@ kaudit_to_bsm(struct kaudit_record *kar,
case AUE_LPATHCONF:
case AUE_PATHCONF:
case AUE_READLINK:
+ case AUE_READLINKAT:
case AUE_REVOKE:
case AUE_RMDIR:
case AUE_SEARCHFS:
@@ -762,6 +756,8 @@ kaudit_to_bsm(struct kaudit_record *kar,
case AUE_ACCESS:
case AUE_EACCESS:
+ case AUE_FACCESSAT:
+ ATFD1_TOKENS(1);
UPATH1_VNODE1_TOKENS;
if (ARG_IS_VALID(kar, ARG_VALUE)) {
tok = au_to_arg32(2, "mode", ar->ar_arg_value);
@@ -1059,6 +1055,10 @@ kaudit_to_bsm(struct kaudit_record *kar,
break;
case AUE_MKDIR:
+ case AUE_MKDIRAT:
+ case AUE_MKFIFO:
+ case AUE_MKFIFOAT:
+ ATFD1_TOKENS(1);
if (ARG_IS_VALID(kar, ARG_MODE)) {
tok = au_to_arg32(2, "mode", ar->ar_arg_mode);
kau_write(rec, tok);
@@ -1067,6 +1067,8 @@ kaudit_to_bsm(struct kaudit_record *kar,
break;
case AUE_MKNOD:
+ case AUE_MKNODAT:
+ ATFD1_TOKENS(1);
if (ARG_IS_VALID(kar, ARG_MODE)) {
tok = au_to_arg32(2, "mode", ar->ar_arg_mode);
kau_write(rec, tok);
@@ -1546,10 +1548,12 @@ kaudit_to_bsm(struct kaudit_record *kar,
break;
case AUE_SYMLINK:
+ case AUE_SYMLINKAT:
if (ARG_IS_VALID(kar, ARG_TEXT)) {
tok = au_to_text(ar->ar_arg_text);
kau_write(rec, tok);
}
+ ATFD1_TOKENS(1);
UPATH1_VNODE1_TOKENS;
break;
Modified: stable/9/sys/security/audit/audit_bsm_klib.c
==============================================================================
--- stable/9/sys/security/audit/audit_bsm_klib.c Sun Dec 16 23:29:56 2012 (r244323)
+++ stable/9/sys/security/audit/audit_bsm_klib.c Sun Dec 16 23:41:34 2012 (r244324)
@@ -462,13 +462,13 @@ auditon_command_event(int cmd)
* leave the filename starting with '/' in the audit log in this case.
*/
void
-audit_canon_path(struct thread *td, char *path, char *cpath)
+audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath)
{
struct vnode *cvnp, *rvnp;
char *rbuf, *fbuf, *copy;
struct filedesc *fdp;
struct sbuf sbf;
- int error, cwir;
+ int error, needslash, vfslocked;
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s: at %s:%d",
__func__, __FILE__, __LINE__);
@@ -491,10 +491,27 @@ audit_canon_path(struct thread *td, char
* path.
*/
if (*path != '/') {
- cvnp = fdp->fd_cdir;
- vhold(cvnp);
+ if (dirfd == AT_FDCWD) {
+ cvnp = fdp->fd_cdir;
+ vhold(cvnp);
+ } else {
+ /* XXX: fgetvp() that vhold()s vnode instead of vref()ing it would be better */
+ error = fgetvp(td, dirfd, 0, &cvnp);
+ if (error) {
+ cpath[0] = '\0';
+ if (rvnp != NULL)
+ vdrop(rvnp);
+ return;
+ }
+ vhold(cvnp);
+ vfslocked = VFS_LOCK_GIANT(cvnp->v_mount);
+ vrele(cvnp);
+ VFS_UNLOCK_GIANT(vfslocked);
+ }
+ needslash = (fdp->fd_rdir != cvnp);
+ } else {
+ needslash = 1;
}
- cwir = (fdp->fd_rdir == fdp->fd_cdir);
FILEDESC_SUNLOCK(fdp);
/*
* NB: We require that the supplied array be at least MAXPATHLEN bytes
@@ -536,7 +553,7 @@ audit_canon_path(struct thread *td, char
(void) sbuf_cat(&sbf, rbuf);
free(fbuf, M_TEMP);
}
- if (cwir == 0 || (cwir != 0 && cvnp == NULL))
+ if (needslash)
(void) sbuf_putc(&sbf, '/');
/*
* Now that we have processed any alternate root and relative path
Modified: stable/9/sys/security/audit/audit_private.h
==============================================================================
--- stable/9/sys/security/audit/audit_private.h Sun Dec 16 23:29:56 2012 (r244323)
+++ stable/9/sys/security/audit/audit_private.h Sun Dec 16 23:41:34 2012 (r244324)
@@ -388,7 +388,8 @@ au_event_t audit_flags_and_error_to_ope
au_event_t audit_flags_and_error_to_openatevent(int oflags, int error);
au_event_t audit_msgctl_to_event(int cmd);
au_event_t audit_semctl_to_event(int cmr);
-void audit_canon_path(struct thread *td, char *path, char *cpath);
+void audit_canon_path(struct thread *td, int dirfd, char *path,
+ char *cpath);
au_event_t auditon_command_event(int cmd);
/*
Modified: stable/9/sys/security/audit/audit_worker.c
==============================================================================
--- stable/9/sys/security/audit/audit_worker.c Sun Dec 16 23:29:56 2012 (r244323)
+++ stable/9/sys/security/audit/audit_worker.c Sun Dec 16 23:41:34 2012 (r244324)
@@ -88,6 +88,7 @@ static struct proc *audit_thread;
static int audit_file_rotate_wait;
static struct ucred *audit_cred;
static struct vnode *audit_vp;
+static off_t audit_size;
static struct sx audit_worker_lock;
#define AUDIT_WORKER_LOCK_INIT() sx_init(&audit_worker_lock, \
@@ -115,7 +116,6 @@ audit_record_write(struct vnode *vp, str
struct statfs *mnt_stat;
int error, vfslocked;
static int cur_fail;
- struct vattr vattr;
long temp;
AUDIT_WORKER_LOCK_ASSERT();
@@ -134,12 +134,6 @@ audit_record_write(struct vnode *vp, str
error = VFS_STATFS(vp->v_mount, mnt_stat);
if (error)
goto fail;
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- error = VOP_GETATTR(vp, &vattr, cred);
- VOP_UNLOCK(vp, 0);
- if (error)
- goto fail;
- audit_fstat.af_currsz = vattr.va_size;
/*
* We handle four different space-related limits:
@@ -196,11 +190,11 @@ audit_record_write(struct vnode *vp, str
* to the daemon. This is only approximate, which is fine as more
* records may be generated before the daemon rotates the file.
*/
- if ((audit_fstat.af_filesz != 0) && (audit_file_rotate_wait == 0) &&
- (vattr.va_size >= audit_fstat.af_filesz)) {
+ if (audit_fstat.af_filesz != 0 &&
+ audit_size >= audit_fstat.af_filesz * (audit_file_rotate_wait + 1)) {
AUDIT_WORKER_LOCK_ASSERT();
- audit_file_rotate_wait = 1;
+ audit_file_rotate_wait++;
(void)audit_send_trigger(AUDIT_TRIGGER_ROTATE_KERNEL);
}
@@ -239,6 +233,8 @@ audit_record_write(struct vnode *vp, str
goto fail_enospc;
else if (error)
goto fail;
+ AUDIT_WORKER_LOCK_ASSERT();
+ audit_size += len;
/*
* Catch completion of a queue drain here; if we're draining and the
@@ -452,10 +448,20 @@ audit_rotate_vnode(struct ucred *cred, s
struct ucred *old_audit_cred;
struct vnode *old_audit_vp;
int vfslocked;
+ struct vattr vattr;
KASSERT((cred != NULL && vp != NULL) || (cred == NULL && vp == NULL),
("audit_rotate_vnode: cred %p vp %p", cred, vp));
+ if (vp != NULL) {
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ if (VOP_GETATTR(vp, &vattr, cred) != 0)
+ vattr.va_size = 0;
+ VOP_UNLOCK(vp, 0);
+ } else {
+ vattr.va_size = 0;
+ }
+
/*
* Rotate the vnode/cred, and clear the rotate flag so that we will
* send a rotate trigger if the new file fills.
@@ -465,6 +471,7 @@ audit_rotate_vnode(struct ucred *cred, s
old_audit_vp = audit_vp;
audit_cred = cred;
audit_vp = vp;
+ audit_size = vattr.va_size;
audit_file_rotate_wait = 0;
audit_enabled = (audit_vp != NULL);
AUDIT_WORKER_UNLOCK();
More information about the svn-src-stable-9
mailing list