| 1 | /*- | 
| 2 |  * Copyright (c) 1999-2016 Apple Inc. | 
| 3 |  * All rights reserved. | 
| 4 |  * | 
| 5 |  * Redistribution and use in source and binary forms, with or without | 
| 6 |  * modification, are permitted provided that the following conditions | 
| 7 |  * are met: | 
| 8 |  * 1.  Redistributions of source code must retain the above copyright | 
| 9 |  *     notice, this list of conditions and the following disclaimer. | 
| 10 |  * 2.  Redistributions in binary form must reproduce the above copyright | 
| 11 |  *     notice, this list of conditions and the following disclaimer in the | 
| 12 |  *     documentation and/or other materials provided with the distribution. | 
| 13 |  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of | 
| 14 |  *     its contributors may be used to endorse or promote products derived | 
| 15 |  *     from this software without specific prior written permission. | 
| 16 |  * | 
| 17 |  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND | 
| 18 |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
| 19 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
| 20 |  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR | 
| 21 |  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
| 22 |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
| 23 |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
| 24 |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 
| 25 |  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | 
| 26 |  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 
| 27 |  * POSSIBILITY OF SUCH DAMAGE. | 
| 28 |  * | 
| 29 |  */ | 
| 30 | /* | 
| 31 |  * NOTICE: This file was modified by McAfee Research in 2004 to introduce | 
| 32 |  * support for mandatory and extensible security protections.  This notice | 
| 33 |  * is included in support of clause 2.2 (b) of the Apple Public License, | 
| 34 |  * Version 2.0. | 
| 35 |  */ | 
| 36 |  | 
| 37 | #include <sys/param.h> | 
| 38 | #include <sys/fcntl.h> | 
| 39 | #include <sys/kernel.h> | 
| 40 | #include <sys/lock.h> | 
| 41 | #include <sys/namei.h> | 
| 42 | #include <sys/proc_internal.h> | 
| 43 | #include <sys/kauth.h> | 
| 44 | #include <sys/queue.h> | 
| 45 | #include <sys/systm.h> | 
| 46 | #include <sys/time.h> | 
| 47 | #include <sys/ucred.h> | 
| 48 | #include <sys/uio.h> | 
| 49 | #include <sys/unistd.h> | 
| 50 | #include <sys/file_internal.h> | 
| 51 | #include <sys/vnode_internal.h> | 
| 52 | #include <sys/user.h> | 
| 53 | #include <sys/syscall.h> | 
| 54 | #include <sys/malloc.h> | 
| 55 | #include <sys/un.h> | 
| 56 | #include <sys/sysent.h> | 
| 57 | #include <sys/sysproto.h> | 
| 58 | #include <sys/vfs_context.h> | 
| 59 | #include <sys/domain.h> | 
| 60 | #include <sys/protosw.h> | 
| 61 | #include <sys/socketvar.h> | 
| 62 | #include <sys/codesign.h> | 
| 63 | #include <sys/ubc.h> | 
| 64 |  | 
| 65 | #include <bsm/audit.h> | 
| 66 | #include <bsm/audit_internal.h> | 
| 67 | #include <bsm/audit_kevents.h> | 
| 68 |  | 
| 69 | #include <security/audit/audit.h> | 
| 70 | #include <security/audit/audit_bsd.h> | 
| 71 | #include <security/audit/audit_private.h> | 
| 72 |  | 
| 73 | #include <mach/host_priv.h> | 
| 74 | #include <mach/host_special_ports.h> | 
| 75 | #include <mach/audit_triggers_server.h> | 
| 76 |  | 
| 77 | #include <kern/host.h> | 
| 78 | #include <kern/kalloc.h> | 
| 79 | #include <kern/zalloc.h> | 
| 80 | #include <kern/sched_prim.h> | 
| 81 |  | 
| 82 | #if CONFIG_MACF | 
| 83 | #include <bsm/audit_record.h> | 
| 84 | #include <security/mac.h> | 
| 85 | #include <security/mac_framework.h> | 
| 86 | #include <security/mac_policy.h> | 
| 87 | extern zone_t audit_mac_label_zone; | 
| 88 | #endif | 
| 89 |  | 
| 90 | #include <net/route.h> | 
| 91 |  | 
| 92 | #include <netinet/in.h> | 
| 93 | #include <netinet/in_pcb.h> | 
| 94 |  | 
| 95 | #if CONFIG_AUDIT | 
| 96 | /* | 
| 97 |  * Calls to manipulate elements of the audit record structure from system | 
| 98 |  * call code.  Macro wrappers will prevent this functions from being entered | 
| 99 |  * if auditing is disabled, avoiding the function call cost.  We check the | 
| 100 |  * thread audit record pointer anyway, as the audit condition could change, | 
| 101 |  * and pre-selection may not have allocated an audit record for this event. | 
| 102 |  * | 
| 103 |  * XXXAUDIT: Should we assert, in each case, that this field of the record | 
| 104 |  * hasn't already been filled in? | 
| 105 |  */ | 
| 106 | void | 
| 107 | audit_arg_addr(struct kaudit_record *ar, user_addr_t addr) | 
| 108 | { | 
| 109 | 	struct proc *p = current_proc(); | 
| 110 |  | 
| 111 | 	ar->k_ar.ar_arg_addr = addr; | 
| 112 |  | 
| 113 | 	/* | 
| 114 | 	 * If the process is 64-bit then flag the address as such. | 
| 115 | 	 */ | 
| 116 | 	if (proc_is64bit(p)) | 
| 117 | 		ARG_SET_VALID(ar, ARG_ADDR64); | 
| 118 | 	else | 
| 119 | 		ARG_SET_VALID(ar, ARG_ADDR32); | 
| 120 | } | 
| 121 |  | 
| 122 | void | 
| 123 | audit_arg_exit(struct kaudit_record *ar, int status, int retval) | 
| 124 | { | 
| 125 |  | 
| 126 | 	ar->k_ar.ar_arg_exitstatus = status; | 
| 127 | 	ar->k_ar.ar_arg_exitretval = retval; | 
| 128 | 	ARG_SET_VALID(ar, ARG_EXIT); | 
| 129 | } | 
| 130 |  | 
| 131 | void | 
| 132 | audit_arg_len(struct kaudit_record *ar, user_size_t len) | 
| 133 | { | 
| 134 |  | 
| 135 | 	ar->k_ar.ar_arg_len = len; | 
| 136 | 	ARG_SET_VALID(ar, ARG_LEN); | 
| 137 | } | 
| 138 |  | 
| 139 | void | 
| 140 | audit_arg_fd2(struct kaudit_record *ar, int fd) | 
| 141 | { | 
| 142 |  | 
| 143 | 	ar->k_ar.ar_arg_fd2 = fd; | 
| 144 | 	ARG_SET_VALID(ar, ARG_FD2); | 
| 145 | } | 
| 146 |  | 
| 147 | void | 
| 148 | audit_arg_fd(struct kaudit_record *ar, int fd) | 
| 149 | { | 
| 150 |  | 
| 151 | 	ar->k_ar.ar_arg_fd = fd; | 
| 152 | 	ARG_SET_VALID(ar, ARG_FD); | 
| 153 | } | 
| 154 |  | 
| 155 | void | 
| 156 | audit_arg_fflags(struct kaudit_record *ar, int fflags) | 
| 157 | { | 
| 158 |  | 
| 159 | 	ar->k_ar.ar_arg_fflags = fflags; | 
| 160 | 	ARG_SET_VALID(ar, ARG_FFLAGS); | 
| 161 | } | 
| 162 |  | 
| 163 | void | 
| 164 | audit_arg_gid(struct kaudit_record *ar, gid_t gid) | 
| 165 | { | 
| 166 |  | 
| 167 | 	ar->k_ar.ar_arg_gid = gid; | 
| 168 | 	ARG_SET_VALID(ar, ARG_GID); | 
| 169 | } | 
| 170 |  | 
| 171 | void | 
| 172 | audit_arg_uid(struct kaudit_record *ar, uid_t uid) | 
| 173 | { | 
| 174 |  | 
| 175 | 	ar->k_ar.ar_arg_uid = uid; | 
| 176 | 	ARG_SET_VALID(ar, ARG_UID); | 
| 177 | } | 
| 178 |  | 
| 179 | void | 
| 180 | audit_arg_egid(struct kaudit_record *ar, gid_t egid) | 
| 181 | { | 
| 182 |  | 
| 183 | 	ar->k_ar.ar_arg_egid = egid; | 
| 184 | 	ARG_SET_VALID(ar, ARG_EGID); | 
| 185 | } | 
| 186 |  | 
| 187 | void | 
| 188 | audit_arg_euid(struct kaudit_record *ar, uid_t euid) | 
| 189 | { | 
| 190 |  | 
| 191 | 	ar->k_ar.ar_arg_euid = euid; | 
| 192 | 	ARG_SET_VALID(ar, ARG_EUID); | 
| 193 | } | 
| 194 |  | 
| 195 | void | 
| 196 | audit_arg_rgid(struct kaudit_record *ar, gid_t rgid) | 
| 197 | { | 
| 198 |  | 
| 199 | 	ar->k_ar.ar_arg_rgid = rgid; | 
| 200 | 	ARG_SET_VALID(ar, ARG_RGID); | 
| 201 | } | 
| 202 |  | 
| 203 | void | 
| 204 | audit_arg_ruid(struct kaudit_record *ar, uid_t ruid) | 
| 205 | { | 
| 206 |  | 
| 207 | 	ar->k_ar.ar_arg_ruid = ruid; | 
| 208 | 	ARG_SET_VALID(ar, ARG_RUID); | 
| 209 | } | 
| 210 |  | 
| 211 | void | 
| 212 | audit_arg_sgid(struct kaudit_record *ar, gid_t sgid) | 
| 213 | { | 
| 214 |  | 
| 215 | 	ar->k_ar.ar_arg_sgid = sgid; | 
| 216 | 	ARG_SET_VALID(ar, ARG_SGID); | 
| 217 | } | 
| 218 |  | 
| 219 | void | 
| 220 | audit_arg_suid(struct kaudit_record *ar, uid_t suid) | 
| 221 | { | 
| 222 |  | 
| 223 | 	ar->k_ar.ar_arg_suid = suid; | 
| 224 | 	ARG_SET_VALID(ar, ARG_SUID); | 
| 225 | } | 
| 226 |  | 
| 227 | void | 
| 228 | audit_arg_groupset(struct kaudit_record *ar, gid_t *gidset, u_int gidset_size) | 
| 229 | { | 
| 230 | 	u_int i; | 
| 231 |  | 
| 232 | 	for (i = 0; i < gidset_size; i++) | 
| 233 | 		ar->k_ar.ar_arg_groups.gidset[i] = gidset[i]; | 
| 234 | 	ar->k_ar.ar_arg_groups.gidset_size = gidset_size; | 
| 235 | 	ARG_SET_VALID(ar, ARG_GROUPSET); | 
| 236 | } | 
| 237 |  | 
| 238 | void | 
| 239 | audit_arg_login(struct kaudit_record *ar, char *login) | 
| 240 | { | 
| 241 |  | 
| 242 | 	strlcpy(ar->k_ar.ar_arg_login, login, MAXLOGNAME); | 
| 243 | 	ARG_SET_VALID(ar, ARG_LOGIN); | 
| 244 | } | 
| 245 |  | 
| 246 | void | 
| 247 | audit_arg_ctlname(struct kaudit_record *ar, int *name, int namelen) | 
| 248 | { | 
| 249 |  | 
| 250 | 	bcopy(name, &ar->k_ar.ar_arg_ctlname, namelen * sizeof(int)); | 
| 251 | 	ar->k_ar.ar_arg_len = namelen; | 
| 252 | 	ARG_SET_VALID(ar, ARG_CTLNAME | ARG_LEN); | 
| 253 | } | 
| 254 |  | 
| 255 | void | 
| 256 | audit_arg_mask(struct kaudit_record *ar, int mask) | 
| 257 | { | 
| 258 |  | 
| 259 | 	ar->k_ar.ar_arg_mask = mask; | 
| 260 | 	ARG_SET_VALID(ar, ARG_MASK); | 
| 261 | } | 
| 262 |  | 
| 263 | void | 
| 264 | audit_arg_mode(struct kaudit_record *ar, mode_t mode) | 
| 265 | { | 
| 266 |  | 
| 267 | 	ar->k_ar.ar_arg_mode = mode; | 
| 268 | 	ARG_SET_VALID(ar, ARG_MODE); | 
| 269 | } | 
| 270 |  | 
| 271 | void | 
| 272 | audit_arg_value32(struct kaudit_record *ar, uint32_t value32) | 
| 273 | { | 
| 274 |  | 
| 275 | 	ar->k_ar.ar_arg_value32 = value32; | 
| 276 | 	ARG_SET_VALID(ar, ARG_VALUE32); | 
| 277 | } | 
| 278 |  | 
| 279 | void | 
| 280 | audit_arg_value64(struct kaudit_record *ar, uint64_t value64) | 
| 281 | { | 
| 282 |  | 
| 283 | 	ar->k_ar.ar_arg_value64 = value64; | 
| 284 | 	ARG_SET_VALID(ar, ARG_VALUE64); | 
| 285 | } | 
| 286 |  | 
| 287 | void | 
| 288 | audit_arg_owner(struct kaudit_record *ar, uid_t uid, gid_t gid) | 
| 289 | { | 
| 290 |  | 
| 291 | 	ar->k_ar.ar_arg_uid = uid; | 
| 292 | 	ar->k_ar.ar_arg_gid = gid; | 
| 293 | 	ARG_SET_VALID(ar, ARG_UID | ARG_GID); | 
| 294 | } | 
| 295 |  | 
| 296 | void | 
| 297 | audit_arg_pid(struct kaudit_record *ar, pid_t pid) | 
| 298 | { | 
| 299 |  | 
| 300 | 	ar->k_ar.ar_arg_pid = pid; | 
| 301 | 	ARG_SET_VALID(ar, ARG_PID); | 
| 302 | } | 
| 303 |  | 
| 304 | void | 
| 305 | audit_arg_process(struct kaudit_record *ar, proc_t p) | 
| 306 | { | 
| 307 | 	kauth_cred_t my_cred; | 
| 308 |  | 
| 309 | 	KASSERT(p != NULL, ("audit_arg_process: p == NULL" )); | 
| 310 |  | 
| 311 | 	if ( p == NULL) | 
| 312 | 		return; | 
| 313 |  | 
| 314 | 	my_cred = kauth_cred_proc_ref(p); | 
| 315 | 	ar->k_ar.ar_arg_auid = my_cred->cr_audit.as_aia_p->ai_auid; | 
| 316 | 	ar->k_ar.ar_arg_asid = my_cred->cr_audit.as_aia_p->ai_asid; | 
| 317 | 	bcopy(&my_cred->cr_audit.as_aia_p->ai_termid, | 
| 318 | 	    &ar->k_ar.ar_arg_termid_addr, sizeof(au_tid_addr_t)); | 
| 319 | 	ar->k_ar.ar_arg_euid = kauth_cred_getuid(my_cred); | 
| 320 | 	ar->k_ar.ar_arg_egid = kauth_cred_getgid(my_cred); | 
| 321 | 	ar->k_ar.ar_arg_ruid = kauth_cred_getruid(my_cred); | 
| 322 | 	ar->k_ar.ar_arg_rgid = kauth_cred_getrgid(my_cred); | 
| 323 | 	kauth_cred_unref(&my_cred); | 
| 324 | 	ar->k_ar.ar_arg_pid = p->p_pid; | 
| 325 | 	ARG_SET_VALID(ar, ARG_AUID | ARG_EUID | ARG_EGID | ARG_RUID | | 
| 326 | 	    ARG_RGID | ARG_ASID | ARG_TERMID_ADDR | ARG_PID | ARG_PROCESS); | 
| 327 | } | 
| 328 |  | 
| 329 | void | 
| 330 | audit_arg_signum(struct kaudit_record *ar, u_int signum) | 
| 331 | { | 
| 332 |  | 
| 333 | 	ar->k_ar.ar_arg_signum = signum; | 
| 334 | 	ARG_SET_VALID(ar, ARG_SIGNUM); | 
| 335 | } | 
| 336 |  | 
| 337 | void | 
| 338 | audit_arg_socket(struct kaudit_record *ar, int sodomain, int sotype, | 
| 339 |     int soprotocol) | 
| 340 | { | 
| 341 |  | 
| 342 | 	ar->k_ar.ar_arg_sockinfo.sai_domain = sodomain; | 
| 343 | 	ar->k_ar.ar_arg_sockinfo.sai_type = sotype; | 
| 344 | 	ar->k_ar.ar_arg_sockinfo.sai_protocol = soprotocol; | 
| 345 | 	ARG_SET_VALID(ar, ARG_SOCKINFO); | 
| 346 | } | 
| 347 |  | 
| 348 | /* | 
| 349 |  * Note that the current working directory vp must be supplied at the audit | 
| 350 |  * call site to permit per thread current working directories, and that it | 
| 351 |  * must take a upath starting with '/' into account for chroot if the path | 
| 352 |  * is absolute.  This results in the real (non-chroot) path being recorded | 
| 353 |  * in the audit record. | 
| 354 |  */ | 
| 355 | void | 
| 356 | audit_arg_sockaddr(struct kaudit_record *ar, struct vnode *cwd_vp, | 
| 357 |     struct sockaddr *sa) | 
| 358 | { | 
| 359 | 	char path[SOCK_MAXADDRLEN - offsetof(struct sockaddr_un, sun_path) + 1] = "" ; | 
| 360 | 	struct sockaddr_un *sun; | 
| 361 | 	ssize_t namelen; | 
| 362 |  | 
| 363 | 	KASSERT(sa != NULL, ("audit_arg_sockaddr: sa == NULL" )); | 
| 364 |  | 
| 365 | 	if (cwd_vp == NULL || sa == NULL) | 
| 366 | 		return; | 
| 367 |  | 
| 368 | 	if (sa->sa_len > sizeof(ar->k_ar.ar_arg_sockaddr)) | 
| 369 | 		bcopy(sa, &ar->k_ar.ar_arg_sockaddr, sizeof(ar->k_ar.ar_arg_sockaddr)); | 
| 370 | 	else | 
| 371 | 		bcopy(sa, &ar->k_ar.ar_arg_sockaddr, sa->sa_len); | 
| 372 |  | 
| 373 | 	switch (sa->sa_family) { | 
| 374 | 	case AF_INET: | 
| 375 | 		ARG_SET_VALID(ar, ARG_SADDRINET); | 
| 376 | 		break; | 
| 377 |  | 
| 378 | 	case AF_INET6: | 
| 379 | 		ARG_SET_VALID(ar, ARG_SADDRINET6); | 
| 380 | 		break; | 
| 381 |  | 
| 382 | 	case AF_UNIX: | 
| 383 | 		sun = (struct sockaddr_un *)sa; | 
| 384 | 		namelen = sun->sun_len - offsetof(struct sockaddr_un, sun_path); | 
| 385 | 		if (namelen > 0 && (size_t)namelen < sizeof(path)) { | 
| 386 | 			/* | 
| 387 | 			 * Make sure the path is NUL-terminated | 
| 388 | 			 */ | 
| 389 | 			bcopy(sun->sun_path, path, namelen); | 
| 390 | 			path[namelen] = 0; | 
| 391 | 			audit_arg_upath(ar, cwd_vp, path, ARG_UPATH1); | 
| 392 | 		} | 
| 393 | 		ARG_SET_VALID(ar, ARG_SADDRUNIX); | 
| 394 | 		break; | 
| 395 | 	/* XXXAUDIT: default:? */ | 
| 396 | 	} | 
| 397 | } | 
| 398 |  | 
| 399 | void | 
| 400 | audit_arg_auid(struct kaudit_record *ar, uid_t auid) | 
| 401 | { | 
| 402 |  | 
| 403 | 	ar->k_ar.ar_arg_auid = auid; | 
| 404 | 	ARG_SET_VALID(ar, ARG_AUID); | 
| 405 | } | 
| 406 |  | 
| 407 | void | 
| 408 | audit_arg_auditinfo(struct kaudit_record *ar, struct auditinfo *au_info) | 
| 409 | { | 
| 410 |  | 
| 411 | 	ar->k_ar.ar_arg_auid = au_info->ai_auid; | 
| 412 | 	ar->k_ar.ar_arg_asid = au_info->ai_asid; | 
| 413 | 	ar->k_ar.ar_arg_amask.am_success = au_info->ai_mask.am_success; | 
| 414 | 	ar->k_ar.ar_arg_amask.am_failure = au_info->ai_mask.am_failure; | 
| 415 | 	ar->k_ar.ar_arg_termid.port = au_info->ai_termid.port; | 
| 416 | 	ar->k_ar.ar_arg_termid.machine = au_info->ai_termid.machine; | 
| 417 | 	ARG_SET_VALID(ar, ARG_AUID | ARG_ASID | ARG_AMASK | ARG_TERMID); | 
| 418 | } | 
| 419 |  | 
| 420 | void | 
| 421 | audit_arg_auditinfo_addr(struct kaudit_record *ar, | 
| 422 |     struct auditinfo_addr *au_info) | 
| 423 | { | 
| 424 |  | 
| 425 | 	ar->k_ar.ar_arg_auid = au_info->ai_auid; | 
| 426 | 	ar->k_ar.ar_arg_asid = au_info->ai_asid; | 
| 427 | 	ar->k_ar.ar_arg_amask.am_success = au_info->ai_mask.am_success; | 
| 428 | 	ar->k_ar.ar_arg_amask.am_failure = au_info->ai_mask.am_failure; | 
| 429 | 	ar->k_ar.ar_arg_termid_addr.at_type = au_info->ai_termid.at_type; | 
| 430 | 	ar->k_ar.ar_arg_termid_addr.at_port = au_info->ai_termid.at_port; | 
| 431 | 	ar->k_ar.ar_arg_termid_addr.at_addr[0] = au_info->ai_termid.at_addr[0]; | 
| 432 | 	ar->k_ar.ar_arg_termid_addr.at_addr[1] = au_info->ai_termid.at_addr[1]; | 
| 433 | 	ar->k_ar.ar_arg_termid_addr.at_addr[2] = au_info->ai_termid.at_addr[2]; | 
| 434 | 	ar->k_ar.ar_arg_termid_addr.at_addr[3] = au_info->ai_termid.at_addr[3]; | 
| 435 | 	ARG_SET_VALID(ar, ARG_AUID | ARG_ASID | ARG_AMASK | ARG_TERMID_ADDR); | 
| 436 | } | 
| 437 |  | 
| 438 | void | 
| 439 | audit_arg_text(struct kaudit_record *ar, char *text) | 
| 440 | { | 
| 441 |  | 
| 442 | 	KASSERT(text != NULL, ("audit_arg_text: text == NULL" )); | 
| 443 |  | 
| 444 | 	/* Invalidate the text string */ | 
| 445 | 	ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_TEXT); | 
| 446 | 	if (text == NULL) | 
| 447 | 		return; | 
| 448 |  | 
| 449 | 	if (ar->k_ar.ar_arg_text == NULL)  | 
| 450 | 		ar->k_ar.ar_arg_text = malloc(MAXPATHLEN, M_AUDITTEXT,  | 
| 451 | 		    M_WAITOK); | 
| 452 |  | 
| 453 | 	strncpy(ar->k_ar.ar_arg_text, text, MAXPATHLEN); | 
| 454 | 	ARG_SET_VALID(ar, ARG_TEXT); | 
| 455 | } | 
| 456 |  | 
| 457 | void | 
| 458 | audit_arg_opaque(struct kaudit_record *ar, void *data, size_t size) | 
| 459 | { | 
| 460 |  | 
| 461 | 	KASSERT(data != NULL, ("audit_arg_opaque: data == NULL" )); | 
| 462 | 	KASSERT(size <= UINT16_MAX, ("audit_arg_opaque: size > UINT16_MAX" )); | 
| 463 |  | 
| 464 | 	if (data == NULL || size > UINT16_MAX) | 
| 465 | 		return; | 
| 466 |  | 
| 467 | 	if (ar->k_ar.ar_arg_opaque == NULL) | 
| 468 | 		ar->k_ar.ar_arg_opaque = malloc(size, M_AUDITDATA, M_WAITOK); | 
| 469 | 	else | 
| 470 | 		return; | 
| 471 |  | 
| 472 | 	memcpy(ar->k_ar.ar_arg_opaque, data, size); | 
| 473 | 	ar->k_ar.ar_arg_opq_size = (u_int16_t) size; | 
| 474 | 	ARG_SET_VALID(ar, ARG_OPAQUE); | 
| 475 | } | 
| 476 |  | 
| 477 | void | 
| 478 | audit_arg_data(struct kaudit_record *ar, void *data, size_t size, size_t number) | 
| 479 | { | 
| 480 | 	size_t sz; | 
| 481 |  | 
| 482 | 	KASSERT(data != NULL, ("audit_arg_data: data == NULL" )); | 
| 483 | 	KASSERT(size >= AUR_BYTE_SIZE && size <= AUR_INT64_SIZE, | 
| 484 | 	    ("audit_arg_data: size < AUR_BYTE_SIZE or size > AUR_INT64_SIZE" )); | 
| 485 | 	KASSERT(number <= UINT8_MAX, | 
| 486 | 	    ("audit_arg_data: number > UINT8_MAX" )); | 
| 487 |  | 
| 488 | 	if (data == NULL || size < AUR_BYTE_SIZE || size > AUR_INT64_SIZE || | 
| 489 | 	    number > UINT8_MAX) | 
| 490 | 		return; | 
| 491 |  | 
| 492 | 	sz = size * number; | 
| 493 |  | 
| 494 | 	if (ar->k_ar.ar_arg_data == NULL) | 
| 495 | 		ar->k_ar.ar_arg_data = malloc(sz, M_AUDITDATA, M_WAITOK); | 
| 496 | 	else | 
| 497 | 		return; | 
| 498 |  | 
| 499 | 	memcpy(ar->k_ar.ar_arg_data, data, sz); | 
| 500 |  | 
| 501 | 	switch(size) { | 
| 502 | 	case AUR_BYTE_SIZE: | 
| 503 | 		ar->k_ar.ar_arg_data_type = AUR_BYTE; | 
| 504 | 		break; | 
| 505 |  | 
| 506 | 	case AUR_SHORT_SIZE: | 
| 507 | 		ar->k_ar.ar_arg_data_type = AUR_SHORT; | 
| 508 | 		break; | 
| 509 |  | 
| 510 | 	case AUR_INT32_SIZE: | 
| 511 | 		ar->k_ar.ar_arg_data_type = AUR_INT32; | 
| 512 | 		break; | 
| 513 |  | 
| 514 | 	case AUR_INT64_SIZE: | 
| 515 | 		ar->k_ar.ar_arg_data_type = AUR_INT64; | 
| 516 | 		break; | 
| 517 |  | 
| 518 | 	default: | 
| 519 | 		free(ar->k_ar.ar_arg_data, M_AUDITDATA); | 
| 520 | 		ar->k_ar.ar_arg_data = NULL; | 
| 521 | 		return; | 
| 522 | 	} | 
| 523 |  | 
| 524 | 	ar->k_ar.ar_arg_data_count = (u_char)number; | 
| 525 |  | 
| 526 | 	ARG_SET_VALID(ar, ARG_DATA); | 
| 527 | } | 
| 528 |  | 
| 529 | void | 
| 530 | audit_arg_cmd(struct kaudit_record *ar, int cmd) | 
| 531 | { | 
| 532 |  | 
| 533 | 	ar->k_ar.ar_arg_cmd = cmd; | 
| 534 | 	ARG_SET_VALID(ar, ARG_CMD); | 
| 535 | } | 
| 536 |  | 
| 537 | void | 
| 538 | audit_arg_svipc_cmd(struct kaudit_record *ar, int cmd) | 
| 539 | { | 
| 540 |  | 
| 541 | 	ar->k_ar.ar_arg_svipc_cmd = cmd; | 
| 542 | 	ARG_SET_VALID(ar, ARG_SVIPC_CMD); | 
| 543 | } | 
| 544 |  | 
| 545 | void | 
| 546 | audit_arg_svipc_perm(struct kaudit_record *ar, struct ipc_perm *perm) | 
| 547 | { | 
| 548 |  | 
| 549 | 	bcopy(perm, &ar->k_ar.ar_arg_svipc_perm, | 
| 550 | 	    sizeof(ar->k_ar.ar_arg_svipc_perm)); | 
| 551 | 	ARG_SET_VALID(ar, ARG_SVIPC_PERM); | 
| 552 | } | 
| 553 |  | 
| 554 | void | 
| 555 | audit_arg_svipc_id(struct kaudit_record *ar, int id) | 
| 556 | { | 
| 557 |  | 
| 558 | 	ar->k_ar.ar_arg_svipc_id = id; | 
| 559 | 	ARG_SET_VALID(ar, ARG_SVIPC_ID); | 
| 560 | } | 
| 561 |  | 
| 562 | void | 
| 563 | audit_arg_svipc_addr(struct kaudit_record *ar, user_addr_t addr) | 
| 564 | { | 
| 565 |  | 
| 566 | 	ar->k_ar.ar_arg_svipc_addr = addr; | 
| 567 | 	ARG_SET_VALID(ar, ARG_SVIPC_ADDR); | 
| 568 | } | 
| 569 |  | 
| 570 | void | 
| 571 | audit_arg_posix_ipc_perm(struct kaudit_record *ar, uid_t uid, gid_t gid, | 
| 572 |     mode_t mode) | 
| 573 | { | 
| 574 |  | 
| 575 | 	ar->k_ar.ar_arg_pipc_perm.pipc_uid = uid; | 
| 576 | 	ar->k_ar.ar_arg_pipc_perm.pipc_gid = gid; | 
| 577 | 	ar->k_ar.ar_arg_pipc_perm.pipc_mode = mode; | 
| 578 | 	ARG_SET_VALID(ar, ARG_POSIX_IPC_PERM); | 
| 579 | } | 
| 580 |  | 
| 581 | void | 
| 582 | audit_arg_auditon(struct kaudit_record *ar, union auditon_udata *udata) | 
| 583 | { | 
| 584 |  | 
| 585 | 	bcopy((void *)udata, &ar->k_ar.ar_arg_auditon, | 
| 586 | 	    sizeof(ar->k_ar.ar_arg_auditon)); | 
| 587 | 	ARG_SET_VALID(ar, ARG_AUDITON); | 
| 588 | } | 
| 589 |  | 
| 590 | /* | 
| 591 |  * Audit information about a file, either the file's vnode info, or its | 
| 592 |  * socket address info. | 
| 593 |  */ | 
| 594 | void | 
| 595 | audit_arg_file(struct kaudit_record *ar, __unused proc_t p, | 
| 596 |     struct fileproc *fp) | 
| 597 | { | 
| 598 | 	struct socket *so; | 
| 599 | 	struct inpcb *pcb; | 
| 600 | 	struct sockaddr_in *sin; | 
| 601 | 	struct sockaddr_in6 *sin6; | 
| 602 |  | 
| 603 | 	switch (FILEGLOB_DTYPE(fp->f_fglob)) { | 
| 604 | 	case DTYPE_VNODE: | 
| 605 | 	/* case DTYPE_FIFO: */ | 
| 606 | 		audit_arg_vnpath_withref(ar, | 
| 607 | 		    (struct vnode *)fp->f_fglob->fg_data, ARG_VNODE1); | 
| 608 | 		break; | 
| 609 |  | 
| 610 | 	case DTYPE_SOCKET: | 
| 611 | 		so = (struct socket *)fp->f_fglob->fg_data; | 
| 612 | 		if (SOCK_CHECK_DOM(so, PF_INET)) { | 
| 613 | 			if (so->so_pcb == NULL) | 
| 614 | 				break; | 
| 615 | 			ar->k_ar.ar_arg_sockinfo.sai_type = | 
| 616 | 			    so->so_type; | 
| 617 | 			ar->k_ar.ar_arg_sockinfo.sai_domain = SOCK_DOM(so); | 
| 618 | 			ar->k_ar.ar_arg_sockinfo.sai_protocol = SOCK_PROTO(so); | 
| 619 | 			pcb = (struct inpcb *)so->so_pcb; | 
| 620 | 			sin = (struct sockaddr_in *) | 
| 621 | 			    &ar->k_ar.ar_arg_sockinfo.sai_faddr; | 
| 622 | 			sin->sin_addr.s_addr = pcb->inp_faddr.s_addr; | 
| 623 | 			sin->sin_port = pcb->inp_fport; | 
| 624 | 			sin = (struct sockaddr_in *) | 
| 625 | 			    &ar->k_ar.ar_arg_sockinfo.sai_laddr; | 
| 626 | 			sin->sin_addr.s_addr = pcb->inp_laddr.s_addr; | 
| 627 | 			sin->sin_port = pcb->inp_lport; | 
| 628 | 			ARG_SET_VALID(ar, ARG_SOCKINFO); | 
| 629 | 		} | 
| 630 | 		if (SOCK_CHECK_DOM(so, PF_INET6)) { | 
| 631 | 			if (so->so_pcb == NULL) | 
| 632 | 				break; | 
| 633 | 			ar->k_ar.ar_arg_sockinfo.sai_type = | 
| 634 | 			    so->so_type; | 
| 635 | 			ar->k_ar.ar_arg_sockinfo.sai_domain = SOCK_DOM(so); | 
| 636 | 			ar->k_ar.ar_arg_sockinfo.sai_protocol = SOCK_PROTO(so); | 
| 637 | 			pcb = (struct inpcb *)so->so_pcb; | 
| 638 | 			sin6 = (struct sockaddr_in6 *) | 
| 639 | 			    &ar->k_ar.ar_arg_sockinfo.sai_faddr; | 
| 640 | 			sin6->sin6_addr = pcb->in6p_faddr; | 
| 641 | 			sin6->sin6_port = pcb->in6p_fport; | 
| 642 | 			sin6 = (struct sockaddr_in6 *) | 
| 643 | 			    &ar->k_ar.ar_arg_sockinfo.sai_laddr; | 
| 644 | 			sin6->sin6_addr = pcb->in6p_laddr; | 
| 645 | 			sin6->sin6_port = pcb->in6p_lport; | 
| 646 | 			ARG_SET_VALID(ar, ARG_SOCKINFO); | 
| 647 | 		} | 
| 648 | 		break; | 
| 649 |  | 
| 650 | 	default: | 
| 651 | 		/* XXXAUDIT: else? */ | 
| 652 | 		break; | 
| 653 | 	} | 
| 654 | } | 
| 655 |  | 
| 656 | /* | 
| 657 |  * Store a path as given by the user process for auditing into the audit | 
| 658 |  * record stored on the user thread.  This function will allocate the memory | 
| 659 |  * to store the path info if not already available.  This memory will be | 
| 660 |  * freed when the audit record is freed. | 
| 661 |  *  | 
| 662 |  * Note that the current working directory vp must be supplied at the audit call | 
| 663 |  * site to permit per thread current working directories, and that it must take | 
| 664 |  * a upath starting with '/' into account for chroot if the path is absolute. | 
| 665 |  * This results in the real (non-chroot) path being recorded in the audit | 
| 666 |  * record. | 
| 667 |  * | 
| 668 |  * XXXAUDIT: Possibly assert that the memory isn't already allocated? | 
| 669 |  */ | 
| 670 | void | 
| 671 | audit_arg_upath(struct kaudit_record *ar, struct vnode *cwd_vp, char *upath, u_int64_t flag) | 
| 672 | { | 
| 673 | 	char **pathp; | 
| 674 |  | 
| 675 | 	KASSERT(upath != NULL, ("audit_arg_upath: upath == NULL" )); | 
| 676 | 	KASSERT((flag == ARG_UPATH1) || (flag == ARG_UPATH2), | 
| 677 | 	    ("audit_arg_upath: flag %llu" , (unsigned long long)flag)); | 
| 678 | 	KASSERT((flag != ARG_UPATH1) || (flag != ARG_UPATH2), | 
| 679 | 	    ("audit_arg_upath: flag %llu" , (unsigned long long)flag)); | 
| 680 |  | 
| 681 | 	if (flag == ARG_UPATH1) | 
| 682 | 		pathp = &ar->k_ar.ar_arg_upath1; | 
| 683 | 	else | 
| 684 | 		pathp = &ar->k_ar.ar_arg_upath2; | 
| 685 |  | 
| 686 | 	if (*pathp == NULL) | 
| 687 | 		*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK); | 
| 688 | 	else | 
| 689 | 		return; | 
| 690 |  | 
| 691 | 	if (audit_canon_path(cwd_vp, upath, *pathp) == 0) | 
| 692 | 		ARG_SET_VALID(ar, flag); | 
| 693 | 	else { | 
| 694 | 		free(*pathp, M_AUDITPATH); | 
| 695 | 		*pathp = NULL; | 
| 696 | 	} | 
| 697 | } | 
| 698 |  | 
| 699 | /* | 
| 700 |  * Function to save the path and vnode attr information into the audit | 
| 701 |  * record. | 
| 702 |  * | 
| 703 |  * It is assumed that the caller will hold any vnode locks necessary to | 
| 704 |  * perform a VNOP_GETATTR() on the passed vnode. | 
| 705 |  * | 
| 706 |  * XXX: The attr code is very similar to vfs_vnops.c:vn_stat(), but always | 
| 707 |  * provides access to the generation number as we need that to construct the | 
| 708 |  * BSM file ID. | 
| 709 |  * | 
| 710 |  * XXX: We should accept the process argument from the caller, since it's | 
| 711 |  * very likely they already have a reference. | 
| 712 |  * | 
| 713 |  * XXX: Error handling in this function is poor. | 
| 714 |  * | 
| 715 |  * XXXAUDIT: Possibly KASSERT the path pointer is NULL? | 
| 716 |  */ | 
| 717 | void | 
| 718 | audit_arg_vnpath(struct kaudit_record *ar, struct vnode *vp, u_int64_t flags) | 
| 719 | { | 
| 720 | 	struct vnode_attr va; | 
| 721 | 	int error; | 
| 722 | 	int len; | 
| 723 | 	char **pathp; | 
| 724 | 	struct vnode_au_info *vnp; | 
| 725 | 	proc_t p; | 
| 726 | #if CONFIG_MACF | 
| 727 | 	char **vnode_mac_labelp; | 
| 728 | 	struct mac mac; | 
| 729 | #endif | 
| 730 |  | 
| 731 | 	KASSERT(vp != NULL, ("audit_arg_vnpath: vp == NULL" )); | 
| 732 | 	KASSERT((flags == ARG_VNODE1) || (flags == ARG_VNODE2), | 
| 733 | 	    ("audit_arg_vnpath: flags != ARG_VNODE[1,2]" )); | 
| 734 |  | 
| 735 | 	p = current_proc(); | 
| 736 |  | 
| 737 | 	/*  | 
| 738 | 	 * XXXAUDIT: The below clears, and then resets the flags for valid | 
| 739 | 	 * arguments.  Ideally, either the new vnode is used, or the old one | 
| 740 | 	 * would be. | 
| 741 | 	 */ | 
| 742 | 	if (flags & ARG_VNODE1) { | 
| 743 | 		ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_KPATH1); | 
| 744 | 		ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_VNODE1); | 
| 745 | 		pathp = &ar->k_ar.ar_arg_kpath1; | 
| 746 | 		vnp = &ar->k_ar.ar_arg_vnode1; | 
| 747 | #if CONFIG_MACF | 
| 748 | 		vnode_mac_labelp = &ar->k_ar.ar_vnode1_mac_labels; | 
| 749 | #endif | 
| 750 | 	} else { | 
| 751 | 		ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_KPATH2); | 
| 752 | 		ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_VNODE2); | 
| 753 | 		pathp = &ar->k_ar.ar_arg_kpath2; | 
| 754 | 		vnp = &ar->k_ar.ar_arg_vnode2; | 
| 755 | #if CONFIG_MACF | 
| 756 | 		vnode_mac_labelp = &ar->k_ar.ar_vnode2_mac_labels; | 
| 757 | #endif | 
| 758 | 	} | 
| 759 |  | 
| 760 | 	if (*pathp == NULL) | 
| 761 | 		*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK); | 
| 762 | 	else | 
| 763 | 		return; | 
| 764 |  | 
| 765 | 	/* | 
| 766 | 	 * If vn_getpath() succeeds, place it in a string buffer | 
| 767 | 	 * attached to the audit record, and set a flag indicating | 
| 768 | 	 * it is present. | 
| 769 | 	 */ | 
| 770 | 	len = MAXPATHLEN; | 
| 771 | 	if (vn_getpath(vp, *pathp, &len) == 0) { | 
| 772 | 		if (flags & ARG_VNODE1) | 
| 773 | 			ARG_SET_VALID(ar, ARG_KPATH1); | 
| 774 | 		else | 
| 775 | 			ARG_SET_VALID(ar, ARG_KPATH2); | 
| 776 | 	} else { | 
| 777 | 		free(*pathp, M_AUDITPATH); | 
| 778 | 		*pathp = NULL; | 
| 779 | 	} | 
| 780 |  | 
| 781 | 	VATTR_INIT(&va); | 
| 782 | 	VATTR_WANTED(&va, va_mode); | 
| 783 | 	VATTR_WANTED(&va, va_uid); | 
| 784 | 	VATTR_WANTED(&va, va_gid); | 
| 785 | 	VATTR_WANTED(&va, va_rdev); | 
| 786 | 	VATTR_WANTED(&va, va_fsid); | 
| 787 | 	VATTR_WANTED(&va, va_fileid); | 
| 788 | 	VATTR_WANTED(&va, va_gen); | 
| 789 | 	error = vnode_getattr(vp, &va, vfs_context_current()); | 
| 790 | 	if (error) { | 
| 791 | 		/* XXX: How to handle this case? */ | 
| 792 | 		return; | 
| 793 | 	} | 
| 794 |  | 
| 795 | #if CONFIG_MACF | 
| 796 | 	if (*vnode_mac_labelp == NULL && (vp->v_lflag & VL_LABELED) == VL_LABELED) { | 
| 797 | 		*vnode_mac_labelp = (char *)zalloc(audit_mac_label_zone); | 
| 798 | 		if (*vnode_mac_labelp != NULL) { | 
| 799 | 			mac.m_buflen = MAC_AUDIT_LABEL_LEN; | 
| 800 | 			mac.m_string = *vnode_mac_labelp; | 
| 801 | 			mac_vnode_label_externalize_audit(vp, &mac); | 
| 802 | 		} | 
| 803 | 	} | 
| 804 | #endif | 
| 805 |  | 
| 806 | 	/* | 
| 807 | 	 * XXX do we want to fall back here when these aren't supported? | 
| 808 | 	 */ | 
| 809 | 	vnp->vn_mode = va.va_mode; | 
| 810 | 	vnp->vn_uid = va.va_uid; | 
| 811 | 	vnp->vn_gid = va.va_gid; | 
| 812 | 	vnp->vn_dev = va.va_rdev; | 
| 813 | 	vnp->vn_fsid = va.va_fsid; | 
| 814 | 	vnp->vn_fileid = (u_int32_t)va.va_fileid; | 
| 815 | 	vnp->vn_gen = va.va_gen; | 
| 816 | 	if (flags & ARG_VNODE1) | 
| 817 | 		ARG_SET_VALID(ar, ARG_VNODE1); | 
| 818 | 	else | 
| 819 | 		ARG_SET_VALID(ar, ARG_VNODE2); | 
| 820 | } | 
| 821 |  | 
| 822 | void | 
| 823 | audit_arg_vnpath_withref(struct kaudit_record *ar, struct vnode *vp, u_int64_t flags) | 
| 824 | { | 
| 825 | 	if (vp == NULL || vnode_getwithref(vp)) | 
| 826 | 		return; | 
| 827 | 	audit_arg_vnpath(ar, vp, flags); | 
| 828 | 	(void)vnode_put(vp); | 
| 829 | } | 
| 830 |  | 
| 831 | void | 
| 832 | audit_arg_mach_port1(struct kaudit_record *ar, mach_port_name_t port) | 
| 833 | { | 
| 834 |  | 
| 835 | 	ar->k_ar.ar_arg_mach_port1 = port; | 
| 836 | 	ARG_SET_VALID(ar, ARG_MACHPORT1); | 
| 837 | } | 
| 838 |  | 
| 839 | void | 
| 840 | audit_arg_mach_port2(struct kaudit_record *ar, mach_port_name_t port) | 
| 841 | { | 
| 842 |  | 
| 843 | 	ar->k_ar.ar_arg_mach_port2 = port; | 
| 844 | 	ARG_SET_VALID(ar, ARG_MACHPORT2); | 
| 845 | } | 
| 846 |  | 
| 847 |  | 
| 848 | /* | 
| 849 |  * Audit the argument strings passed to exec. | 
| 850 |  */ | 
| 851 | void | 
| 852 | audit_arg_argv(struct kaudit_record *ar, char *argv, int argc, int length) | 
| 853 | { | 
| 854 |  | 
| 855 | 	if (audit_argv == 0 || argc == 0) | 
| 856 | 		return; | 
| 857 |  | 
| 858 | 	if (ar->k_ar.ar_arg_argv == NULL) | 
| 859 | 		ar->k_ar.ar_arg_argv = malloc(length, M_AUDITTEXT, M_WAITOK); | 
| 860 | 	bcopy(argv, ar->k_ar.ar_arg_argv, length); | 
| 861 | 	ar->k_ar.ar_arg_argc = argc; | 
| 862 | 	ARG_SET_VALID(ar, ARG_ARGV); | 
| 863 | } | 
| 864 |  | 
| 865 | /* | 
| 866 |  * Audit the environment strings passed to exec. | 
| 867 |  */ | 
| 868 | void | 
| 869 | audit_arg_envv(struct kaudit_record *ar, char *envv, int envc, int length) | 
| 870 | { | 
| 871 |  | 
| 872 | 	if (audit_arge == 0 || envc == 0) | 
| 873 | 		return; | 
| 874 |  | 
| 875 | 	if (ar->k_ar.ar_arg_envv == NULL) | 
| 876 | 		ar->k_ar.ar_arg_envv = malloc(length, M_AUDITTEXT, M_WAITOK); | 
| 877 | 	bcopy(envv, ar->k_ar.ar_arg_envv, length); | 
| 878 | 	ar->k_ar.ar_arg_envc = envc; | 
| 879 | 	ARG_SET_VALID(ar, ARG_ENVV); | 
| 880 | } | 
| 881 |  | 
| 882 | /* | 
| 883 |  * The close() system call uses it's own audit call to capture the path/vnode | 
| 884 |  * information because those pieces are not easily obtained within the system | 
| 885 |  * call itself. | 
| 886 |  */ | 
| 887 | void | 
| 888 | audit_sysclose(struct kaudit_record *ar, proc_t p, int fd) | 
| 889 | { | 
| 890 | 	struct fileproc *fp; | 
| 891 | 	struct vnode *vp; | 
| 892 |  | 
| 893 | 	KASSERT(p != NULL, ("audit_sysclose: p == NULL" )); | 
| 894 |  | 
| 895 | 	audit_arg_fd(ar, fd); | 
| 896 |  | 
| 897 | 	if (fp_getfvp(p, fd, &fp, &vp) != 0) | 
| 898 | 		return; | 
| 899 |  | 
| 900 | 	audit_arg_vnpath_withref(ar, (struct vnode *)fp->f_fglob->fg_data, | 
| 901 | 	    ARG_VNODE1); | 
| 902 | 	fp_drop(p, fd, fp, 0); | 
| 903 | } | 
| 904 |  | 
| 905 | void | 
| 906 | audit_identity_info_destruct(struct au_identity_info *id_info) | 
| 907 | { | 
| 908 | 	if (!id_info) { | 
| 909 | 		return; | 
| 910 | 	} | 
| 911 |  | 
| 912 | 	if (id_info->signing_id != NULL) { | 
| 913 | 		free(id_info->signing_id, M_AUDITTEXT); | 
| 914 | 		id_info->signing_id = NULL; | 
| 915 | 	} | 
| 916 |  | 
| 917 | 	if (id_info->team_id != NULL) { | 
| 918 | 		free(id_info->team_id, M_AUDITTEXT); | 
| 919 | 		id_info->team_id = NULL; | 
| 920 | 	} | 
| 921 |  | 
| 922 | 	if (id_info->cdhash != NULL) { | 
| 923 | 		free(id_info->cdhash, M_AUDITDATA); | 
| 924 | 		id_info->cdhash = NULL; | 
| 925 | 	} | 
| 926 | } | 
| 927 |  | 
| 928 | void | 
| 929 | audit_identity_info_construct(struct au_identity_info *id_info) | 
| 930 | { | 
| 931 | 	struct proc *p; | 
| 932 | 	struct cs_blob *blob; | 
| 933 | 	unsigned int signer_type = 0; | 
| 934 | 	const char *signing_id = NULL; | 
| 935 | 	const char* team_id = NULL; | 
| 936 | 	const uint8_t *cdhash = NULL; | 
| 937 | 	size_t src_len = 0; | 
| 938 |  | 
| 939 | 	p = current_proc(); | 
| 940 | 	blob = csproc_get_blob(p); | 
| 941 | 	if (blob) { | 
| 942 | 		signing_id = csblob_get_identity(blob); | 
| 943 | 		cdhash = csblob_get_cdhash(blob); | 
| 944 | 		team_id = csblob_get_teamid(blob); | 
| 945 | 		signer_type = csblob_get_platform_binary(blob) ? 1 : 0; | 
| 946 | 	} | 
| 947 |  | 
| 948 | 	id_info->signer_type = signer_type; | 
| 949 |  | 
| 950 | 	if (id_info->signing_id == NULL && signing_id != NULL) { | 
| 951 | 		id_info->signing_id = malloc( MAX_AU_IDENTITY_SIGNING_ID_LENGTH, | 
| 952 | 			M_AUDITTEXT, M_WAITOK); | 
| 953 | 		if (id_info->signing_id != NULL) { | 
| 954 | 			src_len = strlcpy(id_info->signing_id, | 
| 955 | 				signing_id, MAX_AU_IDENTITY_SIGNING_ID_LENGTH); | 
| 956 |  | 
| 957 | 			if (src_len >= MAX_AU_IDENTITY_SIGNING_ID_LENGTH) { | 
| 958 | 				id_info->signing_id_trunc = 1; | 
| 959 | 			} | 
| 960 | 		} | 
| 961 | 	} | 
| 962 |  | 
| 963 | 	if (id_info->team_id == NULL && team_id != NULL) { | 
| 964 | 		id_info->team_id = malloc(MAX_AU_IDENTITY_TEAM_ID_LENGTH, | 
| 965 | 			M_AUDITTEXT, M_WAITOK); | 
| 966 | 		if (id_info->team_id != NULL) { | 
| 967 | 			src_len = strlcpy(id_info->team_id, team_id, | 
| 968 | 				MAX_AU_IDENTITY_TEAM_ID_LENGTH); | 
| 969 |  | 
| 970 | 			if (src_len >= MAX_AU_IDENTITY_TEAM_ID_LENGTH) { | 
| 971 | 				id_info->team_id_trunc = 1; | 
| 972 | 			} | 
| 973 | 		} | 
| 974 | 	} | 
| 975 |  | 
| 976 | 	if (id_info->cdhash == NULL && cdhash != NULL) { | 
| 977 | 		id_info->cdhash = malloc(CS_CDHASH_LEN, M_AUDITDATA, M_WAITOK); | 
| 978 | 		if (id_info->cdhash != NULL) { | 
| 979 | 			memcpy(id_info->cdhash, cdhash, CS_CDHASH_LEN); | 
| 980 | 			id_info->cdhash_len = CS_CDHASH_LEN; | 
| 981 | 		} | 
| 982 | 	} | 
| 983 | } | 
| 984 |  | 
| 985 | void | 
| 986 | audit_arg_identity(struct kaudit_record *ar) | 
| 987 | { | 
| 988 | 	audit_identity_info_construct(&ar->k_ar.ar_arg_identity); | 
| 989 | 	ARG_SET_VALID(ar, ARG_IDENTITY); | 
| 990 | } | 
| 991 |  | 
| 992 | #endif /* CONFIG_AUDIT */ | 
| 993 |  |