]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/security/mac_biba/mac_biba.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / security / mac_biba / mac_biba.c
1 /*-
2  * Copyright (c) 1999-2002, 2007 Robert N. M. Watson
3  * Copyright (c) 2001-2005 McAfee, 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 McAfee
9  * Research, the Security Research Division of McAfee, 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  * Biba fixed label mandatory integrity policy.
41  */
42
43 #include <sys/param.h>
44 #include <sys/conf.h>
45 #include <sys/extattr.h>
46 #include <sys/kernel.h>
47 #include <sys/ksem.h>
48 #include <sys/malloc.h>
49 #include <sys/mman.h>
50 #include <sys/mount.h>
51 #include <sys/priv.h>
52 #include <sys/proc.h>
53 #include <sys/sbuf.h>
54 #include <sys/systm.h>
55 #include <sys/sysproto.h>
56 #include <sys/sysent.h>
57 #include <sys/systm.h>
58 #include <sys/vnode.h>
59 #include <sys/file.h>
60 #include <sys/socket.h>
61 #include <sys/socketvar.h>
62 #include <sys/pipe.h>
63 #include <sys/sx.h>
64 #include <sys/sysctl.h>
65 #include <sys/msg.h>
66 #include <sys/sem.h>
67 #include <sys/shm.h>
68
69 #include <fs/devfs/devfs.h>
70
71 #include <net/bpfdesc.h>
72 #include <net/if.h>
73 #include <net/if_types.h>
74 #include <net/if_var.h>
75
76 #include <netinet/in.h>
77 #include <netinet/in_pcb.h>
78 #include <netinet/ip_var.h>
79
80 #include <vm/uma.h>
81 #include <vm/vm.h>
82
83 #include <security/mac/mac_policy.h>
84 #include <security/mac_biba/mac_biba.h>
85
86 SYSCTL_DECL(_security_mac);
87
88 SYSCTL_NODE(_security_mac, OID_AUTO, biba, CTLFLAG_RW, 0,
89     "TrustedBSD mac_biba policy controls");
90
91 static int      biba_label_size = sizeof(struct mac_biba);
92 SYSCTL_INT(_security_mac_biba, OID_AUTO, label_size, CTLFLAG_RD,
93     &biba_label_size, 0, "Size of struct mac_biba");
94
95 static int      biba_enabled = 1;
96 SYSCTL_INT(_security_mac_biba, OID_AUTO, enabled, CTLFLAG_RW, &biba_enabled,
97     0, "Enforce MAC/Biba policy");
98 TUNABLE_INT("security.mac.biba.enabled", &biba_enabled);
99
100 static int      destroyed_not_inited;
101 SYSCTL_INT(_security_mac_biba, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
102     &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
103
104 static int      trust_all_interfaces = 0;
105 SYSCTL_INT(_security_mac_biba, OID_AUTO, trust_all_interfaces, CTLFLAG_RD,
106     &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/Biba");
107 TUNABLE_INT("security.mac.biba.trust_all_interfaces", &trust_all_interfaces);
108
109 static char     trusted_interfaces[128];
110 SYSCTL_STRING(_security_mac_biba, OID_AUTO, trusted_interfaces, CTLFLAG_RD,
111     trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/Biba");
112 TUNABLE_STR("security.mac.biba.trusted_interfaces", trusted_interfaces,
113     sizeof(trusted_interfaces));
114
115 static int      max_compartments = MAC_BIBA_MAX_COMPARTMENTS;
116 SYSCTL_INT(_security_mac_biba, OID_AUTO, max_compartments, CTLFLAG_RD,
117     &max_compartments, 0, "Maximum supported compartments");
118
119 static int      ptys_equal = 0;
120 SYSCTL_INT(_security_mac_biba, OID_AUTO, ptys_equal, CTLFLAG_RW, &ptys_equal,
121     0, "Label pty devices as biba/equal on create");
122 TUNABLE_INT("security.mac.biba.ptys_equal", &ptys_equal);
123
124 static int      interfaces_equal;
125 SYSCTL_INT(_security_mac_biba, OID_AUTO, interfaces_equal, CTLFLAG_RW,
126     &interfaces_equal, 0, "Label network interfaces as biba/equal on create");
127 TUNABLE_INT("security.mac.biba.interfaces_equal", &interfaces_equal);
128
129 static int      revocation_enabled = 0;
130 SYSCTL_INT(_security_mac_biba, OID_AUTO, revocation_enabled, CTLFLAG_RW,
131     &revocation_enabled, 0, "Revoke access to objects on relabel");
132 TUNABLE_INT("security.mac.biba.revocation_enabled", &revocation_enabled);
133
134 static int      biba_slot;
135 #define SLOT(l) ((struct mac_biba *)mac_label_get((l), biba_slot))
136 #define SLOT_SET(l, val) mac_label_set((l), biba_slot, (uintptr_t)(val))
137
138 static uma_zone_t       zone_biba;
139
140 static __inline int
141 biba_bit_set_empty(u_char *set) {
142         int i;
143
144         for (i = 0; i < MAC_BIBA_MAX_COMPARTMENTS >> 3; i++)
145                 if (set[i] != 0)
146                         return (0);
147         return (1);
148 }
149
150 static struct mac_biba *
151 biba_alloc(int flag)
152 {
153
154         return (uma_zalloc(zone_biba, flag | M_ZERO));
155 }
156
157 static void
158 biba_free(struct mac_biba *mb)
159 {
160
161         if (mb != NULL)
162                 uma_zfree(zone_biba, mb);
163         else
164                 atomic_add_int(&destroyed_not_inited, 1);
165 }
166
167 static int
168 biba_atmostflags(struct mac_biba *mb, int flags)
169 {
170
171         if ((mb->mb_flags & flags) != mb->mb_flags)
172                 return (EINVAL);
173         return (0);
174 }
175
176 static int
177 biba_dominate_element(struct mac_biba_element *a, struct mac_biba_element *b)
178 {
179         int bit;
180
181         switch (a->mbe_type) {
182         case MAC_BIBA_TYPE_EQUAL:
183         case MAC_BIBA_TYPE_HIGH:
184                 return (1);
185
186         case MAC_BIBA_TYPE_LOW:
187                 switch (b->mbe_type) {
188                 case MAC_BIBA_TYPE_GRADE:
189                 case MAC_BIBA_TYPE_HIGH:
190                         return (0);
191
192                 case MAC_BIBA_TYPE_EQUAL:
193                 case MAC_BIBA_TYPE_LOW:
194                         return (1);
195
196                 default:
197                         panic("biba_dominate_element: b->mbe_type invalid");
198                 }
199
200         case MAC_BIBA_TYPE_GRADE:
201                 switch (b->mbe_type) {
202                 case MAC_BIBA_TYPE_EQUAL:
203                 case MAC_BIBA_TYPE_LOW:
204                         return (1);
205
206                 case MAC_BIBA_TYPE_HIGH:
207                         return (0);
208
209                 case MAC_BIBA_TYPE_GRADE:
210                         for (bit = 1; bit <= MAC_BIBA_MAX_COMPARTMENTS; bit++)
211                                 if (!MAC_BIBA_BIT_TEST(bit,
212                                     a->mbe_compartments) &&
213                                     MAC_BIBA_BIT_TEST(bit, b->mbe_compartments))
214                                         return (0);
215                         return (a->mbe_grade >= b->mbe_grade);
216
217                 default:
218                         panic("biba_dominate_element: b->mbe_type invalid");
219                 }
220
221         default:
222                 panic("biba_dominate_element: a->mbe_type invalid");
223         }
224
225         return (0);
226 }
227
228 static int
229 biba_subject_dominate_high(struct mac_biba *mb)
230 {
231         struct mac_biba_element *element;
232
233         KASSERT((mb->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
234             ("biba_effective_in_range: mb not effective"));
235         element = &mb->mb_effective;
236
237         return (element->mbe_type == MAC_BIBA_TYPE_EQUAL ||
238             element->mbe_type == MAC_BIBA_TYPE_HIGH);
239 }
240
241 static int
242 biba_range_in_range(struct mac_biba *rangea, struct mac_biba *rangeb)
243 {
244
245         return (biba_dominate_element(&rangeb->mb_rangehigh,
246             &rangea->mb_rangehigh) &&
247             biba_dominate_element(&rangea->mb_rangelow,
248             &rangeb->mb_rangelow));
249 }
250
251 static int
252 biba_effective_in_range(struct mac_biba *effective, struct mac_biba *range)
253 {
254
255         KASSERT((effective->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
256             ("biba_effective_in_range: a not effective"));
257         KASSERT((range->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
258             ("biba_effective_in_range: b not range"));
259
260         return (biba_dominate_element(&range->mb_rangehigh,
261             &effective->mb_effective) &&
262             biba_dominate_element(&effective->mb_effective,
263             &range->mb_rangelow));
264
265         return (1);
266 }
267
268 static int
269 biba_dominate_effective(struct mac_biba *a, struct mac_biba *b)
270 {
271         KASSERT((a->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
272             ("biba_dominate_effective: a not effective"));
273         KASSERT((b->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
274             ("biba_dominate_effective: b not effective"));
275
276         return (biba_dominate_element(&a->mb_effective, &b->mb_effective));
277 }
278
279 static int
280 biba_equal_element(struct mac_biba_element *a, struct mac_biba_element *b)
281 {
282
283         if (a->mbe_type == MAC_BIBA_TYPE_EQUAL ||
284             b->mbe_type == MAC_BIBA_TYPE_EQUAL)
285                 return (1);
286
287         return (a->mbe_type == b->mbe_type && a->mbe_grade == b->mbe_grade);
288 }
289
290 static int
291 biba_equal_effective(struct mac_biba *a, struct mac_biba *b)
292 {
293
294         KASSERT((a->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
295             ("biba_equal_effective: a not effective"));
296         KASSERT((b->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
297             ("biba_equal_effective: b not effective"));
298
299         return (biba_equal_element(&a->mb_effective, &b->mb_effective));
300 }
301
302 static int
303 biba_contains_equal(struct mac_biba *mb)
304 {
305
306         if (mb->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
307                 if (mb->mb_effective.mbe_type == MAC_BIBA_TYPE_EQUAL)
308                         return (1);
309         }
310
311         if (mb->mb_flags & MAC_BIBA_FLAG_RANGE) {
312                 if (mb->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL)
313                         return (1);
314                 if (mb->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
315                         return (1);
316         }
317
318         return (0);
319 }
320
321 static int
322 biba_subject_privileged(struct mac_biba *mb)
323 {
324
325         KASSERT((mb->mb_flags & MAC_BIBA_FLAGS_BOTH) == MAC_BIBA_FLAGS_BOTH,
326             ("biba_subject_privileged: subject doesn't have both labels"));
327
328         /* If the effective is EQUAL, it's ok. */
329         if (mb->mb_effective.mbe_type == MAC_BIBA_TYPE_EQUAL)
330                 return (0);
331
332         /* If either range endpoint is EQUAL, it's ok. */
333         if (mb->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL ||
334             mb->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
335                 return (0);
336
337         /* If the range is low-high, it's ok. */
338         if (mb->mb_rangelow.mbe_type == MAC_BIBA_TYPE_LOW &&
339             mb->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_HIGH)
340                 return (0);
341
342         /* It's not ok. */
343         return (EPERM);
344 }
345
346 static int
347 biba_high_effective(struct mac_biba *mb)
348 {
349
350         KASSERT((mb->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
351             ("biba_equal_effective: mac_biba not effective"));
352
353         return (mb->mb_effective.mbe_type == MAC_BIBA_TYPE_HIGH);
354 }
355
356 static int
357 biba_valid(struct mac_biba *mb)
358 {
359
360         if (mb->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
361                 switch (mb->mb_effective.mbe_type) {
362                 case MAC_BIBA_TYPE_GRADE:
363                         break;
364
365                 case MAC_BIBA_TYPE_EQUAL:
366                 case MAC_BIBA_TYPE_HIGH:
367                 case MAC_BIBA_TYPE_LOW:
368                         if (mb->mb_effective.mbe_grade != 0 ||
369                             !MAC_BIBA_BIT_SET_EMPTY(
370                             mb->mb_effective.mbe_compartments))
371                                 return (EINVAL);
372                         break;
373
374                 default:
375                         return (EINVAL);
376                 }
377         } else {
378                 if (mb->mb_effective.mbe_type != MAC_BIBA_TYPE_UNDEF)
379                         return (EINVAL);
380         }
381
382         if (mb->mb_flags & MAC_BIBA_FLAG_RANGE) {
383                 switch (mb->mb_rangelow.mbe_type) {
384                 case MAC_BIBA_TYPE_GRADE:
385                         break;
386
387                 case MAC_BIBA_TYPE_EQUAL:
388                 case MAC_BIBA_TYPE_HIGH:
389                 case MAC_BIBA_TYPE_LOW:
390                         if (mb->mb_rangelow.mbe_grade != 0 ||
391                             !MAC_BIBA_BIT_SET_EMPTY(
392                             mb->mb_rangelow.mbe_compartments))
393                                 return (EINVAL);
394                         break;
395
396                 default:
397                         return (EINVAL);
398                 }
399
400                 switch (mb->mb_rangehigh.mbe_type) {
401                 case MAC_BIBA_TYPE_GRADE:
402                         break;
403
404                 case MAC_BIBA_TYPE_EQUAL:
405                 case MAC_BIBA_TYPE_HIGH:
406                 case MAC_BIBA_TYPE_LOW:
407                         if (mb->mb_rangehigh.mbe_grade != 0 ||
408                             !MAC_BIBA_BIT_SET_EMPTY(
409                             mb->mb_rangehigh.mbe_compartments))
410                                 return (EINVAL);
411                         break;
412
413                 default:
414                         return (EINVAL);
415                 }
416                 if (!biba_dominate_element(&mb->mb_rangehigh,
417                     &mb->mb_rangelow))
418                         return (EINVAL);
419         } else {
420                 if (mb->mb_rangelow.mbe_type != MAC_BIBA_TYPE_UNDEF ||
421                     mb->mb_rangehigh.mbe_type != MAC_BIBA_TYPE_UNDEF)
422                         return (EINVAL);
423         }
424
425         return (0);
426 }
427
428 static void
429 biba_set_range(struct mac_biba *mb, u_short typelow, u_short gradelow,
430     u_char *compartmentslow, u_short typehigh, u_short gradehigh,
431     u_char *compartmentshigh)
432 {
433
434         mb->mb_rangelow.mbe_type = typelow;
435         mb->mb_rangelow.mbe_grade = gradelow;
436         if (compartmentslow != NULL)
437                 memcpy(mb->mb_rangelow.mbe_compartments, compartmentslow,
438                     sizeof(mb->mb_rangelow.mbe_compartments));
439         mb->mb_rangehigh.mbe_type = typehigh;
440         mb->mb_rangehigh.mbe_grade = gradehigh;
441         if (compartmentshigh != NULL)
442                 memcpy(mb->mb_rangehigh.mbe_compartments, compartmentshigh,
443                     sizeof(mb->mb_rangehigh.mbe_compartments));
444         mb->mb_flags |= MAC_BIBA_FLAG_RANGE;
445 }
446
447 static void
448 biba_set_effective(struct mac_biba *mb, u_short type, u_short grade,
449     u_char *compartments)
450 {
451
452         mb->mb_effective.mbe_type = type;
453         mb->mb_effective.mbe_grade = grade;
454         if (compartments != NULL)
455                 memcpy(mb->mb_effective.mbe_compartments, compartments,
456                     sizeof(mb->mb_effective.mbe_compartments));
457         mb->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
458 }
459
460 static void
461 biba_copy_range(struct mac_biba *labelfrom, struct mac_biba *labelto)
462 {
463
464         KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
465             ("biba_copy_range: labelfrom not range"));
466
467         labelto->mb_rangelow = labelfrom->mb_rangelow;
468         labelto->mb_rangehigh = labelfrom->mb_rangehigh;
469         labelto->mb_flags |= MAC_BIBA_FLAG_RANGE;
470 }
471
472 static void
473 biba_copy_effective(struct mac_biba *labelfrom, struct mac_biba *labelto)
474 {
475
476         KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
477             ("biba_copy_effective: labelfrom not effective"));
478
479         labelto->mb_effective = labelfrom->mb_effective;
480         labelto->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
481 }
482
483 static void
484 biba_copy(struct mac_biba *source, struct mac_biba *dest)
485 {
486
487         if (source->mb_flags & MAC_BIBA_FLAG_EFFECTIVE)
488                 biba_copy_effective(source, dest);
489         if (source->mb_flags & MAC_BIBA_FLAG_RANGE)
490                 biba_copy_range(source, dest);
491 }
492
493 /*
494  * Policy module operations.
495  */
496 static void
497 biba_init(struct mac_policy_conf *conf)
498 {
499
500         zone_biba = uma_zcreate("mac_biba", sizeof(struct mac_biba), NULL,
501             NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
502 }
503
504 /*
505  * Label operations.
506  */
507 static void
508 biba_init_label(struct label *label)
509 {
510
511         SLOT_SET(label, biba_alloc(M_WAITOK));
512 }
513
514 static int
515 biba_init_label_waitcheck(struct label *label, int flag)
516 {
517
518         SLOT_SET(label, biba_alloc(flag));
519         if (SLOT(label) == NULL)
520                 return (ENOMEM);
521
522         return (0);
523 }
524
525 static void
526 biba_destroy_label(struct label *label)
527 {
528
529         biba_free(SLOT(label));
530         SLOT_SET(label, NULL);
531 }
532
533 /*
534  * biba_element_to_string() accepts an sbuf and Biba element.  It converts
535  * the Biba element to a string and stores the result in the sbuf; if there
536  * isn't space in the sbuf, -1 is returned.
537  */
538 static int
539 biba_element_to_string(struct sbuf *sb, struct mac_biba_element *element)
540 {
541         int i, first;
542
543         switch (element->mbe_type) {
544         case MAC_BIBA_TYPE_HIGH:
545                 return (sbuf_printf(sb, "high"));
546
547         case MAC_BIBA_TYPE_LOW:
548                 return (sbuf_printf(sb, "low"));
549
550         case MAC_BIBA_TYPE_EQUAL:
551                 return (sbuf_printf(sb, "equal"));
552
553         case MAC_BIBA_TYPE_GRADE:
554                 if (sbuf_printf(sb, "%d", element->mbe_grade) == -1)
555                         return (-1);
556
557                 first = 1;
558                 for (i = 1; i <= MAC_BIBA_MAX_COMPARTMENTS; i++) {
559                         if (MAC_BIBA_BIT_TEST(i, element->mbe_compartments)) {
560                                 if (first) {
561                                         if (sbuf_putc(sb, ':') == -1)
562                                                 return (-1);
563                                         if (sbuf_printf(sb, "%d", i) == -1)
564                                                 return (-1);
565                                         first = 0;
566                                 } else {
567                                         if (sbuf_printf(sb, "+%d", i) == -1)
568                                                 return (-1);
569                                 }
570                         }
571                 }
572                 return (0);
573
574         default:
575                 panic("biba_element_to_string: invalid type (%d)",
576                     element->mbe_type);
577         }
578 }
579
580 /*
581  * biba_to_string() converts a Biba label to a string, and places the results
582  * in the passed sbuf.  It returns 0 on success, or EINVAL if there isn't
583  * room in the sbuf.  Note: the sbuf will be modified even in a failure case,
584  * so the caller may need to revert the sbuf by restoring the offset if
585  * that's undesired.
586  */
587 static int
588 biba_to_string(struct sbuf *sb, struct mac_biba *mb)
589 {
590
591         if (mb->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
592                 if (biba_element_to_string(sb, &mb->mb_effective) == -1)
593                         return (EINVAL);
594         }
595
596         if (mb->mb_flags & MAC_BIBA_FLAG_RANGE) {
597                 if (sbuf_putc(sb, '(') == -1)
598                         return (EINVAL);
599
600                 if (biba_element_to_string(sb, &mb->mb_rangelow) == -1)
601                         return (EINVAL);
602
603                 if (sbuf_putc(sb, '-') == -1)
604                         return (EINVAL);
605
606                 if (biba_element_to_string(sb, &mb->mb_rangehigh) == -1)
607                         return (EINVAL);
608
609                 if (sbuf_putc(sb, ')') == -1)
610                         return (EINVAL);
611         }
612
613         return (0);
614 }
615
616 static int
617 biba_externalize_label(struct label *label, char *element_name,
618     struct sbuf *sb, int *claimed)
619 {
620         struct mac_biba *mb;
621
622         if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
623                 return (0);
624
625         (*claimed)++;
626
627         mb = SLOT(label);
628         return (biba_to_string(sb, mb));
629 }
630
631 static int
632 biba_parse_element(struct mac_biba_element *element, char *string)
633 {
634         char *compartment, *end, *grade;
635         int value;
636
637         if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) {
638                 element->mbe_type = MAC_BIBA_TYPE_HIGH;
639                 element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
640         } else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) {
641                 element->mbe_type = MAC_BIBA_TYPE_LOW;
642                 element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
643         } else if (strcmp(string, "equal") == 0 ||
644             strcmp(string, "eq") == 0) {
645                 element->mbe_type = MAC_BIBA_TYPE_EQUAL;
646                 element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
647         } else {
648                 element->mbe_type = MAC_BIBA_TYPE_GRADE;
649
650                 /*
651                  * Numeric grade piece of the element.
652                  */
653                 grade = strsep(&string, ":");
654                 value = strtol(grade, &end, 10);
655                 if (end == grade || *end != '\0')
656                         return (EINVAL);
657                 if (value < 0 || value > 65535)
658                         return (EINVAL);
659                 element->mbe_grade = value;
660
661                 /*
662                  * Optional compartment piece of the element.  If none are
663                  * included, we assume that the label has no compartments.
664                  */
665                 if (string == NULL)
666                         return (0);
667                 if (*string == '\0')
668                         return (0);
669
670                 while ((compartment = strsep(&string, "+")) != NULL) {
671                         value = strtol(compartment, &end, 10);
672                         if (compartment == end || *end != '\0')
673                                 return (EINVAL);
674                         if (value < 1 || value > MAC_BIBA_MAX_COMPARTMENTS)
675                                 return (EINVAL);
676                         MAC_BIBA_BIT_SET(value, element->mbe_compartments);
677                 }
678         }
679
680         return (0);
681 }
682
683 /*
684  * Note: destructively consumes the string, make a local copy before calling
685  * if that's a problem.
686  */
687 static int
688 biba_parse(struct mac_biba *mb, char *string)
689 {
690         char *rangehigh, *rangelow, *effective;
691         int error;
692
693         effective = strsep(&string, "(");
694         if (*effective == '\0')
695                 effective = NULL;
696
697         if (string != NULL) {
698                 rangelow = strsep(&string, "-");
699                 if (string == NULL)
700                         return (EINVAL);
701                 rangehigh = strsep(&string, ")");
702                 if (string == NULL)
703                         return (EINVAL);
704                 if (*string != '\0')
705                         return (EINVAL);
706         } else {
707                 rangelow = NULL;
708                 rangehigh = NULL;
709         }
710
711         KASSERT((rangelow != NULL && rangehigh != NULL) ||
712             (rangelow == NULL && rangehigh == NULL),
713             ("biba_parse: range mismatch"));
714
715         bzero(mb, sizeof(*mb));
716         if (effective != NULL) {
717                 error = biba_parse_element(&mb->mb_effective, effective);
718                 if (error)
719                         return (error);
720                 mb->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
721         }
722
723         if (rangelow != NULL) {
724                 error = biba_parse_element(&mb->mb_rangelow, rangelow);
725                 if (error)
726                         return (error);
727                 error = biba_parse_element(&mb->mb_rangehigh, rangehigh);
728                 if (error)
729                         return (error);
730                 mb->mb_flags |= MAC_BIBA_FLAG_RANGE;
731         }
732
733         error = biba_valid(mb);
734         if (error)
735                 return (error);
736
737         return (0);
738 }
739
740 static int
741 biba_internalize_label(struct label *label, char *element_name,
742     char *element_data, int *claimed)
743 {
744         struct mac_biba *mb, mb_temp;
745         int error;
746
747         if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
748                 return (0);
749
750         (*claimed)++;
751
752         error = biba_parse(&mb_temp, element_data);
753         if (error)
754                 return (error);
755
756         mb = SLOT(label);
757         *mb = mb_temp;
758
759         return (0);
760 }
761
762 static void
763 biba_copy_label(struct label *src, struct label *dest)
764 {
765
766         *SLOT(dest) = *SLOT(src);
767 }
768
769 /*
770  * Labeling event operations: file system objects, and things that look a lot
771  * like file system objects.
772  */
773 static void
774 biba_create_devfs_device(struct ucred *cred, struct mount *mp,
775     struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
776 {
777         struct mac_biba *mb;
778         int biba_type;
779
780         mb = SLOT(delabel);
781         if (strcmp(dev->si_name, "null") == 0 ||
782             strcmp(dev->si_name, "zero")== 0 ||
783             strcmp(dev->si_name, "random") == 0 ||
784             strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
785                 biba_type = MAC_BIBA_TYPE_EQUAL;
786         else if (ptys_equal &&
787             (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
788             strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
789                 biba_type = MAC_BIBA_TYPE_EQUAL;
790         else
791                 biba_type = MAC_BIBA_TYPE_HIGH;
792         biba_set_effective(mb, biba_type, 0, NULL);
793 }
794
795 static void
796 biba_create_devfs_directory(struct mount *mp, char *dirname,
797     int dirnamelen, struct devfs_dirent *de, struct label *delabel)
798 {
799         struct mac_biba *mb;
800
801         mb = SLOT(delabel);
802         biba_set_effective(mb, MAC_BIBA_TYPE_HIGH, 0, NULL);
803 }
804
805 static void
806 biba_create_devfs_symlink(struct ucred *cred, struct mount *mp,
807     struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
808     struct label *delabel)
809 {
810         struct mac_biba *source, *dest;
811
812         source = SLOT(cred->cr_label);
813         dest = SLOT(delabel);
814
815         biba_copy_effective(source, dest);
816 }
817
818 static void
819 biba_create_mount(struct ucred *cred, struct mount *mp,
820     struct label *mplabel)
821 {
822         struct mac_biba *source, *dest;
823
824         source = SLOT(cred->cr_label);
825         dest = SLOT(mplabel);
826
827         biba_copy_effective(source, dest);
828 }
829
830 static void
831 biba_relabel_vnode(struct ucred *cred, struct vnode *vp,
832     struct label *vplabel, struct label *newlabel)
833 {
834         struct mac_biba *source, *dest;
835
836         source = SLOT(newlabel);
837         dest = SLOT(vplabel);
838
839         biba_copy(source, dest);
840 }
841
842 static void
843 biba_update_devfs(struct mount *mp, struct devfs_dirent *de,
844     struct label *delabel, struct vnode *vp, struct label *vplabel)
845 {
846         struct mac_biba *source, *dest;
847
848         source = SLOT(vplabel);
849         dest = SLOT(delabel);
850
851         biba_copy(source, dest);
852 }
853
854 static void
855 biba_associate_vnode_devfs(struct mount *mp, struct label *mntlabel,
856     struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
857     struct label *vplabel)
858 {
859         struct mac_biba *source, *dest;
860
861         source = SLOT(delabel);
862         dest = SLOT(vplabel);
863
864         biba_copy_effective(source, dest);
865 }
866
867 static int
868 biba_associate_vnode_extattr(struct mount *mp, struct label *mplabel,
869     struct vnode *vp, struct label *vplabel)
870 {
871         struct mac_biba temp, *source, *dest;
872         int buflen, error;
873
874         source = SLOT(mplabel);
875         dest = SLOT(vplabel);
876
877         buflen = sizeof(temp);
878         bzero(&temp, buflen);
879
880         error = vn_extattr_get(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
881             MAC_BIBA_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
882         if (error == ENOATTR || error == EOPNOTSUPP) {
883                 /* Fall back to the mntlabel. */
884                 biba_copy_effective(source, dest);
885                 return (0);
886         } else if (error)
887                 return (error);
888
889         if (buflen != sizeof(temp)) {
890                 printf("biba_associate_vnode_extattr: bad size %d\n",
891                     buflen);
892                 return (EPERM);
893         }
894         if (biba_valid(&temp) != 0) {
895                 printf("biba_associate_vnode_extattr: invalid\n");
896                 return (EPERM);
897         }
898         if ((temp.mb_flags & MAC_BIBA_FLAGS_BOTH) != MAC_BIBA_FLAG_EFFECTIVE) {
899                 printf("biba_associate_vnode_extattr: not effective\n");
900                 return (EPERM);
901         }
902
903         biba_copy_effective(&temp, dest);
904         return (0);
905 }
906
907 static void
908 biba_associate_vnode_singlelabel(struct mount *mp,
909     struct label *mplabel, struct vnode *vp, struct label *vplabel)
910 {
911         struct mac_biba *source, *dest;
912
913         source = SLOT(mplabel);
914         dest = SLOT(vplabel);
915
916         biba_copy_effective(source, dest);
917 }
918
919 static int
920 biba_create_vnode_extattr(struct ucred *cred, struct mount *mp,
921     struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
922     struct vnode *vp, struct label *vplabel, struct componentname *cnp)
923 {
924         struct mac_biba *source, *dest, temp;
925         size_t buflen;
926         int error;
927
928         buflen = sizeof(temp);
929         bzero(&temp, buflen);
930
931         source = SLOT(cred->cr_label);
932         dest = SLOT(vplabel);
933         biba_copy_effective(source, &temp);
934
935         error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
936             MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread);
937         if (error == 0)
938                 biba_copy_effective(source, dest);
939         return (error);
940 }
941
942 static int
943 biba_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
944     struct label *vplabel, struct label *intlabel)
945 {
946         struct mac_biba *source, temp;
947         size_t buflen;
948         int error;
949
950         buflen = sizeof(temp);
951         bzero(&temp, buflen);
952
953         source = SLOT(intlabel);
954         if ((source->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) == 0)
955                 return (0);
956
957         biba_copy_effective(source, &temp);
958
959         error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
960             MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread);
961         return (error);
962 }
963
964 /*
965  * Labeling event operations: IPC object.
966  */
967 static void
968 biba_create_inpcb_from_socket(struct socket *so, struct label *solabel,
969     struct inpcb *inp, struct label *inplabel)
970 {
971         struct mac_biba *source, *dest;
972
973         source = SLOT(solabel);
974         dest = SLOT(inplabel);
975
976         biba_copy_effective(source, dest);
977 }
978
979 static void
980 biba_create_mbuf_from_socket(struct socket *so, struct label *solabel,
981     struct mbuf *m, struct label *mlabel)
982 {
983         struct mac_biba *source, *dest;
984
985         source = SLOT(solabel);
986         dest = SLOT(mlabel);
987
988         biba_copy_effective(source, dest);
989 }
990
991 static void
992 biba_create_socket(struct ucred *cred, struct socket *so,
993     struct label *solabel)
994 {
995         struct mac_biba *source, *dest;
996
997         source = SLOT(cred->cr_label);
998         dest = SLOT(solabel);
999
1000         biba_copy_effective(source, dest);
1001 }
1002
1003 static void
1004 biba_create_pipe(struct ucred *cred, struct pipepair *pp,
1005     struct label *pplabel)
1006 {
1007         struct mac_biba *source, *dest;
1008
1009         source = SLOT(cred->cr_label);
1010         dest = SLOT(pplabel);
1011
1012         biba_copy_effective(source, dest);
1013 }
1014
1015 static void
1016 biba_create_posix_sem(struct ucred *cred, struct ksem *ks,
1017     struct label *kslabel)
1018 {
1019         struct mac_biba *source, *dest;
1020
1021         source = SLOT(cred->cr_label);
1022         dest = SLOT(kslabel);
1023
1024         biba_copy_effective(source, dest);
1025 }
1026
1027 static void
1028 biba_create_socket_from_socket(struct socket *oldso,
1029     struct label *oldsolabel, struct socket *newso, struct label *newsolabel)
1030 {
1031         struct mac_biba *source, *dest;
1032
1033         source = SLOT(oldsolabel);
1034         dest = SLOT(newsolabel);
1035
1036         biba_copy_effective(source, dest);
1037 }
1038
1039 static void
1040 biba_relabel_socket(struct ucred *cred, struct socket *so,
1041     struct label *solabel, struct label *newlabel)
1042 {
1043         struct mac_biba *source, *dest;
1044
1045         source = SLOT(newlabel);
1046         dest = SLOT(solabel);
1047
1048         biba_copy(source, dest);
1049 }
1050
1051 static void
1052 biba_relabel_pipe(struct ucred *cred, struct pipepair *pp,
1053     struct label *pplabel, struct label *newlabel)
1054 {
1055         struct mac_biba *source, *dest;
1056
1057         source = SLOT(newlabel);
1058         dest = SLOT(pplabel);
1059
1060         biba_copy(source, dest);
1061 }
1062
1063 static void
1064 biba_set_socket_peer_from_mbuf(struct mbuf *m, struct label *mlabel,
1065     struct socket *so, struct label *sopeerlabel)
1066 {
1067         struct mac_biba *source, *dest;
1068
1069         source = SLOT(mlabel);
1070         dest = SLOT(sopeerlabel);
1071
1072         biba_copy_effective(source, dest);
1073 }
1074
1075 /*
1076  * Labeling event operations: System V IPC objects.
1077  */
1078 static void
1079 biba_create_sysv_msgmsg(struct ucred *cred, struct msqid_kernel *msqkptr,
1080     struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
1081 {
1082         struct mac_biba *source, *dest;
1083
1084         /* Ignore the msgq label */
1085         source = SLOT(cred->cr_label);
1086         dest = SLOT(msglabel);
1087
1088         biba_copy_effective(source, dest);
1089 }
1090
1091 static void
1092 biba_create_sysv_msgqueue(struct ucred *cred,
1093     struct msqid_kernel *msqkptr, struct label *msqlabel)
1094 {
1095         struct mac_biba *source, *dest;
1096
1097         source = SLOT(cred->cr_label);
1098         dest = SLOT(msqlabel);
1099
1100         biba_copy_effective(source, dest);
1101 }
1102
1103 static void
1104 biba_create_sysv_sem(struct ucred *cred, struct semid_kernel *semakptr,
1105     struct label *semalabel)
1106 {
1107         struct mac_biba *source, *dest;
1108
1109         source = SLOT(cred->cr_label);
1110         dest = SLOT(semalabel);
1111
1112         biba_copy_effective(source, dest);
1113 }
1114
1115 static void
1116 biba_create_sysv_shm(struct ucred *cred, struct shmid_kernel *shmsegptr,
1117     struct label *shmlabel)
1118 {
1119         struct mac_biba *source, *dest;
1120
1121         source = SLOT(cred->cr_label);
1122         dest = SLOT(shmlabel);
1123
1124         biba_copy_effective(source, dest);
1125 }
1126
1127 /*
1128  * Labeling event operations: network objects.
1129  */
1130 static void
1131 biba_set_socket_peer_from_socket(struct socket *oldso,
1132     struct label *oldsolabel, struct socket *newso,
1133     struct label *newsopeerlabel)
1134 {
1135         struct mac_biba *source, *dest;
1136
1137         source = SLOT(oldsolabel);
1138         dest = SLOT(newsopeerlabel);
1139
1140         biba_copy_effective(source, dest);
1141 }
1142
1143 static void
1144 biba_create_bpfdesc(struct ucred *cred, struct bpf_d *d,
1145     struct label *dlabel)
1146 {
1147         struct mac_biba *source, *dest;
1148
1149         source = SLOT(cred->cr_label);
1150         dest = SLOT(dlabel);
1151
1152         biba_copy_effective(source, dest);
1153 }
1154
1155 static void
1156 biba_create_ifnet(struct ifnet *ifp, struct label *ifplabel)
1157 {
1158         char tifname[IFNAMSIZ], *p, *q;
1159         char tiflist[sizeof(trusted_interfaces)];
1160         struct mac_biba *dest;
1161         int len, type;
1162
1163         dest = SLOT(ifplabel);
1164
1165         if (ifp->if_type == IFT_LOOP || interfaces_equal != 0) {
1166                 type = MAC_BIBA_TYPE_EQUAL;
1167                 goto set;
1168         }
1169
1170         if (trust_all_interfaces) {
1171                 type = MAC_BIBA_TYPE_HIGH;
1172                 goto set;
1173         }
1174
1175         type = MAC_BIBA_TYPE_LOW;
1176
1177         if (trusted_interfaces[0] == '\0' ||
1178             !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1179                 goto set;
1180
1181         bzero(tiflist, sizeof(tiflist));
1182         for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1183                 if(*p != ' ' && *p != '\t')
1184                         *q = *p;
1185
1186         for (p = q = tiflist;; p++) {
1187                 if (*p == ',' || *p == '\0') {
1188                         len = p - q;
1189                         if (len < IFNAMSIZ) {
1190                                 bzero(tifname, sizeof(tifname));
1191                                 bcopy(q, tifname, len);
1192                                 if (strcmp(tifname, ifp->if_xname) == 0) {
1193                                         type = MAC_BIBA_TYPE_HIGH;
1194                                         break;
1195                                 }
1196                         } else {
1197                                 *p = '\0';
1198                                 printf("mac_biba warning: interface name "
1199                                     "\"%s\" is too long (must be < %d)\n",
1200                                     q, IFNAMSIZ);
1201                         }
1202                         if (*p == '\0')
1203                                 break;
1204                         q = p + 1;
1205                 }
1206         }
1207 set:
1208         biba_set_effective(dest, type, 0, NULL);
1209         biba_set_range(dest, type, 0, NULL, type, 0, NULL);
1210 }
1211
1212 static void
1213 biba_create_ipq(struct mbuf *m, struct label *mlabel, struct ipq *q,
1214     struct label *qlabel)
1215 {
1216         struct mac_biba *source, *dest;
1217
1218         source = SLOT(mlabel);
1219         dest = SLOT(qlabel);
1220
1221         biba_copy_effective(source, dest);
1222 }
1223
1224 static void
1225 biba_create_datagram_from_ipq(struct ipq *q, struct label *qlabel,
1226     struct mbuf *m, struct label *mlabel)
1227 {
1228         struct mac_biba *source, *dest;
1229
1230         source = SLOT(qlabel);
1231         dest = SLOT(mlabel);
1232
1233         /* Just use the head, since we require them all to match. */
1234         biba_copy_effective(source, dest);
1235 }
1236
1237 static void
1238 biba_create_fragment(struct mbuf *m, struct label *mlabel,
1239     struct mbuf *frag, struct label *fraglabel)
1240 {
1241         struct mac_biba *source, *dest;
1242
1243         source = SLOT(mlabel);
1244         dest = SLOT(fraglabel);
1245
1246         biba_copy_effective(source, dest);
1247 }
1248
1249 static void
1250 biba_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel,
1251     struct mbuf *m, struct label *mlabel)
1252 {
1253         struct mac_biba *source, *dest;
1254
1255         source = SLOT(inplabel);
1256         dest = SLOT(mlabel);
1257
1258         biba_copy_effective(source, dest);
1259 }
1260
1261 static void
1262 biba_create_mbuf_linklayer(struct ifnet *ifp, struct label *ifplabel,
1263     struct mbuf *m, struct label *mlabel)
1264 {
1265         struct mac_biba *dest;
1266
1267         dest = SLOT(mlabel);
1268
1269         biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1270 }
1271
1272 static void
1273 biba_create_mbuf_from_bpfdesc(struct bpf_d *d, struct label *dlabel,
1274     struct mbuf *m, struct label *mlabel)
1275 {
1276         struct mac_biba *source, *dest;
1277
1278         source = SLOT(dlabel);
1279         dest = SLOT(mlabel);
1280
1281         biba_copy_effective(source, dest);
1282 }
1283
1284 static void
1285 biba_create_mbuf_from_ifnet(struct ifnet *ifp, struct label *ifplabel,
1286     struct mbuf *m, struct label *mlabel)
1287 {
1288         struct mac_biba *source, *dest;
1289
1290         source = SLOT(ifplabel);
1291         dest = SLOT(mlabel);
1292
1293         biba_copy_effective(source, dest);
1294 }
1295
1296 static void
1297 biba_create_mbuf_multicast_encap(struct mbuf *m, struct label *mlabel,
1298     struct ifnet *ifp, struct label *ifplabel, struct mbuf *mnew,
1299     struct label *mnewlabel)
1300 {
1301         struct mac_biba *source, *dest;
1302
1303         source = SLOT(mlabel);
1304         dest = SLOT(mnewlabel);
1305
1306         biba_copy_effective(source, dest);
1307 }
1308
1309 static void
1310 biba_create_mbuf_netlayer(struct mbuf *m, struct label *mlabel,
1311     struct mbuf *newm, struct label *mnewlabel)
1312 {
1313         struct mac_biba *source, *dest;
1314
1315         source = SLOT(mlabel);
1316         dest = SLOT(mnewlabel);
1317
1318         biba_copy_effective(source, dest);
1319 }
1320
1321 static int
1322 biba_fragment_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1323     struct label *qlabel)
1324 {
1325         struct mac_biba *a, *b;
1326
1327         a = SLOT(qlabel);
1328         b = SLOT(mlabel);
1329
1330         return (biba_equal_effective(a, b));
1331 }
1332
1333 static void
1334 biba_relabel_ifnet(struct ucred *cred, struct ifnet *ifp,
1335     struct label *ifplabel, struct label *newlabel)
1336 {
1337         struct mac_biba *source, *dest;
1338
1339         source = SLOT(newlabel);
1340         dest = SLOT(ifplabel);
1341
1342         biba_copy(source, dest);
1343 }
1344
1345 static void
1346 biba_update_ipq(struct mbuf *m, struct label *mlabel, struct ipq *q,
1347     struct label *qlabel)
1348 {
1349
1350         /* NOOP: we only accept matching labels, so no need to update */
1351 }
1352
1353 static void
1354 biba_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1355     struct inpcb *inp, struct label *inplabel)
1356 {
1357         struct mac_biba *source, *dest;
1358
1359         source = SLOT(solabel);
1360         dest = SLOT(inplabel);
1361
1362         biba_copy(source, dest);
1363 }
1364
1365 static void
1366 biba_create_mbuf_from_firewall(struct mbuf *m, struct label *label)
1367 {
1368         struct mac_biba *dest;
1369
1370         dest = SLOT(label);
1371
1372         /* XXX: where is the label for the firewall really comming from? */
1373         biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1374 }
1375
1376 /*
1377  * Labeling event operations: processes.
1378  */
1379 static void
1380 biba_create_proc0(struct ucred *cred)
1381 {
1382         struct mac_biba *dest;
1383
1384         dest = SLOT(cred->cr_label);
1385
1386         biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1387         biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL, MAC_BIBA_TYPE_HIGH,
1388             0, NULL);
1389 }
1390
1391 static void
1392 biba_create_proc1(struct ucred *cred)
1393 {
1394         struct mac_biba *dest;
1395
1396         dest = SLOT(cred->cr_label);
1397
1398         biba_set_effective(dest, MAC_BIBA_TYPE_HIGH, 0, NULL);
1399         biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL, MAC_BIBA_TYPE_HIGH,
1400             0, NULL);
1401 }
1402
1403 static void
1404 biba_relabel_cred(struct ucred *cred, struct label *newlabel)
1405 {
1406         struct mac_biba *source, *dest;
1407
1408         source = SLOT(newlabel);
1409         dest = SLOT(cred->cr_label);
1410
1411         biba_copy(source, dest);
1412 }
1413
1414 /*
1415  * Label cleanup/flush operations
1416  */
1417 static void
1418 biba_cleanup_sysv_msgmsg(struct label *msglabel)
1419 {
1420
1421         bzero(SLOT(msglabel), sizeof(struct mac_biba));
1422 }
1423
1424 static void
1425 biba_cleanup_sysv_msgqueue(struct label *msqlabel)
1426 {
1427
1428         bzero(SLOT(msqlabel), sizeof(struct mac_biba));
1429 }
1430
1431 static void
1432 biba_cleanup_sysv_sem(struct label *semalabel)
1433 {
1434
1435         bzero(SLOT(semalabel), sizeof(struct mac_biba));
1436 }
1437
1438 static void
1439 biba_cleanup_sysv_shm(struct label *shmlabel)
1440 {
1441         bzero(SLOT(shmlabel), sizeof(struct mac_biba));
1442 }
1443
1444 /*
1445  * Access control checks.
1446  */
1447 static int
1448 biba_check_bpfdesc_receive(struct bpf_d *d, struct label *dlabel,
1449     struct ifnet *ifp, struct label *ifplabel)
1450 {
1451         struct mac_biba *a, *b;
1452
1453         if (!biba_enabled)
1454                 return (0);
1455
1456         a = SLOT(dlabel);
1457         b = SLOT(ifplabel);
1458
1459         if (biba_equal_effective(a, b))
1460                 return (0);
1461         return (EACCES);
1462 }
1463
1464 static int
1465 biba_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1466 {
1467         struct mac_biba *subj, *new;
1468         int error;
1469
1470         subj = SLOT(cred->cr_label);
1471         new = SLOT(newlabel);
1472
1473         /*
1474          * If there is a Biba label update for the credential, it may be an
1475          * update of the effective, range, or both.
1476          */
1477         error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1478         if (error)
1479                 return (error);
1480
1481         /*
1482          * If the Biba label is to be changed, authorize as appropriate.
1483          */
1484         if (new->mb_flags & MAC_BIBA_FLAGS_BOTH) {
1485                 /*
1486                  * If the change request modifies both the Biba label
1487                  * effective and range, check that the new effective will be
1488                  * in the new range.
1489                  */
1490                 if ((new->mb_flags & MAC_BIBA_FLAGS_BOTH) ==
1491                     MAC_BIBA_FLAGS_BOTH &&
1492                     !biba_effective_in_range(new, new))
1493                         return (EINVAL);
1494
1495                 /*
1496                  * To change the Biba effective label on a credential, the
1497                  * new effective label must be in the current range.
1498                  */
1499                 if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE &&
1500                     !biba_effective_in_range(new, subj))
1501                         return (EPERM);
1502
1503                 /*
1504                  * To change the Biba range on a credential, the new range
1505                  * label must be in the current range.
1506                  */
1507                 if (new->mb_flags & MAC_BIBA_FLAG_RANGE &&
1508                     !biba_range_in_range(new, subj))
1509                         return (EPERM);
1510
1511                 /*
1512                  * To have EQUAL in any component of the new credential Biba
1513                  * label, the subject must already have EQUAL in their label.
1514                  */
1515                 if (biba_contains_equal(new)) {
1516                         error = biba_subject_privileged(subj);
1517                         if (error)
1518                                 return (error);
1519                 }
1520         }
1521
1522         return (0);
1523 }
1524
1525 static int
1526 biba_check_cred_visible(struct ucred *u1, struct ucred *u2)
1527 {
1528         struct mac_biba *subj, *obj;
1529
1530         if (!biba_enabled)
1531                 return (0);
1532
1533         subj = SLOT(u1->cr_label);
1534         obj = SLOT(u2->cr_label);
1535
1536         /* XXX: range */
1537         if (!biba_dominate_effective(obj, subj))
1538                 return (ESRCH);
1539
1540         return (0);
1541 }
1542
1543 static int
1544 biba_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1545     struct label *ifplabel, struct label *newlabel)
1546 {
1547         struct mac_biba *subj, *new;
1548         int error;
1549
1550         subj = SLOT(cred->cr_label);
1551         new = SLOT(newlabel);
1552
1553         /*
1554          * If there is a Biba label update for the interface, it may be an
1555          * update of the effective, range, or both.
1556          */
1557         error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1558         if (error)
1559                 return (error);
1560
1561         /*
1562          * Relabling network interfaces requires Biba privilege.
1563          */
1564         error = biba_subject_privileged(subj);
1565         if (error)
1566                 return (error);
1567
1568         return (0);
1569 }
1570
1571 static int
1572 biba_check_ifnet_transmit(struct ifnet *ifp, struct label *ifplabel,
1573     struct mbuf *m, struct label *mlabel)
1574 {
1575         struct mac_biba *p, *i;
1576
1577         if (!biba_enabled)
1578                 return (0);
1579
1580         p = SLOT(mlabel);
1581         i = SLOT(ifplabel);
1582
1583         return (biba_effective_in_range(p, i) ? 0 : EACCES);
1584 }
1585
1586 static int
1587 biba_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1588     struct mbuf *m, struct label *mlabel)
1589 {
1590         struct mac_biba *p, *i;
1591
1592         if (!biba_enabled)
1593                 return (0);
1594
1595         p = SLOT(mlabel);
1596         i = SLOT(inplabel);
1597
1598         return (biba_equal_effective(p, i) ? 0 : EACCES);
1599 }
1600
1601 static int
1602 biba_check_inpcb_visible(struct ucred *cred, struct inpcb *inp,
1603     struct label *inplabel)
1604 {
1605         struct mac_biba *subj, *obj;
1606
1607         if (!biba_enabled)
1608                 return (0);
1609
1610         subj = SLOT(cred->cr_label);
1611         obj = SLOT(inplabel);
1612
1613         if (!biba_dominate_effective(obj, subj))
1614                 return (ENOENT);
1615
1616         return (0);
1617 }
1618
1619 static int
1620 biba_check_sysv_msgrcv(struct ucred *cred, struct msg *msgptr,
1621     struct label *msglabel)
1622 {
1623         struct mac_biba *subj, *obj;
1624
1625         if (!biba_enabled)
1626                 return (0);
1627
1628         subj = SLOT(cred->cr_label);
1629         obj = SLOT(msglabel);
1630
1631         if (!biba_dominate_effective(obj, subj))
1632                 return (EACCES);
1633
1634         return (0);
1635 }
1636
1637 static int
1638 biba_check_sysv_msgrmid(struct ucred *cred, struct msg *msgptr,
1639     struct label *msglabel)
1640 {
1641         struct mac_biba *subj, *obj;
1642
1643         if (!biba_enabled)
1644                 return (0);
1645
1646         subj = SLOT(cred->cr_label);
1647         obj = SLOT(msglabel);
1648
1649         if (!biba_dominate_effective(subj, obj))
1650                 return (EACCES);
1651
1652         return (0);
1653 }
1654
1655 static int
1656 biba_check_sysv_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
1657     struct label *msqklabel)
1658 {
1659         struct mac_biba *subj, *obj;
1660
1661         if (!biba_enabled)
1662                 return (0);
1663
1664         subj = SLOT(cred->cr_label);
1665         obj = SLOT(msqklabel);
1666
1667         if (!biba_dominate_effective(obj, subj))
1668                 return (EACCES);
1669
1670         return (0);
1671 }
1672
1673 static int
1674 biba_check_sysv_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
1675     struct label *msqklabel)
1676 {
1677         struct mac_biba *subj, *obj;
1678
1679         if (!biba_enabled)
1680                 return (0);
1681
1682         subj = SLOT(cred->cr_label);
1683         obj = SLOT(msqklabel);
1684
1685         if (!biba_dominate_effective(subj, obj))
1686                 return (EACCES);
1687
1688         return (0);
1689 }
1690
1691 static int
1692 biba_check_sysv_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
1693     struct label *msqklabel)
1694 {
1695         struct mac_biba *subj, *obj;
1696
1697         if (!biba_enabled)
1698                 return (0);
1699
1700         subj = SLOT(cred->cr_label);
1701         obj = SLOT(msqklabel);
1702
1703         if (!biba_dominate_effective(obj, subj))
1704                 return (EACCES);
1705
1706         return (0);
1707 }
1708
1709 static int
1710 biba_check_sysv_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
1711     struct label *msqklabel, int cmd)
1712 {
1713         struct mac_biba *subj, *obj;
1714
1715         if (!biba_enabled)
1716                 return (0);
1717
1718         subj = SLOT(cred->cr_label);
1719         obj = SLOT(msqklabel);
1720
1721         switch(cmd) {
1722         case IPC_RMID:
1723         case IPC_SET:
1724                 if (!biba_dominate_effective(subj, obj))
1725                         return (EACCES);
1726                 break;
1727
1728         case IPC_STAT:
1729                 if (!biba_dominate_effective(obj, subj))
1730                         return (EACCES);
1731                 break;
1732
1733         default:
1734                 return (EACCES);
1735         }
1736
1737         return (0);
1738 }
1739
1740 static int
1741 biba_check_sysv_semctl(struct ucred *cred, struct semid_kernel *semakptr,
1742     struct label *semaklabel, int cmd)
1743 {
1744         struct mac_biba *subj, *obj;
1745
1746         if (!biba_enabled)
1747                 return (0);
1748
1749         subj = SLOT(cred->cr_label);
1750         obj = SLOT(semaklabel);
1751
1752         switch(cmd) {
1753         case IPC_RMID:
1754         case IPC_SET:
1755         case SETVAL:
1756         case SETALL:
1757                 if (!biba_dominate_effective(subj, obj))
1758                         return (EACCES);
1759                 break;
1760
1761         case IPC_STAT:
1762         case GETVAL:
1763         case GETPID:
1764         case GETNCNT:
1765         case GETZCNT:
1766         case GETALL:
1767                 if (!biba_dominate_effective(obj, subj))
1768                         return (EACCES);
1769                 break;
1770
1771         default:
1772                 return (EACCES);
1773         }
1774
1775         return (0);
1776 }
1777
1778 static int
1779 biba_check_sysv_semget(struct ucred *cred, struct semid_kernel *semakptr,
1780     struct label *semaklabel)
1781 {
1782         struct mac_biba *subj, *obj;
1783
1784         if (!biba_enabled)
1785                 return (0);
1786
1787         subj = SLOT(cred->cr_label);
1788         obj = SLOT(semaklabel);
1789
1790         if (!biba_dominate_effective(obj, subj))
1791                 return (EACCES);
1792
1793         return (0);
1794 }
1795
1796 static int
1797 biba_check_sysv_semop(struct ucred *cred, struct semid_kernel *semakptr,
1798     struct label *semaklabel, size_t accesstype)
1799 {
1800         struct mac_biba *subj, *obj;
1801
1802         if (!biba_enabled)
1803                 return (0);
1804
1805         subj = SLOT(cred->cr_label);
1806         obj = SLOT(semaklabel);
1807
1808         if (accesstype & SEM_R)
1809                 if (!biba_dominate_effective(obj, subj))
1810                         return (EACCES);
1811
1812         if (accesstype & SEM_A)
1813                 if (!biba_dominate_effective(subj, obj))
1814                         return (EACCES);
1815
1816         return (0);
1817 }
1818
1819 static int
1820 biba_check_sysv_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
1821     struct label *shmseglabel, int shmflg)
1822 {
1823         struct mac_biba *subj, *obj;
1824
1825         if (!biba_enabled)
1826                 return (0);
1827
1828         subj = SLOT(cred->cr_label);
1829         obj = SLOT(shmseglabel);
1830
1831         if (!biba_dominate_effective(obj, subj))
1832                 return (EACCES);
1833         if ((shmflg & SHM_RDONLY) == 0) {
1834                 if (!biba_dominate_effective(subj, obj))
1835                         return (EACCES);
1836         }
1837         
1838         return (0);
1839 }
1840
1841 static int
1842 biba_check_sysv_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
1843     struct label *shmseglabel, int cmd)
1844 {
1845         struct mac_biba *subj, *obj;
1846
1847         if (!biba_enabled)
1848                 return (0);
1849
1850         subj = SLOT(cred->cr_label);
1851         obj = SLOT(shmseglabel);
1852
1853         switch(cmd) {
1854         case IPC_RMID:
1855         case IPC_SET:
1856                 if (!biba_dominate_effective(subj, obj))
1857                         return (EACCES);
1858                 break;
1859
1860         case IPC_STAT:
1861         case SHM_STAT:
1862                 if (!biba_dominate_effective(obj, subj))
1863                         return (EACCES);
1864                 break;
1865
1866         default:
1867                 return (EACCES);
1868         }
1869
1870         return (0);
1871 }
1872
1873 static int
1874 biba_check_sysv_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
1875     struct label *shmseglabel, int shmflg)
1876 {
1877         struct mac_biba *subj, *obj;
1878
1879         if (!biba_enabled)
1880                 return (0);
1881
1882         subj = SLOT(cred->cr_label);
1883         obj = SLOT(shmseglabel);
1884
1885         if (!biba_dominate_effective(obj, subj))
1886                 return (EACCES);
1887
1888         return (0);
1889 }
1890
1891 static int
1892 biba_check_kld_load(struct ucred *cred, struct vnode *vp,
1893     struct label *vplabel)
1894 {
1895         struct mac_biba *subj, *obj;
1896         int error;
1897
1898         if (!biba_enabled)
1899                 return (0);
1900
1901         subj = SLOT(cred->cr_label);
1902
1903         error = biba_subject_privileged(subj);
1904         if (error)
1905                 return (error);
1906
1907         obj = SLOT(vplabel);
1908         if (!biba_high_effective(obj))
1909                 return (EACCES);
1910
1911         return (0);
1912 }
1913
1914 static int
1915 biba_check_mount_stat(struct ucred *cred, struct mount *mp,
1916     struct label *mplabel)
1917 {
1918         struct mac_biba *subj, *obj;
1919
1920         if (!biba_enabled)
1921                 return (0);
1922
1923         subj = SLOT(cred->cr_label);
1924         obj = SLOT(mplabel);
1925
1926         if (!biba_dominate_effective(obj, subj))
1927                 return (EACCES);
1928
1929         return (0);
1930 }
1931
1932 static int
1933 biba_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
1934     struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1935 {
1936
1937         if(!biba_enabled)
1938                 return (0);
1939
1940         /* XXX: This will be implemented soon... */
1941
1942         return (0);
1943 }
1944
1945 static int
1946 biba_check_pipe_poll(struct ucred *cred, struct pipepair *pp,
1947     struct label *pplabel)
1948 {
1949         struct mac_biba *subj, *obj;
1950
1951         if (!biba_enabled)
1952                 return (0);
1953
1954         subj = SLOT(cred->cr_label);
1955         obj = SLOT(pplabel);
1956
1957         if (!biba_dominate_effective(obj, subj))
1958                 return (EACCES);
1959
1960         return (0);
1961 }
1962
1963 static int
1964 biba_check_pipe_read(struct ucred *cred, struct pipepair *pp,
1965     struct label *pplabel)
1966 {
1967         struct mac_biba *subj, *obj;
1968
1969         if (!biba_enabled)
1970                 return (0);
1971
1972         subj = SLOT(cred->cr_label);
1973         obj = SLOT(pplabel);
1974
1975         if (!biba_dominate_effective(obj, subj))
1976                 return (EACCES);
1977
1978         return (0);
1979 }
1980
1981 static int
1982 biba_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1983     struct label *pplabel, struct label *newlabel)
1984 {
1985         struct mac_biba *subj, *obj, *new;
1986         int error;
1987
1988         new = SLOT(newlabel);
1989         subj = SLOT(cred->cr_label);
1990         obj = SLOT(pplabel);
1991
1992         /*
1993          * If there is a Biba label update for a pipe, it must be a effective
1994          * update.
1995          */
1996         error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
1997         if (error)
1998                 return (error);
1999
2000         /*
2001          * To perform a relabel of a pipe (Biba label or not), Biba must
2002          * authorize the relabel.
2003          */
2004         if (!biba_effective_in_range(obj, subj))
2005                 return (EPERM);
2006
2007         /*
2008          * If the Biba label is to be changed, authorize as appropriate.
2009          */
2010         if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
2011                 /*
2012                  * To change the Biba label on a pipe, the new pipe label
2013                  * must be in the subject range.
2014                  */
2015                 if (!biba_effective_in_range(new, subj))
2016                         return (EPERM);
2017
2018                 /*
2019                  * To change the Biba label on a pipe to be EQUAL, the
2020                  * subject must have appropriate privilege.
2021                  */
2022                 if (biba_contains_equal(new)) {
2023                         error = biba_subject_privileged(subj);
2024                         if (error)
2025                                 return (error);
2026                 }
2027         }
2028
2029         return (0);
2030 }
2031
2032 static int
2033 biba_check_pipe_stat(struct ucred *cred, struct pipepair *pp,
2034     struct label *pplabel)
2035 {
2036         struct mac_biba *subj, *obj;
2037
2038         if (!biba_enabled)
2039                 return (0);
2040
2041         subj = SLOT(cred->cr_label);
2042         obj = SLOT(pplabel);
2043
2044         if (!biba_dominate_effective(obj, subj))
2045                 return (EACCES);
2046
2047         return (0);
2048 }
2049
2050 static int
2051 biba_check_pipe_write(struct ucred *cred, struct pipepair *pp,
2052     struct label *pplabel)
2053 {
2054         struct mac_biba *subj, *obj;
2055
2056         if (!biba_enabled)
2057                 return (0);
2058
2059         subj = SLOT(cred->cr_label);
2060         obj = SLOT(pplabel);
2061
2062         if (!biba_dominate_effective(subj, obj))
2063                 return (EACCES);
2064
2065         return (0);
2066 }
2067
2068 static int
2069 biba_check_posix_sem_write(struct ucred *cred, struct ksem *ks,
2070     struct label *kslabel)
2071 {
2072         struct mac_biba *subj, *obj;
2073
2074         if (!biba_enabled)
2075                 return (0);
2076
2077         subj = SLOT(cred->cr_label);
2078         obj = SLOT(kslabel);
2079
2080         if (!biba_dominate_effective(subj, obj))
2081                 return (EACCES);
2082
2083         return (0);
2084 }
2085
2086 static int
2087 biba_check_posix_sem_rdonly(struct ucred *cred, struct ksem *ks,
2088     struct label *kslabel)
2089 {
2090         struct mac_biba *subj, *obj;
2091
2092         if (!biba_enabled)
2093                 return (0);
2094
2095         subj = SLOT(cred->cr_label);
2096         obj = SLOT(kslabel);
2097
2098         if (!biba_dominate_effective(obj, subj))
2099                 return (EACCES);
2100
2101         return (0);
2102 }
2103
2104 static int
2105 biba_check_proc_debug(struct ucred *cred, struct proc *p)
2106 {
2107         struct mac_biba *subj, *obj;
2108
2109         if (!biba_enabled)
2110                 return (0);
2111
2112         subj = SLOT(cred->cr_label);
2113         obj = SLOT(p->p_ucred->cr_label);
2114
2115         /* XXX: range checks */
2116         if (!biba_dominate_effective(obj, subj))
2117                 return (ESRCH);
2118         if (!biba_dominate_effective(subj, obj))
2119                 return (EACCES);
2120
2121         return (0);
2122 }
2123
2124 static int
2125 biba_check_proc_sched(struct ucred *cred, struct proc *p)
2126 {
2127         struct mac_biba *subj, *obj;
2128
2129         if (!biba_enabled)
2130                 return (0);
2131
2132         subj = SLOT(cred->cr_label);
2133         obj = SLOT(p->p_ucred->cr_label);
2134
2135         /* XXX: range checks */
2136         if (!biba_dominate_effective(obj, subj))
2137                 return (ESRCH);
2138         if (!biba_dominate_effective(subj, obj))
2139                 return (EACCES);
2140
2141         return (0);
2142 }
2143
2144 static int
2145 biba_check_proc_signal(struct ucred *cred, struct proc *p, int signum)
2146 {
2147         struct mac_biba *subj, *obj;
2148
2149         if (!biba_enabled)
2150                 return (0);
2151
2152         subj = SLOT(cred->cr_label);
2153         obj = SLOT(p->p_ucred->cr_label);
2154
2155         /* XXX: range checks */
2156         if (!biba_dominate_effective(obj, subj))
2157                 return (ESRCH);
2158         if (!biba_dominate_effective(subj, obj))
2159                 return (EACCES);
2160
2161         return (0);
2162 }
2163
2164 static int
2165 biba_check_socket_deliver(struct socket *so, struct label *solabel,
2166     struct mbuf *m, struct label *mlabel)
2167 {
2168         struct mac_biba *p, *s;
2169
2170         if (!biba_enabled)
2171                 return (0);
2172
2173         p = SLOT(mlabel);
2174         s = SLOT(solabel);
2175
2176         return (biba_equal_effective(p, s) ? 0 : EACCES);
2177 }
2178
2179 static int
2180 biba_check_socket_relabel(struct ucred *cred, struct socket *so,
2181     struct label *solabel, struct label *newlabel)
2182 {
2183         struct mac_biba *subj, *obj, *new;
2184         int error;
2185
2186         new = SLOT(newlabel);
2187         subj = SLOT(cred->cr_label);
2188         obj = SLOT(solabel);
2189
2190         /*
2191          * If there is a Biba label update for the socket, it may be an
2192          * update of effective.
2193          */
2194         error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
2195         if (error)
2196                 return (error);
2197
2198         /*
2199          * To relabel a socket, the old socket effective must be in the
2200          * subject range.
2201          */
2202         if (!biba_effective_in_range(obj, subj))
2203                 return (EPERM);
2204
2205         /*
2206          * If the Biba label is to be changed, authorize as appropriate.
2207          */
2208         if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
2209                 /*
2210                  * To relabel a socket, the new socket effective must be in
2211                  * the subject range.
2212                  */
2213                 if (!biba_effective_in_range(new, subj))
2214                         return (EPERM);
2215
2216                 /*
2217                  * To change the Biba label on the socket to contain EQUAL,
2218                  * the subject must have appropriate privilege.
2219                  */
2220                 if (biba_contains_equal(new)) {
2221                         error = biba_subject_privileged(subj);
2222                         if (error)
2223                                 return (error);
2224                 }
2225         }
2226
2227         return (0);
2228 }
2229
2230 static int
2231 biba_check_socket_visible(struct ucred *cred, struct socket *so,
2232     struct label *solabel)
2233 {
2234         struct mac_biba *subj, *obj;
2235
2236         if (!biba_enabled)
2237                 return (0);
2238
2239         subj = SLOT(cred->cr_label);
2240         obj = SLOT(solabel);
2241
2242         if (!biba_dominate_effective(obj, subj))
2243                 return (ENOENT);
2244
2245         return (0);
2246 }
2247
2248 /*
2249  * Some system privileges are allowed regardless of integrity grade; others
2250  * are allowed only when running with privilege with respect to the Biba
2251  * policy as they might otherwise allow bypassing of the integrity policy.
2252  */
2253 static int
2254 biba_priv_check(struct ucred *cred, int priv)
2255 {
2256         struct mac_biba *subj;
2257         int error;
2258
2259         if (!biba_enabled)
2260                 return (0);
2261
2262         /*
2263          * Exempt only specific privileges from the Biba integrity policy.
2264          */
2265         switch (priv) {
2266         case PRIV_KTRACE:
2267         case PRIV_MSGBUF:
2268
2269         /*
2270          * Allow processes to manipulate basic process audit properties, and
2271          * to submit audit records.
2272          */
2273         case PRIV_AUDIT_GETAUDIT:
2274         case PRIV_AUDIT_SETAUDIT:
2275         case PRIV_AUDIT_SUBMIT:
2276
2277         /*
2278          * Allow processes to manipulate their regular UNIX credentials.
2279          */
2280         case PRIV_CRED_SETUID:
2281         case PRIV_CRED_SETEUID:
2282         case PRIV_CRED_SETGID:
2283         case PRIV_CRED_SETEGID:
2284         case PRIV_CRED_SETGROUPS:
2285         case PRIV_CRED_SETREUID:
2286         case PRIV_CRED_SETREGID:
2287         case PRIV_CRED_SETRESUID:
2288         case PRIV_CRED_SETRESGID:
2289
2290         /*
2291          * Allow processes to perform system monitoring.
2292          */
2293         case PRIV_SEEOTHERGIDS:
2294         case PRIV_SEEOTHERUIDS:
2295                 break;
2296
2297         /*
2298          * Allow access to general process debugging facilities.  We
2299          * separately control debugging based on MAC label.
2300          */
2301         case PRIV_DEBUG_DIFFCRED:
2302         case PRIV_DEBUG_SUGID:
2303         case PRIV_DEBUG_UNPRIV:
2304
2305         /*
2306          * Allow manipulating jails.
2307          */
2308         case PRIV_JAIL_ATTACH:
2309
2310         /*
2311          * Allow privilege with respect to the Partition policy, but not the
2312          * Privs policy.
2313          */
2314         case PRIV_MAC_PARTITION:
2315
2316         /*
2317          * Allow privilege with respect to process resource limits and login
2318          * context.
2319          */
2320         case PRIV_PROC_LIMIT:
2321         case PRIV_PROC_SETLOGIN:
2322         case PRIV_PROC_SETRLIMIT:
2323
2324         /*
2325          * Allow System V and POSIX IPC privileges.
2326          */
2327         case PRIV_IPC_READ:
2328         case PRIV_IPC_WRITE:
2329         case PRIV_IPC_ADMIN:
2330         case PRIV_IPC_MSGSIZE:
2331         case PRIV_MQ_ADMIN:
2332
2333         /*
2334          * Allow certain scheduler manipulations -- possibly this should be
2335          * controlled by more fine-grained policy, as potentially low
2336          * integrity processes can deny CPU to higher integrity ones.
2337          */
2338         case PRIV_SCHED_DIFFCRED:
2339         case PRIV_SCHED_SETPRIORITY:
2340         case PRIV_SCHED_RTPRIO:
2341         case PRIV_SCHED_SETPOLICY:
2342         case PRIV_SCHED_SET:
2343         case PRIV_SCHED_SETPARAM:
2344
2345         /*
2346          * More IPC privileges.
2347          */
2348         case PRIV_SEM_WRITE:
2349
2350         /*
2351          * Allow signaling privileges subject to integrity policy.
2352          */
2353         case PRIV_SIGNAL_DIFFCRED:
2354         case PRIV_SIGNAL_SUGID:
2355
2356         /*
2357          * Allow access to only limited sysctls from lower integrity levels;
2358          * piggy-back on the Jail definition.
2359          */
2360         case PRIV_SYSCTL_WRITEJAIL:
2361
2362         /*
2363          * Allow TTY-based privileges, subject to general device access using
2364          * labels on TTY device nodes, but not console privilege.
2365          */
2366         case PRIV_TTY_DRAINWAIT:
2367         case PRIV_TTY_DTRWAIT:
2368         case PRIV_TTY_EXCLUSIVE:
2369         case PRIV_TTY_PRISON:
2370         case PRIV_TTY_STI:
2371         case PRIV_TTY_SETA:
2372
2373         /*
2374          * Grant most VFS privileges, as almost all are in practice bounded
2375          * by more specific checks using labels.
2376          */
2377         case PRIV_VFS_READ:
2378         case PRIV_VFS_WRITE:
2379         case PRIV_VFS_ADMIN:
2380         case PRIV_VFS_EXEC:
2381         case PRIV_VFS_LOOKUP:
2382         case PRIV_VFS_CHFLAGS_DEV:
2383         case PRIV_VFS_CHOWN:
2384         case PRIV_VFS_CHROOT:
2385         case PRIV_VFS_RETAINSUGID:
2386         case PRIV_VFS_EXCEEDQUOTA:
2387         case PRIV_VFS_FCHROOT:
2388         case PRIV_VFS_FHOPEN:
2389         case PRIV_VFS_FHSTATFS:
2390         case PRIV_VFS_GENERATION:
2391         case PRIV_VFS_GETFH:
2392         case PRIV_VFS_GETQUOTA:
2393         case PRIV_VFS_LINK:
2394         case PRIV_VFS_MOUNT:
2395         case PRIV_VFS_MOUNT_OWNER:
2396         case PRIV_VFS_MOUNT_PERM:
2397         case PRIV_VFS_MOUNT_SUIDDIR:
2398         case PRIV_VFS_MOUNT_NONUSER:
2399         case PRIV_VFS_SETGID:
2400         case PRIV_VFS_STICKYFILE:
2401         case PRIV_VFS_SYSFLAGS:
2402         case PRIV_VFS_UNMOUNT:
2403
2404         /*
2405          * Allow VM privileges; it would be nice if these were subject to
2406          * resource limits.
2407          */
2408         case PRIV_VM_MADV_PROTECT:
2409         case PRIV_VM_MLOCK:
2410         case PRIV_VM_MUNLOCK:
2411
2412         /*
2413          * Allow some but not all network privileges.  In general, dont allow
2414          * reconfiguring the network stack, just normal use.
2415          */
2416         case PRIV_NETATALK_RESERVEDPORT:
2417         case PRIV_NETINET_RESERVEDPORT:
2418         case PRIV_NETINET_RAW:
2419         case PRIV_NETINET_REUSEPORT:
2420         case PRIV_NETIPX_RESERVEDPORT:
2421         case PRIV_NETIPX_RAW:
2422                 break;
2423
2424         /*
2425          * All remaining system privileges are allow only if the process
2426          * holds privilege with respect to the Biba policy.
2427          */
2428         default:
2429                 subj = SLOT(cred->cr_label);
2430                 error = biba_subject_privileged(subj);
2431                 if (error)
2432                         return (error);
2433         }
2434         return (0);
2435 }
2436
2437 static int
2438 biba_check_system_acct(struct ucred *cred, struct vnode *vp,
2439     struct label *vplabel)
2440 {
2441         struct mac_biba *subj, *obj;
2442         int error;
2443
2444         if (!biba_enabled)
2445                 return (0);
2446
2447         subj = SLOT(cred->cr_label);
2448
2449         error = biba_subject_privileged(subj);
2450         if (error)
2451                 return (error);
2452
2453         if (vplabel == NULL)
2454                 return (0);
2455
2456         obj = SLOT(vplabel);
2457         if (!biba_high_effective(obj))
2458                 return (EACCES);
2459
2460         return (0);
2461 }
2462
2463 static int
2464 biba_check_system_auditctl(struct ucred *cred, struct vnode *vp,
2465     struct label *vplabel)
2466 {
2467         struct mac_biba *subj, *obj;
2468         int error;
2469
2470         if (!biba_enabled)
2471                 return (0);
2472
2473         subj = SLOT(cred->cr_label);
2474
2475         error = biba_subject_privileged(subj);
2476         if (error)
2477                 return (error);
2478
2479         if (vplabel == NULL)
2480                 return (0);
2481
2482         obj = SLOT(vplabel);
2483         if (!biba_high_effective(obj))
2484                 return (EACCES);
2485
2486         return (0);
2487 }
2488
2489 static int
2490 biba_check_system_auditon(struct ucred *cred, int cmd)
2491 {
2492         struct mac_biba *subj;
2493         int error;
2494
2495         if (!biba_enabled)
2496                 return (0);
2497
2498         subj = SLOT(cred->cr_label);
2499
2500         error = biba_subject_privileged(subj);
2501         if (error)
2502                 return (error);
2503
2504         return (0);
2505 }
2506
2507 static int
2508 biba_check_system_swapon(struct ucred *cred, struct vnode *vp,
2509     struct label *vplabel)
2510 {
2511         struct mac_biba *subj, *obj;
2512         int error;
2513
2514         if (!biba_enabled)
2515                 return (0);
2516
2517         subj = SLOT(cred->cr_label);
2518         obj = SLOT(vplabel);
2519
2520         error = biba_subject_privileged(subj);
2521         if (error)
2522                 return (error);
2523
2524         if (!biba_high_effective(obj))
2525                 return (EACCES);
2526
2527         return (0);
2528 }
2529
2530 static int
2531 biba_check_system_swapoff(struct ucred *cred, struct vnode *vp,
2532     struct label *label)
2533 {
2534         struct mac_biba *subj;
2535         int error;
2536
2537         if (!biba_enabled)
2538                 return (0);
2539
2540         subj = SLOT(cred->cr_label);
2541
2542         error = biba_subject_privileged(subj);
2543         if (error)
2544                 return (error);
2545
2546         return (0);
2547 }
2548
2549 static int
2550 biba_check_system_sysctl(struct ucred *cred, struct sysctl_oid *oidp,
2551     void *arg1, int arg2, struct sysctl_req *req)
2552 {
2553         struct mac_biba *subj;
2554         int error;
2555
2556         if (!biba_enabled)
2557                 return (0);
2558
2559         subj = SLOT(cred->cr_label);
2560
2561         /*
2562          * Treat sysctl variables without CTLFLAG_ANYBODY flag as biba/high,
2563          * but also require privilege to change them.
2564          */
2565         if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) {
2566                 if (!biba_subject_dominate_high(subj))
2567                         return (EACCES);
2568
2569                 error = biba_subject_privileged(subj);
2570                 if (error)
2571                         return (error);
2572         }
2573
2574         return (0);
2575 }
2576
2577 static int
2578 biba_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
2579     struct label *dvplabel)
2580 {
2581         struct mac_biba *subj, *obj;
2582
2583         if (!biba_enabled)
2584                 return (0);
2585
2586         subj = SLOT(cred->cr_label);
2587         obj = SLOT(dvplabel);
2588
2589         if (!biba_dominate_effective(obj, subj))
2590                 return (EACCES);
2591
2592         return (0);
2593 }
2594
2595 static int
2596 biba_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
2597     struct label *dvplabel)
2598 {
2599         struct mac_biba *subj, *obj;
2600
2601         if (!biba_enabled)
2602                 return (0);
2603
2604         subj = SLOT(cred->cr_label);
2605         obj = SLOT(dvplabel);
2606
2607         if (!biba_dominate_effective(obj, subj))
2608                 return (EACCES);
2609
2610         return (0);
2611 }
2612
2613 static int
2614 biba_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2615     struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2616 {
2617         struct mac_biba *subj, *obj;
2618
2619         if (!biba_enabled)
2620                 return (0);
2621
2622         subj = SLOT(cred->cr_label);
2623         obj = SLOT(dvplabel);
2624
2625         if (!biba_dominate_effective(subj, obj))
2626                 return (EACCES);
2627
2628         return (0);
2629 }
2630
2631 static int
2632 biba_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2633     struct label *vplabel, acl_type_t type)
2634 {
2635         struct mac_biba *subj, *obj;
2636
2637         if (!biba_enabled)
2638                 return (0);
2639
2640         subj = SLOT(cred->cr_label);
2641         obj = SLOT(vplabel);
2642
2643         if (!biba_dominate_effective(subj, obj))
2644                 return (EACCES);
2645
2646         return (0);
2647 }
2648
2649 static int
2650 biba_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
2651     struct label *vplabel, int attrnamespace, const char *name)
2652 {
2653         struct mac_biba *subj, *obj;
2654
2655         if (!biba_enabled)
2656                 return (0);
2657
2658         subj = SLOT(cred->cr_label);
2659         obj = SLOT(vplabel);
2660
2661         if (!biba_dominate_effective(subj, obj))
2662                 return (EACCES);
2663
2664         return (0);
2665 }
2666
2667 static int
2668 biba_check_vnode_exec(struct ucred *cred, struct vnode *vp,
2669     struct label *vplabel, struct image_params *imgp,
2670     struct label *execlabel)
2671 {
2672         struct mac_biba *subj, *obj, *exec;
2673         int error;
2674
2675         if (execlabel != NULL) {
2676                 /*
2677                  * We currently don't permit labels to be changed at
2678                  * exec-time as part of Biba, so disallow non-NULL Biba label
2679                  * elements in the execlabel.
2680                  */
2681                 exec = SLOT(execlabel);
2682                 error = biba_atmostflags(exec, 0);
2683                 if (error)
2684                         return (error);
2685         }
2686
2687         if (!biba_enabled)
2688                 return (0);
2689
2690         subj = SLOT(cred->cr_label);
2691         obj = SLOT(vplabel);
2692
2693         if (!biba_dominate_effective(obj, subj))
2694                 return (EACCES);
2695
2696         return (0);
2697 }
2698
2699 static int
2700 biba_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
2701     struct label *vplabel, acl_type_t type)
2702 {
2703         struct mac_biba *subj, *obj;
2704
2705         if (!biba_enabled)
2706                 return (0);
2707
2708         subj = SLOT(cred->cr_label);
2709         obj = SLOT(vplabel);
2710
2711         if (!biba_dominate_effective(obj, subj))
2712                 return (EACCES);
2713
2714         return (0);
2715 }
2716
2717 static int
2718 biba_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2719     struct label *vplabel, int attrnamespace, const char *name,
2720     struct uio *uio)
2721 {
2722         struct mac_biba *subj, *obj;
2723
2724         if (!biba_enabled)
2725                 return (0);
2726
2727         subj = SLOT(cred->cr_label);
2728         obj = SLOT(vplabel);
2729
2730         if (!biba_dominate_effective(obj, subj))
2731                 return (EACCES);
2732
2733         return (0);
2734 }
2735
2736 static int
2737 biba_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2738     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2739     struct componentname *cnp)
2740 {
2741         struct mac_biba *subj, *obj;
2742
2743         if (!biba_enabled)
2744                 return (0);
2745
2746         subj = SLOT(cred->cr_label);
2747         obj = SLOT(dvplabel);
2748
2749         if (!biba_dominate_effective(subj, obj))
2750                 return (EACCES);
2751
2752         obj = SLOT(vplabel);
2753
2754         if (!biba_dominate_effective(subj, obj))
2755                 return (EACCES);
2756
2757         return (0);
2758 }
2759
2760 static int
2761 biba_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
2762     struct label *vplabel, int attrnamespace)
2763 {
2764         struct mac_biba *subj, *obj;
2765
2766         if (!biba_enabled)
2767                 return (0);
2768
2769         subj = SLOT(cred->cr_label);
2770         obj = SLOT(vplabel);
2771
2772         if (!biba_dominate_effective(obj, subj))
2773                 return (EACCES);
2774
2775         return (0);
2776 }
2777
2778 static int
2779 biba_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2780     struct label *dvplabel, struct componentname *cnp)
2781 {
2782         struct mac_biba *subj, *obj;
2783
2784         if (!biba_enabled)
2785                 return (0);
2786
2787         subj = SLOT(cred->cr_label);
2788         obj = SLOT(dvplabel);
2789
2790         if (!biba_dominate_effective(obj, subj))
2791                 return (EACCES);
2792
2793         return (0);
2794 }
2795
2796 static int
2797 biba_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2798     struct label *vplabel, int prot, int flags)
2799 {
2800         struct mac_biba *subj, *obj;
2801
2802         /*
2803          * Rely on the use of open()-time protections to handle
2804          * non-revocation cases.
2805          */
2806         if (!biba_enabled || !revocation_enabled)
2807                 return (0);
2808
2809         subj = SLOT(cred->cr_label);
2810         obj = SLOT(vplabel);
2811
2812         if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2813                 if (!biba_dominate_effective(obj, subj))
2814                         return (EACCES);
2815         }
2816         if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2817                 if (!biba_dominate_effective(subj, obj))
2818                         return (EACCES);
2819         }
2820
2821         return (0);
2822 }
2823
2824 static int
2825 biba_check_vnode_open(struct ucred *cred, struct vnode *vp,
2826     struct label *vplabel, int acc_mode)
2827 {
2828         struct mac_biba *subj, *obj;
2829
2830         if (!biba_enabled)
2831                 return (0);
2832
2833         subj = SLOT(cred->cr_label);
2834         obj = SLOT(vplabel);
2835
2836         /* XXX privilege override for admin? */
2837         if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2838                 if (!biba_dominate_effective(obj, subj))
2839                         return (EACCES);
2840         }
2841         if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2842                 if (!biba_dominate_effective(subj, obj))
2843                         return (EACCES);
2844         }
2845
2846         return (0);
2847 }
2848
2849 static int
2850 biba_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2851     struct vnode *vp, struct label *vplabel)
2852 {
2853         struct mac_biba *subj, *obj;
2854
2855         if (!biba_enabled || !revocation_enabled)
2856                 return (0);
2857
2858         subj = SLOT(active_cred->cr_label);
2859         obj = SLOT(vplabel);
2860
2861         if (!biba_dominate_effective(obj, subj))
2862                 return (EACCES);
2863
2864         return (0);
2865 }
2866
2867 static int
2868 biba_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2869     struct vnode *vp, struct label *vplabel)
2870 {
2871         struct mac_biba *subj, *obj;
2872
2873         if (!biba_enabled || !revocation_enabled)
2874                 return (0);
2875
2876         subj = SLOT(active_cred->cr_label);
2877         obj = SLOT(vplabel);
2878
2879         if (!biba_dominate_effective(obj, subj))
2880                 return (EACCES);
2881
2882         return (0);
2883 }
2884
2885 static int
2886 biba_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
2887     struct label *dvplabel)
2888 {
2889         struct mac_biba *subj, *obj;
2890
2891         if (!biba_enabled)
2892                 return (0);
2893
2894         subj = SLOT(cred->cr_label);
2895         obj = SLOT(dvplabel);
2896
2897         if (!biba_dominate_effective(obj, subj))
2898                 return (EACCES);
2899
2900         return (0);
2901 }
2902
2903 static int
2904 biba_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
2905     struct label *vplabel)
2906 {
2907         struct mac_biba *subj, *obj;
2908
2909         if (!biba_enabled)
2910                 return (0);
2911
2912         subj = SLOT(cred->cr_label);
2913         obj = SLOT(vplabel);
2914
2915         if (!biba_dominate_effective(obj, subj))
2916                 return (EACCES);
2917
2918         return (0);
2919 }
2920
2921 static int
2922 biba_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2923     struct label *vplabel, struct label *newlabel)
2924 {
2925         struct mac_biba *old, *new, *subj;
2926         int error;
2927
2928         old = SLOT(vplabel);
2929         new = SLOT(newlabel);
2930         subj = SLOT(cred->cr_label);
2931
2932         /*
2933          * If there is a Biba label update for the vnode, it must be a
2934          * effective label.
2935          */
2936         error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
2937         if (error)
2938                 return (error);
2939
2940         /*
2941          * To perform a relabel of the vnode (Biba label or not), Biba must
2942          * authorize the relabel.
2943          */
2944         if (!biba_effective_in_range(old, subj))
2945                 return (EPERM);
2946
2947         /*
2948          * If the Biba label is to be changed, authorize as appropriate.
2949          */
2950         if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
2951                 /*
2952                  * To change the Biba label on a vnode, the new vnode label
2953                  * must be in the subject range.
2954                  */
2955                 if (!biba_effective_in_range(new, subj))
2956                         return (EPERM);
2957
2958                 /*
2959                  * To change the Biba label on the vnode to be EQUAL, the
2960                  * subject must have appropriate privilege.
2961                  */
2962                 if (biba_contains_equal(new)) {
2963                         error = biba_subject_privileged(subj);
2964                         if (error)
2965                                 return (error);
2966                 }
2967         }
2968
2969         return (0);
2970 }
2971
2972 static int
2973 biba_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2974     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2975     struct componentname *cnp)
2976 {
2977         struct mac_biba *subj, *obj;
2978
2979         if (!biba_enabled)
2980                 return (0);
2981
2982         subj = SLOT(cred->cr_label);
2983         obj = SLOT(dvplabel);
2984
2985         if (!biba_dominate_effective(subj, obj))
2986                 return (EACCES);
2987
2988         obj = SLOT(vplabel);
2989
2990         if (!biba_dominate_effective(subj, obj))
2991                 return (EACCES);
2992
2993         return (0);
2994 }
2995
2996 static int
2997 biba_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2998     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2999     int samedir, struct componentname *cnp)
3000 {
3001         struct mac_biba *subj, *obj;
3002
3003         if (!biba_enabled)
3004                 return (0);
3005
3006         subj = SLOT(cred->cr_label);
3007         obj = SLOT(dvplabel);
3008
3009         if (!biba_dominate_effective(subj, obj))
3010                 return (EACCES);
3011
3012         if (vp != NULL) {
3013                 obj = SLOT(vplabel);
3014
3015                 if (!biba_dominate_effective(subj, obj))
3016                         return (EACCES);
3017         }
3018
3019         return (0);
3020 }
3021
3022 static int
3023 biba_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
3024     struct label *vplabel)
3025 {
3026         struct mac_biba *subj, *obj;
3027
3028         if (!biba_enabled)
3029                 return (0);
3030
3031         subj = SLOT(cred->cr_label);
3032         obj = SLOT(vplabel);
3033
3034         if (!biba_dominate_effective(subj, obj))
3035                 return (EACCES);
3036
3037         return (0);
3038 }
3039
3040 static int
3041 biba_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
3042     struct label *vplabel, acl_type_t type, struct acl *acl)
3043 {
3044         struct mac_biba *subj, *obj;
3045
3046         if (!biba_enabled)
3047                 return (0);
3048
3049         subj = SLOT(cred->cr_label);
3050         obj = SLOT(vplabel);
3051
3052         if (!biba_dominate_effective(subj, obj))
3053                 return (EACCES);
3054
3055         return (0);
3056 }
3057
3058 static int
3059 biba_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
3060     struct label *vplabel, int attrnamespace, const char *name,
3061     struct uio *uio)
3062 {
3063         struct mac_biba *subj, *obj;
3064
3065         if (!biba_enabled)
3066                 return (0);
3067
3068         subj = SLOT(cred->cr_label);
3069         obj = SLOT(vplabel);
3070
3071         if (!biba_dominate_effective(subj, obj))
3072                 return (EACCES);
3073
3074         /* XXX: protect the MAC EA in a special way? */
3075
3076         return (0);
3077 }
3078
3079 static int
3080 biba_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
3081     struct label *vplabel, u_long flags)
3082 {
3083         struct mac_biba *subj, *obj;
3084
3085         if (!biba_enabled)
3086                 return (0);
3087
3088         subj = SLOT(cred->cr_label);
3089         obj = SLOT(vplabel);
3090
3091         if (!biba_dominate_effective(subj, obj))
3092                 return (EACCES);
3093
3094         return (0);
3095 }
3096
3097 static int
3098 biba_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
3099     struct label *vplabel, mode_t mode)
3100 {
3101         struct mac_biba *subj, *obj;
3102
3103         if (!biba_enabled)
3104                 return (0);
3105
3106         subj = SLOT(cred->cr_label);
3107         obj = SLOT(vplabel);
3108
3109         if (!biba_dominate_effective(subj, obj))
3110                 return (EACCES);
3111
3112         return (0);
3113 }
3114
3115 static int
3116 biba_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
3117     struct label *vplabel, uid_t uid, gid_t gid)
3118 {
3119         struct mac_biba *subj, *obj;
3120
3121         if (!biba_enabled)
3122                 return (0);
3123
3124         subj = SLOT(cred->cr_label);
3125         obj = SLOT(vplabel);
3126
3127         if (!biba_dominate_effective(subj, obj))
3128                 return (EACCES);
3129
3130         return (0);
3131 }
3132
3133 static int
3134 biba_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
3135     struct label *vplabel, struct timespec atime, struct timespec mtime)
3136 {
3137         struct mac_biba *subj, *obj;
3138
3139         if (!biba_enabled)
3140                 return (0);
3141
3142         subj = SLOT(cred->cr_label);
3143         obj = SLOT(vplabel);
3144
3145         if (!biba_dominate_effective(subj, obj))
3146                 return (EACCES);
3147
3148         return (0);
3149 }
3150
3151 static int
3152 biba_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
3153     struct vnode *vp, struct label *vplabel)
3154 {
3155         struct mac_biba *subj, *obj;
3156
3157         if (!biba_enabled)
3158                 return (0);
3159
3160         subj = SLOT(active_cred->cr_label);
3161         obj = SLOT(vplabel);
3162
3163         if (!biba_dominate_effective(obj, subj))
3164                 return (EACCES);
3165
3166         return (0);
3167 }
3168
3169 static int
3170 biba_check_vnode_unlink(struct ucred *cred, struct vnode *dvp,
3171     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
3172     struct componentname *cnp)
3173 {
3174         struct mac_biba *subj, *obj;
3175
3176         if (!biba_enabled)
3177                 return (0);
3178
3179         subj = SLOT(cred->cr_label);
3180         obj = SLOT(dvplabel);
3181
3182         if (!biba_dominate_effective(subj, obj))
3183                 return (EACCES);
3184
3185         obj = SLOT(vplabel);
3186
3187         if (!biba_dominate_effective(subj, obj))
3188                 return (EACCES);
3189
3190         return (0);
3191 }
3192
3193 static int
3194 biba_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
3195     struct vnode *vp, struct label *vplabel)
3196 {
3197         struct mac_biba *subj, *obj;
3198
3199         if (!biba_enabled || !revocation_enabled)
3200                 return (0);
3201
3202         subj = SLOT(active_cred->cr_label);
3203         obj = SLOT(vplabel);
3204
3205         if (!biba_dominate_effective(subj, obj))
3206                 return (EACCES);
3207
3208         return (0);
3209 }
3210
3211 static void
3212 biba_associate_nfsd_label(struct ucred *cred)
3213 {
3214         struct mac_biba *label;
3215
3216         label = SLOT(cred->cr_label);
3217         biba_set_effective(label, MAC_BIBA_TYPE_LOW, 0, NULL);
3218         biba_set_range(label, MAC_BIBA_TYPE_LOW, 0, NULL, MAC_BIBA_TYPE_HIGH,
3219             0, NULL);
3220 }
3221
3222 static void
3223 biba_init_syncache_from_inpcb(struct label *label, struct inpcb *inp)
3224 {
3225         struct mac_biba *source, *dest;
3226
3227         source = SLOT(inp->inp_label);
3228         dest = SLOT(label);
3229         biba_copy_effective(source, dest);
3230 }
3231
3232 static void
3233 biba_create_mbuf_from_syncache(struct label *sc_label, struct mbuf *m,
3234     struct label *mlabel)
3235 {
3236         struct mac_biba *source, *dest;
3237
3238         source = SLOT(sc_label);
3239         dest = SLOT(mlabel);
3240         biba_copy_effective(source, dest);
3241 }
3242
3243 static struct mac_policy_ops mac_biba_ops =
3244 {
3245         .mpo_init = biba_init,
3246         .mpo_init_bpfdesc_label = biba_init_label,
3247         .mpo_init_cred_label = biba_init_label,
3248         .mpo_init_devfs_label = biba_init_label,
3249         .mpo_init_ifnet_label = biba_init_label,
3250         .mpo_init_inpcb_label = biba_init_label_waitcheck,
3251         .mpo_init_syncache_label = biba_init_label_waitcheck,
3252         .mpo_init_sysv_msgmsg_label = biba_init_label,
3253         .mpo_init_sysv_msgqueue_label = biba_init_label,
3254         .mpo_init_sysv_sem_label = biba_init_label,
3255         .mpo_init_sysv_shm_label = biba_init_label,
3256         .mpo_init_ipq_label = biba_init_label_waitcheck,
3257         .mpo_init_mbuf_label = biba_init_label_waitcheck,
3258         .mpo_init_mount_label = biba_init_label,
3259         .mpo_init_pipe_label = biba_init_label,
3260         .mpo_init_posix_sem_label = biba_init_label,
3261         .mpo_init_socket_label = biba_init_label_waitcheck,
3262         .mpo_init_socket_peer_label = biba_init_label_waitcheck,
3263         .mpo_init_syncache_from_inpcb = biba_init_syncache_from_inpcb,
3264         .mpo_init_vnode_label = biba_init_label,
3265         .mpo_destroy_bpfdesc_label = biba_destroy_label,
3266         .mpo_destroy_cred_label = biba_destroy_label,
3267         .mpo_destroy_devfs_label = biba_destroy_label,
3268         .mpo_destroy_ifnet_label = biba_destroy_label,
3269         .mpo_destroy_inpcb_label = biba_destroy_label,
3270         .mpo_destroy_syncache_label = biba_destroy_label,
3271         .mpo_destroy_sysv_msgmsg_label = biba_destroy_label,
3272         .mpo_destroy_sysv_msgqueue_label = biba_destroy_label,
3273         .mpo_destroy_sysv_sem_label = biba_destroy_label,
3274         .mpo_destroy_sysv_shm_label = biba_destroy_label,
3275         .mpo_destroy_ipq_label = biba_destroy_label,
3276         .mpo_destroy_mbuf_label = biba_destroy_label,
3277         .mpo_destroy_mount_label = biba_destroy_label,
3278         .mpo_destroy_pipe_label = biba_destroy_label,
3279         .mpo_destroy_posix_sem_label = biba_destroy_label,
3280         .mpo_destroy_socket_label = biba_destroy_label,
3281         .mpo_destroy_socket_peer_label = biba_destroy_label,
3282         .mpo_destroy_vnode_label = biba_destroy_label,
3283         .mpo_copy_cred_label = biba_copy_label,
3284         .mpo_copy_ifnet_label = biba_copy_label,
3285         .mpo_copy_mbuf_label = biba_copy_label,
3286         .mpo_copy_pipe_label = biba_copy_label,
3287         .mpo_copy_socket_label = biba_copy_label,
3288         .mpo_copy_vnode_label = biba_copy_label,
3289         .mpo_externalize_cred_label = biba_externalize_label,
3290         .mpo_externalize_ifnet_label = biba_externalize_label,
3291         .mpo_externalize_pipe_label = biba_externalize_label,
3292         .mpo_externalize_socket_label = biba_externalize_label,
3293         .mpo_externalize_socket_peer_label = biba_externalize_label,
3294         .mpo_externalize_vnode_label = biba_externalize_label,
3295         .mpo_internalize_cred_label = biba_internalize_label,
3296         .mpo_internalize_ifnet_label = biba_internalize_label,
3297         .mpo_internalize_pipe_label = biba_internalize_label,
3298         .mpo_internalize_socket_label = biba_internalize_label,
3299         .mpo_internalize_vnode_label = biba_internalize_label,
3300         .mpo_create_devfs_device = biba_create_devfs_device,
3301         .mpo_create_devfs_directory = biba_create_devfs_directory,
3302         .mpo_create_devfs_symlink = biba_create_devfs_symlink,
3303         .mpo_create_mount = biba_create_mount,
3304         .mpo_relabel_vnode = biba_relabel_vnode,
3305         .mpo_update_devfs = biba_update_devfs,
3306         .mpo_associate_vnode_devfs = biba_associate_vnode_devfs,
3307         .mpo_associate_vnode_extattr = biba_associate_vnode_extattr,
3308         .mpo_associate_vnode_singlelabel = biba_associate_vnode_singlelabel,
3309         .mpo_create_vnode_extattr = biba_create_vnode_extattr,
3310         .mpo_setlabel_vnode_extattr = biba_setlabel_vnode_extattr,
3311         .mpo_create_mbuf_from_socket = biba_create_mbuf_from_socket,
3312         .mpo_create_mbuf_from_syncache = biba_create_mbuf_from_syncache,
3313         .mpo_create_pipe = biba_create_pipe,
3314         .mpo_create_posix_sem = biba_create_posix_sem,
3315         .mpo_create_socket = biba_create_socket,
3316         .mpo_create_socket_from_socket = biba_create_socket_from_socket,
3317         .mpo_relabel_pipe = biba_relabel_pipe,
3318         .mpo_relabel_socket = biba_relabel_socket,
3319         .mpo_set_socket_peer_from_mbuf = biba_set_socket_peer_from_mbuf,
3320         .mpo_set_socket_peer_from_socket = biba_set_socket_peer_from_socket,
3321         .mpo_create_bpfdesc = biba_create_bpfdesc,
3322         .mpo_create_datagram_from_ipq = biba_create_datagram_from_ipq,
3323         .mpo_create_fragment = biba_create_fragment,
3324         .mpo_create_ifnet = biba_create_ifnet,
3325         .mpo_create_inpcb_from_socket = biba_create_inpcb_from_socket,
3326         .mpo_create_sysv_msgmsg = biba_create_sysv_msgmsg,
3327         .mpo_create_sysv_msgqueue = biba_create_sysv_msgqueue,
3328         .mpo_create_sysv_sem = biba_create_sysv_sem,
3329         .mpo_create_sysv_shm = biba_create_sysv_shm,
3330         .mpo_create_ipq = biba_create_ipq,
3331         .mpo_create_mbuf_from_inpcb = biba_create_mbuf_from_inpcb,
3332         .mpo_create_mbuf_linklayer = biba_create_mbuf_linklayer,
3333         .mpo_create_mbuf_from_bpfdesc = biba_create_mbuf_from_bpfdesc,
3334         .mpo_create_mbuf_from_ifnet = biba_create_mbuf_from_ifnet,
3335         .mpo_create_mbuf_multicast_encap = biba_create_mbuf_multicast_encap,
3336         .mpo_create_mbuf_netlayer = biba_create_mbuf_netlayer,
3337         .mpo_fragment_match = biba_fragment_match,
3338         .mpo_relabel_ifnet = biba_relabel_ifnet,
3339         .mpo_update_ipq = biba_update_ipq,
3340         .mpo_inpcb_sosetlabel = biba_inpcb_sosetlabel,
3341         .mpo_create_proc0 = biba_create_proc0,
3342         .mpo_create_proc1 = biba_create_proc1,
3343         .mpo_relabel_cred = biba_relabel_cred,
3344         .mpo_cleanup_sysv_msgmsg = biba_cleanup_sysv_msgmsg,
3345         .mpo_cleanup_sysv_msgqueue = biba_cleanup_sysv_msgqueue,
3346         .mpo_cleanup_sysv_sem = biba_cleanup_sysv_sem,
3347         .mpo_cleanup_sysv_shm = biba_cleanup_sysv_shm,
3348         .mpo_check_bpfdesc_receive = biba_check_bpfdesc_receive,
3349         .mpo_check_cred_relabel = biba_check_cred_relabel,
3350         .mpo_check_cred_visible = biba_check_cred_visible,
3351         .mpo_check_ifnet_relabel = biba_check_ifnet_relabel,
3352         .mpo_check_ifnet_transmit = biba_check_ifnet_transmit,
3353         .mpo_check_inpcb_deliver = biba_check_inpcb_deliver,
3354         .mpo_check_inpcb_visible = biba_check_inpcb_visible,
3355         .mpo_check_sysv_msgrcv = biba_check_sysv_msgrcv,
3356         .mpo_check_sysv_msgrmid = biba_check_sysv_msgrmid,
3357         .mpo_check_sysv_msqget = biba_check_sysv_msqget,
3358         .mpo_check_sysv_msqsnd = biba_check_sysv_msqsnd,
3359         .mpo_check_sysv_msqrcv = biba_check_sysv_msqrcv,
3360         .mpo_check_sysv_msqctl = biba_check_sysv_msqctl,
3361         .mpo_check_sysv_semctl = biba_check_sysv_semctl,
3362         .mpo_check_sysv_semget = biba_check_sysv_semget,
3363         .mpo_check_sysv_semop = biba_check_sysv_semop,
3364         .mpo_check_sysv_shmat = biba_check_sysv_shmat,
3365         .mpo_check_sysv_shmctl = biba_check_sysv_shmctl,
3366         .mpo_check_sysv_shmget = biba_check_sysv_shmget,
3367         .mpo_check_kld_load = biba_check_kld_load,
3368         .mpo_check_mount_stat = biba_check_mount_stat,
3369         .mpo_check_pipe_ioctl = biba_check_pipe_ioctl,
3370         .mpo_check_pipe_poll = biba_check_pipe_poll,
3371         .mpo_check_pipe_read = biba_check_pipe_read,
3372         .mpo_check_pipe_relabel = biba_check_pipe_relabel,
3373         .mpo_check_pipe_stat = biba_check_pipe_stat,
3374         .mpo_check_pipe_write = biba_check_pipe_write,
3375         .mpo_check_posix_sem_destroy = biba_check_posix_sem_write,
3376         .mpo_check_posix_sem_getvalue = biba_check_posix_sem_rdonly,
3377         .mpo_check_posix_sem_open = biba_check_posix_sem_write,
3378         .mpo_check_posix_sem_post = biba_check_posix_sem_write,
3379         .mpo_check_posix_sem_unlink = biba_check_posix_sem_write,
3380         .mpo_check_posix_sem_wait = biba_check_posix_sem_write,
3381         .mpo_check_proc_debug = biba_check_proc_debug,
3382         .mpo_check_proc_sched = biba_check_proc_sched,
3383         .mpo_check_proc_signal = biba_check_proc_signal,
3384         .mpo_check_socket_deliver = biba_check_socket_deliver,
3385         .mpo_check_socket_relabel = biba_check_socket_relabel,
3386         .mpo_check_socket_visible = biba_check_socket_visible,
3387         .mpo_check_system_acct = biba_check_system_acct,
3388         .mpo_check_system_auditctl = biba_check_system_auditctl,
3389         .mpo_check_system_auditon = biba_check_system_auditon,
3390         .mpo_check_system_swapon = biba_check_system_swapon,
3391         .mpo_check_system_swapoff = biba_check_system_swapoff,
3392         .mpo_check_system_sysctl = biba_check_system_sysctl,
3393         .mpo_check_vnode_access = biba_check_vnode_open,
3394         .mpo_check_vnode_chdir = biba_check_vnode_chdir,
3395         .mpo_check_vnode_chroot = biba_check_vnode_chroot,
3396         .mpo_check_vnode_create = biba_check_vnode_create,
3397         .mpo_check_vnode_deleteacl = biba_check_vnode_deleteacl,
3398         .mpo_check_vnode_deleteextattr = biba_check_vnode_deleteextattr,
3399         .mpo_check_vnode_exec = biba_check_vnode_exec,
3400         .mpo_check_vnode_getacl = biba_check_vnode_getacl,
3401         .mpo_check_vnode_getextattr = biba_check_vnode_getextattr,
3402         .mpo_check_vnode_link = biba_check_vnode_link,
3403         .mpo_check_vnode_listextattr = biba_check_vnode_listextattr,
3404         .mpo_check_vnode_lookup = biba_check_vnode_lookup,
3405         .mpo_check_vnode_mmap = biba_check_vnode_mmap,
3406         .mpo_check_vnode_open = biba_check_vnode_open,
3407         .mpo_check_vnode_poll = biba_check_vnode_poll,
3408         .mpo_check_vnode_read = biba_check_vnode_read,
3409         .mpo_check_vnode_readdir = biba_check_vnode_readdir,
3410         .mpo_check_vnode_readlink = biba_check_vnode_readlink,
3411         .mpo_check_vnode_relabel = biba_check_vnode_relabel,
3412         .mpo_check_vnode_rename_from = biba_check_vnode_rename_from,
3413         .mpo_check_vnode_rename_to = biba_check_vnode_rename_to,
3414         .mpo_check_vnode_revoke = biba_check_vnode_revoke,
3415         .mpo_check_vnode_setacl = biba_check_vnode_setacl,
3416         .mpo_check_vnode_setextattr = biba_check_vnode_setextattr,
3417         .mpo_check_vnode_setflags = biba_check_vnode_setflags,
3418         .mpo_check_vnode_setmode = biba_check_vnode_setmode,
3419         .mpo_check_vnode_setowner = biba_check_vnode_setowner,
3420         .mpo_check_vnode_setutimes = biba_check_vnode_setutimes,
3421         .mpo_check_vnode_stat = biba_check_vnode_stat,
3422         .mpo_check_vnode_unlink = biba_check_vnode_unlink,
3423         .mpo_check_vnode_write = biba_check_vnode_write,
3424         .mpo_associate_nfsd_label = biba_associate_nfsd_label,
3425         .mpo_create_mbuf_from_firewall = biba_create_mbuf_from_firewall,
3426         .mpo_priv_check = biba_priv_check,
3427 };
3428
3429 MAC_POLICY_SET(&mac_biba_ops, mac_biba, "TrustedBSD MAC/Biba",
3430     MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &biba_slot);