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