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