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