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