1/*-
2 * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson
3 * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
4 * Copyright (c) 2006 SPARTA, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson for the TrustedBSD Project.
8 *
9 * This software was developed for the FreeBSD Project in part by NAI Labs,
10 * the Security Research Division of Network Associates, Inc. under
11 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
12 * CHATS research program.
13 *
14 * This software was enhanced by SPARTA ISSO under SPAWAR contract
15 * N66001-04-C-6019 ("SEFOS").
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 *    notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 *    notice, this list of conditions and the following disclaimer in the
24 *    documentation and/or other materials provided with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * $FreeBSD$
39 */
40
41/*
42 * Developed by the TrustedBSD Project.
43 *
44 * Low-watermark floating label mandatory integrity policy.
45 */
46
47#include <sys/types.h>
48#include <sys/param.h>
49#include <sys/acl.h>
50#include <sys/conf.h>
51#include <sys/extattr.h>
52#include <sys/kernel.h>
53#include <sys/malloc.h>
54#include <sys/mman.h>
55#include <sys/mount.h>
56#include <sys/priv.h>
57#include <sys/proc.h>
58#include <sys/sbuf.h>
59#include <sys/systm.h>
60#include <sys/sysproto.h>
61#include <sys/sysent.h>
62#include <sys/systm.h>
63#include <sys/vnode.h>
64#include <sys/file.h>
65#include <sys/socket.h>
66#include <sys/socketvar.h>
67#include <sys/sx.h>
68#include <sys/pipe.h>
69#include <sys/sysctl.h>
70#include <sys/syslog.h>
71
72#include <fs/devfs/devfs.h>
73
74#include <net/bpfdesc.h>
75#include <net/if.h>
76#include <net/if_types.h>
77#include <net/if_var.h>
78
79#include <netinet/in.h>
80#include <netinet/in_pcb.h>
81#include <netinet/ip_var.h>
82
83#include <vm/vm.h>
84
85#include <security/mac/mac_policy.h>
86#include <security/mac/mac_framework.h>
87#include <security/mac_lomac/mac_lomac.h>
88
89struct mac_lomac_proc {
90	struct mac_lomac mac_lomac;
91	struct mtx mtx;
92};
93
94SYSCTL_DECL(_security_mac);
95
96static SYSCTL_NODE(_security_mac, OID_AUTO, lomac, CTLFLAG_RW, 0,
97    "TrustedBSD mac_lomac policy controls");
98
99static int	lomac_label_size = sizeof(struct mac_lomac);
100SYSCTL_INT(_security_mac_lomac, OID_AUTO, label_size, CTLFLAG_RD,
101    &lomac_label_size, 0, "Size of struct mac_lomac");
102
103static int	lomac_enabled = 1;
104SYSCTL_INT(_security_mac_lomac, OID_AUTO, enabled, CTLFLAG_RWTUN,
105    &lomac_enabled, 0, "Enforce MAC/LOMAC policy");
106
107static int	destroyed_not_inited;
108SYSCTL_INT(_security_mac_lomac, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
109    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
110
111static int	trust_all_interfaces = 0;
112SYSCTL_INT(_security_mac_lomac, OID_AUTO, trust_all_interfaces, CTLFLAG_RDTUN,
113    &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/LOMAC");
114
115static char	trusted_interfaces[128];
116SYSCTL_STRING(_security_mac_lomac, OID_AUTO, trusted_interfaces, CTLFLAG_RDTUN,
117    trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/LOMAC");
118
119static int	ptys_equal = 0;
120SYSCTL_INT(_security_mac_lomac, OID_AUTO, ptys_equal, CTLFLAG_RWTUN,
121    &ptys_equal, 0, "Label pty devices as lomac/equal on create");
122
123static int	revocation_enabled = 1;
124SYSCTL_INT(_security_mac_lomac, OID_AUTO, revocation_enabled, CTLFLAG_RWTUN,
125    &revocation_enabled, 0, "Revoke access to objects on relabel");
126
127static int	lomac_slot;
128#define	SLOT(l)	((struct mac_lomac *)mac_label_get((l), lomac_slot))
129#define	SLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val))
130#define	PSLOT(l) ((struct mac_lomac_proc *)				\
131    mac_label_get((l), lomac_slot))
132#define	PSLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val))
133
134static MALLOC_DEFINE(M_LOMAC, "mac_lomac_label", "MAC/LOMAC labels");
135
136static struct mac_lomac *
137lomac_alloc(int flag)
138{
139	struct mac_lomac *ml;
140
141	ml = malloc(sizeof(*ml), M_LOMAC, M_ZERO | flag);
142
143	return (ml);
144}
145
146static void
147lomac_free(struct mac_lomac *ml)
148{
149
150	if (ml != NULL)
151		free(ml, M_LOMAC);
152	else
153		atomic_add_int(&destroyed_not_inited, 1);
154}
155
156static int
157lomac_atmostflags(struct mac_lomac *ml, int flags)
158{
159
160	if ((ml->ml_flags & flags) != ml->ml_flags)
161		return (EINVAL);
162	return (0);
163}
164
165static int
166lomac_dominate_element(struct mac_lomac_element *a,
167    struct mac_lomac_element *b)
168{
169
170	switch (a->mle_type) {
171	case MAC_LOMAC_TYPE_EQUAL:
172	case MAC_LOMAC_TYPE_HIGH:
173		return (1);
174
175	case MAC_LOMAC_TYPE_LOW:
176		switch (b->mle_type) {
177		case MAC_LOMAC_TYPE_GRADE:
178		case MAC_LOMAC_TYPE_HIGH:
179			return (0);
180
181		case MAC_LOMAC_TYPE_EQUAL:
182		case MAC_LOMAC_TYPE_LOW:
183			return (1);
184
185		default:
186			panic("lomac_dominate_element: b->mle_type invalid");
187		}
188
189	case MAC_LOMAC_TYPE_GRADE:
190		switch (b->mle_type) {
191		case MAC_LOMAC_TYPE_EQUAL:
192		case MAC_LOMAC_TYPE_LOW:
193			return (1);
194
195		case MAC_LOMAC_TYPE_HIGH:
196			return (0);
197
198		case MAC_LOMAC_TYPE_GRADE:
199			return (a->mle_grade >= b->mle_grade);
200
201		default:
202			panic("lomac_dominate_element: b->mle_type invalid");
203		}
204
205	default:
206		panic("lomac_dominate_element: a->mle_type invalid");
207	}
208}
209
210static int
211lomac_range_in_range(struct mac_lomac *rangea, struct mac_lomac *rangeb)
212{
213
214	return (lomac_dominate_element(&rangeb->ml_rangehigh,
215	    &rangea->ml_rangehigh) &&
216	    lomac_dominate_element(&rangea->ml_rangelow,
217	    &rangeb->ml_rangelow));
218}
219
220static int
221lomac_single_in_range(struct mac_lomac *single, struct mac_lomac *range)
222{
223
224	KASSERT((single->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
225	    ("lomac_single_in_range: a not single"));
226	KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
227	    ("lomac_single_in_range: b not range"));
228
229	return (lomac_dominate_element(&range->ml_rangehigh,
230	    &single->ml_single) && lomac_dominate_element(&single->ml_single,
231	    &range->ml_rangelow));
232}
233
234static int
235lomac_auxsingle_in_range(struct mac_lomac *single, struct mac_lomac *range)
236{
237
238	KASSERT((single->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
239	    ("lomac_single_in_range: a not auxsingle"));
240	KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
241	    ("lomac_single_in_range: b not range"));
242
243	return (lomac_dominate_element(&range->ml_rangehigh,
244	    &single->ml_auxsingle) &&
245	    lomac_dominate_element(&single->ml_auxsingle,
246	    &range->ml_rangelow));
247}
248
249static int
250lomac_dominate_single(struct mac_lomac *a, struct mac_lomac *b)
251{
252	KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
253	    ("lomac_dominate_single: a not single"));
254	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
255	    ("lomac_dominate_single: b not single"));
256
257	return (lomac_dominate_element(&a->ml_single, &b->ml_single));
258}
259
260static int
261lomac_subject_dominate(struct mac_lomac *a, struct mac_lomac *b)
262{
263	KASSERT((~a->ml_flags &
264	    (MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_RANGE)) == 0,
265	    ("lomac_dominate_single: a not subject"));
266	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
267	    ("lomac_dominate_single: b not single"));
268
269	return (lomac_dominate_element(&a->ml_rangehigh, &b->ml_single));
270}
271
272static int
273lomac_equal_element(struct mac_lomac_element *a, struct mac_lomac_element *b)
274{
275
276	if (a->mle_type == MAC_LOMAC_TYPE_EQUAL ||
277	    b->mle_type == MAC_LOMAC_TYPE_EQUAL)
278		return (1);
279
280	return (a->mle_type == b->mle_type && a->mle_grade == b->mle_grade);
281}
282
283static int
284lomac_equal_single(struct mac_lomac *a, struct mac_lomac *b)
285{
286
287	KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
288	    ("lomac_equal_single: a not single"));
289	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
290	    ("lomac_equal_single: b not single"));
291
292	return (lomac_equal_element(&a->ml_single, &b->ml_single));
293}
294
295static int
296lomac_contains_equal(struct mac_lomac *ml)
297{
298
299	if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE)
300		if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
301			return (1);
302	if (ml->ml_flags & MAC_LOMAC_FLAG_AUX)
303		if (ml->ml_auxsingle.mle_type == MAC_LOMAC_TYPE_EQUAL)
304			return (1);
305
306	if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) {
307		if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL)
308			return (1);
309		if (ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
310			return (1);
311	}
312
313	return (0);
314}
315
316static int
317lomac_subject_privileged(struct mac_lomac *ml)
318{
319
320	KASSERT((ml->ml_flags & MAC_LOMAC_FLAGS_BOTH) ==
321	    MAC_LOMAC_FLAGS_BOTH,
322	    ("lomac_subject_privileged: subject doesn't have both labels"));
323
324	/* If the single is EQUAL, it's ok. */
325	if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
326		return (0);
327
328	/* If either range endpoint is EQUAL, it's ok. */
329	if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL ||
330	    ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
331		return (0);
332
333	/* If the range is low-high, it's ok. */
334	if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_LOW &&
335	    ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_HIGH)
336		return (0);
337
338	/* It's not ok. */
339	return (EPERM);
340}
341
342static int
343lomac_high_single(struct mac_lomac *ml)
344{
345
346	KASSERT((ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
347	    ("lomac_high_single: mac_lomac not single"));
348
349	return (ml->ml_single.mle_type == MAC_LOMAC_TYPE_HIGH);
350}
351
352static int
353lomac_valid(struct mac_lomac *ml)
354{
355
356	if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
357		switch (ml->ml_single.mle_type) {
358		case MAC_LOMAC_TYPE_GRADE:
359		case MAC_LOMAC_TYPE_EQUAL:
360		case MAC_LOMAC_TYPE_HIGH:
361		case MAC_LOMAC_TYPE_LOW:
362			break;
363
364		default:
365			return (EINVAL);
366		}
367	} else {
368		if (ml->ml_single.mle_type != MAC_LOMAC_TYPE_UNDEF)
369			return (EINVAL);
370	}
371
372	if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) {
373		switch (ml->ml_auxsingle.mle_type) {
374		case MAC_LOMAC_TYPE_GRADE:
375		case MAC_LOMAC_TYPE_EQUAL:
376		case MAC_LOMAC_TYPE_HIGH:
377		case MAC_LOMAC_TYPE_LOW:
378			break;
379
380		default:
381			return (EINVAL);
382		}
383	} else {
384		if (ml->ml_auxsingle.mle_type != MAC_LOMAC_TYPE_UNDEF)
385			return (EINVAL);
386	}
387
388	if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) {
389		switch (ml->ml_rangelow.mle_type) {
390		case MAC_LOMAC_TYPE_GRADE:
391		case MAC_LOMAC_TYPE_EQUAL:
392		case MAC_LOMAC_TYPE_HIGH:
393		case MAC_LOMAC_TYPE_LOW:
394			break;
395
396		default:
397			return (EINVAL);
398		}
399
400		switch (ml->ml_rangehigh.mle_type) {
401		case MAC_LOMAC_TYPE_GRADE:
402		case MAC_LOMAC_TYPE_EQUAL:
403		case MAC_LOMAC_TYPE_HIGH:
404		case MAC_LOMAC_TYPE_LOW:
405			break;
406
407		default:
408			return (EINVAL);
409		}
410		if (!lomac_dominate_element(&ml->ml_rangehigh,
411		    &ml->ml_rangelow))
412			return (EINVAL);
413	} else {
414		if (ml->ml_rangelow.mle_type != MAC_LOMAC_TYPE_UNDEF ||
415		    ml->ml_rangehigh.mle_type != MAC_LOMAC_TYPE_UNDEF)
416			return (EINVAL);
417	}
418
419	return (0);
420}
421
422static void
423lomac_set_range(struct mac_lomac *ml, u_short typelow, u_short gradelow,
424    u_short typehigh, u_short gradehigh)
425{
426
427	ml->ml_rangelow.mle_type = typelow;
428	ml->ml_rangelow.mle_grade = gradelow;
429	ml->ml_rangehigh.mle_type = typehigh;
430	ml->ml_rangehigh.mle_grade = gradehigh;
431	ml->ml_flags |= MAC_LOMAC_FLAG_RANGE;
432}
433
434static void
435lomac_set_single(struct mac_lomac *ml, u_short type, u_short grade)
436{
437
438	ml->ml_single.mle_type = type;
439	ml->ml_single.mle_grade = grade;
440	ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
441}
442
443static void
444lomac_copy_range(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
445{
446
447	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
448	    ("lomac_copy_range: labelfrom not range"));
449
450	labelto->ml_rangelow = labelfrom->ml_rangelow;
451	labelto->ml_rangehigh = labelfrom->ml_rangehigh;
452	labelto->ml_flags |= MAC_LOMAC_FLAG_RANGE;
453}
454
455static void
456lomac_copy_single(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
457{
458
459	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
460	    ("lomac_copy_single: labelfrom not single"));
461
462	labelto->ml_single = labelfrom->ml_single;
463	labelto->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
464}
465
466static void
467lomac_copy_auxsingle(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
468{
469
470	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
471	    ("lomac_copy_auxsingle: labelfrom not auxsingle"));
472
473	labelto->ml_auxsingle = labelfrom->ml_auxsingle;
474	labelto->ml_flags |= MAC_LOMAC_FLAG_AUX;
475}
476
477static void
478lomac_copy(struct mac_lomac *source, struct mac_lomac *dest)
479{
480
481	if (source->ml_flags & MAC_LOMAC_FLAG_SINGLE)
482		lomac_copy_single(source, dest);
483	if (source->ml_flags & MAC_LOMAC_FLAG_AUX)
484		lomac_copy_auxsingle(source, dest);
485	if (source->ml_flags & MAC_LOMAC_FLAG_RANGE)
486		lomac_copy_range(source, dest);
487}
488
489static int	lomac_to_string(struct sbuf *sb, struct mac_lomac *ml);
490
491static int
492maybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel,
493    const char *actionname, const char *objname, struct vnode *vp)
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 less
510		 * severe than this one, and keep the more severe.  This can
511		 * only happen for a multi-threaded application.
512		 */
513		if (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	lomac_copy_single(objlabel, &subj->mac_lomac);
523	/*
524	 * Start with the original range, then minimize each side of the
525	 * range to the point of not dominating the object.  The high side
526	 * will always be demoted, of course.
527	 */
528	lomac_copy_range(subjlabel, &subj->mac_lomac);
529	if (!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	thread_lock(curthread);
535	curthread->td_flags |= TDF_ASTPENDING | TDF_MACPEND;
536	thread_unlock(curthread);
537
538	/*
539	 * Avoid memory allocation while holding a mutex; cache the label.
540	 */
541	lomac_copy_single(&subj->mac_lomac, &cached_subjlabel);
542	mtx_unlock(&subj->mtx);
543
544	sbuf_new(&subjlabel_sb, NULL, 0, SBUF_AUTOEXTEND);
545	lomac_to_string(&subjlabel_sb, subjlabel);
546	sbuf_finish(&subjlabel_sb);
547	subjlabeltext = sbuf_data(&subjlabel_sb);
548
549	sbuf_new(&subjtext_sb, NULL, 0, SBUF_AUTOEXTEND);
550	lomac_to_string(&subjtext_sb, &subj->mac_lomac);
551	sbuf_finish(&subjtext_sb);
552	subjtext = sbuf_data(&subjtext_sb);
553
554	sbuf_new(&objlabel_sb, NULL, 0, SBUF_AUTOEXTEND);
555	lomac_to_string(&objlabel_sb, objlabel);
556	sbuf_finish(&objlabel_sb);
557	objlabeltext = sbuf_data(&objlabel_sb);
558
559	pgid = p->p_pgrp->pg_id;		/* XXX could be stale? */
560	if (vp != NULL && VOP_GETATTR(vp, &va, curthread->td_ucred) == 0) {
561		log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
562		    " level %s after %s a level-%s %s (inode=%ju, "
563		    "mountpount=%s)\n",
564		    subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
565		    p->p_comm, subjtext, actionname, objlabeltext, objname,
566		    (uintmax_t)va.va_fileid, vp->v_mount->mnt_stat.f_mntonname);
567	} else {
568		log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
569		    " level %s after %s a level-%s %s\n",
570		    subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
571		    p->p_comm, subjtext, actionname, objlabeltext, objname);
572	}
573
574	sbuf_delete(&subjlabel_sb);
575	sbuf_delete(&subjtext_sb);
576	sbuf_delete(&objlabel_sb);
577
578	return (0);
579}
580
581/*
582 * Relabel "to" to "from" only if "from" is a valid label (contains at least
583 * a single), as for a relabel operation which may or may not involve a
584 * relevant label.
585 */
586static void
587try_relabel(struct mac_lomac *from, struct mac_lomac *to)
588{
589
590	if (from->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
591		bzero(to, sizeof(*to));
592		lomac_copy(from, to);
593	}
594}
595
596/*
597 * Policy module operations.
598 */
599static void
600lomac_init(struct mac_policy_conf *conf)
601{
602
603}
604
605/*
606 * Label operations.
607 */
608static void
609lomac_init_label(struct label *label)
610{
611
612	SLOT_SET(label, lomac_alloc(M_WAITOK));
613}
614
615static int
616lomac_init_label_waitcheck(struct label *label, int flag)
617{
618
619	SLOT_SET(label, lomac_alloc(flag));
620	if (SLOT(label) == NULL)
621		return (ENOMEM);
622
623	return (0);
624}
625
626static void
627lomac_destroy_label(struct label *label)
628{
629
630	lomac_free(SLOT(label));
631	SLOT_SET(label, NULL);
632}
633
634static int
635lomac_element_to_string(struct sbuf *sb, struct mac_lomac_element *element)
636{
637
638	switch (element->mle_type) {
639	case MAC_LOMAC_TYPE_HIGH:
640		return (sbuf_printf(sb, "high"));
641
642	case MAC_LOMAC_TYPE_LOW:
643		return (sbuf_printf(sb, "low"));
644
645	case MAC_LOMAC_TYPE_EQUAL:
646		return (sbuf_printf(sb, "equal"));
647
648	case MAC_LOMAC_TYPE_GRADE:
649		return (sbuf_printf(sb, "%d", element->mle_grade));
650
651	default:
652		panic("lomac_element_to_string: invalid type (%d)",
653		    element->mle_type);
654	}
655}
656
657static int
658lomac_to_string(struct sbuf *sb, struct mac_lomac *ml)
659{
660
661	if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
662		if (lomac_element_to_string(sb, &ml->ml_single) == -1)
663			return (EINVAL);
664	}
665
666	if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) {
667		if (sbuf_putc(sb, '[') == -1)
668			return (EINVAL);
669
670		if (lomac_element_to_string(sb, &ml->ml_auxsingle) == -1)
671			return (EINVAL);
672
673		if (sbuf_putc(sb, ']') == -1)
674			return (EINVAL);
675	}
676
677	if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) {
678		if (sbuf_putc(sb, '(') == -1)
679			return (EINVAL);
680
681		if (lomac_element_to_string(sb, &ml->ml_rangelow) == -1)
682			return (EINVAL);
683
684		if (sbuf_putc(sb, '-') == -1)
685			return (EINVAL);
686
687		if (lomac_element_to_string(sb, &ml->ml_rangehigh) == -1)
688			return (EINVAL);
689
690		if (sbuf_putc(sb, ')') == -1)
691			return (EINVAL);
692	}
693
694	return (0);
695}
696
697static int
698lomac_externalize_label(struct label *label, char *element_name,
699    struct sbuf *sb, int *claimed)
700{
701	struct mac_lomac *ml;
702
703	if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
704		return (0);
705
706	(*claimed)++;
707
708	ml = SLOT(label);
709
710	return (lomac_to_string(sb, ml));
711}
712
713static int
714lomac_parse_element(struct mac_lomac_element *element, char *string)
715{
716
717	if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) {
718		element->mle_type = MAC_LOMAC_TYPE_HIGH;
719		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
720	} else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) {
721		element->mle_type = MAC_LOMAC_TYPE_LOW;
722		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
723	} else if (strcmp(string, "equal") == 0 ||
724	    strcmp(string, "eq") == 0) {
725		element->mle_type = MAC_LOMAC_TYPE_EQUAL;
726		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
727	} else {
728		char *p0, *p1;
729		int d;
730
731		p0 = string;
732		d = strtol(p0, &p1, 10);
733
734		if (d < 0 || d > 65535)
735			return (EINVAL);
736		element->mle_type = MAC_LOMAC_TYPE_GRADE;
737		element->mle_grade = d;
738
739		if (p1 == p0 || *p1 != '\0')
740			return (EINVAL);
741	}
742
743	return (0);
744}
745
746/*
747 * Note: destructively consumes the string, make a local copy before calling
748 * if that's a problem.
749 */
750static int
751lomac_parse(struct mac_lomac *ml, char *string)
752{
753	char *range, *rangeend, *rangehigh, *rangelow, *single, *auxsingle,
754	    *auxsingleend;
755	int error;
756
757	/* Do we have a range? */
758	single = string;
759	range = strchr(string, '(');
760	if (range == single)
761		single = NULL;
762	auxsingle = strchr(string, '[');
763	if (auxsingle == single)
764		single = NULL;
765	if (range != NULL && auxsingle != NULL)
766		return (EINVAL);
767	rangelow = rangehigh = NULL;
768	if (range != NULL) {
769		/* Nul terminate the end of the single string. */
770		*range = '\0';
771		range++;
772		rangelow = range;
773		rangehigh = strchr(rangelow, '-');
774		if (rangehigh == NULL)
775			return (EINVAL);
776		rangehigh++;
777		if (*rangelow == '\0' || *rangehigh == '\0')
778			return (EINVAL);
779		rangeend = strchr(rangehigh, ')');
780		if (rangeend == NULL)
781			return (EINVAL);
782		if (*(rangeend + 1) != '\0')
783			return (EINVAL);
784		/* Nul terminate the ends of the ranges. */
785		*(rangehigh - 1) = '\0';
786		*rangeend = '\0';
787	}
788	KASSERT((rangelow != NULL && rangehigh != NULL) ||
789	    (rangelow == NULL && rangehigh == NULL),
790	    ("lomac_internalize_label: range mismatch"));
791	if (auxsingle != NULL) {
792		/* Nul terminate the end of the single string. */
793		*auxsingle = '\0';
794		auxsingle++;
795		auxsingleend = strchr(auxsingle, ']');
796		if (auxsingleend == NULL)
797			return (EINVAL);
798		if (*(auxsingleend + 1) != '\0')
799			return (EINVAL);
800		/* Nul terminate the end of the auxsingle. */
801		*auxsingleend = '\0';
802	}
803
804	bzero(ml, sizeof(*ml));
805	if (single != NULL) {
806		error = lomac_parse_element(&ml->ml_single, single);
807		if (error)
808			return (error);
809		ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
810	}
811
812	if (auxsingle != NULL) {
813		error = lomac_parse_element(&ml->ml_auxsingle, auxsingle);
814		if (error)
815			return (error);
816		ml->ml_flags |= MAC_LOMAC_FLAG_AUX;
817	}
818
819	if (rangelow != NULL) {
820		error = lomac_parse_element(&ml->ml_rangelow, rangelow);
821		if (error)
822			return (error);
823		error = lomac_parse_element(&ml->ml_rangehigh, rangehigh);
824		if (error)
825			return (error);
826		ml->ml_flags |= MAC_LOMAC_FLAG_RANGE;
827	}
828
829	error = lomac_valid(ml);
830	if (error)
831		return (error);
832
833	return (0);
834}
835
836static int
837lomac_internalize_label(struct label *label, char *element_name,
838    char *element_data, int *claimed)
839{
840	struct mac_lomac *ml, ml_temp;
841	int error;
842
843	if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
844		return (0);
845
846	(*claimed)++;
847
848	error = lomac_parse(&ml_temp, element_data);
849	if (error)
850		return (error);
851
852	ml = SLOT(label);
853	*ml = ml_temp;
854
855	return (0);
856}
857
858static void
859lomac_copy_label(struct label *src, struct label *dest)
860{
861
862	*SLOT(dest) = *SLOT(src);
863}
864
865/*
866 * Object-specific entry point implementations are sorted alphabetically by
867 * object type name and then by operation.
868 */
869static int
870lomac_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel,
871    struct ifnet *ifp, struct label *ifplabel)
872{
873	struct mac_lomac *a, *b;
874
875	if (!lomac_enabled)
876		return (0);
877
878	a = SLOT(dlabel);
879	b = SLOT(ifplabel);
880
881	if (lomac_equal_single(a, b))
882		return (0);
883	return (EACCES);
884}
885
886static void
887lomac_bpfdesc_create(struct ucred *cred, struct bpf_d *d,
888    struct label *dlabel)
889{
890	struct mac_lomac *source, *dest;
891
892	source = SLOT(cred->cr_label);
893	dest = SLOT(dlabel);
894
895	lomac_copy_single(source, dest);
896}
897
898static void
899lomac_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel,
900    struct mbuf *m, struct label *mlabel)
901{
902	struct mac_lomac *source, *dest;
903
904	source = SLOT(dlabel);
905	dest = SLOT(mlabel);
906
907	lomac_copy_single(source, dest);
908}
909
910static int
911lomac_cred_check_relabel(struct ucred *cred, struct label *newlabel)
912{
913	struct mac_lomac *subj, *new;
914	int error;
915
916	subj = SLOT(cred->cr_label);
917	new = SLOT(newlabel);
918
919	/*
920	 * If there is a LOMAC label update for the credential, it may be an
921	 * update of the single, range, or both.
922	 */
923	error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
924	if (error)
925		return (error);
926
927	/*
928	 * If the LOMAC label is to be changed, authorize as appropriate.
929	 */
930	if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
931		/*
932		 * Fill in the missing parts from the previous label.
933		 */
934		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
935			lomac_copy_single(subj, new);
936		if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
937			lomac_copy_range(subj, new);
938
939		/*
940		 * To change the LOMAC range on a credential, the new range
941		 * label must be in the current range.
942		 */
943		if (!lomac_range_in_range(new, subj))
944			return (EPERM);
945
946		/*
947		 * To change the LOMAC single label on a credential, the new
948		 * single label must be in the new range.  Implicitly from
949		 * the previous check, the new single is in the old range.
950		 */
951		if (!lomac_single_in_range(new, new))
952			return (EPERM);
953
954		/*
955		 * To have EQUAL in any component of the new credential LOMAC
956		 * label, the subject must already have EQUAL in their label.
957		 */
958		if (lomac_contains_equal(new)) {
959			error = lomac_subject_privileged(subj);
960			if (error)
961				return (error);
962		}
963
964		/*
965		 * XXXMAC: Additional consistency tests regarding the single
966		 * and range of the new label might be performed here.
967		 */
968	}
969
970	return (0);
971}
972
973static int
974lomac_cred_check_visible(struct ucred *cr1, struct ucred *cr2)
975{
976	struct mac_lomac *subj, *obj;
977
978	if (!lomac_enabled)
979		return (0);
980
981	subj = SLOT(cr1->cr_label);
982	obj = SLOT(cr2->cr_label);
983
984	/* XXX: range */
985	if (!lomac_dominate_single(obj, subj))
986		return (ESRCH);
987
988	return (0);
989}
990
991static void
992lomac_cred_create_init(struct ucred *cred)
993{
994	struct mac_lomac *dest;
995
996	dest = SLOT(cred->cr_label);
997
998	lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0);
999	lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0);
1000}
1001
1002static void
1003lomac_cred_create_swapper(struct ucred *cred)
1004{
1005	struct mac_lomac *dest;
1006
1007	dest = SLOT(cred->cr_label);
1008
1009	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1010	lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0);
1011}
1012
1013static void
1014lomac_cred_relabel(struct ucred *cred, struct label *newlabel)
1015{
1016	struct mac_lomac *source, *dest;
1017
1018	source = SLOT(newlabel);
1019	dest = SLOT(cred->cr_label);
1020
1021	try_relabel(source, dest);
1022}
1023
1024static void
1025lomac_devfs_create_device(struct ucred *cred, struct mount *mp,
1026    struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
1027{
1028	struct mac_lomac *ml;
1029	const char *dn;
1030	int lomac_type;
1031
1032	ml = SLOT(delabel);
1033	dn = devtoname(dev);
1034	if (strcmp(dn, "null") == 0 ||
1035	    strcmp(dn, "zero") == 0 ||
1036	    strcmp(dn, "random") == 0 ||
1037	    strncmp(dn, "fd/", strlen("fd/")) == 0 ||
1038	    strncmp(dn, "ttyv", strlen("ttyv")) == 0)
1039		lomac_type = MAC_LOMAC_TYPE_EQUAL;
1040	else if (ptys_equal &&
1041	    (strncmp(dn, "ttyp", strlen("ttyp")) == 0 ||
1042	    strncmp(dn, "pts/", strlen("pts/")) == 0 ||
1043	    strncmp(dn, "ptyp", strlen("ptyp")) == 0))
1044		lomac_type = MAC_LOMAC_TYPE_EQUAL;
1045	else
1046		lomac_type = MAC_LOMAC_TYPE_HIGH;
1047	lomac_set_single(ml, lomac_type, 0);
1048}
1049
1050static void
1051lomac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
1052    struct devfs_dirent *de, struct label *delabel)
1053{
1054	struct mac_lomac *ml;
1055
1056	ml = SLOT(delabel);
1057	lomac_set_single(ml, MAC_LOMAC_TYPE_HIGH, 0);
1058}
1059
1060static void
1061lomac_devfs_create_symlink(struct ucred *cred, struct mount *mp,
1062    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
1063    struct label *delabel)
1064{
1065	struct mac_lomac *source, *dest;
1066
1067	source = SLOT(cred->cr_label);
1068	dest = SLOT(delabel);
1069
1070	lomac_copy_single(source, dest);
1071}
1072
1073static void
1074lomac_devfs_update(struct mount *mp, struct devfs_dirent *de,
1075    struct label *delabel, struct vnode *vp, struct label *vplabel)
1076{
1077	struct mac_lomac *source, *dest;
1078
1079	source = SLOT(vplabel);
1080	dest = SLOT(delabel);
1081
1082	lomac_copy(source, dest);
1083}
1084
1085static void
1086lomac_devfs_vnode_associate(struct mount *mp, struct label *mplabel,
1087    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
1088    struct label *vplabel)
1089{
1090	struct mac_lomac *source, *dest;
1091
1092	source = SLOT(delabel);
1093	dest = SLOT(vplabel);
1094
1095	lomac_copy_single(source, dest);
1096}
1097
1098static int
1099lomac_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
1100    struct label *ifplabel, struct label *newlabel)
1101{
1102	struct mac_lomac *subj, *new;
1103	int error;
1104
1105	subj = SLOT(cred->cr_label);
1106	new = SLOT(newlabel);
1107
1108	/*
1109	 * If there is a LOMAC label update for the interface, it may be an
1110	 * update of the single, range, or both.
1111	 */
1112	error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1113	if (error)
1114		return (error);
1115
1116	/*
1117	 * Relabling network interfaces requires LOMAC privilege.
1118	 */
1119	error = lomac_subject_privileged(subj);
1120	if (error)
1121		return (error);
1122
1123	/*
1124	 * If the LOMAC label is to be changed, authorize as appropriate.
1125	 */
1126	if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1127		/*
1128		 * Fill in the missing parts from the previous label.
1129		 */
1130		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1131			lomac_copy_single(subj, new);
1132		if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1133			lomac_copy_range(subj, new);
1134
1135		/*
1136		 * Rely on the traditional superuser status for the LOMAC
1137		 * interface relabel requirements.  XXXMAC: This will go
1138		 * away.
1139		 *
1140		 * XXXRW: This is also redundant to a higher layer check.
1141		 */
1142		error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0);
1143		if (error)
1144			return (EPERM);
1145
1146		/*
1147		 * XXXMAC: Additional consistency tests regarding the single
1148		 * and the range of the new label might be performed here.
1149		 */
1150	}
1151
1152	return (0);
1153}
1154
1155static int
1156lomac_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
1157    struct mbuf *m, struct label *mlabel)
1158{
1159	struct mac_lomac *p, *i;
1160
1161	if (!lomac_enabled)
1162		return (0);
1163
1164	p = SLOT(mlabel);
1165	i = SLOT(ifplabel);
1166
1167	return (lomac_single_in_range(p, i) ? 0 : EACCES);
1168}
1169
1170static void
1171lomac_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
1172{
1173	char tifname[IFNAMSIZ], *p, *q;
1174	char tiflist[sizeof(trusted_interfaces)];
1175	struct mac_lomac *dest;
1176	int len, grade;
1177
1178	dest = SLOT(ifplabel);
1179
1180	if (ifp->if_type == IFT_LOOP) {
1181		grade = MAC_LOMAC_TYPE_EQUAL;
1182		goto set;
1183	}
1184
1185	if (trust_all_interfaces) {
1186		grade = MAC_LOMAC_TYPE_HIGH;
1187		goto set;
1188	}
1189
1190	grade = MAC_LOMAC_TYPE_LOW;
1191
1192	if (trusted_interfaces[0] == '\0' ||
1193	    !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1194		goto set;
1195
1196	bzero(tiflist, sizeof(tiflist));
1197	for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1198		if(*p != ' ' && *p != '\t')
1199			*q = *p;
1200
1201	for (p = q = tiflist;; p++) {
1202		if (*p == ',' || *p == '\0') {
1203			len = p - q;
1204			if (len < IFNAMSIZ) {
1205				bzero(tifname, sizeof(tifname));
1206				bcopy(q, tifname, len);
1207				if (strcmp(tifname, ifp->if_xname) == 0) {
1208					grade = MAC_LOMAC_TYPE_HIGH;
1209					break;
1210				}
1211			}
1212			else {
1213				*p = '\0';
1214				printf("MAC/LOMAC warning: interface name "
1215				    "\"%s\" is too long (must be < %d)\n",
1216				    q, IFNAMSIZ);
1217			}
1218			if (*p == '\0')
1219				break;
1220			q = p + 1;
1221		}
1222	}
1223set:
1224	lomac_set_single(dest, grade, 0);
1225	lomac_set_range(dest, grade, 0, grade, 0);
1226}
1227
1228static void
1229lomac_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1230    struct mbuf *m, struct label *mlabel)
1231{
1232	struct mac_lomac *source, *dest;
1233
1234	source = SLOT(ifplabel);
1235	dest = SLOT(mlabel);
1236
1237	lomac_copy_single(source, dest);
1238}
1239
1240static void
1241lomac_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1242    struct label *ifplabel, struct label *newlabel)
1243{
1244	struct mac_lomac *source, *dest;
1245
1246	source = SLOT(newlabel);
1247	dest = SLOT(ifplabel);
1248
1249	try_relabel(source, dest);
1250}
1251
1252static int
1253lomac_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1254    struct mbuf *m, struct label *mlabel)
1255{
1256	struct mac_lomac *p, *i;
1257
1258	if (!lomac_enabled)
1259		return (0);
1260
1261	p = SLOT(mlabel);
1262	i = SLOT(inplabel);
1263
1264	return (lomac_equal_single(p, i) ? 0 : EACCES);
1265}
1266
1267static int
1268lomac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
1269    struct label *inplabel)
1270{
1271	struct mac_lomac *subj, *obj;
1272
1273	if (!lomac_enabled)
1274		return (0);
1275
1276	subj = SLOT(cred->cr_label);
1277	obj = SLOT(inplabel);
1278
1279	if (!lomac_dominate_single(obj, subj))
1280		return (ENOENT);
1281
1282	return (0);
1283}
1284
1285static void
1286lomac_inpcb_create(struct socket *so, struct label *solabel,
1287    struct inpcb *inp, struct label *inplabel)
1288{
1289	struct mac_lomac *source, *dest;
1290
1291	source = SLOT(solabel);
1292	dest = SLOT(inplabel);
1293
1294	lomac_copy_single(source, dest);
1295}
1296
1297static void
1298lomac_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1299    struct mbuf *m, struct label *mlabel)
1300{
1301	struct mac_lomac *source, *dest;
1302
1303	source = SLOT(inplabel);
1304	dest = SLOT(mlabel);
1305
1306	lomac_copy_single(source, dest);
1307}
1308
1309static void
1310lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1311    struct inpcb *inp, struct label *inplabel)
1312{
1313	struct mac_lomac *source, *dest;
1314
1315	SOCK_LOCK_ASSERT(so);
1316
1317	source = SLOT(solabel);
1318	dest = SLOT(inplabel);
1319
1320	lomac_copy_single(source, dest);
1321}
1322
1323static void
1324lomac_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1325    struct label *q6label)
1326{
1327	struct mac_lomac *source, *dest;
1328
1329	source = SLOT(mlabel);
1330	dest = SLOT(q6label);
1331
1332	lomac_copy_single(source, dest);
1333}
1334
1335static int
1336lomac_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1337    struct label *q6label)
1338{
1339	struct mac_lomac *a, *b;
1340
1341	a = SLOT(q6label);
1342	b = SLOT(mlabel);
1343
1344	return (lomac_equal_single(a, b));
1345}
1346
1347static void
1348lomac_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1349    struct label *mlabel)
1350{
1351	struct mac_lomac *source, *dest;
1352
1353	source = SLOT(q6label);
1354	dest = SLOT(mlabel);
1355
1356	/* Just use the head, since we require them all to match. */
1357	lomac_copy_single(source, dest);
1358}
1359
1360static void
1361lomac_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1362    struct label *q6label)
1363{
1364
1365	/* NOOP: we only accept matching labels, so no need to update */
1366}
1367
1368static void
1369lomac_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1370    struct label *qlabel)
1371{
1372	struct mac_lomac *source, *dest;
1373
1374	source = SLOT(mlabel);
1375	dest = SLOT(qlabel);
1376
1377	lomac_copy_single(source, dest);
1378}
1379
1380static int
1381lomac_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1382    struct label *qlabel)
1383{
1384	struct mac_lomac *a, *b;
1385
1386	a = SLOT(qlabel);
1387	b = SLOT(mlabel);
1388
1389	return (lomac_equal_single(a, b));
1390}
1391
1392static void
1393lomac_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1394    struct label *mlabel)
1395{
1396	struct mac_lomac *source, *dest;
1397
1398	source = SLOT(qlabel);
1399	dest = SLOT(mlabel);
1400
1401	/* Just use the head, since we require them all to match. */
1402	lomac_copy_single(source, dest);
1403}
1404
1405static void
1406lomac_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1407    struct label *qlabel)
1408{
1409
1410	/* NOOP: we only accept matching labels, so no need to update */
1411}
1412
1413static int
1414lomac_kld_check_load(struct ucred *cred, struct vnode *vp,
1415    struct label *vplabel)
1416{
1417	struct mac_lomac *subj, *obj;
1418
1419	if (!lomac_enabled)
1420		return (0);
1421
1422	subj = SLOT(cred->cr_label);
1423	obj = SLOT(vplabel);
1424
1425	if (lomac_subject_privileged(subj))
1426		return (EPERM);
1427
1428	if (!lomac_high_single(obj))
1429		return (EACCES);
1430
1431	return (0);
1432}
1433
1434static void
1435lomac_mount_create(struct ucred *cred, struct mount *mp,
1436    struct label *mplabel)
1437{
1438	struct mac_lomac *source, *dest;
1439
1440	source = SLOT(cred->cr_label);
1441	dest = SLOT(mplabel);
1442	lomac_copy_single(source, dest);
1443}
1444
1445static void
1446lomac_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1447    struct mbuf *m, struct label *mlabel)
1448{
1449	struct mac_lomac *dest;
1450
1451	dest = SLOT(mlabel);
1452
1453	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1454}
1455
1456static void
1457lomac_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1458    struct mbuf *msend, struct label *msendlabel)
1459{
1460	struct mac_lomac *source, *dest;
1461
1462	source = SLOT(mrecvlabel);
1463	dest = SLOT(msendlabel);
1464
1465	lomac_copy_single(source, dest);
1466}
1467
1468static void
1469lomac_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1470{
1471	struct mac_lomac *dest;
1472
1473	dest = SLOT(mlabel);
1474
1475	/* XXX: where is the label for the firewall really coming from? */
1476	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1477}
1478
1479static void
1480lomac_netinet_fragment(struct mbuf *m, struct label *mlabel,
1481    struct mbuf *frag, struct label *fraglabel)
1482{
1483	struct mac_lomac *source, *dest;
1484
1485	source = SLOT(mlabel);
1486	dest = SLOT(fraglabel);
1487
1488	lomac_copy_single(source, dest);
1489}
1490
1491static void
1492lomac_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1493    struct mbuf *msend, struct label *msendlabel)
1494{
1495	struct mac_lomac *source, *dest;
1496
1497	source = SLOT(mrecvlabel);
1498	dest = SLOT(msendlabel);
1499
1500	lomac_copy_single(source, dest);
1501}
1502
1503static void
1504lomac_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1505    struct mbuf *m, struct label *mlabel)
1506{
1507	struct mac_lomac *dest;
1508
1509	dest = SLOT(mlabel);
1510
1511	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1512}
1513
1514static void
1515lomac_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1516    struct mbuf *m, struct label *mlabel)
1517{
1518	struct mac_lomac *dest;
1519
1520	dest = SLOT(mlabel);
1521
1522	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1523}
1524
1525static int
1526lomac_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1527    struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1528{
1529
1530	if (!lomac_enabled)
1531		return (0);
1532
1533	/* XXX: This will be implemented soon... */
1534
1535	return (0);
1536}
1537
1538static int
1539lomac_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1540    struct label *pplabel)
1541{
1542	struct mac_lomac *subj, *obj;
1543
1544	if (!lomac_enabled)
1545		return (0);
1546
1547	subj = SLOT(cred->cr_label);
1548	obj = SLOT(pplabel);
1549
1550	if (!lomac_dominate_single(obj, subj))
1551		return (maybe_demote(subj, obj, "reading", "pipe", NULL));
1552
1553	return (0);
1554}
1555
1556static int
1557lomac_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1558    struct label *pplabel, struct label *newlabel)
1559{
1560	struct mac_lomac *subj, *obj, *new;
1561	int error;
1562
1563	new = SLOT(newlabel);
1564	subj = SLOT(cred->cr_label);
1565	obj = SLOT(pplabel);
1566
1567	/*
1568	 * If there is a LOMAC label update for a pipe, it must be a single
1569	 * update.
1570	 */
1571	error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1572	if (error)
1573		return (error);
1574
1575	/*
1576	 * To perform a relabel of a pipe (LOMAC label or not), LOMAC must
1577	 * authorize the relabel.
1578	 */
1579	if (!lomac_single_in_range(obj, subj))
1580		return (EPERM);
1581
1582	/*
1583	 * If the LOMAC label is to be changed, authorize as appropriate.
1584	 */
1585	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1586		/*
1587		 * To change the LOMAC label on a pipe, the new pipe label
1588		 * must be in the subject range.
1589		 */
1590		if (!lomac_single_in_range(new, subj))
1591			return (EPERM);
1592
1593		/*
1594		 * To change the LOMAC label on a pipe to be EQUAL, the
1595		 * subject must have appropriate privilege.
1596		 */
1597		if (lomac_contains_equal(new)) {
1598			error = lomac_subject_privileged(subj);
1599			if (error)
1600				return (error);
1601		}
1602	}
1603
1604	return (0);
1605}
1606
1607static int
1608lomac_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1609    struct label *pplabel)
1610{
1611	struct mac_lomac *subj, *obj;
1612
1613	if (!lomac_enabled)
1614		return (0);
1615
1616	subj = SLOT(cred->cr_label);
1617	obj = SLOT(pplabel);
1618
1619	if (!lomac_subject_dominate(subj, obj))
1620		return (EACCES);
1621
1622	return (0);
1623}
1624
1625static void
1626lomac_pipe_create(struct ucred *cred, struct pipepair *pp,
1627    struct label *pplabel)
1628{
1629	struct mac_lomac *source, *dest;
1630
1631	source = SLOT(cred->cr_label);
1632	dest = SLOT(pplabel);
1633
1634	lomac_copy_single(source, dest);
1635}
1636
1637static void
1638lomac_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1639    struct label *pplabel, struct label *newlabel)
1640{
1641	struct mac_lomac *source, *dest;
1642
1643	source = SLOT(newlabel);
1644	dest = SLOT(pplabel);
1645
1646	try_relabel(source, dest);
1647}
1648
1649/*
1650 * Some system privileges are allowed regardless of integrity grade; others
1651 * are allowed only when running with privilege with respect to the LOMAC
1652 * policy as they might otherwise allow bypassing of the integrity policy.
1653 */
1654static int
1655lomac_priv_check(struct ucred *cred, int priv)
1656{
1657	struct mac_lomac *subj;
1658	int error;
1659
1660	if (!lomac_enabled)
1661		return (0);
1662
1663	/*
1664	 * Exempt only specific privileges from the LOMAC integrity policy.
1665	 */
1666	switch (priv) {
1667	case PRIV_KTRACE:
1668	case PRIV_MSGBUF:
1669
1670	/*
1671	 * Allow processes to manipulate basic process audit properties, and
1672	 * to submit audit records.
1673	 */
1674	case PRIV_AUDIT_GETAUDIT:
1675	case PRIV_AUDIT_SETAUDIT:
1676	case PRIV_AUDIT_SUBMIT:
1677
1678	/*
1679	 * Allow processes to manipulate their regular UNIX credentials.
1680	 */
1681	case PRIV_CRED_SETUID:
1682	case PRIV_CRED_SETEUID:
1683	case PRIV_CRED_SETGID:
1684	case PRIV_CRED_SETEGID:
1685	case PRIV_CRED_SETGROUPS:
1686	case PRIV_CRED_SETREUID:
1687	case PRIV_CRED_SETREGID:
1688	case PRIV_CRED_SETRESUID:
1689	case PRIV_CRED_SETRESGID:
1690
1691	/*
1692	 * Allow processes to perform system monitoring.
1693	 */
1694	case PRIV_SEEOTHERGIDS:
1695	case PRIV_SEEOTHERUIDS:
1696		break;
1697
1698	/*
1699	 * Allow access to general process debugging facilities.  We
1700	 * separately control debugging based on MAC label.
1701	 */
1702	case PRIV_DEBUG_DIFFCRED:
1703	case PRIV_DEBUG_SUGID:
1704	case PRIV_DEBUG_UNPRIV:
1705
1706	/*
1707	 * Allow manipulating jails.
1708	 */
1709	case PRIV_JAIL_ATTACH:
1710
1711	/*
1712	 * Allow privilege with respect to the Partition policy, but not the
1713	 * Privs policy.
1714	 */
1715	case PRIV_MAC_PARTITION:
1716
1717	/*
1718	 * Allow privilege with respect to process resource limits and login
1719	 * context.
1720	 */
1721	case PRIV_PROC_LIMIT:
1722	case PRIV_PROC_SETLOGIN:
1723	case PRIV_PROC_SETRLIMIT:
1724
1725	/*
1726	 * Allow System V and POSIX IPC privileges.
1727	 */
1728	case PRIV_IPC_READ:
1729	case PRIV_IPC_WRITE:
1730	case PRIV_IPC_ADMIN:
1731	case PRIV_IPC_MSGSIZE:
1732	case PRIV_MQ_ADMIN:
1733
1734	/*
1735	 * Allow certain scheduler manipulations -- possibly this should be
1736	 * controlled by more fine-grained policy, as potentially low
1737	 * integrity processes can deny CPU to higher integrity ones.
1738	 */
1739	case PRIV_SCHED_DIFFCRED:
1740	case PRIV_SCHED_SETPRIORITY:
1741	case PRIV_SCHED_RTPRIO:
1742	case PRIV_SCHED_SETPOLICY:
1743	case PRIV_SCHED_SET:
1744	case PRIV_SCHED_SETPARAM:
1745
1746	/*
1747	 * More IPC privileges.
1748	 */
1749	case PRIV_SEM_WRITE:
1750
1751	/*
1752	 * Allow signaling privileges subject to integrity policy.
1753	 */
1754	case PRIV_SIGNAL_DIFFCRED:
1755	case PRIV_SIGNAL_SUGID:
1756
1757	/*
1758	 * Allow access to only limited sysctls from lower integrity levels;
1759	 * piggy-back on the Jail definition.
1760	 */
1761	case PRIV_SYSCTL_WRITEJAIL:
1762
1763	/*
1764	 * Allow TTY-based privileges, subject to general device access using
1765	 * labels on TTY device nodes, but not console privilege.
1766	 */
1767	case PRIV_TTY_DRAINWAIT:
1768	case PRIV_TTY_DTRWAIT:
1769	case PRIV_TTY_EXCLUSIVE:
1770	case PRIV_TTY_STI:
1771	case PRIV_TTY_SETA:
1772
1773	/*
1774	 * Grant most VFS privileges, as almost all are in practice bounded
1775	 * by more specific checks using labels.
1776	 */
1777	case PRIV_VFS_READ:
1778	case PRIV_VFS_WRITE:
1779	case PRIV_VFS_ADMIN:
1780	case PRIV_VFS_EXEC:
1781	case PRIV_VFS_LOOKUP:
1782	case PRIV_VFS_CHFLAGS_DEV:
1783	case PRIV_VFS_CHOWN:
1784	case PRIV_VFS_CHROOT:
1785	case PRIV_VFS_RETAINSUGID:
1786	case PRIV_VFS_EXCEEDQUOTA:
1787	case PRIV_VFS_FCHROOT:
1788	case PRIV_VFS_FHOPEN:
1789	case PRIV_VFS_FHSTATFS:
1790	case PRIV_VFS_GENERATION:
1791	case PRIV_VFS_GETFH:
1792	case PRIV_VFS_GETQUOTA:
1793	case PRIV_VFS_LINK:
1794	case PRIV_VFS_MOUNT:
1795	case PRIV_VFS_MOUNT_OWNER:
1796	case PRIV_VFS_MOUNT_PERM:
1797	case PRIV_VFS_MOUNT_SUIDDIR:
1798	case PRIV_VFS_MOUNT_NONUSER:
1799	case PRIV_VFS_SETGID:
1800	case PRIV_VFS_STICKYFILE:
1801	case PRIV_VFS_SYSFLAGS:
1802	case PRIV_VFS_UNMOUNT:
1803
1804	/*
1805	 * Allow VM privileges; it would be nice if these were subject to
1806	 * resource limits.
1807	 */
1808	case PRIV_VM_MADV_PROTECT:
1809	case PRIV_VM_MLOCK:
1810	case PRIV_VM_MUNLOCK:
1811	case PRIV_VM_SWAP_NOQUOTA:
1812	case PRIV_VM_SWAP_NORLIMIT:
1813
1814	/*
1815	 * Allow some but not all network privileges.  In general, dont allow
1816	 * reconfiguring the network stack, just normal use.
1817	 */
1818	case PRIV_NETINET_RESERVEDPORT:
1819	case PRIV_NETINET_RAW:
1820	case PRIV_NETINET_REUSEPORT:
1821		break;
1822
1823	/*
1824	 * All remaining system privileges are allow only if the process
1825	 * holds privilege with respect to the LOMAC policy.
1826	 */
1827	default:
1828		subj = SLOT(cred->cr_label);
1829		error = lomac_subject_privileged(subj);
1830		if (error)
1831			return (error);
1832	}
1833	return (0);
1834}
1835
1836static int
1837lomac_proc_check_debug(struct ucred *cred, struct proc *p)
1838{
1839	struct mac_lomac *subj, *obj;
1840
1841	if (!lomac_enabled)
1842		return (0);
1843
1844	subj = SLOT(cred->cr_label);
1845	obj = SLOT(p->p_ucred->cr_label);
1846
1847	/* XXX: range checks */
1848	if (!lomac_dominate_single(obj, subj))
1849		return (ESRCH);
1850	if (!lomac_subject_dominate(subj, obj))
1851		return (EACCES);
1852
1853	return (0);
1854}
1855
1856static int
1857lomac_proc_check_sched(struct ucred *cred, struct proc *p)
1858{
1859	struct mac_lomac *subj, *obj;
1860
1861	if (!lomac_enabled)
1862		return (0);
1863
1864	subj = SLOT(cred->cr_label);
1865	obj = SLOT(p->p_ucred->cr_label);
1866
1867	/* XXX: range checks */
1868	if (!lomac_dominate_single(obj, subj))
1869		return (ESRCH);
1870	if (!lomac_subject_dominate(subj, obj))
1871		return (EACCES);
1872
1873	return (0);
1874}
1875
1876static int
1877lomac_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1878{
1879	struct mac_lomac *subj, *obj;
1880
1881	if (!lomac_enabled)
1882		return (0);
1883
1884	subj = SLOT(cred->cr_label);
1885	obj = SLOT(p->p_ucred->cr_label);
1886
1887	/* XXX: range checks */
1888	if (!lomac_dominate_single(obj, subj))
1889		return (ESRCH);
1890	if (!lomac_subject_dominate(subj, obj))
1891		return (EACCES);
1892
1893	return (0);
1894}
1895
1896static void
1897lomac_proc_destroy_label(struct label *label)
1898{
1899
1900	mtx_destroy(&PSLOT(label)->mtx);
1901	free(PSLOT(label), M_LOMAC);
1902	PSLOT_SET(label, NULL);
1903}
1904
1905static void
1906lomac_proc_init_label(struct label *label)
1907{
1908
1909	PSLOT_SET(label, malloc(sizeof(struct mac_lomac_proc), M_LOMAC,
1910	    M_ZERO | M_WAITOK));
1911	mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF);
1912}
1913
1914static int
1915lomac_socket_check_deliver(struct socket *so, struct label *solabel,
1916    struct mbuf *m, struct label *mlabel)
1917{
1918	struct mac_lomac *p, *s;
1919	int error;
1920
1921	if (!lomac_enabled)
1922		return (0);
1923
1924	p = SLOT(mlabel);
1925	s = SLOT(solabel);
1926
1927	SOCK_LOCK(so);
1928	error = lomac_equal_single(p, s) ? 0 : EACCES;
1929	SOCK_UNLOCK(so);
1930	return (error);
1931}
1932
1933static int
1934lomac_socket_check_relabel(struct ucred *cred, struct socket *so,
1935    struct label *solabel, struct label *newlabel)
1936{
1937	struct mac_lomac *subj, *obj, *new;
1938	int error;
1939
1940	SOCK_LOCK_ASSERT(so);
1941
1942	new = SLOT(newlabel);
1943	subj = SLOT(cred->cr_label);
1944	obj = SLOT(solabel);
1945
1946	/*
1947	 * If there is a LOMAC label update for the socket, it may be an
1948	 * update of single.
1949	 */
1950	error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1951	if (error)
1952		return (error);
1953
1954	/*
1955	 * To relabel a socket, the old socket single must be in the subject
1956	 * range.
1957	 */
1958	if (!lomac_single_in_range(obj, subj))
1959		return (EPERM);
1960
1961	/*
1962	 * If the LOMAC label is to be changed, authorize as appropriate.
1963	 */
1964	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1965		/*
1966		 * To relabel a socket, the new socket single must be in the
1967		 * subject range.
1968		 */
1969		if (!lomac_single_in_range(new, subj))
1970			return (EPERM);
1971
1972		/*
1973		 * To change the LOMAC label on the socket to contain EQUAL,
1974		 * the subject must have appropriate privilege.
1975		 */
1976		if (lomac_contains_equal(new)) {
1977			error = lomac_subject_privileged(subj);
1978			if (error)
1979				return (error);
1980		}
1981	}
1982
1983	return (0);
1984}
1985
1986static int
1987lomac_socket_check_visible(struct ucred *cred, struct socket *so,
1988    struct label *solabel)
1989{
1990	struct mac_lomac *subj, *obj;
1991
1992	if (!lomac_enabled)
1993		return (0);
1994
1995	subj = SLOT(cred->cr_label);
1996	obj = SLOT(solabel);
1997
1998	SOCK_LOCK(so);
1999	if (!lomac_dominate_single(obj, subj)) {
2000		SOCK_UNLOCK(so);
2001		return (ENOENT);
2002	}
2003	SOCK_UNLOCK(so);
2004
2005	return (0);
2006}
2007
2008static void
2009lomac_socket_create(struct ucred *cred, struct socket *so,
2010    struct label *solabel)
2011{
2012	struct mac_lomac *source, *dest;
2013
2014	source = SLOT(cred->cr_label);
2015	dest = SLOT(solabel);
2016
2017	lomac_copy_single(source, dest);
2018}
2019
2020static void
2021lomac_socket_create_mbuf(struct socket *so, struct label *solabel,
2022    struct mbuf *m, struct label *mlabel)
2023{
2024	struct mac_lomac *source, *dest;
2025
2026	source = SLOT(solabel);
2027	dest = SLOT(mlabel);
2028
2029	SOCK_LOCK(so);
2030	lomac_copy_single(source, dest);
2031	SOCK_UNLOCK(so);
2032}
2033
2034static void
2035lomac_socket_newconn(struct socket *oldso, struct label *oldsolabel,
2036    struct socket *newso, struct label *newsolabel)
2037{
2038	struct mac_lomac source, *dest;
2039
2040	SOCK_LOCK(oldso);
2041	source = *SLOT(oldsolabel);
2042	SOCK_UNLOCK(oldso);
2043
2044	dest = SLOT(newsolabel);
2045
2046	SOCK_LOCK(newso);
2047	lomac_copy_single(&source, dest);
2048	SOCK_UNLOCK(newso);
2049}
2050
2051static void
2052lomac_socket_relabel(struct ucred *cred, struct socket *so,
2053    struct label *solabel, struct label *newlabel)
2054{
2055	struct mac_lomac *source, *dest;
2056
2057	SOCK_LOCK_ASSERT(so);
2058
2059	source = SLOT(newlabel);
2060	dest = SLOT(solabel);
2061
2062	try_relabel(source, dest);
2063}
2064
2065static void
2066lomac_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
2067    struct socket *so, struct label *sopeerlabel)
2068{
2069	struct mac_lomac *source, *dest;
2070
2071	source = SLOT(mlabel);
2072	dest = SLOT(sopeerlabel);
2073
2074	SOCK_LOCK(so);
2075	lomac_copy_single(source, dest);
2076	SOCK_UNLOCK(so);
2077}
2078
2079static void
2080lomac_socketpeer_set_from_socket(struct socket *oldso,
2081    struct label *oldsolabel, struct socket *newso,
2082    struct label *newsopeerlabel)
2083{
2084	struct mac_lomac source, *dest;
2085
2086	SOCK_LOCK(oldso);
2087	source = *SLOT(oldsolabel);
2088	SOCK_UNLOCK(oldso);
2089
2090	dest = SLOT(newsopeerlabel);
2091
2092	SOCK_LOCK(newso);
2093	lomac_copy_single(&source, dest);
2094	SOCK_UNLOCK(newso);
2095}
2096
2097static void
2098lomac_syncache_create(struct label *label, struct inpcb *inp)
2099{
2100	struct mac_lomac *source, *dest;
2101
2102	source = SLOT(inp->inp_label);
2103	dest = SLOT(label);
2104	lomac_copy(source, dest);
2105}
2106
2107static void
2108lomac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
2109    struct label *mlabel)
2110{
2111	struct mac_lomac *source, *dest;
2112
2113	source = SLOT(sc_label);
2114	dest = SLOT(mlabel);
2115	lomac_copy(source, dest);
2116}
2117
2118static int
2119lomac_system_check_acct(struct ucred *cred, struct vnode *vp,
2120    struct label *vplabel)
2121{
2122	struct mac_lomac *subj, *obj;
2123
2124	if (!lomac_enabled)
2125		return (0);
2126
2127	subj = SLOT(cred->cr_label);
2128	obj = SLOT(vplabel);
2129
2130	if (lomac_subject_privileged(subj))
2131		return (EPERM);
2132
2133	if (!lomac_high_single(obj))
2134		return (EACCES);
2135
2136	return (0);
2137}
2138
2139static int
2140lomac_system_check_auditctl(struct ucred *cred, struct vnode *vp,
2141    struct label *vplabel)
2142{
2143	struct mac_lomac *subj, *obj;
2144
2145	if (!lomac_enabled)
2146		return (0);
2147
2148	subj = SLOT(cred->cr_label);
2149	obj = SLOT(vplabel);
2150
2151	if (lomac_subject_privileged(subj))
2152		return (EPERM);
2153
2154	if (!lomac_high_single(obj))
2155		return (EACCES);
2156
2157	return (0);
2158}
2159
2160static int
2161lomac_system_check_swapoff(struct ucred *cred, struct vnode *vp,
2162    struct label *vplabel)
2163{
2164	struct mac_lomac *subj;
2165
2166	if (!lomac_enabled)
2167		return (0);
2168
2169	subj = SLOT(cred->cr_label);
2170
2171	if (lomac_subject_privileged(subj))
2172		return (EPERM);
2173
2174	return (0);
2175}
2176
2177static int
2178lomac_system_check_swapon(struct ucred *cred, struct vnode *vp,
2179    struct label *vplabel)
2180{
2181	struct mac_lomac *subj, *obj;
2182
2183	if (!lomac_enabled)
2184		return (0);
2185
2186	subj = SLOT(cred->cr_label);
2187	obj = SLOT(vplabel);
2188
2189	if (lomac_subject_privileged(subj))
2190		return (EPERM);
2191
2192	if (!lomac_high_single(obj))
2193		return (EACCES);
2194
2195	return (0);
2196}
2197
2198static int
2199lomac_system_check_sysctl(struct ucred *cred, struct sysctl_oid *oidp,
2200    void *arg1, int arg2, struct sysctl_req *req)
2201{
2202	struct mac_lomac *subj;
2203
2204	if (!lomac_enabled)
2205		return (0);
2206
2207	subj = SLOT(cred->cr_label);
2208
2209	/*
2210	 * Treat sysctl variables without CTLFLAG_ANYBODY flag as lomac/high,
2211	 * but also require privilege to change them.
2212	 */
2213	if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) {
2214#ifdef notdef
2215		if (!lomac_subject_dominate_high(subj))
2216			return (EACCES);
2217#endif
2218
2219		if (lomac_subject_privileged(subj))
2220			return (EPERM);
2221	}
2222
2223	return (0);
2224}
2225
2226static void
2227lomac_thread_userret(struct thread *td)
2228{
2229	struct proc *p = td->td_proc;
2230	struct mac_lomac_proc *subj = PSLOT(p->p_label);
2231	struct ucred *newcred, *oldcred;
2232	int dodrop;
2233
2234	mtx_lock(&subj->mtx);
2235	if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
2236		dodrop = 0;
2237		mtx_unlock(&subj->mtx);
2238		newcred = crget();
2239		/*
2240		 * Prevent a lock order reversal in mac_proc_vm_revoke;
2241		 * ideally, the other user of subj->mtx wouldn't be holding
2242		 * Giant.
2243		 */
2244		mtx_lock(&Giant);
2245		PROC_LOCK(p);
2246		mtx_lock(&subj->mtx);
2247		/*
2248		 * Check if we lost the race while allocating the cred.
2249		 */
2250		if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) {
2251			crfree(newcred);
2252			goto out;
2253		}
2254		oldcred = p->p_ucred;
2255		crcopy(newcred, oldcred);
2256		crhold(newcred);
2257		lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label));
2258		proc_set_cred(p, newcred);
2259		crfree(oldcred);
2260		dodrop = 1;
2261	out:
2262		mtx_unlock(&subj->mtx);
2263		PROC_UNLOCK(p);
2264		if (dodrop)
2265			mac_proc_vm_revoke(curthread);
2266		mtx_unlock(&Giant);
2267	} else {
2268		mtx_unlock(&subj->mtx);
2269	}
2270}
2271
2272static int
2273lomac_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2274    struct vnode *vp, struct label *vplabel)
2275{
2276	struct mac_lomac ml_temp, *source, *dest;
2277	int buflen, error;
2278
2279	source = SLOT(mplabel);
2280	dest = SLOT(vplabel);
2281
2282	buflen = sizeof(ml_temp);
2283	bzero(&ml_temp, buflen);
2284
2285	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
2286	    MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&ml_temp, curthread);
2287	if (error == ENOATTR || error == EOPNOTSUPP) {
2288		/* Fall back to the mntlabel. */
2289		lomac_copy_single(source, dest);
2290		return (0);
2291	} else if (error)
2292		return (error);
2293
2294	if (buflen != sizeof(ml_temp)) {
2295		if (buflen != sizeof(ml_temp) - sizeof(ml_temp.ml_auxsingle)) {
2296			printf("lomac_vnode_associate_extattr: bad size %d\n",
2297			    buflen);
2298			return (EPERM);
2299		}
2300		bzero(&ml_temp.ml_auxsingle, sizeof(ml_temp.ml_auxsingle));
2301		buflen = sizeof(ml_temp);
2302		(void)vn_extattr_set(vp, IO_NODELOCKED,
2303		    MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME,
2304		    buflen, (char *)&ml_temp, curthread);
2305	}
2306	if (lomac_valid(&ml_temp) != 0) {
2307		printf("lomac_vnode_associate_extattr: invalid\n");
2308		return (EPERM);
2309	}
2310	if ((ml_temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) !=
2311	    MAC_LOMAC_FLAG_SINGLE) {
2312		printf("lomac_vnode_associate_extattr: not single\n");
2313		return (EPERM);
2314	}
2315
2316	lomac_copy_single(&ml_temp, dest);
2317	return (0);
2318}
2319
2320static void
2321lomac_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2322    struct vnode *vp, struct label *vplabel)
2323{
2324	struct mac_lomac *source, *dest;
2325
2326	source = SLOT(mplabel);
2327	dest = SLOT(vplabel);
2328
2329	lomac_copy_single(source, dest);
2330}
2331
2332static int
2333lomac_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2334    struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2335{
2336	struct mac_lomac *subj, *obj;
2337
2338	if (!lomac_enabled)
2339		return (0);
2340
2341	subj = SLOT(cred->cr_label);
2342	obj = SLOT(dvplabel);
2343
2344	if (!lomac_subject_dominate(subj, obj))
2345		return (EACCES);
2346	if (obj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2347	    !lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle))
2348		return (EACCES);
2349
2350	return (0);
2351}
2352
2353static int
2354lomac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2355    struct label *vplabel, acl_type_t type)
2356{
2357	struct mac_lomac *subj, *obj;
2358
2359	if (!lomac_enabled)
2360		return (0);
2361
2362	subj = SLOT(cred->cr_label);
2363	obj = SLOT(vplabel);
2364
2365	if (!lomac_subject_dominate(subj, obj))
2366		return (EACCES);
2367
2368	return (0);
2369}
2370
2371static int
2372lomac_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2373    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2374    struct componentname *cnp)
2375{
2376	struct mac_lomac *subj, *obj;
2377
2378	if (!lomac_enabled)
2379		return (0);
2380
2381	subj = SLOT(cred->cr_label);
2382	obj = SLOT(dvplabel);
2383
2384	if (!lomac_subject_dominate(subj, obj))
2385		return (EACCES);
2386
2387	obj = SLOT(vplabel);
2388
2389	if (!lomac_subject_dominate(subj, obj))
2390		return (EACCES);
2391
2392	return (0);
2393}
2394
2395static int
2396lomac_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2397    struct label *vplabel, int prot, int flags)
2398{
2399	struct mac_lomac *subj, *obj;
2400
2401	/*
2402	 * Rely on the use of open()-time protections to handle
2403	 * non-revocation cases.
2404	 */
2405	if (!lomac_enabled)
2406		return (0);
2407
2408	subj = SLOT(cred->cr_label);
2409	obj = SLOT(vplabel);
2410
2411	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2412		if (!lomac_subject_dominate(subj, obj))
2413			return (EACCES);
2414	}
2415	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2416		if (!lomac_dominate_single(obj, subj))
2417			return (maybe_demote(subj, obj, "mapping", "file", vp));
2418	}
2419
2420	return (0);
2421}
2422
2423static void
2424lomac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp,
2425    struct label *vplabel, /* XXX vm_prot_t */ int *prot)
2426{
2427	struct mac_lomac *subj, *obj;
2428
2429	/*
2430	 * Rely on the use of open()-time protections to handle
2431	 * non-revocation cases.
2432	 */
2433	if (!lomac_enabled || !revocation_enabled)
2434		return;
2435
2436	subj = SLOT(cred->cr_label);
2437	obj = SLOT(vplabel);
2438
2439	if (!lomac_subject_dominate(subj, obj))
2440		*prot &= ~VM_PROT_WRITE;
2441}
2442
2443static int
2444lomac_vnode_check_open(struct ucred *cred, struct vnode *vp,
2445    struct label *vplabel, accmode_t accmode)
2446{
2447	struct mac_lomac *subj, *obj;
2448
2449	if (!lomac_enabled)
2450		return (0);
2451
2452	subj = SLOT(cred->cr_label);
2453	obj = SLOT(vplabel);
2454
2455	/* XXX privilege override for admin? */
2456	if (accmode & VMODIFY_PERMS) {
2457		if (!lomac_subject_dominate(subj, obj))
2458			return (EACCES);
2459	}
2460
2461	return (0);
2462}
2463
2464static int
2465lomac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2466    struct vnode *vp, struct label *vplabel)
2467{
2468	struct mac_lomac *subj, *obj;
2469
2470	if (!lomac_enabled || !revocation_enabled)
2471		return (0);
2472
2473	subj = SLOT(active_cred->cr_label);
2474	obj = SLOT(vplabel);
2475
2476	if (!lomac_dominate_single(obj, subj))
2477		return (maybe_demote(subj, obj, "reading", "file", vp));
2478
2479	return (0);
2480}
2481
2482static int
2483lomac_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2484    struct label *vplabel, struct label *newlabel)
2485{
2486	struct mac_lomac *old, *new, *subj;
2487	int error;
2488
2489	old = SLOT(vplabel);
2490	new = SLOT(newlabel);
2491	subj = SLOT(cred->cr_label);
2492
2493	/*
2494	 * If there is a LOMAC label update for the vnode, it must be a
2495	 * single label, with an optional explicit auxiliary single.
2496	 */
2497	error = lomac_atmostflags(new,
2498	    MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX);
2499	if (error)
2500		return (error);
2501
2502	/*
2503	 * To perform a relabel of the vnode (LOMAC label or not), LOMAC must
2504	 * authorize the relabel.
2505	 */
2506	if (!lomac_single_in_range(old, subj))
2507		return (EPERM);
2508
2509	/*
2510	 * If the LOMAC label is to be changed, authorize as appropriate.
2511	 */
2512	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2513		/*
2514		 * To change the LOMAC label on a vnode, the new vnode label
2515		 * must be in the subject range.
2516		 */
2517		if (!lomac_single_in_range(new, subj))
2518			return (EPERM);
2519
2520		/*
2521		 * To change the LOMAC label on the vnode to be EQUAL, the
2522		 * subject must have appropriate privilege.
2523		 */
2524		if (lomac_contains_equal(new)) {
2525			error = lomac_subject_privileged(subj);
2526			if (error)
2527				return (error);
2528		}
2529	}
2530	if (new->ml_flags & MAC_LOMAC_FLAG_AUX) {
2531		/*
2532		 * Fill in the missing parts from the previous label.
2533		 */
2534		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2535			lomac_copy_single(subj, new);
2536
2537		/*
2538		 * To change the auxiliary LOMAC label on a vnode, the new
2539		 * vnode label must be in the subject range.
2540		 */
2541		if (!lomac_auxsingle_in_range(new, subj))
2542			return (EPERM);
2543
2544		/*
2545		 * To change the auxiliary LOMAC label on the vnode to be
2546		 * EQUAL, the subject must have appropriate privilege.
2547		 */
2548		if (lomac_contains_equal(new)) {
2549			error = lomac_subject_privileged(subj);
2550			if (error)
2551				return (error);
2552		}
2553	}
2554
2555	return (0);
2556}
2557
2558static int
2559lomac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2560    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2561    struct componentname *cnp)
2562{
2563	struct mac_lomac *subj, *obj;
2564
2565	if (!lomac_enabled)
2566		return (0);
2567
2568	subj = SLOT(cred->cr_label);
2569	obj = SLOT(dvplabel);
2570
2571	if (!lomac_subject_dominate(subj, obj))
2572		return (EACCES);
2573
2574	obj = SLOT(vplabel);
2575
2576	if (!lomac_subject_dominate(subj, obj))
2577		return (EACCES);
2578
2579	return (0);
2580}
2581
2582static int
2583lomac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2584    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2585    int samedir, struct componentname *cnp)
2586{
2587	struct mac_lomac *subj, *obj;
2588
2589	if (!lomac_enabled)
2590		return (0);
2591
2592	subj = SLOT(cred->cr_label);
2593	obj = SLOT(dvplabel);
2594
2595	if (!lomac_subject_dominate(subj, obj))
2596		return (EACCES);
2597
2598	if (vp != NULL) {
2599		obj = SLOT(vplabel);
2600
2601		if (!lomac_subject_dominate(subj, obj))
2602			return (EACCES);
2603	}
2604
2605	return (0);
2606}
2607
2608static int
2609lomac_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2610    struct label *vplabel)
2611{
2612	struct mac_lomac *subj, *obj;
2613
2614	if (!lomac_enabled)
2615		return (0);
2616
2617	subj = SLOT(cred->cr_label);
2618	obj = SLOT(vplabel);
2619
2620	if (!lomac_subject_dominate(subj, obj))
2621		return (EACCES);
2622
2623	return (0);
2624}
2625
2626static int
2627lomac_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2628    struct label *vplabel, acl_type_t type, struct acl *acl)
2629{
2630	struct mac_lomac *subj, *obj;
2631
2632	if (!lomac_enabled)
2633		return (0);
2634
2635	subj = SLOT(cred->cr_label);
2636	obj = SLOT(vplabel);
2637
2638	if (!lomac_subject_dominate(subj, obj))
2639		return (EACCES);
2640
2641	return (0);
2642}
2643
2644static int
2645lomac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2646    struct label *vplabel, int attrnamespace, const char *name)
2647{
2648	struct mac_lomac *subj, *obj;
2649
2650	if (!lomac_enabled)
2651		return (0);
2652
2653	subj = SLOT(cred->cr_label);
2654	obj = SLOT(vplabel);
2655
2656	if (!lomac_subject_dominate(subj, obj))
2657		return (EACCES);
2658
2659	/* XXX: protect the MAC EA in a special way? */
2660
2661	return (0);
2662}
2663
2664static int
2665lomac_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
2666    struct label *vplabel, u_long flags)
2667{
2668	struct mac_lomac *subj, *obj;
2669
2670	if (!lomac_enabled)
2671		return (0);
2672
2673	subj = SLOT(cred->cr_label);
2674	obj = SLOT(vplabel);
2675
2676	if (!lomac_subject_dominate(subj, obj))
2677		return (EACCES);
2678
2679	return (0);
2680}
2681
2682static int
2683lomac_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
2684    struct label *vplabel, mode_t mode)
2685{
2686	struct mac_lomac *subj, *obj;
2687
2688	if (!lomac_enabled)
2689		return (0);
2690
2691	subj = SLOT(cred->cr_label);
2692	obj = SLOT(vplabel);
2693
2694	if (!lomac_subject_dominate(subj, obj))
2695		return (EACCES);
2696
2697	return (0);
2698}
2699
2700static int
2701lomac_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
2702    struct label *vplabel, uid_t uid, gid_t gid)
2703{
2704	struct mac_lomac *subj, *obj;
2705
2706	if (!lomac_enabled)
2707		return (0);
2708
2709	subj = SLOT(cred->cr_label);
2710	obj = SLOT(vplabel);
2711
2712	if (!lomac_subject_dominate(subj, obj))
2713		return (EACCES);
2714
2715	return (0);
2716}
2717
2718static int
2719lomac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
2720    struct label *vplabel, struct timespec atime, struct timespec mtime)
2721{
2722	struct mac_lomac *subj, *obj;
2723
2724	if (!lomac_enabled)
2725		return (0);
2726
2727	subj = SLOT(cred->cr_label);
2728	obj = SLOT(vplabel);
2729
2730	if (!lomac_subject_dominate(subj, obj))
2731		return (EACCES);
2732
2733	return (0);
2734}
2735
2736static int
2737lomac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
2738    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2739    struct componentname *cnp)
2740{
2741	struct mac_lomac *subj, *obj;
2742
2743	if (!lomac_enabled)
2744		return (0);
2745
2746	subj = SLOT(cred->cr_label);
2747	obj = SLOT(dvplabel);
2748
2749	if (!lomac_subject_dominate(subj, obj))
2750		return (EACCES);
2751
2752	obj = SLOT(vplabel);
2753
2754	if (!lomac_subject_dominate(subj, obj))
2755		return (EACCES);
2756
2757	return (0);
2758}
2759
2760static int
2761lomac_vnode_check_write(struct ucred *active_cred,
2762    struct ucred *file_cred, struct vnode *vp, struct label *vplabel)
2763{
2764	struct mac_lomac *subj, *obj;
2765
2766	if (!lomac_enabled || !revocation_enabled)
2767		return (0);
2768
2769	subj = SLOT(active_cred->cr_label);
2770	obj = SLOT(vplabel);
2771
2772	if (!lomac_subject_dominate(subj, obj))
2773		return (EACCES);
2774
2775	return (0);
2776}
2777
2778static int
2779lomac_vnode_create_extattr(struct ucred *cred, struct mount *mp,
2780    struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
2781    struct vnode *vp, struct label *vplabel, struct componentname *cnp)
2782{
2783	struct mac_lomac *source, *dest, *dir, temp;
2784	size_t buflen;
2785	int error;
2786
2787	buflen = sizeof(temp);
2788	bzero(&temp, buflen);
2789
2790	source = SLOT(cred->cr_label);
2791	dest = SLOT(vplabel);
2792	dir = SLOT(dvplabel);
2793	if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) {
2794		lomac_copy_auxsingle(dir, &temp);
2795		lomac_set_single(&temp, dir->ml_auxsingle.mle_type,
2796		    dir->ml_auxsingle.mle_grade);
2797	} else {
2798		lomac_copy_single(source, &temp);
2799	}
2800
2801	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
2802	    MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
2803	if (error == 0)
2804		lomac_copy(&temp, dest);
2805	return (error);
2806}
2807
2808static void
2809lomac_vnode_execve_transition(struct ucred *old, struct ucred *new,
2810    struct vnode *vp, struct label *vplabel, struct label *interpvplabel,
2811    struct image_params *imgp, struct label *execlabel)
2812{
2813	struct mac_lomac *source, *dest, *obj, *robj;
2814
2815	source = SLOT(old->cr_label);
2816	dest = SLOT(new->cr_label);
2817	obj = SLOT(vplabel);
2818	robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj;
2819
2820	lomac_copy(source, dest);
2821	/*
2822	 * If there's an auxiliary label on the real object, respect it and
2823	 * assume that this level should be assumed immediately if a higher
2824	 * level is currently in place.
2825	 */
2826	if (robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2827	    !lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single)
2828	    && lomac_auxsingle_in_range(robj, dest))
2829		lomac_set_single(dest, robj->ml_auxsingle.mle_type,
2830		    robj->ml_auxsingle.mle_grade);
2831	/*
2832	 * Restructuring to use the execve transitioning mechanism instead of
2833	 * the normal demotion mechanism here would be difficult, so just
2834	 * copy the label over and perform standard demotion.  This is also
2835	 * non-optimal because it will result in the intermediate label "new"
2836	 * being created and immediately recycled.
2837	 */
2838	if (lomac_enabled && revocation_enabled &&
2839	    !lomac_dominate_single(obj, source))
2840		(void)maybe_demote(source, obj, "executing", "file", vp);
2841}
2842
2843static int
2844lomac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp,
2845    struct label *vplabel, struct label *interpvplabel,
2846    struct image_params *imgp, struct label *execlabel)
2847{
2848	struct mac_lomac *subj, *obj, *robj;
2849
2850	if (!lomac_enabled || !revocation_enabled)
2851		return (0);
2852
2853	subj = SLOT(old->cr_label);
2854	obj = SLOT(vplabel);
2855	robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj;
2856
2857	return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2858	    !lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single)
2859	    && lomac_auxsingle_in_range(robj, subj)) ||
2860	    !lomac_dominate_single(obj, subj));
2861}
2862
2863static void
2864lomac_vnode_relabel(struct ucred *cred, struct vnode *vp,
2865    struct label *vplabel, struct label *newlabel)
2866{
2867	struct mac_lomac *source, *dest;
2868
2869	source = SLOT(newlabel);
2870	dest = SLOT(vplabel);
2871
2872	try_relabel(source, dest);
2873}
2874
2875static int
2876lomac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
2877    struct label *vplabel, struct label *intlabel)
2878{
2879	struct mac_lomac *source, temp;
2880	size_t buflen;
2881	int error;
2882
2883	buflen = sizeof(temp);
2884	bzero(&temp, buflen);
2885
2886	source = SLOT(intlabel);
2887	if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2888		return (0);
2889
2890	lomac_copy_single(source, &temp);
2891	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
2892	    MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
2893	return (error);
2894}
2895
2896static struct mac_policy_ops lomac_ops =
2897{
2898	.mpo_init = lomac_init,
2899
2900	.mpo_bpfdesc_check_receive = lomac_bpfdesc_check_receive,
2901	.mpo_bpfdesc_create = lomac_bpfdesc_create,
2902	.mpo_bpfdesc_create_mbuf = lomac_bpfdesc_create_mbuf,
2903	.mpo_bpfdesc_destroy_label = lomac_destroy_label,
2904	.mpo_bpfdesc_init_label = lomac_init_label,
2905
2906	.mpo_cred_check_relabel = lomac_cred_check_relabel,
2907	.mpo_cred_check_visible = lomac_cred_check_visible,
2908	.mpo_cred_copy_label = lomac_copy_label,
2909	.mpo_cred_create_swapper = lomac_cred_create_swapper,
2910	.mpo_cred_create_init = lomac_cred_create_init,
2911	.mpo_cred_destroy_label = lomac_destroy_label,
2912	.mpo_cred_externalize_label = lomac_externalize_label,
2913	.mpo_cred_init_label = lomac_init_label,
2914	.mpo_cred_internalize_label = lomac_internalize_label,
2915	.mpo_cred_relabel = lomac_cred_relabel,
2916
2917	.mpo_devfs_create_device = lomac_devfs_create_device,
2918	.mpo_devfs_create_directory = lomac_devfs_create_directory,
2919	.mpo_devfs_create_symlink = lomac_devfs_create_symlink,
2920	.mpo_devfs_destroy_label = lomac_destroy_label,
2921	.mpo_devfs_init_label = lomac_init_label,
2922	.mpo_devfs_update = lomac_devfs_update,
2923	.mpo_devfs_vnode_associate = lomac_devfs_vnode_associate,
2924
2925	.mpo_ifnet_check_relabel = lomac_ifnet_check_relabel,
2926	.mpo_ifnet_check_transmit = lomac_ifnet_check_transmit,
2927	.mpo_ifnet_copy_label = lomac_copy_label,
2928	.mpo_ifnet_create = lomac_ifnet_create,
2929	.mpo_ifnet_create_mbuf = lomac_ifnet_create_mbuf,
2930	.mpo_ifnet_destroy_label = lomac_destroy_label,
2931	.mpo_ifnet_externalize_label = lomac_externalize_label,
2932	.mpo_ifnet_init_label = lomac_init_label,
2933	.mpo_ifnet_internalize_label = lomac_internalize_label,
2934	.mpo_ifnet_relabel = lomac_ifnet_relabel,
2935
2936	.mpo_syncache_create = lomac_syncache_create,
2937	.mpo_syncache_destroy_label = lomac_destroy_label,
2938	.mpo_syncache_init_label = lomac_init_label_waitcheck,
2939
2940	.mpo_inpcb_check_deliver = lomac_inpcb_check_deliver,
2941	.mpo_inpcb_check_visible = lomac_inpcb_check_visible,
2942	.mpo_inpcb_create = lomac_inpcb_create,
2943	.mpo_inpcb_create_mbuf = lomac_inpcb_create_mbuf,
2944	.mpo_inpcb_destroy_label = lomac_destroy_label,
2945	.mpo_inpcb_init_label = lomac_init_label_waitcheck,
2946	.mpo_inpcb_sosetlabel = lomac_inpcb_sosetlabel,
2947
2948	.mpo_ip6q_create = lomac_ip6q_create,
2949	.mpo_ip6q_destroy_label = lomac_destroy_label,
2950	.mpo_ip6q_init_label = lomac_init_label_waitcheck,
2951	.mpo_ip6q_match = lomac_ip6q_match,
2952	.mpo_ip6q_reassemble = lomac_ip6q_reassemble,
2953	.mpo_ip6q_update = lomac_ip6q_update,
2954
2955	.mpo_ipq_create = lomac_ipq_create,
2956	.mpo_ipq_destroy_label = lomac_destroy_label,
2957	.mpo_ipq_init_label = lomac_init_label_waitcheck,
2958	.mpo_ipq_match = lomac_ipq_match,
2959	.mpo_ipq_reassemble = lomac_ipq_reassemble,
2960	.mpo_ipq_update = lomac_ipq_update,
2961
2962	.mpo_kld_check_load = lomac_kld_check_load,
2963
2964	.mpo_mbuf_copy_label = lomac_copy_label,
2965	.mpo_mbuf_destroy_label = lomac_destroy_label,
2966	.mpo_mbuf_init_label = lomac_init_label_waitcheck,
2967
2968	.mpo_mount_create = lomac_mount_create,
2969	.mpo_mount_destroy_label = lomac_destroy_label,
2970	.mpo_mount_init_label = lomac_init_label,
2971
2972	.mpo_netinet_arp_send = lomac_netinet_arp_send,
2973	.mpo_netinet_firewall_reply = lomac_netinet_firewall_reply,
2974	.mpo_netinet_firewall_send = lomac_netinet_firewall_send,
2975	.mpo_netinet_fragment = lomac_netinet_fragment,
2976	.mpo_netinet_icmp_reply = lomac_netinet_icmp_reply,
2977	.mpo_netinet_igmp_send = lomac_netinet_igmp_send,
2978
2979	.mpo_netinet6_nd6_send = lomac_netinet6_nd6_send,
2980
2981	.mpo_pipe_check_ioctl = lomac_pipe_check_ioctl,
2982	.mpo_pipe_check_read = lomac_pipe_check_read,
2983	.mpo_pipe_check_relabel = lomac_pipe_check_relabel,
2984	.mpo_pipe_check_write = lomac_pipe_check_write,
2985	.mpo_pipe_copy_label = lomac_copy_label,
2986	.mpo_pipe_create = lomac_pipe_create,
2987	.mpo_pipe_destroy_label = lomac_destroy_label,
2988	.mpo_pipe_externalize_label = lomac_externalize_label,
2989	.mpo_pipe_init_label = lomac_init_label,
2990	.mpo_pipe_internalize_label = lomac_internalize_label,
2991	.mpo_pipe_relabel = lomac_pipe_relabel,
2992
2993	.mpo_priv_check = lomac_priv_check,
2994
2995	.mpo_proc_check_debug = lomac_proc_check_debug,
2996	.mpo_proc_check_sched = lomac_proc_check_sched,
2997	.mpo_proc_check_signal = lomac_proc_check_signal,
2998	.mpo_proc_destroy_label = lomac_proc_destroy_label,
2999	.mpo_proc_init_label = lomac_proc_init_label,
3000
3001	.mpo_socket_check_deliver = lomac_socket_check_deliver,
3002	.mpo_socket_check_relabel = lomac_socket_check_relabel,
3003	.mpo_socket_check_visible = lomac_socket_check_visible,
3004	.mpo_socket_copy_label = lomac_copy_label,
3005	.mpo_socket_create = lomac_socket_create,
3006	.mpo_socket_create_mbuf = lomac_socket_create_mbuf,
3007	.mpo_socket_destroy_label = lomac_destroy_label,
3008	.mpo_socket_externalize_label = lomac_externalize_label,
3009	.mpo_socket_init_label = lomac_init_label_waitcheck,
3010	.mpo_socket_internalize_label = lomac_internalize_label,
3011	.mpo_socket_newconn = lomac_socket_newconn,
3012	.mpo_socket_relabel = lomac_socket_relabel,
3013
3014	.mpo_socketpeer_destroy_label = lomac_destroy_label,
3015	.mpo_socketpeer_externalize_label = lomac_externalize_label,
3016	.mpo_socketpeer_init_label = lomac_init_label_waitcheck,
3017	.mpo_socketpeer_set_from_mbuf = lomac_socketpeer_set_from_mbuf,
3018	.mpo_socketpeer_set_from_socket = lomac_socketpeer_set_from_socket,
3019
3020	.mpo_syncache_create_mbuf = lomac_syncache_create_mbuf,
3021
3022	.mpo_system_check_acct = lomac_system_check_acct,
3023	.mpo_system_check_auditctl = lomac_system_check_auditctl,
3024	.mpo_system_check_swapoff = lomac_system_check_swapoff,
3025	.mpo_system_check_swapon = lomac_system_check_swapon,
3026	.mpo_system_check_sysctl = lomac_system_check_sysctl,
3027
3028	.mpo_thread_userret = lomac_thread_userret,
3029
3030	.mpo_vnode_associate_extattr = lomac_vnode_associate_extattr,
3031	.mpo_vnode_associate_singlelabel = lomac_vnode_associate_singlelabel,
3032	.mpo_vnode_check_access = lomac_vnode_check_open,
3033	.mpo_vnode_check_create = lomac_vnode_check_create,
3034	.mpo_vnode_check_deleteacl = lomac_vnode_check_deleteacl,
3035	.mpo_vnode_check_link = lomac_vnode_check_link,
3036	.mpo_vnode_check_mmap = lomac_vnode_check_mmap,
3037	.mpo_vnode_check_mmap_downgrade = lomac_vnode_check_mmap_downgrade,
3038	.mpo_vnode_check_open = lomac_vnode_check_open,
3039	.mpo_vnode_check_read = lomac_vnode_check_read,
3040	.mpo_vnode_check_relabel = lomac_vnode_check_relabel,
3041	.mpo_vnode_check_rename_from = lomac_vnode_check_rename_from,
3042	.mpo_vnode_check_rename_to = lomac_vnode_check_rename_to,
3043	.mpo_vnode_check_revoke = lomac_vnode_check_revoke,
3044	.mpo_vnode_check_setacl = lomac_vnode_check_setacl,
3045	.mpo_vnode_check_setextattr = lomac_vnode_check_setextattr,
3046	.mpo_vnode_check_setflags = lomac_vnode_check_setflags,
3047	.mpo_vnode_check_setmode = lomac_vnode_check_setmode,
3048	.mpo_vnode_check_setowner = lomac_vnode_check_setowner,
3049	.mpo_vnode_check_setutimes = lomac_vnode_check_setutimes,
3050	.mpo_vnode_check_unlink = lomac_vnode_check_unlink,
3051	.mpo_vnode_check_write = lomac_vnode_check_write,
3052	.mpo_vnode_copy_label = lomac_copy_label,
3053	.mpo_vnode_create_extattr = lomac_vnode_create_extattr,
3054	.mpo_vnode_destroy_label = lomac_destroy_label,
3055	.mpo_vnode_execve_transition = lomac_vnode_execve_transition,
3056	.mpo_vnode_execve_will_transition = lomac_vnode_execve_will_transition,
3057	.mpo_vnode_externalize_label = lomac_externalize_label,
3058	.mpo_vnode_init_label = lomac_init_label,
3059	.mpo_vnode_internalize_label = lomac_internalize_label,
3060	.mpo_vnode_relabel = lomac_vnode_relabel,
3061	.mpo_vnode_setlabel_extattr = lomac_vnode_setlabel_extattr,
3062};
3063
3064MAC_POLICY_SET(&lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC",
3065    MPC_LOADTIME_FLAG_NOTLATE, &lomac_slot);
3066