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