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