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