]> git.saurik.com Git - apple/xnu.git/blame - security/mac_vfs.c
xnu-2422.90.20.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
39236c6e
A
408void
409mac_vnode_notify_link(vfs_context_t ctx, struct vnode *vp,
410 struct vnode *dvp, struct componentname *cnp)
411{
412 kauth_cred_t cred;
413
414 if (!mac_vnode_enforce ||
415 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
416 return;
417
418 cred = vfs_context_ucred(ctx);
419 MAC_PERFORM(vnode_notify_link, cred, dvp, dvp->v_label, vp, vp->v_label, cnp);
420}
421
2d21ac55
A
422/*
423 * Extended attribute 'name' was updated via
424 * vn_setxattr() or vn_removexattr(). Allow the
425 * policy to update the vnode label.
426 */
427void
428mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp,
429 const char *name)
430{
431 int error = 0;
432
b0d623f7 433 if (!mac_vnode_enforce || !mac_label_vnodes)
2d21ac55
A
434 return;
435
436 MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp,
437 vp->v_label, name);
438 if (error == 0)
439 return;
440
441 vnode_lock(vp);
442 vnode_relabel(vp);
443 vnode_unlock(vp);
444 return;
445}
446
447static int
448mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp,
449 struct label *intlabel)
450{
451 kauth_cred_t cred;
452 int error;
453
b0d623f7 454 if (!mac_vnode_enforce || !mac_label_vnodes ||
2d21ac55
A
455 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
456 return 0;
457
458 cred = vfs_context_ucred(ctx);
459 MAC_CHECK(vnode_label_store, cred, vp, vp->v_label, intlabel);
460
461 return (error);
462}
463
c910b4d9 464int
2d21ac55 465mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp,
39236c6e
A
466 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl,
467 void *macextensions)
2d21ac55
A
468{
469 kauth_cred_t cred;
c910b4d9 470 int disjoint = 0;
6d2010ae 471 posix_cred_t pcred = posix_cred_get(new);
2d21ac55
A
472
473 if (!mac_proc_enforce && !mac_vnode_enforce)
c910b4d9 474 return disjoint;
2d21ac55
A
475
476 /* mark the new cred to indicate "matching" includes the label */
6d2010ae 477 pcred->cr_flags |= CRF_MAC_ENFORCE;
2d21ac55
A
478
479 cred = vfs_context_ucred(ctx);
39236c6e
A
480
481 /*
482 * NB: Cannot use MAC_PERFORM macro because we need a sequence point after
483 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
484 * spawnattrlen as an argument to the hook.
485 */
486 {
487 struct mac_policy_conf *mpc;
488 u_int i;
489
490 for (i = 0; i< mac_policy_list.staticmax; i++) {
491 mpc = mac_policy_list.entries[i].mpc;
492 if (mpc == NULL)
493 continue;
494
495 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
496 if (hook == NULL)
497 continue;
498
499 size_t spawnattrlen = 0;
500 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
501
502 hook(cred, new, vfs_context_proc(ctx), vp, scriptvp, vp->v_label,
503 scriptvnodelabel, execl, spawnattr, spawnattrlen, &disjoint);
504 }
505 if (mac_policy_list_conditional_busy() != 0) {
506 for (; i <= mac_policy_list.maxindex; i++) {
507 mpc = mac_policy_list.entries[i].mpc;
508 if (mpc == NULL)
509 continue;
510
511 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
512 if (hook == NULL)
513 continue;
514
515 size_t spawnattrlen = 0;
516 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
517
518 hook(cred, new, vfs_context_proc(ctx), vp, scriptvp, vp->v_label,
519 scriptvnodelabel, execl, spawnattr, spawnattrlen, &disjoint);
520 }
521 mac_policy_list_unbusy();
522 }
523 }
c910b4d9
A
524
525 return (disjoint);
2d21ac55
A
526}
527
528int
529mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp,
39236c6e
A
530 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel,
531 struct proc *p, void *macextensions)
2d21ac55
A
532{
533 kauth_cred_t cred;
534 int result = 0;
535
536 if (!mac_proc_enforce && !mac_vnode_enforce)
537 return result;
538
539 cred = vfs_context_ucred(ctx);
39236c6e
A
540
541 /*
542 * NB: Cannot use MAC_BOOLEAN macro because we need a sequence point after
543 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
544 * spawnattrlen as an argument to the hook.
545 */
546 {
547 struct mac_policy_conf *mpc;
548 u_int i;
549
550 for (i = 0; i< mac_policy_list.staticmax; i++) {
551 mpc = mac_policy_list.entries[i].mpc;
552 if (mpc == NULL)
553 continue;
554
555 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
556 if (hook == NULL)
557 continue;
558
559 size_t spawnattrlen = 0;
560 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
561
562 result = result || hook(cred, vp, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
563 }
564 if (mac_policy_list_conditional_busy() != 0) {
565 for (; i <= mac_policy_list.maxindex; i++) {
566 mpc = mac_policy_list.entries[i].mpc;
567 if (mpc == NULL)
568 continue;
569
570 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
571 if (hook == NULL)
572 continue;
573
574 size_t spawnattrlen = 0;
575 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
576
577 result = result || hook(cred, vp, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
578 }
579 mac_policy_list_unbusy();
580 }
581 }
2d21ac55
A
582
583 return (result);
584}
585
586int
587mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp,
588 int acc_mode)
589{
590 kauth_cred_t cred;
591 int error;
592 int mask;
593
594 if (!mac_vnode_enforce ||
595 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
596 return 0;
597
598 cred = vfs_context_ucred(ctx);
599 /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */
600 mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode);
601 MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask);
602 return (error);
603 }
604
605int
606mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp)
607{
608 kauth_cred_t cred;
609 int error;
610
611 if (!mac_vnode_enforce ||
612 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
613 return (0);
614
615 cred = vfs_context_ucred(ctx);
616 MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
617 return (error);
618}
619
620int
621mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp,
622 struct componentname *cnp)
623{
624 kauth_cred_t cred;
625 int error;
626
627 if (!mac_vnode_enforce ||
628 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
629 return (0);
630
631 cred = vfs_context_ucred(ctx);
632 MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp);
633 return (error);
634}
635
636int
637mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp,
638 struct componentname *cnp, struct vnode_attr *vap)
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_create, cred, dvp, dvp->v_label, cnp, vap);
649 return (error);
650}
651
652int
653mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp,
654 struct componentname *cnp)
655{
656 kauth_cred_t cred;
657 int error;
658
659 if (!mac_vnode_enforce ||
660 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
661 return (0);
662
663 cred = vfs_context_ucred(ctx);
664 MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
665 vp->v_label, cnp);
666 return (error);
667}
668#if 0
669int
670mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp,
671 acl_type_t type)
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_deleteacl, cred, vp, vp->v_label, type);
682 return (error);
683}
684#endif
685
686int
687mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp,
688 const char *name)
689{
690 kauth_cred_t cred;
691 int error;
692
693 if (!mac_vnode_enforce ||
694 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
695 return (0);
696
697 cred = vfs_context_ucred(ctx);
698 MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name);
699 return (error);
700}
701int
702mac_vnode_check_exchangedata(vfs_context_t ctx,
703 struct vnode *v1, struct vnode *v2)
704{
705 kauth_cred_t cred;
706 int error;
707
708 if (!mac_vnode_enforce ||
709 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
710 return (0);
711
712 cred = vfs_context_ucred(ctx);
713 MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label,
714 v2, v2->v_label);
715
716 return (error);
717}
718
719#if 0
720int
721mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
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_getacl, cred, vp, vp->v_label, type);
732 return (error);
733}
734#endif
735
736int
737mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp,
738 struct attrlist *alist)
739{
740 kauth_cred_t cred;
741 int error;
742
743 if (!mac_vnode_enforce ||
744 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
745 return (0);
746
747 cred = vfs_context_ucred(ctx);
748 MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist);
749
750 /* Falsify results instead of returning error? */
751 return (error);
752}
753
754int
755mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp,
756 struct image_params *imgp)
757{
758 kauth_cred_t cred;
39236c6e 759 int error = 0;
2d21ac55
A
760
761 if (!mac_vnode_enforce || !mac_proc_enforce)
762 return (0);
763
764 cred = vfs_context_ucred(ctx);
39236c6e
A
765
766 /*
767 * NB: Cannot use MAC_CHECK macro because we need a sequence point after
768 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
769 * spawnattrlen as an argument to the hook.
770 */
771 {
772 struct mac_policy_conf *mpc;
773 u_int i;
774
775 for (i = 0; i< mac_policy_list.staticmax; i++) {
776 mpc = mac_policy_list.entries[i].mpc;
777 if (mpc == NULL)
778 continue;
779
780 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
781 if (hook == NULL)
782 continue;
783
784 size_t spawnattrlen = 0;
785 void *spawnattr = (imgp != NULL) ? exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen) : NULL;
786
787 error = mac_error_select(
788 hook(cred, vp, vp->v_label,
789 (imgp != NULL) ? imgp->ip_execlabelp : NULL,
790 (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL,
791 (imgp != NULL) ? &imgp->ip_csflags : NULL,
792 spawnattr, spawnattrlen), error);
793 }
794 if (mac_policy_list_conditional_busy() != 0) {
795 for (; i <= mac_policy_list.maxindex; i++) {
796 mpc = mac_policy_list.entries[i].mpc;
797 if (mpc == NULL)
798 continue;
799
800 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
801 if (hook == NULL)
802 continue;
803
804 size_t spawnattrlen = 0;
805 void *spawnattr = (imgp != NULL) ? exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen) : NULL;
806
807 error = mac_error_select(
808 hook(cred, vp, vp->v_label,
809 (imgp != NULL) ? imgp->ip_execlabelp : NULL,
810 (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL,
811 (imgp != NULL) ? &imgp->ip_csflags : NULL,
812 spawnattr, spawnattrlen), error);
813 }
814 mac_policy_list_unbusy();
815 }
816 }
817
2d21ac55
A
818 return (error);
819}
820
6d2010ae
A
821int
822mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp)
823{
824 kauth_cred_t cred;
825 int error;
826
827 if (!mac_vnode_enforce ||
828 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
829 return (0);
830
831 cred = vfs_context_ucred(ctx);
832 MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label);
833 return (error);
834}
835
593a1d5f 836int
39236c6e
A
837mac_vnode_check_signature(struct vnode *vp, off_t macho_offset,
838 unsigned char *sha1,
593a1d5f
A
839 void * signature, size_t size)
840{
841 int error;
842
843 if (!mac_vnode_enforce || !mac_proc_enforce)
844 return (0);
845
39236c6e 846 MAC_CHECK(vnode_check_signature, vp, vp->v_label, macho_offset, sha1, signature, size);
593a1d5f
A
847 return (error);
848}
849
2d21ac55
A
850#if 0
851int
852mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
853{
854 kauth_cred_t cred;
855 int error;
856
857 if (!mac_vnode_enforce ||
858 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
859 return (0);
860
861 cred = vfs_context_ucred(ctx);
862 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
863 return (error);
864}
865#endif
866
867int
868mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp,
869 const char *name, struct uio *uio)
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_getextattr, cred, vp, vp->v_label,
880 name, uio);
881 return (error);
882}
883
884int
885mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd)
886{
887 kauth_cred_t cred;
888 int error;
889
890 if (!mac_vnode_enforce ||
891 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
892 return (0);
893
894 cred = vfs_context_ucred(ctx);
895 MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd);
896 return (error);
897}
898
899int
900mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred,
901 struct knote *kn, struct vnode *vp)
902{
903 kauth_cred_t cred;
904 int error;
905
906 if (!mac_vnode_enforce ||
907 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
908 return (0);
909
910 cred = vfs_context_ucred(ctx);
911 MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp,
912 vp->v_label);
913
914 return (error);
915}
916
917int
918mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp,
919 struct vnode *vp, struct componentname *cnp)
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_link, cred, dvp, dvp->v_label, vp,
930 vp->v_label, cnp);
931 return (error);
932}
933
934int
935mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp)
936{
937 kauth_cred_t cred;
938 int error;
939
940 if (!mac_vnode_enforce ||
941 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
942 return (0);
943
944 cred = vfs_context_ucred(ctx);
945 MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label);
946 return (error);
947}
948
949int
950mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp,
951 struct componentname *cnp)
952{
953 kauth_cred_t cred;
954 int error;
955
956 if (!mac_vnode_enforce ||
957 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
958 return (0);
959
960 cred = vfs_context_ucred(ctx);
961 MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
962 return (error);
963}
964
965int
966mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode)
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_open, cred, vp, vp->v_label, acc_mode);
977 return (error);
978}
979
980int
981mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred,
982 struct vnode *vp)
983{
984 kauth_cred_t cred;
985 int error;
986
987 if (!mac_vnode_enforce ||
988 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
989 return (0);
990
991 cred = vfs_context_ucred(ctx);
992 MAC_CHECK(vnode_check_read, cred, file_cred, vp,
993 vp->v_label);
994
995 return (error);
996}
997
998int
999mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp)
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_readdir, cred, dvp, dvp->v_label);
1010 return (error);
1011}
1012
1013int
1014mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp)
1015{
1016 kauth_cred_t cred;
1017 int error;
1018
1019 if (!mac_vnode_enforce ||
1020 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1021 return (0);
1022
1023 cred = vfs_context_ucred(ctx);
1024 MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
1025 return (error);
1026}
1027
1028int
1029mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp,
1030 struct label *newlabel)
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_label_update, cred, vp, vp->v_label, newlabel);
1041
1042 return (error);
1043}
1044
1045int
1046mac_vnode_check_rename_from(vfs_context_t ctx, struct vnode *dvp,
1047 struct vnode *vp, struct componentname *cnp)
1048{
1049 kauth_cred_t cred;
1050 int error;
1051
1052 if (!mac_vnode_enforce ||
1053 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1054 return (0);
1055
1056 cred = vfs_context_ucred(ctx);
1057 MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
1058 vp->v_label, cnp);
1059 return (error);
1060}
1061
1062int
1063mac_vnode_check_rename_to(vfs_context_t ctx, struct vnode *dvp,
1064 struct vnode *vp, int samedir, struct componentname *cnp)
1065{
1066 kauth_cred_t cred;
1067 int error;
1068
1069 if (!mac_vnode_enforce ||
1070 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1071 return (0);
1072
1073 cred = vfs_context_ucred(ctx);
1074 MAC_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp,
1075 vp != NULL ? vp->v_label : NULL, samedir, cnp);
1076 return (error);
1077}
1078
1079int
1080mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
1081{
1082 kauth_cred_t cred;
1083 int error;
1084
1085 if (!mac_vnode_enforce ||
1086 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1087 return (0);
1088
1089 cred = vfs_context_ucred(ctx);
1090 MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
1091 return (error);
1092}
1093
6d2010ae
A
1094int
1095mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist)
1096{
1097 kauth_cred_t cred;
1098 int error;
1099
1100 if (!mac_vnode_enforce ||
1101 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1102 return (0);
1103
1104 cred = vfs_context_ucred(ctx);
1105 MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist);
1106 return (error);
1107}
1108
2d21ac55
A
1109int
1110mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which)
1111{
1112 kauth_cred_t cred;
1113 int error;
1114
1115 if (!mac_vnode_enforce ||
1116 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1117 return (0);
1118
1119 cred = vfs_context_ucred(ctx);
1120 MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which);
1121 return (error);
1122}
1123
1124#if 0
1125int
1126mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type,
1127 struct acl *acl)
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_setacl, cred, vp, vp->v_label, type, acl);
1138 return (error);
1139}
1140#endif
1141
1142int
1143mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp,
1144 struct attrlist *alist)
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_setattrlist, cred, vp, vp->v_label, alist);
1155 return (error);
1156}
1157
1158int
1159mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp,
1160 const char *name, struct uio *uio)
1161{
1162 kauth_cred_t cred;
1163 int error;
1164
1165 if (!mac_vnode_enforce ||
1166 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1167 return (0);
1168
1169 cred = vfs_context_ucred(ctx);
1170 MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
1171 name, uio);
1172 return (error);
1173}
1174
1175int
1176mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
1177{
1178 kauth_cred_t cred;
1179 int error;
1180
1181 if (!mac_vnode_enforce ||
1182 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1183 return (0);
1184
1185 cred = vfs_context_ucred(ctx);
1186 MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
1187 return (error);
1188}
1189
1190int
1191mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
1192{
1193 kauth_cred_t cred;
1194 int error;
1195
1196 if (!mac_vnode_enforce ||
1197 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1198 return (0);
1199
1200 cred = vfs_context_ucred(ctx);
1201 MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
1202 return (error);
1203}
1204
1205int
1206mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid,
1207 gid_t gid)
1208{
1209 kauth_cred_t cred;
1210 int error;
1211
1212 if (!mac_vnode_enforce ||
1213 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1214 return (0);
1215
1216 cred = vfs_context_ucred(ctx);
1217 MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid);
1218 return (error);
1219}
1220
1221int
1222mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp,
1223 struct timespec atime, struct timespec mtime)
1224{
1225 kauth_cred_t cred;
1226 int error;
1227
1228 if (!mac_vnode_enforce ||
1229 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1230 return (0);
1231
1232 cred = vfs_context_ucred(ctx);
1233 MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime,
1234 mtime);
1235 return (error);
1236}
1237
1238int
1239mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred,
1240 struct vnode *vp)
1241{
1242 kauth_cred_t cred;
1243 int error;
1244
1245 if (!mac_vnode_enforce ||
1246 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1247 return (0);
1248
1249 cred = vfs_context_ucred(ctx);
1250 MAC_CHECK(vnode_check_stat, cred, file_cred, vp,
1251 vp->v_label);
1252 return (error);
1253}
1254
1255int
1256mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred,
1257 struct vnode *vp)
1258{
1259 kauth_cred_t cred;
1260 int error;
1261
1262 if (!mac_vnode_enforce ||
1263 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1264 return (0);
1265
1266 cred = vfs_context_ucred(ctx);
1267 MAC_CHECK(vnode_check_truncate, cred, file_cred, vp,
1268 vp->v_label);
1269
1270 return (error);
1271}
1272
1273int
1274mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred,
1275 struct vnode *vp)
1276{
1277 kauth_cred_t cred;
1278 int error;
1279
1280 if (!mac_vnode_enforce ||
1281 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1282 return (0);
1283
1284 cred = vfs_context_ucred(ctx);
1285 MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label);
1286
1287 return (error);
1288}
1289
b0d623f7
A
1290int
1291mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp,
1292 struct componentname *cnp, struct vnode_attr *vap)
1293{
1294 kauth_cred_t cred;
1295 int error;
1296
1297 if (!mac_vnode_enforce ||
1298 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1299 return (0);
1300
1301 cred = vfs_context_ucred(ctx);
1302 MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap);
1303 return (error);
1304}
1305
1306int
1307mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp)
1308{
1309 kauth_cred_t cred;
1310 int error;
1311
1312 if (!mac_vnode_enforce ||
1313 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1314 return (0);
1315
1316 cred = vfs_context_ucred(ctx);
1317 MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label);
1318 return (error);
1319}
1320
2d21ac55
A
1321void
1322mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel)
1323{
1324 kauth_cred_t cred = vfs_context_ucred(ctx);
b0d623f7
A
1325 struct label *tmpl = NULL;
1326
1327 if (vp->v_label == NULL)
1328 tmpl = mac_vnode_label_alloc();
2d21ac55
A
1329
1330 vnode_lock(vp);
b0d623f7
A
1331
1332 /* recheck after lock */
1333 if (vp->v_label == NULL) {
1334 vp->v_label = tmpl;
1335 tmpl = NULL;
1336 }
1337
2d21ac55
A
1338 MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel);
1339 vnode_unlock(vp);
b0d623f7
A
1340
1341 if (tmpl != NULL)
1342 mac_vnode_label_free(tmpl);
2d21ac55
A
1343}
1344
39236c6e
A
1345int
1346mac_vnode_find_sigs(struct proc *p, struct vnode *vp, off_t offset)
1347{
1348 int error;
1349
1350 if (!mac_vnode_enforce || !mac_proc_enforce)
1351 return (0);
1352
1353 MAC_CHECK(vnode_find_sigs, p, vp, offset, vp->v_label);
1354
1355 return (error);
1356}
1357
2d21ac55
A
1358void
1359mac_mount_label_associate(vfs_context_t ctx, struct mount *mp)
1360{
1361 kauth_cred_t cred = vfs_context_ucred(ctx);
1362
1363 /* XXX: eventually this logic may be handled by the policy? */
1364
1365 /* We desire MULTILABEL for the root filesystem. */
1366 if ((mp->mnt_flag & MNT_ROOTFS) &&
1367 (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0))
1368 mp->mnt_flag |= MNT_MULTILABEL;
1369
1370 /* MULTILABEL on DEVFS. */
1371 if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0)
1372 mp->mnt_flag |= MNT_MULTILABEL;
1373
1374 /* MULTILABEL on FDESC pseudo-filesystem. */
1375 if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0)
1376 mp->mnt_flag |= MNT_MULTILABEL;
1377
1378 /* MULTILABEL on all NFS filesystems. */
1379 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0)
1380 mp->mnt_flag |= MNT_MULTILABEL;
1381
1382 /* MULTILABEL on all AFP filesystems. */
1383 if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0)
1384 mp->mnt_flag |= MNT_MULTILABEL;
1385
1386 if (mp->mnt_vtable != NULL) {
1387 /* Any filesystem that supports native XATTRs. */
1388 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR))
1389 mp->mnt_flag |= MNT_MULTILABEL;
1390
1391 /* Filesystem does not support multilabel. */
1392 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) &&
1393 (mp->mnt_flag & MNT_MULTILABEL))
1394 mp->mnt_flag &= ~MNT_MULTILABEL;
1395 }
1396
1397 MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel);
316670eb 1398#if DEBUG
2d21ac55
A
1399 printf("MAC Framework enabling %s support: %s -> %s (%s)\n",
1400 mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel",
1401 mp->mnt_vfsstat.f_mntfromname,
1402 mp->mnt_vfsstat.f_mntonname,
1403 mp->mnt_vfsstat.f_fstypename);
1404#endif
1405}
1406
1407int
1408mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp,
1409 struct componentname *cnp, const char *vfc_name)
1410{
1411 kauth_cred_t cred;
1412 int error;
1413
1414 if (!mac_vnode_enforce ||
1415 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1416 return (0);
1417
1418 cred = vfs_context_ucred(ctx);
1419 MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name);
1420
1421 return (error);
1422}
1423
1424int
1425mac_mount_check_remount(vfs_context_t ctx, struct mount *mp)
1426{
1427 kauth_cred_t cred;
1428 int error;
1429
1430 if (!mac_vnode_enforce ||
1431 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1432 return (0);
1433
1434 cred = vfs_context_ucred(ctx);
1435 MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel);
1436
1437 return (error);
1438}
1439
1440int
1441mac_mount_check_umount(vfs_context_t ctx, struct mount *mp)
1442{
1443 kauth_cred_t cred;
1444 int error;
1445
1446 if (!mac_vnode_enforce ||
1447 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1448 return (0);
1449
1450 cred = vfs_context_ucred(ctx);
1451 MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel);
1452
1453 return (error);
1454}
1455
1456int
1457mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp,
1458 struct vfs_attr *vfa)
1459{
1460 kauth_cred_t cred;
1461 int error;
1462
1463 if (!mac_vnode_enforce ||
1464 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1465 return (0);
1466
1467 cred = vfs_context_ucred(ctx);
1468 MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa);
1469 return (error);
1470}
1471
1472int
1473mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp,
1474 struct vfs_attr *vfa)
1475{
1476 kauth_cred_t cred;
1477 int error;
1478
1479 if (!mac_vnode_enforce ||
1480 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1481 return (0);
1482
1483 cred = vfs_context_ucred(ctx);
1484 MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa);
1485 return (error);
1486}
1487
1488int
1489mac_mount_check_stat(vfs_context_t ctx, struct mount *mount)
1490{
1491 kauth_cred_t cred;
1492 int error;
1493
1494 if (!mac_vnode_enforce ||
1495 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1496 return (0);
1497
1498 cred = vfs_context_ucred(ctx);
1499 MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel);
1500
1501 return (error);
1502}
1503
1504int
1505mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount)
1506{
1507 kauth_cred_t cred;
1508 int error;
1509
1510 if (!mac_vnode_enforce ||
1511 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1512 return (0);
1513
1514 cred = vfs_context_ucred(ctx);
1515 MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel);
1516
1517 return (error);
1518}
1519
1520int
1521mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd)
1522{
1523 kauth_cred_t cred;
1524 int error;
1525
1526 if (!mac_vnode_enforce ||
1527 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1528 return (0);
1529
1530 cred = vfs_context_ucred(ctx);
1531 MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd);
1532
1533 return (error);
1534}
1535
1536void
1537mac_devfs_label_associate_device(dev_t dev, struct devnode *de,
1538 const char *fullpath)
1539{
1540 if (!mac_device_enforce)
1541 return;
1542
1543 MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label,
1544 fullpath);
1545}
1546
1547void
1548mac_devfs_label_associate_directory(const char *dirname, int dirnamelen,
1549 struct devnode *de, const char *fullpath)
1550{
1551 if (!mac_device_enforce)
1552 return;
1553
1554 MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de,
1555 de->dn_label, fullpath);
1556}
1557
1558int
1559vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context)
1560{
1561 int error;
1562
b0d623f7 1563 if (!mac_vnode_enforce || !mac_label_vnodes)
2d21ac55
A
1564 return (0);
1565
1566 if (vp->v_mount == NULL) {
1567 printf("vn_setlabel: null v_mount\n");
1568 if (vp->v_type != VNON)
1569 printf("vn_setlabel: null v_mount with non-VNON\n");
1570 return (EBADF);
1571 }
1572
1573 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1574 return (ENOTSUP);
1575
1576 /*
1577 * Multi-phase commit. First check the policies to confirm the
1578 * change is OK. Then commit via the filesystem. Finally,
1579 * update the actual vnode label. Question: maybe the filesystem
1580 * should update the vnode at the end as part of VNOP_SETLABEL()?
1581 */
1582 error = mac_vnode_check_label_update(context, vp, intlabel);
1583 if (error)
1584 return (error);
1585
1586 error = VNOP_SETLABEL(vp, intlabel, context);
1587 if (error == ENOTSUP) {
1588 error = mac_vnode_label_store(context, vp,
1589 intlabel);
1590 if (error) {
1591 printf("%s: mac_vnode_label_store failed %d\n",
1592 __func__, error);
1593 return (error);
1594 }
1595 mac_vnode_label_update(context, vp, intlabel);
1596 } else
1597 if (error) {
1598 printf("vn_setlabel: vop setlabel failed %d\n", error);
1599 return (error);
1600 }
1601
1602 return (0);
1603}
1604
1605int
1606mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
1607 struct vnode *vp, vfs_context_t ctx)
1608{
1609 struct fileproc *fp;
39236c6e 1610#if CONFIG_MACF_SOCKET_SUBSET
2d21ac55 1611 struct socket *so;
39236c6e 1612#endif
2d21ac55
A
1613 struct pipe *cpipe;
1614 struct vnode *fvp;
1615 struct proc *p;
1616 int error;
1617
1618 error = 0;
1619
1620 /*
1621 * If no backing file, let the policy choose which label to use.
1622 */
1623 if (fnp->fd_fd == -1) {
1624 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1625 mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label);
1626 return (0);
1627 }
1628
1629 p = vfs_context_proc(ctx);
1630 error = fp_lookup(p, fnp->fd_fd, &fp, 0);
1631 if (error)
1632 return (error);
1633
1634 if (fp->f_fglob == NULL) {
1635 error = EBADF;
1636 goto out;
1637 }
1638
39236c6e 1639 switch (FILEGLOB_DTYPE(fp->f_fglob)) {
2d21ac55
A
1640 case DTYPE_VNODE:
1641 fvp = (struct vnode *)fp->f_fglob->fg_data;
1642 if ((error = vnode_getwithref(fvp)))
1643 goto out;
1644 MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label);
1645 (void)vnode_put(fvp);
1646 break;
39236c6e 1647#if CONFIG_MACF_SOCKET_SUBSET
2d21ac55
A
1648 case DTYPE_SOCKET:
1649 so = (struct socket *)fp->f_fglob->fg_data;
1650 socket_lock(so, 1);
1651 MAC_PERFORM(vnode_label_associate_socket,
1652 vfs_context_ucred(ctx), (socket_t)so, so->so_label,
1653 vp, vp->v_label);
1654 socket_unlock(so, 1);
1655 break;
39236c6e 1656#endif
2d21ac55
A
1657 case DTYPE_PSXSHM:
1658 pshm_label_associate(fp, vp, ctx);
1659 break;
1660 case DTYPE_PSXSEM:
1661 psem_label_associate(fp, vp, ctx);
1662 break;
1663 case DTYPE_PIPE:
1664 cpipe = (struct pipe *)fp->f_fglob->fg_data;
1665 /* kern/sys_pipe.c:pipe_select() suggests this test. */
1666 if (cpipe == (struct pipe *)-1) {
1667 error = EINVAL;
1668 goto out;
1669 }
1670 PIPE_LOCK(cpipe);
1671 MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx),
1672 cpipe, cpipe->pipe_label, vp, vp->v_label);
1673 PIPE_UNLOCK(cpipe);
1674 break;
1675 case DTYPE_KQUEUE:
1676 case DTYPE_FSEVENTS:
1677 default:
1678 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1679 mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label,
1680 vp, vp->v_label);
1681 break;
1682 }
1683out:
1684 fp_drop(p, fnp->fd_fd, fp, 0);
1685 return (error);
1686}