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