]> git.saurik.com Git - apple/xnu.git/blob - security/mac_vfs.c
xnu-2782.20.48.tar.gz
[apple/xnu.git] / security / mac_vfs.c
1 /*
2 * Copyright (c) 2007 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 <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/kernel.h>
68 #include <sys/proc.h>
69 #include <sys/kauth.h>
70
71 #include <sys/file_internal.h>
72 #include <sys/imgact.h>
73 #include <sys/namei.h>
74 #include <sys/mount_internal.h>
75 #include <sys/pipe.h>
76 #include <sys/posix_sem.h>
77 #include <sys/posix_shm.h>
78 #include <sys/uio_internal.h>
79 #include <sys/vnode_internal.h>
80
81 #include <miscfs/devfs/devfsdefs.h>
82 #include <miscfs/devfs/fdesc.h>
83
84 #include <security/mac_internal.h>
85
86 /* convert {R,W,X}_OK values to V{READ,WRITE,EXEC} */
87 #define ACCESS_MODE_TO_VNODE_MASK(m) (m << 6)
88
89 static struct label *
90 mac_devfsdirent_label_alloc(void)
91 {
92 struct label *label;
93
94 label = mac_labelzone_alloc(MAC_WAITOK);
95 if (label == NULL)
96 return (NULL);
97 MAC_PERFORM(devfs_label_init, label);
98 return (label);
99 }
100
101 void
102 mac_devfs_label_init(struct devnode *de)
103 {
104
105 de->dn_label = mac_devfsdirent_label_alloc();
106 }
107
108 static struct label *
109 mac_mount_label_alloc(void)
110 {
111 struct label *label;
112
113 label = mac_labelzone_alloc(MAC_WAITOK);
114 if (label == NULL)
115 return (NULL);
116 MAC_PERFORM(mount_label_init, label);
117 return (label);
118 }
119
120 void
121 mac_mount_label_init(struct mount *mp)
122 {
123
124 mp->mnt_mntlabel = mac_mount_label_alloc();
125 }
126
127 struct label *
128 mac_vnode_label_alloc(void)
129 {
130 struct label *label;
131
132 label = mac_labelzone_alloc(MAC_WAITOK);
133 if (label == NULL)
134 return (NULL);
135 MAC_PERFORM(vnode_label_init, label);
136 return (label);
137 }
138
139 void
140 mac_vnode_label_init(vnode_t vp)
141 {
142 vp->v_label = mac_vnode_label_alloc();
143 }
144
145 int
146 mac_vnode_label_init_needed(vnode_t vp)
147 {
148 return (mac_label_vnodes != 0 && vp->v_label == NULL);
149 }
150
151 /*
152 * vnode labels are allocated at the same time as vnodes, but vnodes are never
153 * freed. Instead, we want to remove any sensitive information before putting
154 * them on the free list for reuse.
155 */
156 void
157 mac_vnode_label_recycle(vnode_t vp)
158 {
159
160 MAC_PERFORM(vnode_label_recycle, vp->v_label);
161 }
162
163 static void
164 mac_devfs_label_free(struct label *label)
165 {
166 MAC_PERFORM(devfs_label_destroy, label);
167 mac_labelzone_free(label);
168 }
169
170 void
171 mac_devfs_label_destroy(struct devnode *de)
172 {
173 if (de->dn_label != NULL) {
174 mac_devfs_label_free(de->dn_label);
175 de->dn_label = NULL;
176 }
177 }
178
179 static void
180 mac_mount_label_free(struct label *label)
181 {
182
183 MAC_PERFORM(mount_label_destroy, label);
184 mac_labelzone_free(label);
185 }
186
187 void
188 mac_mount_label_destroy(struct mount *mp)
189 {
190 if (mp->mnt_mntlabel != NULL) {
191 mac_mount_label_free(mp->mnt_mntlabel);
192 mp->mnt_mntlabel = NULL;
193 }
194 }
195
196 void
197 mac_vnode_label_free(struct label *label)
198 {
199 MAC_PERFORM(vnode_label_destroy, label);
200 mac_labelzone_free(label);
201 }
202
203 #ifndef __APPLE__
204 void
205 mac_vnode_label_destroy(struct vnode *vp)
206 {
207 if (vp->v_label != NULL) {
208 mac_vnode_label_free(vp->v_label);
209 vp->v_label = NULL;
210 }
211 }
212 #endif
213
214 void
215 mac_vnode_label_copy(struct label *src, struct label *dest)
216 {
217 if (src == NULL) {
218 MAC_PERFORM(vnode_label_init, dest);
219 } else {
220 MAC_PERFORM(vnode_label_copy, src, dest);
221 }
222 }
223
224 int
225 mac_vnode_label_externalize_audit(struct vnode *vp, struct mac *mac)
226 {
227 int error;
228
229 /* It is assumed that any necessary vnode locking is done on entry */
230 error = MAC_EXTERNALIZE_AUDIT(vnode, vp->v_label,
231 mac->m_string, mac->m_buflen);
232
233 return (error);
234 }
235
236 int
237 mac_vnode_label_externalize(struct label *label, char *elements,
238 char *outbuf, size_t outbuflen, int flags __unused)
239 {
240 int error;
241
242 error = MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
243
244 return (error);
245 }
246
247 int
248 mac_vnode_label_internalize(struct label *label, char *string)
249 {
250 int error;
251
252 error = MAC_INTERNALIZE(vnode, label, string);
253
254 return (error);
255 }
256
257 int
258 mac_mount_label_internalize(struct label *label, char *string)
259 {
260 int error;
261
262 error = MAC_INTERNALIZE(mount, label, string);
263
264 return (error);
265 }
266
267 int
268 mac_mount_label_externalize(struct label *label, char *elements,
269 char *outbuf, size_t outbuflen)
270 {
271 int error;
272
273 error = MAC_EXTERNALIZE(mount, label, elements, outbuf, outbuflen);
274
275 return (error);
276 }
277
278 void
279 mac_devfs_label_copy(struct label *src, struct label *dest)
280 {
281 if (!mac_device_enforce)
282 return;
283
284 MAC_PERFORM(devfs_label_copy, src, dest);
285 }
286
287 void
288 mac_devfs_label_update(struct mount *mp, struct devnode *de,
289 struct vnode *vp)
290 {
291
292 if (!mac_device_enforce)
293 return;
294
295 MAC_PERFORM(devfs_label_update, mp, de, de->dn_label, vp,
296 vp->v_label);
297 }
298
299 int
300 mac_vnode_label_associate(struct mount *mp, struct vnode *vp, vfs_context_t ctx)
301 {
302 struct devnode *dnp;
303 struct fdescnode *fnp;
304 int error = 0;
305
306 if (!mac_vnode_enforce)
307 return (error);
308
309 /* XXX: should not inspect v_tag in kernel! */
310 switch (vp->v_tag) {
311 case VT_DEVFS:
312 dnp = VTODN(vp);
313 mac_vnode_label_associate_devfs(mp, dnp, vp);
314 break;
315 case VT_FDESC:
316 fnp = VTOFDESC(vp);
317 error = mac_vnode_label_associate_fdesc(mp, fnp, vp, ctx);
318 break;
319 default:
320 error = mac_vnode_label_associate_extattr(mp, vp);
321 break;
322 }
323
324 return (error);
325 }
326
327 void
328 mac_vnode_label_associate_devfs(struct mount *mp, struct devnode *de,
329 struct vnode *vp)
330 {
331 if (!mac_device_enforce)
332 return;
333
334 MAC_PERFORM(vnode_label_associate_devfs,
335 mp, mp ? mp->mnt_mntlabel : NULL,
336 de, de->dn_label,
337 vp, vp->v_label);
338 }
339
340 int
341 mac_vnode_label_associate_extattr(struct mount *mp, struct vnode *vp)
342 {
343 int error;
344
345 MAC_CHECK(vnode_label_associate_extattr, mp, mp->mnt_mntlabel, vp,
346 vp->v_label);
347
348 return (error);
349 }
350
351 void
352 mac_vnode_label_associate_singlelabel(struct mount *mp, struct vnode *vp)
353 {
354
355 if (!mac_vnode_enforce || !mac_label_vnodes)
356 return;
357
358 MAC_PERFORM(vnode_label_associate_singlelabel, mp,
359 mp ? mp->mnt_mntlabel : NULL, vp, vp->v_label);
360 }
361
362 int
363 mac_vnode_notify_create(vfs_context_t ctx, struct mount *mp,
364 struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
365 {
366 kauth_cred_t cred;
367 int error;
368
369 if (!mac_vnode_enforce ||
370 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
371 return (0);
372
373 cred = vfs_context_ucred(ctx);
374 MAC_CHECK(vnode_notify_create, cred, mp, mp->mnt_mntlabel,
375 dvp, dvp->v_label, vp, vp->v_label, cnp);
376
377 return (error);
378 }
379
380 void
381 mac_vnode_notify_rename(vfs_context_t ctx, struct vnode *vp,
382 struct vnode *dvp, struct componentname *cnp)
383 {
384 kauth_cred_t cred;
385
386 if (!mac_vnode_enforce ||
387 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
388 return;
389
390 cred = vfs_context_ucred(ctx);
391 MAC_PERFORM(vnode_notify_rename, cred, vp, vp->v_label,
392 dvp, dvp->v_label, cnp);
393 }
394
395 void
396 mac_vnode_notify_open(vfs_context_t ctx, struct vnode *vp, int acc_flags)
397 {
398 kauth_cred_t cred;
399
400 if (!mac_vnode_enforce ||
401 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
402 return;
403
404 cred = vfs_context_ucred(ctx);
405 MAC_PERFORM(vnode_notify_open, cred, vp, vp->v_label, acc_flags);
406 }
407
408 void
409 mac_vnode_notify_link(vfs_context_t ctx, struct vnode *vp,
410 struct vnode *dvp, struct componentname *cnp)
411 {
412 kauth_cred_t cred;
413
414 if (!mac_vnode_enforce ||
415 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
416 return;
417
418 cred = vfs_context_ucred(ctx);
419 MAC_PERFORM(vnode_notify_link, cred, dvp, dvp->v_label, vp, vp->v_label, cnp);
420 }
421
422 /*
423 * Extended attribute 'name' was updated via
424 * vn_setxattr() or vn_removexattr(). Allow the
425 * policy to update the vnode label.
426 */
427 void
428 mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp,
429 const char *name)
430 {
431 int error = 0;
432
433 if (!mac_vnode_enforce || !mac_label_vnodes)
434 return;
435
436 MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp,
437 vp->v_label, name);
438 if (error == 0)
439 return;
440
441 vnode_lock(vp);
442 vnode_relabel(vp);
443 vnode_unlock(vp);
444 return;
445 }
446
447 static int
448 mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp,
449 struct label *intlabel)
450 {
451 kauth_cred_t cred;
452 int error;
453
454 if (!mac_vnode_enforce || !mac_label_vnodes ||
455 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
456 return 0;
457
458 cred = vfs_context_ucred(ctx);
459 MAC_CHECK(vnode_label_store, cred, vp, vp->v_label, intlabel);
460
461 return (error);
462 }
463
464 void
465 mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp, off_t offset,
466 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl, u_int *csflags,
467 void *macextensions, int *disjoint, int *labelupdateerror)
468 {
469 kauth_cred_t cred;
470 *disjoint = 0;
471 int error;
472 posix_cred_t pcred = posix_cred_get(new);
473
474 if (!mac_proc_enforce && !mac_vnode_enforce)
475 return;
476
477 /* mark the new cred to indicate "matching" includes the label */
478 pcred->cr_flags |= CRF_MAC_ENFORCE;
479
480 cred = vfs_context_ucred(ctx);
481
482 /*
483 * NB: Cannot use MAC_CHECK macro because we need a sequence point after
484 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
485 * spawnattrlen as an argument to the hook.
486 */
487 {
488 struct mac_policy_conf *mpc;
489 u_int i;
490
491 error = 0;
492 for (i = 0; i< mac_policy_list.staticmax; i++) {
493 mpc = mac_policy_list.entries[i].mpc;
494 if (mpc == NULL)
495 continue;
496
497 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
498 if (hook == NULL)
499 continue;
500
501 size_t spawnattrlen = 0;
502 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
503
504 error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp,
505 vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint),
506 error);
507 }
508 if (mac_policy_list_conditional_busy() != 0) {
509 for (; i <= mac_policy_list.maxindex; i++) {
510 mpc = mac_policy_list.entries[i].mpc;
511 if (mpc == NULL)
512 continue;
513
514 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
515 if (hook == NULL)
516 continue;
517
518 size_t spawnattrlen = 0;
519 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
520
521 error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp,
522 vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint),
523 error);
524 }
525 mac_policy_list_unbusy();
526 }
527 }
528 *labelupdateerror = error;
529 }
530
531 int
532 mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp, off_t offset,
533 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel,
534 struct proc *p, void *macextensions)
535 {
536 kauth_cred_t cred;
537 int result = 0;
538
539 if (!mac_proc_enforce && !mac_vnode_enforce)
540 return result;
541
542 cred = vfs_context_ucred(ctx);
543
544 /*
545 * NB: Cannot use MAC_BOOLEAN macro because we need a sequence point after
546 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
547 * spawnattrlen as an argument to the hook.
548 */
549 {
550 struct mac_policy_conf *mpc;
551 u_int i;
552
553 for (i = 0; i< mac_policy_list.staticmax; i++) {
554 mpc = mac_policy_list.entries[i].mpc;
555 if (mpc == NULL)
556 continue;
557
558 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
559 if (hook == NULL)
560 continue;
561
562 size_t spawnattrlen = 0;
563 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
564
565 result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
566 }
567 if (mac_policy_list_conditional_busy() != 0) {
568 for (; i <= mac_policy_list.maxindex; i++) {
569 mpc = mac_policy_list.entries[i].mpc;
570 if (mpc == NULL)
571 continue;
572
573 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
574 if (hook == NULL)
575 continue;
576
577 size_t spawnattrlen = 0;
578 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
579
580 result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
581 }
582 mac_policy_list_unbusy();
583 }
584 }
585
586 return (result);
587 }
588
589 int
590 mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp,
591 int acc_mode)
592 {
593 kauth_cred_t cred;
594 int error;
595 int mask;
596
597 if (!mac_vnode_enforce ||
598 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
599 return 0;
600
601 cred = vfs_context_ucred(ctx);
602 /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */
603 mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode);
604 MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask);
605 return (error);
606 }
607
608 int
609 mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp)
610 {
611 kauth_cred_t cred;
612 int error;
613
614 if (!mac_vnode_enforce ||
615 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
616 return (0);
617
618 cred = vfs_context_ucred(ctx);
619 MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
620 return (error);
621 }
622
623 int
624 mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp,
625 struct componentname *cnp)
626 {
627 kauth_cred_t cred;
628 int error;
629
630 if (!mac_vnode_enforce ||
631 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
632 return (0);
633
634 cred = vfs_context_ucred(ctx);
635 MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp);
636 return (error);
637 }
638
639 int
640 mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp,
641 struct componentname *cnp, struct vnode_attr *vap)
642 {
643 kauth_cred_t cred;
644 int error;
645
646 if (!mac_vnode_enforce ||
647 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
648 return (0);
649
650 cred = vfs_context_ucred(ctx);
651 MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
652 return (error);
653 }
654
655 int
656 mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp,
657 struct componentname *cnp)
658 {
659 kauth_cred_t cred;
660 int error;
661
662 if (!mac_vnode_enforce ||
663 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
664 return (0);
665
666 cred = vfs_context_ucred(ctx);
667 MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
668 vp->v_label, cnp);
669 return (error);
670 }
671 #if 0
672 int
673 mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp,
674 acl_type_t type)
675 {
676 kauth_cred_t cred;
677 int error;
678
679 if (!mac_vnode_enforce ||
680 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
681 return (0);
682
683 cred = vfs_context_ucred(ctx);
684 MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
685 return (error);
686 }
687 #endif
688
689 int
690 mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp,
691 const char *name)
692 {
693 kauth_cred_t cred;
694 int error;
695
696 if (!mac_vnode_enforce ||
697 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
698 return (0);
699
700 cred = vfs_context_ucred(ctx);
701 MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name);
702 return (error);
703 }
704 int
705 mac_vnode_check_exchangedata(vfs_context_t ctx,
706 struct vnode *v1, struct vnode *v2)
707 {
708 kauth_cred_t cred;
709 int error;
710
711 if (!mac_vnode_enforce ||
712 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
713 return (0);
714
715 cred = vfs_context_ucred(ctx);
716 MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label,
717 v2, v2->v_label);
718
719 return (error);
720 }
721
722 #if 0
723 int
724 mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
725 {
726 kauth_cred_t cred;
727 int error;
728
729 if (!mac_vnode_enforce ||
730 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
731 return (0);
732
733 cred = vfs_context_ucred(ctx);
734 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
735 return (error);
736 }
737 #endif
738
739 int
740 mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp,
741 struct attrlist *alist)
742 {
743 kauth_cred_t cred;
744 int error;
745
746 if (!mac_vnode_enforce ||
747 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
748 return (0);
749
750 cred = vfs_context_ucred(ctx);
751 MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist);
752
753 /* Falsify results instead of returning error? */
754 return (error);
755 }
756
757 int
758 mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp,
759 struct image_params *imgp)
760 {
761 kauth_cred_t cred;
762 int error = 0;
763
764 if (!mac_vnode_enforce || !mac_proc_enforce)
765 return (0);
766
767 cred = vfs_context_ucred(ctx);
768
769 /*
770 * NB: Cannot use MAC_CHECK macro because we need a sequence point after
771 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
772 * spawnattrlen as an argument to the hook.
773 */
774 {
775 struct mac_policy_conf *mpc;
776 u_int i;
777
778 for (i = 0; i< mac_policy_list.staticmax; i++) {
779 mpc = mac_policy_list.entries[i].mpc;
780 if (mpc == NULL)
781 continue;
782
783 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
784 if (hook == NULL)
785 continue;
786
787 size_t spawnattrlen = 0;
788 void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen);
789
790 error = mac_error_select(
791 hook(cred,
792 vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp,
793 imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags,
794 spawnattr, spawnattrlen), error);
795 }
796 if (mac_policy_list_conditional_busy() != 0) {
797 for (; i <= mac_policy_list.maxindex; i++) {
798 mpc = mac_policy_list.entries[i].mpc;
799 if (mpc == NULL)
800 continue;
801
802 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
803 if (hook == NULL)
804 continue;
805
806 size_t spawnattrlen = 0;
807 void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen);
808
809 error = mac_error_select(
810 hook(cred,
811 vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp,
812 imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags,
813 spawnattr, spawnattrlen), error);
814 }
815 mac_policy_list_unbusy();
816 }
817 }
818
819 return (error);
820 }
821
822 int
823 mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp)
824 {
825 kauth_cred_t cred;
826 int error;
827
828 if (!mac_vnode_enforce ||
829 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
830 return (0);
831
832 cred = vfs_context_ucred(ctx);
833 MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label);
834 return (error);
835 }
836
837 int
838 mac_vnode_check_signature(struct vnode *vp, off_t macho_offset,
839 unsigned char *sha1,
840 const void *signature, size_t size,
841 int *is_platform_binary)
842 {
843 int error;
844
845 if (!mac_vnode_enforce || !mac_proc_enforce)
846 return (0);
847
848 MAC_CHECK(vnode_check_signature, vp, vp->v_label, macho_offset, sha1,
849 signature, size, is_platform_binary);
850 return (error);
851 }
852
853 #if 0
854 int
855 mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
856 {
857 kauth_cred_t cred;
858 int error;
859
860 if (!mac_vnode_enforce ||
861 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
862 return (0);
863
864 cred = vfs_context_ucred(ctx);
865 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
866 return (error);
867 }
868 #endif
869
870 int
871 mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp,
872 const char *name, struct uio *uio)
873 {
874 kauth_cred_t cred;
875 int error;
876
877 if (!mac_vnode_enforce ||
878 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
879 return (0);
880
881 cred = vfs_context_ucred(ctx);
882 MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
883 name, uio);
884 return (error);
885 }
886
887 int
888 mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd)
889 {
890 kauth_cred_t cred;
891 int error;
892
893 if (!mac_vnode_enforce ||
894 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
895 return (0);
896
897 cred = vfs_context_ucred(ctx);
898 MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd);
899 return (error);
900 }
901
902 int
903 mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred,
904 struct knote *kn, struct vnode *vp)
905 {
906 kauth_cred_t cred;
907 int error;
908
909 if (!mac_vnode_enforce ||
910 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
911 return (0);
912
913 cred = vfs_context_ucred(ctx);
914 MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp,
915 vp->v_label);
916
917 return (error);
918 }
919
920 int
921 mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp,
922 struct vnode *vp, struct componentname *cnp)
923 {
924 kauth_cred_t cred;
925 int error;
926
927 if (!mac_vnode_enforce ||
928 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
929 return (0);
930
931 cred = vfs_context_ucred(ctx);
932 MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
933 vp->v_label, cnp);
934 return (error);
935 }
936
937 int
938 mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp)
939 {
940 kauth_cred_t cred;
941 int error;
942
943 if (!mac_vnode_enforce ||
944 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
945 return (0);
946
947 cred = vfs_context_ucred(ctx);
948 MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label);
949 return (error);
950 }
951
952 int
953 mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp,
954 struct componentname *cnp)
955 {
956 kauth_cred_t cred;
957 int error;
958
959 if (!mac_vnode_enforce ||
960 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
961 return (0);
962
963 cred = vfs_context_ucred(ctx);
964 MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
965 return (error);
966 }
967
968 int
969 mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode)
970 {
971 kauth_cred_t cred;
972 int error;
973
974 if (!mac_vnode_enforce ||
975 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
976 return (0);
977
978 cred = vfs_context_ucred(ctx);
979 MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode);
980 return (error);
981 }
982
983 int
984 mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred,
985 struct vnode *vp)
986 {
987 kauth_cred_t cred;
988 int error;
989
990 if (!mac_vnode_enforce ||
991 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
992 return (0);
993
994 cred = vfs_context_ucred(ctx);
995 MAC_CHECK(vnode_check_read, cred, file_cred, vp,
996 vp->v_label);
997
998 return (error);
999 }
1000
1001 int
1002 mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp)
1003 {
1004 kauth_cred_t cred;
1005 int error;
1006
1007 if (!mac_vnode_enforce ||
1008 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1009 return (0);
1010
1011 cred = vfs_context_ucred(ctx);
1012 MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
1013 return (error);
1014 }
1015
1016 int
1017 mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp)
1018 {
1019 kauth_cred_t cred;
1020 int error;
1021
1022 if (!mac_vnode_enforce ||
1023 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1024 return (0);
1025
1026 cred = vfs_context_ucred(ctx);
1027 MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
1028 return (error);
1029 }
1030
1031 int
1032 mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp,
1033 struct label *newlabel)
1034 {
1035 kauth_cred_t cred;
1036 int error;
1037
1038 if (!mac_vnode_enforce ||
1039 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1040 return (0);
1041
1042 cred = vfs_context_ucred(ctx);
1043 MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel);
1044
1045 return (error);
1046 }
1047
1048 int
1049 mac_vnode_check_rename(vfs_context_t ctx, struct vnode *dvp,
1050 struct vnode *vp, struct componentname *cnp, struct vnode *tdvp,
1051 struct vnode *tvp, struct componentname *tcnp)
1052 {
1053 kauth_cred_t cred;
1054 int error;
1055
1056 if (!mac_vnode_enforce ||
1057 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1058 return (0);
1059
1060 cred = vfs_context_ucred(ctx);
1061
1062 MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
1063 vp->v_label, cnp);
1064 if (error)
1065 return (error);
1066
1067 MAC_CHECK(vnode_check_rename_to, cred, tdvp, tdvp->v_label, tvp,
1068 tvp != NULL ? tvp->v_label : NULL, dvp == tdvp, tcnp);
1069 if (error)
1070 return (error);
1071
1072 MAC_CHECK(vnode_check_rename, cred, dvp, dvp->v_label, vp,
1073 vp->v_label, cnp, tdvp, tdvp->v_label, tvp,
1074 tvp != NULL ? tvp->v_label : NULL, tcnp);
1075 return (error);
1076 }
1077
1078 int
1079 mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
1080 {
1081 kauth_cred_t cred;
1082 int error;
1083
1084 if (!mac_vnode_enforce ||
1085 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1086 return (0);
1087
1088 cred = vfs_context_ucred(ctx);
1089 MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
1090 return (error);
1091 }
1092
1093 int
1094 mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist)
1095 {
1096 kauth_cred_t cred;
1097 int error;
1098
1099 if (!mac_vnode_enforce ||
1100 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1101 return (0);
1102
1103 cred = vfs_context_ucred(ctx);
1104 MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist);
1105 return (error);
1106 }
1107
1108 int
1109 mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which)
1110 {
1111 kauth_cred_t cred;
1112 int error;
1113
1114 if (!mac_vnode_enforce ||
1115 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1116 return (0);
1117
1118 cred = vfs_context_ucred(ctx);
1119 MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which);
1120 return (error);
1121 }
1122
1123 #if 0
1124 int
1125 mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type,
1126 struct acl *acl)
1127 {
1128 kauth_cred_t cred;
1129 int error;
1130
1131 if (!mac_vnode_enforce ||
1132 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1133 return (0);
1134
1135 cred = vfs_context_ucred(ctx);
1136 MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl);
1137 return (error);
1138 }
1139 #endif
1140
1141 int
1142 mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp,
1143 struct attrlist *alist)
1144 {
1145 kauth_cred_t cred;
1146 int error;
1147
1148 if (!mac_vnode_enforce ||
1149 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1150 return (0);
1151
1152 cred = vfs_context_ucred(ctx);
1153 MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist);
1154 return (error);
1155 }
1156
1157 int
1158 mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp,
1159 const char *name, struct uio *uio)
1160 {
1161 kauth_cred_t cred;
1162 int error;
1163
1164 if (!mac_vnode_enforce ||
1165 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1166 return (0);
1167
1168 cred = vfs_context_ucred(ctx);
1169 MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
1170 name, uio);
1171 return (error);
1172 }
1173
1174 int
1175 mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
1176 {
1177 kauth_cred_t cred;
1178 int error;
1179
1180 if (!mac_vnode_enforce ||
1181 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1182 return (0);
1183
1184 cred = vfs_context_ucred(ctx);
1185 MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
1186 return (error);
1187 }
1188
1189 int
1190 mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
1191 {
1192 kauth_cred_t cred;
1193 int error;
1194
1195 if (!mac_vnode_enforce ||
1196 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1197 return (0);
1198
1199 cred = vfs_context_ucred(ctx);
1200 MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
1201 return (error);
1202 }
1203
1204 int
1205 mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid,
1206 gid_t gid)
1207 {
1208 kauth_cred_t cred;
1209 int error;
1210
1211 if (!mac_vnode_enforce ||
1212 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1213 return (0);
1214
1215 cred = vfs_context_ucred(ctx);
1216 MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid);
1217 return (error);
1218 }
1219
1220 int
1221 mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp,
1222 struct timespec atime, struct timespec mtime)
1223 {
1224 kauth_cred_t cred;
1225 int error;
1226
1227 if (!mac_vnode_enforce ||
1228 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1229 return (0);
1230
1231 cred = vfs_context_ucred(ctx);
1232 MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime,
1233 mtime);
1234 return (error);
1235 }
1236
1237 int
1238 mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred,
1239 struct vnode *vp)
1240 {
1241 kauth_cred_t cred;
1242 int error;
1243
1244 if (!mac_vnode_enforce ||
1245 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1246 return (0);
1247
1248 cred = vfs_context_ucred(ctx);
1249 MAC_CHECK(vnode_check_stat, cred, file_cred, vp,
1250 vp->v_label);
1251 return (error);
1252 }
1253
1254 int
1255 mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred,
1256 struct vnode *vp)
1257 {
1258 kauth_cred_t cred;
1259 int error;
1260
1261 if (!mac_vnode_enforce ||
1262 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1263 return (0);
1264
1265 cred = vfs_context_ucred(ctx);
1266 MAC_CHECK(vnode_check_truncate, cred, file_cred, vp,
1267 vp->v_label);
1268
1269 return (error);
1270 }
1271
1272 int
1273 mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred,
1274 struct vnode *vp)
1275 {
1276 kauth_cred_t cred;
1277 int error;
1278
1279 if (!mac_vnode_enforce ||
1280 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1281 return (0);
1282
1283 cred = vfs_context_ucred(ctx);
1284 MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label);
1285
1286 return (error);
1287 }
1288
1289 int
1290 mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp,
1291 struct componentname *cnp, struct vnode_attr *vap)
1292 {
1293 kauth_cred_t cred;
1294 int error;
1295
1296 if (!mac_vnode_enforce ||
1297 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1298 return (0);
1299
1300 cred = vfs_context_ucred(ctx);
1301 MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap);
1302 return (error);
1303 }
1304
1305 int
1306 mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp)
1307 {
1308 kauth_cred_t cred;
1309 int error;
1310
1311 if (!mac_vnode_enforce ||
1312 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1313 return (0);
1314
1315 cred = vfs_context_ucred(ctx);
1316 MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label);
1317 return (error);
1318 }
1319
1320 void
1321 mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel)
1322 {
1323 kauth_cred_t cred = vfs_context_ucred(ctx);
1324 struct label *tmpl = NULL;
1325
1326 if (vp->v_label == NULL)
1327 tmpl = mac_vnode_label_alloc();
1328
1329 vnode_lock(vp);
1330
1331 /* recheck after lock */
1332 if (vp->v_label == NULL) {
1333 vp->v_label = tmpl;
1334 tmpl = NULL;
1335 }
1336
1337 MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel);
1338 vnode_unlock(vp);
1339
1340 if (tmpl != NULL)
1341 mac_vnode_label_free(tmpl);
1342 }
1343
1344 int
1345 mac_vnode_find_sigs(struct proc *p, struct vnode *vp, off_t offset)
1346 {
1347 int error;
1348
1349 if (!mac_vnode_enforce || !mac_proc_enforce)
1350 return (0);
1351
1352 MAC_CHECK(vnode_find_sigs, p, vp, offset, vp->v_label);
1353
1354 return (error);
1355 }
1356
1357 void
1358 mac_mount_label_associate(vfs_context_t ctx, struct mount *mp)
1359 {
1360 kauth_cred_t cred = vfs_context_ucred(ctx);
1361
1362 /* XXX: eventually this logic may be handled by the policy? */
1363
1364 /* We desire MULTILABEL for the root filesystem. */
1365 if ((mp->mnt_flag & MNT_ROOTFS) &&
1366 (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0))
1367 mp->mnt_flag |= MNT_MULTILABEL;
1368
1369 /* MULTILABEL on DEVFS. */
1370 if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0)
1371 mp->mnt_flag |= MNT_MULTILABEL;
1372
1373 /* MULTILABEL on FDESC pseudo-filesystem. */
1374 if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0)
1375 mp->mnt_flag |= MNT_MULTILABEL;
1376
1377 /* MULTILABEL on all NFS filesystems. */
1378 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0)
1379 mp->mnt_flag |= MNT_MULTILABEL;
1380
1381 /* MULTILABEL on all AFP filesystems. */
1382 if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0)
1383 mp->mnt_flag |= MNT_MULTILABEL;
1384
1385 if (mp->mnt_vtable != NULL) {
1386 /* Any filesystem that supports native XATTRs. */
1387 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR))
1388 mp->mnt_flag |= MNT_MULTILABEL;
1389
1390 /* Filesystem does not support multilabel. */
1391 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) &&
1392 (mp->mnt_flag & MNT_MULTILABEL))
1393 mp->mnt_flag &= ~MNT_MULTILABEL;
1394 }
1395
1396 MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel);
1397 #if DEBUG
1398 printf("MAC Framework enabling %s support: %s -> %s (%s)\n",
1399 mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel",
1400 mp->mnt_vfsstat.f_mntfromname,
1401 mp->mnt_vfsstat.f_mntonname,
1402 mp->mnt_vfsstat.f_fstypename);
1403 #endif
1404 }
1405
1406 int
1407 mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp,
1408 struct componentname *cnp, const char *vfc_name)
1409 {
1410 kauth_cred_t cred;
1411 int error;
1412
1413 if (!mac_vnode_enforce ||
1414 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1415 return (0);
1416
1417 cred = vfs_context_ucred(ctx);
1418 MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name);
1419
1420 return (error);
1421 }
1422
1423 int
1424 mac_mount_check_remount(vfs_context_t ctx, struct mount *mp)
1425 {
1426 kauth_cred_t cred;
1427 int error;
1428
1429 if (!mac_vnode_enforce ||
1430 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1431 return (0);
1432
1433 cred = vfs_context_ucred(ctx);
1434 MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel);
1435
1436 return (error);
1437 }
1438
1439 int
1440 mac_mount_check_umount(vfs_context_t ctx, struct mount *mp)
1441 {
1442 kauth_cred_t cred;
1443 int error;
1444
1445 if (!mac_vnode_enforce ||
1446 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1447 return (0);
1448
1449 cred = vfs_context_ucred(ctx);
1450 MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel);
1451
1452 return (error);
1453 }
1454
1455 int
1456 mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp,
1457 struct vfs_attr *vfa)
1458 {
1459 kauth_cred_t cred;
1460 int error;
1461
1462 if (!mac_vnode_enforce ||
1463 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1464 return (0);
1465
1466 cred = vfs_context_ucred(ctx);
1467 MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa);
1468 return (error);
1469 }
1470
1471 int
1472 mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp,
1473 struct vfs_attr *vfa)
1474 {
1475 kauth_cred_t cred;
1476 int error;
1477
1478 if (!mac_vnode_enforce ||
1479 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1480 return (0);
1481
1482 cred = vfs_context_ucred(ctx);
1483 MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa);
1484 return (error);
1485 }
1486
1487 int
1488 mac_mount_check_stat(vfs_context_t ctx, struct mount *mount)
1489 {
1490 kauth_cred_t cred;
1491 int error;
1492
1493 if (!mac_vnode_enforce ||
1494 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1495 return (0);
1496
1497 cred = vfs_context_ucred(ctx);
1498 MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel);
1499
1500 return (error);
1501 }
1502
1503 int
1504 mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount)
1505 {
1506 kauth_cred_t cred;
1507 int error;
1508
1509 if (!mac_vnode_enforce ||
1510 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1511 return (0);
1512
1513 cred = vfs_context_ucred(ctx);
1514 MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel);
1515
1516 return (error);
1517 }
1518
1519 int
1520 mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd)
1521 {
1522 kauth_cred_t cred;
1523 int error;
1524
1525 if (!mac_vnode_enforce ||
1526 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1527 return (0);
1528
1529 cred = vfs_context_ucred(ctx);
1530 MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd);
1531
1532 return (error);
1533 }
1534
1535 void
1536 mac_devfs_label_associate_device(dev_t dev, struct devnode *de,
1537 const char *fullpath)
1538 {
1539 if (!mac_device_enforce)
1540 return;
1541
1542 MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label,
1543 fullpath);
1544 }
1545
1546 void
1547 mac_devfs_label_associate_directory(const char *dirname, int dirnamelen,
1548 struct devnode *de, const char *fullpath)
1549 {
1550 if (!mac_device_enforce)
1551 return;
1552
1553 MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de,
1554 de->dn_label, fullpath);
1555 }
1556
1557 int
1558 vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context)
1559 {
1560 int error;
1561
1562 if (!mac_vnode_enforce || !mac_label_vnodes)
1563 return (0);
1564
1565 if (vp->v_mount == NULL) {
1566 printf("vn_setlabel: null v_mount\n");
1567 if (vp->v_type != VNON)
1568 printf("vn_setlabel: null v_mount with non-VNON\n");
1569 return (EBADF);
1570 }
1571
1572 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1573 return (ENOTSUP);
1574
1575 /*
1576 * Multi-phase commit. First check the policies to confirm the
1577 * change is OK. Then commit via the filesystem. Finally,
1578 * update the actual vnode label. Question: maybe the filesystem
1579 * should update the vnode at the end as part of VNOP_SETLABEL()?
1580 */
1581 error = mac_vnode_check_label_update(context, vp, intlabel);
1582 if (error)
1583 return (error);
1584
1585 error = VNOP_SETLABEL(vp, intlabel, context);
1586 if (error == ENOTSUP) {
1587 error = mac_vnode_label_store(context, vp,
1588 intlabel);
1589 if (error) {
1590 printf("%s: mac_vnode_label_store failed %d\n",
1591 __func__, error);
1592 return (error);
1593 }
1594 mac_vnode_label_update(context, vp, intlabel);
1595 } else
1596 if (error) {
1597 printf("vn_setlabel: vop setlabel failed %d\n", error);
1598 return (error);
1599 }
1600
1601 return (0);
1602 }
1603
1604 int
1605 mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
1606 struct vnode *vp, vfs_context_t ctx)
1607 {
1608 struct fileproc *fp;
1609 #if CONFIG_MACF_SOCKET_SUBSET
1610 struct socket *so;
1611 #endif
1612 struct pipe *cpipe;
1613 struct vnode *fvp;
1614 struct proc *p;
1615 int error;
1616
1617 error = 0;
1618
1619 /*
1620 * If no backing file, let the policy choose which label to use.
1621 */
1622 if (fnp->fd_fd == -1) {
1623 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1624 mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label);
1625 return (0);
1626 }
1627
1628 p = vfs_context_proc(ctx);
1629 error = fp_lookup(p, fnp->fd_fd, &fp, 0);
1630 if (error)
1631 return (error);
1632
1633 if (fp->f_fglob == NULL) {
1634 error = EBADF;
1635 goto out;
1636 }
1637
1638 switch (FILEGLOB_DTYPE(fp->f_fglob)) {
1639 case DTYPE_VNODE:
1640 fvp = (struct vnode *)fp->f_fglob->fg_data;
1641 if ((error = vnode_getwithref(fvp)))
1642 goto out;
1643 MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label);
1644 (void)vnode_put(fvp);
1645 break;
1646 #if CONFIG_MACF_SOCKET_SUBSET
1647 case DTYPE_SOCKET:
1648 so = (struct socket *)fp->f_fglob->fg_data;
1649 socket_lock(so, 1);
1650 MAC_PERFORM(vnode_label_associate_socket,
1651 vfs_context_ucred(ctx), (socket_t)so, so->so_label,
1652 vp, vp->v_label);
1653 socket_unlock(so, 1);
1654 break;
1655 #endif
1656 case DTYPE_PSXSHM:
1657 pshm_label_associate(fp, vp, ctx);
1658 break;
1659 case DTYPE_PSXSEM:
1660 psem_label_associate(fp, vp, ctx);
1661 break;
1662 case DTYPE_PIPE:
1663 cpipe = (struct pipe *)fp->f_fglob->fg_data;
1664 /* kern/sys_pipe.c:pipe_select() suggests this test. */
1665 if (cpipe == (struct pipe *)-1) {
1666 error = EINVAL;
1667 goto out;
1668 }
1669 PIPE_LOCK(cpipe);
1670 MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx),
1671 cpipe, cpipe->pipe_label, vp, vp->v_label);
1672 PIPE_UNLOCK(cpipe);
1673 break;
1674 case DTYPE_KQUEUE:
1675 case DTYPE_FSEVENTS:
1676 default:
1677 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1678 mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label,
1679 vp, vp->v_label);
1680 break;
1681 }
1682 out:
1683 fp_drop(p, fnp->fd_fd, fp, 0);
1684 return (error);
1685 }