#include <sys/systm.h>
#include <sys/types.h>
#include <sys/proc_internal.h>
#include <sys/vnode_internal.h>
#include <sys/fcntl.h>
#include <sys/filedesc.h>
#include <sys/sem.h>
#include <bsm/audit.h>
#include <bsm/audit_kernel.h>
#include <bsm/audit_kevents.h>
#include <bsm/audit_klib.h>
au_event_t sys_au_event[] = {
AUE_NULL,
AUE_EXIT,
AUE_FORK,
AUE_NULL,
AUE_NULL,
AUE_OPEN_RWTC,
AUE_CLOSE,
AUE_NULL,
AUE_O_CREAT,
AUE_LINK,
AUE_UNLINK,
AUE_NULL,
AUE_CHDIR,
AUE_FCHDIR,
AUE_MKNOD,
AUE_CHMOD,
AUE_CHOWN,
AUE_NULL,
#if COMPAT_GETFSSTAT
AUE_GETFSSTAT,
#else
AUE_NULL,
#endif
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_SETUID,
AUE_NULL,
AUE_NULL,
AUE_PTRACE,
AUE_RECVMSG,
AUE_SENDMSG,
AUE_RECVFROM,
AUE_ACCEPT,
AUE_NULL,
AUE_NULL,
AUE_ACCESS,
AUE_CHFLAGS,
AUE_FCHFLAGS,
AUE_NULL,
AUE_KILL,
AUE_O_STAT,
AUE_NULL,
AUE_O_LSTAT,
AUE_NULL,
AUE_PIPE,
AUE_NULL,
AUE_NULL,
AUE_KTRACE,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_SETLOGIN,
AUE_ACCT,
AUE_NULL,
AUE_NULL,
AUE_IOCTL,
AUE_REBOOT,
AUE_REVOKE,
AUE_SYMLINK,
AUE_READLINK,
AUE_EXECVE,
AUE_UMASK,
AUE_CHROOT,
AUE_O_FSTAT,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_VFORK,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_O_MMAP,
AUE_NULL,
AUE_MUNMAP,
AUE_MPROTECT,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_SETGROUPS,
AUE_NULL,
AUE_SETPGRP,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_O_SETHOSTNAME,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_FCNTL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_SETPRIORITY,
AUE_SOCKET,
AUE_CONNECT,
AUE_NULL,
AUE_NULL,
AUE_O_SEND,
AUE_O_RECV,
AUE_NULL,
AUE_BIND,
AUE_SETSOCKOPT,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_O_RECVMSG,
AUE_O_SENDMSG,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_SETTIMEOFDAY,
AUE_FCHOWN,
AUE_FCHMOD,
AUE_O_RECVFROM,
AUE_NULL,
AUE_NULL,
AUE_RENAME,
AUE_O_TRUNCATE,
AUE_O_FTRUNCATE,
AUE_FLOCK,
AUE_MKFIFO,
AUE_SENDTO,
AUE_SHUTDOWN,
AUE_SOCKETPAIR,
AUE_MKDIR,
AUE_RMDIR,
AUE_UTIMES,
AUE_FUTIMES,
AUE_ADJTIME,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_O_SETRLIMIT,
AUE_O_KILLPG,
AUE_SETSID,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_SETPRIVEXEC,
AUE_NULL,
AUE_NULL,
AUE_NFSSVC,
AUE_O_GETDIRENTRIES,
AUE_STATFS,
AUE_FSTATFS,
AUE_UNMOUNT,
AUE_NULL,
AUE_GETFH,
AUE_NULL,
AUE_O_SETDOMAINNAME,
AUE_NULL,
#if QUOTA
AUE_QUOTACTL,
#else
AUE_NULL,
#endif
AUE_NULL,
AUE_MOUNT,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_SETGID,
AUE_SETEGID,
AUE_SETEUID,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_STAT,
AUE_FSTAT,
AUE_LSTAT,
AUE_PATHCONF,
AUE_FPATHCONF,
#if COMPAT_GETFSSTAT
AUE_GETFSSTAT,
#else
AUE_NULL,
#endif
AUE_NULL,
AUE_SETRLIMIT,
AUE_GETDIRENTRIES,
AUE_MMAP,
AUE_NULL,
AUE_NULL,
AUE_TRUNCATE,
AUE_FTRUNCATE,
AUE_SYSCTL,
AUE_MLOCK,
AUE_MUNLOCK,
AUE_UNDELETE,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_GETATTRLIST,
AUE_SETATTRLIST,
AUE_GETDIRENTRIESATTR,
AUE_EXCHANGEDATA,
AUE_CHECKUSERACCESS,
AUE_SEARCHFS,
AUE_DELETE,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_MINHERIT,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_SEMCTL,
AUE_SEMGET,
AUE_SEMOP,
AUE_NULL,
AUE_MSGCTL,
AUE_MSGGET,
AUE_MSGSND,
AUE_MSGRCV,
AUE_SHMAT,
AUE_SHMCTL,
AUE_SHMDT,
AUE_SHMGET,
AUE_SHMOPEN,
AUE_SHMUNLINK,
AUE_SEMOPEN,
AUE_SEMCLOSE,
AUE_SEMUNLINK,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_LOADSHFILE,
AUE_RESETSHFILE,
AUE_NEWSYSTEMSHREG,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_AUDIT,
AUE_AUDITON,
AUE_NULL,
AUE_GETAUID,
AUE_SETAUID,
AUE_GETAUDIT,
AUE_SETAUDIT,
AUE_GETAUDIT_ADDR,
AUE_SETAUDIT_ADDR,
AUE_AUDITCTL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_LCHOWN,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL,
AUE_NULL
};
int nsys_au_event = sizeof(sys_au_event) / sizeof(sys_au_event[0]);
#define EVCLASSMAP_HASH_TABLE_SIZE 251
struct evclass_elem {
au_event_t event;
au_class_t class;
LIST_ENTRY(evclass_elem) entry;
};
struct evclass_list {
LIST_HEAD(, evclass_elem) head;
};
struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE];
au_class_t au_event_class(au_event_t event)
{
struct evclass_list *evcl;
struct evclass_elem *evc;
evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE];
LIST_FOREACH(evc, &evcl->head, entry) {
if (evc->event == event)
return (evc->class);
}
return (AU_NULL);
}
void au_evclassmap_insert(au_event_t event, au_class_t class)
{
struct evclass_list *evcl;
struct evclass_elem *evc;
evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE];
LIST_FOREACH(evc, &evcl->head, entry) {
if (evc->event == event) {
evc->class = class;
return;
}
}
kmem_alloc(kernel_map, (vm_offset_t *)&evc, sizeof(*evc));
if (evc == NULL) {
return;
}
evc->event = event;
evc->class = class;
LIST_INSERT_HEAD(&evcl->head, evc, entry);
}
void au_evclassmap_init()
{
int i;
for (i = 0; i < EVCLASSMAP_HASH_TABLE_SIZE; i++) {
LIST_INIT(&evclass_hash[i].head);
}
for (i = 0; i < nsys_au_event; i++) {
if (sys_au_event[i] != AUE_NULL) {
au_evclassmap_insert(sys_au_event[i], AU_NULL);
}
}
au_evclassmap_insert(AUE_TASKFORPID, AU_NULL);
au_evclassmap_insert(AUE_PIDFORTASK, AU_NULL);
au_evclassmap_insert(AUE_SWAPON, AU_NULL);
au_evclassmap_insert(AUE_SWAPOFF, AU_NULL);
au_evclassmap_insert(AUE_MAPFD, AU_NULL);
au_evclassmap_insert(AUE_INITPROCESS, AU_NULL);
au_evclassmap_insert(AUE_OPEN_R, AU_FREAD);
au_evclassmap_insert(AUE_OPEN_RC, AU_FREAD|AU_FCREATE);
au_evclassmap_insert(AUE_OPEN_RTC, AU_FREAD|AU_FCREATE|AU_FDELETE);
au_evclassmap_insert(AUE_OPEN_RT, AU_FREAD|AU_FDELETE);
au_evclassmap_insert(AUE_OPEN_RW, AU_FREAD|AU_FWRITE);
au_evclassmap_insert(AUE_OPEN_RWC, AU_FREAD|AU_FWRITE|AU_FCREATE);
au_evclassmap_insert(AUE_OPEN_RWTC, AU_FREAD|AU_FWRITE|AU_FCREATE|AU_FDELETE);
au_evclassmap_insert(AUE_OPEN_RWT, AU_FREAD|AU_FWRITE|AU_FDELETE);
au_evclassmap_insert(AUE_OPEN_W, AU_FWRITE);
au_evclassmap_insert(AUE_OPEN_WC, AU_FWRITE|AU_FCREATE);
au_evclassmap_insert(AUE_OPEN_WTC, AU_FWRITE|AU_FCREATE|AU_FDELETE);
au_evclassmap_insert(AUE_OPEN_WT, AU_FWRITE|AU_FDELETE);
}
int au_preselect(au_event_t event, au_mask_t *mask_p, int sorf)
{
au_class_t effmask = 0;
au_class_t ae_class;
if(mask_p == NULL)
return (-1);
ae_class = au_event_class(event);
if(sorf & AU_PRS_SUCCESS) {
effmask |= (mask_p->am_success & ae_class);
}
if(sorf & AU_PRS_FAILURE) {
effmask |= (mask_p->am_failure & ae_class);
}
if(effmask)
return (1);
else
return (0);
}
au_event_t ctlname_to_sysctlevent(int name[], uint64_t valid_arg) {
if ((valid_arg & (ARG_CTLNAME | ARG_LEN)) !=
(ARG_CTLNAME | ARG_LEN))
return AUE_SYSCTL;
switch (name[0]) {
case KERN_OSTYPE:
case KERN_OSRELEASE:
case KERN_OSREV:
case KERN_VERSION:
case KERN_ARGMAX:
case KERN_CLOCKRATE:
case KERN_BOOTTIME:
case KERN_POSIX1:
case KERN_NGROUPS:
case KERN_JOB_CONTROL:
case KERN_SAVED_IDS:
case KERN_NETBOOT:
case KERN_SYMFILE:
case KERN_SHREG_PRIVATIZABLE:
return AUE_SYSCTL_NONADMIN;
case KERN_MAXVNODES:
case KERN_MAXPROC:
case KERN_MAXFILES:
case KERN_MAXPROCPERUID:
case KERN_MAXFILESPERPROC:
case KERN_HOSTID:
case KERN_AIOMAX:
case KERN_AIOPROCMAX:
case KERN_AIOTHREADS:
case KERN_COREDUMP:
case KERN_SUGID_COREDUMP:
return (valid_arg & ARG_VALUE) ?
AUE_SYSCTL : AUE_SYSCTL_NONADMIN;
default:
return AUE_SYSCTL;
}
}
au_event_t flags_and_error_to_openevent(int oflags, int error) {
au_event_t aevent;
oflags = oflags & (O_RDONLY | O_CREAT | O_TRUNC | O_RDWR | O_WRONLY);
switch (oflags) {
case O_RDONLY:
aevent = AUE_OPEN_R;
break;
case (O_RDONLY | O_CREAT):
aevent = AUE_OPEN_RC;
break;
case (O_RDONLY | O_CREAT | O_TRUNC):
aevent = AUE_OPEN_RTC;
break;
case (O_RDONLY | O_TRUNC):
aevent = AUE_OPEN_RT;
break;
case O_RDWR:
aevent = AUE_OPEN_RW;
break;
case (O_RDWR | O_CREAT):
aevent = AUE_OPEN_RWC;
break;
case (O_RDWR | O_CREAT | O_TRUNC):
aevent = AUE_OPEN_RWTC;
break;
case (O_RDWR | O_TRUNC):
aevent = AUE_OPEN_RWT;
break;
case O_WRONLY:
aevent = AUE_OPEN_W;
break;
case (O_WRONLY | O_CREAT):
aevent = AUE_OPEN_WC;
break;
case (O_WRONLY | O_CREAT | O_TRUNC):
aevent = AUE_OPEN_WTC;
break;
case (O_WRONLY | O_TRUNC):
aevent = AUE_OPEN_WT;
break;
default:
aevent = AUE_OPEN;
break;
}
switch (aevent) {
case AUE_OPEN_R:
case AUE_OPEN_RT:
case AUE_OPEN_RW:
case AUE_OPEN_RWT:
case AUE_OPEN_W:
case AUE_OPEN_WT:
if (error == ENOENT)
aevent = AUE_OPEN;
}
return aevent;
}
au_event_t msgctl_to_event(int cmd)
{
switch (cmd) {
case IPC_RMID:
return AUE_MSGCTL_RMID;
case IPC_SET:
return AUE_MSGCTL_SET;
case IPC_STAT:
return AUE_MSGCTL_STAT;
default:
return AUE_MSGCTL;
}
}
au_event_t semctl_to_event(int cmd)
{
switch (cmd) {
case GETALL:
return AUE_SEMCTL_GETALL;
case GETNCNT:
return AUE_SEMCTL_GETNCNT;
case GETPID:
return AUE_SEMCTL_GETPID;
case GETVAL:
return AUE_SEMCTL_GETVAL;
case GETZCNT:
return AUE_SEMCTL_GETZCNT;
case IPC_RMID:
return AUE_SEMCTL_RMID;
case IPC_SET:
return AUE_SEMCTL_SET;
case SETALL:
return AUE_SEMCTL_SETALL;
case SETVAL:
return AUE_SEMCTL_SETVAL;
case IPC_STAT:
return AUE_SEMCTL_STAT;
default:
return AUE_SEMCTL;
}
}
int auditon_command_event(int cmd)
{
switch(cmd) {
case A_GETPOLICY:
return AUE_AUDITON_GPOLICY;
break;
case A_SETPOLICY:
return AUE_AUDITON_SPOLICY;
break;
case A_GETKMASK:
return AUE_AUDITON_GETKMASK;
break;
case A_SETKMASK:
return AUE_AUDITON_SETKMASK;
break;
case A_GETQCTRL:
return AUE_AUDITON_GQCTRL;
break;
case A_SETQCTRL:
return AUE_AUDITON_SQCTRL;
break;
case A_GETCWD:
return AUE_AUDITON_GETCWD;
break;
case A_GETCAR:
return AUE_AUDITON_GETCAR;
break;
case A_GETSTAT:
return AUE_AUDITON_GETSTAT;
break;
case A_SETSTAT:
return AUE_AUDITON_SETSTAT;
break;
case A_SETUMASK:
return AUE_AUDITON_SETUMASK;
break;
case A_SETSMASK:
return AUE_AUDITON_SETSMASK;
break;
case A_GETCOND:
return AUE_AUDITON_GETCOND;
break;
case A_SETCOND:
return AUE_AUDITON_SETCOND;
break;
case A_GETCLASS:
return AUE_AUDITON_GETCLASS;
break;
case A_SETCLASS:
return AUE_AUDITON_SETCLASS;
break;
case A_GETPINFO:
case A_SETPMASK:
case A_SETFSIZE:
case A_GETFSIZE:
case A_GETPINFO_ADDR:
case A_GETKAUDIT:
case A_SETKAUDIT:
default:
return AUE_AUDITON;
break;
}
}
int canon_path(struct proc *p, char *path, char *cpath)
{
char *bufp;
int len;
struct vnode *vnp;
struct filedesc *fdp;
int ret;
fdp = p->p_fd;
bufp = path;
if (*(path) == '/') {
while (*(bufp) == '/')
bufp++;
if ((fdp->fd_rdir == NULL) ||
(fdp->fd_rdir == rootvnode)) {
vnp = NULL;
bufp--;
} else {
vnp = fdp->fd_rdir;
}
} else {
vnp = fdp->fd_cdir;
bufp = path;
}
if (vnp != NULL) {
len = MAXPATHLEN;
ret = vn_getpath(vnp, cpath, &len);
if (ret != 0) {
cpath[0] = '\0';
return (ret);
}
if (len < MAXPATHLEN)
cpath[len-1] = '/';
strncpy(cpath + len, bufp, MAXPATHLEN - len);
} else {
strncpy(cpath, bufp, MAXPATHLEN);
}
return (0);
}