]> git.saurik.com Git - apple/xnu.git/blob - security/mac_vfs.c
xnu-1228.15.4.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/fdesc/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
143 vp->v_label = mac_vnode_label_alloc();
144 }
145
146 /*
147 * vnode labels are allocated at the same time as vnodes, but vnodes are never
148 * freed. Instead, we want to remove any sensitive information before putting
149 * them on the free list for reuse.
150 */
151 void
152 mac_vnode_label_recycle(vnode_t vp)
153 {
154
155 MAC_PERFORM(vnode_label_recycle, vp->v_label);
156 }
157
158 static void
159 mac_devfs_label_free(struct label *label)
160 {
161 MAC_PERFORM(devfs_label_destroy, label);
162 mac_labelzone_free(label);
163 }
164
165 void
166 mac_devfs_label_destroy(struct devnode *de)
167 {
168 if (de->dn_label != NULL) {
169 mac_devfs_label_free(de->dn_label);
170 de->dn_label = NULL;
171 }
172 }
173
174 static void
175 mac_mount_label_free(struct label *label)
176 {
177
178 MAC_PERFORM(mount_label_destroy, label);
179 mac_labelzone_free(label);
180 }
181
182 void
183 mac_mount_label_destroy(struct mount *mp)
184 {
185
186
187 if (mp->mnt_mntlabel != NULL) {
188 mac_mount_label_free(mp->mnt_mntlabel);
189 mp->mnt_mntlabel = NULL;
190 }
191 }
192
193 void
194 mac_vnode_label_free(struct label *label)
195 {
196
197 MAC_PERFORM(vnode_label_destroy, label);
198 mac_labelzone_free(label);
199 }
200
201 #ifndef __APPLE__
202 void
203 mac_vnode_label_destroy(struct vnode *vp)
204 {
205
206 mac_vnode_label_free(vp->v_label);
207 vp->v_label = NULL;
208 }
209 #endif
210
211 void
212 mac_vnode_label_copy(struct label *src, struct label *dest)
213 {
214
215 MAC_PERFORM(vnode_label_copy, src, dest);
216 }
217
218 int
219 mac_vnode_label_externalize_audit(struct vnode *vp, struct mac *mac)
220 {
221 int error;
222
223 /* It is assumed that any necessary vnode locking is done on entry */
224 error = MAC_EXTERNALIZE_AUDIT(vnode, vp->v_label,
225 mac->m_string, mac->m_buflen);
226
227 return (error);
228 }
229
230 int
231 mac_vnode_label_externalize(struct label *label, char *elements,
232 char *outbuf, size_t outbuflen, int flags __unused)
233 {
234 int error;
235
236 error = MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
237
238 return (error);
239 }
240
241 int
242 mac_vnode_label_internalize(struct label *label, char *string)
243 {
244 int error;
245
246 error = MAC_INTERNALIZE(vnode, label, string);
247
248 return (error);
249 }
250
251 int
252 mac_mount_label_internalize(struct label *label, char *string)
253 {
254 int error;
255
256 error = MAC_INTERNALIZE(mount, label, string);
257
258 return (error);
259 }
260
261 int
262 mac_mount_label_externalize(struct label *label, char *elements,
263 char *outbuf, size_t outbuflen)
264 {
265 int error;
266
267 error = MAC_EXTERNALIZE(mount, label, elements, outbuf, outbuflen);
268
269 return (error);
270 }
271
272 void
273 mac_devfs_label_copy(struct label *src, struct label *dest)
274 {
275 if (!mac_device_enforce)
276 return;
277
278 MAC_PERFORM(devfs_label_copy, src, dest);
279 }
280
281 void
282 mac_devfs_label_update(struct mount *mp, struct devnode *de,
283 struct vnode *vp)
284 {
285
286 if (!mac_device_enforce)
287 return;
288
289 MAC_PERFORM(devfs_label_update, mp, de, de->dn_label, vp,
290 vp->v_label);
291 }
292
293 int
294 mac_vnode_label_associate(struct mount *mp, struct vnode *vp, vfs_context_t ctx)
295 {
296 struct devnode *dnp;
297 struct fdescnode *fnp;
298 int error = 0;
299
300 if (!mac_vnode_enforce)
301 return (error);
302
303 /* XXX: should not inspect v_tag in kernel! */
304 switch (vp->v_tag) {
305 case VT_DEVFS:
306 dnp = VTODN(vp);
307 mac_vnode_label_associate_devfs(mp, dnp, vp);
308 break;
309 case VT_FDESC:
310 fnp = VTOFDESC(vp);
311 error = mac_vnode_label_associate_fdesc(mp, fnp, vp, ctx);
312 break;
313 default:
314 error = mac_vnode_label_associate_extattr(mp, vp);
315 break;
316 }
317
318 return (error);
319 }
320
321 void
322 mac_vnode_label_associate_devfs(struct mount *mp, struct devnode *de,
323 struct vnode *vp)
324 {
325 if (!mac_device_enforce)
326 return;
327
328 MAC_PERFORM(vnode_label_associate_devfs,
329 mp, mp ? mp->mnt_mntlabel : NULL,
330 de, de->dn_label,
331 vp, vp->v_label);
332 }
333
334 int
335 mac_vnode_label_associate_extattr(struct mount *mp, struct vnode *vp)
336 {
337 int error;
338
339 MAC_CHECK(vnode_label_associate_extattr, mp, mp->mnt_mntlabel, vp,
340 vp->v_label);
341
342 return (error);
343 }
344
345 void
346 mac_vnode_label_associate_singlelabel(struct mount *mp, struct vnode *vp)
347 {
348
349 if (!mac_vnode_enforce)
350 return;
351
352 MAC_PERFORM(vnode_label_associate_singlelabel, mp,
353 mp ? mp->mnt_mntlabel : NULL, vp, vp->v_label);
354 }
355
356 int
357 mac_vnode_notify_create(vfs_context_t ctx, struct mount *mp,
358 struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
359 {
360 kauth_cred_t cred;
361 int error;
362
363 if (!mac_vnode_enforce ||
364 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
365 return (0);
366
367 cred = vfs_context_ucred(ctx);
368 MAC_CHECK(vnode_notify_create, cred, mp, mp->mnt_mntlabel,
369 dvp, dvp->v_label, vp, vp->v_label, cnp);
370
371 return (error);
372 }
373
374 /*
375 * Extended attribute 'name' was updated via
376 * vn_setxattr() or vn_removexattr(). Allow the
377 * policy to update the vnode label.
378 */
379 void
380 mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp,
381 const char *name)
382 {
383 int error = 0;
384
385 if (!mac_vnode_enforce)
386 return;
387
388 MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp,
389 vp->v_label, name);
390 if (error == 0)
391 return;
392
393 vnode_lock(vp);
394 vnode_relabel(vp);
395 vnode_unlock(vp);
396 return;
397 }
398
399 static int
400 mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp,
401 struct label *intlabel)
402 {
403 kauth_cred_t cred;
404 int error;
405
406 if (!mac_vnode_enforce &&
407 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
408 return 0;
409
410 cred = vfs_context_ucred(ctx);
411 MAC_CHECK(vnode_label_store, cred, vp, vp->v_label, intlabel);
412
413 return (error);
414 }
415
416 int
417 mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp,
418 struct label *scriptvnodelabel, struct label *execl)
419 {
420 kauth_cred_t cred;
421 int disjoint = 0;
422
423 if (!mac_proc_enforce && !mac_vnode_enforce)
424 return disjoint;
425
426 /* mark the new cred to indicate "matching" includes the label */
427 new->cr_flags |= CRF_MAC_ENFORCE;
428
429 cred = vfs_context_ucred(ctx);
430 MAC_PERFORM(cred_label_update_execve, cred, new, vp, vp->v_label,
431 scriptvnodelabel, execl, &disjoint);
432
433 return (disjoint);
434 }
435
436 int
437 mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp,
438 struct label *scriptvnodelabel, struct label *execlabel, struct proc *p)
439 {
440 kauth_cred_t cred;
441 int result = 0;
442
443 if (!mac_proc_enforce && !mac_vnode_enforce)
444 return result;
445
446 cred = vfs_context_ucred(ctx);
447 MAC_BOOLEAN(cred_check_label_update_execve, ||, cred, vp, vp->v_label,
448 scriptvnodelabel, execlabel, p);
449
450 return (result);
451 }
452
453 int
454 mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp,
455 int acc_mode)
456 {
457 kauth_cred_t cred;
458 int error;
459 int mask;
460
461 if (!mac_vnode_enforce ||
462 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
463 return 0;
464
465 cred = vfs_context_ucred(ctx);
466 /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */
467 mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode);
468 MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask);
469 return (error);
470 }
471
472 int
473 mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp)
474 {
475 kauth_cred_t cred;
476 int error;
477
478 if (!mac_vnode_enforce ||
479 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
480 return (0);
481
482 cred = vfs_context_ucred(ctx);
483 MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
484 return (error);
485 }
486
487 int
488 mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp,
489 struct componentname *cnp)
490 {
491 kauth_cred_t cred;
492 int error;
493
494 if (!mac_vnode_enforce ||
495 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
496 return (0);
497
498 cred = vfs_context_ucred(ctx);
499 MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp);
500 return (error);
501 }
502
503 int
504 mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp,
505 struct componentname *cnp, struct vnode_attr *vap)
506 {
507 kauth_cred_t cred;
508 int error;
509
510 if (!mac_vnode_enforce ||
511 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
512 return (0);
513
514 cred = vfs_context_ucred(ctx);
515 MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
516 return (error);
517 }
518
519 int
520 mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp,
521 struct componentname *cnp)
522 {
523 kauth_cred_t cred;
524 int error;
525
526 if (!mac_vnode_enforce ||
527 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
528 return (0);
529
530 cred = vfs_context_ucred(ctx);
531 MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
532 vp->v_label, cnp);
533 return (error);
534 }
535 #if 0
536 int
537 mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp,
538 acl_type_t type)
539 {
540 kauth_cred_t cred;
541 int error;
542
543 if (!mac_vnode_enforce ||
544 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
545 return (0);
546
547 cred = vfs_context_ucred(ctx);
548 MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
549 return (error);
550 }
551 #endif
552
553 int
554 mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp,
555 const char *name)
556 {
557 kauth_cred_t cred;
558 int error;
559
560 if (!mac_vnode_enforce ||
561 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
562 return (0);
563
564 cred = vfs_context_ucred(ctx);
565 MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name);
566 return (error);
567 }
568 int
569 mac_vnode_check_exchangedata(vfs_context_t ctx,
570 struct vnode *v1, struct vnode *v2)
571 {
572 kauth_cred_t cred;
573 int error;
574
575 if (!mac_vnode_enforce ||
576 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
577 return (0);
578
579 cred = vfs_context_ucred(ctx);
580 MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label,
581 v2, v2->v_label);
582
583 return (error);
584 }
585
586 #if 0
587 int
588 mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
589 {
590 kauth_cred_t cred;
591 int error;
592
593 if (!mac_vnode_enforce ||
594 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
595 return (0);
596
597 cred = vfs_context_ucred(ctx);
598 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
599 return (error);
600 }
601 #endif
602
603 int
604 mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp,
605 struct attrlist *alist)
606 {
607 kauth_cred_t cred;
608 int error;
609
610 if (!mac_vnode_enforce ||
611 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
612 return (0);
613
614 cred = vfs_context_ucred(ctx);
615 MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist);
616
617 /* Falsify results instead of returning error? */
618 return (error);
619 }
620
621 int
622 mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp,
623 struct image_params *imgp)
624 {
625 kauth_cred_t cred;
626 int error;
627
628 if (!mac_vnode_enforce || !mac_proc_enforce)
629 return (0);
630
631 cred = vfs_context_ucred(ctx);
632 MAC_CHECK(vnode_check_exec, cred, vp, vp->v_label,
633 (imgp != NULL) ? imgp->ip_execlabelp : NULL,
634 (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL,
635 (imgp != NULL) ? &imgp->ip_csflags : NULL);
636 return (error);
637 }
638
639 int
640 mac_vnode_check_signature(struct vnode *vp, unsigned char *sha1,
641 void * signature, size_t size)
642 {
643 int error;
644
645 if (!mac_vnode_enforce || !mac_proc_enforce)
646 return (0);
647
648 MAC_CHECK(vnode_check_signature, vp, vp->v_label, sha1, signature, size);
649 return (error);
650 }
651
652 #if 0
653 int
654 mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
655 {
656 kauth_cred_t cred;
657 int error;
658
659 if (!mac_vnode_enforce ||
660 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
661 return (0);
662
663 cred = vfs_context_ucred(ctx);
664 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
665 return (error);
666 }
667 #endif
668
669 int
670 mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp,
671 const char *name, struct uio *uio)
672 {
673 kauth_cred_t cred;
674 int error;
675
676 if (!mac_vnode_enforce ||
677 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
678 return (0);
679
680 cred = vfs_context_ucred(ctx);
681 MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
682 name, uio);
683 return (error);
684 }
685
686 int
687 mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd)
688 {
689 kauth_cred_t cred;
690 int error;
691
692 if (!mac_vnode_enforce ||
693 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
694 return (0);
695
696 cred = vfs_context_ucred(ctx);
697 MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd);
698 return (error);
699 }
700
701 int
702 mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred,
703 struct knote *kn, struct vnode *vp)
704 {
705 kauth_cred_t cred;
706 int error;
707
708 if (!mac_vnode_enforce ||
709 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
710 return (0);
711
712 cred = vfs_context_ucred(ctx);
713 MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp,
714 vp->v_label);
715
716 return (error);
717 }
718
719 int
720 mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp,
721 struct vnode *vp, struct componentname *cnp)
722 {
723 kauth_cred_t cred;
724 int error;
725
726 if (!mac_vnode_enforce ||
727 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
728 return (0);
729
730 cred = vfs_context_ucred(ctx);
731 MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
732 vp->v_label, cnp);
733 return (error);
734 }
735
736 int
737 mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp)
738 {
739 kauth_cred_t cred;
740 int error;
741
742 if (!mac_vnode_enforce ||
743 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
744 return (0);
745
746 cred = vfs_context_ucred(ctx);
747 MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label);
748 return (error);
749 }
750
751 int
752 mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp,
753 struct componentname *cnp)
754 {
755 kauth_cred_t cred;
756 int error;
757
758 if (!mac_vnode_enforce ||
759 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
760 return (0);
761
762 cred = vfs_context_ucred(ctx);
763 MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
764 return (error);
765 }
766
767 int
768 mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode)
769 {
770 kauth_cred_t cred;
771 int error;
772
773 if (!mac_vnode_enforce ||
774 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
775 return (0);
776
777 cred = vfs_context_ucred(ctx);
778 MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode);
779 return (error);
780 }
781
782 int
783 mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred,
784 struct vnode *vp)
785 {
786 kauth_cred_t cred;
787 int error;
788
789 if (!mac_vnode_enforce ||
790 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
791 return (0);
792
793 cred = vfs_context_ucred(ctx);
794 MAC_CHECK(vnode_check_read, cred, file_cred, vp,
795 vp->v_label);
796
797 return (error);
798 }
799
800 int
801 mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp)
802 {
803 kauth_cred_t cred;
804 int error;
805
806 if (!mac_vnode_enforce ||
807 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
808 return (0);
809
810 cred = vfs_context_ucred(ctx);
811 MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
812 return (error);
813 }
814
815 int
816 mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp)
817 {
818 kauth_cred_t cred;
819 int error;
820
821 if (!mac_vnode_enforce ||
822 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
823 return (0);
824
825 cred = vfs_context_ucred(ctx);
826 MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
827 return (error);
828 }
829
830 int
831 mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp,
832 struct label *newlabel)
833 {
834 kauth_cred_t cred;
835 int error;
836
837 if (!mac_vnode_enforce ||
838 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
839 return (0);
840
841 cred = vfs_context_ucred(ctx);
842 MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel);
843
844 return (error);
845 }
846
847 int
848 mac_vnode_check_rename_from(vfs_context_t ctx, struct vnode *dvp,
849 struct vnode *vp, struct componentname *cnp)
850 {
851 kauth_cred_t cred;
852 int error;
853
854 if (!mac_vnode_enforce ||
855 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
856 return (0);
857
858 cred = vfs_context_ucred(ctx);
859 MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
860 vp->v_label, cnp);
861 return (error);
862 }
863
864 int
865 mac_vnode_check_rename_to(vfs_context_t ctx, struct vnode *dvp,
866 struct vnode *vp, int samedir, struct componentname *cnp)
867 {
868 kauth_cred_t cred;
869 int error;
870
871 if (!mac_vnode_enforce ||
872 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
873 return (0);
874
875 cred = vfs_context_ucred(ctx);
876 MAC_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp,
877 vp != NULL ? vp->v_label : NULL, samedir, cnp);
878 return (error);
879 }
880
881 int
882 mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
883 {
884 kauth_cred_t cred;
885 int error;
886
887 if (!mac_vnode_enforce ||
888 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
889 return (0);
890
891 cred = vfs_context_ucred(ctx);
892 MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
893 return (error);
894 }
895
896 int
897 mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which)
898 {
899 kauth_cred_t cred;
900 int error;
901
902 if (!mac_vnode_enforce ||
903 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
904 return (0);
905
906 cred = vfs_context_ucred(ctx);
907 MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which);
908 return (error);
909 }
910
911 #if 0
912 int
913 mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type,
914 struct acl *acl)
915 {
916 kauth_cred_t cred;
917 int error;
918
919 if (!mac_vnode_enforce ||
920 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
921 return (0);
922
923 cred = vfs_context_ucred(ctx);
924 MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl);
925 return (error);
926 }
927 #endif
928
929 int
930 mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp,
931 struct attrlist *alist)
932 {
933 kauth_cred_t cred;
934 int error;
935
936 if (!mac_vnode_enforce ||
937 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
938 return (0);
939
940 cred = vfs_context_ucred(ctx);
941 MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist);
942 return (error);
943 }
944
945 int
946 mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp,
947 const char *name, struct uio *uio)
948 {
949 kauth_cred_t cred;
950 int error;
951
952 if (!mac_vnode_enforce ||
953 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
954 return (0);
955
956 cred = vfs_context_ucred(ctx);
957 MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
958 name, uio);
959 return (error);
960 }
961
962 int
963 mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
964 {
965 kauth_cred_t cred;
966 int error;
967
968 if (!mac_vnode_enforce ||
969 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
970 return (0);
971
972 cred = vfs_context_ucred(ctx);
973 MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
974 return (error);
975 }
976
977 int
978 mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
979 {
980 kauth_cred_t cred;
981 int error;
982
983 if (!mac_vnode_enforce ||
984 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
985 return (0);
986
987 cred = vfs_context_ucred(ctx);
988 MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
989 return (error);
990 }
991
992 int
993 mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid,
994 gid_t gid)
995 {
996 kauth_cred_t cred;
997 int error;
998
999 if (!mac_vnode_enforce ||
1000 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1001 return (0);
1002
1003 cred = vfs_context_ucred(ctx);
1004 MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid);
1005 return (error);
1006 }
1007
1008 int
1009 mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp,
1010 struct timespec atime, struct timespec mtime)
1011 {
1012 kauth_cred_t cred;
1013 int error;
1014
1015 if (!mac_vnode_enforce ||
1016 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1017 return (0);
1018
1019 cred = vfs_context_ucred(ctx);
1020 MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime,
1021 mtime);
1022 return (error);
1023 }
1024
1025 int
1026 mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred,
1027 struct vnode *vp)
1028 {
1029 kauth_cred_t cred;
1030 int error;
1031
1032 if (!mac_vnode_enforce ||
1033 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1034 return (0);
1035
1036 cred = vfs_context_ucred(ctx);
1037 MAC_CHECK(vnode_check_stat, cred, file_cred, vp,
1038 vp->v_label);
1039 return (error);
1040 }
1041
1042 int
1043 mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred,
1044 struct vnode *vp)
1045 {
1046 kauth_cred_t cred;
1047 int error;
1048
1049 if (!mac_vnode_enforce ||
1050 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1051 return (0);
1052
1053 cred = vfs_context_ucred(ctx);
1054 MAC_CHECK(vnode_check_truncate, cred, file_cred, vp,
1055 vp->v_label);
1056
1057 return (error);
1058 }
1059
1060 int
1061 mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred,
1062 struct vnode *vp)
1063 {
1064 kauth_cred_t cred;
1065 int error;
1066
1067 if (!mac_vnode_enforce ||
1068 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1069 return (0);
1070
1071 cred = vfs_context_ucred(ctx);
1072 MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label);
1073
1074 return (error);
1075 }
1076
1077 void
1078 mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel)
1079 {
1080 kauth_cred_t cred = vfs_context_ucred(ctx);
1081
1082 vnode_lock(vp);
1083 MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel);
1084 vnode_unlock(vp);
1085 }
1086
1087 void
1088 mac_mount_label_associate(vfs_context_t ctx, struct mount *mp)
1089 {
1090 kauth_cred_t cred = vfs_context_ucred(ctx);
1091
1092 /* XXX: eventually this logic may be handled by the policy? */
1093
1094 /* We desire MULTILABEL for the root filesystem. */
1095 if ((mp->mnt_flag & MNT_ROOTFS) &&
1096 (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0))
1097 mp->mnt_flag |= MNT_MULTILABEL;
1098
1099 /* MULTILABEL on DEVFS. */
1100 if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0)
1101 mp->mnt_flag |= MNT_MULTILABEL;
1102
1103 /* MULTILABEL on FDESC pseudo-filesystem. */
1104 if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0)
1105 mp->mnt_flag |= MNT_MULTILABEL;
1106
1107 /* MULTILABEL on all NFS filesystems. */
1108 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0)
1109 mp->mnt_flag |= MNT_MULTILABEL;
1110
1111 /* MULTILABEL on all AFP filesystems. */
1112 if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0)
1113 mp->mnt_flag |= MNT_MULTILABEL;
1114
1115 if (mp->mnt_vtable != NULL) {
1116 /* Any filesystem that supports native XATTRs. */
1117 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR))
1118 mp->mnt_flag |= MNT_MULTILABEL;
1119
1120 /* Filesystem does not support multilabel. */
1121 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) &&
1122 (mp->mnt_flag & MNT_MULTILABEL))
1123 mp->mnt_flag &= ~MNT_MULTILABEL;
1124 }
1125
1126 MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel);
1127 #if MAC_DEBUG
1128 printf("MAC Framework enabling %s support: %s -> %s (%s)\n",
1129 mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel",
1130 mp->mnt_vfsstat.f_mntfromname,
1131 mp->mnt_vfsstat.f_mntonname,
1132 mp->mnt_vfsstat.f_fstypename);
1133 #endif
1134 }
1135
1136 int
1137 mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp,
1138 struct componentname *cnp, const char *vfc_name)
1139 {
1140 kauth_cred_t cred;
1141 int error;
1142
1143 if (!mac_vnode_enforce ||
1144 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1145 return (0);
1146
1147 cred = vfs_context_ucred(ctx);
1148 MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name);
1149
1150 return (error);
1151 }
1152
1153 int
1154 mac_mount_check_remount(vfs_context_t ctx, struct mount *mp)
1155 {
1156 kauth_cred_t cred;
1157 int error;
1158
1159 if (!mac_vnode_enforce ||
1160 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1161 return (0);
1162
1163 cred = vfs_context_ucred(ctx);
1164 MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel);
1165
1166 return (error);
1167 }
1168
1169 int
1170 mac_mount_check_umount(vfs_context_t ctx, struct mount *mp)
1171 {
1172 kauth_cred_t cred;
1173 int error;
1174
1175 if (!mac_vnode_enforce ||
1176 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1177 return (0);
1178
1179 cred = vfs_context_ucred(ctx);
1180 MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel);
1181
1182 return (error);
1183 }
1184
1185 int
1186 mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp,
1187 struct vfs_attr *vfa)
1188 {
1189 kauth_cred_t cred;
1190 int error;
1191
1192 if (!mac_vnode_enforce ||
1193 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1194 return (0);
1195
1196 cred = vfs_context_ucred(ctx);
1197 MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa);
1198 return (error);
1199 }
1200
1201 int
1202 mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp,
1203 struct vfs_attr *vfa)
1204 {
1205 kauth_cred_t cred;
1206 int error;
1207
1208 if (!mac_vnode_enforce ||
1209 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1210 return (0);
1211
1212 cred = vfs_context_ucred(ctx);
1213 MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa);
1214 return (error);
1215 }
1216
1217 int
1218 mac_mount_check_stat(vfs_context_t ctx, struct mount *mount)
1219 {
1220 kauth_cred_t cred;
1221 int error;
1222
1223 if (!mac_vnode_enforce ||
1224 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1225 return (0);
1226
1227 cred = vfs_context_ucred(ctx);
1228 MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel);
1229
1230 return (error);
1231 }
1232
1233 int
1234 mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount)
1235 {
1236 kauth_cred_t cred;
1237 int error;
1238
1239 if (!mac_vnode_enforce ||
1240 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1241 return (0);
1242
1243 cred = vfs_context_ucred(ctx);
1244 MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel);
1245
1246 return (error);
1247 }
1248
1249 int
1250 mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd)
1251 {
1252 kauth_cred_t cred;
1253 int error;
1254
1255 if (!mac_vnode_enforce ||
1256 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1257 return (0);
1258
1259 cred = vfs_context_ucred(ctx);
1260 MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd);
1261
1262 return (error);
1263 }
1264
1265 void
1266 mac_devfs_label_associate_device(dev_t dev, struct devnode *de,
1267 const char *fullpath)
1268 {
1269 if (!mac_device_enforce)
1270 return;
1271
1272 MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label,
1273 fullpath);
1274 }
1275
1276 void
1277 mac_devfs_label_associate_directory(const char *dirname, int dirnamelen,
1278 struct devnode *de, const char *fullpath)
1279 {
1280 if (!mac_device_enforce)
1281 return;
1282
1283 MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de,
1284 de->dn_label, fullpath);
1285 }
1286
1287 int
1288 vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context)
1289 {
1290 int error;
1291
1292 if (!mac_vnode_enforce)
1293 return (0);
1294
1295 if (vp->v_mount == NULL) {
1296 printf("vn_setlabel: null v_mount\n");
1297 if (vp->v_type != VNON)
1298 printf("vn_setlabel: null v_mount with non-VNON\n");
1299 return (EBADF);
1300 }
1301
1302 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1303 return (ENOTSUP);
1304
1305 /*
1306 * Multi-phase commit. First check the policies to confirm the
1307 * change is OK. Then commit via the filesystem. Finally,
1308 * update the actual vnode label. Question: maybe the filesystem
1309 * should update the vnode at the end as part of VNOP_SETLABEL()?
1310 */
1311 error = mac_vnode_check_label_update(context, vp, intlabel);
1312 if (error)
1313 return (error);
1314
1315 error = VNOP_SETLABEL(vp, intlabel, context);
1316 if (error == ENOTSUP) {
1317 error = mac_vnode_label_store(context, vp,
1318 intlabel);
1319 if (error) {
1320 printf("%s: mac_vnode_label_store failed %d\n",
1321 __func__, error);
1322 return (error);
1323 }
1324 mac_vnode_label_update(context, vp, intlabel);
1325 } else
1326 if (error) {
1327 printf("vn_setlabel: vop setlabel failed %d\n", error);
1328 return (error);
1329 }
1330
1331 return (0);
1332 }
1333
1334 int
1335 mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
1336 struct vnode *vp, vfs_context_t ctx)
1337 {
1338 struct fileproc *fp;
1339 struct socket *so;
1340 struct pipe *cpipe;
1341 struct vnode *fvp;
1342 struct proc *p;
1343 int error;
1344
1345 error = 0;
1346
1347 /*
1348 * If no backing file, let the policy choose which label to use.
1349 */
1350 if (fnp->fd_fd == -1) {
1351 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1352 mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label);
1353 return (0);
1354 }
1355
1356 p = vfs_context_proc(ctx);
1357 error = fp_lookup(p, fnp->fd_fd, &fp, 0);
1358 if (error)
1359 return (error);
1360
1361 if (fp->f_fglob == NULL) {
1362 error = EBADF;
1363 goto out;
1364 }
1365
1366 switch (fp->f_fglob->fg_type) {
1367 case DTYPE_VNODE:
1368 fvp = (struct vnode *)fp->f_fglob->fg_data;
1369 if ((error = vnode_getwithref(fvp)))
1370 goto out;
1371 MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label);
1372 (void)vnode_put(fvp);
1373 break;
1374 case DTYPE_SOCKET:
1375 so = (struct socket *)fp->f_fglob->fg_data;
1376 socket_lock(so, 1);
1377 MAC_PERFORM(vnode_label_associate_socket,
1378 vfs_context_ucred(ctx), (socket_t)so, so->so_label,
1379 vp, vp->v_label);
1380 socket_unlock(so, 1);
1381 break;
1382 case DTYPE_PSXSHM:
1383 pshm_label_associate(fp, vp, ctx);
1384 break;
1385 case DTYPE_PSXSEM:
1386 psem_label_associate(fp, vp, ctx);
1387 break;
1388 case DTYPE_PIPE:
1389 cpipe = (struct pipe *)fp->f_fglob->fg_data;
1390 /* kern/sys_pipe.c:pipe_select() suggests this test. */
1391 if (cpipe == (struct pipe *)-1) {
1392 error = EINVAL;
1393 goto out;
1394 }
1395 PIPE_LOCK(cpipe);
1396 MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx),
1397 cpipe, cpipe->pipe_label, vp, vp->v_label);
1398 PIPE_UNLOCK(cpipe);
1399 break;
1400 case DTYPE_KQUEUE:
1401 case DTYPE_FSEVENTS:
1402 default:
1403 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1404 mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label,
1405 vp, vp->v_label);
1406 break;
1407 }
1408 out:
1409 fp_drop(p, fnp->fd_fd, fp, 0);
1410 return (error);
1411 }