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
78ZONE_DEFINE(mac_audit_data_zone, "mac_audit_data_zone",
79 MAC_AUDIT_DATA_LIMIT, ZC_PGZ_USE_GUARDS);
80
81int
82mac_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
91int
92mac_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
101int
102mac_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
112int
113mac_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(p: curp)) {
125 return 0;
126 }
127
128 MAC_CHECK(proc_check_getauid, current_cached_proc_cred(curp));
129
130 return error;
131}
132
133int
134mac_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(p: curp)) {
145 return 0;
146 }
147
148 MAC_CHECK(proc_check_setauid, current_cached_proc_cred(curp), auid);
149
150 return error;
151}
152
153int
154mac_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(p: curp)) {
165 return 0;
166 }
167
168 MAC_CHECK(proc_check_getaudit, current_cached_proc_cred(curp));
169
170 return error;
171}
172
173int
174mac_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(p: 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 */
201int
202mac_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 */
221int
222mac_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(s: text);
230 plen = 2 + strlen(s: 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(zone: mac_audit_data_zone);
247
248 strlcpy(dst: sanitized, src: name, MAC_AUDIT_DATA_LIMIT);
249 strlcat(dst: sanitized, src: ": ", MAC_AUDIT_DATA_LIMIT);
250 strlcat(dst: sanitized, src: text, MAC_AUDIT_DATA_LIMIT);
251
252 return audit_mac_data(MAC_AUDIT_TEXT_TYPE, len: size, data: (u_char *)sanitized);
253}
254
255int
256mac_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
294int
295mac_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
348int
349mac_system_check_audit(__unused struct ucred *cred, __unused void *record, __unused int length)
350{
351 return 0;
352}
353
354int
355mac_system_check_auditon(__unused struct ucred *cred, __unused int cmd)
356{
357 return 0;
358}
359
360int
361mac_system_check_auditctl(__unused struct ucred *cred, __unused struct vnode *vp)
362{
363 return 0;
364}
365
366int
367mac_proc_check_getauid(__unused struct proc *curp)
368{
369 return 0;
370}
371
372int
373mac_proc_check_setauid(__unused struct proc *curp, __unused uid_t auid)
374{
375 return 0;
376}
377
378int
379mac_proc_check_getaudit(__unused struct proc *curp)
380{
381 return 0;
382}
383
384int
385mac_proc_check_setaudit(__unused struct proc *curp,
386 __unused struct auditinfo_addr *ai)
387{
388 return 0;
389}
390
391int
392mac_audit_check_preselect(__unused struct ucred *cred, __unused unsigned short syscode,
393 __unused void *args)
394{
395 return MAC_AUDIT_DEFAULT;
396}
397
398int
399mac_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
405int
406mac_audit_text(__unused char *text, __unused mac_policy_handle_t handle)
407{
408 return 0;
409}
410#endif /* !CONFIG_AUDIT */
411