mac_mls.c revision 103183
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed by Robert Watson for the TrustedBSD Project.
7 *
8 * This software was developed for the FreeBSD Project in part by NAI Labs,
9 * the Security Research Division of Network Associates, Inc. under
10 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
11 * CHATS research program.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 * 3. The names of the authors may not be used to endorse or promote
22 *    products derived from this software without specific prior written
23 *    permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * $FreeBSD: head/sys/security/mac_mls/mac_mls.c 103183 2002-09-10 12:45:02Z bde $
38 */
39
40/*
41 * Developed by the TrustedBSD Project.
42 * MLS fixed label mandatory confidentiality policy.
43 */
44
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/acl.h>
48#include <sys/conf.h>
49#include <sys/kernel.h>
50#include <sys/mac.h>
51#include <sys/malloc.h>
52#include <sys/mount.h>
53#include <sys/proc.h>
54#include <sys/systm.h>
55#include <sys/sysproto.h>
56#include <sys/sysent.h>
57#include <sys/vnode.h>
58#include <sys/file.h>
59#include <sys/socket.h>
60#include <sys/socketvar.h>
61#include <sys/pipe.h>
62#include <sys/sysctl.h>
63
64#include <fs/devfs/devfs.h>
65
66#include <net/bpfdesc.h>
67#include <net/if.h>
68#include <net/if_types.h>
69#include <net/if_var.h>
70
71#include <netinet/in.h>
72#include <netinet/ip_var.h>
73
74#include <vm/vm.h>
75
76#include <sys/mac_policy.h>
77
78#include <security/mac_mls/mac_mls.h>
79
80SYSCTL_DECL(_security_mac);
81
82SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
83    "TrustedBSD mac_mls policy controls");
84
85static int	mac_mls_enabled = 0;
86SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
87    &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
88TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
89
90static int	destroyed_not_inited;
91SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
92    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
93
94static int	mac_mls_revocation_enabled = 0;
95SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
96    &mac_mls_revocation_enabled, 0, "Revoke access to objects on relabel");
97TUNABLE_INT("security.mac.mls.revocation_enabled",
98    &mac_mls_revocation_enabled);
99
100static int	mac_mls_slot;
101#define	SLOT(l)	((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
102
103MALLOC_DEFINE(M_MACMLS, "mls label", "MAC/MLS labels");
104
105static int	mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
106		    struct label *vnodelabel, mode_t acc_mode);
107
108static struct mac_mls *
109mls_alloc(int how)
110{
111	struct mac_mls *mac_mls;
112
113	mac_mls = malloc(sizeof(struct mac_mls), M_MACMLS, M_ZERO | how);
114
115	return (mac_mls);
116}
117
118static void
119mls_free(struct mac_mls *mac_mls)
120{
121
122	if (mac_mls != NULL)
123		free(mac_mls, M_MACMLS);
124	else
125		atomic_add_int(&destroyed_not_inited, 1);
126}
127
128static int
129mac_mls_dominate_element(struct mac_mls_element *a,
130    struct mac_mls_element *b)
131{
132
133	switch(a->mme_type) {
134	case MAC_MLS_TYPE_EQUAL:
135	case MAC_MLS_TYPE_HIGH:
136		return (1);
137
138	case MAC_MLS_TYPE_LOW:
139		switch (b->mme_type) {
140		case MAC_MLS_TYPE_LEVEL:
141		case MAC_MLS_TYPE_HIGH:
142			return (0);
143
144		case MAC_MLS_TYPE_EQUAL:
145		case MAC_MLS_TYPE_LOW:
146			return (1);
147
148		default:
149			panic("mac_mls_dominate_element: b->mme_type invalid");
150		}
151
152	case MAC_MLS_TYPE_LEVEL:
153		switch (b->mme_type) {
154		case MAC_MLS_TYPE_EQUAL:
155		case MAC_MLS_TYPE_LOW:
156			return (1);
157
158		case MAC_MLS_TYPE_HIGH:
159			return (0);
160
161		case MAC_MLS_TYPE_LEVEL:
162			return (a->mme_level >= b->mme_level);
163
164		default:
165			panic("mac_mls_dominate_element: b->mme_type invalid");
166		}
167
168	default:
169		panic("mac_mls_dominate_element: a->mme_type invalid");
170	}
171
172	return (0);
173}
174
175static int
176mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
177{
178
179	return (mac_mls_dominate_element(&rangeb->mm_rangehigh,
180	    &rangea->mm_rangehigh) &&
181	    mac_mls_dominate_element(&rangea->mm_rangelow,
182	    &rangeb->mm_rangelow));
183}
184
185static int
186mac_mls_single_in_range(struct mac_mls *single, struct mac_mls *range)
187{
188
189	KASSERT((single->mm_flag & MAC_MLS_FLAG_SINGLE) != 0,
190	    ("mac_mls_single_in_range: a not single"));
191	KASSERT((range->mm_flag & MAC_MLS_FLAG_RANGE) != 0,
192	    ("mac_mls_single_in_range: b not range"));
193
194	return (mac_mls_dominate_element(&range->mm_rangehigh,
195	    &single->mm_single) &&
196	    mac_mls_dominate_element(&single->mm_single,
197	    &range->mm_rangelow));
198
199	return (1);
200}
201
202static int
203mac_mls_dominate_single(struct mac_mls *a, struct mac_mls *b)
204{
205	KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
206	    ("mac_mls_dominate_single: a not single"));
207	KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
208	    ("mac_mls_dominate_single: b not single"));
209
210	return (mac_mls_dominate_element(&a->mm_single, &b->mm_single));
211}
212
213static int
214mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
215{
216
217	if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
218	    b->mme_type == MAC_MLS_TYPE_EQUAL)
219		return (1);
220
221	return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
222}
223
224static int
225mac_mls_equal_range(struct mac_mls *a, struct mac_mls *b)
226{
227
228	KASSERT((a->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
229	    ("mac_mls_equal_range: a not range"));
230	KASSERT((b->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
231	    ("mac_mls_equal_range: b not range"));
232
233	return (mac_mls_equal_element(&a->mm_rangelow, &b->mm_rangelow) &&
234	    mac_mls_equal_element(&a->mm_rangehigh, &b->mm_rangehigh));
235}
236
237static int
238mac_mls_equal_single(struct mac_mls *a, struct mac_mls *b)
239{
240
241	KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
242	    ("mac_mls_equal_single: a not single"));
243	KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
244	    ("mac_mls_equal_single: b not single"));
245
246	return (mac_mls_equal_element(&a->mm_single, &b->mm_single));
247}
248
249static int
250mac_mls_valid(struct mac_mls *mac_mls)
251{
252
253	if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
254		switch (mac_mls->mm_single.mme_type) {
255		case MAC_MLS_TYPE_LEVEL:
256			break;
257
258		case MAC_MLS_TYPE_EQUAL:
259		case MAC_MLS_TYPE_HIGH:
260		case MAC_MLS_TYPE_LOW:
261			if (mac_mls->mm_single.mme_level != 0)
262				return (EINVAL);
263			break;
264
265		default:
266			return (EINVAL);
267		}
268	} else {
269		if (mac_mls->mm_single.mme_type != MAC_MLS_TYPE_UNDEF)
270			return (EINVAL);
271	}
272
273	if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
274		switch (mac_mls->mm_rangelow.mme_type) {
275		case MAC_MLS_TYPE_LEVEL:
276			break;
277
278		case MAC_MLS_TYPE_EQUAL:
279		case MAC_MLS_TYPE_HIGH:
280		case MAC_MLS_TYPE_LOW:
281			if (mac_mls->mm_rangelow.mme_level != 0)
282				return (EINVAL);
283			break;
284
285		default:
286			return (EINVAL);
287		}
288
289		switch (mac_mls->mm_rangehigh.mme_type) {
290		case MAC_MLS_TYPE_LEVEL:
291			break;
292
293		case MAC_MLS_TYPE_EQUAL:
294		case MAC_MLS_TYPE_HIGH:
295		case MAC_MLS_TYPE_LOW:
296			if (mac_mls->mm_rangehigh.mme_level != 0)
297				return (EINVAL);
298			break;
299
300		default:
301			return (EINVAL);
302		}
303		if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh,
304		    &mac_mls->mm_rangelow))
305			return (EINVAL);
306	} else {
307		if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
308		    mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
309			return (EINVAL);
310	}
311
312	return (0);
313}
314
315static void
316mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow,
317    u_short levellow, u_short typehigh, u_short levelhigh)
318{
319
320	mac_mls->mm_rangelow.mme_type = typelow;
321	mac_mls->mm_rangelow.mme_level = levellow;
322	mac_mls->mm_rangehigh.mme_type = typehigh;
323	mac_mls->mm_rangehigh.mme_level = levelhigh;
324	mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
325}
326
327static void
328mac_mls_set_single(struct mac_mls *mac_mls, u_short type, u_short level)
329{
330
331	mac_mls->mm_single.mme_type = type;
332	mac_mls->mm_single.mme_level = level;
333	mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE;
334}
335
336static void
337mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
338{
339	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
340	    ("mac_mls_copy_range: labelfrom not range"));
341
342	labelto->mm_rangelow = labelfrom->mm_rangelow;
343	labelto->mm_rangehigh = labelfrom->mm_rangehigh;
344	labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
345}
346
347static void
348mac_mls_copy_single(struct mac_mls *labelfrom, struct mac_mls *labelto)
349{
350
351	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
352	    ("mac_mls_copy_single: labelfrom not single"));
353
354	labelto->mm_single = labelfrom->mm_single;
355	labelto->mm_flags |= MAC_MLS_FLAG_SINGLE;
356}
357
358static void
359mac_mls_copy_single_to_range(struct mac_mls *labelfrom,
360    struct mac_mls *labelto)
361{
362
363	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
364	    ("mac_mls_copy_single_to_range: labelfrom not single"));
365
366	labelto->mm_rangelow = labelfrom->mm_single;
367	labelto->mm_rangehigh = labelfrom->mm_single;
368	labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
369}
370
371/*
372 * Policy module operations.
373 */
374static void
375mac_mls_destroy(struct mac_policy_conf *conf)
376{
377
378}
379
380static void
381mac_mls_init(struct mac_policy_conf *conf)
382{
383
384}
385
386/*
387 * Label operations.
388 */
389static void
390mac_mls_init_bpfdesc(struct bpf_d *bpf_d, struct label *label)
391{
392
393	SLOT(label) = mls_alloc(M_WAITOK);
394}
395
396static void
397mac_mls_init_cred(struct ucred *ucred, struct label *label)
398{
399
400	SLOT(label) = mls_alloc(M_WAITOK);
401}
402
403static void
404mac_mls_init_devfsdirent(struct devfs_dirent *devfs_dirent,
405    struct label *label)
406{
407
408	SLOT(label) = mls_alloc(M_WAITOK);
409}
410
411static void
412mac_mls_init_ifnet(struct ifnet *ifnet, struct label *label)
413{
414
415	SLOT(label) = mls_alloc(M_WAITOK);
416}
417
418static void
419mac_mls_init_ipq(struct ipq *ipq, struct label *label)
420{
421
422	SLOT(label) = mls_alloc(M_WAITOK);
423}
424
425static int
426mac_mls_init_mbuf(struct mbuf *mbuf, int how, struct label *label)
427{
428
429	SLOT(label) = mls_alloc(how);
430	if (SLOT(label) == NULL)
431		return (ENOMEM);
432
433	return (0);
434}
435
436static void
437mac_mls_init_mount(struct mount *mount, struct label *mntlabel,
438    struct label *fslabel)
439{
440
441	SLOT(mntlabel) = mls_alloc(M_WAITOK);
442	SLOT(fslabel) = mls_alloc(M_WAITOK);
443}
444
445static void
446mac_mls_init_socket(struct socket *socket, struct label *label,
447    struct label *peerlabel)
448{
449
450	SLOT(label) = mls_alloc(M_WAITOK);
451	SLOT(peerlabel) = mls_alloc(M_WAITOK);
452}
453
454static void
455mac_mls_init_pipe(struct pipe *pipe, struct label *label)
456{
457
458	SLOT(label) = mls_alloc(M_WAITOK);
459}
460
461static void
462mac_mls_init_temp(struct label *label)
463{
464
465	SLOT(label) = mls_alloc(M_WAITOK);
466}
467
468static void
469mac_mls_init_vnode(struct vnode *vp, struct label *label)
470{
471
472	SLOT(label) = mls_alloc(M_WAITOK);
473}
474
475static void
476mac_mls_destroy_bpfdesc(struct bpf_d *bpf_d, struct label *label)
477{
478
479	mls_free(SLOT(label));
480	SLOT(label) = NULL;
481}
482
483static void
484mac_mls_destroy_cred(struct ucred *ucred, struct label *label)
485{
486
487	mls_free(SLOT(label));
488	SLOT(label) = NULL;
489}
490
491static void
492mac_mls_destroy_devfsdirent(struct devfs_dirent *devfs_dirent,
493    struct label *label)
494{
495
496	mls_free(SLOT(label));
497	SLOT(label) = NULL;
498}
499
500static void
501mac_mls_destroy_ifnet(struct ifnet *ifnet, struct label *label)
502{
503
504	mls_free(SLOT(label));
505	SLOT(label) = NULL;
506}
507
508static void
509mac_mls_destroy_ipq(struct ipq *ipq, struct label *label)
510{
511
512	mls_free(SLOT(label));
513	SLOT(label) = NULL;
514}
515
516static void
517mac_mls_destroy_mbuf(struct mbuf *mbuf, struct label *label)
518{
519
520	mls_free(SLOT(label));
521	SLOT(label) = NULL;
522}
523
524static void
525mac_mls_destroy_mount(struct mount *mount, struct label *mntlabel,
526    struct label *fslabel)
527{
528
529	mls_free(SLOT(mntlabel));
530	SLOT(mntlabel) = NULL;
531	mls_free(SLOT(fslabel));
532	SLOT(fslabel) = NULL;
533}
534
535static void
536mac_mls_destroy_socket(struct socket *socket, struct label *label,
537    struct label *peerlabel)
538{
539
540	mls_free(SLOT(label));
541	SLOT(label) = NULL;
542	mls_free(SLOT(peerlabel));
543	SLOT(peerlabel) = NULL;
544}
545
546static void
547mac_mls_destroy_pipe(struct pipe *pipe, struct label *label)
548{
549
550	mls_free(SLOT(label));
551	SLOT(label) = NULL;
552}
553
554static void
555mac_mls_destroy_temp(struct label *label)
556{
557
558	mls_free(SLOT(label));
559	SLOT(label) = NULL;
560}
561
562static void
563mac_mls_destroy_vnode(struct vnode *vp, struct label *label)
564{
565
566	mls_free(SLOT(label));
567	SLOT(label) = NULL;
568}
569
570static int
571mac_mls_externalize(struct label *label, struct mac *extmac)
572{
573	struct mac_mls *mac_mls;
574
575	mac_mls = SLOT(label);
576
577	if (mac_mls == NULL) {
578		printf("mac_mls_externalize: NULL pointer\n");
579		return (0);
580	}
581
582	extmac->m_mls = *mac_mls;
583
584	return (0);
585}
586
587static int
588mac_mls_internalize(struct label *label, struct mac *extmac)
589{
590	struct mac_mls *mac_mls;
591	int error;
592
593	mac_mls = SLOT(label);
594
595	error = mac_mls_valid(mac_mls);
596	if (error)
597		return (error);
598
599	*mac_mls = extmac->m_mls;
600
601	return (0);
602}
603
604/*
605 * Labeling event operations: file system objects, and things that look
606 * a lot like file system objects.
607 */
608static void
609mac_mls_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent,
610    struct label *label)
611{
612	struct mac_mls *mac_mls;
613	int mls_type;
614
615	mac_mls = SLOT(label);
616	if (strcmp(dev->si_name, "null") == 0 ||
617	    strcmp(dev->si_name, "zero") == 0 ||
618	    strcmp(dev->si_name, "random") == 0 ||
619	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
620		mls_type = MAC_MLS_TYPE_EQUAL;
621	else if (strcmp(dev->si_name, "kmem") == 0 ||
622	    strcmp(dev->si_name, "mem") == 0)
623		mls_type = MAC_MLS_TYPE_HIGH;
624	else
625		mls_type = MAC_MLS_TYPE_LOW;
626	mac_mls_set_single(mac_mls, mls_type, 0);
627}
628
629static void
630mac_mls_create_devfs_directory(char *dirname, int dirnamelen,
631    struct devfs_dirent *devfs_dirent, struct label *label)
632{
633	struct mac_mls *mac_mls;
634
635	mac_mls = SLOT(label);
636	mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
637}
638
639static void
640mac_mls_create_devfs_vnode(struct devfs_dirent *devfs_dirent,
641    struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
642{
643	struct mac_mls *source, *dest;
644
645	source = SLOT(direntlabel);
646	dest = SLOT(vnodelabel);
647	mac_mls_copy_single(source, dest);
648}
649
650static void
651mac_mls_create_vnode(struct ucred *cred, struct vnode *parent,
652    struct label *parentlabel, struct vnode *child, struct label *childlabel)
653{
654	struct mac_mls *source, *dest;
655
656	source = SLOT(&cred->cr_label);
657	dest = SLOT(childlabel);
658
659	mac_mls_copy_single(source, dest);
660}
661
662static void
663mac_mls_create_mount(struct ucred *cred, struct mount *mp,
664    struct label *mntlabel, struct label *fslabel)
665{
666	struct mac_mls *source, *dest;
667
668	source = SLOT(&cred->cr_label);
669	dest = SLOT(mntlabel);
670	mac_mls_copy_single(source, dest);
671	dest = SLOT(fslabel);
672	mac_mls_copy_single(source, dest);
673}
674
675static void
676mac_mls_create_root_mount(struct ucred *cred, struct mount *mp,
677    struct label *mntlabel, struct label *fslabel)
678{
679	struct mac_mls *mac_mls;
680
681	/* Always mount root as high integrity. */
682	mac_mls = SLOT(fslabel);
683	mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
684	mac_mls = SLOT(mntlabel);
685	mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
686}
687
688static void
689mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp,
690    struct label *vnodelabel, struct label *label)
691{
692	struct mac_mls *source, *dest;
693
694	source = SLOT(label);
695	dest = SLOT(vnodelabel);
696
697	mac_mls_copy_single(source, dest);
698}
699
700static void
701mac_mls_update_devfsdirent(struct devfs_dirent *devfs_dirent,
702    struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
703{
704	struct mac_mls *source, *dest;
705
706	source = SLOT(vnodelabel);
707	dest = SLOT(direntlabel);
708
709	mac_mls_copy_single(source, dest);
710}
711
712static void
713mac_mls_update_procfsvnode(struct vnode *vp, struct label *vnodelabel,
714    struct ucred *cred)
715{
716	struct mac_mls *source, *dest;
717
718	source = SLOT(&cred->cr_label);
719	dest = SLOT(vnodelabel);
720
721	/*
722	 * Only copy the single, not the range, since vnodes only have
723	 * a single.
724	 */
725	mac_mls_copy_single(source, dest);
726}
727
728static int
729mac_mls_update_vnode_from_externalized(struct vnode *vp,
730    struct label *vnodelabel, struct mac *extmac)
731{
732	struct mac_mls *source, *dest;
733	int error;
734
735	source = &extmac->m_mls;
736	dest = SLOT(vnodelabel);
737
738	error = mac_mls_valid(source);
739	if (error)
740		return (error);
741
742	if ((source->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
743		return (EINVAL);
744
745	mac_mls_copy_single(source, dest);
746
747	return (0);
748}
749
750static void
751mac_mls_update_vnode_from_mount(struct vnode *vp, struct label *vnodelabel,
752    struct mount *mp, struct label *fslabel)
753{
754	struct mac_mls *source, *dest;
755
756	source = SLOT(fslabel);
757	dest = SLOT(vnodelabel);
758
759	mac_mls_copy_single(source, dest);
760}
761
762/*
763 * Labeling event operations: IPC object.
764 */
765static void
766mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
767    struct mbuf *m, struct label *mbuflabel)
768{
769	struct mac_mls *source, *dest;
770
771	source = SLOT(socketlabel);
772	dest = SLOT(mbuflabel);
773
774	mac_mls_copy_single(source, dest);
775}
776
777static void
778mac_mls_create_socket(struct ucred *cred, struct socket *socket,
779    struct label *socketlabel)
780{
781	struct mac_mls *source, *dest;
782
783	source = SLOT(&cred->cr_label);
784	dest = SLOT(socketlabel);
785
786	mac_mls_copy_single(source, dest);
787	mac_mls_copy_single_to_range(source, dest);
788}
789
790static void
791mac_mls_create_pipe(struct ucred *cred, struct pipe *pipe,
792    struct label *pipelabel)
793{
794	struct mac_mls *source, *dest;
795
796	source = SLOT(&cred->cr_label);
797	dest = SLOT(pipelabel);
798
799	mac_mls_copy_single(source, dest);
800}
801
802static void
803mac_mls_create_socket_from_socket(struct socket *oldsocket,
804    struct label *oldsocketlabel, struct socket *newsocket,
805    struct label *newsocketlabel)
806{
807	struct mac_mls *source, *dest;
808
809	source = SLOT(oldsocketlabel);
810	dest = SLOT(newsocketlabel);
811
812	mac_mls_copy_single(source, dest);
813	mac_mls_copy_range(source, dest);
814}
815
816static void
817mac_mls_relabel_socket(struct ucred *cred, struct socket *socket,
818    struct label *socketlabel, struct label *newlabel)
819{
820	struct mac_mls *source, *dest;
821
822	source = SLOT(newlabel);
823	dest = SLOT(socketlabel);
824
825	mac_mls_copy_single(source, dest);
826	mac_mls_copy_range(source, dest);
827}
828
829static void
830mac_mls_relabel_pipe(struct ucred *cred, struct pipe *pipe,
831    struct label *pipelabel, struct label *newlabel)
832{
833	struct mac_mls *source, *dest;
834
835	source = SLOT(newlabel);
836	dest = SLOT(pipelabel);
837
838	mac_mls_copy_single(source, dest);
839}
840
841static void
842mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
843    struct socket *socket, struct label *socketpeerlabel)
844{
845	struct mac_mls *source, *dest;
846
847	source = SLOT(mbuflabel);
848	dest = SLOT(socketpeerlabel);
849
850	mac_mls_copy_single(source, dest);
851}
852
853/*
854 * Labeling event operations: network objects.
855 */
856static void
857mac_mls_set_socket_peer_from_socket(struct socket *oldsocket,
858    struct label *oldsocketlabel, struct socket *newsocket,
859    struct label *newsocketpeerlabel)
860{
861	struct mac_mls *source, *dest;
862
863	source = SLOT(oldsocketlabel);
864	dest = SLOT(newsocketpeerlabel);
865
866	mac_mls_copy_single(source, dest);
867}
868
869static void
870mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
871    struct label *bpflabel)
872{
873	struct mac_mls *source, *dest;
874
875	source = SLOT(&cred->cr_label);
876	dest = SLOT(bpflabel);
877
878	mac_mls_copy_single(source, dest);
879}
880
881static void
882mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
883{
884	struct mac_mls *dest;
885	int level;
886
887	dest = SLOT(ifnetlabel);
888
889	if (ifnet->if_type == IFT_LOOP)
890		level = MAC_MLS_TYPE_EQUAL;
891	else
892		level = MAC_MLS_TYPE_LOW;
893
894	mac_mls_set_single(dest, level, 0);
895	mac_mls_set_range(dest, level, 0, level, 0);
896}
897
898static void
899mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
900    struct ipq *ipq, struct label *ipqlabel)
901{
902	struct mac_mls *source, *dest;
903
904	source = SLOT(fragmentlabel);
905	dest = SLOT(ipqlabel);
906
907	mac_mls_copy_single(source, dest);
908}
909
910static void
911mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
912    struct mbuf *datagram, struct label *datagramlabel)
913{
914	struct mac_mls *source, *dest;
915
916	source = SLOT(ipqlabel);
917	dest = SLOT(datagramlabel);
918
919	/* Just use the head, since we require them all to match. */
920	mac_mls_copy_single(source, dest);
921}
922
923static void
924mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
925    struct mbuf *fragment, struct label *fragmentlabel)
926{
927	struct mac_mls *source, *dest;
928
929	source = SLOT(datagramlabel);
930	dest = SLOT(fragmentlabel);
931
932	mac_mls_copy_single(source, dest);
933}
934
935static void
936mac_mls_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
937    struct label *oldmbuflabel, struct mbuf *newmbuf,
938    struct label *newmbuflabel)
939{
940	struct mac_mls *source, *dest;
941
942	source = SLOT(oldmbuflabel);
943	dest = SLOT(newmbuflabel);
944
945	mac_mls_copy_single(source, dest);
946}
947
948static void
949mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
950    struct mbuf *mbuf, struct label *mbuflabel)
951{
952	struct mac_mls *dest;
953
954	dest = SLOT(mbuflabel);
955
956	mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0);
957}
958
959static void
960mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
961    struct mbuf *mbuf, struct label *mbuflabel)
962{
963	struct mac_mls *source, *dest;
964
965	source = SLOT(bpflabel);
966	dest = SLOT(mbuflabel);
967
968	mac_mls_copy_single(source, dest);
969}
970
971static void
972mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
973    struct mbuf *m, struct label *mbuflabel)
974{
975	struct mac_mls *source, *dest;
976
977	source = SLOT(ifnetlabel);
978	dest = SLOT(mbuflabel);
979
980	mac_mls_copy_single(source, dest);
981}
982
983static void
984mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
985    struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
986    struct mbuf *newmbuf, struct label *newmbuflabel)
987{
988	struct mac_mls *source, *dest;
989
990	source = SLOT(oldmbuflabel);
991	dest = SLOT(newmbuflabel);
992
993	mac_mls_copy_single(source, dest);
994}
995
996static void
997mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
998    struct mbuf *newmbuf, struct label *newmbuflabel)
999{
1000	struct mac_mls *source, *dest;
1001
1002	source = SLOT(oldmbuflabel);
1003	dest = SLOT(newmbuflabel);
1004
1005	mac_mls_copy_single(source, dest);
1006}
1007
1008static int
1009mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1010    struct ipq *ipq, struct label *ipqlabel)
1011{
1012	struct mac_mls *a, *b;
1013
1014	a = SLOT(ipqlabel);
1015	b = SLOT(fragmentlabel);
1016
1017	return (mac_mls_equal_single(a, b));
1018}
1019
1020static void
1021mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1022    struct label *ifnetlabel, struct label *newlabel)
1023{
1024	struct mac_mls *source, *dest;
1025
1026	source = SLOT(newlabel);
1027	dest = SLOT(ifnetlabel);
1028
1029	mac_mls_copy_single(source, dest);
1030	mac_mls_copy_range(source, dest);
1031}
1032
1033static void
1034mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1035    struct ipq *ipq, struct label *ipqlabel)
1036{
1037
1038	/* NOOP: we only accept matching labels, so no need to update */
1039}
1040
1041/*
1042 * Labeling event operations: processes.
1043 */
1044static void
1045mac_mls_create_cred(struct ucred *cred_parent, struct ucred *cred_child)
1046{
1047	struct mac_mls *source, *dest;
1048
1049	source = SLOT(&cred_parent->cr_label);
1050	dest = SLOT(&cred_child->cr_label);
1051
1052	mac_mls_copy_single(source, dest);
1053	mac_mls_copy_range(source, dest);
1054}
1055
1056static void
1057mac_mls_execve_transition(struct ucred *old, struct ucred *new,
1058    struct vnode *vp, struct mac *vnodelabel)
1059{
1060	struct mac_mls *source, *dest;
1061
1062	source = SLOT(&old->cr_label);
1063	dest = SLOT(&new->cr_label);
1064
1065	mac_mls_copy_single(source, dest);
1066	mac_mls_copy_range(source, dest);
1067}
1068
1069static int
1070mac_mls_execve_will_transition(struct ucred *old, struct vnode *vp,
1071    struct mac *vnodelabel)
1072{
1073
1074	return (0);
1075}
1076
1077static void
1078mac_mls_create_proc0(struct ucred *cred)
1079{
1080	struct mac_mls *dest;
1081
1082	dest = SLOT(&cred->cr_label);
1083
1084	mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0);
1085	mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, MAC_MLS_TYPE_HIGH, 0);
1086}
1087
1088static void
1089mac_mls_create_proc1(struct ucred *cred)
1090{
1091	struct mac_mls *dest;
1092
1093	dest = SLOT(&cred->cr_label);
1094
1095	mac_mls_set_single(dest, MAC_MLS_TYPE_LOW, 0);
1096	mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, MAC_MLS_TYPE_HIGH, 0);
1097}
1098
1099static void
1100mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel)
1101{
1102	struct mac_mls *source, *dest;
1103
1104	source = SLOT(newlabel);
1105	dest = SLOT(&cred->cr_label);
1106
1107	mac_mls_copy_single(source, dest);
1108	mac_mls_copy_range(source, dest);
1109}
1110
1111/*
1112 * Access control checks.
1113 */
1114static int
1115mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1116     struct ifnet *ifnet, struct label *ifnetlabel)
1117{
1118	struct mac_mls *a, *b;
1119
1120	if (!mac_mls_enabled)
1121		return (0);
1122
1123	a = SLOT(bpflabel);
1124	b = SLOT(ifnetlabel);
1125
1126	if (mac_mls_equal_single(a, b))
1127		return (0);
1128	return (EACCES);
1129}
1130
1131static int
1132mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1133{
1134	struct mac_mls *subj, *new;
1135
1136	subj = SLOT(&cred->cr_label);
1137	new = SLOT(newlabel);
1138
1139	if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH)
1140		return (EINVAL);
1141
1142	/*
1143	 * XXX: Allow processes with root privilege to set labels outside
1144	 * their range, so suid things like "su" work.  This WILL go away
1145	 * when we figure out the 'correct' solution...
1146	 */
1147	if (!suser_cred(cred, 0))
1148		return (0);
1149
1150	/*
1151	 * The new single must be in the old range.
1152	 */
1153	if (!mac_mls_single_in_range(new, subj))
1154		return (EPERM);
1155
1156	/*
1157	 * The new range must be in the old range.
1158	 */
1159	if (!mac_mls_range_in_range(new, subj))
1160		return (EPERM);
1161
1162	/*
1163	 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1164	 */
1165
1166	return (0);
1167}
1168
1169
1170static int
1171mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
1172{
1173	struct mac_mls *subj, *obj;
1174
1175	if (!mac_mls_enabled)
1176		return (0);
1177
1178	subj = SLOT(&u1->cr_label);
1179	obj = SLOT(&u2->cr_label);
1180
1181	/* XXX: range */
1182	if (!mac_mls_dominate_single(subj, obj))
1183		return (ESRCH);
1184
1185	return (0);
1186}
1187
1188static int
1189mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1190    struct label *ifnetlabel, struct label *newlabel)
1191{
1192	struct mac_mls *subj, *new;
1193
1194	subj = SLOT(&cred->cr_label);
1195	new = SLOT(newlabel);
1196
1197	if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH)
1198		return (EINVAL);
1199
1200	/* XXX: privilege model here? */
1201
1202	return (suser_cred(cred, 0));
1203}
1204
1205static int
1206mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1207    struct mbuf *m, struct label *mbuflabel)
1208{
1209	struct mac_mls *p, *i;
1210
1211	if (!mac_mls_enabled)
1212		return (0);
1213
1214	p = SLOT(mbuflabel);
1215	i = SLOT(ifnetlabel);
1216
1217	return (mac_mls_single_in_range(p, i) ? 0 : EACCES);
1218}
1219
1220static int
1221mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp,
1222    struct label *mntlabel)
1223{
1224	struct mac_mls *subj, *obj;
1225
1226	if (!mac_mls_enabled)
1227		return (0);
1228
1229	subj = SLOT(&cred->cr_label);
1230	obj = SLOT(mntlabel);
1231
1232	if (!mac_mls_dominate_single(subj, obj))
1233		return (EACCES);
1234
1235	return (0);
1236}
1237
1238static int
1239mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1240    struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1241{
1242
1243	if(!mac_mls_enabled)
1244		return (0);
1245
1246	/* XXX: This will be implemented soon... */
1247
1248	return (0);
1249}
1250
1251static int
1252mac_mls_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
1253    struct label *pipelabel)
1254{
1255	struct mac_mls *subj, *obj;
1256
1257	if (!mac_mls_enabled)
1258		return (0);
1259
1260	subj = SLOT(&cred->cr_label);
1261	obj = SLOT((pipelabel));
1262
1263	if (!mac_mls_dominate_single(subj, obj))
1264		return (EACCES);
1265
1266	return (0);
1267}
1268
1269static int
1270mac_mls_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1271    struct label *pipelabel)
1272{
1273	struct mac_mls *subj, *obj;
1274
1275	if (!mac_mls_enabled)
1276		return (0);
1277
1278	subj = SLOT(&cred->cr_label);
1279	obj = SLOT((pipelabel));
1280
1281	if (!mac_mls_dominate_single(subj, obj))
1282		return (EACCES);
1283
1284	return (0);
1285}
1286
1287static int
1288mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1289    struct label *pipelabel, struct label *newlabel)
1290{
1291	struct mac_mls *subj, *obj, *new;
1292
1293	new = SLOT(newlabel);
1294	subj = SLOT(&cred->cr_label);
1295	obj = SLOT(pipelabel);
1296
1297	if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1298		return (EINVAL);
1299
1300	/*
1301	 * To relabel a pipe, the old pipe label must be in the subject
1302	 * range.
1303	 */
1304	if (!mac_mls_single_in_range(obj, subj))
1305		return (EPERM);
1306
1307	/*
1308	 * To relabel a pipe, the new pipe label must be in the subject
1309	 * range.
1310	 */
1311	if (!mac_mls_single_in_range(new, subj))
1312		return (EPERM);
1313
1314	/*
1315	 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1316	 */
1317
1318	return (0);
1319}
1320
1321static int
1322mac_mls_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
1323    struct label *pipelabel)
1324{
1325	struct mac_mls *subj, *obj;
1326
1327	if (!mac_mls_enabled)
1328		return (0);
1329
1330	subj = SLOT(&cred->cr_label);
1331	obj = SLOT((pipelabel));
1332
1333	if (!mac_mls_dominate_single(subj, obj))
1334		return (EACCES);
1335
1336	return (0);
1337}
1338
1339static int
1340mac_mls_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1341    struct label *pipelabel)
1342{
1343	struct mac_mls *subj, *obj;
1344
1345	if (!mac_mls_enabled)
1346		return (0);
1347
1348	subj = SLOT(&cred->cr_label);
1349	obj = SLOT((pipelabel));
1350
1351	if (!mac_mls_dominate_single(obj, subj))
1352		return (EACCES);
1353
1354	return (0);
1355}
1356
1357static int
1358mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc)
1359{
1360	struct mac_mls *subj, *obj;
1361
1362	if (!mac_mls_enabled)
1363		return (0);
1364
1365	subj = SLOT(&cred->cr_label);
1366	obj = SLOT(&proc->p_ucred->cr_label);
1367
1368	/* XXX: range checks */
1369	if (!mac_mls_dominate_single(subj, obj))
1370		return (ESRCH);
1371	if (!mac_mls_dominate_single(obj, subj))
1372		return (EACCES);
1373
1374	return (0);
1375}
1376
1377static int
1378mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc)
1379{
1380	struct mac_mls *subj, *obj;
1381
1382	if (!mac_mls_enabled)
1383		return (0);
1384
1385	subj = SLOT(&cred->cr_label);
1386	obj = SLOT(&proc->p_ucred->cr_label);
1387
1388	/* XXX: range checks */
1389	if (!mac_mls_dominate_single(subj, obj))
1390		return (ESRCH);
1391	if (!mac_mls_dominate_single(obj, subj))
1392		return (EACCES);
1393
1394	return (0);
1395}
1396
1397static int
1398mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1399{
1400	struct mac_mls *subj, *obj;
1401
1402	if (!mac_mls_enabled)
1403		return (0);
1404
1405	subj = SLOT(&cred->cr_label);
1406	obj = SLOT(&proc->p_ucred->cr_label);
1407
1408	/* XXX: range checks */
1409	if (!mac_mls_dominate_single(subj, obj))
1410		return (ESRCH);
1411	if (!mac_mls_dominate_single(obj, subj))
1412		return (EACCES);
1413
1414	return (0);
1415}
1416
1417static int
1418mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel,
1419    struct mbuf *m, struct label *mbuflabel)
1420{
1421	struct mac_mls *p, *s;
1422
1423	if (!mac_mls_enabled)
1424		return (0);
1425
1426	p = SLOT(mbuflabel);
1427	s = SLOT(socketlabel);
1428
1429	return (mac_mls_equal_single(p, s) ? 0 : EACCES);
1430}
1431
1432static int
1433mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket,
1434    struct label *socketlabel, struct label *newlabel)
1435{
1436	struct mac_mls *subj, *obj, *new;
1437
1438	new = SLOT(newlabel);
1439	subj = SLOT(&cred->cr_label);
1440	obj = SLOT(socketlabel);
1441
1442	if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1443		return (EINVAL);
1444
1445	/*
1446	 * To relabel a socket, the old socket label must be in the subject
1447	 * range.
1448	 */
1449	if (!mac_mls_single_in_range(obj, subj))
1450		return (EPERM);
1451
1452	/*
1453	 * To relabel a socket, the new socket label must be in the subject
1454	 * range.
1455	 */
1456	if (!mac_mls_single_in_range(new, subj))
1457		return (EPERM);
1458
1459	/*
1460	 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1461	 */
1462
1463	return (0);
1464}
1465
1466static int
1467mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket,
1468    struct label *socketlabel)
1469{
1470	struct mac_mls *subj, *obj;
1471
1472	if (!mac_mls_enabled)
1473		return (0);
1474
1475	subj = SLOT(&cred->cr_label);
1476	obj = SLOT(socketlabel);
1477
1478	if (!mac_mls_dominate_single(subj, obj))
1479		return (ENOENT);
1480
1481	return (0);
1482}
1483
1484static int
1485mac_mls_check_vnode_access(struct ucred *cred, struct vnode *vp,
1486    struct label *label, mode_t flags)
1487{
1488
1489	return (mac_mls_check_vnode_open(cred, vp, label, flags));
1490}
1491
1492static int
1493mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
1494    struct label *dlabel)
1495{
1496	struct mac_mls *subj, *obj;
1497
1498	if (!mac_mls_enabled)
1499		return (0);
1500
1501	subj = SLOT(&cred->cr_label);
1502	obj = SLOT(dlabel);
1503
1504	if (!mac_mls_dominate_single(subj, obj))
1505		return (EACCES);
1506
1507	return (0);
1508}
1509
1510static int
1511mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
1512    struct label *dlabel)
1513{
1514	struct mac_mls *subj, *obj;
1515
1516	if (!mac_mls_enabled)
1517		return (0);
1518
1519	subj = SLOT(&cred->cr_label);
1520	obj = SLOT(dlabel);
1521
1522	if (!mac_mls_dominate_single(subj, obj))
1523		return (EACCES);
1524
1525	return (0);
1526}
1527
1528static int
1529mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1530    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
1531{
1532	struct mac_mls *subj, *obj;
1533
1534	if (!mac_mls_enabled)
1535		return (0);
1536
1537	subj = SLOT(&cred->cr_label);
1538	obj = SLOT(dlabel);
1539
1540	if (!mac_mls_dominate_single(obj, subj))
1541		return (EACCES);
1542
1543	return (0);
1544}
1545
1546static int
1547mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
1548    struct label *dlabel, struct vnode *vp, struct label *label,
1549    struct componentname *cnp)
1550{
1551	struct mac_mls *subj, *obj;
1552
1553	if (!mac_mls_enabled)
1554		return (0);
1555
1556	subj = SLOT(&cred->cr_label);
1557	obj = SLOT(dlabel);
1558
1559	if (!mac_mls_dominate_single(obj, subj))
1560		return (EACCES);
1561
1562	obj = SLOT(label);
1563
1564	if (!mac_mls_dominate_single(obj, subj))
1565		return (EACCES);
1566
1567	return (0);
1568}
1569
1570static int
1571mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1572    struct label *label, acl_type_t type)
1573{
1574	struct mac_mls *subj, *obj;
1575
1576	if (!mac_mls_enabled)
1577		return (0);
1578
1579	subj = SLOT(&cred->cr_label);
1580	obj = SLOT(label);
1581
1582	if (!mac_mls_dominate_single(obj, subj))
1583		return (EACCES);
1584
1585	return (0);
1586}
1587
1588static int
1589mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1590    struct label *label)
1591{
1592	struct mac_mls *subj, *obj;
1593
1594	if (!mac_mls_enabled)
1595		return (0);
1596
1597	subj = SLOT(&cred->cr_label);
1598	obj = SLOT(label);
1599
1600	if (!mac_mls_dominate_single(subj, obj))
1601		return (EACCES);
1602
1603	return (0);
1604}
1605
1606static int
1607mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
1608    struct label *label, acl_type_t type)
1609{
1610	struct mac_mls *subj, *obj;
1611
1612	if (!mac_mls_enabled)
1613		return (0);
1614
1615	subj = SLOT(&cred->cr_label);
1616	obj = SLOT(label);
1617
1618	if (!mac_mls_dominate_single(subj, obj))
1619		return (EACCES);
1620
1621	return (0);
1622}
1623
1624static int
1625mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1626    struct label *label, int attrnamespace, const char *name, struct uio *uio)
1627{
1628	struct mac_mls *subj, *obj;
1629
1630	if (!mac_mls_enabled)
1631		return (0);
1632
1633	subj = SLOT(&cred->cr_label);
1634	obj = SLOT(label);
1635
1636	if (!mac_mls_dominate_single(subj, obj))
1637		return (EACCES);
1638
1639	return (0);
1640}
1641
1642static int
1643mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1644    struct label *dlabel, struct componentname *cnp)
1645{
1646	struct mac_mls *subj, *obj;
1647
1648	if (!mac_mls_enabled)
1649		return (0);
1650
1651	subj = SLOT(&cred->cr_label);
1652	obj = SLOT(dlabel);
1653
1654	if (!mac_mls_dominate_single(subj, obj))
1655		return (EACCES);
1656
1657	return (0);
1658}
1659
1660static int
1661mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
1662    struct label *vnodelabel, mode_t acc_mode)
1663{
1664	struct mac_mls *subj, *obj;
1665
1666	if (!mac_mls_enabled)
1667		return (0);
1668
1669	subj = SLOT(&cred->cr_label);
1670	obj = SLOT(vnodelabel);
1671
1672	/* XXX privilege override for admin? */
1673	if (acc_mode & (VREAD | VEXEC | VSTAT)) {
1674		if (!mac_mls_dominate_single(subj, obj))
1675			return (EACCES);
1676	}
1677	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
1678		if (!mac_mls_dominate_single(obj, subj))
1679			return (EACCES);
1680	}
1681
1682	return (0);
1683}
1684
1685static int
1686mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1687    struct vnode *vp, struct label *label)
1688{
1689	struct mac_mls *subj, *obj;
1690
1691	if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1692		return (0);
1693
1694	subj = SLOT(&active_cred->cr_label);
1695	obj = SLOT(label);
1696
1697	if (!mac_mls_dominate_single(subj, obj))
1698		return (EACCES);
1699
1700	return (0);
1701}
1702
1703static int
1704mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1705    struct vnode *vp, struct label *label)
1706{
1707	struct mac_mls *subj, *obj;
1708
1709	if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1710		return (0);
1711
1712	subj = SLOT(&active_cred->cr_label);
1713	obj = SLOT(label);
1714
1715	if (!mac_mls_dominate_single(subj, obj))
1716		return (EACCES);
1717
1718	return (0);
1719}
1720
1721static int
1722mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
1723    struct label *dlabel)
1724{
1725	struct mac_mls *subj, *obj;
1726
1727	if (!mac_mls_enabled)
1728		return (0);
1729
1730	subj = SLOT(&cred->cr_label);
1731	obj = SLOT(dlabel);
1732
1733	if (!mac_mls_dominate_single(subj, obj))
1734		return (EACCES);
1735
1736	return (0);
1737}
1738
1739static int
1740mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
1741    struct label *vnodelabel)
1742{
1743	struct mac_mls *subj, *obj;
1744
1745	if (!mac_mls_enabled)
1746		return (0);
1747
1748	subj = SLOT(&cred->cr_label);
1749	obj = SLOT(vnodelabel);
1750
1751	if (!mac_mls_dominate_single(subj, obj))
1752		return (EACCES);
1753
1754	return (0);
1755}
1756
1757static int
1758mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1759    struct label *vnodelabel, struct label *newlabel)
1760{
1761	struct mac_mls *old, *new, *subj;
1762
1763	old = SLOT(vnodelabel);
1764	new = SLOT(newlabel);
1765	subj = SLOT(&cred->cr_label);
1766
1767	if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1768		return (EINVAL);
1769
1770	/*
1771	 * To relabel a vnode, the old vnode label must be in the subject
1772	 * range.
1773	 */
1774	if (!mac_mls_single_in_range(old, subj))
1775		return (EPERM);
1776
1777	/*
1778	 * To relabel a vnode, the new vnode label must be in the subject
1779	 * range.
1780	 */
1781	if (!mac_mls_single_in_range(new, subj))
1782		return (EPERM);
1783
1784	/*
1785	 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1786	 */
1787
1788	return (suser_cred(cred, 0));
1789}
1790
1791
1792static int
1793mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1794    struct label *dlabel, struct vnode *vp, struct label *label,
1795    struct componentname *cnp)
1796{
1797	struct mac_mls *subj, *obj;
1798
1799	if (!mac_mls_enabled)
1800		return (0);
1801
1802	subj = SLOT(&cred->cr_label);
1803	obj = SLOT(dlabel);
1804
1805	if (!mac_mls_dominate_single(obj, subj))
1806		return (EACCES);
1807
1808	obj = SLOT(label);
1809
1810	if (!mac_mls_dominate_single(obj, subj))
1811		return (EACCES);
1812
1813	return (0);
1814}
1815
1816static int
1817mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1818    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
1819    struct componentname *cnp)
1820{
1821	struct mac_mls *subj, *obj;
1822
1823	if (!mac_mls_enabled)
1824		return (0);
1825
1826	subj = SLOT(&cred->cr_label);
1827	obj = SLOT(dlabel);
1828
1829	if (!mac_mls_dominate_single(obj, subj))
1830		return (EACCES);
1831
1832	if (vp != NULL) {
1833		obj = SLOT(label);
1834
1835		if (!mac_mls_dominate_single(obj, subj))
1836			return (EACCES);
1837	}
1838
1839	return (0);
1840}
1841
1842static int
1843mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
1844    struct label *label)
1845{
1846	struct mac_mls *subj, *obj;
1847
1848	if (!mac_mls_enabled)
1849		return (0);
1850
1851	subj = SLOT(&cred->cr_label);
1852	obj = SLOT(label);
1853
1854	if (!mac_mls_dominate_single(obj, subj))
1855		return (EACCES);
1856
1857	return (0);
1858}
1859
1860static int
1861mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
1862    struct label *label, acl_type_t type, struct acl *acl)
1863{
1864	struct mac_mls *subj, *obj;
1865
1866	if (!mac_mls_enabled)
1867		return (0);
1868
1869	subj = SLOT(&cred->cr_label);
1870	obj = SLOT(label);
1871
1872	if (!mac_mls_dominate_single(obj, subj))
1873		return (EACCES);
1874
1875	return (0);
1876}
1877
1878static int
1879mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1880    struct label *vnodelabel, int attrnamespace, const char *name,
1881    struct uio *uio)
1882{
1883	struct mac_mls *subj, *obj;
1884
1885	if (!mac_mls_enabled)
1886		return (0);
1887
1888	subj = SLOT(&cred->cr_label);
1889	obj = SLOT(vnodelabel);
1890
1891	if (!mac_mls_dominate_single(obj, subj))
1892		return (EACCES);
1893
1894	/* XXX: protect the MAC EA in a special way? */
1895
1896	return (0);
1897}
1898
1899static int
1900mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
1901    struct label *vnodelabel, u_long flags)
1902{
1903	struct mac_mls *subj, *obj;
1904
1905	if (!mac_mls_enabled)
1906		return (0);
1907
1908	subj = SLOT(&cred->cr_label);
1909	obj = SLOT(vnodelabel);
1910
1911	if (!mac_mls_dominate_single(obj, subj))
1912		return (EACCES);
1913
1914	return (0);
1915}
1916
1917static int
1918mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
1919    struct label *vnodelabel, mode_t mode)
1920{
1921	struct mac_mls *subj, *obj;
1922
1923	if (!mac_mls_enabled)
1924		return (0);
1925
1926	subj = SLOT(&cred->cr_label);
1927	obj = SLOT(vnodelabel);
1928
1929	if (!mac_mls_dominate_single(obj, subj))
1930		return (EACCES);
1931
1932	return (0);
1933}
1934
1935static int
1936mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
1937    struct label *vnodelabel, uid_t uid, gid_t gid)
1938{
1939	struct mac_mls *subj, *obj;
1940
1941	if (!mac_mls_enabled)
1942		return (0);
1943
1944	subj = SLOT(&cred->cr_label);
1945	obj = SLOT(vnodelabel);
1946
1947	if (!mac_mls_dominate_single(obj, subj))
1948		return (EACCES);
1949
1950	return (0);
1951}
1952
1953static int
1954mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1955    struct label *vnodelabel, struct timespec atime, struct timespec mtime)
1956{
1957	struct mac_mls *subj, *obj;
1958
1959	if (!mac_mls_enabled)
1960		return (0);
1961
1962	subj = SLOT(&cred->cr_label);
1963	obj = SLOT(vnodelabel);
1964
1965	if (!mac_mls_dominate_single(obj, subj))
1966		return (EACCES);
1967
1968	return (0);
1969}
1970
1971static int
1972mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1973    struct vnode *vp, struct label *vnodelabel)
1974{
1975	struct mac_mls *subj, *obj;
1976
1977	if (!mac_mls_enabled)
1978		return (0);
1979
1980	subj = SLOT(&active_cred->cr_label);
1981	obj = SLOT(vnodelabel);
1982
1983	if (!mac_mls_dominate_single(subj, obj))
1984		return (EACCES);
1985
1986	return (0);
1987}
1988
1989static int
1990mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1991    struct vnode *vp, struct label *label)
1992{
1993	struct mac_mls *subj, *obj;
1994
1995	if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1996		return (0);
1997
1998	subj = SLOT(&active_cred->cr_label);
1999	obj = SLOT(label);
2000
2001	if (!mac_mls_dominate_single(obj, subj))
2002		return (EACCES);
2003
2004	return (0);
2005}
2006
2007static vm_prot_t
2008mac_mls_check_vnode_mmap_perms(struct ucred *cred, struct vnode *vp,
2009    struct label *label, int newmapping)
2010{
2011	struct mac_mls *subj, *obj;
2012	vm_prot_t prot = 0;
2013
2014	if (!mac_mls_enabled || (!mac_mls_revocation_enabled && !newmapping))
2015		return (VM_PROT_ALL);
2016
2017	subj = SLOT(&cred->cr_label);
2018	obj = SLOT(label);
2019
2020	if (mac_mls_dominate_single(subj, obj))
2021		prot |= VM_PROT_READ | VM_PROT_EXECUTE;
2022	if (mac_mls_dominate_single(obj, subj))
2023		prot |= VM_PROT_WRITE;
2024	return (prot);
2025}
2026
2027static struct mac_policy_op_entry mac_mls_ops[] =
2028{
2029	{ MAC_DESTROY,
2030	    (macop_t)mac_mls_destroy },
2031	{ MAC_INIT,
2032	    (macop_t)mac_mls_init },
2033	{ MAC_INIT_BPFDESC,
2034	    (macop_t)mac_mls_init_bpfdesc },
2035	{ MAC_INIT_CRED,
2036	    (macop_t)mac_mls_init_cred },
2037	{ MAC_INIT_DEVFSDIRENT,
2038	    (macop_t)mac_mls_init_devfsdirent },
2039	{ MAC_INIT_IFNET,
2040	    (macop_t)mac_mls_init_ifnet },
2041	{ MAC_INIT_IPQ,
2042	    (macop_t)mac_mls_init_ipq },
2043	{ MAC_INIT_MBUF,
2044	    (macop_t)mac_mls_init_mbuf },
2045	{ MAC_INIT_MOUNT,
2046	    (macop_t)mac_mls_init_mount },
2047	{ MAC_INIT_PIPE,
2048	    (macop_t)mac_mls_init_pipe },
2049	{ MAC_INIT_SOCKET,
2050	    (macop_t)mac_mls_init_socket },
2051	{ MAC_INIT_TEMP,
2052	    (macop_t)mac_mls_init_temp },
2053	{ MAC_INIT_VNODE,
2054	    (macop_t)mac_mls_init_vnode },
2055	{ MAC_DESTROY_BPFDESC,
2056	    (macop_t)mac_mls_destroy_bpfdesc },
2057	{ MAC_DESTROY_CRED,
2058	    (macop_t)mac_mls_destroy_cred },
2059	{ MAC_DESTROY_DEVFSDIRENT,
2060	    (macop_t)mac_mls_destroy_devfsdirent },
2061	{ MAC_DESTROY_IFNET,
2062	    (macop_t)mac_mls_destroy_ifnet },
2063	{ MAC_DESTROY_IPQ,
2064	    (macop_t)mac_mls_destroy_ipq },
2065	{ MAC_DESTROY_MBUF,
2066	    (macop_t)mac_mls_destroy_mbuf },
2067	{ MAC_DESTROY_MOUNT,
2068	    (macop_t)mac_mls_destroy_mount },
2069	{ MAC_DESTROY_PIPE,
2070	    (macop_t)mac_mls_destroy_pipe },
2071	{ MAC_DESTROY_SOCKET,
2072	    (macop_t)mac_mls_destroy_socket },
2073	{ MAC_DESTROY_TEMP,
2074	    (macop_t)mac_mls_destroy_temp },
2075	{ MAC_DESTROY_VNODE,
2076	    (macop_t)mac_mls_destroy_vnode },
2077	{ MAC_EXTERNALIZE,
2078	    (macop_t)mac_mls_externalize },
2079	{ MAC_INTERNALIZE,
2080	    (macop_t)mac_mls_internalize },
2081	{ MAC_CREATE_DEVFS_DEVICE,
2082	    (macop_t)mac_mls_create_devfs_device },
2083	{ MAC_CREATE_DEVFS_DIRECTORY,
2084	    (macop_t)mac_mls_create_devfs_directory },
2085	{ MAC_CREATE_DEVFS_VNODE,
2086	    (macop_t)mac_mls_create_devfs_vnode },
2087	{ MAC_CREATE_VNODE,
2088	    (macop_t)mac_mls_create_vnode },
2089	{ MAC_CREATE_MOUNT,
2090	    (macop_t)mac_mls_create_mount },
2091	{ MAC_CREATE_ROOT_MOUNT,
2092	    (macop_t)mac_mls_create_root_mount },
2093	{ MAC_RELABEL_VNODE,
2094	    (macop_t)mac_mls_relabel_vnode },
2095	{ MAC_UPDATE_DEVFSDIRENT,
2096	    (macop_t)mac_mls_update_devfsdirent },
2097	{ MAC_UPDATE_PROCFSVNODE,
2098	    (macop_t)mac_mls_update_procfsvnode },
2099	{ MAC_UPDATE_VNODE_FROM_EXTERNALIZED,
2100	    (macop_t)mac_mls_update_vnode_from_externalized },
2101	{ MAC_UPDATE_VNODE_FROM_MOUNT,
2102	    (macop_t)mac_mls_update_vnode_from_mount },
2103	{ MAC_CREATE_MBUF_FROM_SOCKET,
2104	    (macop_t)mac_mls_create_mbuf_from_socket },
2105	{ MAC_CREATE_PIPE,
2106	    (macop_t)mac_mls_create_pipe },
2107	{ MAC_CREATE_SOCKET,
2108	    (macop_t)mac_mls_create_socket },
2109	{ MAC_CREATE_SOCKET_FROM_SOCKET,
2110	    (macop_t)mac_mls_create_socket_from_socket },
2111	{ MAC_RELABEL_PIPE,
2112	    (macop_t)mac_mls_relabel_pipe },
2113	{ MAC_RELABEL_SOCKET,
2114	    (macop_t)mac_mls_relabel_socket },
2115	{ MAC_SET_SOCKET_PEER_FROM_MBUF,
2116	    (macop_t)mac_mls_set_socket_peer_from_mbuf },
2117	{ MAC_SET_SOCKET_PEER_FROM_SOCKET,
2118	    (macop_t)mac_mls_set_socket_peer_from_socket },
2119	{ MAC_CREATE_BPFDESC,
2120	    (macop_t)mac_mls_create_bpfdesc },
2121	{ MAC_CREATE_DATAGRAM_FROM_IPQ,
2122	    (macop_t)mac_mls_create_datagram_from_ipq },
2123	{ MAC_CREATE_FRAGMENT,
2124	    (macop_t)mac_mls_create_fragment },
2125	{ MAC_CREATE_IFNET,
2126	    (macop_t)mac_mls_create_ifnet },
2127	{ MAC_CREATE_IPQ,
2128	    (macop_t)mac_mls_create_ipq },
2129	{ MAC_CREATE_MBUF_FROM_MBUF,
2130	    (macop_t)mac_mls_create_mbuf_from_mbuf },
2131	{ MAC_CREATE_MBUF_LINKLAYER,
2132	    (macop_t)mac_mls_create_mbuf_linklayer },
2133	{ MAC_CREATE_MBUF_FROM_BPFDESC,
2134	    (macop_t)mac_mls_create_mbuf_from_bpfdesc },
2135	{ MAC_CREATE_MBUF_FROM_IFNET,
2136	    (macop_t)mac_mls_create_mbuf_from_ifnet },
2137	{ MAC_CREATE_MBUF_MULTICAST_ENCAP,
2138	    (macop_t)mac_mls_create_mbuf_multicast_encap },
2139	{ MAC_CREATE_MBUF_NETLAYER,
2140	    (macop_t)mac_mls_create_mbuf_netlayer },
2141	{ MAC_FRAGMENT_MATCH,
2142	    (macop_t)mac_mls_fragment_match },
2143	{ MAC_RELABEL_IFNET,
2144	    (macop_t)mac_mls_relabel_ifnet },
2145	{ MAC_UPDATE_IPQ,
2146	    (macop_t)mac_mls_update_ipq },
2147	{ MAC_CREATE_CRED,
2148	    (macop_t)mac_mls_create_cred },
2149	{ MAC_EXECVE_TRANSITION,
2150	    (macop_t)mac_mls_execve_transition },
2151	{ MAC_EXECVE_WILL_TRANSITION,
2152	    (macop_t)mac_mls_execve_will_transition },
2153	{ MAC_CREATE_PROC0,
2154	    (macop_t)mac_mls_create_proc0 },
2155	{ MAC_CREATE_PROC1,
2156	    (macop_t)mac_mls_create_proc1 },
2157	{ MAC_RELABEL_CRED,
2158	    (macop_t)mac_mls_relabel_cred },
2159	{ MAC_CHECK_BPFDESC_RECEIVE,
2160	    (macop_t)mac_mls_check_bpfdesc_receive },
2161	{ MAC_CHECK_CRED_RELABEL,
2162	    (macop_t)mac_mls_check_cred_relabel },
2163	{ MAC_CHECK_CRED_VISIBLE,
2164	    (macop_t)mac_mls_check_cred_visible },
2165	{ MAC_CHECK_IFNET_RELABEL,
2166	    (macop_t)mac_mls_check_ifnet_relabel },
2167	{ MAC_CHECK_IFNET_TRANSMIT,
2168	    (macop_t)mac_mls_check_ifnet_transmit },
2169	{ MAC_CHECK_MOUNT_STAT,
2170	    (macop_t)mac_mls_check_mount_stat },
2171	{ MAC_CHECK_PIPE_IOCTL,
2172	    (macop_t)mac_mls_check_pipe_ioctl },
2173	{ MAC_CHECK_PIPE_POLL,
2174	    (macop_t)mac_mls_check_pipe_poll },
2175	{ MAC_CHECK_PIPE_READ,
2176	    (macop_t)mac_mls_check_pipe_read },
2177	{ MAC_CHECK_PIPE_RELABEL,
2178	    (macop_t)mac_mls_check_pipe_relabel },
2179	{ MAC_CHECK_PIPE_STAT,
2180	    (macop_t)mac_mls_check_pipe_stat },
2181	{ MAC_CHECK_PIPE_WRITE,
2182	    (macop_t)mac_mls_check_pipe_write },
2183	{ MAC_CHECK_PROC_DEBUG,
2184	    (macop_t)mac_mls_check_proc_debug },
2185	{ MAC_CHECK_PROC_SCHED,
2186	    (macop_t)mac_mls_check_proc_sched },
2187	{ MAC_CHECK_PROC_SIGNAL,
2188	    (macop_t)mac_mls_check_proc_signal },
2189	{ MAC_CHECK_SOCKET_DELIVER,
2190	    (macop_t)mac_mls_check_socket_deliver },
2191	{ MAC_CHECK_SOCKET_RELABEL,
2192	    (macop_t)mac_mls_check_socket_relabel },
2193	{ MAC_CHECK_SOCKET_VISIBLE,
2194	    (macop_t)mac_mls_check_socket_visible },
2195	{ MAC_CHECK_VNODE_ACCESS,
2196	    (macop_t)mac_mls_check_vnode_access },
2197	{ MAC_CHECK_VNODE_CHDIR,
2198	    (macop_t)mac_mls_check_vnode_chdir },
2199	{ MAC_CHECK_VNODE_CHROOT,
2200	    (macop_t)mac_mls_check_vnode_chroot },
2201	{ MAC_CHECK_VNODE_CREATE,
2202	    (macop_t)mac_mls_check_vnode_create },
2203	{ MAC_CHECK_VNODE_DELETE,
2204	    (macop_t)mac_mls_check_vnode_delete },
2205	{ MAC_CHECK_VNODE_DELETEACL,
2206	    (macop_t)mac_mls_check_vnode_deleteacl },
2207	{ MAC_CHECK_VNODE_EXEC,
2208	    (macop_t)mac_mls_check_vnode_exec },
2209	{ MAC_CHECK_VNODE_GETACL,
2210	    (macop_t)mac_mls_check_vnode_getacl },
2211	{ MAC_CHECK_VNODE_GETEXTATTR,
2212	    (macop_t)mac_mls_check_vnode_getextattr },
2213	{ MAC_CHECK_VNODE_LOOKUP,
2214	    (macop_t)mac_mls_check_vnode_lookup },
2215	{ MAC_CHECK_VNODE_OPEN,
2216	    (macop_t)mac_mls_check_vnode_open },
2217	{ MAC_CHECK_VNODE_POLL,
2218	    (macop_t)mac_mls_check_vnode_poll },
2219	{ MAC_CHECK_VNODE_READ,
2220	    (macop_t)mac_mls_check_vnode_read },
2221	{ MAC_CHECK_VNODE_READDIR,
2222	    (macop_t)mac_mls_check_vnode_readdir },
2223	{ MAC_CHECK_VNODE_READLINK,
2224	    (macop_t)mac_mls_check_vnode_readlink },
2225	{ MAC_CHECK_VNODE_RELABEL,
2226	    (macop_t)mac_mls_check_vnode_relabel },
2227	{ MAC_CHECK_VNODE_RENAME_FROM,
2228	    (macop_t)mac_mls_check_vnode_rename_from },
2229	{ MAC_CHECK_VNODE_RENAME_TO,
2230	    (macop_t)mac_mls_check_vnode_rename_to },
2231	{ MAC_CHECK_VNODE_REVOKE,
2232	    (macop_t)mac_mls_check_vnode_revoke },
2233	{ MAC_CHECK_VNODE_SETACL,
2234	    (macop_t)mac_mls_check_vnode_setacl },
2235	{ MAC_CHECK_VNODE_SETEXTATTR,
2236	    (macop_t)mac_mls_check_vnode_setextattr },
2237	{ MAC_CHECK_VNODE_SETFLAGS,
2238	    (macop_t)mac_mls_check_vnode_setflags },
2239	{ MAC_CHECK_VNODE_SETMODE,
2240	    (macop_t)mac_mls_check_vnode_setmode },
2241	{ MAC_CHECK_VNODE_SETOWNER,
2242	    (macop_t)mac_mls_check_vnode_setowner },
2243	{ MAC_CHECK_VNODE_SETUTIMES,
2244	    (macop_t)mac_mls_check_vnode_setutimes },
2245	{ MAC_CHECK_VNODE_STAT,
2246	    (macop_t)mac_mls_check_vnode_stat },
2247	{ MAC_CHECK_VNODE_WRITE,
2248	    (macop_t)mac_mls_check_vnode_write },
2249	{ MAC_CHECK_VNODE_MMAP_PERMS,
2250	    (macop_t)mac_mls_check_vnode_mmap_perms },
2251	{ MAC_OP_LAST, NULL }
2252};
2253
2254MAC_POLICY_SET(mac_mls_ops, trustedbsd_mac_mls, "TrustedBSD MAC/MLS",
2255    MPC_LOADTIME_FLAG_NOTLATE, &mac_mls_slot);
2256