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