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