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