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