audit_arg.c revision 195926
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: head/sys/security/audit/audit_arg.c 195926 2009-07-28 21:52:24Z rwatson $");
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,
266	    ("audit_arg_groupset: gidset_size > NGROUPS"));
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, 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		audit_arg_upath(td, ((struct sockaddr_un *)sa)->sun_path,
467		    ARG_UPATH1);
468		ARG_SET_VALID(ar, ARG_SADDRUNIX);
469		break;
470	/* XXXAUDIT: default:? */
471	}
472}
473
474void
475audit_arg_auid(uid_t auid)
476{
477	struct kaudit_record *ar;
478
479	ar = currecord();
480	if (ar == NULL)
481		return;
482
483	ar->k_ar.ar_arg_auid = auid;
484	ARG_SET_VALID(ar, ARG_AUID);
485}
486
487void
488audit_arg_auditinfo(struct auditinfo *au_info)
489{
490	struct kaudit_record *ar;
491
492	ar = currecord();
493	if (ar == NULL)
494		return;
495
496	ar->k_ar.ar_arg_auid = au_info->ai_auid;
497	ar->k_ar.ar_arg_asid = au_info->ai_asid;
498	ar->k_ar.ar_arg_amask.am_success = au_info->ai_mask.am_success;
499	ar->k_ar.ar_arg_amask.am_failure = au_info->ai_mask.am_failure;
500	ar->k_ar.ar_arg_termid.port = au_info->ai_termid.port;
501	ar->k_ar.ar_arg_termid.machine = au_info->ai_termid.machine;
502	ARG_SET_VALID(ar, ARG_AUID | ARG_ASID | ARG_AMASK | ARG_TERMID);
503}
504
505void
506audit_arg_auditinfo_addr(struct auditinfo_addr *au_info)
507{
508	struct kaudit_record *ar;
509
510	ar = currecord();
511	if (ar == NULL)
512		return;
513
514	ar->k_ar.ar_arg_auid = au_info->ai_auid;
515	ar->k_ar.ar_arg_asid = au_info->ai_asid;
516	ar->k_ar.ar_arg_amask.am_success = au_info->ai_mask.am_success;
517	ar->k_ar.ar_arg_amask.am_failure = au_info->ai_mask.am_failure;
518	ar->k_ar.ar_arg_termid_addr.at_type = au_info->ai_termid.at_type;
519	ar->k_ar.ar_arg_termid_addr.at_port = au_info->ai_termid.at_port;
520	ar->k_ar.ar_arg_termid_addr.at_addr[0] = au_info->ai_termid.at_addr[0];
521	ar->k_ar.ar_arg_termid_addr.at_addr[1] = au_info->ai_termid.at_addr[1];
522	ar->k_ar.ar_arg_termid_addr.at_addr[2] = au_info->ai_termid.at_addr[2];
523	ar->k_ar.ar_arg_termid_addr.at_addr[3] = au_info->ai_termid.at_addr[3];
524	ARG_SET_VALID(ar, ARG_AUID | ARG_ASID | ARG_AMASK | ARG_TERMID_ADDR);
525}
526
527void
528audit_arg_text(char *text)
529{
530	struct kaudit_record *ar;
531
532	KASSERT(text != NULL, ("audit_arg_text: text == NULL"));
533
534	ar = currecord();
535	if (ar == NULL)
536		return;
537
538	/* Invalidate the text string */
539	ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_TEXT);
540
541	if (ar->k_ar.ar_arg_text == NULL)
542		ar->k_ar.ar_arg_text = malloc(MAXPATHLEN, M_AUDITTEXT,
543		    M_WAITOK);
544
545	strncpy(ar->k_ar.ar_arg_text, text, MAXPATHLEN);
546	ARG_SET_VALID(ar, ARG_TEXT);
547}
548
549void
550audit_arg_cmd(int cmd)
551{
552	struct kaudit_record *ar;
553
554	ar = currecord();
555	if (ar == NULL)
556		return;
557
558	ar->k_ar.ar_arg_cmd = cmd;
559	ARG_SET_VALID(ar, ARG_CMD);
560}
561
562void
563audit_arg_svipc_cmd(int cmd)
564{
565	struct kaudit_record *ar;
566
567	ar = currecord();
568	if (ar == NULL)
569		return;
570
571	ar->k_ar.ar_arg_svipc_cmd = cmd;
572	ARG_SET_VALID(ar, ARG_SVIPC_CMD);
573}
574
575void
576audit_arg_svipc_perm(struct ipc_perm *perm)
577{
578	struct kaudit_record *ar;
579
580	ar = currecord();
581	if (ar == NULL)
582		return;
583
584	bcopy(perm, &ar->k_ar.ar_arg_svipc_perm,
585	    sizeof(ar->k_ar.ar_arg_svipc_perm));
586	ARG_SET_VALID(ar, ARG_SVIPC_PERM);
587}
588
589void
590audit_arg_svipc_id(int id)
591{
592	struct kaudit_record *ar;
593
594	ar = currecord();
595	if (ar == NULL)
596		return;
597
598	ar->k_ar.ar_arg_svipc_id = id;
599	ARG_SET_VALID(ar, ARG_SVIPC_ID);
600}
601
602void
603audit_arg_svipc_addr(void * addr)
604{
605	struct kaudit_record *ar;
606
607	ar = currecord();
608	if (ar == NULL)
609		return;
610
611	ar->k_ar.ar_arg_svipc_addr = addr;
612	ARG_SET_VALID(ar, ARG_SVIPC_ADDR);
613}
614
615void
616audit_arg_posix_ipc_perm(uid_t uid, gid_t gid, mode_t mode)
617{
618	struct kaudit_record *ar;
619
620	ar = currecord();
621	if (ar == NULL)
622		return;
623
624	ar->k_ar.ar_arg_pipc_perm.pipc_uid = uid;
625	ar->k_ar.ar_arg_pipc_perm.pipc_gid = gid;
626	ar->k_ar.ar_arg_pipc_perm.pipc_mode = mode;
627	ARG_SET_VALID(ar, ARG_POSIX_IPC_PERM);
628}
629
630void
631audit_arg_auditon(union auditon_udata *udata)
632{
633	struct kaudit_record *ar;
634
635	ar = currecord();
636	if (ar == NULL)
637		return;
638
639	bcopy((void *)udata, &ar->k_ar.ar_arg_auditon,
640	    sizeof(ar->k_ar.ar_arg_auditon));
641	ARG_SET_VALID(ar, ARG_AUDITON);
642}
643
644/*
645 * Audit information about a file, either the file's vnode info, or its
646 * socket address info.
647 */
648void
649audit_arg_file(struct proc *p, struct file *fp)
650{
651	struct kaudit_record *ar;
652	struct socket *so;
653	struct inpcb *pcb;
654	struct vnode *vp;
655	int vfslocked;
656
657	ar = currecord();
658	if (ar == NULL)
659		return;
660
661	switch (fp->f_type) {
662	case DTYPE_VNODE:
663	case DTYPE_FIFO:
664		/*
665		 * XXXAUDIT: Only possibly to record as first vnode?
666		 */
667		vp = fp->f_vnode;
668		vfslocked = VFS_LOCK_GIANT(vp->v_mount);
669		vn_lock(vp, LK_SHARED | LK_RETRY);
670		audit_arg_vnode1(vp);
671		VOP_UNLOCK(vp, 0);
672		VFS_UNLOCK_GIANT(vfslocked);
673		break;
674
675	case DTYPE_SOCKET:
676		so = (struct socket *)fp->f_data;
677		if (INP_CHECK_SOCKAF(so, PF_INET)) {
678			SOCK_LOCK(so);
679			ar->k_ar.ar_arg_sockinfo.so_type =
680			    so->so_type;
681			ar->k_ar.ar_arg_sockinfo.so_domain =
682			    INP_SOCKAF(so);
683			ar->k_ar.ar_arg_sockinfo.so_protocol =
684			    so->so_proto->pr_protocol;
685			SOCK_UNLOCK(so);
686			pcb = (struct inpcb *)so->so_pcb;
687			INP_RLOCK(pcb);
688			ar->k_ar.ar_arg_sockinfo.so_raddr =
689			    pcb->inp_faddr.s_addr;
690			ar->k_ar.ar_arg_sockinfo.so_laddr =
691			    pcb->inp_laddr.s_addr;
692			ar->k_ar.ar_arg_sockinfo.so_rport =
693			    pcb->inp_fport;
694			ar->k_ar.ar_arg_sockinfo.so_lport =
695			    pcb->inp_lport;
696			INP_RUNLOCK(pcb);
697			ARG_SET_VALID(ar, ARG_SOCKINFO);
698		}
699		break;
700
701	default:
702		/* XXXAUDIT: else? */
703		break;
704	}
705}
706
707/*
708 * Store a path as given by the user process for auditing into the audit
709 * record stored on the user thread.  This function will allocate the memory
710 * to store the path info if not already available.  This memory will be
711 * freed when the audit record is freed.
712 *
713 * XXXAUDIT: Possibly assert that the memory isn't already allocated?
714 */
715void
716audit_arg_upath(struct thread *td, char *upath, u_int64_t flag)
717{
718	struct kaudit_record *ar;
719	char **pathp;
720
721	KASSERT(td != NULL, ("audit_arg_upath: td == NULL"));
722	KASSERT(upath != NULL, ("audit_arg_upath: upath == NULL"));
723
724	ar = currecord();
725	if (ar == NULL)
726		return;
727
728	KASSERT((flag == ARG_UPATH1) || (flag == ARG_UPATH2),
729	    ("audit_arg_upath: flag %llu", (unsigned long long)flag));
730	KASSERT((flag != ARG_UPATH1) || (flag != ARG_UPATH2),
731	    ("audit_arg_upath: flag %llu", (unsigned long long)flag));
732
733	if (flag == ARG_UPATH1)
734		pathp = &ar->k_ar.ar_arg_upath1;
735	else
736		pathp = &ar->k_ar.ar_arg_upath2;
737
738	if (*pathp == NULL)
739		*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK);
740
741	audit_canon_path(td, upath, *pathp);
742
743	ARG_SET_VALID(ar, flag);
744}
745
746/*
747 * Function to save the path and vnode attr information into the audit
748 * record.
749 *
750 * It is assumed that the caller will hold any vnode locks necessary to
751 * perform a VOP_GETATTR() on the passed vnode.
752 *
753 * XXX: The attr code is very similar to vfs_vnops.c:vn_stat(), but always
754 * provides access to the generation number as we need that to construct the
755 * BSM file ID.
756 *
757 * XXX: We should accept the process argument from the caller, since it's
758 * very likely they already have a reference.
759 *
760 * XXX: Error handling in this function is poor.
761 *
762 * XXXAUDIT: Possibly KASSERT the path pointer is NULL?
763 */
764static int
765audit_arg_vnode(struct vnode *vp, struct vnode_au_info *vnp)
766{
767	struct vattr vattr;
768	int error;
769
770	/*
771	 * Assume that if the caller is calling audit_arg_vnode() on a
772	 * non-MPSAFE vnode, then it will have acquired Giant.
773	 */
774	VFS_ASSERT_GIANT(vp->v_mount);
775	ASSERT_VOP_LOCKED(vp, "audit_arg_vnode");
776
777	error = VOP_GETATTR(vp, &vattr, curthread->td_ucred);
778	if (error) {
779		/* XXX: How to handle this case? */
780		return (error);
781	}
782
783	vnp->vn_mode = vattr.va_mode;
784	vnp->vn_uid = vattr.va_uid;
785	vnp->vn_gid = vattr.va_gid;
786	vnp->vn_dev = vattr.va_rdev;
787	vnp->vn_fsid = vattr.va_fsid;
788	vnp->vn_fileid = vattr.va_fileid;
789	vnp->vn_gen = vattr.va_gen;
790	return (0);
791}
792
793void
794audit_arg_vnode1(struct vnode *vp)
795{
796	struct kaudit_record *ar;
797	int error;
798
799	ar = currecord();
800	if (ar == NULL)
801		return;
802
803	ARG_CLEAR_VALID(ar, ARG_VNODE1);
804	error = audit_arg_vnode(vp, &ar->k_ar.ar_arg_vnode1);
805	if (error == 0)
806		ARG_SET_VALID(ar, ARG_VNODE1);
807}
808
809void
810audit_arg_vnode2(struct vnode *vp)
811{
812	struct kaudit_record *ar;
813	int error;
814
815	ar = currecord();
816	if (ar == NULL)
817		return;
818
819	ARG_CLEAR_VALID(ar, ARG_VNODE2);
820	error = audit_arg_vnode(vp, &ar->k_ar.ar_arg_vnode2);
821	if (error == 0)
822		ARG_SET_VALID(ar, ARG_VNODE2);
823}
824
825/*
826 * Audit the argument strings passed to exec.
827 */
828void
829audit_arg_argv(char *argv, int argc, int length)
830{
831	struct kaudit_record *ar;
832
833	if (audit_argv == 0)
834		return;
835
836	ar = currecord();
837	if (ar == NULL)
838		return;
839
840	ar->k_ar.ar_arg_argv = malloc(length, M_AUDITTEXT, M_WAITOK);
841	bcopy(argv, ar->k_ar.ar_arg_argv, length);
842	ar->k_ar.ar_arg_argc = argc;
843	ARG_SET_VALID(ar, ARG_ARGV);
844}
845
846/*
847 * Audit the environment strings passed to exec.
848 */
849void
850audit_arg_envv(char *envv, int envc, int length)
851{
852	struct kaudit_record *ar;
853
854	if (audit_arge == 0)
855		return;
856
857	ar = currecord();
858	if (ar == NULL)
859		return;
860
861	ar->k_ar.ar_arg_envv = malloc(length, M_AUDITTEXT, M_WAITOK);
862	bcopy(envv, ar->k_ar.ar_arg_envv, length);
863	ar->k_ar.ar_arg_envc = envc;
864	ARG_SET_VALID(ar, ARG_ENVV);
865}
866
867/*
868 * The close() system call uses it's own audit call to capture the path/vnode
869 * information because those pieces are not easily obtained within the system
870 * call itself.
871 */
872void
873audit_sysclose(struct thread *td, int fd)
874{
875	struct kaudit_record *ar;
876	struct vnode *vp;
877	struct file *fp;
878	int vfslocked;
879
880	KASSERT(td != NULL, ("audit_sysclose: td == NULL"));
881
882	ar = currecord();
883	if (ar == NULL)
884		return;
885
886	audit_arg_fd(fd);
887
888	if (getvnode(td->td_proc->p_fd, fd, &fp) != 0)
889		return;
890
891	vp = fp->f_vnode;
892	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
893	vn_lock(vp, LK_SHARED | LK_RETRY);
894	audit_arg_vnode1(vp);
895	VOP_UNLOCK(vp, 0);
896	VFS_UNLOCK_GIANT(vfslocked);
897	fdrop(fp, td);
898}
899