/*
- * Copyright (c) 1999-2009 Apple Inc.
+ * Copyright (c) 1999-2016 Apple Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include <netinet/in.h>
#include <netinet/ip.h>
-#include <kern/lock.h>
-
#if CONFIG_AUDIT
MALLOC_DEFINE(M_AUDITBSM, "audit_bsm", "Audit BSM data");
} \
} while (0)
+#define KPATH2_TOKENS do { \
+ if (ARG_IS_VALID(kar, ARG_KPATH2)) { \
+ tok = au_to_path(ar->ar_arg_kpath2); \
+ kau_write(rec, tok); \
+ } \
+} while (0)
+
#define VNODE1_TOKENS do { \
if (ARG_IS_VALID(kar, ARG_KPATH1)) { \
tok = au_to_path(ar->ar_arg_kpath1); \
} \
} while (0)
+#define VNODE2_PATH_TOKENS do { \
+ if (ARG_IS_VALID(kar, ARG_KPATH2)) { \
+ tok = au_to_path(ar->ar_arg_kpath2); \
+ kau_write(rec, tok); \
+ } \
+ if (ARG_IS_VALID(kar, ARG_VNODE2)) { \
+ tok = au_to_attr32(&ar->ar_arg_vnode2); \
+ kau_write(rec, tok); \
+ MAC_VNODE2_LABEL_TOKEN; \
+ } \
+} while (0)
+
#define FD_VNODE1_TOKENS do { \
if (ARG_IS_VALID(kar, ARG_VNODE1)) { \
if (ARG_IS_VALID(kar, ARG_KPATH1)) { \
kau_write(rec, tok);
}
UPATH1_VNODE1_TOKENS;
+ VNODE2_PATH_TOKENS;
+ if (ARG_IS_VALID(kar, ARG_DATA)) {
+ tok = au_to_data(AUP_HEX, ar->ar_arg_data_type,
+ ar->ar_arg_data_count, ar->ar_arg_data);
+ kau_write(rec, tok);
+ }
break;
case AUE_FCHMOD_EXTENDED:
case AUE_FUTIMES:
case AUE_GETDIRENTRIES:
case AUE_GETDIRENTRIESATTR:
+ case AUE_GETATTRLISTBULK:
#if 0 /* XXXss new */
case AUE_POLL:
#endif
case AUE_RENAME:
UPATH1_VNODE1_TOKENS;
UPATH2_TOKENS;
+ KPATH2_TOKENS;
break;
case AUE_MKDIR_EXTENDED:
case AUE_UNMOUNT:
UPATH1_VNODE1_TOKENS;
break;
+ case AUE_FMOUNT:
+ if (ARG_IS_VALID(kar, ARG_FD)) {
+ tok = au_to_arg32(2, "dir fd", ar->ar_arg_fd);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
+ tok = au_to_arg32(3, "flags", ar->ar_arg_fflags);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_TEXT)) {
+ tok = au_to_text(ar->ar_arg_text);
+ kau_write(rec, tok);
+ }
+ break;
case AUE_MSGCTL:
ar->ar_event = audit_msgctl_to_event(ar->ar_arg_svipc_cmd);
}
break;
- case AUE_OPENAT_RC:
- case AUE_OPENAT_RTC:
- case AUE_OPENAT_RWC:
- case AUE_OPENAT_RWTC:
- case AUE_OPENAT_WC:
- case AUE_OPENAT_WTC:
+ case AUE_OPEN:
+ 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 (ARG_IS_VALID(kar, ARG_FFLAGS)) {
+ tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
+ kau_write(rec, tok);
+ }
+ UPATH1_VNODE1_TOKENS;
+ break;
+
+ case AUE_OPEN_RC:
+ case AUE_OPEN_RTC:
+ case AUE_OPEN_RWC:
+ case AUE_OPEN_RWTC:
+ case AUE_OPEN_WC:
+ case AUE_OPEN_WTC:
if (ARG_IS_VALID(kar, ARG_MODE)) {
tok = au_to_arg32(3, "mode", ar->ar_arg_mode);
kau_write(rec, tok);
}
if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
- tok = au_to_arg32(3, "flags", ar->ar_arg_fflags);
+ tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
kau_write(rec, tok);
}
- if (ARG_IS_VALID(kar, ARG_FD)) {
- tok = au_to_arg32(1, "dir fd", ar->ar_arg_fd);
+ UPATH1_VNODE1_TOKENS;
+ break;
+
+ case AUE_OPEN_EXTENDED:
+ case AUE_OPEN_EXTENDED_R:
+ case AUE_OPEN_EXTENDED_RT:
+ case AUE_OPEN_EXTENDED_RW:
+ case AUE_OPEN_EXTENDED_RWT:
+ case AUE_OPEN_EXTENDED_W:
+ case AUE_OPEN_EXTENDED_WT:
+ EXTENDED_TOKENS(3);
+ if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
+ tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
kau_write(rec, tok);
}
UPATH1_VNODE1_TOKENS;
UPATH1_VNODE1_TOKENS;
break;
- case AUE_OPEN_RC:
- case AUE_OPEN_RTC:
- case AUE_OPEN_RWC:
- case AUE_OPEN_RWTC:
- case AUE_OPEN_WC:
- case AUE_OPEN_WTC:
- if (ARG_IS_VALID(kar, ARG_MODE)) {
- tok = au_to_arg32(3, "mode", ar->ar_arg_mode);
- kau_write(rec, tok);
- }
- if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
- tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
- kau_write(rec, tok);
- }
- UPATH1_VNODE1_TOKENS;
- break;
-
case AUE_OPENAT:
case AUE_OPENAT_R:
case AUE_OPENAT_RT:
UPATH1_VNODE1_TOKENS;
break;
- case AUE_OPEN_EXTENDED:
- case AUE_OPEN_EXTENDED_R:
- case AUE_OPEN_EXTENDED_RT:
- case AUE_OPEN_EXTENDED_RW:
- case AUE_OPEN_EXTENDED_RWT:
- case AUE_OPEN_EXTENDED_W:
- case AUE_OPEN_EXTENDED_WT:
- EXTENDED_TOKENS(3);
+ case AUE_OPENAT_RC:
+ case AUE_OPENAT_RTC:
+ case AUE_OPENAT_RWC:
+ case AUE_OPENAT_RWTC:
+ case AUE_OPENAT_WC:
+ case AUE_OPENAT_WTC:
+ if (ARG_IS_VALID(kar, ARG_MODE)) {
+ tok = au_to_arg32(4, "mode", ar->ar_arg_mode);
+ kau_write(rec, tok);
+ }
if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
- tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
+ tok = au_to_arg32(3, "flags", ar->ar_arg_fflags);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_FD)) {
+ tok = au_to_arg32(1, "dir fd", ar->ar_arg_fd);
kau_write(rec, tok);
}
UPATH1_VNODE1_TOKENS;
break;
- case AUE_OPEN:
- case AUE_OPEN_R:
- case AUE_OPEN_RT:
- case AUE_OPEN_RW:
- case AUE_OPEN_RWT:
- case AUE_OPEN_W:
- case AUE_OPEN_WT:
+ case AUE_OPENBYID:
+ case AUE_OPENBYID_R:
+ case AUE_OPENBYID_RT:
+ case AUE_OPENBYID_RW:
+ case AUE_OPENBYID_RWT:
+ case AUE_OPENBYID_W:
+ case AUE_OPENBYID_WT:
if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
- tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
+ tok = au_to_arg32(3, "flags", ar->ar_arg_fflags);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_VALUE32)) {
+ tok = au_to_arg32(1, "volfsid", ar->ar_arg_value32);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_VALUE64)) {
+ tok = au_to_arg64(2, "objid", ar->ar_arg_value64);
kau_write(rec, tok);
}
- UPATH1_VNODE1_TOKENS;
break;
+ case AUE_RENAMEAT:
+ case AUE_FACCESSAT:
+ case AUE_FCHMODAT:
+ case AUE_FCHOWNAT:
+ case AUE_FSTATAT:
+ case AUE_LINKAT:
case AUE_UNLINKAT:
+ case AUE_READLINKAT:
+ case AUE_SYMLINKAT:
+ case AUE_MKDIRAT:
+ case AUE_GETATTRLISTAT:
+ case AUE_SETATTRLISTAT:
if (ARG_IS_VALID(kar, ARG_FD)) {
tok = au_to_arg32(1, "dir fd", ar->ar_arg_fd);
kau_write(rec, tok);
UPATH1_VNODE1_TOKENS;
break;
+ case AUE_CLONEFILEAT:
+ if (ARG_IS_VALID(kar, ARG_FD)) {
+ tok = au_to_arg32(1, "src dir fd", ar->ar_arg_fd);
+ kau_write(rec, tok);
+ }
+ UPATH1_VNODE1_TOKENS;
+ if (ARG_IS_VALID(kar, ARG_FD2)) {
+ tok = au_to_arg32(1, "dst dir fd", ar->ar_arg_fd2);
+ kau_write(rec, tok);
+ }
+ UPATH2_TOKENS;
+ if (ARG_IS_VALID(kar, ARG_VALUE32)) {
+ tok = au_to_arg32(1, "flags", ar->ar_arg_value32);
+ kau_write(rec, tok);
+ }
+ break;
+
+ case AUE_FCLONEFILEAT:
+ FD_VNODE1_TOKENS;
+ if (ARG_IS_VALID(kar, ARG_FD2)) {
+ tok = au_to_arg32(1, "dst dir fd", ar->ar_arg_fd2);
+ kau_write(rec, tok);
+ }
+ UPATH2_TOKENS;
+ if (ARG_IS_VALID(kar, ARG_VALUE32)) {
+ tok = au_to_arg32(1, "flags", ar->ar_arg_value32);
+ kau_write(rec, tok);
+ }
+ break;
+
case AUE_PTRACE:
if (ARG_IS_VALID(kar, ARG_CMD)) {
tok = au_to_arg32(1, "request", ar->ar_arg_cmd);
case AUE_MAC_GET_PROC:
case AUE_MAC_SET_PROC:
- case AUE_MAC_GET_LCTX:
- case AUE_MAC_SET_LCTX:
PROCESS_MAC_TOKENS;
break;
#endif
tok = au_to_return32(au_errno_to_bsm(ar->ar_errno), ar->ar_retval);
kau_write(rec, tok); /* Every record gets a return token */
+ if (ARG_IS_VALID(kar, ARG_IDENTITY)) {
+ struct au_identity_info *id = &ar->ar_arg_identity;
+ tok = au_to_identity(id->signer_type, id->signing_id,
+ id->signing_id_trunc, id->team_id, id->team_id_trunc,
+ id->cdhash, id->cdhash_len);
+ kau_write(rec, tok);
+ }
+
kau_close(rec, &ar->ar_endtime, ar->ar_event);
*pau = rec;
}
/*
- * Verify that a record is a valid BSM record. This verification is simple
- * now, but may be expanded on sometime in the future. Return 1 if the
+ * Verify that a record is a valid BSM record. Return 1 if the
* record is good, 0 otherwise.
*/
int
-bsm_rec_verify(void *rec)
+bsm_rec_verify(void *rec, int length)
{
- char c = *(char *)rec;
+ /* Used to partially deserialize the buffer */
+ struct hdr_tok_partial *hdr;
+ struct trl_tok_partial *trl;
- /*
- * Check the token ID of the first token; it has to be a header
- * token.
- *
- * XXXAUDIT There needs to be a token structure to map a token.
- * XXXAUDIT 'Shouldn't be simply looking at the first char.
- */
- if ((c != AUT_HEADER32) && (c != AUT_HEADER32_EX) &&
- (c != AUT_HEADER64) && (c != AUT_HEADER64_EX))
+ /* A record requires a complete header and trailer token */
+ if (length < (AUDIT_HEADER_SIZE + AUDIT_TRAILER_SIZE)) {
return (0);
+ }
+
+ hdr = (struct hdr_tok_partial*)rec;
+
+ /* Ensure the provided length matches what the record shows */
+ if ((uint32_t)length != ntohl(hdr->len)) {
+ return (0);
+ }
+
+ trl = (struct trl_tok_partial*)(rec + (length - AUDIT_TRAILER_SIZE));
+
+ /* Ensure the buffer contains what look like header and trailer tokens */
+ if (((hdr->type != AUT_HEADER32) && (hdr->type != AUT_HEADER32_EX) &&
+ (hdr->type != AUT_HEADER64) && (hdr->type != AUT_HEADER64_EX)) ||
+ (trl->type != AUT_TRAILER)) {
+ return (0);
+ }
+
+ /* Ensure the header and trailer agree on the length */
+ if (hdr->len != trl->len) {
+ return (0);
+ }
+
+ /* Ensure the trailer token has a proper magic value */
+ if (ntohs(trl->magic) != AUT_TRAILER_MAGIC) {
+ return (0);
+ }
+
return (1);
}
#endif /* CONFIG_AUDIT */