#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/kmem.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <sys/user.h>
#include <sys/stropts.h>
#include <sys/systm.h>
#include <sys/pathname.h>
#include <sys/debug.h>
#include <sys/cred.h>
#include <sys/zone.h>
#include <c2/audit.h>
#include <c2/audit_kernel.h>
#include <c2/audit_kevents.h>
#include <c2/audit_record.h>
#include "audit_door_infc.h"
extern uint_t num_syscall;
extern kmutex_t pidlock;
int audit_load = 0;
kmutex_t module_lock;
void
audit_init_module()
{
token_t *rp = NULL;
label_t jb;
t_audit_data_t *tad = U2A(u);
mutex_enter(&module_lock);
if (audit_active != C2AUDIT_UNLOADED) {
mutex_exit(&module_lock);
return;
}
audit_active = C2AUDIT_LOADED;
mutex_exit(&module_lock);
au_mem_init();
if (setjmp(&jb)) {
audit_async_drop((caddr_t *)(&rp), 0);
return;
}
ASSERT(tad->tad_errjmp == NULL);
tad->tad_errjmp = (void *)&jb;
tad->tad_ctrl |= TAD_ERRJMP;
au_write((caddr_t *)&rp, au_to_text("booting kernel"));
audit_async_finish((caddr_t *)&rp, AUE_SYSTEMBOOT, 0,
&(p0.p_user.u_start));
}
#include <sys/syscall.h>
int
audit_start(
unsigned type,
unsigned scid,
uint32_t audit_state,
int error,
klwp_t *lwp)
{
struct t_audit_data *tad;
au_kcontext_t *kctx;
tad = U2A(u);
ASSERT(tad != NULL);
tad->tad_audit = audit_state;
if (error) {
tad->tad_ctrl = 0;
tad->tad_flag = 0;
return (0);
}
audit_update_context(curproc, NULL);
if (scid == 0) {
tad->tad_ctrl = 0;
tad->tad_flag = 0;
return (0);
}
if (scid >= num_syscall)
scid = 0;
(void) save_syscall_args();
tad->tad_ctrl = audit_s2e[scid].au_ctrl;
tad->tad_scid = scid;
tad->tad_event = audit_s2e[scid].au_event;
if (audit_s2e[scid].au_init != (au_event_t (*)(au_event_t))NULL) {
tad->tad_event = (*audit_s2e[scid].au_init)(tad->tad_event);
}
kctx = GET_KCTX_PZ;
if ((tad->tad_flag = auditme(kctx, tad,
kctx->auk_ets[tad->tad_event])) == 0) {
return (0);
}
if (audit_state & ~(AUC_AUDITING | AUC_INIT_AUDIT)) {
tad->tad_flag = 0;
return (0);
}
if (audit_state == AUC_NOSPACE) {
if ((kctx->auk_policy & AUDIT_CNT) ||
(kctx->auk_policy & AUDIT_SCNT)) {
tad->tad_flag = 0;
AS_INC(as_dropped, 1, kctx);
return (0);
}
}
tad->tad_evmod = 0;
if (audit_s2e[scid].au_start != NULL) {
(*audit_s2e[scid].au_start)(tad);
}
return (0);
}
void
audit_finish(
unsigned type,
unsigned scid,
int error,
rval_t *rval)
{
struct t_audit_data *tad;
int flag;
au_defer_info_t *attr;
au_kcontext_t *kctx = GET_KCTX_PZ;
tad = U2A(u);
attr = tad->tad_defer_head;
while (attr != NULL) {
au_defer_info_t *tmp_attr = attr;
au_close_time(kctx, (token_t *)attr->audi_ad, attr->audi_flag,
attr->audi_e_type, attr->audi_e_mod, &(attr->audi_atime));
attr = attr->audi_next;
kmem_free(tmp_attr, sizeof (au_defer_info_t));
}
tad->tad_defer_head = tad->tad_defer_tail = NULL;
if (tad->tad_flag == 0 && !(tad->tad_ctrl & TAD_SAVPATH)) {
tad->tad_scid = 0;
tad->tad_event = 0;
tad->tad_evmod = 0;
tad->tad_ctrl = 0;
tad->tad_audit = AUC_UNSET;
ASSERT(tad->tad_aupath == NULL);
return;
}
scid = tad->tad_scid;
if (audit_s2e[scid].au_finish != NULL) {
(*audit_s2e[scid].au_finish)(tad, error, rval);
}
if (tad->tad_flag) {
tad->tad_flag = 0;
if (flag = audit_success(kctx, tad, error, NULL)) {
unsigned int sy_flags;
cred_t *cr = CRED();
const auditinfo_addr_t *ainfo = crgetauinfo(cr);
ASSERT(ainfo != NULL);
AUDIT_SETSUBJ(&(u_ad), cr, ainfo, kctx);
if (tad->tad_evmod & PAD_SPRIVUSE) {
au_write(&(u_ad),
au_to_privset("", &tad->tad_sprivs,
AUT_UPRIV, 1));
}
if (tad->tad_evmod & PAD_FPRIVUSE) {
au_write(&(u_ad),
au_to_privset("", &tad->tad_fprivs,
AUT_UPRIV, 0));
}
#ifdef _SYSCALL32_IMPL
if (lwp_getdatamodel(ttolwp(curthread)) ==
DATAMODEL_NATIVE) {
sy_flags = sysent[scid].sy_flags & SE_RVAL_MASK;
} else {
sy_flags =
sysent32[scid].sy_flags & SE_RVAL_MASK;
}
#else
sy_flags = sysent[scid].sy_flags & SE_RVAL_MASK;
#endif
if (sy_flags == SE_32RVAL1) {
if (type == 0) {
au_write(&(u_ad),
au_to_return32(error, 0));
} else {
au_write(&(u_ad), au_to_return32(error,
rval->r_val1));
}
}
if (sy_flags == (SE_32RVAL2|SE_32RVAL1)) {
if (type == 0) {
au_write(&(u_ad),
au_to_return32(error, 0));
} else {
au_write(&(u_ad),
au_to_return32(error,
rval->r_val1));
#ifdef NOTYET
au_write(&(u_ad), au_to_return32(error,
rval->r_val2));
#endif
}
}
if (sy_flags == SE_64RVAL) {
if (type == 0) {
au_write(&(u_ad),
au_to_return64(error, 0));
} else {
au_write(&(u_ad), au_to_return64(error,
rval->r_vals));
}
}
AS_INC(as_generated, 1, kctx);
AS_INC(as_kernel, 1, kctx);
}
au_close(kctx, &(u_ad), flag, tad->tad_event, tad->tad_evmod,
NULL);
}
ASSERT(u_ad == NULL);
if (tad->tad_aupath != NULL) {
au_pathrele(tad->tad_aupath);
tad->tad_aupath = NULL;
}
if (tad->tad_atpath) {
au_pathrele(tad->tad_atpath);
tad->tad_atpath = NULL;
}
tad->tad_scid = 0;
tad->tad_event = 0;
tad->tad_evmod = 0;
tad->tad_ctrl = 0;
tad->tad_audit = AUC_UNSET;
}
int
audit_success(au_kcontext_t *kctx, struct t_audit_data *tad, int error,
cred_t *cr)
{
au_state_t ess;
au_state_t esf;
au_mask_t amask;
const auditinfo_addr_t *ainfo;
ess = esf = kctx->auk_ets[tad->tad_event];
if (error)
tad->tad_evmod |= PAD_FAILURE;
if (tad->tad_ctrl & TAD_NOAUDIT)
return (0);
if (cr == NULL)
cr = CRED();
ainfo = crgetauinfo(cr);
if (ainfo == NULL)
return (0);
amask = ainfo->ai_mask;
if (error == 0)
return ((ess & amask.as_success) ? AU_OK : 0);
else
return ((esf & amask.as_failure) ? AU_OK : 0);
}
int
auditme(au_kcontext_t *kctx, struct t_audit_data *tad, au_state_t estate)
{
int flag = 0;
au_mask_t amask;
const auditinfo_addr_t *ainfo;
ainfo = crgetauinfo(CRED());
if (ainfo == NULL)
return (0);
amask = ainfo->ai_mask;
if (amask.as_success & estate || amask.as_failure & estate) {
flag = 1;
} else if ((tad->tad_scid == SYS_putmsg) ||
(tad->tad_scid == SYS_getmsg)) {
estate = kctx->auk_ets[AUE_SOCKCONNECT] |
kctx->auk_ets[AUE_SOCKACCEPT] |
kctx->auk_ets[AUE_SOCKSEND] |
kctx->auk_ets[AUE_SOCKRECEIVE];
if (amask.as_success & estate || amask.as_failure & estate)
flag = 1;
} else if (tad->tad_scid == SYS_execve &&
getpflags(PRIV_PFEXEC, CRED()) != 0) {
estate = kctx->auk_ets[AUE_PFEXEC];
if (amask.as_success & estate || amask.as_failure & estate)
flag = 1;
}
return (flag);
}