]> git.saurik.com Git - apple/xnu.git/blob - security/mac_vfs.c
81b311012fb7a1abbc5b9821b3c904b6c6b7470a
[apple/xnu.git] / security / mac_vfs.c
1 /*
2 * Copyright (c) 2007-2016 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 * Copyright (c) 2005 SPARTA, Inc.
33 *
34 * This software was developed by Robert Watson and Ilmar Habibulin for the
35 * TrustedBSD Project.
36 *
37 * This software was developed for the FreeBSD Project in part by Network
38 * Associates Laboratories, the Security Research Division of Network
39 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
40 * as part of the DARPA CHATS research program.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 */
64
65 #include <kern/kalloc.h>
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/kernel.h>
70 #include <sys/proc.h>
71 #include <sys/kauth.h>
72
73 #include <sys/file_internal.h>
74 #include <sys/imgact.h>
75 #include <sys/namei.h>
76 #include <sys/mount_internal.h>
77 #include <sys/pipe.h>
78 #include <sys/posix_sem.h>
79 #include <sys/posix_shm.h>
80 #include <sys/reason.h>
81 #include <sys/uio_internal.h>
82 #include <sys/vnode_internal.h>
83
84 #include <miscfs/devfs/devfsdefs.h>
85 #include <miscfs/devfs/fdesc.h>
86
87 #include <security/mac_internal.h>
88
89 /* convert {R,W,X}_OK values to V{READ,WRITE,EXEC} */
90 #define ACCESS_MODE_TO_VNODE_MASK(m) (m << 6)
91
92 static struct label *
93 mac_devfsdirent_label_alloc(void)
94 {
95 struct label *label;
96
97 label = mac_labelzone_alloc(MAC_WAITOK);
98 if (label == NULL) {
99 return NULL;
100 }
101 MAC_PERFORM(devfs_label_init, label);
102 return label;
103 }
104
105 void
106 mac_devfs_label_init(struct devnode *de)
107 {
108 de->dn_label = mac_devfsdirent_label_alloc();
109 }
110
111 static struct label *
112 mac_mount_label_alloc(void)
113 {
114 struct label *label;
115
116 label = mac_labelzone_alloc(MAC_WAITOK);
117 if (label == NULL) {
118 return NULL;
119 }
120 MAC_PERFORM(mount_label_init, label);
121 return label;
122 }
123
124 void
125 mac_mount_label_init(struct mount *mp)
126 {
127 mp->mnt_mntlabel = mac_mount_label_alloc();
128 }
129
130 struct label *
131 mac_vnode_label_alloc(void)
132 {
133 struct label *label;
134
135 label = mac_labelzone_alloc(MAC_WAITOK);
136 if (label == NULL) {
137 return NULL;
138 }
139 MAC_PERFORM(vnode_label_init, label);
140 return label;
141 }
142
143 void
144 mac_vnode_label_init(vnode_t vp)
145 {
146 vp->v_label = mac_vnode_label_alloc();
147 }
148
149 int
150 mac_vnode_label_init_needed(vnode_t vp)
151 {
152 return mac_label_vnodes != 0 && vp->v_label == NULL;
153 }
154
155 /*
156 * vnode labels are allocated at the same time as vnodes, but vnodes are never
157 * freed. Instead, we want to remove any sensitive information before putting
158 * them on the free list for reuse.
159 */
160 void
161 mac_vnode_label_recycle(vnode_t vp)
162 {
163 MAC_PERFORM(vnode_label_recycle, vp->v_label);
164 }
165
166 static void
167 mac_devfs_label_free(struct label *label)
168 {
169 MAC_PERFORM(devfs_label_destroy, label);
170 mac_labelzone_free(label);
171 }
172
173 void
174 mac_devfs_label_destroy(struct devnode *de)
175 {
176 if (de->dn_label != NULL) {
177 mac_devfs_label_free(de->dn_label);
178 de->dn_label = NULL;
179 }
180 }
181
182 static void
183 mac_mount_label_free(struct label *label)
184 {
185 MAC_PERFORM(mount_label_destroy, label);
186 mac_labelzone_free(label);
187 }
188
189 void
190 mac_mount_label_destroy(struct mount *mp)
191 {
192 if (mp->mnt_mntlabel != NULL) {
193 mac_mount_label_free(mp->mnt_mntlabel);
194 mp->mnt_mntlabel = NULL;
195 }
196 }
197
198 void
199 mac_vnode_label_free(struct label *label)
200 {
201 MAC_PERFORM(vnode_label_destroy, label);
202 mac_labelzone_free(label);
203 }
204
205 #ifndef __APPLE__
206 void
207 mac_vnode_label_destroy(struct vnode *vp)
208 {
209 if (vp->v_label != NULL) {
210 mac_vnode_label_free(vp->v_label);
211 vp->v_label = NULL;
212 }
213 }
214 #endif
215
216 void
217 mac_vnode_label_copy(struct label *src, struct label *dest)
218 {
219 if (src == NULL) {
220 MAC_PERFORM(vnode_label_init, dest);
221 } else {
222 MAC_PERFORM(vnode_label_copy, src, dest);
223 }
224 }
225
226 int
227 mac_vnode_label_externalize_audit(struct vnode *vp, struct mac *mac)
228 {
229 int error;
230
231 /* It is assumed that any necessary vnode locking is done on entry */
232 error = MAC_EXTERNALIZE_AUDIT(vnode, vp->v_label,
233 mac->m_string, mac->m_buflen);
234
235 return error;
236 }
237
238 int
239 mac_vnode_label_externalize(struct label *label, char *elements,
240 char *outbuf, size_t outbuflen, int flags __unused)
241 {
242 int error;
243
244 error = MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
245
246 return error;
247 }
248
249 int
250 mac_vnode_label_internalize(struct label *label, char *string)
251 {
252 int error;
253
254 error = MAC_INTERNALIZE(vnode, label, string);
255
256 return error;
257 }
258
259 int
260 mac_mount_label_internalize(struct label *label, char *string)
261 {
262 int error;
263
264 error = MAC_INTERNALIZE(mount, label, string);
265
266 return error;
267 }
268
269 int
270 mac_mount_label_externalize(struct label *label, char *elements,
271 char *outbuf, size_t outbuflen)
272 {
273 int error;
274
275 error = MAC_EXTERNALIZE(mount, label, elements, outbuf, outbuflen);
276
277 return error;
278 }
279
280 void
281 mac_devfs_label_copy(struct label *src, struct label *dest)
282 {
283 #if SECURITY_MAC_CHECK_ENFORCE
284 /* 21167099 - only check if we allow write */
285 if (!mac_device_enforce) {
286 return;
287 }
288 #endif
289
290 MAC_PERFORM(devfs_label_copy, src, dest);
291 }
292
293 void
294 mac_devfs_label_update(struct mount *mp, struct devnode *de,
295 struct vnode *vp)
296 {
297 #if SECURITY_MAC_CHECK_ENFORCE
298 /* 21167099 - only check if we allow write */
299 if (!mac_device_enforce) {
300 return;
301 }
302 #endif
303
304 MAC_PERFORM(devfs_label_update, mp, de, de->dn_label, vp,
305 vp->v_label);
306 }
307
308 int
309 mac_vnode_label_associate(struct mount *mp, struct vnode *vp, vfs_context_t ctx)
310 {
311 struct devnode *dnp;
312 struct fdescnode *fnp;
313 int error = 0;
314
315 #if SECURITY_MAC_CHECK_ENFORCE
316 /* 21167099 - only check if we allow write */
317 if (!mac_vnode_enforce) {
318 return error;
319 }
320 #endif
321
322 /* XXX: should not inspect v_tag in kernel! */
323 switch (vp->v_tag) {
324 case VT_DEVFS:
325 dnp = VTODN(vp);
326 mac_vnode_label_associate_devfs(mp, dnp, vp);
327 break;
328 case VT_FDESC:
329 fnp = VTOFDESC(vp);
330 error = mac_vnode_label_associate_fdesc(mp, fnp, vp, ctx);
331 break;
332 default:
333 error = mac_vnode_label_associate_extattr(mp, vp);
334 break;
335 }
336
337 return error;
338 }
339
340 void
341 mac_vnode_label_associate_devfs(struct mount *mp, struct devnode *de,
342 struct vnode *vp)
343 {
344 #if SECURITY_MAC_CHECK_ENFORCE
345 /* 21167099 - only check if we allow write */
346 if (!mac_device_enforce) {
347 return;
348 }
349 #endif
350
351 MAC_PERFORM(vnode_label_associate_devfs,
352 mp, mp ? mp->mnt_mntlabel : NULL,
353 de, de->dn_label,
354 vp, vp->v_label);
355 }
356
357 int
358 mac_vnode_label_associate_extattr(struct mount *mp, struct vnode *vp)
359 {
360 int error;
361
362 MAC_CHECK(vnode_label_associate_extattr, mp, mp->mnt_mntlabel, vp,
363 vp->v_label);
364
365 return error;
366 }
367
368 void
369 mac_vnode_label_associate_singlelabel(struct mount *mp, struct vnode *vp)
370 {
371 #if SECURITY_MAC_CHECK_ENFORCE
372 /* 21167099 - only check if we allow write */
373 if (!mac_vnode_enforce) {
374 return;
375 }
376 #endif
377 if (!mac_label_vnodes) {
378 return;
379 }
380
381 MAC_PERFORM(vnode_label_associate_singlelabel, mp,
382 mp ? mp->mnt_mntlabel : NULL, vp, vp->v_label);
383 }
384
385 int
386 mac_vnode_notify_create(vfs_context_t ctx, struct mount *mp,
387 struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
388 {
389 kauth_cred_t cred;
390 int error;
391
392 #if SECURITY_MAC_CHECK_ENFORCE
393 /* 21167099 - only check if we allow write */
394 if (!mac_vnode_enforce) {
395 return 0;
396 }
397 #endif
398 cred = vfs_context_ucred(ctx);
399 if (!mac_cred_check_enforce(cred)) {
400 return 0;
401 }
402 MAC_CHECK(vnode_notify_create, cred, mp, mp->mnt_mntlabel,
403 dvp, dvp->v_label, vp, vp->v_label, cnp);
404
405 return error;
406 }
407
408 void
409 mac_vnode_notify_rename(vfs_context_t ctx, struct vnode *vp,
410 struct vnode *dvp, struct componentname *cnp)
411 {
412 kauth_cred_t cred;
413
414 #if SECURITY_MAC_CHECK_ENFORCE
415 /* 21167099 - only check if we allow write */
416 if (!mac_vnode_enforce) {
417 return;
418 }
419 #endif
420 cred = vfs_context_ucred(ctx);
421 if (!mac_cred_check_enforce(cred)) {
422 return;
423 }
424 MAC_PERFORM(vnode_notify_rename, cred, vp, vp->v_label,
425 dvp, dvp->v_label, cnp);
426 }
427
428 void
429 mac_vnode_notify_open(vfs_context_t ctx, struct vnode *vp, int acc_flags)
430 {
431 kauth_cred_t cred;
432
433 #if SECURITY_MAC_CHECK_ENFORCE
434 /* 21167099 - only check if we allow write */
435 if (!mac_vnode_enforce) {
436 return;
437 }
438 #endif
439 cred = vfs_context_ucred(ctx);
440 if (!mac_cred_check_enforce(cred)) {
441 return;
442 }
443 MAC_PERFORM(vnode_notify_open, cred, vp, vp->v_label, acc_flags);
444 }
445
446 void
447 mac_vnode_notify_link(vfs_context_t ctx, struct vnode *vp,
448 struct vnode *dvp, struct componentname *cnp)
449 {
450 kauth_cred_t cred;
451
452 #if SECURITY_MAC_CHECK_ENFORCE
453 /* 21167099 - only check if we allow write */
454 if (!mac_vnode_enforce) {
455 return;
456 }
457 #endif
458 cred = vfs_context_ucred(ctx);
459 if (!mac_cred_check_enforce(cred)) {
460 return;
461 }
462 MAC_PERFORM(vnode_notify_link, cred, dvp, dvp->v_label, vp, vp->v_label, cnp);
463 }
464
465 void
466 mac_vnode_notify_deleteextattr(vfs_context_t ctx, struct vnode *vp, const char *name)
467 {
468 kauth_cred_t cred;
469
470 #if SECURITY_MAC_CHECK_ENFORCE
471 /* 21167099 - only check if we allow write */
472 if (!mac_vnode_enforce) {
473 return;
474 }
475 #endif
476 cred = vfs_context_ucred(ctx);
477 if (!mac_cred_check_enforce(cred)) {
478 return;
479 }
480 MAC_PERFORM(vnode_notify_deleteextattr, cred, vp, vp->v_label, name);
481 }
482
483 void
484 mac_vnode_notify_setacl(vfs_context_t ctx, struct vnode *vp, struct kauth_acl *acl)
485 {
486 kauth_cred_t cred;
487
488 #if SECURITY_MAC_CHECK_ENFORCE
489 /* 21167099 - only check if we allow write */
490 if (!mac_vnode_enforce) {
491 return;
492 }
493 #endif
494 cred = vfs_context_ucred(ctx);
495 if (!mac_cred_check_enforce(cred)) {
496 return;
497 }
498 MAC_PERFORM(vnode_notify_setacl, cred, vp, vp->v_label, acl);
499 }
500
501 void
502 mac_vnode_notify_setattrlist(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist)
503 {
504 kauth_cred_t cred;
505
506 #if SECURITY_MAC_CHECK_ENFORCE
507 /* 21167099 - only check if we allow write */
508 if (!mac_vnode_enforce) {
509 return;
510 }
511 #endif
512 cred = vfs_context_ucred(ctx);
513 if (!mac_cred_check_enforce(cred)) {
514 return;
515 }
516 MAC_PERFORM(vnode_notify_setattrlist, cred, vp, vp->v_label, alist);
517 }
518
519 void
520 mac_vnode_notify_setextattr(vfs_context_t ctx, struct vnode *vp, const char *name, struct uio *uio)
521 {
522 kauth_cred_t cred;
523
524 #if SECURITY_MAC_CHECK_ENFORCE
525 /* 21167099 - only check if we allow write */
526 if (!mac_vnode_enforce) {
527 return;
528 }
529 #endif
530 cred = vfs_context_ucred(ctx);
531 if (!mac_cred_check_enforce(cred)) {
532 return;
533 }
534 MAC_PERFORM(vnode_notify_setextattr, cred, vp, vp->v_label, name, uio);
535 }
536
537 void
538 mac_vnode_notify_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
539 {
540 kauth_cred_t cred;
541
542 #if SECURITY_MAC_CHECK_ENFORCE
543 /* 21167099 - only check if we allow write */
544 if (!mac_vnode_enforce) {
545 return;
546 }
547 #endif
548 cred = vfs_context_ucred(ctx);
549 if (!mac_cred_check_enforce(cred)) {
550 return;
551 }
552 MAC_PERFORM(vnode_notify_setflags, cred, vp, vp->v_label, flags);
553 }
554
555 void
556 mac_vnode_notify_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
557 {
558 kauth_cred_t cred;
559
560 #if SECURITY_MAC_CHECK_ENFORCE
561 /* 21167099 - only check if we allow write */
562 if (!mac_vnode_enforce) {
563 return;
564 }
565 #endif
566 cred = vfs_context_ucred(ctx);
567 if (!mac_cred_check_enforce(cred)) {
568 return;
569 }
570 MAC_PERFORM(vnode_notify_setmode, cred, vp, vp->v_label, mode);
571 }
572
573 void
574 mac_vnode_notify_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid, gid_t gid)
575 {
576 kauth_cred_t cred;
577
578 #if SECURITY_MAC_CHECK_ENFORCE
579 /* 21167099 - only check if we allow write */
580 if (!mac_vnode_enforce) {
581 return;
582 }
583 #endif
584 cred = vfs_context_ucred(ctx);
585 if (!mac_cred_check_enforce(cred)) {
586 return;
587 }
588 MAC_PERFORM(vnode_notify_setowner, cred, vp, vp->v_label, uid, gid);
589 }
590
591 void
592 mac_vnode_notify_setutimes(vfs_context_t ctx, struct vnode *vp, struct timespec atime, struct timespec mtime)
593 {
594 kauth_cred_t cred;
595
596 #if SECURITY_MAC_CHECK_ENFORCE
597 /* 21167099 - only check if we allow write */
598 if (!mac_vnode_enforce) {
599 return;
600 }
601 #endif
602 cred = vfs_context_ucred(ctx);
603 if (!mac_cred_check_enforce(cred)) {
604 return;
605 }
606 MAC_PERFORM(vnode_notify_setutimes, cred, vp, vp->v_label, atime, mtime);
607 }
608
609 void
610 mac_vnode_notify_truncate(vfs_context_t ctx, kauth_cred_t file_cred, struct vnode *vp)
611 {
612 kauth_cred_t cred;
613
614 #if SECURITY_MAC_CHECK_ENFORCE
615 /* 21167099 - only check if we allow write */
616 if (!mac_vnode_enforce) {
617 return;
618 }
619 #endif
620 cred = vfs_context_ucred(ctx);
621 if (!mac_cred_check_enforce(cred)) {
622 return;
623 }
624 MAC_PERFORM(vnode_notify_truncate, cred, file_cred, vp, vp->v_label);
625 }
626
627 /*
628 * Extended attribute 'name' was updated via
629 * vn_setxattr() or vn_removexattr(). Allow the
630 * policy to update the vnode label.
631 */
632 void
633 mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp,
634 const char *name)
635 {
636 int error = 0;
637
638 #if SECURITY_MAC_CHECK_ENFORCE
639 /* 21167099 - only check if we allow write */
640 if (!mac_vnode_enforce) {
641 return;
642 }
643 #endif
644 if (!mac_label_vnodes) {
645 return;
646 }
647
648 MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp,
649 vp->v_label, name);
650 if (error == 0) {
651 return;
652 }
653
654 vnode_lock(vp);
655 vnode_relabel(vp);
656 vnode_unlock(vp);
657 return;
658 }
659
660 static int
661 mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp,
662 struct label *intlabel)
663 {
664 kauth_cred_t cred;
665 int error;
666
667 #if SECURITY_MAC_CHECK_ENFORCE
668 /* 21167099 - only check if we allow write */
669 if (!mac_vnode_enforce) {
670 return 0;
671 }
672 #endif
673 if (!mac_label_vnodes) {
674 return 0;
675 }
676
677 cred = vfs_context_ucred(ctx);
678 if (!mac_cred_check_enforce(cred)) {
679 return 0;
680 }
681 MAC_CHECK(vnode_label_store, cred, vp, vp->v_label, intlabel);
682
683 return error;
684 }
685
686 void
687 mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp, off_t offset,
688 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl, u_int *csflags,
689 void *macextensions, int *disjoint, int *labelupdateerror)
690 {
691 kauth_cred_t cred;
692 *disjoint = 0;
693 int error;
694 posix_cred_t pcred = posix_cred_get(new);
695
696 #if SECURITY_MAC_CHECK_ENFORCE
697 /* 21167099 - only check if we allow write */
698 if (!mac_proc_enforce || !mac_vnode_enforce) {
699 return;
700 }
701 #endif
702
703 /* mark the new cred to indicate "matching" includes the label */
704 pcred->cr_flags |= CRF_MAC_ENFORCE;
705
706 cred = vfs_context_ucred(ctx);
707
708 /*
709 * NB: Cannot use MAC_CHECK macro because we need a sequence point after
710 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
711 * spawnattrlen as an argument to the hook.
712 */
713 {
714 struct mac_policy_conf *mpc;
715 u_int i;
716
717 error = 0;
718 for (i = 0; i < mac_policy_list.staticmax; i++) {
719 mpc = mac_policy_list.entries[i].mpc;
720 if (mpc == NULL) {
721 continue;
722 }
723
724 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
725 if (hook == NULL) {
726 continue;
727 }
728
729 size_t spawnattrlen = 0;
730 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
731
732 error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp,
733 vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint),
734 error);
735 }
736 if (mac_policy_list_conditional_busy() != 0) {
737 for (; i <= mac_policy_list.maxindex; i++) {
738 mpc = mac_policy_list.entries[i].mpc;
739 if (mpc == NULL) {
740 continue;
741 }
742
743 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
744 if (hook == NULL) {
745 continue;
746 }
747
748 size_t spawnattrlen = 0;
749 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
750
751 error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp,
752 vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint),
753 error);
754 }
755 mac_policy_list_unbusy();
756 }
757 }
758 *labelupdateerror = error;
759 }
760
761 int
762 mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp, off_t offset,
763 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel,
764 struct proc *p, void *macextensions)
765 {
766 kauth_cred_t cred;
767 int result = 0;
768
769 #if SECURITY_MAC_CHECK_ENFORCE
770 /* 21167099 - only check if we allow write */
771 if (!mac_proc_enforce || !mac_vnode_enforce) {
772 return result;
773 }
774 #endif
775
776 cred = vfs_context_ucred(ctx);
777
778 /*
779 * NB: Cannot use MAC_BOOLEAN macro because we need a sequence point after
780 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
781 * spawnattrlen as an argument to the hook.
782 */
783 {
784 struct mac_policy_conf *mpc;
785 u_int i;
786
787 for (i = 0; i < mac_policy_list.staticmax; i++) {
788 mpc = mac_policy_list.entries[i].mpc;
789 if (mpc == NULL) {
790 continue;
791 }
792
793 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
794 if (hook == NULL) {
795 continue;
796 }
797
798 size_t spawnattrlen = 0;
799 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
800
801 result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
802 }
803 if (mac_policy_list_conditional_busy() != 0) {
804 for (; i <= mac_policy_list.maxindex; i++) {
805 mpc = mac_policy_list.entries[i].mpc;
806 if (mpc == NULL) {
807 continue;
808 }
809
810 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
811 if (hook == NULL) {
812 continue;
813 }
814
815 size_t spawnattrlen = 0;
816 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
817
818 result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
819 }
820 mac_policy_list_unbusy();
821 }
822 }
823
824 return result;
825 }
826
827 int
828 mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp,
829 int acc_mode)
830 {
831 kauth_cred_t cred;
832 int error;
833 int mask;
834
835 #if SECURITY_MAC_CHECK_ENFORCE
836 /* 21167099 - only check if we allow write */
837 if (!mac_vnode_enforce) {
838 return 0;
839 }
840 #endif
841 cred = vfs_context_ucred(ctx);
842 if (!mac_cred_check_enforce(cred)) {
843 return 0;
844 }
845 /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */
846 mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode);
847 MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask);
848 return error;
849 }
850
851 int
852 mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp)
853 {
854 kauth_cred_t cred;
855 int error;
856
857 #if SECURITY_MAC_CHECK_ENFORCE
858 /* 21167099 - only check if we allow write */
859 if (!mac_vnode_enforce) {
860 return 0;
861 }
862 #endif
863 cred = vfs_context_ucred(ctx);
864 if (!mac_cred_check_enforce(cred)) {
865 return 0;
866 }
867 MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
868 return error;
869 }
870
871 int
872 mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp,
873 struct componentname *cnp)
874 {
875 kauth_cred_t cred;
876 int error;
877
878 #if SECURITY_MAC_CHECK_ENFORCE
879 /* 21167099 - only check if we allow write */
880 if (!mac_vnode_enforce) {
881 return 0;
882 }
883 #endif
884 cred = vfs_context_ucred(ctx);
885 if (!mac_cred_check_enforce(cred)) {
886 return 0;
887 }
888 MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp);
889 return error;
890 }
891
892 int
893 mac_vnode_check_clone(vfs_context_t ctx, struct vnode *dvp,
894 struct vnode *vp, struct componentname *cnp)
895 {
896 kauth_cred_t cred;
897 int error;
898
899 #if SECURITY_MAC_CHECK_ENFORCE
900 /* 21167099 - only check if we allow write */
901 if (!mac_vnode_enforce) {
902 return 0;
903 }
904 #endif
905 cred = vfs_context_ucred(ctx);
906 if (!mac_cred_check_enforce(cred)) {
907 return 0;
908 }
909 MAC_CHECK(vnode_check_clone, cred, dvp, dvp->v_label, vp,
910 vp->v_label, cnp);
911 return error;
912 }
913 int
914 mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp,
915 struct componentname *cnp, struct vnode_attr *vap)
916 {
917 kauth_cred_t cred;
918 int error;
919
920 #if SECURITY_MAC_CHECK_ENFORCE
921 /* 21167099 - only check if we allow write */
922 if (!mac_vnode_enforce) {
923 return 0;
924 }
925 #endif
926 cred = vfs_context_ucred(ctx);
927 if (!mac_cred_check_enforce(cred)) {
928 return 0;
929 }
930 MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
931 return error;
932 }
933
934 int
935 mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp,
936 struct componentname *cnp)
937 {
938 kauth_cred_t cred;
939 int error;
940
941 #if SECURITY_MAC_CHECK_ENFORCE
942 /* 21167099 - only check if we allow write */
943 if (!mac_vnode_enforce) {
944 return 0;
945 }
946 #endif
947 cred = vfs_context_ucred(ctx);
948 if (!mac_cred_check_enforce(cred)) {
949 return 0;
950 }
951 MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
952 vp->v_label, cnp);
953 return error;
954 }
955 #if 0
956 int
957 mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp,
958 acl_type_t type)
959 {
960 kauth_cred_t cred;
961 int error;
962
963 #if SECURITY_MAC_CHECK_ENFORCE
964 /* 21167099 - only check if we allow write */
965 if (!mac_vnode_enforce) {
966 return 0;
967 }
968 #endif
969 cred = vfs_context_ucred(ctx);
970 if (!mac_cred_check_enforce(cred)) {
971 return 0;
972 }
973 MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
974 return error;
975 }
976 #endif
977
978 int
979 mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp,
980 const char *name)
981 {
982 kauth_cred_t cred;
983 int error;
984
985 #if SECURITY_MAC_CHECK_ENFORCE
986 /* 21167099 - only check if we allow write */
987 if (!mac_vnode_enforce) {
988 return 0;
989 }
990 #endif
991 cred = vfs_context_ucred(ctx);
992 if (!mac_cred_check_enforce(cred)) {
993 return 0;
994 }
995 MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name);
996 return error;
997 }
998 int
999 mac_vnode_check_exchangedata(vfs_context_t ctx,
1000 struct vnode *v1, struct vnode *v2)
1001 {
1002 kauth_cred_t cred;
1003 int error;
1004
1005 #if SECURITY_MAC_CHECK_ENFORCE
1006 /* 21167099 - only check if we allow write */
1007 if (!mac_vnode_enforce) {
1008 return 0;
1009 }
1010 #endif
1011 cred = vfs_context_ucred(ctx);
1012 if (!mac_cred_check_enforce(cred)) {
1013 return 0;
1014 }
1015 MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label,
1016 v2, v2->v_label);
1017
1018 return error;
1019 }
1020
1021 #if 0
1022 int
1023 mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
1024 {
1025 kauth_cred_t cred;
1026 int error;
1027
1028 #if SECURITY_MAC_CHECK_ENFORCE
1029 /* 21167099 - only check if we allow write */
1030 if (!mac_vnode_enforce) {
1031 return 0;
1032 }
1033 #endif
1034 cred = vfs_context_ucred(ctx);
1035 if (!mac_cred_check_enforce(cred)) {
1036 return 0;
1037 }
1038 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
1039 return error;
1040 }
1041 #endif
1042
1043 int
1044 mac_vnode_check_getattr(vfs_context_t ctx, struct ucred *file_cred,
1045 struct vnode *vp, struct vnode_attr *va)
1046 {
1047 kauth_cred_t cred;
1048 int error;
1049
1050 #if SECURITY_MAC_CHECK_ENFORCE
1051 /* 21167099 - only check if we allow write */
1052 if (!mac_vnode_enforce) {
1053 return 0;
1054 }
1055 #endif
1056 cred = vfs_context_ucred(ctx);
1057 if (!mac_cred_check_enforce(cred)) {
1058 return 0;
1059 }
1060 MAC_CHECK(vnode_check_getattr, cred, file_cred, vp, vp->v_label, va);
1061 return error;
1062 }
1063
1064 int
1065 mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp,
1066 struct attrlist *alist)
1067 {
1068 kauth_cred_t cred;
1069 int error;
1070
1071 #if SECURITY_MAC_CHECK_ENFORCE
1072 /* 21167099 - only check if we allow write */
1073 if (!mac_vnode_enforce) {
1074 return 0;
1075 }
1076 #endif
1077 cred = vfs_context_ucred(ctx);
1078 if (!mac_cred_check_enforce(cred)) {
1079 return 0;
1080 }
1081 MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist);
1082
1083 /* Falsify results instead of returning error? */
1084 return error;
1085 }
1086
1087 int
1088 mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp,
1089 struct image_params *imgp)
1090 {
1091 kauth_cred_t cred;
1092 int error = 0;
1093
1094 #if SECURITY_MAC_CHECK_ENFORCE
1095 /* 21167099 - only check if we allow write */
1096 if (!mac_proc_enforce || !mac_vnode_enforce) {
1097 return 0;
1098 }
1099 #endif
1100
1101 cred = vfs_context_ucred(ctx);
1102
1103 /*
1104 * NB: Cannot use MAC_CHECK macro because we need a sequence point after
1105 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
1106 * spawnattrlen as an argument to the hook.
1107 */
1108 {
1109 struct mac_policy_conf *mpc;
1110 u_int i;
1111
1112 for (i = 0; i < mac_policy_list.staticmax; i++) {
1113 mpc = mac_policy_list.entries[i].mpc;
1114 if (mpc == NULL) {
1115 continue;
1116 }
1117
1118 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
1119 if (hook == NULL) {
1120 continue;
1121 }
1122
1123 size_t spawnattrlen = 0;
1124 void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen);
1125
1126 error = mac_error_select(
1127 hook(cred,
1128 vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp,
1129 imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags,
1130 spawnattr, spawnattrlen), error);
1131 }
1132 if (mac_policy_list_conditional_busy() != 0) {
1133 for (; i <= mac_policy_list.maxindex; i++) {
1134 mpc = mac_policy_list.entries[i].mpc;
1135 if (mpc == NULL) {
1136 continue;
1137 }
1138
1139 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
1140 if (hook == NULL) {
1141 continue;
1142 }
1143
1144 size_t spawnattrlen = 0;
1145 void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen);
1146
1147 error = mac_error_select(
1148 hook(cred,
1149 vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp,
1150 imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags,
1151 spawnattr, spawnattrlen), error);
1152 }
1153 mac_policy_list_unbusy();
1154 }
1155 }
1156
1157 return error;
1158 }
1159
1160 int
1161 mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp)
1162 {
1163 kauth_cred_t cred;
1164 int error;
1165
1166 #if SECURITY_MAC_CHECK_ENFORCE
1167 /* 21167099 - only check if we allow write */
1168 if (!mac_vnode_enforce) {
1169 return 0;
1170 }
1171 #endif
1172 cred = vfs_context_ucred(ctx);
1173 if (!mac_cred_check_enforce(cred)) {
1174 return 0;
1175 }
1176 MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label);
1177 return error;
1178 }
1179
1180 int
1181 mac_vnode_check_signature(struct vnode *vp, struct cs_blob *cs_blob,
1182 struct image_params *imgp,
1183 unsigned int *cs_flags, unsigned int *signer_type,
1184 int flags)
1185 {
1186 int error;
1187 char *fatal_failure_desc = NULL;
1188 size_t fatal_failure_desc_len = 0;
1189
1190 char *vn_path = NULL;
1191 vm_size_t vn_pathlen = MAXPATHLEN;
1192 cpu_type_t cpu_type = (imgp == NULL) ? CPU_TYPE_ANY : imgp->ip_origcputype;
1193
1194
1195 #if SECURITY_MAC_CHECK_ENFORCE
1196 /* 21167099 - only check if we allow write */
1197 if (!mac_proc_enforce || !mac_vnode_enforce) {
1198 return 0;
1199 }
1200 #endif
1201
1202 MAC_CHECK(vnode_check_signature, vp, vp->v_label, cpu_type, cs_blob,
1203 cs_flags, signer_type, flags, &fatal_failure_desc, &fatal_failure_desc_len);
1204
1205 if (fatal_failure_desc_len) {
1206 // A fatal code signature validation failure occured, formulate a crash
1207 // reason.
1208
1209 char const *path = NULL;
1210
1211 vn_path = (char *)kalloc(MAXPATHLEN);
1212 if (vn_path != NULL) {
1213 if (vn_getpath(vp, vn_path, (int*)&vn_pathlen) == 0) {
1214 path = vn_path;
1215 } else {
1216 path = "(get vnode path failed)";
1217 }
1218 } else {
1219 path = "(path alloc failed)";
1220 }
1221
1222 if (error == 0) {
1223 panic("mac_vnode_check_signature: MAC hook returned no error, "
1224 "but status is claimed to be fatal? "
1225 "path: '%s', fatal_failure_desc_len: %ld, fatal_failure_desc:\n%s\n",
1226 path, fatal_failure_desc_len, fatal_failure_desc);
1227 }
1228
1229 printf("mac_vnode_check_signature: %s: code signature validation failed fatally: %s",
1230 path, fatal_failure_desc);
1231
1232 if (imgp == NULL) {
1233 goto out;
1234 }
1235
1236 os_reason_t reason = os_reason_create(OS_REASON_CODESIGNING,
1237 CODESIGNING_EXIT_REASON_TASKGATED_INVALID_SIG);
1238
1239 if (reason == OS_REASON_NULL) {
1240 printf("mac_vnode_check_signature: %s: failure to allocate exit reason for validation failure: %s\n",
1241 path, fatal_failure_desc);
1242 goto out;
1243 }
1244
1245 imgp->ip_cs_error = reason;
1246 reason->osr_flags = (OS_REASON_FLAG_GENERATE_CRASH_REPORT |
1247 OS_REASON_FLAG_CONSISTENT_FAILURE);
1248
1249 if (fatal_failure_desc == NULL) {
1250 // This may happen if allocation for the buffer failed.
1251 printf("mac_vnode_check_signature: %s: fatal failure is missing its description.\n", path);
1252 } else {
1253 mach_vm_address_t data_addr = 0;
1254
1255 int reason_error = 0;
1256 int kcdata_error = 0;
1257
1258 if ((reason_error = os_reason_alloc_buffer_noblock(reason, kcdata_estimate_required_buffer_size
1259 (1, fatal_failure_desc_len))) == 0 &&
1260 (kcdata_error = kcdata_get_memory_addr(&reason->osr_kcd_descriptor,
1261 EXIT_REASON_USER_DESC, fatal_failure_desc_len,
1262 &data_addr)) == KERN_SUCCESS) {
1263 kern_return_t mc_error = kcdata_memcpy(&reason->osr_kcd_descriptor, (mach_vm_address_t)data_addr,
1264 fatal_failure_desc, fatal_failure_desc_len);
1265
1266 if (mc_error != KERN_SUCCESS) {
1267 printf("mac_vnode_check_signature: %s: failed to copy reason string "
1268 "(kcdata_memcpy error: %d, length: %ld)\n",
1269 path, mc_error, fatal_failure_desc_len);
1270 }
1271 } else {
1272 printf("mac_vnode_check_signature: %s: failed to allocate space for reason string "
1273 "(os_reason_alloc_buffer error: %d, kcdata error: %d, length: %ld)\n",
1274 path, reason_error, kcdata_error, fatal_failure_desc_len);
1275 }
1276 }
1277 }
1278
1279 out:
1280 if (vn_path) {
1281 kfree(vn_path, MAXPATHLEN);
1282 }
1283
1284 if (fatal_failure_desc_len > 0 && fatal_failure_desc != NULL) {
1285 kfree(fatal_failure_desc, fatal_failure_desc_len);
1286 }
1287
1288 return error;
1289 }
1290
1291 #if 0
1292 int
1293 mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
1294 {
1295 kauth_cred_t cred;
1296 int error;
1297
1298 #if SECURITY_MAC_CHECK_ENFORCE
1299 /* 21167099 - only check if we allow write */
1300 if (!mac_vnode_enforce) {
1301 return 0;
1302 }
1303 #endif
1304 cred = vfs_context_ucred(ctx);
1305 if (!mac_cred_check_enforce(cred)) {
1306 return 0;
1307 }
1308 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
1309 return error;
1310 }
1311 #endif
1312
1313 int
1314 mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp,
1315 const char *name, struct uio *uio)
1316 {
1317 kauth_cred_t cred;
1318 int error;
1319
1320 #if SECURITY_MAC_CHECK_ENFORCE
1321 /* 21167099 - only check if we allow write */
1322 if (!mac_vnode_enforce) {
1323 return 0;
1324 }
1325 #endif
1326 cred = vfs_context_ucred(ctx);
1327 if (!mac_cred_check_enforce(cred)) {
1328 return 0;
1329 }
1330 MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
1331 name, uio);
1332 return error;
1333 }
1334
1335 int
1336 mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd)
1337 {
1338 kauth_cred_t cred;
1339 int error;
1340
1341 #if SECURITY_MAC_CHECK_ENFORCE
1342 /* 21167099 - only check if we allow write */
1343 if (!mac_vnode_enforce) {
1344 return 0;
1345 }
1346 #endif
1347 cred = vfs_context_ucred(ctx);
1348 if (!mac_cred_check_enforce(cred)) {
1349 return 0;
1350 }
1351 MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd);
1352 return error;
1353 }
1354
1355 int
1356 mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred,
1357 struct knote *kn, struct vnode *vp)
1358 {
1359 kauth_cred_t cred;
1360 int error;
1361
1362 #if SECURITY_MAC_CHECK_ENFORCE
1363 /* 21167099 - only check if we allow write */
1364 if (!mac_vnode_enforce) {
1365 return 0;
1366 }
1367 #endif
1368 cred = vfs_context_ucred(ctx);
1369 if (!mac_cred_check_enforce(cred)) {
1370 return 0;
1371 }
1372 MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp,
1373 vp->v_label);
1374
1375 return error;
1376 }
1377
1378 int
1379 mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp,
1380 struct vnode *vp, struct componentname *cnp)
1381 {
1382 kauth_cred_t cred;
1383 int error;
1384
1385 #if SECURITY_MAC_CHECK_ENFORCE
1386 /* 21167099 - only check if we allow write */
1387 if (!mac_vnode_enforce) {
1388 return 0;
1389 }
1390 #endif
1391 cred = vfs_context_ucred(ctx);
1392 if (!mac_cred_check_enforce(cred)) {
1393 return 0;
1394 }
1395 MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
1396 vp->v_label, cnp);
1397 return error;
1398 }
1399
1400 int
1401 mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp)
1402 {
1403 kauth_cred_t cred;
1404 int error;
1405
1406 #if SECURITY_MAC_CHECK_ENFORCE
1407 /* 21167099 - only check if we allow write */
1408 if (!mac_vnode_enforce) {
1409 return 0;
1410 }
1411 #endif
1412 cred = vfs_context_ucred(ctx);
1413 if (!mac_cred_check_enforce(cred)) {
1414 return 0;
1415 }
1416 MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label);
1417 return error;
1418 }
1419
1420 int
1421 mac_vnode_check_lookup_preflight(vfs_context_t ctx, struct vnode *dvp,
1422 const char *path, size_t pathlen)
1423 {
1424 kauth_cred_t cred;
1425 int error;
1426
1427 #if SECURITY_MAC_CHECK_ENFORCE
1428 /* 21167099 - only check if we allow write */
1429 if (!mac_vnode_enforce) {
1430 return 0;
1431 }
1432 #endif
1433 cred = vfs_context_ucred(ctx);
1434 if (!mac_cred_check_enforce(cred)) {
1435 return 0;
1436 }
1437 MAC_CHECK(vnode_check_lookup_preflight, cred, dvp, dvp->v_label, path, pathlen);
1438 return error;
1439 }
1440
1441 int
1442 mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp,
1443 struct componentname *cnp)
1444 {
1445 kauth_cred_t cred;
1446 int error;
1447
1448 #if SECURITY_MAC_CHECK_ENFORCE
1449 /* 21167099 - only check if we allow write */
1450 if (!mac_vnode_enforce) {
1451 return 0;
1452 }
1453 #endif
1454 cred = vfs_context_ucred(ctx);
1455 if (!mac_cred_check_enforce(cred)) {
1456 return 0;
1457 }
1458 MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
1459 return error;
1460 }
1461
1462 int
1463 mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode)
1464 {
1465 kauth_cred_t cred;
1466 int error;
1467
1468 #if SECURITY_MAC_CHECK_ENFORCE
1469 /* 21167099 - only check if we allow write */
1470 if (!mac_vnode_enforce) {
1471 return 0;
1472 }
1473 #endif
1474 cred = vfs_context_ucred(ctx);
1475 if (!mac_cred_check_enforce(cred)) {
1476 return 0;
1477 }
1478 MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode);
1479 return error;
1480 }
1481
1482 int
1483 mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred,
1484 struct vnode *vp)
1485 {
1486 kauth_cred_t cred;
1487 int error;
1488
1489 #if SECURITY_MAC_CHECK_ENFORCE
1490 /* 21167099 - only check if we allow write */
1491 if (!mac_vnode_enforce) {
1492 return 0;
1493 }
1494 #endif
1495 cred = vfs_context_ucred(ctx);
1496 if (!mac_cred_check_enforce(cred)) {
1497 return 0;
1498 }
1499 MAC_CHECK(vnode_check_read, cred, file_cred, vp,
1500 vp->v_label);
1501
1502 return error;
1503 }
1504
1505 int
1506 mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp)
1507 {
1508 kauth_cred_t cred;
1509 int error;
1510
1511 #if SECURITY_MAC_CHECK_ENFORCE
1512 /* 21167099 - only check if we allow write */
1513 if (!mac_vnode_enforce) {
1514 return 0;
1515 }
1516 #endif
1517 cred = vfs_context_ucred(ctx);
1518 if (!mac_cred_check_enforce(cred)) {
1519 return 0;
1520 }
1521 MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
1522 return error;
1523 }
1524
1525 int
1526 mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp)
1527 {
1528 kauth_cred_t cred;
1529 int error;
1530
1531 #if SECURITY_MAC_CHECK_ENFORCE
1532 /* 21167099 - only check if we allow write */
1533 if (!mac_vnode_enforce) {
1534 return 0;
1535 }
1536 #endif
1537 cred = vfs_context_ucred(ctx);
1538 if (!mac_cred_check_enforce(cred)) {
1539 return 0;
1540 }
1541 MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
1542 return error;
1543 }
1544
1545 int
1546 mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp,
1547 struct label *newlabel)
1548 {
1549 kauth_cred_t cred;
1550 int error;
1551
1552 #if SECURITY_MAC_CHECK_ENFORCE
1553 /* 21167099 - only check if we allow write */
1554 if (!mac_vnode_enforce) {
1555 return 0;
1556 }
1557 #endif
1558 cred = vfs_context_ucred(ctx);
1559 if (!mac_cred_check_enforce(cred)) {
1560 return 0;
1561 }
1562 MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel);
1563
1564 return error;
1565 }
1566
1567 int
1568 mac_vnode_check_rename(vfs_context_t ctx, struct vnode *dvp,
1569 struct vnode *vp, struct componentname *cnp, struct vnode *tdvp,
1570 struct vnode *tvp, struct componentname *tcnp)
1571 {
1572 kauth_cred_t cred;
1573 int error;
1574
1575 #if SECURITY_MAC_CHECK_ENFORCE
1576 /* 21167099 - only check if we allow write */
1577 if (!mac_vnode_enforce) {
1578 return 0;
1579 }
1580 #endif
1581 cred = vfs_context_ucred(ctx);
1582 if (!mac_cred_check_enforce(cred)) {
1583 return 0;
1584 }
1585
1586 MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
1587 vp->v_label, cnp);
1588 if (error) {
1589 return error;
1590 }
1591
1592 MAC_CHECK(vnode_check_rename_to, cred, tdvp, tdvp->v_label, tvp,
1593 tvp != NULL ? tvp->v_label : NULL, dvp == tdvp, tcnp);
1594 if (error) {
1595 return error;
1596 }
1597
1598 MAC_CHECK(vnode_check_rename, cred, dvp, dvp->v_label, vp,
1599 vp->v_label, cnp, tdvp, tdvp->v_label, tvp,
1600 tvp != NULL ? tvp->v_label : NULL, tcnp);
1601 return error;
1602 }
1603
1604 int
1605 mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
1606 {
1607 kauth_cred_t cred;
1608 int error;
1609
1610 #if SECURITY_MAC_CHECK_ENFORCE
1611 /* 21167099 - only check if we allow write */
1612 if (!mac_vnode_enforce) {
1613 return 0;
1614 }
1615 #endif
1616 cred = vfs_context_ucred(ctx);
1617 if (!mac_cred_check_enforce(cred)) {
1618 return 0;
1619 }
1620 MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
1621 return error;
1622 }
1623
1624 int
1625 mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist)
1626 {
1627 kauth_cred_t cred;
1628 int error;
1629
1630 #if SECURITY_MAC_CHECK_ENFORCE
1631 /* 21167099 - only check if we allow write */
1632 if (!mac_vnode_enforce) {
1633 return 0;
1634 }
1635 #endif
1636 cred = vfs_context_ucred(ctx);
1637 if (!mac_cred_check_enforce(cred)) {
1638 return 0;
1639 }
1640 MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist);
1641 return error;
1642 }
1643
1644 int
1645 mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which)
1646 {
1647 kauth_cred_t cred;
1648 int error;
1649
1650 #if SECURITY_MAC_CHECK_ENFORCE
1651 /* 21167099 - only check if we allow write */
1652 if (!mac_vnode_enforce) {
1653 return 0;
1654 }
1655 #endif
1656 cred = vfs_context_ucred(ctx);
1657 if (!mac_cred_check_enforce(cred)) {
1658 return 0;
1659 }
1660 MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which);
1661 return error;
1662 }
1663
1664 int
1665 mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp,
1666 struct kauth_acl *acl)
1667 {
1668 kauth_cred_t cred;
1669 int error;
1670
1671 #if SECURITY_MAC_CHECK_ENFORCE
1672 /* 21167099 - only check if we allow write */
1673 if (!mac_vnode_enforce) {
1674 return 0;
1675 }
1676 #endif
1677 cred = vfs_context_ucred(ctx);
1678 if (!mac_cred_check_enforce(cred)) {
1679 return 0;
1680 }
1681 MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, acl);
1682 return error;
1683 }
1684
1685 int
1686 mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp,
1687 struct attrlist *alist)
1688 {
1689 kauth_cred_t cred;
1690 int error;
1691
1692 #if SECURITY_MAC_CHECK_ENFORCE
1693 /* 21167099 - only check if we allow write */
1694 if (!mac_vnode_enforce) {
1695 return 0;
1696 }
1697 #endif
1698 cred = vfs_context_ucred(ctx);
1699 if (!mac_cred_check_enforce(cred)) {
1700 return 0;
1701 }
1702 MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist);
1703 return error;
1704 }
1705
1706 int
1707 mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp,
1708 const char *name, struct uio *uio)
1709 {
1710 kauth_cred_t cred;
1711 int error;
1712
1713 #if SECURITY_MAC_CHECK_ENFORCE
1714 /* 21167099 - only check if we allow write */
1715 if (!mac_vnode_enforce) {
1716 return 0;
1717 }
1718 #endif
1719 cred = vfs_context_ucred(ctx);
1720 if (!mac_cred_check_enforce(cred)) {
1721 return 0;
1722 }
1723 MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
1724 name, uio);
1725 return error;
1726 }
1727
1728 int
1729 mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
1730 {
1731 kauth_cred_t cred;
1732 int error;
1733
1734 #if SECURITY_MAC_CHECK_ENFORCE
1735 /* 21167099 - only check if we allow write */
1736 if (!mac_vnode_enforce) {
1737 return 0;
1738 }
1739 #endif
1740 cred = vfs_context_ucred(ctx);
1741 if (!mac_cred_check_enforce(cred)) {
1742 return 0;
1743 }
1744 MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
1745 return error;
1746 }
1747
1748 int
1749 mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
1750 {
1751 kauth_cred_t cred;
1752 int error;
1753
1754 #if SECURITY_MAC_CHECK_ENFORCE
1755 /* 21167099 - only check if we allow write */
1756 if (!mac_vnode_enforce) {
1757 return 0;
1758 }
1759 #endif
1760 cred = vfs_context_ucred(ctx);
1761 if (!mac_cred_check_enforce(cred)) {
1762 return 0;
1763 }
1764 MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
1765 return error;
1766 }
1767
1768 int
1769 mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid,
1770 gid_t gid)
1771 {
1772 kauth_cred_t cred;
1773 int error;
1774
1775 #if SECURITY_MAC_CHECK_ENFORCE
1776 /* 21167099 - only check if we allow write */
1777 if (!mac_vnode_enforce) {
1778 return 0;
1779 }
1780 #endif
1781 cred = vfs_context_ucred(ctx);
1782 if (!mac_cred_check_enforce(cred)) {
1783 return 0;
1784 }
1785 MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid);
1786 return error;
1787 }
1788
1789 int
1790 mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp,
1791 struct timespec atime, struct timespec mtime)
1792 {
1793 kauth_cred_t cred;
1794 int error;
1795
1796 #if SECURITY_MAC_CHECK_ENFORCE
1797 /* 21167099 - only check if we allow write */
1798 if (!mac_vnode_enforce) {
1799 return 0;
1800 }
1801 #endif
1802 cred = vfs_context_ucred(ctx);
1803 if (!mac_cred_check_enforce(cred)) {
1804 return 0;
1805 }
1806 MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime,
1807 mtime);
1808 return error;
1809 }
1810
1811 int
1812 mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred,
1813 struct vnode *vp)
1814 {
1815 kauth_cred_t cred;
1816 int error;
1817
1818 #if SECURITY_MAC_CHECK_ENFORCE
1819 /* 21167099 - only check if we allow write */
1820 if (!mac_vnode_enforce) {
1821 return 0;
1822 }
1823 #endif
1824 cred = vfs_context_ucred(ctx);
1825 if (!mac_cred_check_enforce(cred)) {
1826 return 0;
1827 }
1828 MAC_CHECK(vnode_check_stat, cred, file_cred, vp,
1829 vp->v_label);
1830 return error;
1831 }
1832
1833 int
1834 mac_vnode_check_trigger_resolve(vfs_context_t ctx, struct vnode *dvp,
1835 struct componentname *cnp)
1836 {
1837 kauth_cred_t cred;
1838 int error;
1839
1840 #if SECURITY_MAC_CHECK_ENFORCE
1841 /* 21167099 - only check if we allow write */
1842 if (!mac_vnode_enforce) {
1843 return 0;
1844 }
1845 #endif
1846 cred = vfs_context_ucred(ctx);
1847 if (!mac_cred_check_enforce(cred)) {
1848 return 0;
1849 }
1850 MAC_CHECK(vnode_check_trigger_resolve, cred, dvp, dvp->v_label, cnp);
1851 return error;
1852 }
1853
1854 int
1855 mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred,
1856 struct vnode *vp)
1857 {
1858 kauth_cred_t cred;
1859 int error;
1860
1861 #if SECURITY_MAC_CHECK_ENFORCE
1862 /* 21167099 - only check if we allow write */
1863 if (!mac_vnode_enforce) {
1864 return 0;
1865 }
1866 #endif
1867 cred = vfs_context_ucred(ctx);
1868 if (!mac_cred_check_enforce(cred)) {
1869 return 0;
1870 }
1871 MAC_CHECK(vnode_check_truncate, cred, file_cred, vp,
1872 vp->v_label);
1873
1874 return error;
1875 }
1876
1877 int
1878 mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred,
1879 struct vnode *vp)
1880 {
1881 kauth_cred_t cred;
1882 int error;
1883
1884 #if SECURITY_MAC_CHECK_ENFORCE
1885 /* 21167099 - only check if we allow write */
1886 if (!mac_vnode_enforce) {
1887 return 0;
1888 }
1889 #endif
1890 cred = vfs_context_ucred(ctx);
1891 if (!mac_cred_check_enforce(cred)) {
1892 return 0;
1893 }
1894 MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label);
1895
1896 return error;
1897 }
1898
1899 int
1900 mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp,
1901 struct componentname *cnp, struct vnode_attr *vap)
1902 {
1903 kauth_cred_t cred;
1904 int error;
1905
1906 #if SECURITY_MAC_CHECK_ENFORCE
1907 /* 21167099 - only check if we allow write */
1908 if (!mac_vnode_enforce) {
1909 return 0;
1910 }
1911 #endif
1912 cred = vfs_context_ucred(ctx);
1913 if (!mac_cred_check_enforce(cred)) {
1914 return 0;
1915 }
1916 MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap);
1917 return error;
1918 }
1919
1920 int
1921 mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp, struct socket *so)
1922 {
1923 kauth_cred_t cred;
1924 int error;
1925
1926 #if SECURITY_MAC_CHECK_ENFORCE
1927 /* 21167099 - only check if we allow write */
1928 if (!mac_vnode_enforce) {
1929 return 0;
1930 }
1931 #endif
1932 cred = vfs_context_ucred(ctx);
1933 if (!mac_cred_check_enforce(cred)) {
1934 return 0;
1935 }
1936 MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label, (socket_t) so);
1937 return error;
1938 }
1939
1940 void
1941 mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel)
1942 {
1943 kauth_cred_t cred = vfs_context_ucred(ctx);
1944 struct label *tmpl = NULL;
1945
1946 if (vp->v_label == NULL) {
1947 tmpl = mac_vnode_label_alloc();
1948 }
1949
1950 vnode_lock(vp);
1951
1952 /* recheck after lock */
1953 if (vp->v_label == NULL) {
1954 vp->v_label = tmpl;
1955 tmpl = NULL;
1956 }
1957
1958 MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel);
1959 vnode_unlock(vp);
1960
1961 if (tmpl != NULL) {
1962 mac_vnode_label_free(tmpl);
1963 }
1964 }
1965
1966 int
1967 mac_vnode_find_sigs(struct proc *p, struct vnode *vp, off_t offset)
1968 {
1969 int error;
1970
1971 #if SECURITY_MAC_CHECK_ENFORCE
1972 /* 21167099 - only check if we allow write */
1973 if (!mac_proc_enforce || !mac_vnode_enforce) {
1974 return 0;
1975 }
1976 #endif
1977
1978 MAC_CHECK(vnode_find_sigs, p, vp, offset, vp->v_label);
1979
1980 return error;
1981 }
1982
1983 void
1984 mac_mount_label_associate(vfs_context_t ctx, struct mount *mp)
1985 {
1986 kauth_cred_t cred = vfs_context_ucred(ctx);
1987
1988 /* XXX: eventually this logic may be handled by the policy? */
1989
1990 /* We desire MULTILABEL for the root filesystem. */
1991 if ((mp->mnt_flag & MNT_ROOTFS) &&
1992 (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0)) {
1993 mp->mnt_flag |= MNT_MULTILABEL;
1994 }
1995
1996 /* MULTILABEL on DEVFS. */
1997 if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0) {
1998 mp->mnt_flag |= MNT_MULTILABEL;
1999 }
2000
2001 /* MULTILABEL on FDESC pseudo-filesystem. */
2002 if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0) {
2003 mp->mnt_flag |= MNT_MULTILABEL;
2004 }
2005
2006 /* MULTILABEL on all NFS filesystems. */
2007 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0) {
2008 mp->mnt_flag |= MNT_MULTILABEL;
2009 }
2010
2011 /* MULTILABEL on all AFP filesystems. */
2012 if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0) {
2013 mp->mnt_flag |= MNT_MULTILABEL;
2014 }
2015
2016 if (mp->mnt_vtable != NULL) {
2017 /* Any filesystem that supports native XATTRs. */
2018 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR)) {
2019 mp->mnt_flag |= MNT_MULTILABEL;
2020 }
2021
2022 /* Filesystem does not support multilabel. */
2023 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) &&
2024 (mp->mnt_flag & MNT_MULTILABEL)) {
2025 mp->mnt_flag &= ~MNT_MULTILABEL;
2026 }
2027 }
2028
2029 MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel);
2030 #if DEBUG
2031 printf("MAC Framework enabling %s support: %s -> %s (%s)\n",
2032 mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel",
2033 mp->mnt_vfsstat.f_mntfromname,
2034 mp->mnt_vfsstat.f_mntonname,
2035 mp->mnt_vfsstat.f_fstypename);
2036 #endif
2037 }
2038
2039 int
2040 mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp,
2041 struct componentname *cnp, const char *vfc_name)
2042 {
2043 kauth_cred_t cred;
2044 int error;
2045
2046 #if SECURITY_MAC_CHECK_ENFORCE
2047 /* 21167099 - only check if we allow write */
2048 if (!mac_vnode_enforce) {
2049 return 0;
2050 }
2051 #endif
2052 cred = vfs_context_ucred(ctx);
2053 if (!mac_cred_check_enforce(cred)) {
2054 return 0;
2055 }
2056 MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name);
2057
2058 return error;
2059 }
2060
2061 int
2062 mac_mount_check_snapshot_create(vfs_context_t ctx, struct mount *mp,
2063 const char *name)
2064 {
2065 kauth_cred_t cred;
2066 int error;
2067
2068 #if SECURITY_MAC_CHECK_ENFORCE
2069 /* 21167099 - only check if we allow write */
2070 if (!mac_vnode_enforce) {
2071 return 0;
2072 }
2073 #endif
2074 cred = vfs_context_ucred(ctx);
2075 if (!mac_cred_check_enforce(cred)) {
2076 return 0;
2077 }
2078 MAC_CHECK(mount_check_snapshot_create, cred, mp, name);
2079 return error;
2080 }
2081
2082 int
2083 mac_mount_check_snapshot_delete(vfs_context_t ctx, struct mount *mp,
2084 const char *name)
2085 {
2086 kauth_cred_t cred;
2087 int error;
2088
2089 #if SECURITY_MAC_CHECK_ENFORCE
2090 /* 21167099 - only check if we allow write */
2091 if (!mac_vnode_enforce) {
2092 return 0;
2093 }
2094 #endif
2095 cred = vfs_context_ucred(ctx);
2096 if (!mac_cred_check_enforce(cred)) {
2097 return 0;
2098 }
2099 MAC_CHECK(mount_check_snapshot_delete, cred, mp, name);
2100 return error;
2101 }
2102
2103 int
2104 mac_mount_check_snapshot_revert(vfs_context_t ctx, struct mount *mp,
2105 const char *name)
2106 {
2107 kauth_cred_t cred;
2108 int error;
2109
2110 #if SECURITY_MAC_CHECK_ENFORCE
2111 /* 21167099 - only check if we allow write */
2112 if (!mac_vnode_enforce) {
2113 return 0;
2114 }
2115 #endif
2116 cred = vfs_context_ucred(ctx);
2117 if (!mac_cred_check_enforce(cred)) {
2118 return 0;
2119 }
2120 MAC_CHECK(mount_check_snapshot_revert, cred, mp, name);
2121 return error;
2122 }
2123
2124 int
2125 mac_mount_check_remount(vfs_context_t ctx, struct mount *mp)
2126 {
2127 kauth_cred_t cred;
2128 int error;
2129
2130 #if SECURITY_MAC_CHECK_ENFORCE
2131 /* 21167099 - only check if we allow write */
2132 if (!mac_vnode_enforce) {
2133 return 0;
2134 }
2135 #endif
2136 cred = vfs_context_ucred(ctx);
2137 if (!mac_cred_check_enforce(cred)) {
2138 return 0;
2139 }
2140 MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel);
2141
2142 return error;
2143 }
2144
2145 int
2146 mac_mount_check_umount(vfs_context_t ctx, struct mount *mp)
2147 {
2148 kauth_cred_t cred;
2149 int error;
2150
2151 #if SECURITY_MAC_CHECK_ENFORCE
2152 /* 21167099 - only check if we allow write */
2153 if (!mac_vnode_enforce) {
2154 return 0;
2155 }
2156 #endif
2157 cred = vfs_context_ucred(ctx);
2158 if (!mac_cred_check_enforce(cred)) {
2159 return 0;
2160 }
2161 MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel);
2162
2163 return error;
2164 }
2165
2166 int
2167 mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp,
2168 struct vfs_attr *vfa)
2169 {
2170 kauth_cred_t cred;
2171 int error;
2172
2173 #if SECURITY_MAC_CHECK_ENFORCE
2174 /* 21167099 - only check if we allow write */
2175 if (!mac_vnode_enforce) {
2176 return 0;
2177 }
2178 #endif
2179 cred = vfs_context_ucred(ctx);
2180 if (!mac_cred_check_enforce(cred)) {
2181 return 0;
2182 }
2183 MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa);
2184 return error;
2185 }
2186
2187 int
2188 mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp,
2189 struct vfs_attr *vfa)
2190 {
2191 kauth_cred_t cred;
2192 int error;
2193
2194 #if SECURITY_MAC_CHECK_ENFORCE
2195 /* 21167099 - only check if we allow write */
2196 if (!mac_vnode_enforce) {
2197 return 0;
2198 }
2199 #endif
2200 cred = vfs_context_ucred(ctx);
2201 if (!mac_cred_check_enforce(cred)) {
2202 return 0;
2203 }
2204 MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa);
2205 return error;
2206 }
2207
2208 int
2209 mac_mount_check_stat(vfs_context_t ctx, struct mount *mount)
2210 {
2211 kauth_cred_t cred;
2212 int error;
2213
2214 #if SECURITY_MAC_CHECK_ENFORCE
2215 /* 21167099 - only check if we allow write */
2216 if (!mac_vnode_enforce) {
2217 return 0;
2218 }
2219 #endif
2220 cred = vfs_context_ucred(ctx);
2221 if (!mac_cred_check_enforce(cred)) {
2222 return 0;
2223 }
2224 MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel);
2225
2226 return error;
2227 }
2228
2229 int
2230 mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount)
2231 {
2232 kauth_cred_t cred;
2233 int error;
2234
2235 #if SECURITY_MAC_CHECK_ENFORCE
2236 /* 21167099 - only check if we allow write */
2237 if (!mac_vnode_enforce) {
2238 return 0;
2239 }
2240 #endif
2241 cred = vfs_context_ucred(ctx);
2242 if (!mac_cred_check_enforce(cred)) {
2243 return 0;
2244 }
2245 MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel);
2246
2247 return error;
2248 }
2249
2250 int
2251 mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd)
2252 {
2253 kauth_cred_t cred;
2254 int error;
2255
2256 #if SECURITY_MAC_CHECK_ENFORCE
2257 /* 21167099 - only check if we allow write */
2258 if (!mac_vnode_enforce) {
2259 return 0;
2260 }
2261 #endif
2262 cred = vfs_context_ucred(ctx);
2263 if (!mac_cred_check_enforce(cred)) {
2264 return 0;
2265 }
2266 MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd);
2267
2268 return error;
2269 }
2270
2271 void
2272 mac_devfs_label_associate_device(dev_t dev, struct devnode *de,
2273 const char *fullpath)
2274 {
2275 #if SECURITY_MAC_CHECK_ENFORCE
2276 /* 21167099 - only check if we allow write */
2277 if (!mac_device_enforce) {
2278 return;
2279 }
2280 #endif
2281
2282 MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label,
2283 fullpath);
2284 }
2285
2286 void
2287 mac_devfs_label_associate_directory(const char *dirname, int dirnamelen,
2288 struct devnode *de, const char *fullpath)
2289 {
2290 #if SECURITY_MAC_CHECK_ENFORCE
2291 /* 21167099 - only check if we allow write */
2292 if (!mac_device_enforce) {
2293 return;
2294 }
2295 #endif
2296
2297 MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de,
2298 de->dn_label, fullpath);
2299 }
2300
2301 int
2302 vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context)
2303 {
2304 int error;
2305
2306 #if SECURITY_MAC_CHECK_ENFORCE
2307 /* 21167099 - only check if we allow write */
2308 if (!mac_vnode_enforce) {
2309 return 0;
2310 }
2311 #endif
2312 if (!mac_label_vnodes) {
2313 return 0;
2314 }
2315
2316 if (vp->v_mount == NULL) {
2317 printf("vn_setlabel: null v_mount\n");
2318 if (vp->v_type != VNON) {
2319 printf("vn_setlabel: null v_mount with non-VNON\n");
2320 }
2321 return EBADF;
2322 }
2323
2324 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
2325 return ENOTSUP;
2326 }
2327
2328 /*
2329 * Multi-phase commit. First check the policies to confirm the
2330 * change is OK. Then commit via the filesystem. Finally,
2331 * update the actual vnode label. Question: maybe the filesystem
2332 * should update the vnode at the end as part of VNOP_SETLABEL()?
2333 */
2334 error = mac_vnode_check_label_update(context, vp, intlabel);
2335 if (error) {
2336 return error;
2337 }
2338
2339 error = VNOP_SETLABEL(vp, intlabel, context);
2340 if (error == ENOTSUP) {
2341 error = mac_vnode_label_store(context, vp,
2342 intlabel);
2343 if (error) {
2344 printf("%s: mac_vnode_label_store failed %d\n",
2345 __func__, error);
2346 return error;
2347 }
2348 mac_vnode_label_update(context, vp, intlabel);
2349 } else if (error) {
2350 printf("vn_setlabel: vop setlabel failed %d\n", error);
2351 return error;
2352 }
2353
2354 return 0;
2355 }
2356
2357 int
2358 mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
2359 struct vnode *vp, vfs_context_t ctx)
2360 {
2361 struct fileproc *fp;
2362 #if CONFIG_MACF_SOCKET_SUBSET
2363 struct socket *so;
2364 #endif
2365 struct pipe *cpipe;
2366 struct vnode *fvp;
2367 struct proc *p;
2368 int error;
2369
2370 error = 0;
2371
2372 /*
2373 * If no backing file, let the policy choose which label to use.
2374 */
2375 if (fnp->fd_fd == -1) {
2376 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
2377 mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label);
2378 return 0;
2379 }
2380
2381 p = vfs_context_proc(ctx);
2382 error = fp_lookup(p, fnp->fd_fd, &fp, 0);
2383 if (error) {
2384 return error;
2385 }
2386
2387 if (fp->f_fglob == NULL) {
2388 error = EBADF;
2389 goto out;
2390 }
2391
2392 switch (FILEGLOB_DTYPE(fp->f_fglob)) {
2393 case DTYPE_VNODE:
2394 fvp = (struct vnode *)fp->f_fglob->fg_data;
2395 if ((error = vnode_getwithref(fvp))) {
2396 goto out;
2397 }
2398 MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label);
2399 (void)vnode_put(fvp);
2400 break;
2401 #if CONFIG_MACF_SOCKET_SUBSET
2402 case DTYPE_SOCKET:
2403 so = (struct socket *)fp->f_fglob->fg_data;
2404 socket_lock(so, 1);
2405 MAC_PERFORM(vnode_label_associate_socket,
2406 vfs_context_ucred(ctx), (socket_t)so, so->so_label,
2407 vp, vp->v_label);
2408 socket_unlock(so, 1);
2409 break;
2410 #endif
2411 case DTYPE_PSXSHM:
2412 pshm_label_associate(fp, vp, ctx);
2413 break;
2414 case DTYPE_PSXSEM:
2415 psem_label_associate(fp, vp, ctx);
2416 break;
2417 case DTYPE_PIPE:
2418 cpipe = (struct pipe *)fp->f_fglob->fg_data;
2419 /* kern/sys_pipe.c:pipe_select() suggests this test. */
2420 if (cpipe == (struct pipe *)-1) {
2421 error = EINVAL;
2422 goto out;
2423 }
2424 PIPE_LOCK(cpipe);
2425 MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx),
2426 cpipe, cpipe->pipe_label, vp, vp->v_label);
2427 PIPE_UNLOCK(cpipe);
2428 break;
2429 case DTYPE_KQUEUE:
2430 case DTYPE_FSEVENTS:
2431 case DTYPE_ATALK:
2432 case DTYPE_NETPOLICY:
2433 default:
2434 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
2435 mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label,
2436 vp, vp->v_label);
2437 break;
2438 }
2439 out:
2440 fp_drop(p, fnp->fd_fd, fp, 0);
2441 return error;
2442 }