xref: /freebsd/sys/security/audit/audit_arg.c (revision 6419bb52)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1999-2005 Apple Inc.
5  * Copyright (c) 2016-2017 Robert N. M. Watson
6  * All rights reserved.
7  *
8  * Portions of this software were developed by BAE Systems, the University of
9  * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL
10  * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent
11  * Computing (TC) research program.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1.  Redistributions of source code must retain the above copyright
17  *     notice, this list of conditions and the following disclaimer.
18  * 2.  Redistributions in binary form must reproduce the above copyright
19  *     notice, this list of conditions and the following disclaimer in the
20  *     documentation and/or other materials provided with the distribution.
21  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
22  *     its contributors may be used to endorse or promote products derived
23  *     from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
29  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
34  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40 
41 #include <sys/param.h>
42 #include <sys/filedesc.h>
43 #include <sys/capsicum.h>
44 #include <sys/ipc.h>
45 #include <sys/mount.h>
46 #include <sys/proc.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/protosw.h>
50 #include <sys/domain.h>
51 #include <sys/sbuf.h>
52 #include <sys/systm.h>
53 #include <sys/un.h>
54 #include <sys/vnode.h>
55 
56 #include <netinet/in.h>
57 #include <netinet/in_pcb.h>
58 
59 #include <security/audit/audit.h>
60 #include <security/audit/audit_private.h>
61 
62 /*
63  * Calls to manipulate elements of the audit record structure from system
64  * call code.  Macro wrappers will prevent this functions from being entered
65  * if auditing is disabled, avoiding the function call cost.  We check the
66  * thread audit record pointer anyway, as the audit condition could change,
67  * and pre-selection may not have allocated an audit record for this event.
68  *
69  * XXXAUDIT: Should we assert, in each case, that this field of the record
70  * hasn't already been filled in?
71  */
72 void
73 audit_arg_addr(void *addr)
74 {
75 	struct kaudit_record *ar;
76 
77 	ar = currecord();
78 	if (ar == NULL)
79 		return;
80 
81 	ar->k_ar.ar_arg_addr = addr;
82 	ARG_SET_VALID(ar, ARG_ADDR);
83 }
84 
85 void
86 audit_arg_exit(int status, int retval)
87 {
88 	struct kaudit_record *ar;
89 
90 	ar = currecord();
91 	if (ar == NULL)
92 		return;
93 
94 	ar->k_ar.ar_arg_exitstatus = status;
95 	ar->k_ar.ar_arg_exitretval = retval;
96 	ARG_SET_VALID(ar, ARG_EXIT);
97 }
98 
99 void
100 audit_arg_len(int len)
101 {
102 	struct kaudit_record *ar;
103 
104 	ar = currecord();
105 	if (ar == NULL)
106 		return;
107 
108 	ar->k_ar.ar_arg_len = len;
109 	ARG_SET_VALID(ar, ARG_LEN);
110 }
111 
112 void
113 audit_arg_atfd1(int atfd)
114 {
115 	struct kaudit_record *ar;
116 
117 	ar = currecord();
118 	if (ar == NULL)
119 		return;
120 
121 	ar->k_ar.ar_arg_atfd1 = atfd;
122 	ARG_SET_VALID(ar, ARG_ATFD1);
123 }
124 
125 void
126 audit_arg_atfd2(int atfd)
127 {
128 	struct kaudit_record *ar;
129 
130 	ar = currecord();
131 	if (ar == NULL)
132 		return;
133 
134 	ar->k_ar.ar_arg_atfd2 = atfd;
135 	ARG_SET_VALID(ar, ARG_ATFD2);
136 }
137 
138 void
139 audit_arg_fd(int fd)
140 {
141 	struct kaudit_record *ar;
142 
143 	ar = currecord();
144 	if (ar == NULL)
145 		return;
146 
147 	ar->k_ar.ar_arg_fd = fd;
148 	ARG_SET_VALID(ar, ARG_FD);
149 }
150 
151 void
152 audit_arg_fflags(int fflags)
153 {
154 	struct kaudit_record *ar;
155 
156 	ar = currecord();
157 	if (ar == NULL)
158 		return;
159 
160 	ar->k_ar.ar_arg_fflags = fflags;
161 	ARG_SET_VALID(ar, ARG_FFLAGS);
162 }
163 
164 void
165 audit_arg_gid(gid_t gid)
166 {
167 	struct kaudit_record *ar;
168 
169 	ar = currecord();
170 	if (ar == NULL)
171 		return;
172 
173 	ar->k_ar.ar_arg_gid = gid;
174 	ARG_SET_VALID(ar, ARG_GID);
175 }
176 
177 void
178 audit_arg_uid(uid_t uid)
179 {
180 	struct kaudit_record *ar;
181 
182 	ar = currecord();
183 	if (ar == NULL)
184 		return;
185 
186 	ar->k_ar.ar_arg_uid = uid;
187 	ARG_SET_VALID(ar, ARG_UID);
188 }
189 
190 void
191 audit_arg_egid(gid_t egid)
192 {
193 	struct kaudit_record *ar;
194 
195 	ar = currecord();
196 	if (ar == NULL)
197 		return;
198 
199 	ar->k_ar.ar_arg_egid = egid;
200 	ARG_SET_VALID(ar, ARG_EGID);
201 }
202 
203 void
204 audit_arg_euid(uid_t euid)
205 {
206 	struct kaudit_record *ar;
207 
208 	ar = currecord();
209 	if (ar == NULL)
210 		return;
211 
212 	ar->k_ar.ar_arg_euid = euid;
213 	ARG_SET_VALID(ar, ARG_EUID);
214 }
215 
216 void
217 audit_arg_rgid(gid_t rgid)
218 {
219 	struct kaudit_record *ar;
220 
221 	ar = currecord();
222 	if (ar == NULL)
223 		return;
224 
225 	ar->k_ar.ar_arg_rgid = rgid;
226 	ARG_SET_VALID(ar, ARG_RGID);
227 }
228 
229 void
230 audit_arg_ruid(uid_t ruid)
231 {
232 	struct kaudit_record *ar;
233 
234 	ar = currecord();
235 	if (ar == NULL)
236 		return;
237 
238 	ar->k_ar.ar_arg_ruid = ruid;
239 	ARG_SET_VALID(ar, ARG_RUID);
240 }
241 
242 void
243 audit_arg_sgid(gid_t sgid)
244 {
245 	struct kaudit_record *ar;
246 
247 	ar = currecord();
248 	if (ar == NULL)
249 		return;
250 
251 	ar->k_ar.ar_arg_sgid = sgid;
252 	ARG_SET_VALID(ar, ARG_SGID);
253 }
254 
255 void
256 audit_arg_suid(uid_t suid)
257 {
258 	struct kaudit_record *ar;
259 
260 	ar = currecord();
261 	if (ar == NULL)
262 		return;
263 
264 	ar->k_ar.ar_arg_suid = suid;
265 	ARG_SET_VALID(ar, ARG_SUID);
266 }
267 
268 void
269 audit_arg_groupset(gid_t *gidset, u_int gidset_size)
270 {
271 	u_int i;
272 	struct kaudit_record *ar;
273 
274 	KASSERT(gidset_size <= ngroups_max + 1,
275 	    ("audit_arg_groupset: gidset_size > (kern.ngroups + 1)"));
276 
277 	ar = currecord();
278 	if (ar == NULL)
279 		return;
280 
281 	if (ar->k_ar.ar_arg_groups.gidset == NULL)
282 		ar->k_ar.ar_arg_groups.gidset = malloc(
283 		    sizeof(gid_t) * gidset_size, M_AUDITGIDSET, M_WAITOK);
284 
285 	for (i = 0; i < gidset_size; i++)
286 		ar->k_ar.ar_arg_groups.gidset[i] = gidset[i];
287 	ar->k_ar.ar_arg_groups.gidset_size = gidset_size;
288 	ARG_SET_VALID(ar, ARG_GROUPSET);
289 }
290 
291 void
292 audit_arg_login(char *login)
293 {
294 	struct kaudit_record *ar;
295 
296 	ar = currecord();
297 	if (ar == NULL)
298 		return;
299 
300 	strlcpy(ar->k_ar.ar_arg_login, login, MAXLOGNAME);
301 	ARG_SET_VALID(ar, ARG_LOGIN);
302 }
303 
304 void
305 audit_arg_ctlname(int *name, int namelen)
306 {
307 	struct kaudit_record *ar;
308 
309 	ar = currecord();
310 	if (ar == NULL)
311 		return;
312 
313 	bcopy(name, &ar->k_ar.ar_arg_ctlname, namelen * sizeof(int));
314 	ar->k_ar.ar_arg_len = namelen;
315 	ARG_SET_VALID(ar, ARG_CTLNAME | ARG_LEN);
316 }
317 
318 void
319 audit_arg_mask(int mask)
320 {
321 	struct kaudit_record *ar;
322 
323 	ar = currecord();
324 	if (ar == NULL)
325 		return;
326 
327 	ar->k_ar.ar_arg_mask = mask;
328 	ARG_SET_VALID(ar, ARG_MASK);
329 }
330 
331 void
332 audit_arg_mode(mode_t mode)
333 {
334 	struct kaudit_record *ar;
335 
336 	ar = currecord();
337 	if (ar == NULL)
338 		return;
339 
340 	ar->k_ar.ar_arg_mode = mode;
341 	ARG_SET_VALID(ar, ARG_MODE);
342 }
343 
344 void
345 audit_arg_dev(int dev)
346 {
347 	struct kaudit_record *ar;
348 
349 	ar = currecord();
350 	if (ar == NULL)
351 		return;
352 
353 	ar->k_ar.ar_arg_dev = dev;
354 	ARG_SET_VALID(ar, ARG_DEV);
355 }
356 
357 void
358 audit_arg_value(long value)
359 {
360 	struct kaudit_record *ar;
361 
362 	ar = currecord();
363 	if (ar == NULL)
364 		return;
365 
366 	ar->k_ar.ar_arg_value = value;
367 	ARG_SET_VALID(ar, ARG_VALUE);
368 }
369 
370 void
371 audit_arg_owner(uid_t uid, gid_t gid)
372 {
373 	struct kaudit_record *ar;
374 
375 	ar = currecord();
376 	if (ar == NULL)
377 		return;
378 
379 	ar->k_ar.ar_arg_uid = uid;
380 	ar->k_ar.ar_arg_gid = gid;
381 	ARG_SET_VALID(ar, ARG_UID | ARG_GID);
382 }
383 
384 void
385 audit_arg_pid(pid_t pid)
386 {
387 	struct kaudit_record *ar;
388 
389 	ar = currecord();
390 	if (ar == NULL)
391 		return;
392 
393 	ar->k_ar.ar_arg_pid = pid;
394 	ARG_SET_VALID(ar, ARG_PID);
395 }
396 
397 void
398 audit_arg_process(struct proc *p)
399 {
400 	struct kaudit_record *ar;
401 	struct ucred *cred;
402 
403 	KASSERT(p != NULL, ("audit_arg_process: p == NULL"));
404 
405 	PROC_LOCK_ASSERT(p, MA_OWNED);
406 
407 	ar = currecord();
408 	if (ar == NULL)
409 		return;
410 
411 	cred = p->p_ucred;
412 	ar->k_ar.ar_arg_auid = cred->cr_audit.ai_auid;
413 	ar->k_ar.ar_arg_euid = cred->cr_uid;
414 	ar->k_ar.ar_arg_egid = cred->cr_groups[0];
415 	ar->k_ar.ar_arg_ruid = cred->cr_ruid;
416 	ar->k_ar.ar_arg_rgid = cred->cr_rgid;
417 	ar->k_ar.ar_arg_asid = cred->cr_audit.ai_asid;
418 	ar->k_ar.ar_arg_termid_addr = cred->cr_audit.ai_termid;
419 	ar->k_ar.ar_arg_pid = p->p_pid;
420 	ARG_SET_VALID(ar, ARG_AUID | ARG_EUID | ARG_EGID | ARG_RUID |
421 	    ARG_RGID | ARG_ASID | ARG_TERMID_ADDR | ARG_PID | ARG_PROCESS);
422 }
423 
424 void
425 audit_arg_signum(u_int signum)
426 {
427 	struct kaudit_record *ar;
428 
429 	ar = currecord();
430 	if (ar == NULL)
431 		return;
432 
433 	ar->k_ar.ar_arg_signum = signum;
434 	ARG_SET_VALID(ar, ARG_SIGNUM);
435 }
436 
437 void
438 audit_arg_socket(int sodomain, int sotype, int soprotocol)
439 {
440 	struct kaudit_record *ar;
441 
442 	ar = currecord();
443 	if (ar == NULL)
444 		return;
445 
446 	ar->k_ar.ar_arg_sockinfo.so_domain = sodomain;
447 	ar->k_ar.ar_arg_sockinfo.so_type = sotype;
448 	ar->k_ar.ar_arg_sockinfo.so_protocol = soprotocol;
449 	ARG_SET_VALID(ar, ARG_SOCKINFO);
450 }
451 
452 void
453 audit_arg_sockaddr(struct thread *td, int dirfd, struct sockaddr *sa)
454 {
455 	struct kaudit_record *ar;
456 
457 	KASSERT(td != NULL, ("audit_arg_sockaddr: td == NULL"));
458 	KASSERT(sa != NULL, ("audit_arg_sockaddr: sa == NULL"));
459 
460 	ar = currecord();
461 	if (ar == NULL)
462 		return;
463 
464 	bcopy(sa, &ar->k_ar.ar_arg_sockaddr, sa->sa_len);
465 	switch (sa->sa_family) {
466 	case AF_INET:
467 		ARG_SET_VALID(ar, ARG_SADDRINET);
468 		break;
469 
470 	case AF_INET6:
471 		ARG_SET_VALID(ar, ARG_SADDRINET6);
472 		break;
473 
474 	case AF_UNIX:
475 		if (dirfd != AT_FDCWD)
476 			audit_arg_atfd1(dirfd);
477 		audit_arg_upath1(td, dirfd,
478 		    ((struct sockaddr_un *)sa)->sun_path);
479 		ARG_SET_VALID(ar, ARG_SADDRUNIX);
480 		break;
481 	/* XXXAUDIT: default:? */
482 	}
483 }
484 
485 void
486 audit_arg_auid(uid_t auid)
487 {
488 	struct kaudit_record *ar;
489 
490 	ar = currecord();
491 	if (ar == NULL)
492 		return;
493 
494 	ar->k_ar.ar_arg_auid = auid;
495 	ARG_SET_VALID(ar, ARG_AUID);
496 }
497 
498 void
499 audit_arg_auditinfo(struct auditinfo *au_info)
500 {
501 	struct kaudit_record *ar;
502 
503 	ar = currecord();
504 	if (ar == NULL)
505 		return;
506 
507 	ar->k_ar.ar_arg_auid = au_info->ai_auid;
508 	ar->k_ar.ar_arg_asid = au_info->ai_asid;
509 	ar->k_ar.ar_arg_amask.am_success = au_info->ai_mask.am_success;
510 	ar->k_ar.ar_arg_amask.am_failure = au_info->ai_mask.am_failure;
511 	ar->k_ar.ar_arg_termid.port = au_info->ai_termid.port;
512 	ar->k_ar.ar_arg_termid.machine = au_info->ai_termid.machine;
513 	ARG_SET_VALID(ar, ARG_AUID | ARG_ASID | ARG_AMASK | ARG_TERMID);
514 }
515 
516 void
517 audit_arg_auditinfo_addr(struct auditinfo_addr *au_info)
518 {
519 	struct kaudit_record *ar;
520 
521 	ar = currecord();
522 	if (ar == NULL)
523 		return;
524 
525 	ar->k_ar.ar_arg_auid = au_info->ai_auid;
526 	ar->k_ar.ar_arg_asid = au_info->ai_asid;
527 	ar->k_ar.ar_arg_amask.am_success = au_info->ai_mask.am_success;
528 	ar->k_ar.ar_arg_amask.am_failure = au_info->ai_mask.am_failure;
529 	ar->k_ar.ar_arg_termid_addr.at_type = au_info->ai_termid.at_type;
530 	ar->k_ar.ar_arg_termid_addr.at_port = au_info->ai_termid.at_port;
531 	ar->k_ar.ar_arg_termid_addr.at_addr[0] = au_info->ai_termid.at_addr[0];
532 	ar->k_ar.ar_arg_termid_addr.at_addr[1] = au_info->ai_termid.at_addr[1];
533 	ar->k_ar.ar_arg_termid_addr.at_addr[2] = au_info->ai_termid.at_addr[2];
534 	ar->k_ar.ar_arg_termid_addr.at_addr[3] = au_info->ai_termid.at_addr[3];
535 	ARG_SET_VALID(ar, ARG_AUID | ARG_ASID | ARG_AMASK | ARG_TERMID_ADDR);
536 }
537 
538 void
539 audit_arg_text(const char *text)
540 {
541 	struct kaudit_record *ar;
542 
543 	KASSERT(text != NULL, ("audit_arg_text: text == NULL"));
544 
545 	ar = currecord();
546 	if (ar == NULL)
547 		return;
548 
549 	/* Invalidate the text string */
550 	ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_TEXT);
551 
552 	if (ar->k_ar.ar_arg_text == NULL)
553 		ar->k_ar.ar_arg_text = malloc(MAXPATHLEN, M_AUDITTEXT,
554 		    M_WAITOK);
555 
556 	strncpy(ar->k_ar.ar_arg_text, text, MAXPATHLEN);
557 	ARG_SET_VALID(ar, ARG_TEXT);
558 }
559 
560 void
561 audit_arg_cmd(int cmd)
562 {
563 	struct kaudit_record *ar;
564 
565 	ar = currecord();
566 	if (ar == NULL)
567 		return;
568 
569 	ar->k_ar.ar_arg_cmd = cmd;
570 	ARG_SET_VALID(ar, ARG_CMD);
571 }
572 
573 void
574 audit_arg_svipc_cmd(int cmd)
575 {
576 	struct kaudit_record *ar;
577 
578 	ar = currecord();
579 	if (ar == NULL)
580 		return;
581 
582 	ar->k_ar.ar_arg_svipc_cmd = cmd;
583 	ARG_SET_VALID(ar, ARG_SVIPC_CMD);
584 }
585 
586 void
587 audit_arg_svipc_perm(struct ipc_perm *perm)
588 {
589 	struct kaudit_record *ar;
590 
591 	ar = currecord();
592 	if (ar == NULL)
593 		return;
594 
595 	bcopy(perm, &ar->k_ar.ar_arg_svipc_perm,
596 	    sizeof(ar->k_ar.ar_arg_svipc_perm));
597 	ARG_SET_VALID(ar, ARG_SVIPC_PERM);
598 }
599 
600 void
601 audit_arg_svipc_id(int id)
602 {
603 	struct kaudit_record *ar;
604 
605 	ar = currecord();
606 	if (ar == NULL)
607 		return;
608 
609 	ar->k_ar.ar_arg_svipc_id = id;
610 	ARG_SET_VALID(ar, ARG_SVIPC_ID);
611 }
612 
613 void
614 audit_arg_svipc_addr(void * addr)
615 {
616 	struct kaudit_record *ar;
617 
618 	ar = currecord();
619 	if (ar == NULL)
620 		return;
621 
622 	ar->k_ar.ar_arg_svipc_addr = addr;
623 	ARG_SET_VALID(ar, ARG_SVIPC_ADDR);
624 }
625 
626 void
627 audit_arg_svipc_which(int which)
628 {
629 	struct kaudit_record *ar;
630 
631 	ar = currecord();
632 	if (ar == NULL)
633 		return;
634 
635 	ar->k_ar.ar_arg_svipc_which = which;
636 	ARG_SET_VALID(ar, ARG_SVIPC_WHICH);
637 }
638 
639 void
640 audit_arg_posix_ipc_perm(uid_t uid, gid_t gid, mode_t mode)
641 {
642 	struct kaudit_record *ar;
643 
644 	ar = currecord();
645 	if (ar == NULL)
646 		return;
647 
648 	ar->k_ar.ar_arg_pipc_perm.pipc_uid = uid;
649 	ar->k_ar.ar_arg_pipc_perm.pipc_gid = gid;
650 	ar->k_ar.ar_arg_pipc_perm.pipc_mode = mode;
651 	ARG_SET_VALID(ar, ARG_POSIX_IPC_PERM);
652 }
653 
654 void
655 audit_arg_auditon(union auditon_udata *udata)
656 {
657 	struct kaudit_record *ar;
658 
659 	ar = currecord();
660 	if (ar == NULL)
661 		return;
662 
663 	bcopy((void *)udata, &ar->k_ar.ar_arg_auditon,
664 	    sizeof(ar->k_ar.ar_arg_auditon));
665 	ARG_SET_VALID(ar, ARG_AUDITON);
666 }
667 
668 /*
669  * Audit information about a file, either the file's vnode info, or its
670  * socket address info.
671  */
672 void
673 audit_arg_file(struct proc *p, struct file *fp)
674 {
675 	struct kaudit_record *ar;
676 	struct socket *so;
677 	struct inpcb *pcb;
678 	struct vnode *vp;
679 
680 	ar = currecord();
681 	if (ar == NULL)
682 		return;
683 
684 	switch (fp->f_type) {
685 	case DTYPE_VNODE:
686 	case DTYPE_FIFO:
687 		/*
688 		 * XXXAUDIT: Only possibly to record as first vnode?
689 		 */
690 		vp = fp->f_vnode;
691 		vn_lock(vp, LK_SHARED | LK_RETRY);
692 		audit_arg_vnode1(vp);
693 		VOP_UNLOCK(vp);
694 		break;
695 
696 	case DTYPE_SOCKET:
697 		so = (struct socket *)fp->f_data;
698 		if (INP_CHECK_SOCKAF(so, PF_INET)) {
699 			SOCK_LOCK(so);
700 			ar->k_ar.ar_arg_sockinfo.so_type =
701 			    so->so_type;
702 			ar->k_ar.ar_arg_sockinfo.so_domain =
703 			    INP_SOCKAF(so);
704 			ar->k_ar.ar_arg_sockinfo.so_protocol =
705 			    so->so_proto->pr_protocol;
706 			SOCK_UNLOCK(so);
707 			pcb = (struct inpcb *)so->so_pcb;
708 			INP_RLOCK(pcb);
709 			ar->k_ar.ar_arg_sockinfo.so_raddr =
710 			    pcb->inp_faddr.s_addr;
711 			ar->k_ar.ar_arg_sockinfo.so_laddr =
712 			    pcb->inp_laddr.s_addr;
713 			ar->k_ar.ar_arg_sockinfo.so_rport =
714 			    pcb->inp_fport;
715 			ar->k_ar.ar_arg_sockinfo.so_lport =
716 			    pcb->inp_lport;
717 			INP_RUNLOCK(pcb);
718 			ARG_SET_VALID(ar, ARG_SOCKINFO);
719 		}
720 		break;
721 
722 	default:
723 		/* XXXAUDIT: else? */
724 		break;
725 	}
726 }
727 
728 /*
729  * Store a path as given by the user process for auditing into the audit
730  * record stored on the user thread.  This function will allocate the memory
731  * to store the path info if not already available.  This memory will be
732  * freed when the audit record is freed.  The path is canonlicalised with
733  * respect to the thread and directory descriptor passed.
734  */
735 static void
736 audit_arg_upath(struct thread *td, int dirfd, char *upath, char **pathp)
737 {
738 
739 	if (*pathp == NULL)
740 		*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK);
741 	audit_canon_path(td, dirfd, upath, *pathp);
742 }
743 
744 void
745 audit_arg_upath1(struct thread *td, int dirfd, char *upath)
746 {
747 	struct kaudit_record *ar;
748 
749 	ar = currecord();
750 	if (ar == NULL)
751 		return;
752 
753 	audit_arg_upath(td, dirfd, upath, &ar->k_ar.ar_arg_upath1);
754 	ARG_SET_VALID(ar, ARG_UPATH1);
755 }
756 
757 void
758 audit_arg_upath2(struct thread *td, int dirfd, char *upath)
759 {
760 	struct kaudit_record *ar;
761 
762 	ar = currecord();
763 	if (ar == NULL)
764 		return;
765 
766 	audit_arg_upath(td, dirfd, upath, &ar->k_ar.ar_arg_upath2);
767 	ARG_SET_VALID(ar, ARG_UPATH2);
768 }
769 
770 static void
771 audit_arg_upath_vp(struct thread *td, struct vnode *rdir, struct vnode *cdir,
772     char *upath, char **pathp)
773 {
774 
775 	if (*pathp == NULL)
776 		*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK);
777 	audit_canon_path_vp(td, rdir, cdir, upath, *pathp);
778 }
779 
780 void
781 audit_arg_upath1_vp(struct thread *td, struct vnode *rdir, struct vnode *cdir,
782     char *upath)
783 {
784 	struct kaudit_record *ar;
785 
786 	ar = currecord();
787 	if (ar == NULL)
788 		return;
789 
790 	audit_arg_upath_vp(td, rdir, cdir, upath, &ar->k_ar.ar_arg_upath1);
791 	ARG_SET_VALID(ar, ARG_UPATH1);
792 }
793 
794 void
795 audit_arg_upath2_vp(struct thread *td, struct vnode *rdir, struct vnode *cdir,
796     char *upath)
797 {
798 	struct kaudit_record *ar;
799 
800 	ar = currecord();
801 	if (ar == NULL)
802 		return;
803 
804 	audit_arg_upath_vp(td, rdir, cdir, upath, &ar->k_ar.ar_arg_upath2);
805 	ARG_SET_VALID(ar, ARG_UPATH2);
806 }
807 
808 /*
809  * Variants on path auditing that do not canonicalise the path passed in;
810  * these are for use with filesystem-like subsystems that employ string names,
811  * but do not support a hierarchical namespace -- for example, POSIX IPC
812  * objects.  The subsystem should have performed any necessary
813  * canonicalisation required to make the paths useful to audit analysis.
814  */
815 static void
816 audit_arg_upath_canon(char *upath, char **pathp)
817 {
818 
819 	if (*pathp == NULL)
820 		*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK);
821 	(void)snprintf(*pathp, MAXPATHLEN, "%s", upath);
822 }
823 
824 void
825 audit_arg_upath1_canon(char *upath)
826 {
827 	struct kaudit_record *ar;
828 
829 	ar = currecord();
830 	if (ar == NULL)
831 		return;
832 
833 	audit_arg_upath_canon(upath, &ar->k_ar.ar_arg_upath1);
834 	ARG_SET_VALID(ar, ARG_UPATH1);
835 }
836 
837 void
838 audit_arg_upath2_canon(char *upath)
839 {
840 	struct kaudit_record *ar;
841 
842 	ar = currecord();
843 	if (ar == NULL)
844 		return;
845 
846 	audit_arg_upath_canon(upath, &ar->k_ar.ar_arg_upath2);
847 	ARG_SET_VALID(ar, ARG_UPATH2);
848 }
849 
850 /*
851  * Function to save the path and vnode attr information into the audit
852  * record.
853  *
854  * It is assumed that the caller will hold any vnode locks necessary to
855  * perform a VOP_GETATTR() on the passed vnode.
856  *
857  * XXX: The attr code is very similar to vfs_vnops.c:vn_stat(), but always
858  * provides access to the generation number as we need that to construct the
859  * BSM file ID.
860  *
861  * XXX: We should accept the process argument from the caller, since it's
862  * very likely they already have a reference.
863  *
864  * XXX: Error handling in this function is poor.
865  *
866  * XXXAUDIT: Possibly KASSERT the path pointer is NULL?
867  */
868 static int
869 audit_arg_vnode(struct vnode *vp, struct vnode_au_info *vnp)
870 {
871 	struct vattr vattr;
872 	int error;
873 
874 	ASSERT_VOP_LOCKED(vp, "audit_arg_vnode");
875 
876 	error = VOP_GETATTR(vp, &vattr, curthread->td_ucred);
877 	if (error) {
878 		/* XXX: How to handle this case? */
879 		return (error);
880 	}
881 
882 	vnp->vn_mode = vattr.va_mode;
883 	vnp->vn_uid = vattr.va_uid;
884 	vnp->vn_gid = vattr.va_gid;
885 	vnp->vn_dev = vattr.va_rdev;
886 	vnp->vn_fsid = vattr.va_fsid;
887 	vnp->vn_fileid = vattr.va_fileid;
888 	vnp->vn_gen = vattr.va_gen;
889 	return (0);
890 }
891 
892 void
893 audit_arg_vnode1(struct vnode *vp)
894 {
895 	struct kaudit_record *ar;
896 	int error;
897 
898 	ar = currecord();
899 	if (ar == NULL)
900 		return;
901 
902 	ARG_CLEAR_VALID(ar, ARG_VNODE1);
903 	error = audit_arg_vnode(vp, &ar->k_ar.ar_arg_vnode1);
904 	if (error == 0)
905 		ARG_SET_VALID(ar, ARG_VNODE1);
906 }
907 
908 void
909 audit_arg_vnode2(struct vnode *vp)
910 {
911 	struct kaudit_record *ar;
912 	int error;
913 
914 	ar = currecord();
915 	if (ar == NULL)
916 		return;
917 
918 	ARG_CLEAR_VALID(ar, ARG_VNODE2);
919 	error = audit_arg_vnode(vp, &ar->k_ar.ar_arg_vnode2);
920 	if (error == 0)
921 		ARG_SET_VALID(ar, ARG_VNODE2);
922 }
923 
924 /*
925  * Audit the argument strings passed to exec.
926  */
927 void
928 audit_arg_argv(char *argv, int argc, int length)
929 {
930 	struct kaudit_record *ar;
931 
932 	if (audit_argv == 0)
933 		return;
934 
935 	ar = currecord();
936 	if (ar == NULL)
937 		return;
938 
939 	ar->k_ar.ar_arg_argv = malloc(length, M_AUDITTEXT, M_WAITOK);
940 	bcopy(argv, ar->k_ar.ar_arg_argv, length);
941 	ar->k_ar.ar_arg_argc = argc;
942 	ARG_SET_VALID(ar, ARG_ARGV);
943 }
944 
945 /*
946  * Audit the environment strings passed to exec.
947  */
948 void
949 audit_arg_envv(char *envv, int envc, int length)
950 {
951 	struct kaudit_record *ar;
952 
953 	if (audit_arge == 0)
954 		return;
955 
956 	ar = currecord();
957 	if (ar == NULL)
958 		return;
959 
960 	ar->k_ar.ar_arg_envv = malloc(length, M_AUDITTEXT, M_WAITOK);
961 	bcopy(envv, ar->k_ar.ar_arg_envv, length);
962 	ar->k_ar.ar_arg_envc = envc;
963 	ARG_SET_VALID(ar, ARG_ENVV);
964 }
965 
966 void
967 audit_arg_rights(cap_rights_t *rightsp)
968 {
969 	struct kaudit_record *ar;
970 
971 	ar = currecord();
972 	if (ar == NULL)
973 		return;
974 
975 	ar->k_ar.ar_arg_rights = *rightsp;
976 	ARG_SET_VALID(ar, ARG_RIGHTS);
977 }
978 
979 void
980 audit_arg_fcntl_rights(uint32_t fcntlrights)
981 {
982 	struct kaudit_record *ar;
983 
984 	ar = currecord();
985 	if (ar == NULL)
986 		return;
987 
988 	ar->k_ar.ar_arg_fcntl_rights = fcntlrights;
989 	ARG_SET_VALID(ar, ARG_FCNTL_RIGHTS);
990 }
991 
992 /*
993  * The close() system call uses it's own audit call to capture the path/vnode
994  * information because those pieces are not easily obtained within the system
995  * call itself.
996  */
997 void
998 audit_sysclose(struct thread *td, int fd)
999 {
1000 	cap_rights_t rights;
1001 	struct kaudit_record *ar;
1002 	struct vnode *vp;
1003 	struct file *fp;
1004 
1005 	KASSERT(td != NULL, ("audit_sysclose: td == NULL"));
1006 
1007 	ar = currecord();
1008 	if (ar == NULL)
1009 		return;
1010 
1011 	audit_arg_fd(fd);
1012 
1013 	if (getvnode(td, fd, cap_rights_init(&rights), &fp) != 0)
1014 		return;
1015 
1016 	vp = fp->f_vnode;
1017 	vn_lock(vp, LK_SHARED | LK_RETRY);
1018 	audit_arg_vnode1(vp);
1019 	VOP_UNLOCK(vp);
1020 	fdrop(fp, td);
1021 }
1022