diff options
Diffstat (limited to 'sys/security/audit')
-rw-r--r-- | sys/security/audit/audit.c | 78 | ||||
-rw-r--r-- | sys/security/audit/audit.h | 10 | ||||
-rw-r--r-- | sys/security/audit/audit_arg.c | 6 | ||||
-rw-r--r-- | sys/security/audit/audit_syscalls.c | 201 |
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); } |