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