#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/kauth.h>
#include <sys/queue.h>
#include <sys/systm.h>
#include <bsm/audit.h>
#include <bsm/audit_internal.h>
#include <bsm/audit_kevents.h>
#include <security/audit/audit.h>
#include <security/audit/audit_private.h>
#include <mach/host_priv.h>
#include <mach/host_special_ports.h>
#include <mach/audit_triggers_server.h>
#include <kern/host.h>
#include <kern/kalloc.h>
#include <kern/zalloc.h>
#include <kern/sched_prim.h>
#if CONFIG_AUDIT
#if CONFIG_MACF
#include <bsm/audit_record.h>
#include <security/mac.h>
#include <security/mac_framework.h>
#include <security/mac_policy.h>
#define MAC_ARG_PREFIX "arg: "
#define MAC_ARG_PREFIX_LEN 5
zone_t audit_mac_label_zone;
extern zone_t mac_audit_data_zone;
void
audit_mac_init(void)
{
audit_mac_label_zone = zinit(MAC_AUDIT_LABEL_LEN,
AQ_HIWATER * 3 * MAC_AUDIT_LABEL_LEN, 8192, "audit_mac_label_zone");
}
int
audit_mac_new(proc_t p, struct kaudit_record *ar)
{
struct mac mac;
ar->k_ar.ar_cred_mac_labels = (char *)zalloc(audit_mac_label_zone);
if (ar->k_ar.ar_cred_mac_labels == NULL) {
return 1;
}
mac.m_buflen = MAC_AUDIT_LABEL_LEN;
mac.m_string = ar->k_ar.ar_cred_mac_labels;
mac_cred_label_externalize_audit(p, &mac);
ar->k_ar.ar_mac_records = (struct mac_audit_record_list_t *)
kalloc(sizeof(*ar->k_ar.ar_mac_records));
if (ar->k_ar.ar_mac_records == NULL) {
zfree(audit_mac_label_zone, ar->k_ar.ar_cred_mac_labels);
return 1;
}
LIST_INIT(ar->k_ar.ar_mac_records);
ar->k_ar.ar_forced_by_mac = 0;
return 0;
}
void
audit_mac_free(struct kaudit_record *ar)
{
struct mac_audit_record *head, *next;
if (ar->k_ar.ar_vnode1_mac_labels != NULL) {
zfree(audit_mac_label_zone, ar->k_ar.ar_vnode1_mac_labels);
}
if (ar->k_ar.ar_vnode2_mac_labels != NULL) {
zfree(audit_mac_label_zone, ar->k_ar.ar_vnode2_mac_labels);
}
if (ar->k_ar.ar_cred_mac_labels != NULL) {
zfree(audit_mac_label_zone, ar->k_ar.ar_cred_mac_labels);
}
if (ar->k_ar.ar_arg_mac_string != NULL) {
kfree(ar->k_ar.ar_arg_mac_string,
MAC_MAX_LABEL_BUF_LEN + MAC_ARG_PREFIX_LEN);
}
head = LIST_FIRST(ar->k_ar.ar_mac_records);
while (head != NULL) {
next = LIST_NEXT(head, records);
zfree(mac_audit_data_zone, head->data);
kfree(head, sizeof(*head));
head = next;
}
kfree(ar->k_ar.ar_mac_records, sizeof(*ar->k_ar.ar_mac_records));
}
int
audit_mac_syscall_enter(unsigned short code, proc_t p, struct uthread *uthread,
kauth_cred_t my_cred, au_event_t event)
{
int error;
error = mac_audit_check_preselect(my_cred, code,
(void *)uthread->uu_arg);
if (error == MAC_AUDIT_YES) {
uthread->uu_ar = audit_new(event, p, uthread);
uthread->uu_ar->k_ar.ar_forced_by_mac = 1;
au_to_text("Forced by a MAC policy");
return 1;
} else if (error == MAC_AUDIT_NO) {
return 0;
} else if (error == MAC_AUDIT_DEFAULT) {
return 1;
}
return 0;
}
int
audit_mac_syscall_exit(unsigned short code, struct uthread *uthread, int error,
int retval)
{
int mac_error;
if (uthread->uu_ar == NULL) {
return 1;
}
mac_error = mac_audit_check_postselect(kauth_cred_get(), code,
(void *) uthread->uu_arg, error, retval,
uthread->uu_ar->k_ar.ar_forced_by_mac);
if (mac_error == MAC_AUDIT_YES) {
uthread->uu_ar->k_ar_commit |= AR_COMMIT_KERNEL;
} else if (mac_error == MAC_AUDIT_NO) {
audit_free(uthread->uu_ar);
return 1;
}
return 0;
}
int
audit_mac_data(int type, int len, u_char *data)
{
struct kaudit_record *cur;
struct mac_audit_record *record;
if (audit_enabled == 0) {
kfree(data, len);
return ENOTSUP;
}
cur = currecord();
if (cur == NULL) {
kfree(data, len);
return ENOTSUP;
}
record = kalloc(sizeof(*record));
if (record == NULL) {
kfree(data, len);
return 0;
}
record->type = type;
record->length = len;
record->data = data;
LIST_INSERT_HEAD(cur->k_ar.ar_mac_records, record, records);
return 0;
}
void
audit_arg_mac_string(struct kaudit_record *ar, char *string)
{
if (ar->k_ar.ar_arg_mac_string == NULL) {
ar->k_ar.ar_arg_mac_string =
kalloc(MAC_MAX_LABEL_BUF_LEN + MAC_ARG_PREFIX_LEN);
}
if (ar->k_ar.ar_arg_mac_string == NULL) {
if (ar->k_ar.ar_arg_mac_string == NULL) {
return;
}
}
strncpy(ar->k_ar.ar_arg_mac_string, MAC_ARG_PREFIX,
MAC_ARG_PREFIX_LEN);
strncpy(ar->k_ar.ar_arg_mac_string + MAC_ARG_PREFIX_LEN, string,
MAC_MAX_LABEL_BUF_LEN);
ARG_SET_VALID(ar, ARG_MAC_STRING);
}
#endif
#endif