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