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
This commit is contained in:
parent
d3cdd95ce0
commit
faef53711b
@ -441,8 +441,7 @@ proc0_init(void *dummy __unused)
|
||||
p->p_ucred->cr_ruidinfo = uifind(0);
|
||||
p->p_ucred->cr_prison = NULL; /* Don't jail it. */
|
||||
#ifdef AUDIT
|
||||
audit_proc_alloc(p);
|
||||
audit_proc_kproc0(p);
|
||||
audit_cred_kproc0(p->p_ucred);
|
||||
#endif
|
||||
#ifdef MAC
|
||||
mac_create_proc0(p->p_ucred);
|
||||
@ -707,7 +706,7 @@ create_init(const void *udata __unused)
|
||||
mac_create_proc1(newcred);
|
||||
#endif
|
||||
#ifdef AUDIT
|
||||
audit_proc_init(initproc);
|
||||
audit_cred_proc1(newcred);
|
||||
#endif
|
||||
initproc->p_ucred = newcred;
|
||||
PROC_UNLOCK(initproc);
|
||||
|
@ -810,9 +810,6 @@ kern_wait(struct thread *td, pid_t pid, int *status, int options,
|
||||
vm_waitproc(p);
|
||||
#ifdef MAC
|
||||
mac_destroy_proc(p);
|
||||
#endif
|
||||
#ifdef AUDIT
|
||||
audit_proc_free(p);
|
||||
#endif
|
||||
KASSERT(FIRST_THREAD_IN_PROC(p),
|
||||
("kern_wait: no residual thread!"));
|
||||
|
@ -278,9 +278,6 @@ fork1(td, flags, pages, procp)
|
||||
newproc = uma_zalloc(proc_zone, M_WAITOK);
|
||||
#ifdef MAC
|
||||
mac_init_proc(newproc);
|
||||
#endif
|
||||
#ifdef AUDIT
|
||||
audit_proc_alloc(newproc);
|
||||
#endif
|
||||
knlist_init(&newproc->p_klist, &newproc->p_mtx, NULL, NULL, NULL);
|
||||
STAILQ_INIT(&newproc->p_ktr);
|
||||
@ -510,9 +507,6 @@ fork1(td, flags, pages, procp)
|
||||
p2->p_sflag = PS_INMEM;
|
||||
PROC_SUNLOCK(p2);
|
||||
td2->td_ucred = crhold(p2->p_ucred);
|
||||
#ifdef AUDIT
|
||||
audit_proc_fork(p1, p2);
|
||||
#endif
|
||||
pargs_hold(p2->p_args);
|
||||
|
||||
if (flags & RFSIGSHARE) {
|
||||
@ -752,9 +746,6 @@ fork1(td, flags, pages, procp)
|
||||
sx_xunlock(&allproc_lock);
|
||||
#ifdef MAC
|
||||
mac_destroy_proc(newproc);
|
||||
#endif
|
||||
#ifdef AUDIT
|
||||
audit_proc_free(newproc);
|
||||
#endif
|
||||
uma_zfree(proc_zone, newproc);
|
||||
if (p1->p_flag & P_HADTHREADS) {
|
||||
|
@ -1763,6 +1763,9 @@ crget(void)
|
||||
|
||||
MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO);
|
||||
refcount_init(&cr->cr_ref, 1);
|
||||
#ifdef AUDIT
|
||||
audit_cred_init(cr);
|
||||
#endif
|
||||
#ifdef MAC
|
||||
mac_init_cred(cr);
|
||||
#endif
|
||||
@ -1804,6 +1807,9 @@ crfree(struct ucred *cr)
|
||||
*/
|
||||
if (jailed(cr))
|
||||
prison_free(cr->cr_prison);
|
||||
#ifdef AUDIT
|
||||
audit_cred_destroy(cr);
|
||||
#endif
|
||||
#ifdef MAC
|
||||
mac_destroy_cred(cr);
|
||||
#endif
|
||||
@ -1836,6 +1842,9 @@ crcopy(struct ucred *dest, struct ucred *src)
|
||||
uihold(dest->cr_ruidinfo);
|
||||
if (jailed(dest))
|
||||
prison_hold(dest->cr_prison);
|
||||
#ifdef AUDIT
|
||||
audit_cred_copy(src, dest);
|
||||
#endif
|
||||
#ifdef MAC
|
||||
mac_copy_cred(src, dest);
|
||||
#endif
|
||||
|
@ -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,15 +531,50 @@ 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));
|
||||
}
|
||||
|
||||
/*
|
||||
* Free audit state from a credential when the credential is freed.
|
||||
*/
|
||||
void
|
||||
audit_cred_destroy(struct ucred *cred)
|
||||
{
|
||||
|
||||
bzero(&cred->cr_audit, sizeof(cred->cr_audit));
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate audit state for a new credential.
|
||||
*/
|
||||
void
|
||||
audit_cred_init(struct ucred *cred)
|
||||
{
|
||||
|
||||
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).
|
||||
*/
|
||||
void
|
||||
audit_cred_kproc0(struct ucred *cred)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
audit_cred_proc1(struct ucred *cred)
|
||||
{
|
||||
|
||||
cred->cr_audit.ai_auid = AU_DEFAUDITID;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -563,62 +596,3 @@ audit_thread_free(struct thread *td)
|
||||
|
||||
KASSERT(td->td_ar == NULL, ("audit_thread_free: td_ar != NULL"));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the audit info from the parent process to the child process when a
|
||||
* fork takes place.
|
||||
*/
|
||||
void
|
||||
audit_proc_fork(struct proc *parent, struct proc *child)
|
||||
{
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the auditing structure for the process.
|
||||
*/
|
||||
void
|
||||
audit_proc_free(struct proc *p)
|
||||
{
|
||||
|
||||
KASSERT(p->p_au != NULL, ("p->p_au == NULL (%d)", p->p_pid));
|
||||
|
||||
free(p->p_au, M_AUDITPROC);
|
||||
p->p_au = NULL;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -156,6 +156,7 @@ audit(struct thread *td, struct audit_args *uap)
|
||||
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)
|
||||
return (EINVAL);
|
||||
if (p_cansee(td, tp) != 0) {
|
||||
PROC_UNLOCK(tp);
|
||||
newcred = crget();
|
||||
if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) {
|
||||
crfree(newcred);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
tp->p_au->ai_mask.am_success =
|
||||
if (p_cansee(td, tp) != 0) {
|
||||
PROC_UNLOCK(tp);
|
||||
crfree(newcred);
|
||||
return (EINVAL);
|
||||
}
|
||||
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);
|
||||
|
||||
#ifdef MAC
|
||||
error = mac_check_proc_setauid(td->td_ucred, id);
|
||||
if (error)
|
||||
return (error);
|
||||
#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?
|
||||
*/
|
||||
newcred = crget();
|
||||
PROC_LOCK(td->td_proc);
|
||||
td->td_proc->p_au->ai_auid = id;
|
||||
oldcred = td->td_proc->p_ucred;
|
||||
crcopy(newcred, oldcred);
|
||||
#ifdef MAC
|
||||
error = mac_check_proc_setauid(oldcred, id);
|
||||
if (error)
|
||||
goto fail;
|
||||
#endif
|
||||
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);
|
||||
|
||||
#ifdef MAC
|
||||
error = mac_check_proc_setaudit(td->td_ucred, &ai);
|
||||
if (error)
|
||||
return (error);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXXRW: Test privilege while holding the proc lock?
|
||||
*/
|
||||
newcred = crget();
|
||||
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;
|
||||
oldcred = td->td_proc->p_ucred;
|
||||
crcopy(newcred, oldcred);
|
||||
#ifdef MAC
|
||||
error = mac_check_proc_setaudit(oldcred, &ai);
|
||||
if (error)
|
||||
goto fail;
|
||||
#endif
|
||||
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);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
#ifdef MAC
|
||||
error = mac_check_proc_setaudit(td->td_ucred, NULL);
|
||||
if (error)
|
||||
return (error);
|
||||
#endif
|
||||
error = copyin(uap->auditinfo_addr, &aia, sizeof(aia));
|
||||
if (error)
|
||||
return (error);
|
||||
PROC_LOCK(td->td_proc);
|
||||
*td->td_proc->p_au = aia;
|
||||
/* 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(oldcred, NULL);
|
||||
if (error)
|
||||
goto fail;
|
||||
#endif
|
||||
error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
|
||||
if (error)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,6 @@ struct pargs {
|
||||
* either lock is sufficient for read access, but both locks must be held
|
||||
* for write access.
|
||||
*/
|
||||
struct auditinfo;
|
||||
struct kaudit_record;
|
||||
struct td_sched;
|
||||
struct nlminfo;
|
||||
@ -580,7 +579,6 @@ struct proc {
|
||||
struct p_sched *p_sched; /* (*) Scheduler-specific data. */
|
||||
STAILQ_HEAD(, ktr_request) p_ktr; /* (o) KTR event queue. */
|
||||
LIST_HEAD(, mqueue_notifier) p_mqnotifier; /* (c) mqueue notifiers.*/
|
||||
struct auditinfo_addr *p_au; /* (c) Process audit properties. */
|
||||
};
|
||||
|
||||
#define p_session p_pgrp->pg_session
|
||||
|
@ -33,6 +33,8 @@
|
||||
#ifndef _SYS_UCRED_H_
|
||||
#define _SYS_UCRED_H_
|
||||
|
||||
#include <bsm/audit.h>
|
||||
|
||||
/*
|
||||
* Credentials.
|
||||
*
|
||||
@ -55,6 +57,7 @@ struct ucred {
|
||||
struct prison *cr_prison; /* jail(2) */
|
||||
#define cr_endcopy cr_label
|
||||
struct label *cr_label; /* MAC label */
|
||||
struct auditinfo_addr cr_audit; /* Audit properties. */
|
||||
};
|
||||
#define NOCRED ((struct ucred *)0) /* no credential available */
|
||||
#define FSCRED ((struct ucred *)-1) /* filesystem credential */
|
||||
|
Loading…
Reference in New Issue
Block a user