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