]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/security/audit/audit_bsm.c
xnu-4903.241.1.tar.gz
[apple/xnu.git] / bsd / security / audit / audit_bsm.c
index 6f665d890b12faf8b7a633502d43474e4a6e7848..876833e4b862fcd9843af3bb0a88782539a7cdd2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -57,8 +57,6 @@
 #include <netinet/in.h>
 #include <netinet/ip.h>
 
-#include <kern/lock.h>
-
 #if CONFIG_AUDIT
 MALLOC_DEFINE(M_AUDITBSM, "audit_bsm", "Audit BSM data");
 
@@ -229,6 +227,13 @@ kau_free(struct au_record *rec)
        }                                                               \
 } 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);                    \
@@ -265,6 +270,18 @@ kau_free(struct au_record *rec)
        }                                                               \
 } 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)) {                    \
@@ -985,6 +1002,12 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
                        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:
@@ -1022,6 +1045,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
        case AUE_FUTIMES:
        case AUE_GETDIRENTRIES:
        case AUE_GETDIRENTRIESATTR:
+       case AUE_GETATTRLISTBULK:
 #if 0  /* XXXss new */
        case AUE_POLL:
 #endif
@@ -1171,6 +1195,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
        case AUE_RENAME:
                UPATH1_VNODE1_TOKENS;
                UPATH2_TOKENS;
+               KPATH2_TOKENS;
                break;
 
        case AUE_MKDIR_EXTENDED:
@@ -1257,6 +1282,20 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
        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);
@@ -1282,22 +1321,47 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
                }
                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;
@@ -1317,23 +1381,6 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
                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:
@@ -1352,36 +1399,60 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
                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);
@@ -1389,6 +1460,36 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
                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);
@@ -1881,8 +1982,6 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
 
        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
@@ -1947,6 +2046,14 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
        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;
@@ -1954,25 +2061,47 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
 }
 
 /*
- * 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 */