]> git.saurik.com Git - apple/xnu.git/blob - security/mac_vfs.c
xnu-1228.5.18.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 void
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
422 if (!mac_proc_enforce && !mac_vnode_enforce)
423 return;
424
425 /* mark the new cred to indicate "matching" includes the label */
426 new->cr_flags |= CRF_MAC_ENFORCE;
427
428 cred = vfs_context_ucred(ctx);
429 MAC_PERFORM(cred_label_update_execve, cred, new, vp, vp->v_label,
430 scriptvnodelabel, execl);
431 }
432
433 int
434 mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp,
435 struct label *scriptvnodelabel, struct label *execlabel, struct proc *p)
436 {
437 kauth_cred_t cred;
438 int result = 0;
439
440 if (!mac_proc_enforce && !mac_vnode_enforce)
441 return result;
442
443 cred = vfs_context_ucred(ctx);
444 MAC_BOOLEAN(cred_check_label_update_execve, ||, cred, vp, vp->v_label,
445 scriptvnodelabel, execlabel, p);
446
447 return (result);
448 }
449
450 int
451 mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp,
452 int acc_mode)
453 {
454 kauth_cred_t cred;
455 int error;
456 int mask;
457
458 if (!mac_vnode_enforce ||
459 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
460 return 0;
461
462 cred = vfs_context_ucred(ctx);
463 /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */
464 mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode);
465 MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask);
466 return (error);
467 }
468
469 int
470 mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp)
471 {
472 kauth_cred_t cred;
473 int error;
474
475 if (!mac_vnode_enforce ||
476 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
477 return (0);
478
479 cred = vfs_context_ucred(ctx);
480 MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
481 return (error);
482 }
483
484 int
485 mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp,
486 struct componentname *cnp)
487 {
488 kauth_cred_t cred;
489 int error;
490
491 if (!mac_vnode_enforce ||
492 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
493 return (0);
494
495 cred = vfs_context_ucred(ctx);
496 MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp);
497 return (error);
498 }
499
500 int
501 mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp,
502 struct componentname *cnp, struct vnode_attr *vap)
503 {
504 kauth_cred_t cred;
505 int error;
506
507 if (!mac_vnode_enforce ||
508 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
509 return (0);
510
511 cred = vfs_context_ucred(ctx);
512 MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
513 return (error);
514 }
515
516 int
517 mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp,
518 struct componentname *cnp)
519 {
520 kauth_cred_t cred;
521 int error;
522
523 if (!mac_vnode_enforce ||
524 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
525 return (0);
526
527 cred = vfs_context_ucred(ctx);
528 MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
529 vp->v_label, cnp);
530 return (error);
531 }
532 #if 0
533 int
534 mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp,
535 acl_type_t type)
536 {
537 kauth_cred_t cred;
538 int error;
539
540 if (!mac_vnode_enforce ||
541 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
542 return (0);
543
544 cred = vfs_context_ucred(ctx);
545 MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
546 return (error);
547 }
548 #endif
549
550 int
551 mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp,
552 const char *name)
553 {
554 kauth_cred_t cred;
555 int error;
556
557 if (!mac_vnode_enforce ||
558 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
559 return (0);
560
561 cred = vfs_context_ucred(ctx);
562 MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name);
563 return (error);
564 }
565 int
566 mac_vnode_check_exchangedata(vfs_context_t ctx,
567 struct vnode *v1, struct vnode *v2)
568 {
569 kauth_cred_t cred;
570 int error;
571
572 if (!mac_vnode_enforce ||
573 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
574 return (0);
575
576 cred = vfs_context_ucred(ctx);
577 MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label,
578 v2, v2->v_label);
579
580 return (error);
581 }
582
583 #if 0
584 int
585 mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
586 {
587 kauth_cred_t cred;
588 int error;
589
590 if (!mac_vnode_enforce ||
591 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
592 return (0);
593
594 cred = vfs_context_ucred(ctx);
595 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
596 return (error);
597 }
598 #endif
599
600 int
601 mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp,
602 struct attrlist *alist)
603 {
604 kauth_cred_t cred;
605 int error;
606
607 if (!mac_vnode_enforce ||
608 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
609 return (0);
610
611 cred = vfs_context_ucred(ctx);
612 MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist);
613
614 /* Falsify results instead of returning error? */
615 return (error);
616 }
617
618 int
619 mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp,
620 struct image_params *imgp)
621 {
622 kauth_cred_t cred;
623 int error;
624
625 if (!mac_vnode_enforce || !mac_proc_enforce)
626 return (0);
627
628 cred = vfs_context_ucred(ctx);
629 MAC_CHECK(vnode_check_exec, cred, vp, vp->v_label,
630 (imgp != NULL) ? imgp->ip_execlabelp : NULL,
631 (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL,
632 (imgp != NULL) ? &imgp->ip_csflags : NULL);
633 return (error);
634 }
635
636 #if 0
637 int
638 mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
639 {
640 kauth_cred_t cred;
641 int error;
642
643 if (!mac_vnode_enforce ||
644 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
645 return (0);
646
647 cred = vfs_context_ucred(ctx);
648 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
649 return (error);
650 }
651 #endif
652
653 int
654 mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp,
655 const char *name, struct uio *uio)
656 {
657 kauth_cred_t cred;
658 int error;
659
660 if (!mac_vnode_enforce ||
661 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
662 return (0);
663
664 cred = vfs_context_ucred(ctx);
665 MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
666 name, uio);
667 return (error);
668 }
669
670 int
671 mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd)
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_ioctl, cred, vp, vp->v_label, cmd);
682 return (error);
683 }
684
685 int
686 mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred,
687 struct knote *kn, struct vnode *vp)
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_kqfilter, cred, file_cred, kn, vp,
698 vp->v_label);
699
700 return (error);
701 }
702
703 int
704 mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp,
705 struct vnode *vp, struct componentname *cnp)
706 {
707 kauth_cred_t cred;
708 int error;
709
710 if (!mac_vnode_enforce ||
711 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
712 return (0);
713
714 cred = vfs_context_ucred(ctx);
715 MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
716 vp->v_label, cnp);
717 return (error);
718 }
719
720 int
721 mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp)
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_listextattr, cred, vp, vp->v_label);
732 return (error);
733 }
734
735 int
736 mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp,
737 struct componentname *cnp)
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_lookup, cred, dvp, dvp->v_label, cnp);
748 return (error);
749 }
750
751 int
752 mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode)
753 {
754 kauth_cred_t cred;
755 int error;
756
757 if (!mac_vnode_enforce ||
758 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
759 return (0);
760
761 cred = vfs_context_ucred(ctx);
762 MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode);
763 return (error);
764 }
765
766 int
767 mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred,
768 struct vnode *vp)
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_read, cred, file_cred, vp,
779 vp->v_label);
780
781 return (error);
782 }
783
784 int
785 mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp)
786 {
787 kauth_cred_t cred;
788 int error;
789
790 if (!mac_vnode_enforce ||
791 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
792 return (0);
793
794 cred = vfs_context_ucred(ctx);
795 MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
796 return (error);
797 }
798
799 int
800 mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp)
801 {
802 kauth_cred_t cred;
803 int error;
804
805 if (!mac_vnode_enforce ||
806 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
807 return (0);
808
809 cred = vfs_context_ucred(ctx);
810 MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
811 return (error);
812 }
813
814 int
815 mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp,
816 struct label *newlabel)
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_label_update, cred, vp, vp->v_label, newlabel);
827
828 return (error);
829 }
830
831 int
832 mac_vnode_check_rename_from(vfs_context_t ctx, struct vnode *dvp,
833 struct vnode *vp, struct componentname *cnp)
834 {
835 kauth_cred_t cred;
836 int error;
837
838 if (!mac_vnode_enforce ||
839 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
840 return (0);
841
842 cred = vfs_context_ucred(ctx);
843 MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
844 vp->v_label, cnp);
845 return (error);
846 }
847
848 int
849 mac_vnode_check_rename_to(vfs_context_t ctx, struct vnode *dvp,
850 struct vnode *vp, int samedir, struct componentname *cnp)
851 {
852 kauth_cred_t cred;
853 int error;
854
855 if (!mac_vnode_enforce ||
856 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
857 return (0);
858
859 cred = vfs_context_ucred(ctx);
860 MAC_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp,
861 vp != NULL ? vp->v_label : NULL, samedir, cnp);
862 return (error);
863 }
864
865 int
866 mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
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_revoke, cred, vp, vp->v_label);
877 return (error);
878 }
879
880 int
881 mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which)
882 {
883 kauth_cred_t cred;
884 int error;
885
886 if (!mac_vnode_enforce ||
887 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
888 return (0);
889
890 cred = vfs_context_ucred(ctx);
891 MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which);
892 return (error);
893 }
894
895 #if 0
896 int
897 mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type,
898 struct acl *acl)
899 {
900 kauth_cred_t cred;
901 int error;
902
903 if (!mac_vnode_enforce ||
904 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
905 return (0);
906
907 cred = vfs_context_ucred(ctx);
908 MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl);
909 return (error);
910 }
911 #endif
912
913 int
914 mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp,
915 struct attrlist *alist)
916 {
917 kauth_cred_t cred;
918 int error;
919
920 if (!mac_vnode_enforce ||
921 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
922 return (0);
923
924 cred = vfs_context_ucred(ctx);
925 MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist);
926 return (error);
927 }
928
929 int
930 mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp,
931 const char *name, struct uio *uio)
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_setextattr, cred, vp, vp->v_label,
942 name, uio);
943 return (error);
944 }
945
946 int
947 mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
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_setflags, cred, vp, vp->v_label, flags);
958 return (error);
959 }
960
961 int
962 mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
963 {
964 kauth_cred_t cred;
965 int error;
966
967 if (!mac_vnode_enforce ||
968 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
969 return (0);
970
971 cred = vfs_context_ucred(ctx);
972 MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
973 return (error);
974 }
975
976 int
977 mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid,
978 gid_t gid)
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_setowner, cred, vp, vp->v_label, uid, gid);
989 return (error);
990 }
991
992 int
993 mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp,
994 struct timespec atime, struct timespec mtime)
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_setutimes, cred, vp, vp->v_label, atime,
1005 mtime);
1006 return (error);
1007 }
1008
1009 int
1010 mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred,
1011 struct vnode *vp)
1012 {
1013 kauth_cred_t cred;
1014 int error;
1015
1016 if (!mac_vnode_enforce ||
1017 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1018 return (0);
1019
1020 cred = vfs_context_ucred(ctx);
1021 MAC_CHECK(vnode_check_stat, cred, file_cred, vp,
1022 vp->v_label);
1023 return (error);
1024 }
1025
1026 int
1027 mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred,
1028 struct vnode *vp)
1029 {
1030 kauth_cred_t cred;
1031 int error;
1032
1033 if (!mac_vnode_enforce ||
1034 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1035 return (0);
1036
1037 cred = vfs_context_ucred(ctx);
1038 MAC_CHECK(vnode_check_truncate, cred, file_cred, vp,
1039 vp->v_label);
1040
1041 return (error);
1042 }
1043
1044 int
1045 mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred,
1046 struct vnode *vp)
1047 {
1048 kauth_cred_t cred;
1049 int error;
1050
1051 if (!mac_vnode_enforce ||
1052 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1053 return (0);
1054
1055 cred = vfs_context_ucred(ctx);
1056 MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label);
1057
1058 return (error);
1059 }
1060
1061 void
1062 mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel)
1063 {
1064 kauth_cred_t cred = vfs_context_ucred(ctx);
1065
1066 vnode_lock(vp);
1067 MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel);
1068 vnode_unlock(vp);
1069 }
1070
1071 void
1072 mac_mount_label_associate(vfs_context_t ctx, struct mount *mp)
1073 {
1074 kauth_cred_t cred = vfs_context_ucred(ctx);
1075
1076 /* XXX: eventually this logic may be handled by the policy? */
1077
1078 /* We desire MULTILABEL for the root filesystem. */
1079 if ((mp->mnt_flag & MNT_ROOTFS) &&
1080 (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0))
1081 mp->mnt_flag |= MNT_MULTILABEL;
1082
1083 /* MULTILABEL on DEVFS. */
1084 if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0)
1085 mp->mnt_flag |= MNT_MULTILABEL;
1086
1087 /* MULTILABEL on FDESC pseudo-filesystem. */
1088 if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0)
1089 mp->mnt_flag |= MNT_MULTILABEL;
1090
1091 /* MULTILABEL on all NFS filesystems. */
1092 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0)
1093 mp->mnt_flag |= MNT_MULTILABEL;
1094
1095 /* MULTILABEL on all AFP filesystems. */
1096 if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0)
1097 mp->mnt_flag |= MNT_MULTILABEL;
1098
1099 if (mp->mnt_vtable != NULL) {
1100 /* Any filesystem that supports native XATTRs. */
1101 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR))
1102 mp->mnt_flag |= MNT_MULTILABEL;
1103
1104 /* Filesystem does not support multilabel. */
1105 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) &&
1106 (mp->mnt_flag & MNT_MULTILABEL))
1107 mp->mnt_flag &= ~MNT_MULTILABEL;
1108 }
1109
1110 MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel);
1111 #if MAC_DEBUG
1112 printf("MAC Framework enabling %s support: %s -> %s (%s)\n",
1113 mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel",
1114 mp->mnt_vfsstat.f_mntfromname,
1115 mp->mnt_vfsstat.f_mntonname,
1116 mp->mnt_vfsstat.f_fstypename);
1117 #endif
1118 }
1119
1120 int
1121 mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp,
1122 struct componentname *cnp, const char *vfc_name)
1123 {
1124 kauth_cred_t cred;
1125 int error;
1126
1127 if (!mac_vnode_enforce ||
1128 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1129 return (0);
1130
1131 cred = vfs_context_ucred(ctx);
1132 MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name);
1133
1134 return (error);
1135 }
1136
1137 int
1138 mac_mount_check_remount(vfs_context_t ctx, struct mount *mp)
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_remount, cred, mp, mp->mnt_mntlabel);
1149
1150 return (error);
1151 }
1152
1153 int
1154 mac_mount_check_umount(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_umount, cred, mp, mp->mnt_mntlabel);
1165
1166 return (error);
1167 }
1168
1169 int
1170 mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp,
1171 struct vfs_attr *vfa)
1172 {
1173 kauth_cred_t cred;
1174 int error;
1175
1176 if (!mac_vnode_enforce ||
1177 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1178 return (0);
1179
1180 cred = vfs_context_ucred(ctx);
1181 MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa);
1182 return (error);
1183 }
1184
1185 int
1186 mac_mount_check_setattr(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_setattr, cred, mp, mp->mnt_mntlabel, vfa);
1198 return (error);
1199 }
1200
1201 int
1202 mac_mount_check_stat(vfs_context_t ctx, struct mount *mount)
1203 {
1204 kauth_cred_t cred;
1205 int error;
1206
1207 if (!mac_vnode_enforce ||
1208 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1209 return (0);
1210
1211 cred = vfs_context_ucred(ctx);
1212 MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel);
1213
1214 return (error);
1215 }
1216
1217 int
1218 mac_mount_check_label_update(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_label_update, cred, mount, mount->mnt_mntlabel);
1229
1230 return (error);
1231 }
1232
1233 int
1234 mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd)
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_fsctl, cred, mp, mp->mnt_mntlabel, cmd);
1245
1246 return (error);
1247 }
1248
1249 void
1250 mac_devfs_label_associate_device(dev_t dev, struct devnode *de,
1251 const char *fullpath)
1252 {
1253 if (!mac_device_enforce)
1254 return;
1255
1256 MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label,
1257 fullpath);
1258 }
1259
1260 void
1261 mac_devfs_label_associate_directory(const char *dirname, int dirnamelen,
1262 struct devnode *de, const char *fullpath)
1263 {
1264 if (!mac_device_enforce)
1265 return;
1266
1267 MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de,
1268 de->dn_label, fullpath);
1269 }
1270
1271 int
1272 vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context)
1273 {
1274 int error;
1275
1276 if (!mac_vnode_enforce)
1277 return (0);
1278
1279 if (vp->v_mount == NULL) {
1280 printf("vn_setlabel: null v_mount\n");
1281 if (vp->v_type != VNON)
1282 printf("vn_setlabel: null v_mount with non-VNON\n");
1283 return (EBADF);
1284 }
1285
1286 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1287 return (ENOTSUP);
1288
1289 /*
1290 * Multi-phase commit. First check the policies to confirm the
1291 * change is OK. Then commit via the filesystem. Finally,
1292 * update the actual vnode label. Question: maybe the filesystem
1293 * should update the vnode at the end as part of VNOP_SETLABEL()?
1294 */
1295 error = mac_vnode_check_label_update(context, vp, intlabel);
1296 if (error)
1297 return (error);
1298
1299 error = VNOP_SETLABEL(vp, intlabel, context);
1300 if (error == ENOTSUP) {
1301 error = mac_vnode_label_store(context, vp,
1302 intlabel);
1303 if (error) {
1304 printf("%s: mac_vnode_label_store failed %d\n",
1305 __func__, error);
1306 return (error);
1307 }
1308 mac_vnode_label_update(context, vp, intlabel);
1309 } else
1310 if (error) {
1311 printf("vn_setlabel: vop setlabel failed %d\n", error);
1312 return (error);
1313 }
1314
1315 return (0);
1316 }
1317
1318 int
1319 mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
1320 struct vnode *vp, vfs_context_t ctx)
1321 {
1322 struct fileproc *fp;
1323 struct socket *so;
1324 struct pipe *cpipe;
1325 struct vnode *fvp;
1326 struct proc *p;
1327 int error;
1328
1329 error = 0;
1330
1331 /*
1332 * If no backing file, let the policy choose which label to use.
1333 */
1334 if (fnp->fd_fd == -1) {
1335 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1336 mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label);
1337 return (0);
1338 }
1339
1340 p = vfs_context_proc(ctx);
1341 error = fp_lookup(p, fnp->fd_fd, &fp, 0);
1342 if (error)
1343 return (error);
1344
1345 if (fp->f_fglob == NULL) {
1346 error = EBADF;
1347 goto out;
1348 }
1349
1350 switch (fp->f_fglob->fg_type) {
1351 case DTYPE_VNODE:
1352 fvp = (struct vnode *)fp->f_fglob->fg_data;
1353 if ((error = vnode_getwithref(fvp)))
1354 goto out;
1355 MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label);
1356 (void)vnode_put(fvp);
1357 break;
1358 case DTYPE_SOCKET:
1359 so = (struct socket *)fp->f_fglob->fg_data;
1360 socket_lock(so, 1);
1361 MAC_PERFORM(vnode_label_associate_socket,
1362 vfs_context_ucred(ctx), (socket_t)so, so->so_label,
1363 vp, vp->v_label);
1364 socket_unlock(so, 1);
1365 break;
1366 case DTYPE_PSXSHM:
1367 pshm_label_associate(fp, vp, ctx);
1368 break;
1369 case DTYPE_PSXSEM:
1370 psem_label_associate(fp, vp, ctx);
1371 break;
1372 case DTYPE_PIPE:
1373 cpipe = (struct pipe *)fp->f_fglob->fg_data;
1374 /* kern/sys_pipe.c:pipe_select() suggests this test. */
1375 if (cpipe == (struct pipe *)-1) {
1376 error = EINVAL;
1377 goto out;
1378 }
1379 PIPE_LOCK(cpipe);
1380 MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx),
1381 cpipe, cpipe->pipe_label, vp, vp->v_label);
1382 PIPE_UNLOCK(cpipe);
1383 break;
1384 case DTYPE_KQUEUE:
1385 case DTYPE_FSEVENTS:
1386 default:
1387 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1388 mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label,
1389 vp, vp->v_label);
1390 break;
1391 }
1392 out:
1393 fp_drop(p, fnp->fd_fd, fp, 0);
1394 return (error);
1395 }