xref: /freebsd/sys/security/audit/audit_bsm_klib.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
151369649SPedro F. Giffuni /*-
251369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni  *
4f4f93a63SRobert Watson  * Copyright (c) 1999-2009 Apple Inc.
5b7830259SRobert Watson  * Copyright (c) 2005, 2016-2017 Robert N. M. Watson
6718c8510SRobert Watson  * All rights reserved.
7718c8510SRobert Watson  *
8759c8caaSRobert Watson  * Portions of this software were developed by BAE Systems, the University of
9759c8caaSRobert Watson  * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL
10759c8caaSRobert Watson  * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent
11759c8caaSRobert Watson  * Computing (TC) research program.
12759c8caaSRobert Watson  *
13718c8510SRobert Watson  * Redistribution and use in source and binary forms, with or without
14718c8510SRobert Watson  * modification, are permitted provided that the following conditions
15718c8510SRobert Watson  * are met:
16718c8510SRobert Watson  * 1.  Redistributions of source code must retain the above copyright
17718c8510SRobert Watson  *     notice, this list of conditions and the following disclaimer.
18718c8510SRobert Watson  * 2.  Redistributions in binary form must reproduce the above copyright
19718c8510SRobert Watson  *     notice, this list of conditions and the following disclaimer in the
20718c8510SRobert Watson  *     documentation and/or other materials provided with the distribution.
21bc9a43d6SRobert Watson  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
22718c8510SRobert Watson  *     its contributors may be used to endorse or promote products derived
23718c8510SRobert Watson  *     from this software without specific prior written permission.
24718c8510SRobert Watson  *
25718c8510SRobert Watson  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
26718c8510SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27718c8510SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28718c8510SRobert Watson  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
29718c8510SRobert Watson  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30718c8510SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31718c8510SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32718c8510SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33718c8510SRobert Watson  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
34718c8510SRobert Watson  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35718c8510SRobert Watson  * POSSIBILITY OF SUCH DAMAGE.
36718c8510SRobert Watson  */
37718c8510SRobert Watson 
38718c8510SRobert Watson #include <sys/param.h>
39f131759fSMateusz Guzik #include <sys/capsicum.h>
40718c8510SRobert Watson #include <sys/fcntl.h>
41718c8510SRobert Watson #include <sys/filedesc.h>
42718c8510SRobert Watson #include <sys/libkern.h>
43718c8510SRobert Watson #include <sys/malloc.h>
44718c8510SRobert Watson #include <sys/mount.h>
45718c8510SRobert Watson #include <sys/proc.h>
46c211285fSRobert Watson #include <sys/rwlock.h>
47718c8510SRobert Watson #include <sys/sem.h>
48dfc714fbSChristian S.J. Peron #include <sys/sbuf.h>
49759c8caaSRobert Watson #include <sys/sx.h>
50718c8510SRobert Watson #include <sys/syscall.h>
51718c8510SRobert Watson #include <sys/sysctl.h>
52718c8510SRobert Watson #include <sys/sysent.h>
53718c8510SRobert Watson #include <sys/vnode.h>
54718c8510SRobert Watson 
55718c8510SRobert Watson #include <bsm/audit.h>
56718c8510SRobert Watson #include <bsm/audit_kevents.h>
57718c8510SRobert Watson #include <security/audit/audit.h>
58718c8510SRobert Watson #include <security/audit/audit_private.h>
59718c8510SRobert Watson 
60e4b4bbb6SRobert Watson struct aue_open_event {
61e4b4bbb6SRobert Watson 	int		aoe_flags;
62e4b4bbb6SRobert Watson 	au_event_t	aoe_event;
63e4b4bbb6SRobert Watson };
64e4b4bbb6SRobert Watson 
65e4b4bbb6SRobert Watson static const struct aue_open_event aue_open[] = {
66e4b4bbb6SRobert Watson 	{ O_RDONLY,					AUE_OPEN_R },
67e4b4bbb6SRobert Watson 	{ (O_RDONLY | O_CREAT),				AUE_OPEN_RC },
68e4b4bbb6SRobert Watson 	{ (O_RDONLY | O_CREAT | O_TRUNC),		AUE_OPEN_RTC },
69e4b4bbb6SRobert Watson 	{ (O_RDONLY | O_TRUNC),				AUE_OPEN_RT },
70e4b4bbb6SRobert Watson 	{ O_RDWR,					AUE_OPEN_RW },
71e4b4bbb6SRobert Watson 	{ (O_RDWR | O_CREAT),				AUE_OPEN_RWC },
72e4b4bbb6SRobert Watson 	{ (O_RDWR | O_CREAT | O_TRUNC),			AUE_OPEN_RWTC },
73e4b4bbb6SRobert Watson 	{ (O_RDWR | O_TRUNC),				AUE_OPEN_RWT },
74e4b4bbb6SRobert Watson 	{ O_WRONLY,					AUE_OPEN_W },
75e4b4bbb6SRobert Watson 	{ (O_WRONLY | O_CREAT),				AUE_OPEN_WC },
76e4b4bbb6SRobert Watson 	{ (O_WRONLY | O_CREAT | O_TRUNC),		AUE_OPEN_WTC },
77e4b4bbb6SRobert Watson 	{ (O_WRONLY | O_TRUNC),				AUE_OPEN_WT },
78e4b4bbb6SRobert Watson };
79e4b4bbb6SRobert Watson 
80e4b4bbb6SRobert Watson static const struct aue_open_event aue_openat[] = {
81e4b4bbb6SRobert Watson 	{ O_RDONLY,					AUE_OPENAT_R },
82e4b4bbb6SRobert Watson 	{ (O_RDONLY | O_CREAT),				AUE_OPENAT_RC },
83e4b4bbb6SRobert Watson 	{ (O_RDONLY | O_CREAT | O_TRUNC),		AUE_OPENAT_RTC },
84e4b4bbb6SRobert Watson 	{ (O_RDONLY | O_TRUNC),				AUE_OPENAT_RT },
85e4b4bbb6SRobert Watson 	{ O_RDWR,					AUE_OPENAT_RW },
86e4b4bbb6SRobert Watson 	{ (O_RDWR | O_CREAT),				AUE_OPENAT_RWC },
87e4b4bbb6SRobert Watson 	{ (O_RDWR | O_CREAT | O_TRUNC),			AUE_OPENAT_RWTC },
88e4b4bbb6SRobert Watson 	{ (O_RDWR | O_TRUNC),				AUE_OPENAT_RWT },
89e4b4bbb6SRobert Watson 	{ O_WRONLY,					AUE_OPENAT_W },
90e4b4bbb6SRobert Watson 	{ (O_WRONLY | O_CREAT),				AUE_OPENAT_WC },
91e4b4bbb6SRobert Watson 	{ (O_WRONLY | O_CREAT | O_TRUNC),		AUE_OPENAT_WTC },
92e4b4bbb6SRobert Watson 	{ (O_WRONLY | O_TRUNC),				AUE_OPENAT_WT },
93e4b4bbb6SRobert Watson };
94e4b4bbb6SRobert Watson 
95b7830259SRobert Watson static const int aue_msgsys[] = {
96b7830259SRobert Watson 	/* 0 */ AUE_MSGCTL,
97b7830259SRobert Watson 	/* 1 */ AUE_MSGGET,
98b7830259SRobert Watson 	/* 2 */ AUE_MSGSND,
99b7830259SRobert Watson 	/* 3 */ AUE_MSGRCV,
100b7830259SRobert Watson };
101b7830259SRobert Watson static const int aue_msgsys_count = sizeof(aue_msgsys) / sizeof(int);
102b7830259SRobert Watson 
103b7830259SRobert Watson static const int aue_semsys[] = {
104b7830259SRobert Watson 	/* 0 */ AUE_SEMCTL,
105b7830259SRobert Watson 	/* 1 */ AUE_SEMGET,
106b7830259SRobert Watson 	/* 2 */ AUE_SEMOP,
107b7830259SRobert Watson };
108b7830259SRobert Watson static const int aue_semsys_count = sizeof(aue_semsys) / sizeof(int);
109b7830259SRobert Watson 
110b7830259SRobert Watson static const int aue_shmsys[] = {
111b7830259SRobert Watson 	/* 0 */ AUE_SHMAT,
112b7830259SRobert Watson 	/* 1 */ AUE_SHMDT,
113b7830259SRobert Watson 	/* 2 */ AUE_SHMGET,
114b7830259SRobert Watson 	/* 3 */ AUE_SHMCTL,
115b7830259SRobert Watson };
116b7830259SRobert Watson static const int aue_shmsys_count = sizeof(aue_shmsys) / sizeof(int);
117b7830259SRobert Watson 
118718c8510SRobert Watson /*
119b521cf27SAlan Somers  * Check whether an event is auditable by comparing the mask of classes this
120718c8510SRobert Watson  * event is part of against the given mask.
121718c8510SRobert Watson  */
122718c8510SRobert Watson int
au_preselect(au_event_t event,au_class_t class,au_mask_t * mask_p,int sorf)123e257c20eSRobert Watson au_preselect(au_event_t event, au_class_t class, au_mask_t *mask_p, int sorf)
124718c8510SRobert Watson {
125718c8510SRobert Watson 	au_class_t effmask = 0;
126718c8510SRobert Watson 
127718c8510SRobert Watson 	if (mask_p == NULL)
128718c8510SRobert Watson 		return (-1);
129718c8510SRobert Watson 
130718c8510SRobert Watson 	/*
131718c8510SRobert Watson 	 * Perform the actual check of the masks against the event.
132718c8510SRobert Watson 	 */
133718c8510SRobert Watson 	if (sorf & AU_PRS_SUCCESS)
134e257c20eSRobert Watson 		effmask |= (mask_p->am_success & class);
135718c8510SRobert Watson 
136718c8510SRobert Watson 	if (sorf & AU_PRS_FAILURE)
137e257c20eSRobert Watson 		effmask |= (mask_p->am_failure & class);
138718c8510SRobert Watson 
139718c8510SRobert Watson 	if (effmask)
140718c8510SRobert Watson 		return (1);
141718c8510SRobert Watson 	else
142718c8510SRobert Watson 		return (0);
143718c8510SRobert Watson }
144718c8510SRobert Watson 
145718c8510SRobert Watson /*
146871499feSRobert Watson  * Convert sysctl names and present arguments to events.
147718c8510SRobert Watson  */
148718c8510SRobert Watson au_event_t
audit_ctlname_to_sysctlevent(int name[],uint64_t valid_arg)1496cc18991SRobert Watson audit_ctlname_to_sysctlevent(int name[], uint64_t valid_arg)
150718c8510SRobert Watson {
151718c8510SRobert Watson 
152718c8510SRobert Watson 	/* can't parse it - so return the worst case */
153871499feSRobert Watson 	if ((valid_arg & (ARG_CTLNAME | ARG_LEN)) != (ARG_CTLNAME | ARG_LEN))
154718c8510SRobert Watson 		return (AUE_SYSCTL);
155718c8510SRobert Watson 
156718c8510SRobert Watson 	switch (name[0]) {
157718c8510SRobert Watson 	/* non-admin "lookups" treat them special */
158718c8510SRobert Watson 	case KERN_OSTYPE:
159718c8510SRobert Watson 	case KERN_OSRELEASE:
160718c8510SRobert Watson 	case KERN_OSREV:
161718c8510SRobert Watson 	case KERN_VERSION:
162718c8510SRobert Watson 	case KERN_ARGMAX:
163718c8510SRobert Watson 	case KERN_CLOCKRATE:
164718c8510SRobert Watson 	case KERN_BOOTTIME:
165718c8510SRobert Watson 	case KERN_POSIX1:
166718c8510SRobert Watson 	case KERN_NGROUPS:
167718c8510SRobert Watson 	case KERN_JOB_CONTROL:
168718c8510SRobert Watson 	case KERN_SAVED_IDS:
169718c8510SRobert Watson 	case KERN_OSRELDATE:
170718c8510SRobert Watson 	case KERN_DUMMY:
171718c8510SRobert Watson 		return (AUE_SYSCTL_NONADMIN);
172718c8510SRobert Watson 
173718c8510SRobert Watson 	/* only treat the changeable controls as admin */
174718c8510SRobert Watson 	case KERN_MAXVNODES:
175718c8510SRobert Watson 	case KERN_MAXPROC:
176718c8510SRobert Watson 	case KERN_MAXFILES:
177718c8510SRobert Watson 	case KERN_MAXPROCPERUID:
178718c8510SRobert Watson 	case KERN_MAXFILESPERPROC:
179718c8510SRobert Watson 	case KERN_HOSTID:
180718c8510SRobert Watson 	case KERN_SECURELVL:
181718c8510SRobert Watson 	case KERN_HOSTNAME:
182718c8510SRobert Watson 	case KERN_PROC:
183718c8510SRobert Watson 	case KERN_FILE:
184718c8510SRobert Watson 	case KERN_PROF:
185718c8510SRobert Watson 	case KERN_NISDOMAINNAME:
186718c8510SRobert Watson 	case KERN_UPDATEINTERVAL:
187718c8510SRobert Watson 	case KERN_NTP_PLL:
188718c8510SRobert Watson 	case KERN_BOOTFILE:
189718c8510SRobert Watson 	case KERN_DUMPDEV:
190718c8510SRobert Watson 	case KERN_IPC:
191718c8510SRobert Watson 	case KERN_PS_STRINGS:
192718c8510SRobert Watson 	case KERN_USRSTACK:
193718c8510SRobert Watson 	case KERN_LOGSIGEXIT:
194718c8510SRobert Watson 	case KERN_IOV_MAX:
195718c8510SRobert Watson 		return ((valid_arg & ARG_VALUE) ?
196718c8510SRobert Watson 		    AUE_SYSCTL : AUE_SYSCTL_NONADMIN);
197718c8510SRobert Watson 
198718c8510SRobert Watson 	default:
199718c8510SRobert Watson 		return (AUE_SYSCTL);
200718c8510SRobert Watson 	}
201718c8510SRobert Watson 	/* NOTREACHED */
202718c8510SRobert Watson }
203718c8510SRobert Watson 
204718c8510SRobert Watson /*
205718c8510SRobert Watson  * Convert an open flags specifier into a specific type of open event for
206718c8510SRobert Watson  * auditing purposes.
207718c8510SRobert Watson  */
208718c8510SRobert Watson au_event_t
audit_flags_and_error_to_openevent(int oflags,int error)2096cc18991SRobert Watson audit_flags_and_error_to_openevent(int oflags, int error)
210871499feSRobert Watson {
211e4b4bbb6SRobert Watson 	int i;
212718c8510SRobert Watson 
213871499feSRobert Watson 	/*
214871499feSRobert Watson 	 * Need to check only those flags we care about.
215871499feSRobert Watson 	 */
216718c8510SRobert Watson 	oflags = oflags & (O_RDONLY | O_CREAT | O_TRUNC | O_RDWR | O_WRONLY);
2178dfea464SPedro F. Giffuni 	for (i = 0; i < nitems(aue_open); i++) {
218e4b4bbb6SRobert Watson 		if (aue_open[i].aoe_flags == oflags)
219e4b4bbb6SRobert Watson 			return (aue_open[i].aoe_event);
220e4b4bbb6SRobert Watson 	}
221e4b4bbb6SRobert Watson 	return (AUE_OPEN);
222718c8510SRobert Watson }
223718c8510SRobert Watson 
224e4b4bbb6SRobert Watson au_event_t
audit_flags_and_error_to_openatevent(int oflags,int error)225e4b4bbb6SRobert Watson audit_flags_and_error_to_openatevent(int oflags, int error)
226e4b4bbb6SRobert Watson {
227e4b4bbb6SRobert Watson 	int i;
228e4b4bbb6SRobert Watson 
229718c8510SRobert Watson 	/*
230e4b4bbb6SRobert Watson 	 * Need to check only those flags we care about.
231718c8510SRobert Watson 	 */
232e4b4bbb6SRobert Watson 	oflags = oflags & (O_RDONLY | O_CREAT | O_TRUNC | O_RDWR | O_WRONLY);
2338dfea464SPedro F. Giffuni 	for (i = 0; i < nitems(aue_openat); i++) {
234e4b4bbb6SRobert Watson 		if (aue_openat[i].aoe_flags == oflags)
235e4b4bbb6SRobert Watson 			return (aue_openat[i].aoe_event);
236718c8510SRobert Watson 	}
237e4b4bbb6SRobert Watson 	return (AUE_OPENAT);
238718c8510SRobert Watson }
239718c8510SRobert Watson 
240718c8510SRobert Watson /*
241718c8510SRobert Watson  * Convert a MSGCTL command to a specific event.
242718c8510SRobert Watson  */
243f4f93a63SRobert Watson au_event_t
audit_msgctl_to_event(int cmd)244303d3f35SRobert Watson audit_msgctl_to_event(int cmd)
245718c8510SRobert Watson {
246718c8510SRobert Watson 
247718c8510SRobert Watson 	switch (cmd) {
248718c8510SRobert Watson 	case IPC_RMID:
249718c8510SRobert Watson 		return (AUE_MSGCTL_RMID);
250718c8510SRobert Watson 
251718c8510SRobert Watson 	case IPC_SET:
252718c8510SRobert Watson 		return (AUE_MSGCTL_SET);
253718c8510SRobert Watson 
254718c8510SRobert Watson 	case IPC_STAT:
255718c8510SRobert Watson 		return (AUE_MSGCTL_STAT);
256718c8510SRobert Watson 
257718c8510SRobert Watson 	default:
258d8c0f4dcSRobert Watson 		/* We will audit a bad command. */
259718c8510SRobert Watson 		return (AUE_MSGCTL);
260718c8510SRobert Watson 	}
261718c8510SRobert Watson }
262718c8510SRobert Watson 
263718c8510SRobert Watson /*
264718c8510SRobert Watson  * Convert a SEMCTL command to a specific event.
265718c8510SRobert Watson  */
266f4f93a63SRobert Watson au_event_t
audit_semctl_to_event(int cmd)267303d3f35SRobert Watson audit_semctl_to_event(int cmd)
268718c8510SRobert Watson {
269718c8510SRobert Watson 
270718c8510SRobert Watson 	switch (cmd) {
271718c8510SRobert Watson 	case GETALL:
272718c8510SRobert Watson 		return (AUE_SEMCTL_GETALL);
273718c8510SRobert Watson 
274718c8510SRobert Watson 	case GETNCNT:
275718c8510SRobert Watson 		return (AUE_SEMCTL_GETNCNT);
276718c8510SRobert Watson 
277718c8510SRobert Watson 	case GETPID:
278718c8510SRobert Watson 		return (AUE_SEMCTL_GETPID);
279718c8510SRobert Watson 
280718c8510SRobert Watson 	case GETVAL:
281718c8510SRobert Watson 		return (AUE_SEMCTL_GETVAL);
282718c8510SRobert Watson 
283718c8510SRobert Watson 	case GETZCNT:
284718c8510SRobert Watson 		return (AUE_SEMCTL_GETZCNT);
285718c8510SRobert Watson 
286718c8510SRobert Watson 	case IPC_RMID:
287718c8510SRobert Watson 		return (AUE_SEMCTL_RMID);
288718c8510SRobert Watson 
289718c8510SRobert Watson 	case IPC_SET:
290718c8510SRobert Watson 		return (AUE_SEMCTL_SET);
291718c8510SRobert Watson 
292718c8510SRobert Watson 	case SETALL:
293718c8510SRobert Watson 		return (AUE_SEMCTL_SETALL);
294718c8510SRobert Watson 
295718c8510SRobert Watson 	case SETVAL:
296718c8510SRobert Watson 		return (AUE_SEMCTL_SETVAL);
297718c8510SRobert Watson 
298718c8510SRobert Watson 	case IPC_STAT:
299718c8510SRobert Watson 		return (AUE_SEMCTL_STAT);
300718c8510SRobert Watson 
301718c8510SRobert Watson 	default:
302f6d4a8a7SRobert Watson 		/* We will audit a bad command. */
303718c8510SRobert Watson 		return (AUE_SEMCTL);
304718c8510SRobert Watson 	}
305718c8510SRobert Watson }
306718c8510SRobert Watson 
307718c8510SRobert Watson /*
308b7830259SRobert Watson  * Convert msgsys(2), semsys(2), and shmsys(2) system-call variations into
309b7830259SRobert Watson  * audit events, if possible.
310b7830259SRobert Watson  */
311b7830259SRobert Watson au_event_t
audit_msgsys_to_event(int which)312b7830259SRobert Watson audit_msgsys_to_event(int which)
313b7830259SRobert Watson {
314b7830259SRobert Watson 
315b7830259SRobert Watson 	if ((which >= 0) && (which < aue_msgsys_count))
316b7830259SRobert Watson 		return (aue_msgsys[which]);
317b7830259SRobert Watson 
318b7830259SRobert Watson 	/* Audit a bad command. */
319b7830259SRobert Watson 	return (AUE_MSGSYS);
320b7830259SRobert Watson }
321b7830259SRobert Watson 
322b7830259SRobert Watson au_event_t
audit_semsys_to_event(int which)323b7830259SRobert Watson audit_semsys_to_event(int which)
324b7830259SRobert Watson {
325b7830259SRobert Watson 
326b7830259SRobert Watson 	if ((which >= 0) && (which < aue_semsys_count))
327b7830259SRobert Watson 		return (aue_semsys[which]);
328b7830259SRobert Watson 
329b7830259SRobert Watson 	/* Audit a bad command. */
330b7830259SRobert Watson 	return (AUE_SEMSYS);
331b7830259SRobert Watson }
332b7830259SRobert Watson 
333b7830259SRobert Watson au_event_t
audit_shmsys_to_event(int which)334b7830259SRobert Watson audit_shmsys_to_event(int which)
335b7830259SRobert Watson {
336b7830259SRobert Watson 
337b7830259SRobert Watson 	if ((which >= 0) && (which < aue_shmsys_count))
338b7830259SRobert Watson 		return (aue_shmsys[which]);
339b7830259SRobert Watson 
340b7830259SRobert Watson 	/* Audit a bad command. */
341b7830259SRobert Watson 	return (AUE_SHMSYS);
342b7830259SRobert Watson }
343b7830259SRobert Watson 
344b7830259SRobert Watson /*
345718c8510SRobert Watson  * Convert a command for the auditon() system call to a audit event.
346718c8510SRobert Watson  */
347f4f93a63SRobert Watson au_event_t
auditon_command_event(int cmd)348718c8510SRobert Watson auditon_command_event(int cmd)
349718c8510SRobert Watson {
350718c8510SRobert Watson 
351718c8510SRobert Watson 	switch(cmd) {
352718c8510SRobert Watson 	case A_GETPOLICY:
353718c8510SRobert Watson 		return (AUE_AUDITON_GPOLICY);
354718c8510SRobert Watson 
355718c8510SRobert Watson 	case A_SETPOLICY:
356718c8510SRobert Watson 		return (AUE_AUDITON_SPOLICY);
357718c8510SRobert Watson 
358718c8510SRobert Watson 	case A_GETKMASK:
359718c8510SRobert Watson 		return (AUE_AUDITON_GETKMASK);
360718c8510SRobert Watson 
361718c8510SRobert Watson 	case A_SETKMASK:
362718c8510SRobert Watson 		return (AUE_AUDITON_SETKMASK);
363718c8510SRobert Watson 
364718c8510SRobert Watson 	case A_GETQCTRL:
365718c8510SRobert Watson 		return (AUE_AUDITON_GQCTRL);
366718c8510SRobert Watson 
367718c8510SRobert Watson 	case A_SETQCTRL:
368718c8510SRobert Watson 		return (AUE_AUDITON_SQCTRL);
369718c8510SRobert Watson 
370718c8510SRobert Watson 	case A_GETCWD:
371718c8510SRobert Watson 		return (AUE_AUDITON_GETCWD);
372718c8510SRobert Watson 
373718c8510SRobert Watson 	case A_GETCAR:
374718c8510SRobert Watson 		return (AUE_AUDITON_GETCAR);
375718c8510SRobert Watson 
376718c8510SRobert Watson 	case A_GETSTAT:
377718c8510SRobert Watson 		return (AUE_AUDITON_GETSTAT);
378718c8510SRobert Watson 
379718c8510SRobert Watson 	case A_SETSTAT:
380718c8510SRobert Watson 		return (AUE_AUDITON_SETSTAT);
381718c8510SRobert Watson 
382718c8510SRobert Watson 	case A_SETUMASK:
383718c8510SRobert Watson 		return (AUE_AUDITON_SETUMASK);
384718c8510SRobert Watson 
385718c8510SRobert Watson 	case A_SETSMASK:
386718c8510SRobert Watson 		return (AUE_AUDITON_SETSMASK);
387718c8510SRobert Watson 
388718c8510SRobert Watson 	case A_GETCOND:
389718c8510SRobert Watson 		return (AUE_AUDITON_GETCOND);
390718c8510SRobert Watson 
391718c8510SRobert Watson 	case A_SETCOND:
392718c8510SRobert Watson 		return (AUE_AUDITON_SETCOND);
393718c8510SRobert Watson 
394718c8510SRobert Watson 	case A_GETCLASS:
395718c8510SRobert Watson 		return (AUE_AUDITON_GETCLASS);
396718c8510SRobert Watson 
397718c8510SRobert Watson 	case A_SETCLASS:
398718c8510SRobert Watson 		return (AUE_AUDITON_SETCLASS);
399718c8510SRobert Watson 
400718c8510SRobert Watson 	case A_GETPINFO:
401718c8510SRobert Watson 	case A_SETPMASK:
402718c8510SRobert Watson 	case A_SETFSIZE:
403718c8510SRobert Watson 	case A_GETFSIZE:
404718c8510SRobert Watson 	case A_GETPINFO_ADDR:
405718c8510SRobert Watson 	case A_GETKAUDIT:
406718c8510SRobert Watson 	case A_SETKAUDIT:
407718c8510SRobert Watson 	default:
408718c8510SRobert Watson 		return (AUE_AUDITON);	/* No special record */
409718c8510SRobert Watson 	}
410718c8510SRobert Watson }
411718c8510SRobert Watson 
412718c8510SRobert Watson /*
413871499feSRobert Watson  * Create a canonical path from given path by prefixing either the root
414871499feSRobert Watson  * directory, or the current working directory.  If the process working
415d8c0f4dcSRobert Watson  * directory is NULL, we could use 'rootvnode' to obtain the root directory,
416871499feSRobert Watson  * but this results in a volfs name written to the audit log. So we will
417871499feSRobert Watson  * leave the filename starting with '/' in the audit log in this case.
418718c8510SRobert Watson  */
419718c8510SRobert Watson void
audit_canon_path_vp(struct thread * td,struct vnode * rdir,struct vnode * cdir,char * path,char * cpath)4207de6c5ebSMateusz Guzik audit_canon_path_vp(struct thread *td, struct vnode *rdir, struct vnode *cdir,
4217de6c5ebSMateusz Guzik     char *path, char *cpath)
422718c8510SRobert Watson {
4239e826d32SMateusz Guzik 	struct vnode *vp;
424dfc714fbSChristian S.J. Peron 	char *rbuf, *fbuf, *copy;
425dfc714fbSChristian S.J. Peron 	struct sbuf sbf;
4269e826d32SMateusz Guzik 	int error;
427718c8510SRobert Watson 
428dfc714fbSChristian S.J. Peron 	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s: at %s:%d",
429dfc714fbSChristian S.J. Peron 	    __func__,  __FILE__, __LINE__);
430dc97e8c7SRobert Watson 
431dfc714fbSChristian S.J. Peron 	copy = path;
432cc62118eSKyle Evans 	if (*path == '/') {
4337de6c5ebSMateusz Guzik 		vp = rdir;
434cc62118eSKyle Evans 	} else {
435cc62118eSKyle Evans 		if (cdir == NULL) {
436cc62118eSKyle Evans 			cpath[0] = '\0';
437cc62118eSKyle Evans 			return;
438cc62118eSKyle Evans 		}
4397de6c5ebSMateusz Guzik 		vp = cdir;
440cc62118eSKyle Evans 	}
4417de6c5ebSMateusz Guzik 	MPASS(vp != NULL);
442718c8510SRobert Watson 	/*
443dfc714fbSChristian S.J. Peron 	 * NB: We require that the supplied array be at least MAXPATHLEN bytes
444dfc714fbSChristian S.J. Peron 	 * long.  If this is not the case, then we can run into serious trouble.
445718c8510SRobert Watson 	 */
446dfc714fbSChristian S.J. Peron 	(void) sbuf_new(&sbf, cpath, MAXPATHLEN, SBUF_FIXEDLEN);
447dfc714fbSChristian S.J. Peron 	/*
448dfc714fbSChristian S.J. Peron 	 * Strip leading forward slashes.
4499e826d32SMateusz Guzik 	 *
4509e826d32SMateusz Guzik 	 * Note this does nothing to fully canonicalize the path.
4517737a00fSChristian S.J. Peron 	 */
452dfc714fbSChristian S.J. Peron 	while (*copy == '/')
453dfc714fbSChristian S.J. Peron 		copy++;
454dfc714fbSChristian S.J. Peron 	/*
455dfc714fbSChristian S.J. Peron 	 * Make sure we handle chroot(2) and prepend the global path to these
456dfc714fbSChristian S.J. Peron 	 * environments.
457dfc714fbSChristian S.J. Peron 	 *
458dfc714fbSChristian S.J. Peron 	 * NB: vn_fullpath(9) on FreeBSD is less reliable than vn_getpath(9)
459dfc714fbSChristian S.J. Peron 	 * on Darwin.  As a result, this may need some additional attention
460dfc714fbSChristian S.J. Peron 	 * in the future.
461dfc714fbSChristian S.J. Peron 	 */
462*feabaaf9SMateusz Guzik 	error = vn_fullpath_global(vp, &rbuf, &fbuf);
463dfc714fbSChristian S.J. Peron 	if (error) {
464dfc714fbSChristian S.J. Peron 		cpath[0] = '\0';
465dfc714fbSChristian S.J. Peron 		return;
466dfc714fbSChristian S.J. Peron 	}
467dfc714fbSChristian S.J. Peron 	(void) sbuf_cat(&sbf, rbuf);
4689e826d32SMateusz Guzik 	/*
4699e826d32SMateusz Guzik 	 * We are going to concatenate the resolved path with the passed path
4709e826d32SMateusz Guzik 	 * with all slashes removed and we want them glued with a single slash.
4719e826d32SMateusz Guzik 	 * However, if the directory is /, the slash is already there.
4729e826d32SMateusz Guzik 	 */
4739e826d32SMateusz Guzik 	if (rbuf[1] != '\0')
474db850267SChristian S.J. Peron 		(void) sbuf_putc(&sbf, '/');
4759e826d32SMateusz Guzik 	free(fbuf, M_TEMP);
476dfc714fbSChristian S.J. Peron 	/*
477dfc714fbSChristian S.J. Peron 	 * Now that we have processed any alternate root and relative path
478dfc714fbSChristian S.J. Peron 	 * names, add the supplied pathname.
479dfc714fbSChristian S.J. Peron 	 */
480dfc714fbSChristian S.J. Peron 	(void) sbuf_cat(&sbf, copy);
481dfc714fbSChristian S.J. Peron 	/*
482dfc714fbSChristian S.J. Peron 	 * One or more of the previous sbuf operations could have resulted in
483dfc714fbSChristian S.J. Peron 	 * the supplied buffer being overflowed.  Check to see if this is the
484dfc714fbSChristian S.J. Peron 	 * case.
485dfc714fbSChristian S.J. Peron 	 */
4864d369413SMatthew D Fleming 	if (sbuf_error(&sbf) != 0) {
487dfc714fbSChristian S.J. Peron 		cpath[0] = '\0';
488dfc714fbSChristian S.J. Peron 		return;
489dfc714fbSChristian S.J. Peron 	}
490dfc714fbSChristian S.J. Peron 	sbuf_finish(&sbf);
491718c8510SRobert Watson }
4927de6c5ebSMateusz Guzik 
4937de6c5ebSMateusz Guzik void
audit_canon_path(struct thread * td,int dirfd,char * path,char * cpath)4947de6c5ebSMateusz Guzik audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath)
4957de6c5ebSMateusz Guzik {
4967de6c5ebSMateusz Guzik 	struct vnode *cdir, *rdir;
4978d03b99bSMateusz Guzik 	struct pwd *pwd;
4987de6c5ebSMateusz Guzik 	cap_rights_t rights;
4997de6c5ebSMateusz Guzik 	int error;
5008d03b99bSMateusz Guzik 	bool vrele_cdir;
5017de6c5ebSMateusz Guzik 
5027de6c5ebSMateusz Guzik 	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s: at %s:%d",
5037de6c5ebSMateusz Guzik 	    __func__,  __FILE__, __LINE__);
5047de6c5ebSMateusz Guzik 
5058d03b99bSMateusz Guzik 	pwd = pwd_hold(td);
5068d03b99bSMateusz Guzik 	rdir = pwd->pwd_rdir;
5078d03b99bSMateusz Guzik 	cdir = NULL;
5088d03b99bSMateusz Guzik 	vrele_cdir = false;
5098d03b99bSMateusz Guzik 	if (*path != '/') {
5107de6c5ebSMateusz Guzik 		if (dirfd == AT_FDCWD) {
5118d03b99bSMateusz Guzik 			cdir = pwd->pwd_cdir;
5127de6c5ebSMateusz Guzik 		} else {
5137de6c5ebSMateusz Guzik 			error = fgetvp(td, dirfd, cap_rights_init(&rights), &cdir);
5147de6c5ebSMateusz Guzik 			if (error != 0) {
5157de6c5ebSMateusz Guzik 				cpath[0] = '\0';
5168d03b99bSMateusz Guzik 				pwd_drop(pwd);
5177de6c5ebSMateusz Guzik 				return;
5187de6c5ebSMateusz Guzik 			}
5198d03b99bSMateusz Guzik 			vrele_cdir = true;
5207de6c5ebSMateusz Guzik 		}
5217de6c5ebSMateusz Guzik 	}
5227de6c5ebSMateusz Guzik 
5237de6c5ebSMateusz Guzik 	audit_canon_path_vp(td, rdir, cdir, path, cpath);
5247de6c5ebSMateusz Guzik 
5258d03b99bSMateusz Guzik 	pwd_drop(pwd);
5268d03b99bSMateusz Guzik 	if (vrele_cdir)
5277de6c5ebSMateusz Guzik 		vrele(cdir);
5287de6c5ebSMateusz Guzik }
529