xref: /xnu-11215/security/mac_audit.c (revision 94d3b452)
1 /*
2  * Copyright (c) 2006-2020 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
30  * Copyright (c) 2001 Ilmar S. Habibulin
31  * Copyright (c) 2001, 2002, 2003, 2004 Networks Associates Technology, Inc.
32  *
33  * This software was developed by Robert Watson and Ilmar Habibulin for the
34  * TrustedBSD Project.
35  *
36  * This software was developed for the FreeBSD Project in part by Network
37  * Associates Laboratories, the Security Research Division of Network
38  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
39  * as part of the DARPA CHATS research program.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60  * SUCH DAMAGE.
61  *
62  */
63 #include <sys/param.h>
64 #include <sys/types.h>
65 #include <sys/vnode.h>
66 #include <sys/vnode_internal.h>
67 #include <sys/kauth.h>
68 #include <sys/queue.h>
69 #include <security/mac_internal.h>
70 #include <bsd/bsm/audit.h>
71 #include <bsd/security/audit/audit.h>
72 #include <bsd/sys/malloc.h>
73 #include <vm/vm_kern.h>
74 #include <kern/zalloc.h>
75 
76 #if CONFIG_AUDIT
77 
78 ZONE_DEFINE(mac_audit_data_zone, "mac_audit_data_zone",
79     MAC_AUDIT_DATA_LIMIT, ZC_PGZ_USE_GUARDS);
80 
81 int
mac_system_check_audit(struct ucred * cred,void * record,int length)82 mac_system_check_audit(struct ucred *cred, void *record, int length)
83 {
84 	int error;
85 
86 	MAC_CHECK(system_check_audit, cred, record, length);
87 
88 	return error;
89 }
90 
91 int
mac_system_check_auditon(struct ucred * cred,int cmd)92 mac_system_check_auditon(struct ucred *cred, int cmd)
93 {
94 	int error;
95 
96 	MAC_CHECK(system_check_auditon, cred, cmd);
97 
98 	return error;
99 }
100 
101 int
mac_system_check_auditctl(struct ucred * cred,struct vnode * vp)102 mac_system_check_auditctl(struct ucred *cred, struct vnode *vp)
103 {
104 	int error;
105 	struct label *vl = vp ? mac_vnode_label(vp) : NULL;
106 
107 	MAC_CHECK(system_check_auditctl, cred, vp, vl);
108 
109 	return error;
110 }
111 
112 int
mac_proc_check_getauid(struct proc * curp)113 mac_proc_check_getauid(struct proc *curp)
114 {
115 	int error;
116 
117 #if SECURITY_MAC_CHECK_ENFORCE
118 	/* 21167099 - only check if we allow write */
119 	if (!mac_proc_enforce) {
120 		return 0;
121 	}
122 #endif
123 
124 	if (!mac_proc_check_enforce(curp)) {
125 		return 0;
126 	}
127 
128 	MAC_CHECK(proc_check_getauid, current_cached_proc_cred(curp));
129 
130 	return error;
131 }
132 
133 int
mac_proc_check_setauid(struct proc * curp,uid_t auid)134 mac_proc_check_setauid(struct proc *curp, uid_t auid)
135 {
136 	int error;
137 
138 #if SECURITY_MAC_CHECK_ENFORCE
139 	/* 21167099 - only check if we allow write */
140 	if (!mac_proc_enforce) {
141 		return 0;
142 	}
143 #endif
144 	if (!mac_proc_check_enforce(curp)) {
145 		return 0;
146 	}
147 
148 	MAC_CHECK(proc_check_setauid, current_cached_proc_cred(curp), auid);
149 
150 	return error;
151 }
152 
153 int
mac_proc_check_getaudit(struct proc * curp)154 mac_proc_check_getaudit(struct proc *curp)
155 {
156 	int error;
157 
158 #if SECURITY_MAC_CHECK_ENFORCE
159 	/* 21167099 - only check if we allow write */
160 	if (!mac_proc_enforce) {
161 		return 0;
162 	}
163 #endif
164 	if (!mac_proc_check_enforce(curp)) {
165 		return 0;
166 	}
167 
168 	MAC_CHECK(proc_check_getaudit, current_cached_proc_cred(curp));
169 
170 	return error;
171 }
172 
173 int
mac_proc_check_setaudit(struct proc * curp,struct auditinfo_addr * ai)174 mac_proc_check_setaudit(struct proc *curp, struct auditinfo_addr *ai)
175 {
176 	int error;
177 
178 #if SECURITY_MAC_CHECK_ENFORCE
179 	/* 21167099 - only check if we allow write */
180 	if (!mac_proc_enforce) {
181 		return 0;
182 	}
183 #endif
184 	if (!mac_proc_check_enforce(curp)) {
185 		return 0;
186 	}
187 
188 	MAC_CHECK(proc_check_setaudit, current_cached_proc_cred(curp), ai);
189 
190 	return error;
191 }
192 
193 #if 0
194 /*
195  * This is the framework entry point for MAC policies to use to add
196  * arbitrary data to the current audit record.
197  * (Currently not supported, as no existing audit viewers would
198  * display this format)
199  *
200  */
201 int
202 mac_audit_data(int len, u_char *data, mac_policy_handle_t handle)
203 {
204 	char *sanitized;
205 
206 	if ((len <= 0) || (len > MAC_AUDIT_DATA_LIMIT)) {
207 		return EINVAL;
208 	}
209 
210 	sanitized = (char *)zalloc(mac_audit_data_zone);
211 
212 	bcopy(data, sanitized, len);
213 	return audit_mac_data(MAC_AUDIT_DATA_TYPE, len, sanitized);
214 }
215 #endif
216 
217 /*
218  * This is the entry point a MAC policy will call to add NULL-
219  * terminated ASCII text to the current audit record.
220  */
221 int
mac_audit_text(char * text,mac_policy_handle_t handle)222 mac_audit_text(char *text, mac_policy_handle_t handle)
223 {
224 	char *sanitized;
225 	const char *name;
226 	size_t i, size, plen, text_len;
227 
228 	name = mac_get_mpc(handle)->mpc_name;
229 	text_len = strlen(text);
230 	plen = 2 + strlen(name);
231 	if (plen + text_len >= MAC_AUDIT_DATA_LIMIT) {
232 		return EINVAL;
233 	}
234 
235 	/*
236 	 * Make sure the text is only composed of only ASCII printable
237 	 * characters.
238 	 */
239 	for (i = 0; i < text_len; i++) {
240 		if (text[i] < (char) 32 || text[i] > (char) 126) {
241 			return EINVAL;
242 		}
243 	}
244 
245 	size = text_len + plen + 1;
246 	sanitized = (char *)zalloc(mac_audit_data_zone);
247 
248 	strlcpy(sanitized, name, MAC_AUDIT_DATA_LIMIT);
249 	strlcat(sanitized, ": ", MAC_AUDIT_DATA_LIMIT);
250 	strlcat(sanitized, text, MAC_AUDIT_DATA_LIMIT);
251 
252 	return audit_mac_data(MAC_AUDIT_TEXT_TYPE, size, (u_char *)sanitized);
253 }
254 
255 int
mac_audit_check_preselect(struct ucred * cred,unsigned short syscode,void * args)256 mac_audit_check_preselect(struct ucred *cred, unsigned short syscode, void *args)
257 {
258 	struct mac_policy_conf *mpc;
259 	int ret, error;
260 	u_int i;
261 
262 	ret = MAC_AUDIT_DEFAULT;
263 	for (i = 0; i < mac_policy_list.staticmax; i++) {
264 		mpc = mac_policy_list.entries[i].mpc;
265 		if (mpc == NULL) {
266 			continue;
267 		}
268 
269 		if (mpc->mpc_ops->mpo_audit_check_preselect != NULL) {
270 			error = mpc->mpc_ops->mpo_audit_check_preselect(cred,
271 			    syscode, args);
272 			ret = (ret > error ? ret : error);
273 		}
274 	}
275 	if (mac_policy_list_conditional_busy() != 0) {
276 		for (; i <= mac_policy_list.maxindex; i++) {
277 			mpc = mac_policy_list.entries[i].mpc;
278 			if (mpc == NULL) {
279 				continue;
280 			}
281 
282 			if (mpc->mpc_ops->mpo_audit_check_preselect != NULL) {
283 				error = mpc->mpc_ops->mpo_audit_check_preselect(cred,
284 				    syscode, args);
285 				ret = (ret > error ? ret : error);
286 			}
287 		}
288 		mac_policy_list_unbusy();
289 	}
290 
291 	return ret;
292 }
293 
294 int
mac_audit_check_postselect(struct ucred * cred,unsigned short syscode,void * args,int error,int retval,int mac_forced)295 mac_audit_check_postselect(struct ucred *cred, unsigned short syscode,
296     void *args, int error, int retval, int mac_forced)
297 {
298 	struct mac_policy_conf *mpc;
299 	int ret, mac_error;
300 	u_int i;
301 
302 	/*
303 	 * If the audit was forced by a MAC policy by mac_audit_check_preselect(),
304 	 * echo that.
305 	 */
306 	if (mac_forced) {
307 		return MAC_AUDIT_YES;
308 	}
309 
310 	ret = MAC_AUDIT_DEFAULT;
311 	for (i = 0; i < mac_policy_list.staticmax; i++) {
312 		mpc = mac_policy_list.entries[i].mpc;
313 		if (mpc == NULL) {
314 			continue;
315 		}
316 
317 		if (mpc->mpc_ops->mpo_audit_check_postselect != NULL) {
318 			mac_error = mpc->mpc_ops->mpo_audit_check_postselect(cred,
319 			    syscode, args, error, retval);
320 			ret = (ret > mac_error ? ret : mac_error);
321 		}
322 	}
323 	if (mac_policy_list_conditional_busy() != 0) {
324 		for (; i <= mac_policy_list.maxindex; i++) {
325 			mpc = mac_policy_list.entries[i].mpc;
326 			if (mpc == NULL) {
327 				continue;
328 			}
329 
330 			if (mpc->mpc_ops->mpo_audit_check_postselect != NULL) {
331 				mac_error = mpc->mpc_ops->mpo_audit_check_postselect(cred,
332 				    syscode, args, error, retval);
333 				ret = (ret > mac_error ? ret : mac_error);
334 			}
335 		}
336 		mac_policy_list_unbusy();
337 	}
338 
339 	return ret;
340 }
341 
342 #else   /* !CONFIG_AUDIT */
343 
344 /*
345  * Function stubs for when AUDIT isn't defined.
346  */
347 
348 int
mac_system_check_audit(__unused struct ucred * cred,__unused void * record,__unused int length)349 mac_system_check_audit(__unused struct ucred *cred, __unused void *record, __unused int length)
350 {
351 	return 0;
352 }
353 
354 int
mac_system_check_auditon(__unused struct ucred * cred,__unused int cmd)355 mac_system_check_auditon(__unused struct ucred *cred, __unused int cmd)
356 {
357 	return 0;
358 }
359 
360 int
mac_system_check_auditctl(__unused struct ucred * cred,__unused struct vnode * vp)361 mac_system_check_auditctl(__unused struct ucred *cred, __unused struct vnode *vp)
362 {
363 	return 0;
364 }
365 
366 int
mac_proc_check_getauid(__unused struct proc * curp)367 mac_proc_check_getauid(__unused struct proc *curp)
368 {
369 	return 0;
370 }
371 
372 int
mac_proc_check_setauid(__unused struct proc * curp,__unused uid_t auid)373 mac_proc_check_setauid(__unused struct proc *curp, __unused uid_t auid)
374 {
375 	return 0;
376 }
377 
378 int
mac_proc_check_getaudit(__unused struct proc * curp)379 mac_proc_check_getaudit(__unused struct proc *curp)
380 {
381 	return 0;
382 }
383 
384 int
mac_proc_check_setaudit(__unused struct proc * curp,__unused struct auditinfo_addr * ai)385 mac_proc_check_setaudit(__unused struct proc *curp,
386     __unused struct auditinfo_addr *ai)
387 {
388 	return 0;
389 }
390 
391 int
mac_audit_check_preselect(__unused struct ucred * cred,__unused unsigned short syscode,__unused void * args)392 mac_audit_check_preselect(__unused struct ucred *cred, __unused unsigned short syscode,
393     __unused void *args)
394 {
395 	return MAC_AUDIT_DEFAULT;
396 }
397 
398 int
mac_audit_check_postselect(__unused struct ucred * cred,__unused unsigned short syscode,__unused void * args,__unused int error,__unused int retval,__unused int mac_forced)399 mac_audit_check_postselect(__unused struct ucred *cred, __unused unsigned short syscode,
400     __unused void *args, __unused int error, __unused int retval, __unused int mac_forced)
401 {
402 	return MAC_AUDIT_DEFAULT;
403 }
404 
405 int
mac_audit_text(__unused char * text,__unused mac_policy_handle_t handle)406 mac_audit_text(__unused char *text, __unused mac_policy_handle_t handle)
407 {
408 	return 0;
409 }
410 #endif  /* !CONFIG_AUDIT */
411