summaryrefslogtreecommitdiffstats
path: root/sys/security/audit
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2007-06-07 22:27:15 +0000
committerrwatson <rwatson@FreeBSD.org>2007-06-07 22:27:15 +0000
commit9f332c91ef20b2392e96c3aed469ba04aeb7b13f (patch)
tree23e84b7f5fd5465f12ed2c509373ee128d73a43a /sys/security/audit
parent1f72bba08402b15a14e6c65f84d0d252f2d2bc1c (diff)
downloadFreeBSD-src-9f332c91ef20b2392e96c3aed469ba04aeb7b13f.zip
FreeBSD-src-9f332c91ef20b2392e96c3aed469ba04aeb7b13f.tar.gz
Move per-process audit state from a pointer in the proc structure to
embedded storage in struct ucred. This allows audit state to be cached with the thread, avoiding locking operations with each system call, and makes it available in asynchronous execution contexts, such as deep in the network stack or VFS. Reviewed by: csjp Approved by: re (kensmith) Obtained from: TrustedBSD Project
Diffstat (limited to 'sys/security/audit')
-rw-r--r--sys/security/audit/audit.c78
-rw-r--r--sys/security/audit/audit.h10
-rw-r--r--sys/security/audit/audit_arg.c6
-rw-r--r--sys/security/audit/audit_syscalls.c201
4 files changed, 133 insertions, 162 deletions
diff --git a/sys/security/audit/audit.c b/sys/security/audit/audit.c
index 6f1fef6..96ea78b 100644
--- a/sys/security/audit/audit.c
+++ b/sys/security/audit/audit.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1999-2005 Apple Computer, Inc.
- * Copyright (c) 2006 Robert N. M. Watson
+ * Copyright (c) 2006-2007 Robert N. M. Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -71,7 +71,7 @@
#include <vm/uma.h>
static uma_zone_t audit_record_zone;
-static MALLOC_DEFINE(M_AUDITPROC, "audit_proc", "Audit process storage");
+static MALLOC_DEFINE(M_AUDITCRED, "audit_cred", "Audit cred storage");
MALLOC_DEFINE(M_AUDITDATA, "audit_data", "Audit data storage");
MALLOC_DEFINE(M_AUDITPATH, "audit_path", "Audit path storage");
MALLOC_DEFINE(M_AUDITTEXT, "audit_text", "Audit text storage");
@@ -176,13 +176,11 @@ audit_record_ctor(void *mem, int size, void *arg, int flags)
ar->k_ar.ar_subj_ruid = td->td_ucred->cr_ruid;
ar->k_ar.ar_subj_rgid = td->td_ucred->cr_rgid;
ar->k_ar.ar_subj_egid = td->td_ucred->cr_groups[0];
- PROC_LOCK(td->td_proc);
- ar->k_ar.ar_subj_auid = td->td_proc->p_au->ai_auid;
- ar->k_ar.ar_subj_asid = td->td_proc->p_au->ai_asid;
+ ar->k_ar.ar_subj_auid = td->td_ucred->cr_audit.ai_auid;
+ ar->k_ar.ar_subj_asid = td->td_ucred->cr_audit.ai_asid;
ar->k_ar.ar_subj_pid = td->td_proc->p_pid;
- ar->k_ar.ar_subj_amask = td->td_proc->p_au->ai_mask;
- ar->k_ar.ar_subj_term_addr = td->td_proc->p_au->ai_termid;
- PROC_UNLOCK(td->td_proc);
+ ar->k_ar.ar_subj_amask = td->td_ucred->cr_audit.ai_mask;
+ ar->k_ar.ar_subj_term_addr = td->td_ucred->cr_audit.ai_termid;
return (0);
}
@@ -470,11 +468,11 @@ audit_syscall_enter(unsigned short code, struct thread *td)
* Check which audit mask to use; either the kernel non-attributable
* event mask or the process audit mask.
*/
- auid = td->td_proc->p_au->ai_auid;
+ auid = td->td_ucred->cr_audit.ai_auid;
if (auid == AU_DEFAUDITID)
aumask = &audit_nae_mask;
else
- aumask = &td->td_proc->p_au->ai_mask;
+ aumask = &td->td_ucred->cr_audit.ai_mask;
/*
* Allocate an audit record, if preselection allows it, and store in
@@ -533,92 +531,68 @@ audit_syscall_exit(int error, struct thread *td)
}
/*
- * Allocate storage for a new process (init, or otherwise).
+ * Copy audit state from an existing credential to a new credential.
*/
void
-audit_proc_alloc(struct proc *p)
+audit_cred_copy(struct ucred *src, struct ucred *dest)
{
- KASSERT(p->p_au == NULL, ("audit_proc_alloc: p->p_au != NULL (%d)",
- p->p_pid));
- p->p_au = malloc(sizeof(*(p->p_au)), M_AUDITPROC, M_WAITOK);
+ bcopy(&src->cr_audit, &dest->cr_audit, sizeof(dest->cr_audit));
}
/*
- * Allocate storage for a new thread.
+ * Free audit state from a credential when the credential is freed.
*/
void
-audit_thread_alloc(struct thread *td)
+audit_cred_destroy(struct ucred *cred)
{
- td->td_ar = NULL;
+ bzero(&cred->cr_audit, sizeof(cred->cr_audit));
}
/*
- * Thread destruction.
+ * Allocate audit state for a new credential.
*/
void
-audit_thread_free(struct thread *td)
+audit_cred_init(struct ucred *cred)
{
- KASSERT(td->td_ar == NULL, ("audit_thread_free: td_ar != NULL"));
+ bzero(&cred->cr_audit, sizeof(cred->cr_audit));
}
/*
* Initialize audit information for the first kernel process (proc 0) and for
* the first user process (init).
- *
- * XXX It is not clear what the initial values should be for audit ID,
- * session ID, etc.
*/
void
-audit_proc_kproc0(struct proc *p)
+audit_cred_kproc0(struct ucred *cred)
{
- KASSERT(p->p_au != NULL, ("audit_proc_kproc0: p->p_au == NULL (%d)",
- p->p_pid));
-
- bzero(p->p_au, sizeof(*(p)->p_au));
}
void
-audit_proc_init(struct proc *p)
+audit_cred_proc1(struct ucred *cred)
{
- KASSERT(p->p_au != NULL, ("audit_proc_init: p->p_au == NULL (%d)",
- p->p_pid));
-
- bzero(p->p_au, sizeof(*(p)->p_au));
- p->p_au->ai_auid = AU_DEFAUDITID;
+ cred->cr_audit.ai_auid = AU_DEFAUDITID;
}
/*
- * Copy the audit info from the parent process to the child process when a
- * fork takes place.
+ * Allocate storage for a new thread.
*/
void
-audit_proc_fork(struct proc *parent, struct proc *child)
+audit_thread_alloc(struct thread *td)
{
- PROC_LOCK_ASSERT(parent, MA_OWNED);
- PROC_LOCK_ASSERT(child, MA_OWNED);
- KASSERT(parent->p_au != NULL,
- ("audit_proc_fork: parent->p_au == NULL (%d)", parent->p_pid));
- KASSERT(child->p_au != NULL,
- ("audit_proc_fork: child->p_au == NULL (%d)", child->p_pid));
-
- bcopy(parent->p_au, child->p_au, sizeof(*child->p_au));
+ td->td_ar = NULL;
}
/*
- * Free the auditing structure for the process.
+ * Thread destruction.
*/
void
-audit_proc_free(struct proc *p)
+audit_thread_free(struct thread *td)
{
- KASSERT(p->p_au != NULL, ("p->p_au == NULL (%d)", p->p_pid));
-
- free(p->p_au, M_AUDITPROC);
- p->p_au = NULL;
+ KASSERT(td->td_ar == NULL, ("audit_thread_free: td_ar != NULL"));
}
diff --git a/sys/security/audit/audit.h b/sys/security/audit/audit.h
index bfb3b58..6550b09 100644
--- a/sys/security/audit/audit.h
+++ b/sys/security/audit/audit.h
@@ -171,11 +171,11 @@ void audit_arg_file(struct proc *p, struct file *fp);
void audit_arg_argv(char *argv, int argc, int length);
void audit_arg_envv(char *envv, int envc, int length);
void audit_sysclose(struct thread *td, int fd);
-void audit_proc_alloc(struct proc *p);
-void audit_proc_kproc0(struct proc *p);
-void audit_proc_init(struct proc *p);
-void audit_proc_fork(struct proc *parent, struct proc *child);
-void audit_proc_free(struct proc *p);
+void audit_cred_copy(struct ucred *src, struct ucred *dest);
+void audit_cred_destroy(struct ucred *cred);
+void audit_cred_init(struct ucred *cred);
+void audit_cred_kproc0(struct ucred *cred);
+void audit_cred_proc1(struct ucred *cred);
void audit_thread_alloc(struct thread *td);
void audit_thread_free(struct thread *td);
diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c
index b5e565a..914f918 100644
--- a/sys/security/audit/audit_arg.c
+++ b/sys/security/audit/audit_arg.c
@@ -364,13 +364,13 @@ audit_arg_process(struct proc *p)
if (ar == NULL)
return;
- ar->k_ar.ar_arg_auid = p->p_au->ai_auid;
+ ar->k_ar.ar_arg_auid = p->p_ucred->cr_audit.ai_auid;
ar->k_ar.ar_arg_euid = p->p_ucred->cr_uid;
ar->k_ar.ar_arg_egid = p->p_ucred->cr_groups[0];
ar->k_ar.ar_arg_ruid = p->p_ucred->cr_ruid;
ar->k_ar.ar_arg_rgid = p->p_ucred->cr_rgid;
- ar->k_ar.ar_arg_asid = p->p_au->ai_asid;
- ar->k_ar.ar_arg_termid_addr = p->p_au->ai_termid;
+ ar->k_ar.ar_arg_asid = p->p_ucred->cr_audit.ai_asid;
+ ar->k_ar.ar_arg_termid_addr = p->p_ucred->cr_audit.ai_termid;
ar->k_ar.ar_arg_pid = p->p_pid;
ARG_SET_VALID(ar, ARG_AUID | ARG_EUID | ARG_EGID | ARG_RUID |
ARG_RGID | ARG_ASID | ARG_TERMID_ADDR | ARG_PID | ARG_PROCESS);
diff --git a/sys/security/audit/audit_syscalls.c b/sys/security/audit/audit_syscalls.c
index cba0aa7..81200ab 100644
--- a/sys/security/audit/audit_syscalls.c
+++ b/sys/security/audit/audit_syscalls.c
@@ -156,6 +156,7 @@ free_out:
int
auditon(struct thread *td, struct auditon_args *uap)
{
+ struct ucred *newcred, *oldcred;
int error;
union auditon_udata udata;
struct proc *tp;
@@ -313,47 +314,53 @@ auditon(struct thread *td, struct auditon_args *uap)
case A_GETPINFO:
if (udata.au_aupinfo.ap_pid < 1)
return (EINVAL);
-
if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
return (EINVAL);
if (p_cansee(td, tp) != 0) {
PROC_UNLOCK(tp);
return (EINVAL);
}
-
- if (tp->p_au->ai_termid.at_type == AU_IPv6) {
+ if (tp->p_ucred->cr_audit.ai_termid.at_type == AU_IPv6) {
PROC_UNLOCK(tp);
return (EINVAL);
}
- udata.au_aupinfo.ap_auid = tp->p_au->ai_auid;
+ udata.au_aupinfo.ap_auid =
+ tp->p_ucred->cr_audit.ai_auid;
udata.au_aupinfo.ap_mask.am_success =
- tp->p_au->ai_mask.am_success;
+ tp->p_ucred->cr_audit.ai_mask.am_success;
udata.au_aupinfo.ap_mask.am_failure =
- tp->p_au->ai_mask.am_failure;
+ tp->p_ucred->cr_audit.ai_mask.am_failure;
udata.au_aupinfo.ap_termid.machine =
- tp->p_au->ai_termid.at_addr[0];
+ tp->p_ucred->cr_audit.ai_termid.at_addr[0];
udata.au_aupinfo.ap_termid.port =
- (dev_t)tp->p_au->ai_termid.at_port;
- udata.au_aupinfo.ap_asid = tp->p_au->ai_asid;
+ (dev_t)tp->p_ucred->cr_audit.ai_termid.at_port;
+ udata.au_aupinfo.ap_asid =
+ tp->p_ucred->cr_audit.ai_asid;
PROC_UNLOCK(tp);
break;
case A_SETPMASK:
if (udata.au_aupinfo.ap_pid < 1)
return (EINVAL);
-
- if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
+ newcred = crget();
+ if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) {
+ crfree(newcred);
return (EINVAL);
+ }
if (p_cansee(td, tp) != 0) {
PROC_UNLOCK(tp);
+ crfree(newcred);
return (EINVAL);
}
-
- tp->p_au->ai_mask.am_success =
+ oldcred = tp->p_ucred;
+ crcopy(newcred, oldcred);
+ newcred->cr_audit.ai_mask.am_success =
udata.au_aupinfo.ap_mask.am_success;
- tp->p_au->ai_mask.am_failure =
+ newcred->cr_audit.ai_mask.am_failure =
udata.au_aupinfo.ap_mask.am_failure;
+ td->td_proc->p_ucred = newcred;
PROC_UNLOCK(tp);
+ crfree(oldcred);
break;
case A_SETFSIZE:
@@ -373,13 +380,16 @@ auditon(struct thread *td, struct auditon_args *uap)
return (EINVAL);
if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL)
return (EINVAL);
- udata.au_aupinfo_addr.ap_auid = tp->p_au->ai_auid;
+ udata.au_aupinfo_addr.ap_auid =
+ tp->p_ucred->cr_audit.ai_auid;
udata.au_aupinfo_addr.ap_mask.am_success =
- tp->p_au->ai_mask.am_success;
+ tp->p_ucred->cr_audit.ai_mask.am_success;
udata.au_aupinfo_addr.ap_mask.am_failure =
- tp->p_au->ai_mask.am_failure;
- udata.au_aupinfo_addr.ap_termid = tp->p_au->ai_termid;
- udata.au_aupinfo_addr.ap_asid = tp->p_au->ai_asid;
+ tp->p_ucred->cr_audit.ai_mask.am_failure;
+ udata.au_aupinfo_addr.ap_termid =
+ tp->p_ucred->cr_audit.ai_termid;
+ udata.au_aupinfo_addr.ap_asid =
+ tp->p_ucred->cr_audit.ai_asid;
PROC_UNLOCK(tp);
break;
@@ -431,64 +441,51 @@ int
getauid(struct thread *td, struct getauid_args *uap)
{
int error;
- au_id_t id;
if (jailed(td->td_ucred))
return (ENOSYS);
error = priv_check(td, PRIV_AUDIT_GETAUDIT);
if (error)
return (error);
-
- /*
- * XXX: Integer read on static pointer dereference: doesn't need
- * locking?
- */
- PROC_LOCK(td->td_proc);
- id = td->td_proc->p_au->ai_auid;
- PROC_UNLOCK(td->td_proc);
- return copyout(&id, uap->auid, sizeof(id));
+ return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid,
+ sizeof(td->td_ucred->cr_audit.ai_auid)));
}
/* ARGSUSED */
int
setauid(struct thread *td, struct setauid_args *uap)
{
- int error;
+ struct ucred *newcred, *oldcred;
au_id_t id;
+ int error;
if (jailed(td->td_ucred))
return (ENOSYS);
- error = priv_check(td, PRIV_AUDIT_SETAUDIT);
- if (error)
- return (error);
-
error = copyin(uap->auid, &id, sizeof(id));
if (error)
return (error);
-
audit_arg_auid(id);
-
+ newcred = crget();
+ PROC_LOCK(td->td_proc);
+ oldcred = td->td_proc->p_ucred;
+ crcopy(newcred, oldcred);
#ifdef MAC
- error = mac_check_proc_setauid(td->td_ucred, id);
+ error = mac_check_proc_setauid(oldcred, id);
if (error)
- return (error);
+ goto fail;
#endif
-
- /*
- * XXX: Integer write on static pointer dereference: doesn't need
- * locking?
- *
- * XXXAUDIT: Might need locking to serialize audit events in the same
- * order as change events? Or maybe that's an under-solveable
- * problem.
- *
- * XXXRW: Test privilege while holding the proc lock?
- */
- PROC_LOCK(td->td_proc);
- td->td_proc->p_au->ai_auid = id;
+ error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
+ if (error)
+ goto fail;
+ newcred->cr_audit.ai_auid = id;
+ td->td_proc->p_ucred = newcred;
PROC_UNLOCK(td->td_proc);
-
+ crfree(oldcred);
return (0);
+fail:
+ PROC_UNLOCK(td->td_proc);
+ crfree(newcred);
+ return (error);
}
/*
@@ -506,108 +503,108 @@ getaudit(struct thread *td, struct getaudit_args *uap)
error = priv_check(td, PRIV_AUDIT_GETAUDIT);
if (error)
return (error);
-
- PROC_LOCK(td->td_proc);
- if (td->td_proc->p_au->ai_termid.at_type == AU_IPv6) {
- PROC_UNLOCK(td->td_proc);
- return (E2BIG);
- }
bzero(&ai, sizeof(ai));
- ai.ai_auid = td->td_proc->p_au->ai_auid;
- ai.ai_mask = td->td_proc->p_au->ai_mask;
- ai.ai_asid = td->td_proc->p_au->ai_asid;
- ai.ai_termid.machine = td->td_proc->p_au->ai_termid.at_addr[0];
- ai.ai_termid.port = td->td_proc->p_au->ai_termid.at_port;
- PROC_UNLOCK(td->td_proc);
-
- return (copyout(&ai, uap->auditinfo, sizeof(ai)));
+ ai.ai_auid = td->td_ucred->cr_audit.ai_auid;
+ ai.ai_mask = td->td_ucred->cr_audit.ai_mask;
+ ai.ai_asid = td->td_ucred->cr_audit.ai_asid;
+ ai.ai_termid.machine = td->td_ucred->cr_audit.ai_termid.at_addr[0];
+ ai.ai_termid.port = td->td_ucred->cr_audit.ai_termid.at_port;
+ return (copyout(&ai, uap->auditinfo, sizeof(&ai)));
}
/* ARGSUSED */
int
setaudit(struct thread *td, struct setaudit_args *uap)
{
+ struct ucred *newcred, *oldcred;
struct auditinfo ai;
int error;
if (jailed(td->td_ucred))
return (ENOSYS);
- error = priv_check(td, PRIV_AUDIT_SETAUDIT);
- if (error)
- return (error);
-
error = copyin(uap->auditinfo, &ai, sizeof(ai));
if (error)
return (error);
-
audit_arg_auditinfo(&ai);
-
+ newcred = crget();
+ PROC_LOCK(td->td_proc);
+ oldcred = td->td_proc->p_ucred;
+ crcopy(newcred, oldcred);
#ifdef MAC
- error = mac_check_proc_setaudit(td->td_ucred, &ai);
+ error = mac_check_proc_setaudit(oldcred, &ai);
if (error)
- return (error);
+ goto fail;
#endif
-
- /*
- * XXXRW: Test privilege while holding the proc lock?
- */
- PROC_LOCK(td->td_proc);
- bzero(td->td_proc->p_au, sizeof(struct auditinfo_addr));
- td->td_proc->p_au->ai_auid = ai.ai_auid;
- td->td_proc->p_au->ai_mask = ai.ai_mask;
- td->td_proc->p_au->ai_asid = ai.ai_asid;
- td->td_proc->p_au->ai_termid.at_addr[0] = ai.ai_termid.machine;
- td->td_proc->p_au->ai_termid.at_port = ai.ai_termid.port;
- td->td_proc->p_au->ai_termid.at_type = AU_IPv4;
+ error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
+ if (error)
+ goto fail;
+ bzero(&newcred->cr_audit, sizeof(newcred->cr_audit));
+ newcred->cr_audit.ai_auid = ai.ai_auid;
+ newcred->cr_audit.ai_mask = ai.ai_mask;
+ newcred->cr_audit.ai_asid = ai.ai_asid;
+ newcred->cr_audit.ai_termid.at_addr[0] = ai.ai_termid.machine;
+ newcred->cr_audit.ai_termid.at_port = ai.ai_termid.port;
+ newcred->cr_audit.ai_termid.at_type = AU_IPv4;
+ td->td_proc->p_ucred = newcred;
PROC_UNLOCK(td->td_proc);
-
+ crfree(oldcred);
return (0);
+fail:
+ PROC_UNLOCK(td->td_proc);
+ crfree(newcred);
+ return (error);
}
/* ARGSUSED */
int
getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
{
- struct auditinfo_addr aia;
int error;
if (jailed(td->td_ucred))
return (ENOSYS);
+ if (uap->length < sizeof(*uap->auditinfo_addr))
+ return (EOVERFLOW);
error = priv_check(td, PRIV_AUDIT_GETAUDIT);
if (error)
return (error);
- if (uap->length < sizeof(aia))
- return (EOVERFLOW);
- PROC_LOCK(td->td_proc);
- aia = *td->td_proc->p_au;
- PROC_UNLOCK(td->td_proc);
- return (copyout(&aia, uap->auditinfo_addr, sizeof(aia)));
+ return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr,
+ sizeof(*uap->auditinfo_addr)));
}
/* ARGSUSED */
int
setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
{
+ struct ucred *newcred, *oldcred;
struct auditinfo_addr aia;
int error;
if (jailed(td->td_ucred))
return (ENOSYS);
- error = priv_check(td, PRIV_AUDIT_SETAUDIT);
+ error = copyin(uap->auditinfo_addr, &aia, sizeof(aia));
if (error)
return (error);
-
+ /* XXXRW: Audit argument. */
+ newcred = crget();
+ PROC_LOCK(td->td_proc);
+ oldcred = td->td_proc->p_ucred;
+ crcopy(newcred, oldcred);
#ifdef MAC
- error = mac_check_proc_setaudit(td->td_ucred, NULL);
+ error = mac_check_proc_setaudit(oldcred, NULL);
if (error)
- return (error);
+ goto fail;
#endif
- error = copyin(uap->auditinfo_addr, &aia, sizeof(aia));
+ error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
if (error)
- return (error);
- PROC_LOCK(td->td_proc);
- *td->td_proc->p_au = aia;
+ goto fail;
+ newcred->cr_audit = aia;
+ td->td_proc->p_ucred = newcred;
PROC_UNLOCK(td->td_proc);
+ crfree(oldcred);
+ return (0);
+fail:
+ crfree(newcred);
return (error);
}
OpenPOWER on IntegriCloud