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