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