mac_lomac.c revision 123607
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001, 2002, 2003 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 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $FreeBSD: head/sys/security/mac_lomac/mac_lomac.c 123607 2003-12-17 14:55:11Z rwatson $
35 */
36
37/*
38 * Developed by the TrustedBSD Project.
39 * Low-watermark floating label mandatory integrity policy.
40 */
41
42#include <sys/types.h>
43#include <sys/param.h>
44#include <sys/acl.h>
45#include <sys/conf.h>
46#include <sys/extattr.h>
47#include <sys/kernel.h>
48#include <sys/mac.h>
49#include <sys/malloc.h>
50#include <sys/mount.h>
51#include <sys/proc.h>
52#include <sys/sbuf.h>
53#include <sys/systm.h>
54#include <sys/sysproto.h>
55#include <sys/sysent.h>
56#include <sys/systm.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#include <sys/syslog.h>
64
65#include <fs/devfs/devfs.h>
66
67#include <net/bpfdesc.h>
68#include <net/if.h>
69#include <net/if_types.h>
70#include <net/if_var.h>
71
72#include <netinet/in.h>
73#include <netinet/in_pcb.h>
74#include <netinet/ip_var.h>
75
76#include <vm/vm.h>
77
78#include <sys/mac_policy.h>
79
80#include <security/mac_lomac/mac_lomac.h>
81
82struct mac_lomac_proc {
83	struct mac_lomac mac_lomac;
84	struct mtx mtx;
85};
86
87SYSCTL_DECL(_security_mac);
88
89SYSCTL_NODE(_security_mac, OID_AUTO, lomac, CTLFLAG_RW, 0,
90    "TrustedBSD mac_lomac policy controls");
91
92static int	mac_lomac_label_size = sizeof(struct mac_lomac);
93SYSCTL_INT(_security_mac_lomac, OID_AUTO, label_size, CTLFLAG_RD,
94    &mac_lomac_label_size, 0, "Size of struct mac_lomac");
95
96static int	mac_lomac_enabled = 1;
97SYSCTL_INT(_security_mac_lomac, OID_AUTO, enabled, CTLFLAG_RW,
98    &mac_lomac_enabled, 0, "Enforce MAC/LOMAC policy");
99TUNABLE_INT("security.mac.lomac.enabled", &mac_lomac_enabled);
100
101static int	destroyed_not_inited;
102SYSCTL_INT(_security_mac_lomac, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
103    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
104
105static int	trust_all_interfaces = 0;
106SYSCTL_INT(_security_mac_lomac, OID_AUTO, trust_all_interfaces, CTLFLAG_RD,
107    &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/LOMAC");
108TUNABLE_INT("security.mac.lomac.trust_all_interfaces", &trust_all_interfaces);
109
110static char	trusted_interfaces[128];
111SYSCTL_STRING(_security_mac_lomac, OID_AUTO, trusted_interfaces, CTLFLAG_RD,
112    trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/LOMAC");
113TUNABLE_STR("security.mac.lomac.trusted_interfaces", trusted_interfaces,
114    sizeof(trusted_interfaces));
115
116static int	ptys_equal = 0;
117SYSCTL_INT(_security_mac_lomac, OID_AUTO, ptys_equal, CTLFLAG_RW,
118    &ptys_equal, 0, "Label pty devices as lomac/equal on create");
119TUNABLE_INT("security.mac.lomac.ptys_equal", &ptys_equal);
120
121static int	revocation_enabled = 1;
122SYSCTL_INT(_security_mac_lomac, OID_AUTO, revocation_enabled, CTLFLAG_RW,
123    &revocation_enabled, 0, "Revoke access to objects on relabel");
124TUNABLE_INT("security.mac.lomac.revocation_enabled", &revocation_enabled);
125
126static int	mac_lomac_slot;
127#define	SLOT(l)	((struct mac_lomac *)LABEL_TO_SLOT((l), mac_lomac_slot).l_ptr)
128#define	PSLOT(l) ((struct mac_lomac_proc *)				\
129    LABEL_TO_SLOT((l), mac_lomac_slot).l_ptr)
130
131MALLOC_DEFINE(M_MACLOMAC, "lomac label", "MAC/LOMAC labels");
132
133static struct mac_lomac *
134lomac_alloc(int flag)
135{
136	struct mac_lomac *mac_lomac;
137
138	mac_lomac = malloc(sizeof(struct mac_lomac), M_MACLOMAC, M_ZERO | flag);
139
140	return (mac_lomac);
141}
142
143static void
144lomac_free(struct mac_lomac *mac_lomac)
145{
146
147	if (mac_lomac != NULL)
148		free(mac_lomac, M_MACLOMAC);
149	else
150		atomic_add_int(&destroyed_not_inited, 1);
151}
152
153static int
154lomac_atmostflags(struct mac_lomac *mac_lomac, int flags)
155{
156
157	if ((mac_lomac->ml_flags & flags) != mac_lomac->ml_flags)
158		return (EINVAL);
159	return (0);
160}
161
162static int
163mac_lomac_dominate_element(struct mac_lomac_element *a,
164    struct mac_lomac_element *b)
165{
166
167	switch (a->mle_type) {
168	case MAC_LOMAC_TYPE_EQUAL:
169	case MAC_LOMAC_TYPE_HIGH:
170		return (1);
171
172	case MAC_LOMAC_TYPE_LOW:
173		switch (b->mle_type) {
174		case MAC_LOMAC_TYPE_GRADE:
175		case MAC_LOMAC_TYPE_HIGH:
176			return (0);
177
178		case MAC_LOMAC_TYPE_EQUAL:
179		case MAC_LOMAC_TYPE_LOW:
180			return (1);
181
182		default:
183			panic("mac_lomac_dominate_element: b->mle_type invalid");
184		}
185
186	case MAC_LOMAC_TYPE_GRADE:
187		switch (b->mle_type) {
188		case MAC_LOMAC_TYPE_EQUAL:
189		case MAC_LOMAC_TYPE_LOW:
190			return (1);
191
192		case MAC_LOMAC_TYPE_HIGH:
193			return (0);
194
195		case MAC_LOMAC_TYPE_GRADE:
196			return (a->mle_grade >= b->mle_grade);
197
198		default:
199			panic("mac_lomac_dominate_element: b->mle_type invalid");
200		}
201
202	default:
203		panic("mac_lomac_dominate_element: a->mle_type invalid");
204	}
205}
206
207static int
208mac_lomac_range_in_range(struct mac_lomac *rangea, struct mac_lomac *rangeb)
209{
210
211	return (mac_lomac_dominate_element(&rangeb->ml_rangehigh,
212	    &rangea->ml_rangehigh) &&
213	    mac_lomac_dominate_element(&rangea->ml_rangelow,
214	    &rangeb->ml_rangelow));
215}
216
217static int
218mac_lomac_single_in_range(struct mac_lomac *single, struct mac_lomac *range)
219{
220
221	KASSERT((single->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
222	    ("mac_lomac_single_in_range: a not single"));
223	KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
224	    ("mac_lomac_single_in_range: b not range"));
225
226	return (mac_lomac_dominate_element(&range->ml_rangehigh,
227	    &single->ml_single) &&
228	    mac_lomac_dominate_element(&single->ml_single,
229	    &range->ml_rangelow));
230}
231
232static int
233mac_lomac_auxsingle_in_range(struct mac_lomac *single, struct mac_lomac *range)
234{
235
236	KASSERT((single->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
237	    ("mac_lomac_single_in_range: a not auxsingle"));
238	KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
239	    ("mac_lomac_single_in_range: b not range"));
240
241	return (mac_lomac_dominate_element(&range->ml_rangehigh,
242	    &single->ml_auxsingle) &&
243	    mac_lomac_dominate_element(&single->ml_auxsingle,
244	    &range->ml_rangelow));
245}
246
247static int
248mac_lomac_dominate_single(struct mac_lomac *a, struct mac_lomac *b)
249{
250	KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
251	    ("mac_lomac_dominate_single: a not single"));
252	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
253	    ("mac_lomac_dominate_single: b not single"));
254
255	return (mac_lomac_dominate_element(&a->ml_single, &b->ml_single));
256}
257
258static int
259mac_lomac_subject_dominate(struct mac_lomac *a, struct mac_lomac *b)
260{
261	KASSERT((~a->ml_flags &
262	    (MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_RANGE)) == 0,
263	    ("mac_lomac_dominate_single: a not subject"));
264	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
265	    ("mac_lomac_dominate_single: b not single"));
266
267	return (mac_lomac_dominate_element(&a->ml_rangehigh,
268	    &b->ml_single));
269}
270
271static int
272mac_lomac_equal_element(struct mac_lomac_element *a, struct mac_lomac_element *b)
273{
274
275	if (a->mle_type == MAC_LOMAC_TYPE_EQUAL ||
276	    b->mle_type == MAC_LOMAC_TYPE_EQUAL)
277		return (1);
278
279	return (a->mle_type == b->mle_type && a->mle_grade == b->mle_grade);
280}
281
282static int
283mac_lomac_equal_single(struct mac_lomac *a, struct mac_lomac *b)
284{
285
286	KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
287	    ("mac_lomac_equal_single: a not single"));
288	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
289	    ("mac_lomac_equal_single: b not single"));
290
291	return (mac_lomac_equal_element(&a->ml_single, &b->ml_single));
292}
293
294static int
295mac_lomac_contains_equal(struct mac_lomac *mac_lomac)
296{
297
298	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE)
299		if (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
300			return (1);
301	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX)
302		if (mac_lomac->ml_auxsingle.mle_type == MAC_LOMAC_TYPE_EQUAL)
303			return (1);
304
305	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
306		if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL)
307			return (1);
308		if (mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
309			return (1);
310	}
311
312	return (0);
313}
314
315static int
316mac_lomac_subject_privileged(struct mac_lomac *mac_lomac)
317{
318
319	KASSERT((mac_lomac->ml_flags & MAC_LOMAC_FLAGS_BOTH) ==
320	    MAC_LOMAC_FLAGS_BOTH,
321	    ("mac_lomac_subject_privileged: subject doesn't have both labels"));
322
323	/* If the single is EQUAL, it's ok. */
324	if (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
325		return (0);
326
327	/* If either range endpoint is EQUAL, it's ok. */
328	if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL ||
329	    mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
330		return (0);
331
332	/* If the range is low-high, it's ok. */
333	if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_LOW &&
334	    mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_HIGH)
335		return (0);
336
337	/* It's not ok. */
338	return (EPERM);
339}
340
341static int
342mac_lomac_high_single(struct mac_lomac *mac_lomac)
343{
344
345	KASSERT((mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
346	    ("mac_lomac_high_single: mac_lomac not single"));
347
348	return (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_HIGH);
349}
350
351static int
352mac_lomac_valid(struct mac_lomac *mac_lomac)
353{
354
355	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
356		switch (mac_lomac->ml_single.mle_type) {
357		case MAC_LOMAC_TYPE_GRADE:
358		case MAC_LOMAC_TYPE_EQUAL:
359		case MAC_LOMAC_TYPE_HIGH:
360		case MAC_LOMAC_TYPE_LOW:
361			break;
362
363		default:
364			return (EINVAL);
365		}
366	} else {
367		if (mac_lomac->ml_single.mle_type != MAC_LOMAC_TYPE_UNDEF)
368			return (EINVAL);
369	}
370
371	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX) {
372		switch (mac_lomac->ml_auxsingle.mle_type) {
373		case MAC_LOMAC_TYPE_GRADE:
374		case MAC_LOMAC_TYPE_EQUAL:
375		case MAC_LOMAC_TYPE_HIGH:
376		case MAC_LOMAC_TYPE_LOW:
377			break;
378
379		default:
380			return (EINVAL);
381		}
382	} else {
383		if (mac_lomac->ml_auxsingle.mle_type != MAC_LOMAC_TYPE_UNDEF)
384			return (EINVAL);
385	}
386
387	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
388		switch (mac_lomac->ml_rangelow.mle_type) {
389		case MAC_LOMAC_TYPE_GRADE:
390		case MAC_LOMAC_TYPE_EQUAL:
391		case MAC_LOMAC_TYPE_HIGH:
392		case MAC_LOMAC_TYPE_LOW:
393			break;
394
395		default:
396			return (EINVAL);
397		}
398
399		switch (mac_lomac->ml_rangehigh.mle_type) {
400		case MAC_LOMAC_TYPE_GRADE:
401		case MAC_LOMAC_TYPE_EQUAL:
402		case MAC_LOMAC_TYPE_HIGH:
403		case MAC_LOMAC_TYPE_LOW:
404			break;
405
406		default:
407			return (EINVAL);
408		}
409		if (!mac_lomac_dominate_element(&mac_lomac->ml_rangehigh,
410		    &mac_lomac->ml_rangelow))
411			return (EINVAL);
412	} else {
413		if (mac_lomac->ml_rangelow.mle_type != MAC_LOMAC_TYPE_UNDEF ||
414		    mac_lomac->ml_rangehigh.mle_type != MAC_LOMAC_TYPE_UNDEF)
415			return (EINVAL);
416	}
417
418	return (0);
419}
420
421static void
422mac_lomac_set_range(struct mac_lomac *mac_lomac, u_short typelow,
423    u_short gradelow, u_short typehigh, u_short gradehigh)
424{
425
426	mac_lomac->ml_rangelow.mle_type = typelow;
427	mac_lomac->ml_rangelow.mle_grade = gradelow;
428	mac_lomac->ml_rangehigh.mle_type = typehigh;
429	mac_lomac->ml_rangehigh.mle_grade = gradehigh;
430	mac_lomac->ml_flags |= MAC_LOMAC_FLAG_RANGE;
431}
432
433static void
434mac_lomac_set_single(struct mac_lomac *mac_lomac, u_short type, u_short grade)
435{
436
437	mac_lomac->ml_single.mle_type = type;
438	mac_lomac->ml_single.mle_grade = grade;
439	mac_lomac->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
440}
441
442static void
443mac_lomac_copy_range(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
444{
445
446	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
447	    ("mac_lomac_copy_range: labelfrom not range"));
448
449	labelto->ml_rangelow = labelfrom->ml_rangelow;
450	labelto->ml_rangehigh = labelfrom->ml_rangehigh;
451	labelto->ml_flags |= MAC_LOMAC_FLAG_RANGE;
452}
453
454static void
455mac_lomac_copy_single(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
456{
457
458	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
459	    ("mac_lomac_copy_single: labelfrom not single"));
460
461	labelto->ml_single = labelfrom->ml_single;
462	labelto->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
463}
464
465static void
466mac_lomac_copy_auxsingle(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
467{
468
469	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
470	    ("mac_lomac_copy_auxsingle: labelfrom not auxsingle"));
471
472	labelto->ml_auxsingle = labelfrom->ml_auxsingle;
473	labelto->ml_flags |= MAC_LOMAC_FLAG_AUX;
474}
475
476static void
477mac_lomac_copy(struct mac_lomac *source, struct mac_lomac *dest)
478{
479
480	if (source->ml_flags & MAC_LOMAC_FLAG_SINGLE)
481		mac_lomac_copy_single(source, dest);
482	if (source->ml_flags & MAC_LOMAC_FLAG_AUX)
483		mac_lomac_copy_auxsingle(source, dest);
484	if (source->ml_flags & MAC_LOMAC_FLAG_RANGE)
485		mac_lomac_copy_range(source, dest);
486}
487
488static int	mac_lomac_to_string(struct sbuf *sb,
489		    struct mac_lomac *mac_lomac);
490
491static int
492maybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel,
493    const char *actionname, const char *objname, struct vnode *vpq)
494{
495	struct sbuf subjlabel_sb, subjtext_sb, objlabel_sb;
496	char *subjlabeltext, *objlabeltext, *subjtext;
497	struct mac_lomac cached_subjlabel;
498	struct mac_lomac_proc *subj;
499	struct vattr va;
500	struct proc *p;
501	pid_t pgid;
502
503	subj = PSLOT(curthread->td_proc->p_label);
504
505	p = curthread->td_proc;
506	mtx_lock(&subj->mtx);
507        if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
508		/*
509		 * Check to see if the pending demotion would be more or
510		 * less severe than this one, and keep the more severe.
511		 * This can only happen for a multi-threaded application.
512		 */
513		if (mac_lomac_dominate_single(objlabel, &subj->mac_lomac)) {
514			mtx_unlock(&subj->mtx);
515			return (0);
516		}
517	}
518	bzero(&subj->mac_lomac, sizeof(subj->mac_lomac));
519	/*
520	 * Always demote the single label.
521	 */
522	mac_lomac_copy_single(objlabel, &subj->mac_lomac);
523	/*
524	 * Start with the original range, then minimize each side of
525	 * the range to the point of not dominating the object.  The
526	 * high side will always be demoted, of course.
527	 */
528	mac_lomac_copy_range(subjlabel, &subj->mac_lomac);
529	if (!mac_lomac_dominate_element(&objlabel->ml_single,
530	    &subj->mac_lomac.ml_rangelow))
531		subj->mac_lomac.ml_rangelow = objlabel->ml_single;
532	subj->mac_lomac.ml_rangehigh = objlabel->ml_single;
533	subj->mac_lomac.ml_flags |= MAC_LOMAC_FLAG_UPDATE;
534	mtx_lock_spin(&sched_lock);
535	curthread->td_flags |= TDF_ASTPENDING;
536	curthread->td_proc->p_sflag |= PS_MACPEND;
537	mtx_unlock_spin(&sched_lock);
538
539	/*
540	 * Avoid memory allocation while holding a mutex; cache the
541	 * label.
542	 */
543	mac_lomac_copy_single(&subj->mac_lomac, &cached_subjlabel);
544	mtx_unlock(&subj->mtx);
545
546	sbuf_new(&subjlabel_sb, NULL, 0, SBUF_AUTOEXTEND);
547	mac_lomac_to_string(&subjlabel_sb, subjlabel);
548	sbuf_finish(&subjlabel_sb);
549	subjlabeltext = sbuf_data(&subjlabel_sb);
550
551	sbuf_new(&subjtext_sb, NULL, 0, SBUF_AUTOEXTEND);
552	mac_lomac_to_string(&subjtext_sb, &subj->mac_lomac);
553	sbuf_finish(&subjtext_sb);
554	subjtext = sbuf_data(&subjtext_sb);
555
556	sbuf_new(&objlabel_sb, NULL, 0, SBUF_AUTOEXTEND);
557	mac_lomac_to_string(&objlabel_sb, objlabel);
558	sbuf_finish(&objlabel_sb);
559	objlabeltext = sbuf_data(&objlabel_sb);
560
561	pgid = p->p_pgrp->pg_id;		/* XXX could be stale? */
562	if (vpq != NULL && VOP_GETATTR(vpq, &va, curthread->td_ucred,
563	    curthread) == 0) {
564		log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
565		    " level %s after %s a level-%s %s (inode=%ld, "
566		    "mountpount=%s)\n",
567		    subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
568		    p->p_comm, subjtext, actionname, objlabeltext, objname,
569		    va.va_fileid, vpq->v_mount->mnt_stat.f_mntonname);
570	} else {
571		log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
572		    " level %s after %s a level-%s %s\n",
573		    subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
574		    p->p_comm, subjtext, actionname, objlabeltext, objname);
575	}
576
577	sbuf_delete(&subjlabel_sb);
578	sbuf_delete(&subjtext_sb);
579	sbuf_delete(&objlabel_sb);
580
581	return (0);
582}
583
584/*
585 * Relabel "to" to "from" only if "from" is a valid label (contains
586 * at least a single), as for a relabel operation which may or may
587 * not involve a relevant label.
588 */
589static void
590try_relabel(struct mac_lomac *from, struct mac_lomac *to)
591{
592
593	if (from->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
594		bzero(to, sizeof(*to));
595		mac_lomac_copy(from, to);
596	}
597}
598
599/*
600 * Policy module operations.
601 */
602static void
603mac_lomac_init(struct mac_policy_conf *conf)
604{
605
606}
607
608/*
609 * Label operations.
610 */
611static void
612mac_lomac_init_label(struct label *label)
613{
614
615	SLOT(label) = lomac_alloc(M_WAITOK);
616}
617
618static int
619mac_lomac_init_label_waitcheck(struct label *label, int flag)
620{
621
622	SLOT(label) = lomac_alloc(flag);
623	if (SLOT(label) == NULL)
624		return (ENOMEM);
625
626	return (0);
627}
628
629static void
630mac_lomac_init_proc_label(struct label *label)
631{
632
633	PSLOT(label) = malloc(sizeof(struct mac_lomac_proc), M_MACLOMAC,
634	    M_ZERO | M_WAITOK);
635	mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF);
636}
637
638static void
639mac_lomac_destroy_label(struct label *label)
640{
641
642	lomac_free(SLOT(label));
643	SLOT(label) = NULL;
644}
645
646static void
647mac_lomac_destroy_proc_label(struct label *label)
648{
649
650	mtx_destroy(&PSLOT(label)->mtx);
651	FREE(PSLOT(label), M_MACLOMAC);
652	PSLOT(label) = NULL;
653}
654
655static int
656mac_lomac_element_to_string(struct sbuf *sb, struct mac_lomac_element *element)
657{
658
659	switch (element->mle_type) {
660	case MAC_LOMAC_TYPE_HIGH:
661		return (sbuf_printf(sb, "high"));
662
663	case MAC_LOMAC_TYPE_LOW:
664		return (sbuf_printf(sb, "low"));
665
666	case MAC_LOMAC_TYPE_EQUAL:
667		return (sbuf_printf(sb, "equal"));
668
669	case MAC_LOMAC_TYPE_GRADE:
670		return (sbuf_printf(sb, "%d", element->mle_grade));
671
672	default:
673		panic("mac_lomac_element_to_string: invalid type (%d)",
674		    element->mle_type);
675	}
676}
677
678static int
679mac_lomac_to_string(struct sbuf *sb, struct mac_lomac *mac_lomac)
680{
681
682	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
683		if (mac_lomac_element_to_string(sb, &mac_lomac->ml_single)
684		    == -1)
685			return (EINVAL);
686	}
687
688	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX) {
689		if (sbuf_putc(sb, '[') == -1)
690			return (EINVAL);
691
692		if (mac_lomac_element_to_string(sb, &mac_lomac->ml_auxsingle)
693		    == -1)
694			return (EINVAL);
695
696		if (sbuf_putc(sb, ']') == -1)
697			return (EINVAL);
698	}
699
700	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
701		if (sbuf_putc(sb, '(') == -1)
702			return (EINVAL);
703
704		if (mac_lomac_element_to_string(sb, &mac_lomac->ml_rangelow)
705		    == -1)
706			return (EINVAL);
707
708		if (sbuf_putc(sb, '-') == -1)
709			return (EINVAL);
710
711		if (mac_lomac_element_to_string(sb, &mac_lomac->ml_rangehigh)
712		    == -1)
713			return (EINVAL);
714
715		if (sbuf_putc(sb, ')') == -1)
716			return (EINVAL);
717	}
718
719	return (0);
720}
721
722static int
723mac_lomac_externalize_label(struct label *label, char *element_name,
724    struct sbuf *sb, int *claimed)
725{
726	struct mac_lomac *mac_lomac;
727
728	if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
729		return (0);
730
731	(*claimed)++;
732
733	mac_lomac = SLOT(label);
734
735	return (mac_lomac_to_string(sb, mac_lomac));
736}
737
738static int
739mac_lomac_parse_element(struct mac_lomac_element *element, char *string)
740{
741
742	if (strcmp(string, "high") == 0 ||
743	    strcmp(string, "hi") == 0) {
744		element->mle_type = MAC_LOMAC_TYPE_HIGH;
745		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
746	} else if (strcmp(string, "low") == 0 ||
747	    strcmp(string, "lo") == 0) {
748		element->mle_type = MAC_LOMAC_TYPE_LOW;
749		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
750	} else if (strcmp(string, "equal") == 0 ||
751	    strcmp(string, "eq") == 0) {
752		element->mle_type = MAC_LOMAC_TYPE_EQUAL;
753		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
754	} else {
755		char *p0, *p1;
756		int d;
757
758		p0 = string;
759		d = strtol(p0, &p1, 10);
760
761		if (d < 0 || d > 65535)
762			return (EINVAL);
763		element->mle_type = MAC_LOMAC_TYPE_GRADE;
764		element->mle_grade = d;
765
766		if (p1 == p0 || *p1 != '\0')
767			return (EINVAL);
768	}
769
770	return (0);
771}
772
773/*
774 * Note: destructively consumes the string, make a local copy before
775 * calling if that's a problem.
776 */
777static int
778mac_lomac_parse(struct mac_lomac *mac_lomac, char *string)
779{
780	char *range, *rangeend, *rangehigh, *rangelow, *single, *auxsingle,
781	    *auxsingleend;
782	int error;
783
784	/* Do we have a range? */
785	single = string;
786	range = index(string, '(');
787	if (range == single)
788		single = NULL;
789	auxsingle = index(string, '[');
790	if (auxsingle == single)
791		single = NULL;
792	if (range != NULL && auxsingle != NULL)
793		return (EINVAL);
794	rangelow = rangehigh = NULL;
795	if (range != NULL) {
796		/* Nul terminate the end of the single string. */
797		*range = '\0';
798		range++;
799		rangelow = range;
800		rangehigh = index(rangelow, '-');
801		if (rangehigh == NULL)
802			return (EINVAL);
803		rangehigh++;
804		if (*rangelow == '\0' || *rangehigh == '\0')
805			return (EINVAL);
806		rangeend = index(rangehigh, ')');
807		if (rangeend == NULL)
808			return (EINVAL);
809		if (*(rangeend + 1) != '\0')
810			return (EINVAL);
811		/* Nul terminate the ends of the ranges. */
812		*(rangehigh - 1) = '\0';
813		*rangeend = '\0';
814	}
815	KASSERT((rangelow != NULL && rangehigh != NULL) ||
816	    (rangelow == NULL && rangehigh == NULL),
817	    ("mac_lomac_internalize_label: range mismatch"));
818	if (auxsingle != NULL) {
819		/* Nul terminate the end of the single string. */
820		*auxsingle = '\0';
821		auxsingle++;
822		auxsingleend = index(auxsingle, ']');
823		if (auxsingleend == NULL)
824			return (EINVAL);
825		if (*(auxsingleend + 1) != '\0')
826			return (EINVAL);
827		/* Nul terminate the end of the auxsingle. */
828		*auxsingleend = '\0';
829	}
830
831	bzero(mac_lomac, sizeof(*mac_lomac));
832	if (single != NULL) {
833		error = mac_lomac_parse_element(&mac_lomac->ml_single, single);
834		if (error)
835			return (error);
836		mac_lomac->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
837	}
838
839	if (auxsingle != NULL) {
840		error = mac_lomac_parse_element(&mac_lomac->ml_auxsingle,
841		    auxsingle);
842		if (error)
843			return (error);
844		mac_lomac->ml_flags |= MAC_LOMAC_FLAG_AUX;
845	}
846
847	if (rangelow != NULL) {
848		error = mac_lomac_parse_element(&mac_lomac->ml_rangelow,
849		    rangelow);
850		if (error)
851			return (error);
852		error = mac_lomac_parse_element(&mac_lomac->ml_rangehigh,
853		    rangehigh);
854		if (error)
855			return (error);
856		mac_lomac->ml_flags |= MAC_LOMAC_FLAG_RANGE;
857	}
858
859	error = mac_lomac_valid(mac_lomac);
860	if (error)
861		return (error);
862
863	return (0);
864}
865
866static int
867mac_lomac_internalize_label(struct label *label, char *element_name,
868    char *element_data, int *claimed)
869{
870	struct mac_lomac *mac_lomac, mac_lomac_temp;
871	int error;
872
873	if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
874		return (0);
875
876	(*claimed)++;
877
878	error = mac_lomac_parse(&mac_lomac_temp, element_data);
879	if (error)
880		return (error);
881
882	mac_lomac = SLOT(label);
883	*mac_lomac = mac_lomac_temp;
884
885	return (0);
886}
887
888static void
889mac_lomac_copy_label(struct label *src, struct label *dest)
890{
891
892	*SLOT(dest) = *SLOT(src);
893}
894
895/*
896 * Labeling event operations: file system objects, and things that look
897 * a lot like file system objects.
898 */
899static void
900mac_lomac_create_devfs_device(struct mount *mp, dev_t dev,
901    struct devfs_dirent *devfs_dirent, struct label *label)
902{
903	struct mac_lomac *mac_lomac;
904	int lomac_type;
905
906	mac_lomac = SLOT(label);
907	if (strcmp(dev->si_name, "null") == 0 ||
908	    strcmp(dev->si_name, "zero") == 0 ||
909	    strcmp(dev->si_name, "random") == 0 ||
910	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0 ||
911	    strncmp(dev->si_name, "ttyv", strlen("ttyv")) == 0)
912		lomac_type = MAC_LOMAC_TYPE_EQUAL;
913	else if (ptys_equal &&
914	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
915	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
916		lomac_type = MAC_LOMAC_TYPE_EQUAL;
917	else
918		lomac_type = MAC_LOMAC_TYPE_HIGH;
919	mac_lomac_set_single(mac_lomac, lomac_type, 0);
920}
921
922static void
923mac_lomac_create_devfs_directory(struct mount *mp, char *dirname,
924    int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
925{
926	struct mac_lomac *mac_lomac;
927
928	mac_lomac = SLOT(label);
929	mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
930}
931
932static void
933mac_lomac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
934    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
935    struct label *delabel)
936{
937	struct mac_lomac *source, *dest;
938
939	source = SLOT(cred->cr_label);
940	dest = SLOT(delabel);
941
942	mac_lomac_copy_single(source, dest);
943}
944
945static void
946mac_lomac_create_mount(struct ucred *cred, struct mount *mp,
947    struct label *mntlabel, struct label *fslabel)
948{
949	struct mac_lomac *source, *dest;
950
951	source = SLOT(cred->cr_label);
952	dest = SLOT(mntlabel);
953	mac_lomac_copy_single(source, dest);
954	dest = SLOT(fslabel);
955	mac_lomac_copy_single(source, dest);
956}
957
958static void
959mac_lomac_create_root_mount(struct ucred *cred, struct mount *mp,
960    struct label *mntlabel, struct label *fslabel)
961{
962	struct mac_lomac *mac_lomac;
963
964	/* Always mount root as high integrity. */
965	mac_lomac = SLOT(fslabel);
966	mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
967	mac_lomac = SLOT(mntlabel);
968	mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
969}
970
971static void
972mac_lomac_relabel_vnode(struct ucred *cred, struct vnode *vp,
973    struct label *vnodelabel, struct label *label)
974{
975	struct mac_lomac *source, *dest;
976
977	source = SLOT(label);
978	dest = SLOT(vnodelabel);
979
980	try_relabel(source, dest);
981}
982
983static void
984mac_lomac_update_devfsdirent(struct mount *mp,
985    struct devfs_dirent *devfs_dirent, struct label *direntlabel,
986    struct vnode *vp, struct label *vnodelabel)
987{
988	struct mac_lomac *source, *dest;
989
990	source = SLOT(vnodelabel);
991	dest = SLOT(direntlabel);
992
993	mac_lomac_copy(source, dest);
994}
995
996static void
997mac_lomac_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
998    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
999    struct label *vlabel)
1000{
1001	struct mac_lomac *source, *dest;
1002
1003	source = SLOT(delabel);
1004	dest = SLOT(vlabel);
1005
1006	mac_lomac_copy_single(source, dest);
1007}
1008
1009static int
1010mac_lomac_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
1011    struct vnode *vp, struct label *vlabel)
1012{
1013	struct mac_lomac temp, *source, *dest;
1014	int buflen, error;
1015
1016	source = SLOT(fslabel);
1017	dest = SLOT(vlabel);
1018
1019	buflen = sizeof(temp);
1020	bzero(&temp, buflen);
1021
1022	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1023	    MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&temp, curthread);
1024	if (error == ENOATTR || error == EOPNOTSUPP) {
1025		/* Fall back to the fslabel. */
1026		mac_lomac_copy_single(source, dest);
1027		return (0);
1028	} else if (error)
1029		return (error);
1030
1031	if (buflen != sizeof(temp)) {
1032		if (buflen != sizeof(temp) - sizeof(temp.ml_auxsingle)) {
1033			printf("mac_lomac_associate_vnode_extattr: bad size %d\n",
1034			    buflen);
1035			return (EPERM);
1036		}
1037		bzero(&temp.ml_auxsingle, sizeof(temp.ml_auxsingle));
1038		buflen = sizeof(temp);
1039		(void)vn_extattr_set(vp, IO_NODELOCKED,
1040		    MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME,
1041		    buflen, (char *)&temp, curthread);
1042	}
1043	if (mac_lomac_valid(&temp) != 0) {
1044		printf("mac_lomac_associate_vnode_extattr: invalid\n");
1045		return (EPERM);
1046	}
1047	if ((temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) != MAC_LOMAC_FLAG_SINGLE) {
1048		printf("mac_lomac_associate_vnode_extattr: not single\n");
1049		return (EPERM);
1050	}
1051
1052	mac_lomac_copy_single(&temp, dest);
1053	return (0);
1054}
1055
1056static void
1057mac_lomac_associate_vnode_singlelabel(struct mount *mp,
1058    struct label *fslabel, struct vnode *vp, struct label *vlabel)
1059{
1060	struct mac_lomac *source, *dest;
1061
1062	source = SLOT(fslabel);
1063	dest = SLOT(vlabel);
1064
1065	mac_lomac_copy_single(source, dest);
1066}
1067
1068static int
1069mac_lomac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1070    struct label *fslabel, struct vnode *dvp, struct label *dlabel,
1071    struct vnode *vp, struct label *vlabel, struct componentname *cnp)
1072{
1073	struct mac_lomac *source, *dest, *dir, temp;
1074	size_t buflen;
1075	int error;
1076
1077	buflen = sizeof(temp);
1078	bzero(&temp, buflen);
1079
1080	source = SLOT(cred->cr_label);
1081	dest = SLOT(vlabel);
1082	dir = SLOT(dlabel);
1083	if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) {
1084		mac_lomac_copy_auxsingle(dir, &temp);
1085		mac_lomac_set_single(&temp, dir->ml_auxsingle.mle_type,
1086		    dir->ml_auxsingle.mle_grade);
1087	} else {
1088		mac_lomac_copy_single(source, &temp);
1089	}
1090
1091	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1092	    MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
1093	if (error == 0)
1094		mac_lomac_copy(&temp, dest);
1095	return (error);
1096}
1097
1098static int
1099mac_lomac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1100    struct label *vlabel, struct label *intlabel)
1101{
1102	struct mac_lomac *source, temp;
1103	size_t buflen;
1104	int error;
1105
1106	buflen = sizeof(temp);
1107	bzero(&temp, buflen);
1108
1109	source = SLOT(intlabel);
1110	if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1111		return (0);
1112
1113	mac_lomac_copy_single(source, &temp);
1114	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1115	    MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
1116	return (error);
1117}
1118
1119/*
1120 * Labeling event operations: IPC object.
1121 */
1122static void
1123mac_lomac_create_inpcb_from_socket(struct socket *so, struct label *solabel,
1124    struct inpcb *inp, struct label *inplabel)
1125{
1126	struct mac_lomac *source, *dest;
1127
1128	source = SLOT(solabel);
1129	dest = SLOT(inplabel);
1130
1131	mac_lomac_copy_single(source, dest);
1132}
1133
1134static void
1135mac_lomac_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
1136    struct mbuf *m, struct label *mbuflabel)
1137{
1138	struct mac_lomac *source, *dest;
1139
1140	source = SLOT(socketlabel);
1141	dest = SLOT(mbuflabel);
1142
1143	mac_lomac_copy_single(source, dest);
1144}
1145
1146static void
1147mac_lomac_create_socket(struct ucred *cred, struct socket *socket,
1148    struct label *socketlabel)
1149{
1150	struct mac_lomac *source, *dest;
1151
1152	source = SLOT(cred->cr_label);
1153	dest = SLOT(socketlabel);
1154
1155	mac_lomac_copy_single(source, dest);
1156}
1157
1158static void
1159mac_lomac_create_pipe(struct ucred *cred, struct pipe *pipe,
1160    struct label *pipelabel)
1161{
1162	struct mac_lomac *source, *dest;
1163
1164	source = SLOT(cred->cr_label);
1165	dest = SLOT(pipelabel);
1166
1167	mac_lomac_copy_single(source, dest);
1168}
1169
1170static void
1171mac_lomac_create_socket_from_socket(struct socket *oldsocket,
1172    struct label *oldsocketlabel, struct socket *newsocket,
1173    struct label *newsocketlabel)
1174{
1175	struct mac_lomac *source, *dest;
1176
1177	source = SLOT(oldsocketlabel);
1178	dest = SLOT(newsocketlabel);
1179
1180	mac_lomac_copy_single(source, dest);
1181}
1182
1183static void
1184mac_lomac_relabel_socket(struct ucred *cred, struct socket *socket,
1185    struct label *socketlabel, struct label *newlabel)
1186{
1187	struct mac_lomac *source, *dest;
1188
1189	source = SLOT(newlabel);
1190	dest = SLOT(socketlabel);
1191
1192	try_relabel(source, dest);
1193}
1194
1195static void
1196mac_lomac_relabel_pipe(struct ucred *cred, struct pipe *pipe,
1197    struct label *pipelabel, struct label *newlabel)
1198{
1199	struct mac_lomac *source, *dest;
1200
1201	source = SLOT(newlabel);
1202	dest = SLOT(pipelabel);
1203
1204	try_relabel(source, dest);
1205}
1206
1207static void
1208mac_lomac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1209    struct socket *socket, struct label *socketpeerlabel)
1210{
1211	struct mac_lomac *source, *dest;
1212
1213	source = SLOT(mbuflabel);
1214	dest = SLOT(socketpeerlabel);
1215
1216	mac_lomac_copy_single(source, dest);
1217}
1218
1219/*
1220 * Labeling event operations: network objects.
1221 */
1222static void
1223mac_lomac_set_socket_peer_from_socket(struct socket *oldsocket,
1224    struct label *oldsocketlabel, struct socket *newsocket,
1225    struct label *newsocketpeerlabel)
1226{
1227	struct mac_lomac *source, *dest;
1228
1229	source = SLOT(oldsocketlabel);
1230	dest = SLOT(newsocketpeerlabel);
1231
1232	mac_lomac_copy_single(source, dest);
1233}
1234
1235static void
1236mac_lomac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1237    struct label *bpflabel)
1238{
1239	struct mac_lomac *source, *dest;
1240
1241	source = SLOT(cred->cr_label);
1242	dest = SLOT(bpflabel);
1243
1244	mac_lomac_copy_single(source, dest);
1245}
1246
1247static void
1248mac_lomac_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1249{
1250	char tifname[IFNAMSIZ], *p, *q;
1251	char tiflist[sizeof(trusted_interfaces)];
1252	struct mac_lomac *dest;
1253	int len, grade;
1254
1255	dest = SLOT(ifnetlabel);
1256
1257	if (ifnet->if_type == IFT_LOOP) {
1258		grade = MAC_LOMAC_TYPE_EQUAL;
1259		goto set;
1260	}
1261
1262	if (trust_all_interfaces) {
1263		grade = MAC_LOMAC_TYPE_HIGH;
1264		goto set;
1265	}
1266
1267	grade = MAC_LOMAC_TYPE_LOW;
1268
1269	if (trusted_interfaces[0] == '\0' ||
1270	    !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1271		goto set;
1272
1273	bzero(tiflist, sizeof(tiflist));
1274	for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1275		if(*p != ' ' && *p != '\t')
1276			*q = *p;
1277
1278	for (p = q = tiflist;; p++) {
1279		if (*p == ',' || *p == '\0') {
1280			len = p - q;
1281			if (len < IFNAMSIZ) {
1282				bzero(tifname, sizeof(tifname));
1283				bcopy(q, tifname, len);
1284				if (strcmp(tifname, ifnet->if_xname) == 0) {
1285					grade = MAC_LOMAC_TYPE_HIGH;
1286					break;
1287				}
1288			}
1289			else {
1290				*p = '\0';
1291				printf("MAC/LOMAC warning: interface name "
1292				    "\"%s\" is too long (must be < %d)\n",
1293				    q, IFNAMSIZ);
1294			}
1295			if (*p == '\0')
1296				break;
1297			q = p + 1;
1298		}
1299	}
1300set:
1301	mac_lomac_set_single(dest, grade, 0);
1302	mac_lomac_set_range(dest, grade, 0, grade, 0);
1303}
1304
1305static void
1306mac_lomac_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1307    struct ipq *ipq, struct label *ipqlabel)
1308{
1309	struct mac_lomac *source, *dest;
1310
1311	source = SLOT(fragmentlabel);
1312	dest = SLOT(ipqlabel);
1313
1314	mac_lomac_copy_single(source, dest);
1315}
1316
1317static void
1318mac_lomac_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1319    struct mbuf *datagram, struct label *datagramlabel)
1320{
1321	struct mac_lomac *source, *dest;
1322
1323	source = SLOT(ipqlabel);
1324	dest = SLOT(datagramlabel);
1325
1326	/* Just use the head, since we require them all to match. */
1327	mac_lomac_copy_single(source, dest);
1328}
1329
1330static void
1331mac_lomac_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1332    struct mbuf *fragment, struct label *fragmentlabel)
1333{
1334	struct mac_lomac *source, *dest;
1335
1336	source = SLOT(datagramlabel);
1337	dest = SLOT(fragmentlabel);
1338
1339	mac_lomac_copy_single(source, dest);
1340}
1341
1342static void
1343mac_lomac_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel,
1344    struct mbuf *m, struct label *mlabel)
1345{
1346	struct mac_lomac *source, *dest;
1347
1348	source = SLOT(inplabel);
1349	dest = SLOT(mlabel);
1350
1351	mac_lomac_copy_single(source, dest);
1352}
1353
1354static void
1355mac_lomac_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
1356    struct label *oldmbuflabel, struct mbuf *newmbuf,
1357    struct label *newmbuflabel)
1358{
1359	struct mac_lomac *source, *dest;
1360
1361	source = SLOT(oldmbuflabel);
1362	dest = SLOT(newmbuflabel);
1363
1364	/*
1365	 * Because the source mbuf may not yet have been "created",
1366	 * just initialized, we do a conditional copy.  Since we don't
1367	 * allow mbufs to have ranges, do a KASSERT to make sure that
1368	 * doesn't happen.
1369	 */
1370	KASSERT((source->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0,
1371	    ("mac_lomac_create_mbuf_from_mbuf: source mbuf has range"));
1372	mac_lomac_copy(source, dest);
1373}
1374
1375static void
1376mac_lomac_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1377    struct mbuf *mbuf, struct label *mbuflabel)
1378{
1379	struct mac_lomac *dest;
1380
1381	dest = SLOT(mbuflabel);
1382
1383	mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1384}
1385
1386static void
1387mac_lomac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1388    struct mbuf *mbuf, struct label *mbuflabel)
1389{
1390	struct mac_lomac *source, *dest;
1391
1392	source = SLOT(bpflabel);
1393	dest = SLOT(mbuflabel);
1394
1395	mac_lomac_copy_single(source, dest);
1396}
1397
1398static void
1399mac_lomac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1400    struct mbuf *m, struct label *mbuflabel)
1401{
1402	struct mac_lomac *source, *dest;
1403
1404	source = SLOT(ifnetlabel);
1405	dest = SLOT(mbuflabel);
1406
1407	mac_lomac_copy_single(source, dest);
1408}
1409
1410static void
1411mac_lomac_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1412    struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1413    struct mbuf *newmbuf, struct label *newmbuflabel)
1414{
1415	struct mac_lomac *source, *dest;
1416
1417	source = SLOT(oldmbuflabel);
1418	dest = SLOT(newmbuflabel);
1419
1420	mac_lomac_copy_single(source, dest);
1421}
1422
1423static void
1424mac_lomac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1425    struct mbuf *newmbuf, struct label *newmbuflabel)
1426{
1427	struct mac_lomac *source, *dest;
1428
1429	source = SLOT(oldmbuflabel);
1430	dest = SLOT(newmbuflabel);
1431
1432	mac_lomac_copy_single(source, dest);
1433}
1434
1435static int
1436mac_lomac_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1437    struct ipq *ipq, struct label *ipqlabel)
1438{
1439	struct mac_lomac *a, *b;
1440
1441	a = SLOT(ipqlabel);
1442	b = SLOT(fragmentlabel);
1443
1444	return (mac_lomac_equal_single(a, b));
1445}
1446
1447static void
1448mac_lomac_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1449    struct label *ifnetlabel, struct label *newlabel)
1450{
1451	struct mac_lomac *source, *dest;
1452
1453	source = SLOT(newlabel);
1454	dest = SLOT(ifnetlabel);
1455
1456	try_relabel(source, dest);
1457}
1458
1459static void
1460mac_lomac_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1461    struct ipq *ipq, struct label *ipqlabel)
1462{
1463
1464	/* NOOP: we only accept matching labels, so no need to update */
1465}
1466
1467static void
1468mac_lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1469    struct inpcb *inp, struct label *inplabel)
1470{
1471	struct mac_lomac *source, *dest;
1472
1473	source = SLOT(solabel);
1474	dest = SLOT(inplabel);
1475
1476	mac_lomac_copy_single(source, dest);
1477}
1478
1479/*
1480 * Labeling event operations: processes.
1481 */
1482static void
1483mac_lomac_execve_transition(struct ucred *old, struct ucred *new,
1484    struct vnode *vp, struct label *vnodelabel,
1485    struct label *interpvnodelabel, struct image_params *imgp,
1486    struct label *execlabel)
1487{
1488	struct mac_lomac *source, *dest, *obj, *robj;
1489
1490	source = SLOT(old->cr_label);
1491	dest = SLOT(new->cr_label);
1492	obj = SLOT(vnodelabel);
1493	robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1494
1495	mac_lomac_copy(source, dest);
1496	/*
1497	 * If there's an auxiliary label on the real object, respect it
1498	 * and assume that this level should be assumed immediately if
1499	 * a higher level is currently in place.
1500	 */
1501	if (robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1502	    !mac_lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single)
1503	    && mac_lomac_auxsingle_in_range(robj, dest))
1504		mac_lomac_set_single(dest, robj->ml_auxsingle.mle_type,
1505		    robj->ml_auxsingle.mle_grade);
1506	/*
1507	 * Restructuring to use the execve transitioning mechanism
1508	 * instead of the normal demotion mechanism here would be
1509	 * difficult, so just copy the label over and perform standard
1510	 * demotion.  This is also non-optimal because it will result
1511	 * in the intermediate label "new" being created and immediately
1512	 * recycled.
1513	 */
1514	if (mac_lomac_enabled && revocation_enabled &&
1515	    !mac_lomac_dominate_single(obj, source))
1516		(void)maybe_demote(source, obj, "executing", "file", vp);
1517}
1518
1519static int
1520mac_lomac_execve_will_transition(struct ucred *old, struct vnode *vp,
1521    struct label *vnodelabel, struct label *interpvnodelabel,
1522    struct image_params *imgp, struct label *execlabel)
1523{
1524	struct mac_lomac *subj, *obj, *robj;
1525
1526	if (!mac_lomac_enabled || !revocation_enabled)
1527		return (0);
1528
1529	subj = SLOT(old->cr_label);
1530	obj = SLOT(vnodelabel);
1531	robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1532
1533	return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1534	    !mac_lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single)
1535	    && mac_lomac_auxsingle_in_range(robj, subj)) ||
1536	    !mac_lomac_dominate_single(obj, subj));
1537}
1538
1539static void
1540mac_lomac_create_proc0(struct ucred *cred)
1541{
1542	struct mac_lomac *dest;
1543
1544	dest = SLOT(cred->cr_label);
1545
1546	mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1547	mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1548	    0);
1549}
1550
1551static void
1552mac_lomac_create_proc1(struct ucred *cred)
1553{
1554	struct mac_lomac *dest;
1555
1556	dest = SLOT(cred->cr_label);
1557
1558	mac_lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0);
1559	mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1560	    0);
1561}
1562
1563static void
1564mac_lomac_relabel_cred(struct ucred *cred, struct label *newlabel)
1565{
1566	struct mac_lomac *source, *dest;
1567
1568	source = SLOT(newlabel);
1569	dest = SLOT(cred->cr_label);
1570
1571	try_relabel(source, dest);
1572}
1573
1574/*
1575 * Access control checks.
1576 */
1577static int
1578mac_lomac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1579    struct ifnet *ifnet, struct label *ifnetlabel)
1580{
1581	struct mac_lomac *a, *b;
1582
1583	if (!mac_lomac_enabled)
1584		return (0);
1585
1586	a = SLOT(bpflabel);
1587	b = SLOT(ifnetlabel);
1588
1589	if (mac_lomac_equal_single(a, b))
1590		return (0);
1591	return (EACCES);
1592}
1593
1594static int
1595mac_lomac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1596{
1597	struct mac_lomac *subj, *new;
1598	int error;
1599
1600	subj = SLOT(cred->cr_label);
1601	new = SLOT(newlabel);
1602
1603	/*
1604	 * If there is a LOMAC label update for the credential, it may
1605	 * be an update of the single, range, or both.
1606	 */
1607	error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1608	if (error)
1609		return (error);
1610
1611	/*
1612	 * If the LOMAC label is to be changed, authorize as appropriate.
1613	 */
1614	if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1615		/*
1616		 * Fill in the missing parts from the previous label.
1617		 */
1618		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1619			mac_lomac_copy_single(subj, new);
1620		if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1621			mac_lomac_copy_range(subj, new);
1622
1623		/*
1624		 * To change the LOMAC range on a credential, the new
1625		 * range label must be in the current range.
1626		 */
1627		if (!mac_lomac_range_in_range(new, subj))
1628			return (EPERM);
1629
1630		/*
1631		 * To change the LOMAC single label on a credential, the
1632		 * new single label must be in the new range.  Implicitly
1633		 * from the previous check, the new single is in the old
1634		 * range.
1635		 */
1636		if (!mac_lomac_single_in_range(new, new))
1637			return (EPERM);
1638
1639		/*
1640		 * To have EQUAL in any component of the new credential
1641		 * LOMAC label, the subject must already have EQUAL in
1642		 * their label.
1643		 */
1644		if (mac_lomac_contains_equal(new)) {
1645			error = mac_lomac_subject_privileged(subj);
1646			if (error)
1647				return (error);
1648		}
1649
1650		/*
1651		 * XXXMAC: Additional consistency tests regarding the
1652		 * single and range of the new label might be performed
1653		 * here.
1654		 */
1655	}
1656
1657	return (0);
1658}
1659
1660static int
1661mac_lomac_check_cred_visible(struct ucred *u1, struct ucred *u2)
1662{
1663	struct mac_lomac *subj, *obj;
1664
1665	if (!mac_lomac_enabled)
1666		return (0);
1667
1668	subj = SLOT(u1->cr_label);
1669	obj = SLOT(u2->cr_label);
1670
1671	/* XXX: range */
1672	if (!mac_lomac_dominate_single(obj, subj))
1673		return (ESRCH);
1674
1675	return (0);
1676}
1677
1678static int
1679mac_lomac_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1680    struct label *ifnetlabel, struct label *newlabel)
1681{
1682	struct mac_lomac *subj, *new;
1683	int error;
1684
1685	subj = SLOT(cred->cr_label);
1686	new = SLOT(newlabel);
1687
1688	/*
1689	 * If there is a LOMAC label update for the interface, it may
1690	 * be an update of the single, range, or both.
1691	 */
1692	error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1693	if (error)
1694		return (error);
1695
1696	/*
1697	 * Relabling network interfaces requires LOMAC privilege.
1698	 */
1699	error = mac_lomac_subject_privileged(subj);
1700	if (error)
1701		return (error);
1702
1703	/*
1704	 * If the LOMAC label is to be changed, authorize as appropriate.
1705	 */
1706	if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1707		/*
1708		 * Fill in the missing parts from the previous label.
1709		 */
1710		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1711			mac_lomac_copy_single(subj, new);
1712		if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1713			mac_lomac_copy_range(subj, new);
1714
1715		/*
1716		 * Rely on the traditional superuser status for the LOMAC
1717		 * interface relabel requirements.  XXXMAC: This will go
1718		 * away.
1719		 */
1720		error = suser_cred(cred, 0);
1721		if (error)
1722			return (EPERM);
1723
1724		/*
1725		 * XXXMAC: Additional consistency tests regarding the single
1726		 * and the range of the new label might be performed here.
1727		 */
1728	}
1729
1730	return (0);
1731}
1732
1733static int
1734mac_lomac_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1735    struct mbuf *m, struct label *mbuflabel)
1736{
1737	struct mac_lomac *p, *i;
1738
1739	if (!mac_lomac_enabled)
1740		return (0);
1741
1742	p = SLOT(mbuflabel);
1743	i = SLOT(ifnetlabel);
1744
1745	return (mac_lomac_single_in_range(p, i) ? 0 : EACCES);
1746}
1747
1748static int
1749mac_lomac_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1750    struct mbuf *m, struct label *mlabel)
1751{
1752	struct mac_lomac *p, *i;
1753
1754	if (!mac_lomac_enabled)
1755		return (0);
1756
1757	p = SLOT(mlabel);
1758	i = SLOT(inplabel);
1759
1760	return (mac_lomac_equal_single(p, i) ? 0 : EACCES);
1761}
1762
1763static int
1764mac_lomac_check_kld_load(struct ucred *cred, struct vnode *vp,
1765    struct label *label)
1766{
1767	struct mac_lomac *subj, *obj;
1768
1769	if (!mac_lomac_enabled)
1770		return (0);
1771
1772	subj = SLOT(cred->cr_label);
1773	obj = SLOT(label);
1774
1775	if (mac_lomac_subject_privileged(subj))
1776		return (EPERM);
1777
1778	if (!mac_lomac_high_single(obj))
1779		return (EACCES);
1780
1781	return (0);
1782}
1783
1784static int
1785mac_lomac_check_kld_unload(struct ucred *cred)
1786{
1787	struct mac_lomac *subj;
1788
1789	if (!mac_lomac_enabled)
1790		return (0);
1791
1792	subj = SLOT(cred->cr_label);
1793
1794	if (mac_lomac_subject_privileged(subj))
1795		return (EPERM);
1796
1797	return (0);
1798}
1799
1800static int
1801mac_lomac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1802    struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1803{
1804
1805	if(!mac_lomac_enabled)
1806		return (0);
1807
1808	/* XXX: This will be implemented soon... */
1809
1810	return (0);
1811}
1812
1813static int
1814mac_lomac_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1815    struct label *pipelabel)
1816{
1817	struct mac_lomac *subj, *obj;
1818
1819	if (!mac_lomac_enabled)
1820		return (0);
1821
1822	subj = SLOT(cred->cr_label);
1823	obj = SLOT((pipelabel));
1824
1825	if (!mac_lomac_dominate_single(obj, subj))
1826		return (maybe_demote(subj, obj, "reading", "pipe", NULL));
1827
1828	return (0);
1829}
1830
1831static int
1832mac_lomac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1833    struct label *pipelabel, struct label *newlabel)
1834{
1835	struct mac_lomac *subj, *obj, *new;
1836	int error;
1837
1838	new = SLOT(newlabel);
1839	subj = SLOT(cred->cr_label);
1840	obj = SLOT(pipelabel);
1841
1842	/*
1843	 * If there is a LOMAC label update for a pipe, it must be a
1844	 * single update.
1845	 */
1846	error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1847	if (error)
1848		return (error);
1849
1850	/*
1851	 * To perform a relabel of a pipe (LOMAC label or not), LOMAC must
1852	 * authorize the relabel.
1853	 */
1854	if (!mac_lomac_single_in_range(obj, subj))
1855		return (EPERM);
1856
1857	/*
1858	 * If the LOMAC label is to be changed, authorize as appropriate.
1859	 */
1860	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1861		/*
1862		 * To change the LOMAC label on a pipe, the new pipe label
1863		 * must be in the subject range.
1864		 */
1865		if (!mac_lomac_single_in_range(new, subj))
1866			return (EPERM);
1867
1868		/*
1869		 * To change the LOMAC label on a pipe to be EQUAL, the
1870		 * subject must have appropriate privilege.
1871		 */
1872		if (mac_lomac_contains_equal(new)) {
1873			error = mac_lomac_subject_privileged(subj);
1874			if (error)
1875				return (error);
1876		}
1877	}
1878
1879	return (0);
1880}
1881
1882static int
1883mac_lomac_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1884    struct label *pipelabel)
1885{
1886	struct mac_lomac *subj, *obj;
1887
1888	if (!mac_lomac_enabled)
1889		return (0);
1890
1891	subj = SLOT(cred->cr_label);
1892	obj = SLOT((pipelabel));
1893
1894	if (!mac_lomac_subject_dominate(subj, obj))
1895		return (EACCES);
1896
1897	return (0);
1898}
1899
1900static int
1901mac_lomac_check_proc_debug(struct ucred *cred, struct proc *proc)
1902{
1903	struct mac_lomac *subj, *obj;
1904
1905	if (!mac_lomac_enabled)
1906		return (0);
1907
1908	subj = SLOT(cred->cr_label);
1909	obj = SLOT(proc->p_ucred->cr_label);
1910
1911	/* XXX: range checks */
1912	if (!mac_lomac_dominate_single(obj, subj))
1913		return (ESRCH);
1914	if (!mac_lomac_subject_dominate(subj, obj))
1915		return (EACCES);
1916
1917	return (0);
1918}
1919
1920static int
1921mac_lomac_check_proc_sched(struct ucred *cred, struct proc *proc)
1922{
1923	struct mac_lomac *subj, *obj;
1924
1925	if (!mac_lomac_enabled)
1926		return (0);
1927
1928	subj = SLOT(cred->cr_label);
1929	obj = SLOT(proc->p_ucred->cr_label);
1930
1931	/* XXX: range checks */
1932	if (!mac_lomac_dominate_single(obj, subj))
1933		return (ESRCH);
1934	if (!mac_lomac_subject_dominate(subj, obj))
1935		return (EACCES);
1936
1937	return (0);
1938}
1939
1940static int
1941mac_lomac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1942{
1943	struct mac_lomac *subj, *obj;
1944
1945	if (!mac_lomac_enabled)
1946		return (0);
1947
1948	subj = SLOT(cred->cr_label);
1949	obj = SLOT(proc->p_ucred->cr_label);
1950
1951	/* XXX: range checks */
1952	if (!mac_lomac_dominate_single(obj, subj))
1953		return (ESRCH);
1954	if (!mac_lomac_subject_dominate(subj, obj))
1955		return (EACCES);
1956
1957	return (0);
1958}
1959
1960static int
1961mac_lomac_check_socket_deliver(struct socket *so, struct label *socketlabel,
1962    struct mbuf *m, struct label *mbuflabel)
1963{
1964	struct mac_lomac *p, *s;
1965
1966	if (!mac_lomac_enabled)
1967		return (0);
1968
1969	p = SLOT(mbuflabel);
1970	s = SLOT(socketlabel);
1971
1972	return (mac_lomac_equal_single(p, s) ? 0 : EACCES);
1973}
1974
1975static int
1976mac_lomac_check_socket_relabel(struct ucred *cred, struct socket *socket,
1977    struct label *socketlabel, struct label *newlabel)
1978{
1979	struct mac_lomac *subj, *obj, *new;
1980	int error;
1981
1982	new = SLOT(newlabel);
1983	subj = SLOT(cred->cr_label);
1984	obj = SLOT(socketlabel);
1985
1986	/*
1987	 * If there is a LOMAC label update for the socket, it may be
1988	 * an update of single.
1989	 */
1990	error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1991	if (error)
1992		return (error);
1993
1994	/*
1995	 * To relabel a socket, the old socket single must be in the subject
1996	 * range.
1997	 */
1998	if (!mac_lomac_single_in_range(obj, subj))
1999		return (EPERM);
2000
2001	/*
2002	 * If the LOMAC label is to be changed, authorize as appropriate.
2003	 */
2004	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2005		/*
2006		 * To relabel a socket, the new socket single must be in
2007		 * the subject range.
2008		 */
2009		if (!mac_lomac_single_in_range(new, subj))
2010			return (EPERM);
2011
2012		/*
2013		 * To change the LOMAC label on the socket to contain EQUAL,
2014		 * the subject must have appropriate privilege.
2015		 */
2016		if (mac_lomac_contains_equal(new)) {
2017			error = mac_lomac_subject_privileged(subj);
2018			if (error)
2019				return (error);
2020		}
2021	}
2022
2023	return (0);
2024}
2025
2026static int
2027mac_lomac_check_socket_visible(struct ucred *cred, struct socket *socket,
2028    struct label *socketlabel)
2029{
2030	struct mac_lomac *subj, *obj;
2031
2032	if (!mac_lomac_enabled)
2033		return (0);
2034
2035	subj = SLOT(cred->cr_label);
2036	obj = SLOT(socketlabel);
2037
2038	if (!mac_lomac_dominate_single(obj, subj))
2039		return (ENOENT);
2040
2041	return (0);
2042}
2043
2044static int
2045mac_lomac_check_system_swapon(struct ucred *cred, struct vnode *vp,
2046    struct label *label)
2047{
2048	struct mac_lomac *subj, *obj;
2049
2050	if (!mac_lomac_enabled)
2051		return (0);
2052
2053	subj = SLOT(cred->cr_label);
2054	obj = SLOT(label);
2055
2056	if (mac_lomac_subject_privileged(subj))
2057		return (EPERM);
2058
2059	if (!mac_lomac_high_single(obj))
2060		return (EACCES);
2061
2062	return (0);
2063}
2064
2065static int
2066mac_lomac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2067    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2068{
2069	struct mac_lomac *subj;
2070
2071	if (!mac_lomac_enabled)
2072		return (0);
2073
2074	subj = SLOT(cred->cr_label);
2075
2076	/*
2077	 * In general, treat sysctl variables as lomac/high, but also
2078	 * require privilege to change them, since they are a
2079	 * communications channel between grades.  Exempt MIB
2080	 * queries from this due to undocmented sysctl magic.
2081	 * XXXMAC: This probably requires some more review.
2082	 */
2083	if (new != NULL) {
2084		if (namelen > 0 && name[0] == 0)
2085			return (0);
2086
2087#ifdef notdef
2088		if (!mac_lomac_subject_dominate_high(subj))
2089			return (EACCES);
2090#endif
2091
2092		if (mac_lomac_subject_privileged(subj))
2093			return (EPERM);
2094	}
2095
2096	return (0);
2097}
2098
2099static int
2100mac_lomac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2101    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2102{
2103	struct mac_lomac *subj, *obj;
2104
2105	if (!mac_lomac_enabled)
2106		return (0);
2107
2108	subj = SLOT(cred->cr_label);
2109	obj = SLOT(dlabel);
2110
2111	if (!mac_lomac_subject_dominate(subj, obj))
2112		return (EACCES);
2113	if (obj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2114	    !mac_lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle))
2115		return (EACCES);
2116
2117	return (0);
2118}
2119
2120static int
2121mac_lomac_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2122    struct label *dlabel, struct vnode *vp, struct label *label,
2123    struct componentname *cnp)
2124{
2125	struct mac_lomac *subj, *obj;
2126
2127	if (!mac_lomac_enabled)
2128		return (0);
2129
2130	subj = SLOT(cred->cr_label);
2131	obj = SLOT(dlabel);
2132
2133	if (!mac_lomac_subject_dominate(subj, obj))
2134		return (EACCES);
2135
2136	obj = SLOT(label);
2137
2138	if (!mac_lomac_subject_dominate(subj, obj))
2139		return (EACCES);
2140
2141	return (0);
2142}
2143
2144static int
2145mac_lomac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2146    struct label *label, acl_type_t type)
2147{
2148	struct mac_lomac *subj, *obj;
2149
2150	if (!mac_lomac_enabled)
2151		return (0);
2152
2153	subj = SLOT(cred->cr_label);
2154	obj = SLOT(label);
2155
2156	if (!mac_lomac_subject_dominate(subj, obj))
2157		return (EACCES);
2158
2159	return (0);
2160}
2161
2162static int
2163mac_lomac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2164    struct label *dlabel, struct vnode *vp, struct label *label,
2165    struct componentname *cnp)
2166{
2167	struct mac_lomac *subj, *obj;
2168
2169	if (!mac_lomac_enabled)
2170		return (0);
2171
2172	subj = SLOT(cred->cr_label);
2173	obj = SLOT(dlabel);
2174
2175	if (!mac_lomac_subject_dominate(subj, obj))
2176		return (EACCES);
2177
2178	obj = SLOT(label);
2179
2180	if (!mac_lomac_subject_dominate(subj, obj))
2181		return (EACCES);
2182
2183	return (0);
2184}
2185
2186static int
2187mac_lomac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2188    struct label *label, int prot)
2189{
2190	struct mac_lomac *subj, *obj;
2191
2192	/*
2193	 * Rely on the use of open()-time protections to handle
2194	 * non-revocation cases.
2195	 */
2196	if (!mac_lomac_enabled)
2197		return (0);
2198
2199	subj = SLOT(cred->cr_label);
2200	obj = SLOT(label);
2201
2202	if (prot & VM_PROT_WRITE) {
2203		if (!mac_lomac_subject_dominate(subj, obj))
2204			return (EACCES);
2205	}
2206	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2207		if (!mac_lomac_dominate_single(obj, subj))
2208			return (maybe_demote(subj, obj, "mapping", "file", vp));
2209	}
2210
2211	return (0);
2212}
2213
2214static int
2215mac_lomac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp,
2216    struct label *label, int prot)
2217{
2218	struct mac_lomac *subj, *obj;
2219
2220	/*
2221	 * Rely on the use of open()-time protections to handle
2222	 * non-revocation cases.
2223	 */
2224	if (!mac_lomac_enabled || !revocation_enabled)
2225		return (0);
2226
2227	subj = SLOT(cred->cr_label);
2228	obj = SLOT(label);
2229
2230	if (prot & VM_PROT_WRITE) {
2231		if (!mac_lomac_subject_dominate(subj, obj))
2232			return (EACCES);
2233	}
2234	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2235		if (!mac_lomac_dominate_single(obj, subj))
2236			return (EACCES);
2237	}
2238
2239	return (0);
2240}
2241
2242static void
2243mac_lomac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp,
2244    struct label *label, /* XXX vm_prot_t */ int *prot)
2245{
2246	struct mac_lomac *subj, *obj;
2247
2248	/*
2249	 * Rely on the use of open()-time protections to handle
2250	 * non-revocation cases.
2251	 */
2252	if (!mac_lomac_enabled || !revocation_enabled)
2253		return;
2254
2255	subj = SLOT(cred->cr_label);
2256	obj = SLOT(label);
2257
2258	if (!mac_lomac_subject_dominate(subj, obj))
2259		*prot &= ~VM_PROT_WRITE;
2260}
2261
2262static int
2263mac_lomac_check_vnode_open(struct ucred *cred, struct vnode *vp,
2264    struct label *vnodelabel, int acc_mode)
2265{
2266	struct mac_lomac *subj, *obj;
2267
2268	if (!mac_lomac_enabled)
2269		return (0);
2270
2271	subj = SLOT(cred->cr_label);
2272	obj = SLOT(vnodelabel);
2273
2274	/* XXX privilege override for admin? */
2275	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2276		if (!mac_lomac_subject_dominate(subj, obj))
2277			return (EACCES);
2278	}
2279
2280	return (0);
2281}
2282
2283static int
2284mac_lomac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2285    struct vnode *vp, struct label *label)
2286{
2287	struct mac_lomac *subj, *obj;
2288
2289	if (!mac_lomac_enabled || !revocation_enabled)
2290		return (0);
2291
2292	subj = SLOT(active_cred->cr_label);
2293	obj = SLOT(label);
2294
2295	if (!mac_lomac_dominate_single(obj, subj))
2296		return (maybe_demote(subj, obj, "reading", "file", vp));
2297
2298	return (0);
2299}
2300
2301static int
2302mac_lomac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2303    struct label *vnodelabel, struct label *newlabel)
2304{
2305	struct mac_lomac *old, *new, *subj;
2306	int error;
2307
2308	old = SLOT(vnodelabel);
2309	new = SLOT(newlabel);
2310	subj = SLOT(cred->cr_label);
2311
2312	/*
2313	 * If there is a LOMAC label update for the vnode, it must be a
2314	 * single label, with an optional explicit auxiliary single.
2315	 */
2316	error = lomac_atmostflags(new,
2317	    MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX);
2318	if (error)
2319		return (error);
2320
2321	/*
2322	 * To perform a relabel of the vnode (LOMAC label or not), LOMAC must
2323	 * authorize the relabel.
2324	 */
2325	if (!mac_lomac_single_in_range(old, subj))
2326		return (EPERM);
2327
2328	/*
2329	 * If the LOMAC label is to be changed, authorize as appropriate.
2330	 */
2331	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2332		/*
2333		 * To change the LOMAC label on a vnode, the new vnode label
2334		 * must be in the subject range.
2335		 */
2336		if (!mac_lomac_single_in_range(new, subj))
2337			return (EPERM);
2338
2339		/*
2340		 * To change the LOMAC label on the vnode to be EQUAL,
2341		 * the subject must have appropriate privilege.
2342		 */
2343		if (mac_lomac_contains_equal(new)) {
2344			error = mac_lomac_subject_privileged(subj);
2345			if (error)
2346				return (error);
2347		}
2348	}
2349	if (new->ml_flags & MAC_LOMAC_FLAG_AUX) {
2350		/*
2351		 * Fill in the missing parts from the previous label.
2352		 */
2353		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2354			mac_lomac_copy_single(subj, new);
2355
2356		/*
2357		 * To change the auxiliary LOMAC label on a vnode, the new
2358		 * vnode label must be in the subject range.
2359		 */
2360		if (!mac_lomac_auxsingle_in_range(new, subj))
2361			return (EPERM);
2362
2363		/*
2364		 * To change the auxiliary LOMAC label on the vnode to be
2365		 * EQUAL, the subject must have appropriate privilege.
2366		 */
2367		if (mac_lomac_contains_equal(new)) {
2368			error = mac_lomac_subject_privileged(subj);
2369			if (error)
2370				return (error);
2371		}
2372	}
2373
2374	return (0);
2375}
2376
2377static int
2378mac_lomac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2379    struct label *dlabel, struct vnode *vp, struct label *label,
2380    struct componentname *cnp)
2381{
2382	struct mac_lomac *subj, *obj;
2383
2384	if (!mac_lomac_enabled)
2385		return (0);
2386
2387	subj = SLOT(cred->cr_label);
2388	obj = SLOT(dlabel);
2389
2390	if (!mac_lomac_subject_dominate(subj, obj))
2391		return (EACCES);
2392
2393	obj = SLOT(label);
2394
2395	if (!mac_lomac_subject_dominate(subj, obj))
2396		return (EACCES);
2397
2398	return (0);
2399}
2400
2401static int
2402mac_lomac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2403    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2404    struct componentname *cnp)
2405{
2406	struct mac_lomac *subj, *obj;
2407
2408	if (!mac_lomac_enabled)
2409		return (0);
2410
2411	subj = SLOT(cred->cr_label);
2412	obj = SLOT(dlabel);
2413
2414	if (!mac_lomac_subject_dominate(subj, obj))
2415		return (EACCES);
2416
2417	if (vp != NULL) {
2418		obj = SLOT(label);
2419
2420		if (!mac_lomac_subject_dominate(subj, obj))
2421			return (EACCES);
2422	}
2423
2424	return (0);
2425}
2426
2427static int
2428mac_lomac_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2429    struct label *label)
2430{
2431	struct mac_lomac *subj, *obj;
2432
2433	if (!mac_lomac_enabled)
2434		return (0);
2435
2436	subj = SLOT(cred->cr_label);
2437	obj = SLOT(label);
2438
2439	if (!mac_lomac_subject_dominate(subj, obj))
2440		return (EACCES);
2441
2442	return (0);
2443}
2444
2445static int
2446mac_lomac_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2447    struct label *label, acl_type_t type, struct acl *acl)
2448{
2449	struct mac_lomac *subj, *obj;
2450
2451	if (!mac_lomac_enabled)
2452		return (0);
2453
2454	subj = SLOT(cred->cr_label);
2455	obj = SLOT(label);
2456
2457	if (!mac_lomac_subject_dominate(subj, obj))
2458		return (EACCES);
2459
2460	return (0);
2461}
2462
2463static int
2464mac_lomac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2465    struct label *vnodelabel, int attrnamespace, const char *name,
2466    struct uio *uio)
2467{
2468	struct mac_lomac *subj, *obj;
2469
2470	if (!mac_lomac_enabled)
2471		return (0);
2472
2473	subj = SLOT(cred->cr_label);
2474	obj = SLOT(vnodelabel);
2475
2476	if (!mac_lomac_subject_dominate(subj, obj))
2477		return (EACCES);
2478
2479	/* XXX: protect the MAC EA in a special way? */
2480
2481	return (0);
2482}
2483
2484static int
2485mac_lomac_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2486    struct label *vnodelabel, u_long flags)
2487{
2488	struct mac_lomac *subj, *obj;
2489
2490	if (!mac_lomac_enabled)
2491		return (0);
2492
2493	subj = SLOT(cred->cr_label);
2494	obj = SLOT(vnodelabel);
2495
2496	if (!mac_lomac_subject_dominate(subj, obj))
2497		return (EACCES);
2498
2499	return (0);
2500}
2501
2502static int
2503mac_lomac_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2504    struct label *vnodelabel, mode_t mode)
2505{
2506	struct mac_lomac *subj, *obj;
2507
2508	if (!mac_lomac_enabled)
2509		return (0);
2510
2511	subj = SLOT(cred->cr_label);
2512	obj = SLOT(vnodelabel);
2513
2514	if (!mac_lomac_subject_dominate(subj, obj))
2515		return (EACCES);
2516
2517	return (0);
2518}
2519
2520static int
2521mac_lomac_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2522    struct label *vnodelabel, uid_t uid, gid_t gid)
2523{
2524	struct mac_lomac *subj, *obj;
2525
2526	if (!mac_lomac_enabled)
2527		return (0);
2528
2529	subj = SLOT(cred->cr_label);
2530	obj = SLOT(vnodelabel);
2531
2532	if (!mac_lomac_subject_dominate(subj, obj))
2533		return (EACCES);
2534
2535	return (0);
2536}
2537
2538static int
2539mac_lomac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2540    struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2541{
2542	struct mac_lomac *subj, *obj;
2543
2544	if (!mac_lomac_enabled)
2545		return (0);
2546
2547	subj = SLOT(cred->cr_label);
2548	obj = SLOT(vnodelabel);
2549
2550	if (!mac_lomac_subject_dominate(subj, obj))
2551		return (EACCES);
2552
2553	return (0);
2554}
2555
2556static int
2557mac_lomac_check_vnode_write(struct ucred *active_cred,
2558    struct ucred *file_cred, struct vnode *vp, struct label *label)
2559{
2560	struct mac_lomac *subj, *obj;
2561
2562	if (!mac_lomac_enabled || !revocation_enabled)
2563		return (0);
2564
2565	subj = SLOT(active_cred->cr_label);
2566	obj = SLOT(label);
2567
2568	if (!mac_lomac_subject_dominate(subj, obj))
2569		return (EACCES);
2570
2571	return (0);
2572}
2573
2574static void
2575mac_lomac_thread_userret(struct thread *td)
2576{
2577	struct proc *p = td->td_proc;
2578	struct mac_lomac_proc *subj = PSLOT(p->p_label);
2579	struct ucred *newcred, *oldcred;
2580	int dodrop;
2581
2582	mtx_lock(&subj->mtx);
2583	if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
2584		dodrop = 0;
2585		mtx_unlock(&subj->mtx);
2586		newcred = crget();
2587		/*
2588		 * Prevent a lock order reversal in
2589		 * mac_cred_mmapped_drop_perms; ideally, the other
2590		 * user of subj->mtx wouldn't be holding Giant.
2591		 */
2592		mtx_lock(&Giant);
2593		PROC_LOCK(p);
2594		mtx_lock(&subj->mtx);
2595		/*
2596		 * Check if we lost the race while allocating the cred.
2597		 */
2598		if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) {
2599			crfree(newcred);
2600			goto out;
2601		}
2602		oldcred = p->p_ucred;
2603		crcopy(newcred, oldcred);
2604		crhold(newcred);
2605		mac_lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label));
2606		p->p_ucred = newcred;
2607		crfree(oldcred);
2608		dodrop = 1;
2609	out:
2610		mtx_unlock(&subj->mtx);
2611		PROC_UNLOCK(p);
2612		if (dodrop)
2613			mac_cred_mmapped_drop_perms(curthread, newcred);
2614		mtx_unlock(&Giant);
2615	} else {
2616		mtx_unlock(&subj->mtx);
2617	}
2618}
2619
2620static struct mac_policy_ops mac_lomac_ops =
2621{
2622	.mpo_init = mac_lomac_init,
2623	.mpo_init_bpfdesc_label = mac_lomac_init_label,
2624	.mpo_init_cred_label = mac_lomac_init_label,
2625	.mpo_init_devfsdirent_label = mac_lomac_init_label,
2626	.mpo_init_ifnet_label = mac_lomac_init_label,
2627	.mpo_init_inpcb_label = mac_lomac_init_label_waitcheck,
2628	.mpo_init_ipq_label = mac_lomac_init_label_waitcheck,
2629	.mpo_init_mbuf_label = mac_lomac_init_label_waitcheck,
2630	.mpo_init_mount_label = mac_lomac_init_label,
2631	.mpo_init_mount_fs_label = mac_lomac_init_label,
2632	.mpo_init_pipe_label = mac_lomac_init_label,
2633	.mpo_init_proc_label = mac_lomac_init_proc_label,
2634	.mpo_init_socket_label = mac_lomac_init_label_waitcheck,
2635	.mpo_init_socket_peer_label = mac_lomac_init_label_waitcheck,
2636	.mpo_init_vnode_label = mac_lomac_init_label,
2637	.mpo_destroy_bpfdesc_label = mac_lomac_destroy_label,
2638	.mpo_destroy_cred_label = mac_lomac_destroy_label,
2639	.mpo_destroy_devfsdirent_label = mac_lomac_destroy_label,
2640	.mpo_destroy_ifnet_label = mac_lomac_destroy_label,
2641	.mpo_destroy_inpcb_label = mac_lomac_destroy_label,
2642	.mpo_destroy_ipq_label = mac_lomac_destroy_label,
2643	.mpo_destroy_mbuf_label = mac_lomac_destroy_label,
2644	.mpo_destroy_mount_label = mac_lomac_destroy_label,
2645	.mpo_destroy_mount_fs_label = mac_lomac_destroy_label,
2646	.mpo_destroy_pipe_label = mac_lomac_destroy_label,
2647	.mpo_destroy_proc_label = mac_lomac_destroy_proc_label,
2648	.mpo_destroy_socket_label = mac_lomac_destroy_label,
2649	.mpo_destroy_socket_peer_label = mac_lomac_destroy_label,
2650	.mpo_destroy_vnode_label = mac_lomac_destroy_label,
2651	.mpo_copy_cred_label = mac_lomac_copy_label,
2652	.mpo_copy_mbuf_label = mac_lomac_copy_label,
2653	.mpo_copy_pipe_label = mac_lomac_copy_label,
2654	.mpo_copy_socket_label = mac_lomac_copy_label,
2655	.mpo_copy_vnode_label = mac_lomac_copy_label,
2656	.mpo_externalize_cred_label = mac_lomac_externalize_label,
2657	.mpo_externalize_ifnet_label = mac_lomac_externalize_label,
2658	.mpo_externalize_pipe_label = mac_lomac_externalize_label,
2659	.mpo_externalize_socket_label = mac_lomac_externalize_label,
2660	.mpo_externalize_socket_peer_label = mac_lomac_externalize_label,
2661	.mpo_externalize_vnode_label = mac_lomac_externalize_label,
2662	.mpo_internalize_cred_label = mac_lomac_internalize_label,
2663	.mpo_internalize_ifnet_label = mac_lomac_internalize_label,
2664	.mpo_internalize_pipe_label = mac_lomac_internalize_label,
2665	.mpo_internalize_socket_label = mac_lomac_internalize_label,
2666	.mpo_internalize_vnode_label = mac_lomac_internalize_label,
2667	.mpo_create_devfs_device = mac_lomac_create_devfs_device,
2668	.mpo_create_devfs_directory = mac_lomac_create_devfs_directory,
2669	.mpo_create_devfs_symlink = mac_lomac_create_devfs_symlink,
2670	.mpo_create_mount = mac_lomac_create_mount,
2671	.mpo_create_root_mount = mac_lomac_create_root_mount,
2672	.mpo_relabel_vnode = mac_lomac_relabel_vnode,
2673	.mpo_update_devfsdirent = mac_lomac_update_devfsdirent,
2674	.mpo_associate_vnode_devfs = mac_lomac_associate_vnode_devfs,
2675	.mpo_associate_vnode_extattr = mac_lomac_associate_vnode_extattr,
2676	.mpo_associate_vnode_singlelabel =
2677	    mac_lomac_associate_vnode_singlelabel,
2678	.mpo_create_vnode_extattr = mac_lomac_create_vnode_extattr,
2679	.mpo_setlabel_vnode_extattr = mac_lomac_setlabel_vnode_extattr,
2680	.mpo_create_mbuf_from_socket = mac_lomac_create_mbuf_from_socket,
2681	.mpo_create_pipe = mac_lomac_create_pipe,
2682	.mpo_create_socket = mac_lomac_create_socket,
2683	.mpo_create_socket_from_socket = mac_lomac_create_socket_from_socket,
2684	.mpo_relabel_pipe = mac_lomac_relabel_pipe,
2685	.mpo_relabel_socket = mac_lomac_relabel_socket,
2686	.mpo_set_socket_peer_from_mbuf = mac_lomac_set_socket_peer_from_mbuf,
2687	.mpo_set_socket_peer_from_socket =
2688	    mac_lomac_set_socket_peer_from_socket,
2689	.mpo_create_bpfdesc = mac_lomac_create_bpfdesc,
2690	.mpo_create_datagram_from_ipq = mac_lomac_create_datagram_from_ipq,
2691	.mpo_create_fragment = mac_lomac_create_fragment,
2692	.mpo_create_ifnet = mac_lomac_create_ifnet,
2693	.mpo_create_inpcb_from_socket = mac_lomac_create_inpcb_from_socket,
2694	.mpo_create_ipq = mac_lomac_create_ipq,
2695	.mpo_create_mbuf_from_inpcb = mac_lomac_create_mbuf_from_inpcb,
2696	.mpo_create_mbuf_from_mbuf = mac_lomac_create_mbuf_from_mbuf,
2697	.mpo_create_mbuf_linklayer = mac_lomac_create_mbuf_linklayer,
2698	.mpo_create_mbuf_from_bpfdesc = mac_lomac_create_mbuf_from_bpfdesc,
2699	.mpo_create_mbuf_from_ifnet = mac_lomac_create_mbuf_from_ifnet,
2700	.mpo_create_mbuf_multicast_encap =
2701	    mac_lomac_create_mbuf_multicast_encap,
2702	.mpo_create_mbuf_netlayer = mac_lomac_create_mbuf_netlayer,
2703	.mpo_fragment_match = mac_lomac_fragment_match,
2704	.mpo_relabel_ifnet = mac_lomac_relabel_ifnet,
2705	.mpo_update_ipq = mac_lomac_update_ipq,
2706	.mpo_inpcb_sosetlabel = mac_lomac_inpcb_sosetlabel,
2707	.mpo_execve_transition = mac_lomac_execve_transition,
2708	.mpo_execve_will_transition = mac_lomac_execve_will_transition,
2709	.mpo_create_proc0 = mac_lomac_create_proc0,
2710	.mpo_create_proc1 = mac_lomac_create_proc1,
2711	.mpo_relabel_cred = mac_lomac_relabel_cred,
2712	.mpo_check_bpfdesc_receive = mac_lomac_check_bpfdesc_receive,
2713	.mpo_check_cred_relabel = mac_lomac_check_cred_relabel,
2714	.mpo_check_cred_visible = mac_lomac_check_cred_visible,
2715	.mpo_check_ifnet_relabel = mac_lomac_check_ifnet_relabel,
2716	.mpo_check_ifnet_transmit = mac_lomac_check_ifnet_transmit,
2717	.mpo_check_inpcb_deliver = mac_lomac_check_inpcb_deliver,
2718	.mpo_check_kld_load = mac_lomac_check_kld_load,
2719	.mpo_check_kld_unload = mac_lomac_check_kld_unload,
2720	.mpo_check_pipe_ioctl = mac_lomac_check_pipe_ioctl,
2721	.mpo_check_pipe_read = mac_lomac_check_pipe_read,
2722	.mpo_check_pipe_relabel = mac_lomac_check_pipe_relabel,
2723	.mpo_check_pipe_write = mac_lomac_check_pipe_write,
2724	.mpo_check_proc_debug = mac_lomac_check_proc_debug,
2725	.mpo_check_proc_sched = mac_lomac_check_proc_sched,
2726	.mpo_check_proc_signal = mac_lomac_check_proc_signal,
2727	.mpo_check_socket_deliver = mac_lomac_check_socket_deliver,
2728	.mpo_check_socket_relabel = mac_lomac_check_socket_relabel,
2729	.mpo_check_socket_visible = mac_lomac_check_socket_visible,
2730	.mpo_check_system_swapon = mac_lomac_check_system_swapon,
2731	.mpo_check_system_sysctl = mac_lomac_check_system_sysctl,
2732	.mpo_check_vnode_access = mac_lomac_check_vnode_open,
2733	.mpo_check_vnode_create = mac_lomac_check_vnode_create,
2734	.mpo_check_vnode_delete = mac_lomac_check_vnode_delete,
2735	.mpo_check_vnode_deleteacl = mac_lomac_check_vnode_deleteacl,
2736	.mpo_check_vnode_link = mac_lomac_check_vnode_link,
2737	.mpo_check_vnode_mmap = mac_lomac_check_vnode_mmap,
2738	.mpo_check_vnode_mmap_downgrade = mac_lomac_check_vnode_mmap_downgrade,
2739	.mpo_check_vnode_mprotect = mac_lomac_check_vnode_mprotect,
2740	.mpo_check_vnode_open = mac_lomac_check_vnode_open,
2741	.mpo_check_vnode_read = mac_lomac_check_vnode_read,
2742	.mpo_check_vnode_relabel = mac_lomac_check_vnode_relabel,
2743	.mpo_check_vnode_rename_from = mac_lomac_check_vnode_rename_from,
2744	.mpo_check_vnode_rename_to = mac_lomac_check_vnode_rename_to,
2745	.mpo_check_vnode_revoke = mac_lomac_check_vnode_revoke,
2746	.mpo_check_vnode_setacl = mac_lomac_check_vnode_setacl,
2747	.mpo_check_vnode_setextattr = mac_lomac_check_vnode_setextattr,
2748	.mpo_check_vnode_setflags = mac_lomac_check_vnode_setflags,
2749	.mpo_check_vnode_setmode = mac_lomac_check_vnode_setmode,
2750	.mpo_check_vnode_setowner = mac_lomac_check_vnode_setowner,
2751	.mpo_check_vnode_setutimes = mac_lomac_check_vnode_setutimes,
2752	.mpo_check_vnode_write = mac_lomac_check_vnode_write,
2753	.mpo_thread_userret = mac_lomac_thread_userret,
2754};
2755
2756MAC_POLICY_SET(&mac_lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC",
2757    MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS,
2758    &mac_lomac_slot);
2759