]> git.saurik.com Git - apple/xnu.git/blob - security/mac_vfs.c
7cc5561a2ac119cd49fc09bd3dbd2193ce4d7067
[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 /*
396 * Extended attribute 'name' was updated via
397 * vn_setxattr() or vn_removexattr(). Allow the
398 * policy to update the vnode label.
399 */
400 void
401 mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp,
402 const char *name)
403 {
404 int error = 0;
405
406 if (!mac_vnode_enforce || !mac_label_vnodes)
407 return;
408
409 MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp,
410 vp->v_label, name);
411 if (error == 0)
412 return;
413
414 vnode_lock(vp);
415 vnode_relabel(vp);
416 vnode_unlock(vp);
417 return;
418 }
419
420 static int
421 mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp,
422 struct label *intlabel)
423 {
424 kauth_cred_t cred;
425 int error;
426
427 if (!mac_vnode_enforce || !mac_label_vnodes ||
428 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
429 return 0;
430
431 cred = vfs_context_ucred(ctx);
432 MAC_CHECK(vnode_label_store, cred, vp, vp->v_label, intlabel);
433
434 return (error);
435 }
436
437 int
438 mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp,
439 struct label *scriptvnodelabel, struct label *execl)
440 {
441 kauth_cred_t cred;
442 int disjoint = 0;
443 posix_cred_t pcred = posix_cred_get(new);
444
445 if (!mac_proc_enforce && !mac_vnode_enforce)
446 return disjoint;
447
448 /* mark the new cred to indicate "matching" includes the label */
449 pcred->cr_flags |= CRF_MAC_ENFORCE;
450
451 cred = vfs_context_ucred(ctx);
452 MAC_PERFORM(cred_label_update_execve, cred, new, vp, vp->v_label,
453 scriptvnodelabel, execl, &disjoint);
454
455 return (disjoint);
456 }
457
458 int
459 mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp,
460 struct label *scriptvnodelabel, struct label *execlabel, struct proc *p)
461 {
462 kauth_cred_t cred;
463 int result = 0;
464
465 if (!mac_proc_enforce && !mac_vnode_enforce)
466 return result;
467
468 cred = vfs_context_ucred(ctx);
469 MAC_BOOLEAN(cred_check_label_update_execve, ||, cred, vp, vp->v_label,
470 scriptvnodelabel, execlabel, p);
471
472 return (result);
473 }
474
475 int
476 mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp,
477 int acc_mode)
478 {
479 kauth_cred_t cred;
480 int error;
481 int mask;
482
483 if (!mac_vnode_enforce ||
484 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
485 return 0;
486
487 cred = vfs_context_ucred(ctx);
488 /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */
489 mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode);
490 MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask);
491 return (error);
492 }
493
494 int
495 mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp)
496 {
497 kauth_cred_t cred;
498 int error;
499
500 if (!mac_vnode_enforce ||
501 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
502 return (0);
503
504 cred = vfs_context_ucred(ctx);
505 MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
506 return (error);
507 }
508
509 int
510 mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp,
511 struct componentname *cnp)
512 {
513 kauth_cred_t cred;
514 int error;
515
516 if (!mac_vnode_enforce ||
517 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
518 return (0);
519
520 cred = vfs_context_ucred(ctx);
521 MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp);
522 return (error);
523 }
524
525 int
526 mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp,
527 struct componentname *cnp, struct vnode_attr *vap)
528 {
529 kauth_cred_t cred;
530 int error;
531
532 if (!mac_vnode_enforce ||
533 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
534 return (0);
535
536 cred = vfs_context_ucred(ctx);
537 MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
538 return (error);
539 }
540
541 int
542 mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp,
543 struct componentname *cnp)
544 {
545 kauth_cred_t cred;
546 int error;
547
548 if (!mac_vnode_enforce ||
549 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
550 return (0);
551
552 cred = vfs_context_ucred(ctx);
553 MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
554 vp->v_label, cnp);
555 return (error);
556 }
557 #if 0
558 int
559 mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp,
560 acl_type_t type)
561 {
562 kauth_cred_t cred;
563 int error;
564
565 if (!mac_vnode_enforce ||
566 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
567 return (0);
568
569 cred = vfs_context_ucred(ctx);
570 MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
571 return (error);
572 }
573 #endif
574
575 int
576 mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp,
577 const char *name)
578 {
579 kauth_cred_t cred;
580 int error;
581
582 if (!mac_vnode_enforce ||
583 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
584 return (0);
585
586 cred = vfs_context_ucred(ctx);
587 MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name);
588 return (error);
589 }
590 int
591 mac_vnode_check_exchangedata(vfs_context_t ctx,
592 struct vnode *v1, struct vnode *v2)
593 {
594 kauth_cred_t cred;
595 int error;
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 MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label,
603 v2, v2->v_label);
604
605 return (error);
606 }
607
608 #if 0
609 int
610 mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
611 {
612 kauth_cred_t cred;
613 int error;
614
615 if (!mac_vnode_enforce ||
616 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
617 return (0);
618
619 cred = vfs_context_ucred(ctx);
620 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
621 return (error);
622 }
623 #endif
624
625 int
626 mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp,
627 struct attrlist *alist)
628 {
629 kauth_cred_t cred;
630 int error;
631
632 if (!mac_vnode_enforce ||
633 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
634 return (0);
635
636 cred = vfs_context_ucred(ctx);
637 MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist);
638
639 /* Falsify results instead of returning error? */
640 return (error);
641 }
642
643 int
644 mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp,
645 struct image_params *imgp)
646 {
647 kauth_cred_t cred;
648 int error;
649
650 if (!mac_vnode_enforce || !mac_proc_enforce)
651 return (0);
652
653 cred = vfs_context_ucred(ctx);
654 MAC_CHECK(vnode_check_exec, cred, vp, vp->v_label,
655 (imgp != NULL) ? imgp->ip_execlabelp : NULL,
656 (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL,
657 (imgp != NULL) ? &imgp->ip_csflags : NULL);
658 return (error);
659 }
660
661 int
662 mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp)
663 {
664 kauth_cred_t cred;
665 int error;
666
667 if (!mac_vnode_enforce ||
668 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
669 return (0);
670
671 cred = vfs_context_ucred(ctx);
672 MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label);
673 return (error);
674 }
675
676 int
677 mac_vnode_check_signature(struct vnode *vp, unsigned char *sha1,
678 void * signature, size_t size)
679 {
680 int error;
681
682 if (!mac_vnode_enforce || !mac_proc_enforce)
683 return (0);
684
685 MAC_CHECK(vnode_check_signature, vp, vp->v_label, sha1, signature, size);
686 return (error);
687 }
688
689 #if 0
690 int
691 mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
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_getacl, cred, vp, vp->v_label, type);
702 return (error);
703 }
704 #endif
705
706 int
707 mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp,
708 const char *name, struct uio *uio)
709 {
710 kauth_cred_t cred;
711 int error;
712
713 if (!mac_vnode_enforce ||
714 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
715 return (0);
716
717 cred = vfs_context_ucred(ctx);
718 MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
719 name, uio);
720 return (error);
721 }
722
723 int
724 mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd)
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_ioctl, cred, vp, vp->v_label, cmd);
735 return (error);
736 }
737
738 int
739 mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred,
740 struct knote *kn, struct vnode *vp)
741 {
742 kauth_cred_t cred;
743 int error;
744
745 if (!mac_vnode_enforce ||
746 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
747 return (0);
748
749 cred = vfs_context_ucred(ctx);
750 MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp,
751 vp->v_label);
752
753 return (error);
754 }
755
756 int
757 mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp,
758 struct vnode *vp, struct componentname *cnp)
759 {
760 kauth_cred_t cred;
761 int error;
762
763 if (!mac_vnode_enforce ||
764 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
765 return (0);
766
767 cred = vfs_context_ucred(ctx);
768 MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
769 vp->v_label, cnp);
770 return (error);
771 }
772
773 int
774 mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp)
775 {
776 kauth_cred_t cred;
777 int error;
778
779 if (!mac_vnode_enforce ||
780 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
781 return (0);
782
783 cred = vfs_context_ucred(ctx);
784 MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label);
785 return (error);
786 }
787
788 int
789 mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp,
790 struct componentname *cnp)
791 {
792 kauth_cred_t cred;
793 int error;
794
795 if (!mac_vnode_enforce ||
796 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
797 return (0);
798
799 cred = vfs_context_ucred(ctx);
800 MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
801 return (error);
802 }
803
804 int
805 mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode)
806 {
807 kauth_cred_t cred;
808 int error;
809
810 if (!mac_vnode_enforce ||
811 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
812 return (0);
813
814 cred = vfs_context_ucred(ctx);
815 MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode);
816 return (error);
817 }
818
819 int
820 mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred,
821 struct vnode *vp)
822 {
823 kauth_cred_t cred;
824 int error;
825
826 if (!mac_vnode_enforce ||
827 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
828 return (0);
829
830 cred = vfs_context_ucred(ctx);
831 MAC_CHECK(vnode_check_read, cred, file_cred, vp,
832 vp->v_label);
833
834 return (error);
835 }
836
837 int
838 mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp)
839 {
840 kauth_cred_t cred;
841 int error;
842
843 if (!mac_vnode_enforce ||
844 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
845 return (0);
846
847 cred = vfs_context_ucred(ctx);
848 MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
849 return (error);
850 }
851
852 int
853 mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp)
854 {
855 kauth_cred_t cred;
856 int error;
857
858 if (!mac_vnode_enforce ||
859 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
860 return (0);
861
862 cred = vfs_context_ucred(ctx);
863 MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
864 return (error);
865 }
866
867 int
868 mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp,
869 struct label *newlabel)
870 {
871 kauth_cred_t cred;
872 int error;
873
874 if (!mac_vnode_enforce ||
875 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
876 return (0);
877
878 cred = vfs_context_ucred(ctx);
879 MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel);
880
881 return (error);
882 }
883
884 int
885 mac_vnode_check_rename_from(vfs_context_t ctx, struct vnode *dvp,
886 struct vnode *vp, struct componentname *cnp)
887 {
888 kauth_cred_t cred;
889 int error;
890
891 if (!mac_vnode_enforce ||
892 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
893 return (0);
894
895 cred = vfs_context_ucred(ctx);
896 MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
897 vp->v_label, cnp);
898 return (error);
899 }
900
901 int
902 mac_vnode_check_rename_to(vfs_context_t ctx, struct vnode *dvp,
903 struct vnode *vp, int samedir, struct componentname *cnp)
904 {
905 kauth_cred_t cred;
906 int error;
907
908 if (!mac_vnode_enforce ||
909 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
910 return (0);
911
912 cred = vfs_context_ucred(ctx);
913 MAC_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp,
914 vp != NULL ? vp->v_label : NULL, samedir, cnp);
915 return (error);
916 }
917
918 int
919 mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
920 {
921 kauth_cred_t cred;
922 int error;
923
924 if (!mac_vnode_enforce ||
925 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
926 return (0);
927
928 cred = vfs_context_ucred(ctx);
929 MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
930 return (error);
931 }
932
933 int
934 mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist)
935 {
936 kauth_cred_t cred;
937 int error;
938
939 if (!mac_vnode_enforce ||
940 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
941 return (0);
942
943 cred = vfs_context_ucred(ctx);
944 MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist);
945 return (error);
946 }
947
948 int
949 mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which)
950 {
951 kauth_cred_t cred;
952 int error;
953
954 if (!mac_vnode_enforce ||
955 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
956 return (0);
957
958 cred = vfs_context_ucred(ctx);
959 MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which);
960 return (error);
961 }
962
963 #if 0
964 int
965 mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type,
966 struct acl *acl)
967 {
968 kauth_cred_t cred;
969 int error;
970
971 if (!mac_vnode_enforce ||
972 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
973 return (0);
974
975 cred = vfs_context_ucred(ctx);
976 MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl);
977 return (error);
978 }
979 #endif
980
981 int
982 mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp,
983 struct attrlist *alist)
984 {
985 kauth_cred_t cred;
986 int error;
987
988 if (!mac_vnode_enforce ||
989 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
990 return (0);
991
992 cred = vfs_context_ucred(ctx);
993 MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist);
994 return (error);
995 }
996
997 int
998 mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp,
999 const char *name, struct uio *uio)
1000 {
1001 kauth_cred_t cred;
1002 int error;
1003
1004 if (!mac_vnode_enforce ||
1005 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1006 return (0);
1007
1008 cred = vfs_context_ucred(ctx);
1009 MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
1010 name, uio);
1011 return (error);
1012 }
1013
1014 int
1015 mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
1016 {
1017 kauth_cred_t cred;
1018 int error;
1019
1020 if (!mac_vnode_enforce ||
1021 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1022 return (0);
1023
1024 cred = vfs_context_ucred(ctx);
1025 MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
1026 return (error);
1027 }
1028
1029 int
1030 mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
1031 {
1032 kauth_cred_t cred;
1033 int error;
1034
1035 if (!mac_vnode_enforce ||
1036 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1037 return (0);
1038
1039 cred = vfs_context_ucred(ctx);
1040 MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
1041 return (error);
1042 }
1043
1044 int
1045 mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid,
1046 gid_t gid)
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_setowner, cred, vp, vp->v_label, uid, gid);
1057 return (error);
1058 }
1059
1060 int
1061 mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp,
1062 struct timespec atime, struct timespec mtime)
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_setutimes, cred, vp, vp->v_label, atime,
1073 mtime);
1074 return (error);
1075 }
1076
1077 int
1078 mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred,
1079 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_stat, cred, file_cred, vp,
1090 vp->v_label);
1091 return (error);
1092 }
1093
1094 int
1095 mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred,
1096 struct vnode *vp)
1097 {
1098 kauth_cred_t cred;
1099 int error;
1100
1101 if (!mac_vnode_enforce ||
1102 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1103 return (0);
1104
1105 cred = vfs_context_ucred(ctx);
1106 MAC_CHECK(vnode_check_truncate, cred, file_cred, vp,
1107 vp->v_label);
1108
1109 return (error);
1110 }
1111
1112 int
1113 mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred,
1114 struct vnode *vp)
1115 {
1116 kauth_cred_t cred;
1117 int error;
1118
1119 if (!mac_vnode_enforce ||
1120 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1121 return (0);
1122
1123 cred = vfs_context_ucred(ctx);
1124 MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label);
1125
1126 return (error);
1127 }
1128
1129 int
1130 mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp,
1131 struct componentname *cnp, struct vnode_attr *vap)
1132 {
1133 kauth_cred_t cred;
1134 int error;
1135
1136 if (!mac_vnode_enforce ||
1137 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1138 return (0);
1139
1140 cred = vfs_context_ucred(ctx);
1141 MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap);
1142 return (error);
1143 }
1144
1145 int
1146 mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp)
1147 {
1148 kauth_cred_t cred;
1149 int error;
1150
1151 if (!mac_vnode_enforce ||
1152 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1153 return (0);
1154
1155 cred = vfs_context_ucred(ctx);
1156 MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label);
1157 return (error);
1158 }
1159
1160 void
1161 mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel)
1162 {
1163 kauth_cred_t cred = vfs_context_ucred(ctx);
1164 struct label *tmpl = NULL;
1165
1166 if (vp->v_label == NULL)
1167 tmpl = mac_vnode_label_alloc();
1168
1169 vnode_lock(vp);
1170
1171 /* recheck after lock */
1172 if (vp->v_label == NULL) {
1173 vp->v_label = tmpl;
1174 tmpl = NULL;
1175 }
1176
1177 MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel);
1178 vnode_unlock(vp);
1179
1180 if (tmpl != NULL)
1181 mac_vnode_label_free(tmpl);
1182 }
1183
1184 void
1185 mac_mount_label_associate(vfs_context_t ctx, struct mount *mp)
1186 {
1187 kauth_cred_t cred = vfs_context_ucred(ctx);
1188
1189 /* XXX: eventually this logic may be handled by the policy? */
1190
1191 /* We desire MULTILABEL for the root filesystem. */
1192 if ((mp->mnt_flag & MNT_ROOTFS) &&
1193 (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0))
1194 mp->mnt_flag |= MNT_MULTILABEL;
1195
1196 /* MULTILABEL on DEVFS. */
1197 if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0)
1198 mp->mnt_flag |= MNT_MULTILABEL;
1199
1200 /* MULTILABEL on FDESC pseudo-filesystem. */
1201 if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0)
1202 mp->mnt_flag |= MNT_MULTILABEL;
1203
1204 /* MULTILABEL on all NFS filesystems. */
1205 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0)
1206 mp->mnt_flag |= MNT_MULTILABEL;
1207
1208 /* MULTILABEL on all AFP filesystems. */
1209 if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0)
1210 mp->mnt_flag |= MNT_MULTILABEL;
1211
1212 if (mp->mnt_vtable != NULL) {
1213 /* Any filesystem that supports native XATTRs. */
1214 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR))
1215 mp->mnt_flag |= MNT_MULTILABEL;
1216
1217 /* Filesystem does not support multilabel. */
1218 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) &&
1219 (mp->mnt_flag & MNT_MULTILABEL))
1220 mp->mnt_flag &= ~MNT_MULTILABEL;
1221 }
1222
1223 MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel);
1224 #if MAC_DEBUG
1225 printf("MAC Framework enabling %s support: %s -> %s (%s)\n",
1226 mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel",
1227 mp->mnt_vfsstat.f_mntfromname,
1228 mp->mnt_vfsstat.f_mntonname,
1229 mp->mnt_vfsstat.f_fstypename);
1230 #endif
1231 }
1232
1233 int
1234 mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp,
1235 struct componentname *cnp, const char *vfc_name)
1236 {
1237 kauth_cred_t cred;
1238 int error;
1239
1240 if (!mac_vnode_enforce ||
1241 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1242 return (0);
1243
1244 cred = vfs_context_ucred(ctx);
1245 MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name);
1246
1247 return (error);
1248 }
1249
1250 int
1251 mac_mount_check_remount(vfs_context_t ctx, struct mount *mp)
1252 {
1253 kauth_cred_t cred;
1254 int error;
1255
1256 if (!mac_vnode_enforce ||
1257 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1258 return (0);
1259
1260 cred = vfs_context_ucred(ctx);
1261 MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel);
1262
1263 return (error);
1264 }
1265
1266 int
1267 mac_mount_check_umount(vfs_context_t ctx, struct mount *mp)
1268 {
1269 kauth_cred_t cred;
1270 int error;
1271
1272 if (!mac_vnode_enforce ||
1273 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1274 return (0);
1275
1276 cred = vfs_context_ucred(ctx);
1277 MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel);
1278
1279 return (error);
1280 }
1281
1282 int
1283 mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp,
1284 struct vfs_attr *vfa)
1285 {
1286 kauth_cred_t cred;
1287 int error;
1288
1289 if (!mac_vnode_enforce ||
1290 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1291 return (0);
1292
1293 cred = vfs_context_ucred(ctx);
1294 MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa);
1295 return (error);
1296 }
1297
1298 int
1299 mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp,
1300 struct vfs_attr *vfa)
1301 {
1302 kauth_cred_t cred;
1303 int error;
1304
1305 if (!mac_vnode_enforce ||
1306 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1307 return (0);
1308
1309 cred = vfs_context_ucred(ctx);
1310 MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa);
1311 return (error);
1312 }
1313
1314 int
1315 mac_mount_check_stat(vfs_context_t ctx, struct mount *mount)
1316 {
1317 kauth_cred_t cred;
1318 int error;
1319
1320 if (!mac_vnode_enforce ||
1321 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1322 return (0);
1323
1324 cred = vfs_context_ucred(ctx);
1325 MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel);
1326
1327 return (error);
1328 }
1329
1330 int
1331 mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount)
1332 {
1333 kauth_cred_t cred;
1334 int error;
1335
1336 if (!mac_vnode_enforce ||
1337 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1338 return (0);
1339
1340 cred = vfs_context_ucred(ctx);
1341 MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel);
1342
1343 return (error);
1344 }
1345
1346 int
1347 mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd)
1348 {
1349 kauth_cred_t cred;
1350 int error;
1351
1352 if (!mac_vnode_enforce ||
1353 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1354 return (0);
1355
1356 cred = vfs_context_ucred(ctx);
1357 MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd);
1358
1359 return (error);
1360 }
1361
1362 void
1363 mac_devfs_label_associate_device(dev_t dev, struct devnode *de,
1364 const char *fullpath)
1365 {
1366 if (!mac_device_enforce)
1367 return;
1368
1369 MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label,
1370 fullpath);
1371 }
1372
1373 void
1374 mac_devfs_label_associate_directory(const char *dirname, int dirnamelen,
1375 struct devnode *de, const char *fullpath)
1376 {
1377 if (!mac_device_enforce)
1378 return;
1379
1380 MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de,
1381 de->dn_label, fullpath);
1382 }
1383
1384 int
1385 vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context)
1386 {
1387 int error;
1388
1389 if (!mac_vnode_enforce || !mac_label_vnodes)
1390 return (0);
1391
1392 if (vp->v_mount == NULL) {
1393 printf("vn_setlabel: null v_mount\n");
1394 if (vp->v_type != VNON)
1395 printf("vn_setlabel: null v_mount with non-VNON\n");
1396 return (EBADF);
1397 }
1398
1399 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1400 return (ENOTSUP);
1401
1402 /*
1403 * Multi-phase commit. First check the policies to confirm the
1404 * change is OK. Then commit via the filesystem. Finally,
1405 * update the actual vnode label. Question: maybe the filesystem
1406 * should update the vnode at the end as part of VNOP_SETLABEL()?
1407 */
1408 error = mac_vnode_check_label_update(context, vp, intlabel);
1409 if (error)
1410 return (error);
1411
1412 error = VNOP_SETLABEL(vp, intlabel, context);
1413 if (error == ENOTSUP) {
1414 error = mac_vnode_label_store(context, vp,
1415 intlabel);
1416 if (error) {
1417 printf("%s: mac_vnode_label_store failed %d\n",
1418 __func__, error);
1419 return (error);
1420 }
1421 mac_vnode_label_update(context, vp, intlabel);
1422 } else
1423 if (error) {
1424 printf("vn_setlabel: vop setlabel failed %d\n", error);
1425 return (error);
1426 }
1427
1428 return (0);
1429 }
1430
1431 int
1432 mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
1433 struct vnode *vp, vfs_context_t ctx)
1434 {
1435 struct fileproc *fp;
1436 struct socket *so;
1437 struct pipe *cpipe;
1438 struct vnode *fvp;
1439 struct proc *p;
1440 int error;
1441
1442 error = 0;
1443
1444 /*
1445 * If no backing file, let the policy choose which label to use.
1446 */
1447 if (fnp->fd_fd == -1) {
1448 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1449 mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label);
1450 return (0);
1451 }
1452
1453 p = vfs_context_proc(ctx);
1454 error = fp_lookup(p, fnp->fd_fd, &fp, 0);
1455 if (error)
1456 return (error);
1457
1458 if (fp->f_fglob == NULL) {
1459 error = EBADF;
1460 goto out;
1461 }
1462
1463 switch (fp->f_fglob->fg_type) {
1464 case DTYPE_VNODE:
1465 fvp = (struct vnode *)fp->f_fglob->fg_data;
1466 if ((error = vnode_getwithref(fvp)))
1467 goto out;
1468 MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label);
1469 (void)vnode_put(fvp);
1470 break;
1471 case DTYPE_SOCKET:
1472 so = (struct socket *)fp->f_fglob->fg_data;
1473 socket_lock(so, 1);
1474 MAC_PERFORM(vnode_label_associate_socket,
1475 vfs_context_ucred(ctx), (socket_t)so, so->so_label,
1476 vp, vp->v_label);
1477 socket_unlock(so, 1);
1478 break;
1479 case DTYPE_PSXSHM:
1480 pshm_label_associate(fp, vp, ctx);
1481 break;
1482 case DTYPE_PSXSEM:
1483 psem_label_associate(fp, vp, ctx);
1484 break;
1485 case DTYPE_PIPE:
1486 cpipe = (struct pipe *)fp->f_fglob->fg_data;
1487 /* kern/sys_pipe.c:pipe_select() suggests this test. */
1488 if (cpipe == (struct pipe *)-1) {
1489 error = EINVAL;
1490 goto out;
1491 }
1492 PIPE_LOCK(cpipe);
1493 MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx),
1494 cpipe, cpipe->pipe_label, vp, vp->v_label);
1495 PIPE_UNLOCK(cpipe);
1496 break;
1497 case DTYPE_KQUEUE:
1498 case DTYPE_FSEVENTS:
1499 default:
1500 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1501 mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label,
1502 vp, vp->v_label);
1503 break;
1504 }
1505 out:
1506 fp_drop(p, fnp->fd_fd, fp, 0);
1507 return (error);
1508 }