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