1/*
2 * Copyright (c) 2007-2016 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 <kern/kalloc.h>
66
67#include <sys/param.h>
68#include <sys/systm.h>
69#include <sys/kernel.h>
70#include <sys/proc.h>
71#include <sys/kauth.h>
72
73#include <sys/file_internal.h>
74#include <sys/imgact.h>
75#include <sys/namei.h>
76#include <sys/mount_internal.h>
77#include <sys/pipe.h>
78#include <sys/posix_sem.h>
79#include <sys/posix_shm.h>
80#include <sys/reason.h>
81#include <sys/uio_internal.h>
82#include <sys/vnode_internal.h>
83
84#include <miscfs/devfs/devfsdefs.h>
85#include <miscfs/devfs/fdesc.h>
86
87#include <security/mac_internal.h>
88
89/* convert {R,W,X}_OK values to V{READ,WRITE,EXEC} */
90#define ACCESS_MODE_TO_VNODE_MASK(m) (m << 6)
91
92static struct label *
93mac_devfsdirent_label_alloc(void)
94{
95 struct label *label;
96
97 label = mac_labelzone_alloc(MAC_WAITOK);
98 if (label == NULL)
99 return (NULL);
100 MAC_PERFORM(devfs_label_init, label);
101 return (label);
102}
103
104void
105mac_devfs_label_init(struct devnode *de)
106{
107
108 de->dn_label = mac_devfsdirent_label_alloc();
109}
110
111static struct label *
112mac_mount_label_alloc(void)
113{
114 struct label *label;
115
116 label = mac_labelzone_alloc(MAC_WAITOK);
117 if (label == NULL)
118 return (NULL);
119 MAC_PERFORM(mount_label_init, label);
120 return (label);
121}
122
123void
124mac_mount_label_init(struct mount *mp)
125{
126
127 mp->mnt_mntlabel = mac_mount_label_alloc();
128}
129
130struct label *
131mac_vnode_label_alloc(void)
132{
133 struct label *label;
134
135 label = mac_labelzone_alloc(MAC_WAITOK);
136 if (label == NULL)
137 return (NULL);
138 MAC_PERFORM(vnode_label_init, label);
139 return (label);
140}
141
142void
143mac_vnode_label_init(vnode_t vp)
144{
145 vp->v_label = mac_vnode_label_alloc();
146}
147
148int
149mac_vnode_label_init_needed(vnode_t vp)
150{
151 return (mac_label_vnodes != 0 && vp->v_label == NULL);
152}
153
154/*
155 * vnode labels are allocated at the same time as vnodes, but vnodes are never
156 * freed. Instead, we want to remove any sensitive information before putting
157 * them on the free list for reuse.
158*/
159void
160mac_vnode_label_recycle(vnode_t vp)
161{
162
163 MAC_PERFORM(vnode_label_recycle, vp->v_label);
164}
165
166static void
167mac_devfs_label_free(struct label *label)
168{
169 MAC_PERFORM(devfs_label_destroy, label);
170 mac_labelzone_free(label);
171}
172
173void
174mac_devfs_label_destroy(struct devnode *de)
175{
176 if (de->dn_label != NULL) {
177 mac_devfs_label_free(de->dn_label);
178 de->dn_label = NULL;
179 }
180}
181
182static void
183mac_mount_label_free(struct label *label)
184{
185
186 MAC_PERFORM(mount_label_destroy, label);
187 mac_labelzone_free(label);
188}
189
190void
191mac_mount_label_destroy(struct mount *mp)
192{
193 if (mp->mnt_mntlabel != NULL) {
194 mac_mount_label_free(mp->mnt_mntlabel);
195 mp->mnt_mntlabel = NULL;
196 }
197}
198
199void
200mac_vnode_label_free(struct label *label)
201{
202 MAC_PERFORM(vnode_label_destroy, label);
203 mac_labelzone_free(label);
204}
205
206#ifndef __APPLE__
207void
208mac_vnode_label_destroy(struct vnode *vp)
209{
210 if (vp->v_label != NULL) {
211 mac_vnode_label_free(vp->v_label);
212 vp->v_label = NULL;
213 }
214}
215#endif
216
217void
218mac_vnode_label_copy(struct label *src, struct label *dest)
219{
220 if (src == NULL) {
221 MAC_PERFORM(vnode_label_init, dest);
222 } else {
223 MAC_PERFORM(vnode_label_copy, src, dest);
224 }
225}
226
227int
228mac_vnode_label_externalize_audit(struct vnode *vp, struct mac *mac)
229{
230 int error;
231
232 /* It is assumed that any necessary vnode locking is done on entry */
233 error = MAC_EXTERNALIZE_AUDIT(vnode, vp->v_label,
234 mac->m_string, mac->m_buflen);
235
236 return (error);
237}
238
239int
240mac_vnode_label_externalize(struct label *label, char *elements,
241 char *outbuf, size_t outbuflen, int flags __unused)
242{
243 int error;
244
245 error = MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
246
247 return (error);
248}
249
250int
251mac_vnode_label_internalize(struct label *label, char *string)
252{
253 int error;
254
255 error = MAC_INTERNALIZE(vnode, label, string);
256
257 return (error);
258}
259
260int
261mac_mount_label_internalize(struct label *label, char *string)
262{
263 int error;
264
265 error = MAC_INTERNALIZE(mount, label, string);
266
267 return (error);
268}
269
270int
271mac_mount_label_externalize(struct label *label, char *elements,
272 char *outbuf, size_t outbuflen)
273{
274 int error;
275
276 error = MAC_EXTERNALIZE(mount, label, elements, outbuf, outbuflen);
277
278 return (error);
279}
280
281void
282mac_devfs_label_copy(struct label *src, struct label *dest)
283{
284#if SECURITY_MAC_CHECK_ENFORCE
285 /* 21167099 - only check if we allow write */
286 if (!mac_device_enforce)
287 return;
288#endif
289
290 MAC_PERFORM(devfs_label_copy, src, dest);
291}
292
293void
294mac_devfs_label_update(struct mount *mp, struct devnode *de,
295 struct vnode *vp)
296{
297#if SECURITY_MAC_CHECK_ENFORCE
298 /* 21167099 - only check if we allow write */
299 if (!mac_device_enforce)
300 return;
301#endif
302
303 MAC_PERFORM(devfs_label_update, mp, de, de->dn_label, vp,
304 vp->v_label);
305}
306
307int
308mac_vnode_label_associate(struct mount *mp, struct vnode *vp, vfs_context_t ctx)
309{
310 struct devnode *dnp;
311 struct fdescnode *fnp;
312 int error = 0;
313
314#if SECURITY_MAC_CHECK_ENFORCE
315 /* 21167099 - only check if we allow write */
316 if (!mac_vnode_enforce)
317 return (error);
318#endif
319
320 /* XXX: should not inspect v_tag in kernel! */
321 switch (vp->v_tag) {
322 case VT_DEVFS:
323 dnp = VTODN(vp);
324 mac_vnode_label_associate_devfs(mp, dnp, vp);
325 break;
326 case VT_FDESC:
327 fnp = VTOFDESC(vp);
328 error = mac_vnode_label_associate_fdesc(mp, fnp, vp, ctx);
329 break;
330 default:
331 error = mac_vnode_label_associate_extattr(mp, vp);
332 break;
333 }
334
335 return (error);
336}
337
338void
339mac_vnode_label_associate_devfs(struct mount *mp, struct devnode *de,
340 struct vnode *vp)
341{
342#if SECURITY_MAC_CHECK_ENFORCE
343 /* 21167099 - only check if we allow write */
344 if (!mac_device_enforce)
345 return;
346#endif
347
348 MAC_PERFORM(vnode_label_associate_devfs,
349 mp, mp ? mp->mnt_mntlabel : NULL,
350 de, de->dn_label,
351 vp, vp->v_label);
352}
353
354int
355mac_vnode_label_associate_extattr(struct mount *mp, struct vnode *vp)
356{
357 int error;
358
359 MAC_CHECK(vnode_label_associate_extattr, mp, mp->mnt_mntlabel, vp,
360 vp->v_label);
361
362 return (error);
363}
364
365void
366mac_vnode_label_associate_singlelabel(struct mount *mp, struct vnode *vp)
367{
368#if SECURITY_MAC_CHECK_ENFORCE
369 /* 21167099 - only check if we allow write */
370 if (!mac_vnode_enforce)
371 return;
372#endif
373 if (!mac_label_vnodes)
374 return;
375
376 MAC_PERFORM(vnode_label_associate_singlelabel, mp,
377 mp ? mp->mnt_mntlabel : NULL, vp, vp->v_label);
378}
379
380int
381mac_vnode_notify_create(vfs_context_t ctx, struct mount *mp,
382 struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
383{
384 kauth_cred_t cred;
385 int error;
386
387#if SECURITY_MAC_CHECK_ENFORCE
388 /* 21167099 - only check if we allow write */
389 if (!mac_vnode_enforce)
390 return (0);
391#endif
392 cred = vfs_context_ucred(ctx);
393 if (!mac_cred_check_enforce(cred))
394 return (0);
395 MAC_CHECK(vnode_notify_create, cred, mp, mp->mnt_mntlabel,
396 dvp, dvp->v_label, vp, vp->v_label, cnp);
397
398 return (error);
399}
400
401void
402mac_vnode_notify_rename(vfs_context_t ctx, struct vnode *vp,
403 struct vnode *dvp, struct componentname *cnp)
404{
405 kauth_cred_t cred;
406
407#if SECURITY_MAC_CHECK_ENFORCE
408 /* 21167099 - only check if we allow write */
409 if (!mac_vnode_enforce)
410 return;
411#endif
412 cred = vfs_context_ucred(ctx);
413 if (!mac_cred_check_enforce(cred))
414 return;
415 MAC_PERFORM(vnode_notify_rename, cred, vp, vp->v_label,
416 dvp, dvp->v_label, cnp);
417}
418
419void
420mac_vnode_notify_open(vfs_context_t ctx, struct vnode *vp, int acc_flags)
421{
422 kauth_cred_t cred;
423
424#if SECURITY_MAC_CHECK_ENFORCE
425 /* 21167099 - only check if we allow write */
426 if (!mac_vnode_enforce)
427 return;
428#endif
429 cred = vfs_context_ucred(ctx);
430 if (!mac_cred_check_enforce(cred))
431 return;
432 MAC_PERFORM(vnode_notify_open, cred, vp, vp->v_label, acc_flags);
433}
434
435void
436mac_vnode_notify_link(vfs_context_t ctx, struct vnode *vp,
437 struct vnode *dvp, struct componentname *cnp)
438{
439 kauth_cred_t cred;
440
441#if SECURITY_MAC_CHECK_ENFORCE
442 /* 21167099 - only check if we allow write */
443 if (!mac_vnode_enforce)
444 return;
445#endif
446 cred = vfs_context_ucred(ctx);
447 if (!mac_cred_check_enforce(cred))
448 return;
449 MAC_PERFORM(vnode_notify_link, cred, dvp, dvp->v_label, vp, vp->v_label, cnp);
450}
451
452void
453mac_vnode_notify_deleteextattr(vfs_context_t ctx, struct vnode *vp, const char *name)
454{
455 kauth_cred_t cred;
456
457#if SECURITY_MAC_CHECK_ENFORCE
458 /* 21167099 - only check if we allow write */
459 if (!mac_vnode_enforce)
460 return;
461#endif
462 cred = vfs_context_ucred(ctx);
463 if (!mac_cred_check_enforce(cred))
464 return;
465 MAC_PERFORM(vnode_notify_deleteextattr, cred, vp, vp->v_label, name);
466}
467
468void
469mac_vnode_notify_setacl(vfs_context_t ctx, struct vnode *vp, struct kauth_acl *acl)
470{
471 kauth_cred_t cred;
472
473#if SECURITY_MAC_CHECK_ENFORCE
474 /* 21167099 - only check if we allow write */
475 if (!mac_vnode_enforce)
476 return;
477#endif
478 cred = vfs_context_ucred(ctx);
479 if (!mac_cred_check_enforce(cred))
480 return;
481 MAC_PERFORM(vnode_notify_setacl, cred, vp, vp->v_label, acl);
482}
483
484void
485mac_vnode_notify_setattrlist(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist)
486{
487 kauth_cred_t cred;
488
489#if SECURITY_MAC_CHECK_ENFORCE
490 /* 21167099 - only check if we allow write */
491 if (!mac_vnode_enforce)
492 return;
493#endif
494 cred = vfs_context_ucred(ctx);
495 if (!mac_cred_check_enforce(cred))
496 return;
497 MAC_PERFORM(vnode_notify_setattrlist, cred, vp, vp->v_label, alist);
498}
499
500void
501mac_vnode_notify_setextattr(vfs_context_t ctx, struct vnode *vp, const char *name, struct uio *uio)
502{
503 kauth_cred_t cred;
504
505#if SECURITY_MAC_CHECK_ENFORCE
506 /* 21167099 - only check if we allow write */
507 if (!mac_vnode_enforce)
508 return;
509#endif
510 cred = vfs_context_ucred(ctx);
511 if (!mac_cred_check_enforce(cred))
512 return;
513 MAC_PERFORM(vnode_notify_setextattr, cred, vp, vp->v_label, name, uio);
514}
515
516void
517mac_vnode_notify_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
518{
519 kauth_cred_t cred;
520
521#if SECURITY_MAC_CHECK_ENFORCE
522 /* 21167099 - only check if we allow write */
523 if (!mac_vnode_enforce)
524 return;
525#endif
526 cred = vfs_context_ucred(ctx);
527 if (!mac_cred_check_enforce(cred))
528 return;
529 MAC_PERFORM(vnode_notify_setflags, cred, vp, vp->v_label, flags);
530}
531
532void
533mac_vnode_notify_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
534{
535 kauth_cred_t cred;
536
537#if SECURITY_MAC_CHECK_ENFORCE
538 /* 21167099 - only check if we allow write */
539 if (!mac_vnode_enforce)
540 return;
541#endif
542 cred = vfs_context_ucred(ctx);
543 if (!mac_cred_check_enforce(cred))
544 return;
545 MAC_PERFORM(vnode_notify_setmode, cred, vp, vp->v_label, mode);
546}
547
548void
549mac_vnode_notify_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid, gid_t gid)
550{
551 kauth_cred_t cred;
552
553#if SECURITY_MAC_CHECK_ENFORCE
554 /* 21167099 - only check if we allow write */
555 if (!mac_vnode_enforce)
556 return;
557#endif
558 cred = vfs_context_ucred(ctx);
559 if (!mac_cred_check_enforce(cred))
560 return;
561 MAC_PERFORM(vnode_notify_setowner, cred, vp, vp->v_label, uid, gid);
562}
563
564void
565mac_vnode_notify_setutimes(vfs_context_t ctx, struct vnode *vp, struct timespec atime, struct timespec mtime)
566{
567 kauth_cred_t cred;
568
569#if SECURITY_MAC_CHECK_ENFORCE
570 /* 21167099 - only check if we allow write */
571 if (!mac_vnode_enforce)
572 return;
573#endif
574 cred = vfs_context_ucred(ctx);
575 if (!mac_cred_check_enforce(cred))
576 return;
577 MAC_PERFORM(vnode_notify_setutimes, cred, vp, vp->v_label, atime, mtime);
578}
579
580void
581mac_vnode_notify_truncate(vfs_context_t ctx, kauth_cred_t file_cred, struct vnode *vp)
582{
583 kauth_cred_t cred;
584
585#if SECURITY_MAC_CHECK_ENFORCE
586 /* 21167099 - only check if we allow write */
587 if (!mac_vnode_enforce)
588 return;
589#endif
590 cred = vfs_context_ucred(ctx);
591 if (!mac_cred_check_enforce(cred))
592 return;
593 MAC_PERFORM(vnode_notify_truncate, cred, file_cred, vp, vp->v_label);
594}
595
596/*
597 * Extended attribute 'name' was updated via
598 * vn_setxattr() or vn_removexattr(). Allow the
599 * policy to update the vnode label.
600 */
601void
602mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp,
603 const char *name)
604{
605 int error = 0;
606
607#if SECURITY_MAC_CHECK_ENFORCE
608 /* 21167099 - only check if we allow write */
609 if (!mac_vnode_enforce)
610 return;
611#endif
612 if (!mac_label_vnodes)
613 return;
614
615 MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp,
616 vp->v_label, name);
617 if (error == 0)
618 return;
619
620 vnode_lock(vp);
621 vnode_relabel(vp);
622 vnode_unlock(vp);
623 return;
624}
625
626static int
627mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp,
628 struct label *intlabel)
629{
630 kauth_cred_t cred;
631 int error;
632
633#if SECURITY_MAC_CHECK_ENFORCE
634 /* 21167099 - only check if we allow write */
635 if (!mac_vnode_enforce)
636 return 0;
637#endif
638 if (!mac_label_vnodes)
639 return 0;
640
641 cred = vfs_context_ucred(ctx);
642 if (!mac_cred_check_enforce(cred))
643 return (0);
644 MAC_CHECK(vnode_label_store, cred, vp, vp->v_label, intlabel);
645
646 return (error);
647}
648
649void
650mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp, off_t offset,
651 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl, u_int *csflags,
652 void *macextensions, int *disjoint, int *labelupdateerror)
653{
654 kauth_cred_t cred;
655 *disjoint = 0;
656 int error;
657 posix_cred_t pcred = posix_cred_get(new);
658
659#if SECURITY_MAC_CHECK_ENFORCE
660 /* 21167099 - only check if we allow write */
661 if (!mac_proc_enforce || !mac_vnode_enforce)
662 return;
663#endif
664
665 /* mark the new cred to indicate "matching" includes the label */
666 pcred->cr_flags |= CRF_MAC_ENFORCE;
667
668 cred = vfs_context_ucred(ctx);
669
670 /*
671 * NB: Cannot use MAC_CHECK macro because we need a sequence point after
672 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
673 * spawnattrlen as an argument to the hook.
674 */
675 {
676 struct mac_policy_conf *mpc;
677 u_int i;
678
679 error = 0;
680 for (i = 0; i< mac_policy_list.staticmax; i++) {
681 mpc = mac_policy_list.entries[i].mpc;
682 if (mpc == NULL)
683 continue;
684
685 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
686 if (hook == NULL)
687 continue;
688
689 size_t spawnattrlen = 0;
690 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
691
692 error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp,
693 vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint),
694 error);
695 }
696 if (mac_policy_list_conditional_busy() != 0) {
697 for (; i <= mac_policy_list.maxindex; i++) {
698 mpc = mac_policy_list.entries[i].mpc;
699 if (mpc == NULL)
700 continue;
701
702 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
703 if (hook == NULL)
704 continue;
705
706 size_t spawnattrlen = 0;
707 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
708
709 error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp,
710 vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint),
711 error);
712 }
713 mac_policy_list_unbusy();
714 }
715 }
716 *labelupdateerror = error;
717}
718
719int
720mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp, off_t offset,
721 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel,
722 struct proc *p, void *macextensions)
723{
724 kauth_cred_t cred;
725 int result = 0;
726
727#if SECURITY_MAC_CHECK_ENFORCE
728 /* 21167099 - only check if we allow write */
729 if (!mac_proc_enforce || !mac_vnode_enforce)
730 return result;
731#endif
732
733 cred = vfs_context_ucred(ctx);
734
735 /*
736 * NB: Cannot use MAC_BOOLEAN macro because we need a sequence point after
737 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
738 * spawnattrlen as an argument to the hook.
739 */
740 {
741 struct mac_policy_conf *mpc;
742 u_int i;
743
744 for (i = 0; i< mac_policy_list.staticmax; i++) {
745 mpc = mac_policy_list.entries[i].mpc;
746 if (mpc == NULL)
747 continue;
748
749 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
750 if (hook == NULL)
751 continue;
752
753 size_t spawnattrlen = 0;
754 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
755
756 result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
757 }
758 if (mac_policy_list_conditional_busy() != 0) {
759 for (; i <= mac_policy_list.maxindex; i++) {
760 mpc = mac_policy_list.entries[i].mpc;
761 if (mpc == NULL)
762 continue;
763
764 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
765 if (hook == NULL)
766 continue;
767
768 size_t spawnattrlen = 0;
769 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
770
771 result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
772 }
773 mac_policy_list_unbusy();
774 }
775 }
776
777 return (result);
778}
779
780int
781mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp,
782 int acc_mode)
783{
784 kauth_cred_t cred;
785 int error;
786 int mask;
787
788#if SECURITY_MAC_CHECK_ENFORCE
789 /* 21167099 - only check if we allow write */
790 if (!mac_vnode_enforce)
791 return 0;
792#endif
793 cred = vfs_context_ucred(ctx);
794 if (!mac_cred_check_enforce(cred))
795 return (0);
796 /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */
797 mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode);
798 MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask);
799 return (error);
800 }
801
802int
803mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp)
804{
805 kauth_cred_t cred;
806 int error;
807
808#if SECURITY_MAC_CHECK_ENFORCE
809 /* 21167099 - only check if we allow write */
810 if (!mac_vnode_enforce)
811 return 0;
812#endif
813 cred = vfs_context_ucred(ctx);
814 if (!mac_cred_check_enforce(cred))
815 return (0);
816 MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
817 return (error);
818}
819
820int
821mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp,
822 struct componentname *cnp)
823{
824 kauth_cred_t cred;
825 int error;
826
827#if SECURITY_MAC_CHECK_ENFORCE
828 /* 21167099 - only check if we allow write */
829 if (!mac_vnode_enforce)
830 return 0;
831#endif
832 cred = vfs_context_ucred(ctx);
833 if (!mac_cred_check_enforce(cred))
834 return (0);
835 MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp);
836 return (error);
837}
838
839int
840mac_vnode_check_clone(vfs_context_t ctx, struct vnode *dvp,
841 struct vnode *vp, struct componentname *cnp)
842{
843 kauth_cred_t cred;
844 int error;
845
846#if SECURITY_MAC_CHECK_ENFORCE
847 /* 21167099 - only check if we allow write */
848 if (!mac_vnode_enforce)
849 return 0;
850#endif
851 cred = vfs_context_ucred(ctx);
852 if (!mac_cred_check_enforce(cred))
853 return (0);
854 MAC_CHECK(vnode_check_clone, cred, dvp, dvp->v_label, vp,
855 vp->v_label, cnp);
856 return (error);
857}
858int
859mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp,
860 struct componentname *cnp, struct vnode_attr *vap)
861{
862 kauth_cred_t cred;
863 int error;
864
865#if SECURITY_MAC_CHECK_ENFORCE
866 /* 21167099 - only check if we allow write */
867 if (!mac_vnode_enforce)
868 return 0;
869#endif
870 cred = vfs_context_ucred(ctx);
871 if (!mac_cred_check_enforce(cred))
872 return (0);
873 MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
874 return (error);
875}
876
877int
878mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp,
879 struct componentname *cnp)
880{
881 kauth_cred_t cred;
882 int error;
883
884#if SECURITY_MAC_CHECK_ENFORCE
885 /* 21167099 - only check if we allow write */
886 if (!mac_vnode_enforce)
887 return 0;
888#endif
889 cred = vfs_context_ucred(ctx);
890 if (!mac_cred_check_enforce(cred))
891 return (0);
892 MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
893 vp->v_label, cnp);
894 return (error);
895}
896#if 0
897int
898mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp,
899 acl_type_t type)
900{
901 kauth_cred_t cred;
902 int error;
903
904#if SECURITY_MAC_CHECK_ENFORCE
905 /* 21167099 - only check if we allow write */
906 if (!mac_vnode_enforce)
907 return 0;
908#endif
909 cred = vfs_context_ucred(ctx);
910 if (!mac_cred_check_enforce(cred))
911 return (0);
912 MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
913 return (error);
914}
915#endif
916
917int
918mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp,
919 const char *name)
920{
921 kauth_cred_t cred;
922 int error;
923
924#if SECURITY_MAC_CHECK_ENFORCE
925 /* 21167099 - only check if we allow write */
926 if (!mac_vnode_enforce)
927 return 0;
928#endif
929 cred = vfs_context_ucred(ctx);
930 if (!mac_cred_check_enforce(cred))
931 return (0);
932 MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name);
933 return (error);
934}
935int
936mac_vnode_check_exchangedata(vfs_context_t ctx,
937 struct vnode *v1, struct vnode *v2)
938{
939 kauth_cred_t cred;
940 int error;
941
942#if SECURITY_MAC_CHECK_ENFORCE
943 /* 21167099 - only check if we allow write */
944 if (!mac_vnode_enforce)
945 return 0;
946#endif
947 cred = vfs_context_ucred(ctx);
948 if (!mac_cred_check_enforce(cred))
949 return (0);
950 MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label,
951 v2, v2->v_label);
952
953 return (error);
954}
955
956#if 0
957int
958mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
959{
960 kauth_cred_t cred;
961 int error;
962
963#if SECURITY_MAC_CHECK_ENFORCE
964 /* 21167099 - only check if we allow write */
965 if (!mac_vnode_enforce)
966 return 0;
967#endif
968 cred = vfs_context_ucred(ctx);
969 if (!mac_cred_check_enforce(cred))
970 return (0);
971 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
972 return (error);
973}
974#endif
975
976int
977mac_vnode_check_getattr(vfs_context_t ctx, struct ucred *file_cred,
978 struct vnode *vp, struct vnode_attr *va)
979{
980 kauth_cred_t cred;
981 int error;
982
983#if SECURITY_MAC_CHECK_ENFORCE
984 /* 21167099 - only check if we allow write */
985 if (!mac_vnode_enforce)
986 return 0;
987#endif
988 cred = vfs_context_ucred(ctx);
989 if (!mac_cred_check_enforce(cred))
990 return (0);
991 MAC_CHECK(vnode_check_getattr, cred, file_cred, vp, vp->v_label, va);
992 return (error);
993}
994
995int
996mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp,
997 struct attrlist *alist)
998{
999 kauth_cred_t cred;
1000 int error;
1001
1002#if SECURITY_MAC_CHECK_ENFORCE
1003 /* 21167099 - only check if we allow write */
1004 if (!mac_vnode_enforce)
1005 return 0;
1006#endif
1007 cred = vfs_context_ucred(ctx);
1008 if (!mac_cred_check_enforce(cred))
1009 return (0);
1010 MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist);
1011
1012 /* Falsify results instead of returning error? */
1013 return (error);
1014}
1015
1016int
1017mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp,
1018 struct image_params *imgp)
1019{
1020 kauth_cred_t cred;
1021 int error = 0;
1022
1023#if SECURITY_MAC_CHECK_ENFORCE
1024 /* 21167099 - only check if we allow write */
1025 if (!mac_proc_enforce || !mac_vnode_enforce)
1026 return 0;
1027#endif
1028
1029 cred = vfs_context_ucred(ctx);
1030
1031 /*
1032 * NB: Cannot use MAC_CHECK macro because we need a sequence point after
1033 * calling exec_spawnattr_getmacpolicyinfo() and before passing the
1034 * spawnattrlen as an argument to the hook.
1035 */
1036 {
1037 struct mac_policy_conf *mpc;
1038 u_int i;
1039
1040 for (i = 0; i< mac_policy_list.staticmax; i++) {
1041 mpc = mac_policy_list.entries[i].mpc;
1042 if (mpc == NULL)
1043 continue;
1044
1045 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
1046 if (hook == NULL)
1047 continue;
1048
1049 size_t spawnattrlen = 0;
1050 void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen);
1051
1052 error = mac_error_select(
1053 hook(cred,
1054 vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp,
1055 imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags,
1056 spawnattr, spawnattrlen), error);
1057 }
1058 if (mac_policy_list_conditional_busy() != 0) {
1059 for (; i <= mac_policy_list.maxindex; i++) {
1060 mpc = mac_policy_list.entries[i].mpc;
1061 if (mpc == NULL)
1062 continue;
1063
1064 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
1065 if (hook == NULL)
1066 continue;
1067
1068 size_t spawnattrlen = 0;
1069 void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen);
1070
1071 error = mac_error_select(
1072 hook(cred,
1073 vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp,
1074 imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags,
1075 spawnattr, spawnattrlen), error);
1076 }
1077 mac_policy_list_unbusy();
1078 }
1079 }
1080
1081 return (error);
1082}
1083
1084int
1085mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp)
1086{
1087 kauth_cred_t cred;
1088 int error;
1089
1090#if SECURITY_MAC_CHECK_ENFORCE
1091 /* 21167099 - only check if we allow write */
1092 if (!mac_vnode_enforce)
1093 return 0;
1094#endif
1095 cred = vfs_context_ucred(ctx);
1096 if (!mac_cred_check_enforce(cred))
1097 return (0);
1098 MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label);
1099 return (error);
1100}
1101
1102int
1103mac_vnode_check_signature(struct vnode *vp, struct cs_blob *cs_blob,
1104 struct image_params *imgp,
1105 unsigned int *cs_flags, unsigned int *signer_type,
1106 int flags)
1107{
1108 int error;
1109 char *fatal_failure_desc = NULL;
1110 size_t fatal_failure_desc_len = 0;
1111
1112 char *vn_path = NULL;
1113 vm_size_t vn_pathlen = MAXPATHLEN;
1114 cpu_type_t cpu_type = (imgp == NULL) ? CPU_TYPE_ANY : imgp->ip_origcputype;
1115
1116
1117#if SECURITY_MAC_CHECK_ENFORCE
1118 /* 21167099 - only check if we allow write */
1119 if (!mac_proc_enforce || !mac_vnode_enforce)
1120 return 0;
1121#endif
1122
1123 MAC_CHECK(vnode_check_signature, vp, vp->v_label, cpu_type, cs_blob,
1124 cs_flags, signer_type, flags, &fatal_failure_desc, &fatal_failure_desc_len);
1125
1126 if (fatal_failure_desc_len) {
1127 // A fatal code signature validation failure occured, formulate a crash
1128 // reason.
1129
1130 char const *path = NULL;
1131
1132 vn_path = (char *)kalloc(MAXPATHLEN);
1133 if (vn_path != NULL) {
1134 if (vn_getpath(vp, vn_path, (int*)&vn_pathlen) == 0) {
1135 path = vn_path;
1136 } else {
1137 path = "(get vnode path failed)";
1138 }
1139 } else {
1140 path = "(path alloc failed)";
1141 }
1142
1143 if (error == 0) {
1144 panic("mac_vnode_check_signature: MAC hook returned no error, "
1145 "but status is claimed to be fatal? "
1146 "path: '%s', fatal_failure_desc_len: %ld, fatal_failure_desc:\n%s\n",
1147 path, fatal_failure_desc_len, fatal_failure_desc);
1148 }
1149
1150 printf("mac_vnode_check_signature: %s: code signature validation failed fatally: %s",
1151 path, fatal_failure_desc);
1152
1153 if (imgp == NULL) {
1154 goto out;
1155 }
1156
1157 os_reason_t reason = os_reason_create(OS_REASON_CODESIGNING,
1158 CODESIGNING_EXIT_REASON_TASKGATED_INVALID_SIG);
1159
1160 if (reason == OS_REASON_NULL) {
1161 printf("mac_vnode_check_signature: %s: failure to allocate exit reason for validation failure: %s\n",
1162 path, fatal_failure_desc);
1163 goto out;
1164 }
1165
1166 imgp->ip_cs_error = reason;
1167 reason->osr_flags = (OS_REASON_FLAG_GENERATE_CRASH_REPORT |
1168 OS_REASON_FLAG_CONSISTENT_FAILURE);
1169
1170 if (fatal_failure_desc == NULL) {
1171 // This may happen if allocation for the buffer failed.
1172 printf("mac_vnode_check_signature: %s: fatal failure is missing its description.\n", path);
1173 } else {
1174 mach_vm_address_t data_addr = 0;
1175
1176 int reason_error = 0;
1177 int kcdata_error = 0;
1178
1179 if ((reason_error = os_reason_alloc_buffer_noblock(reason, kcdata_estimate_required_buffer_size
1180 (1, fatal_failure_desc_len))) == 0 &&
1181 (kcdata_error = kcdata_get_memory_addr(&reason->osr_kcd_descriptor,
1182 EXIT_REASON_USER_DESC, fatal_failure_desc_len,
1183 &data_addr)) == KERN_SUCCESS) {
1184 kern_return_t mc_error = kcdata_memcpy(&reason->osr_kcd_descriptor, (mach_vm_address_t)data_addr,
1185 fatal_failure_desc, fatal_failure_desc_len);
1186
1187 if (mc_error != KERN_SUCCESS) {
1188 printf("mac_vnode_check_signature: %s: failed to copy reason string "
1189 "(kcdata_memcpy error: %d, length: %ld)\n",
1190 path, mc_error, fatal_failure_desc_len);
1191 }
1192 } else {
1193 printf("mac_vnode_check_signature: %s: failed to allocate space for reason string "
1194 "(os_reason_alloc_buffer error: %d, kcdata error: %d, length: %ld)\n",
1195 path, reason_error, kcdata_error, fatal_failure_desc_len);
1196 }
1197
1198 }
1199 }
1200
1201out:
1202 if (vn_path) {
1203 kfree(vn_path, MAXPATHLEN);
1204 }
1205
1206 if (fatal_failure_desc_len > 0 && fatal_failure_desc != NULL) {
1207 kfree(fatal_failure_desc, fatal_failure_desc_len);
1208 }
1209
1210 return (error);
1211}
1212
1213#if 0
1214int
1215mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
1216{
1217 kauth_cred_t cred;
1218 int error;
1219
1220#if SECURITY_MAC_CHECK_ENFORCE
1221 /* 21167099 - only check if we allow write */
1222 if (!mac_vnode_enforce)
1223 return 0;
1224#endif
1225 cred = vfs_context_ucred(ctx);
1226 if (!mac_cred_check_enforce(cred))
1227 return (0);
1228 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
1229 return (error);
1230}
1231#endif
1232
1233int
1234mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp,
1235 const char *name, struct uio *uio)
1236{
1237 kauth_cred_t cred;
1238 int error;
1239
1240#if SECURITY_MAC_CHECK_ENFORCE
1241 /* 21167099 - only check if we allow write */
1242 if (!mac_vnode_enforce)
1243 return 0;
1244#endif
1245 cred = vfs_context_ucred(ctx);
1246 if (!mac_cred_check_enforce(cred))
1247 return (0);
1248 MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
1249 name, uio);
1250 return (error);
1251}
1252
1253int
1254mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd)
1255{
1256 kauth_cred_t cred;
1257 int error;
1258
1259#if SECURITY_MAC_CHECK_ENFORCE
1260 /* 21167099 - only check if we allow write */
1261 if (!mac_vnode_enforce)
1262 return 0;
1263#endif
1264 cred = vfs_context_ucred(ctx);
1265 if (!mac_cred_check_enforce(cred))
1266 return (0);
1267 MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd);
1268 return (error);
1269}
1270
1271int
1272mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred,
1273 struct knote *kn, struct vnode *vp)
1274{
1275 kauth_cred_t cred;
1276 int error;
1277
1278#if SECURITY_MAC_CHECK_ENFORCE
1279 /* 21167099 - only check if we allow write */
1280 if (!mac_vnode_enforce)
1281 return 0;
1282#endif
1283 cred = vfs_context_ucred(ctx);
1284 if (!mac_cred_check_enforce(cred))
1285 return (0);
1286 MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp,
1287 vp->v_label);
1288
1289 return (error);
1290}
1291
1292int
1293mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp,
1294 struct vnode *vp, struct componentname *cnp)
1295{
1296 kauth_cred_t cred;
1297 int error;
1298
1299#if SECURITY_MAC_CHECK_ENFORCE
1300 /* 21167099 - only check if we allow write */
1301 if (!mac_vnode_enforce)
1302 return 0;
1303#endif
1304 cred = vfs_context_ucred(ctx);
1305 if (!mac_cred_check_enforce(cred))
1306 return (0);
1307 MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
1308 vp->v_label, cnp);
1309 return (error);
1310}
1311
1312int
1313mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp)
1314{
1315 kauth_cred_t cred;
1316 int error;
1317
1318#if SECURITY_MAC_CHECK_ENFORCE
1319 /* 21167099 - only check if we allow write */
1320 if (!mac_vnode_enforce)
1321 return 0;
1322#endif
1323 cred = vfs_context_ucred(ctx);
1324 if (!mac_cred_check_enforce(cred))
1325 return (0);
1326 MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label);
1327 return (error);
1328}
1329
1330int
1331mac_vnode_check_lookup_preflight(vfs_context_t ctx, struct vnode *dvp,
1332 const char *path, size_t pathlen)
1333{
1334 kauth_cred_t cred;
1335 int error;
1336
1337#if SECURITY_MAC_CHECK_ENFORCE
1338 /* 21167099 - only check if we allow write */
1339 if (!mac_vnode_enforce)
1340 return 0;
1341#endif
1342 cred = vfs_context_ucred(ctx);
1343 if (!mac_cred_check_enforce(cred))
1344 return (0);
1345 MAC_CHECK(vnode_check_lookup_preflight, cred, dvp, dvp->v_label, path, pathlen);
1346 return (error);
1347}
1348
1349int
1350mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp,
1351 struct componentname *cnp)
1352{
1353 kauth_cred_t cred;
1354 int error;
1355
1356#if SECURITY_MAC_CHECK_ENFORCE
1357 /* 21167099 - only check if we allow write */
1358 if (!mac_vnode_enforce)
1359 return 0;
1360#endif
1361 cred = vfs_context_ucred(ctx);
1362 if (!mac_cred_check_enforce(cred))
1363 return (0);
1364 MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
1365 return (error);
1366}
1367
1368int
1369mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode)
1370{
1371 kauth_cred_t cred;
1372 int error;
1373
1374#if SECURITY_MAC_CHECK_ENFORCE
1375 /* 21167099 - only check if we allow write */
1376 if (!mac_vnode_enforce)
1377 return 0;
1378#endif
1379 cred = vfs_context_ucred(ctx);
1380 if (!mac_cred_check_enforce(cred))
1381 return (0);
1382 MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode);
1383 return (error);
1384}
1385
1386int
1387mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred,
1388 struct vnode *vp)
1389{
1390 kauth_cred_t cred;
1391 int error;
1392
1393#if SECURITY_MAC_CHECK_ENFORCE
1394 /* 21167099 - only check if we allow write */
1395 if (!mac_vnode_enforce)
1396 return 0;
1397#endif
1398 cred = vfs_context_ucred(ctx);
1399 if (!mac_cred_check_enforce(cred))
1400 return (0);
1401 MAC_CHECK(vnode_check_read, cred, file_cred, vp,
1402 vp->v_label);
1403
1404 return (error);
1405}
1406
1407int
1408mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp)
1409{
1410 kauth_cred_t cred;
1411 int error;
1412
1413#if SECURITY_MAC_CHECK_ENFORCE
1414 /* 21167099 - only check if we allow write */
1415 if (!mac_vnode_enforce)
1416 return 0;
1417#endif
1418 cred = vfs_context_ucred(ctx);
1419 if (!mac_cred_check_enforce(cred))
1420 return (0);
1421 MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
1422 return (error);
1423}
1424
1425int
1426mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp)
1427{
1428 kauth_cred_t cred;
1429 int error;
1430
1431#if SECURITY_MAC_CHECK_ENFORCE
1432 /* 21167099 - only check if we allow write */
1433 if (!mac_vnode_enforce)
1434 return 0;
1435#endif
1436 cred = vfs_context_ucred(ctx);
1437 if (!mac_cred_check_enforce(cred))
1438 return (0);
1439 MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
1440 return (error);
1441}
1442
1443int
1444mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp,
1445 struct label *newlabel)
1446{
1447 kauth_cred_t cred;
1448 int error;
1449
1450#if SECURITY_MAC_CHECK_ENFORCE
1451 /* 21167099 - only check if we allow write */
1452 if (!mac_vnode_enforce)
1453 return 0;
1454#endif
1455 cred = vfs_context_ucred(ctx);
1456 if (!mac_cred_check_enforce(cred))
1457 return (0);
1458 MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel);
1459
1460 return (error);
1461}
1462
1463int
1464mac_vnode_check_rename(vfs_context_t ctx, struct vnode *dvp,
1465 struct vnode *vp, struct componentname *cnp, struct vnode *tdvp,
1466 struct vnode *tvp, struct componentname *tcnp)
1467{
1468 kauth_cred_t cred;
1469 int error;
1470
1471#if SECURITY_MAC_CHECK_ENFORCE
1472 /* 21167099 - only check if we allow write */
1473 if (!mac_vnode_enforce)
1474 return 0;
1475#endif
1476 cred = vfs_context_ucred(ctx);
1477 if (!mac_cred_check_enforce(cred))
1478 return (0);
1479
1480 MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
1481 vp->v_label, cnp);
1482 if (error)
1483 return (error);
1484
1485 MAC_CHECK(vnode_check_rename_to, cred, tdvp, tdvp->v_label, tvp,
1486 tvp != NULL ? tvp->v_label : NULL, dvp == tdvp, tcnp);
1487 if (error)
1488 return (error);
1489
1490 MAC_CHECK(vnode_check_rename, cred, dvp, dvp->v_label, vp,
1491 vp->v_label, cnp, tdvp, tdvp->v_label, tvp,
1492 tvp != NULL ? tvp->v_label : NULL, tcnp);
1493 return (error);
1494}
1495
1496int
1497mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
1498{
1499 kauth_cred_t cred;
1500 int error;
1501
1502#if SECURITY_MAC_CHECK_ENFORCE
1503 /* 21167099 - only check if we allow write */
1504 if (!mac_vnode_enforce)
1505 return 0;
1506#endif
1507 cred = vfs_context_ucred(ctx);
1508 if (!mac_cred_check_enforce(cred))
1509 return (0);
1510 MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
1511 return (error);
1512}
1513
1514int
1515mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist)
1516{
1517 kauth_cred_t cred;
1518 int error;
1519
1520#if SECURITY_MAC_CHECK_ENFORCE
1521 /* 21167099 - only check if we allow write */
1522 if (!mac_vnode_enforce)
1523 return 0;
1524#endif
1525 cred = vfs_context_ucred(ctx);
1526 if (!mac_cred_check_enforce(cred))
1527 return (0);
1528 MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist);
1529 return (error);
1530}
1531
1532int
1533mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which)
1534{
1535 kauth_cred_t cred;
1536 int error;
1537
1538#if SECURITY_MAC_CHECK_ENFORCE
1539 /* 21167099 - only check if we allow write */
1540 if (!mac_vnode_enforce)
1541 return 0;
1542#endif
1543 cred = vfs_context_ucred(ctx);
1544 if (!mac_cred_check_enforce(cred))
1545 return (0);
1546 MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which);
1547 return (error);
1548}
1549
1550int
1551mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp,
1552 struct kauth_acl *acl)
1553{
1554 kauth_cred_t cred;
1555 int error;
1556
1557#if SECURITY_MAC_CHECK_ENFORCE
1558 /* 21167099 - only check if we allow write */
1559 if (!mac_vnode_enforce)
1560 return 0;
1561#endif
1562 cred = vfs_context_ucred(ctx);
1563 if (!mac_cred_check_enforce(cred))
1564 return (0);
1565 MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, acl);
1566 return (error);
1567}
1568
1569int
1570mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp,
1571 struct attrlist *alist)
1572{
1573 kauth_cred_t cred;
1574 int error;
1575
1576#if SECURITY_MAC_CHECK_ENFORCE
1577 /* 21167099 - only check if we allow write */
1578 if (!mac_vnode_enforce)
1579 return 0;
1580#endif
1581 cred = vfs_context_ucred(ctx);
1582 if (!mac_cred_check_enforce(cred))
1583 return (0);
1584 MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist);
1585 return (error);
1586}
1587
1588int
1589mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp,
1590 const char *name, struct uio *uio)
1591{
1592 kauth_cred_t cred;
1593 int error;
1594
1595#if SECURITY_MAC_CHECK_ENFORCE
1596 /* 21167099 - only check if we allow write */
1597 if (!mac_vnode_enforce)
1598 return 0;
1599#endif
1600 cred = vfs_context_ucred(ctx);
1601 if (!mac_cred_check_enforce(cred))
1602 return (0);
1603 MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
1604 name, uio);
1605 return (error);
1606}
1607
1608int
1609mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
1610{
1611 kauth_cred_t cred;
1612 int error;
1613
1614#if SECURITY_MAC_CHECK_ENFORCE
1615 /* 21167099 - only check if we allow write */
1616 if (!mac_vnode_enforce)
1617 return 0;
1618#endif
1619 cred = vfs_context_ucred(ctx);
1620 if (!mac_cred_check_enforce(cred))
1621 return (0);
1622 MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
1623 return (error);
1624}
1625
1626int
1627mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
1628{
1629 kauth_cred_t cred;
1630 int error;
1631
1632#if SECURITY_MAC_CHECK_ENFORCE
1633 /* 21167099 - only check if we allow write */
1634 if (!mac_vnode_enforce)
1635 return 0;
1636#endif
1637 cred = vfs_context_ucred(ctx);
1638 if (!mac_cred_check_enforce(cred))
1639 return (0);
1640 MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
1641 return (error);
1642}
1643
1644int
1645mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid,
1646 gid_t gid)
1647{
1648 kauth_cred_t cred;
1649 int error;
1650
1651#if SECURITY_MAC_CHECK_ENFORCE
1652 /* 21167099 - only check if we allow write */
1653 if (!mac_vnode_enforce)
1654 return 0;
1655#endif
1656 cred = vfs_context_ucred(ctx);
1657 if (!mac_cred_check_enforce(cred))
1658 return (0);
1659 MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid);
1660 return (error);
1661}
1662
1663int
1664mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp,
1665 struct timespec atime, struct timespec mtime)
1666{
1667 kauth_cred_t cred;
1668 int error;
1669
1670#if SECURITY_MAC_CHECK_ENFORCE
1671 /* 21167099 - only check if we allow write */
1672 if (!mac_vnode_enforce)
1673 return 0;
1674#endif
1675 cred = vfs_context_ucred(ctx);
1676 if (!mac_cred_check_enforce(cred))
1677 return (0);
1678 MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime,
1679 mtime);
1680 return (error);
1681}
1682
1683int
1684mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred,
1685 struct vnode *vp)
1686{
1687 kauth_cred_t cred;
1688 int error;
1689
1690#if SECURITY_MAC_CHECK_ENFORCE
1691 /* 21167099 - only check if we allow write */
1692 if (!mac_vnode_enforce)
1693 return 0;
1694#endif
1695 cred = vfs_context_ucred(ctx);
1696 if (!mac_cred_check_enforce(cred))
1697 return (0);
1698 MAC_CHECK(vnode_check_stat, cred, file_cred, vp,
1699 vp->v_label);
1700 return (error);
1701}
1702
1703int
1704mac_vnode_check_trigger_resolve(vfs_context_t ctx, struct vnode *dvp,
1705 struct componentname *cnp)
1706{
1707 kauth_cred_t cred;
1708 int error;
1709
1710#if SECURITY_MAC_CHECK_ENFORCE
1711 /* 21167099 - only check if we allow write */
1712 if (!mac_vnode_enforce)
1713 return 0;
1714#endif
1715 cred = vfs_context_ucred(ctx);
1716 if (!mac_cred_check_enforce(cred))
1717 return (0);
1718 MAC_CHECK(vnode_check_trigger_resolve, cred, dvp, dvp->v_label, cnp);
1719 return (error);
1720}
1721
1722int
1723mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred,
1724 struct vnode *vp)
1725{
1726 kauth_cred_t cred;
1727 int error;
1728
1729#if SECURITY_MAC_CHECK_ENFORCE
1730 /* 21167099 - only check if we allow write */
1731 if (!mac_vnode_enforce)
1732 return 0;
1733#endif
1734 cred = vfs_context_ucred(ctx);
1735 if (!mac_cred_check_enforce(cred))
1736 return (0);
1737 MAC_CHECK(vnode_check_truncate, cred, file_cred, vp,
1738 vp->v_label);
1739
1740 return (error);
1741}
1742
1743int
1744mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred,
1745 struct vnode *vp)
1746{
1747 kauth_cred_t cred;
1748 int error;
1749
1750#if SECURITY_MAC_CHECK_ENFORCE
1751 /* 21167099 - only check if we allow write */
1752 if (!mac_vnode_enforce)
1753 return 0;
1754#endif
1755 cred = vfs_context_ucred(ctx);
1756 if (!mac_cred_check_enforce(cred))
1757 return (0);
1758 MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label);
1759
1760 return (error);
1761}
1762
1763int
1764mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp,
1765 struct componentname *cnp, struct vnode_attr *vap)
1766{
1767 kauth_cred_t cred;
1768 int error;
1769
1770#if SECURITY_MAC_CHECK_ENFORCE
1771 /* 21167099 - only check if we allow write */
1772 if (!mac_vnode_enforce)
1773 return 0;
1774#endif
1775 cred = vfs_context_ucred(ctx);
1776 if (!mac_cred_check_enforce(cred))
1777 return (0);
1778 MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap);
1779 return (error);
1780}
1781
1782int
1783mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp, struct socket *so)
1784{
1785 kauth_cred_t cred;
1786 int error;
1787
1788#if SECURITY_MAC_CHECK_ENFORCE
1789 /* 21167099 - only check if we allow write */
1790 if (!mac_vnode_enforce)
1791 return 0;
1792#endif
1793 cred = vfs_context_ucred(ctx);
1794 if (!mac_cred_check_enforce(cred))
1795 return (0);
1796 MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label, (socket_t) so);
1797 return (error);
1798}
1799
1800void
1801mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel)
1802{
1803 kauth_cred_t cred = vfs_context_ucred(ctx);
1804 struct label *tmpl = NULL;
1805
1806 if (vp->v_label == NULL)
1807 tmpl = mac_vnode_label_alloc();
1808
1809 vnode_lock(vp);
1810
1811 /* recheck after lock */
1812 if (vp->v_label == NULL) {
1813 vp->v_label = tmpl;
1814 tmpl = NULL;
1815 }
1816
1817 MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel);
1818 vnode_unlock(vp);
1819
1820 if (tmpl != NULL)
1821 mac_vnode_label_free(tmpl);
1822}
1823
1824int
1825mac_vnode_find_sigs(struct proc *p, struct vnode *vp, off_t offset)
1826{
1827 int error;
1828
1829#if SECURITY_MAC_CHECK_ENFORCE
1830 /* 21167099 - only check if we allow write */
1831 if (!mac_proc_enforce || !mac_vnode_enforce)
1832 return 0;
1833#endif
1834
1835 MAC_CHECK(vnode_find_sigs, p, vp, offset, vp->v_label);
1836
1837 return (error);
1838}
1839
1840void
1841mac_mount_label_associate(vfs_context_t ctx, struct mount *mp)
1842{
1843 kauth_cred_t cred = vfs_context_ucred(ctx);
1844
1845 /* XXX: eventually this logic may be handled by the policy? */
1846
1847 /* We desire MULTILABEL for the root filesystem. */
1848 if ((mp->mnt_flag & MNT_ROOTFS) &&
1849 (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0))
1850 mp->mnt_flag |= MNT_MULTILABEL;
1851
1852 /* MULTILABEL on DEVFS. */
1853 if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0)
1854 mp->mnt_flag |= MNT_MULTILABEL;
1855
1856 /* MULTILABEL on FDESC pseudo-filesystem. */
1857 if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0)
1858 mp->mnt_flag |= MNT_MULTILABEL;
1859
1860 /* MULTILABEL on all NFS filesystems. */
1861 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0)
1862 mp->mnt_flag |= MNT_MULTILABEL;
1863
1864 /* MULTILABEL on all AFP filesystems. */
1865 if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0)
1866 mp->mnt_flag |= MNT_MULTILABEL;
1867
1868 if (mp->mnt_vtable != NULL) {
1869 /* Any filesystem that supports native XATTRs. */
1870 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR))
1871 mp->mnt_flag |= MNT_MULTILABEL;
1872
1873 /* Filesystem does not support multilabel. */
1874 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) &&
1875 (mp->mnt_flag & MNT_MULTILABEL))
1876 mp->mnt_flag &= ~MNT_MULTILABEL;
1877 }
1878
1879 MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel);
1880#if DEBUG
1881 printf("MAC Framework enabling %s support: %s -> %s (%s)\n",
1882 mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel",
1883 mp->mnt_vfsstat.f_mntfromname,
1884 mp->mnt_vfsstat.f_mntonname,
1885 mp->mnt_vfsstat.f_fstypename);
1886#endif
1887}
1888
1889int
1890mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp,
1891 struct componentname *cnp, const char *vfc_name)
1892{
1893 kauth_cred_t cred;
1894 int error;
1895
1896#if SECURITY_MAC_CHECK_ENFORCE
1897 /* 21167099 - only check if we allow write */
1898 if (!mac_vnode_enforce)
1899 return 0;
1900#endif
1901 cred = vfs_context_ucred(ctx);
1902 if (!mac_cred_check_enforce(cred))
1903 return (0);
1904 MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name);
1905
1906 return (error);
1907}
1908
1909int
1910mac_mount_check_snapshot_create(vfs_context_t ctx, struct mount *mp,
1911 const char *name)
1912{
1913 kauth_cred_t cred;
1914 int error;
1915
1916#if SECURITY_MAC_CHECK_ENFORCE
1917 /* 21167099 - only check if we allow write */
1918 if (!mac_vnode_enforce)
1919 return 0;
1920#endif
1921 cred = vfs_context_ucred(ctx);
1922 if (!mac_cred_check_enforce(cred))
1923 return (0);
1924 MAC_CHECK(mount_check_snapshot_create, cred, mp, name);
1925 return (error);
1926}
1927
1928int
1929mac_mount_check_snapshot_delete(vfs_context_t ctx, struct mount *mp,
1930 const char *name)
1931{
1932 kauth_cred_t cred;
1933 int error;
1934
1935#if SECURITY_MAC_CHECK_ENFORCE
1936 /* 21167099 - only check if we allow write */
1937 if (!mac_vnode_enforce)
1938 return 0;
1939#endif
1940 cred = vfs_context_ucred(ctx);
1941 if (!mac_cred_check_enforce(cred))
1942 return (0);
1943 MAC_CHECK(mount_check_snapshot_delete, cred, mp, name);
1944 return (error);
1945}
1946
1947int
1948mac_mount_check_snapshot_revert(vfs_context_t ctx, struct mount *mp,
1949 const char *name)
1950{
1951 kauth_cred_t cred;
1952 int error;
1953
1954#if SECURITY_MAC_CHECK_ENFORCE
1955 /* 21167099 - only check if we allow write */
1956 if (!mac_vnode_enforce)
1957 return 0;
1958#endif
1959 cred = vfs_context_ucred(ctx);
1960 if (!mac_cred_check_enforce(cred))
1961 return (0);
1962 MAC_CHECK(mount_check_snapshot_revert, cred, mp, name);
1963 return (error);
1964}
1965
1966int
1967mac_mount_check_remount(vfs_context_t ctx, struct mount *mp)
1968{
1969 kauth_cred_t cred;
1970 int error;
1971
1972#if SECURITY_MAC_CHECK_ENFORCE
1973 /* 21167099 - only check if we allow write */
1974 if (!mac_vnode_enforce)
1975 return 0;
1976#endif
1977 cred = vfs_context_ucred(ctx);
1978 if (!mac_cred_check_enforce(cred))
1979 return (0);
1980 MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel);
1981
1982 return (error);
1983}
1984
1985int
1986mac_mount_check_umount(vfs_context_t ctx, struct mount *mp)
1987{
1988 kauth_cred_t cred;
1989 int error;
1990
1991#if SECURITY_MAC_CHECK_ENFORCE
1992 /* 21167099 - only check if we allow write */
1993 if (!mac_vnode_enforce)
1994 return 0;
1995#endif
1996 cred = vfs_context_ucred(ctx);
1997 if (!mac_cred_check_enforce(cred))
1998 return (0);
1999 MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel);
2000
2001 return (error);
2002}
2003
2004int
2005mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp,
2006 struct vfs_attr *vfa)
2007{
2008 kauth_cred_t cred;
2009 int error;
2010
2011#if SECURITY_MAC_CHECK_ENFORCE
2012 /* 21167099 - only check if we allow write */
2013 if (!mac_vnode_enforce)
2014 return 0;
2015#endif
2016 cred = vfs_context_ucred(ctx);
2017 if (!mac_cred_check_enforce(cred))
2018 return (0);
2019 MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa);
2020 return (error);
2021}
2022
2023int
2024mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp,
2025 struct vfs_attr *vfa)
2026{
2027 kauth_cred_t cred;
2028 int error;
2029
2030#if SECURITY_MAC_CHECK_ENFORCE
2031 /* 21167099 - only check if we allow write */
2032 if (!mac_vnode_enforce)
2033 return 0;
2034#endif
2035 cred = vfs_context_ucred(ctx);
2036 if (!mac_cred_check_enforce(cred))
2037 return (0);
2038 MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa);
2039 return (error);
2040}
2041
2042int
2043mac_mount_check_stat(vfs_context_t ctx, struct mount *mount)
2044{
2045 kauth_cred_t cred;
2046 int error;
2047
2048#if SECURITY_MAC_CHECK_ENFORCE
2049 /* 21167099 - only check if we allow write */
2050 if (!mac_vnode_enforce)
2051 return 0;
2052#endif
2053 cred = vfs_context_ucred(ctx);
2054 if (!mac_cred_check_enforce(cred))
2055 return (0);
2056 MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel);
2057
2058 return (error);
2059}
2060
2061int
2062mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount)
2063{
2064 kauth_cred_t cred;
2065 int error;
2066
2067#if SECURITY_MAC_CHECK_ENFORCE
2068 /* 21167099 - only check if we allow write */
2069 if (!mac_vnode_enforce)
2070 return 0;
2071#endif
2072 cred = vfs_context_ucred(ctx);
2073 if (!mac_cred_check_enforce(cred))
2074 return (0);
2075 MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel);
2076
2077 return (error);
2078}
2079
2080int
2081mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd)
2082{
2083 kauth_cred_t cred;
2084 int error;
2085
2086#if SECURITY_MAC_CHECK_ENFORCE
2087 /* 21167099 - only check if we allow write */
2088 if (!mac_vnode_enforce)
2089 return 0;
2090#endif
2091 cred = vfs_context_ucred(ctx);
2092 if (!mac_cred_check_enforce(cred))
2093 return (0);
2094 MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd);
2095
2096 return (error);
2097}
2098
2099void
2100mac_devfs_label_associate_device(dev_t dev, struct devnode *de,
2101 const char *fullpath)
2102{
2103#if SECURITY_MAC_CHECK_ENFORCE
2104 /* 21167099 - only check if we allow write */
2105 if (!mac_device_enforce)
2106 return;
2107#endif
2108
2109 MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label,
2110 fullpath);
2111}
2112
2113void
2114mac_devfs_label_associate_directory(const char *dirname, int dirnamelen,
2115 struct devnode *de, const char *fullpath)
2116{
2117#if SECURITY_MAC_CHECK_ENFORCE
2118 /* 21167099 - only check if we allow write */
2119 if (!mac_device_enforce)
2120 return;
2121#endif
2122
2123 MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de,
2124 de->dn_label, fullpath);
2125}
2126
2127int
2128vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context)
2129{
2130 int error;
2131
2132#if SECURITY_MAC_CHECK_ENFORCE
2133 /* 21167099 - only check if we allow write */
2134 if (!mac_vnode_enforce)
2135 return 0;
2136#endif
2137 if (!mac_label_vnodes)
2138 return (0);
2139
2140 if (vp->v_mount == NULL) {
2141 printf("vn_setlabel: null v_mount\n");
2142 if (vp->v_type != VNON)
2143 printf("vn_setlabel: null v_mount with non-VNON\n");
2144 return (EBADF);
2145 }
2146
2147 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2148 return (ENOTSUP);
2149
2150 /*
2151 * Multi-phase commit. First check the policies to confirm the
2152 * change is OK. Then commit via the filesystem. Finally,
2153 * update the actual vnode label. Question: maybe the filesystem
2154 * should update the vnode at the end as part of VNOP_SETLABEL()?
2155 */
2156 error = mac_vnode_check_label_update(context, vp, intlabel);
2157 if (error)
2158 return (error);
2159
2160 error = VNOP_SETLABEL(vp, intlabel, context);
2161 if (error == ENOTSUP) {
2162 error = mac_vnode_label_store(context, vp,
2163 intlabel);
2164 if (error) {
2165 printf("%s: mac_vnode_label_store failed %d\n",
2166 __func__, error);
2167 return (error);
2168 }
2169 mac_vnode_label_update(context, vp, intlabel);
2170 } else
2171 if (error) {
2172 printf("vn_setlabel: vop setlabel failed %d\n", error);
2173 return (error);
2174 }
2175
2176 return (0);
2177}
2178
2179int
2180mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
2181 struct vnode *vp, vfs_context_t ctx)
2182{
2183 struct fileproc *fp;
2184#if CONFIG_MACF_SOCKET_SUBSET
2185 struct socket *so;
2186#endif
2187 struct pipe *cpipe;
2188 struct vnode *fvp;
2189 struct proc *p;
2190 int error;
2191
2192 error = 0;
2193
2194 /*
2195 * If no backing file, let the policy choose which label to use.
2196 */
2197 if (fnp->fd_fd == -1) {
2198 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
2199 mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label);
2200 return (0);
2201 }
2202
2203 p = vfs_context_proc(ctx);
2204 error = fp_lookup(p, fnp->fd_fd, &fp, 0);
2205 if (error)
2206 return (error);
2207
2208 if (fp->f_fglob == NULL) {
2209 error = EBADF;
2210 goto out;
2211 }
2212
2213 switch (FILEGLOB_DTYPE(fp->f_fglob)) {
2214 case DTYPE_VNODE:
2215 fvp = (struct vnode *)fp->f_fglob->fg_data;
2216 if ((error = vnode_getwithref(fvp)))
2217 goto out;
2218 MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label);
2219 (void)vnode_put(fvp);
2220 break;
2221#if CONFIG_MACF_SOCKET_SUBSET
2222 case DTYPE_SOCKET:
2223 so = (struct socket *)fp->f_fglob->fg_data;
2224 socket_lock(so, 1);
2225 MAC_PERFORM(vnode_label_associate_socket,
2226 vfs_context_ucred(ctx), (socket_t)so, so->so_label,
2227 vp, vp->v_label);
2228 socket_unlock(so, 1);
2229 break;
2230#endif
2231 case DTYPE_PSXSHM:
2232 pshm_label_associate(fp, vp, ctx);
2233 break;
2234 case DTYPE_PSXSEM:
2235 psem_label_associate(fp, vp, ctx);
2236 break;
2237 case DTYPE_PIPE:
2238 cpipe = (struct pipe *)fp->f_fglob->fg_data;
2239 /* kern/sys_pipe.c:pipe_select() suggests this test. */
2240 if (cpipe == (struct pipe *)-1) {
2241 error = EINVAL;
2242 goto out;
2243 }
2244 PIPE_LOCK(cpipe);
2245 MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx),
2246 cpipe, cpipe->pipe_label, vp, vp->v_label);
2247 PIPE_UNLOCK(cpipe);
2248 break;
2249 case DTYPE_KQUEUE:
2250 case DTYPE_FSEVENTS:
2251 case DTYPE_ATALK:
2252 case DTYPE_NETPOLICY:
2253 default:
2254 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
2255 mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label,
2256 vp, vp->v_label);
2257 break;
2258 }
2259out:
2260 fp_drop(p, fnp->fd_fd, fp, 0);
2261 return (error);
2262}
2263