1 /*-
2 * Copyright (c) 1999-2002 Robert N. M. Watson
3 * Copyright (c) 2001-2005 McAfee, Inc.
4 * All rights reserved.
5 *
6 * This software was developed by Robert Watson for the TrustedBSD Project.
7 *
8 * This software was developed for the FreeBSD Project in part by McAfee
9 * Research, the Security Research Division of McAfee, Inc. under
10 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
11 * CHATS research program.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $FreeBSD: releng/5.4/sys/security/mac_biba/mac_biba.c 141793 2005-02-13 12:10:38Z rwatson $
35 */
36
37 /*
38 * Developed by the TrustedBSD Project.
39 * Biba fixed label mandatory integrity policy.
40 */
41
42 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/acl.h>
45 #include <sys/conf.h>
46 #include <sys/extattr.h>
47 #include <sys/kernel.h>
48 #include <sys/mac.h>
49 #include <sys/malloc.h>
50 #include <sys/mount.h>
51 #include <sys/proc.h>
52 #include <sys/sbuf.h>
53 #include <sys/systm.h>
54 #include <sys/sysproto.h>
55 #include <sys/sysent.h>
56 #include <sys/systm.h>
57 #include <sys/vnode.h>
58 #include <sys/file.h>
59 #include <sys/socket.h>
60 #include <sys/socketvar.h>
61 #include <sys/pipe.h>
62 #include <sys/sysctl.h>
63
64 #include <fs/devfs/devfs.h>
65
66 #include <net/bpfdesc.h>
67 #include <net/if.h>
68 #include <net/if_types.h>
69 #include <net/if_var.h>
70
71 #include <netinet/in.h>
72 #include <netinet/in_pcb.h>
73 #include <netinet/ip_var.h>
74
75 #include <vm/uma.h>
76 #include <vm/vm.h>
77
78 #include <sys/mac_policy.h>
79
80 #include <security/mac_biba/mac_biba.h>
81
82 SYSCTL_DECL(_security_mac);
83
84 SYSCTL_NODE(_security_mac, OID_AUTO, biba, CTLFLAG_RW, 0,
85 "TrustedBSD mac_biba policy controls");
86
87 static int mac_biba_label_size = sizeof(struct mac_biba);
88 SYSCTL_INT(_security_mac_biba, OID_AUTO, label_size, CTLFLAG_RD,
89 &mac_biba_label_size, 0, "Size of struct mac_biba");
90
91 static int mac_biba_enabled = 1;
92 SYSCTL_INT(_security_mac_biba, OID_AUTO, enabled, CTLFLAG_RW,
93 &mac_biba_enabled, 0, "Enforce MAC/Biba policy");
94 TUNABLE_INT("security.mac.biba.enabled", &mac_biba_enabled);
95
96 static int destroyed_not_inited;
97 SYSCTL_INT(_security_mac_biba, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
98 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
99
100 static int trust_all_interfaces = 0;
101 SYSCTL_INT(_security_mac_biba, OID_AUTO, trust_all_interfaces, CTLFLAG_RD,
102 &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/Biba");
103 TUNABLE_INT("security.mac.biba.trust_all_interfaces", &trust_all_interfaces);
104
105 static char trusted_interfaces[128];
106 SYSCTL_STRING(_security_mac_biba, OID_AUTO, trusted_interfaces, CTLFLAG_RD,
107 trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/Biba");
108 TUNABLE_STR("security.mac.biba.trusted_interfaces", trusted_interfaces,
109 sizeof(trusted_interfaces));
110
111 static int max_compartments = MAC_BIBA_MAX_COMPARTMENTS;
112 SYSCTL_INT(_security_mac_biba, OID_AUTO, max_compartments, CTLFLAG_RD,
113 &max_compartments, 0, "Maximum supported compartments");
114
115 static int ptys_equal = 0;
116 SYSCTL_INT(_security_mac_biba, OID_AUTO, ptys_equal, CTLFLAG_RW,
117 &ptys_equal, 0, "Label pty devices as biba/equal on create");
118 TUNABLE_INT("security.mac.biba.ptys_equal", &ptys_equal);
119
120 static int revocation_enabled = 0;
121 SYSCTL_INT(_security_mac_biba, OID_AUTO, revocation_enabled, CTLFLAG_RW,
122 &revocation_enabled, 0, "Revoke access to objects on relabel");
123 TUNABLE_INT("security.mac.biba.revocation_enabled", &revocation_enabled);
124
125 static int mac_biba_slot;
126 #define SLOT(l) ((struct mac_biba *)LABEL_TO_SLOT((l), mac_biba_slot).l_ptr)
127 #define SLOT_SET(l, val) (LABEL_TO_SLOT((l), mac_biba_slot).l_ptr = (val))
128
129 static uma_zone_t zone_biba;
130
131 static __inline int
132 biba_bit_set_empty(u_char *set) {
133 int i;
134
135 for (i = 0; i < MAC_BIBA_MAX_COMPARTMENTS >> 3; i++)
136 if (set[i] != 0)
137 return (0);
138 return (1);
139 }
140
141 static struct mac_biba *
142 biba_alloc(int flag)
143 {
144
145 return (uma_zalloc(zone_biba, flag | M_ZERO));
146 }
147
148 static void
149 biba_free(struct mac_biba *mac_biba)
150 {
151
152 if (mac_biba != NULL)
153 uma_zfree(zone_biba, mac_biba);
154 else
155 atomic_add_int(&destroyed_not_inited, 1);
156 }
157
158 static int
159 biba_atmostflags(struct mac_biba *mac_biba, int flags)
160 {
161
162 if ((mac_biba->mb_flags & flags) != mac_biba->mb_flags)
163 return (EINVAL);
164 return (0);
165 }
166
167 static int
168 mac_biba_dominate_element(struct mac_biba_element *a,
169 struct mac_biba_element *b)
170 {
171 int bit;
172
173 switch (a->mbe_type) {
174 case MAC_BIBA_TYPE_EQUAL:
175 case MAC_BIBA_TYPE_HIGH:
176 return (1);
177
178 case MAC_BIBA_TYPE_LOW:
179 switch (b->mbe_type) {
180 case MAC_BIBA_TYPE_GRADE:
181 case MAC_BIBA_TYPE_HIGH:
182 return (0);
183
184 case MAC_BIBA_TYPE_EQUAL:
185 case MAC_BIBA_TYPE_LOW:
186 return (1);
187
188 default:
189 panic("mac_biba_dominate_element: b->mbe_type invalid");
190 }
191
192 case MAC_BIBA_TYPE_GRADE:
193 switch (b->mbe_type) {
194 case MAC_BIBA_TYPE_EQUAL:
195 case MAC_BIBA_TYPE_LOW:
196 return (1);
197
198 case MAC_BIBA_TYPE_HIGH:
199 return (0);
200
201 case MAC_BIBA_TYPE_GRADE:
202 for (bit = 1; bit <= MAC_BIBA_MAX_COMPARTMENTS; bit++)
203 if (!MAC_BIBA_BIT_TEST(bit,
204 a->mbe_compartments) &&
205 MAC_BIBA_BIT_TEST(bit, b->mbe_compartments))
206 return (0);
207 return (a->mbe_grade >= b->mbe_grade);
208
209 default:
210 panic("mac_biba_dominate_element: b->mbe_type invalid");
211 }
212
213 default:
214 panic("mac_biba_dominate_element: a->mbe_type invalid");
215 }
216
217 return (0);
218 }
219
220 static int
221 mac_biba_subject_dominate_high(struct mac_biba *mac_biba)
222 {
223 struct mac_biba_element *element;
224
225 KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
226 ("mac_biba_effective_in_range: mac_biba not effective"));
227 element = &mac_biba->mb_effective;
228
229 return (element->mbe_type == MAC_BIBA_TYPE_EQUAL ||
230 element->mbe_type == MAC_BIBA_TYPE_HIGH);
231 }
232
233 static int
234 mac_biba_range_in_range(struct mac_biba *rangea, struct mac_biba *rangeb)
235 {
236
237 return (mac_biba_dominate_element(&rangeb->mb_rangehigh,
238 &rangea->mb_rangehigh) &&
239 mac_biba_dominate_element(&rangea->mb_rangelow,
240 &rangeb->mb_rangelow));
241 }
242
243 static int
244 mac_biba_effective_in_range(struct mac_biba *effective,
245 struct mac_biba *range)
246 {
247
248 KASSERT((effective->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
249 ("mac_biba_effective_in_range: a not effective"));
250 KASSERT((range->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
251 ("mac_biba_effective_in_range: b not range"));
252
253 return (mac_biba_dominate_element(&range->mb_rangehigh,
254 &effective->mb_effective) &&
255 mac_biba_dominate_element(&effective->mb_effective,
256 &range->mb_rangelow));
257
258 return (1);
259 }
260
261 static int
262 mac_biba_dominate_effective(struct mac_biba *a, struct mac_biba *b)
263 {
264 KASSERT((a->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
265 ("mac_biba_dominate_effective: a not effective"));
266 KASSERT((b->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
267 ("mac_biba_dominate_effective: b not effective"));
268
269 return (mac_biba_dominate_element(&a->mb_effective, &b->mb_effective));
270 }
271
272 static int
273 mac_biba_equal_element(struct mac_biba_element *a, struct mac_biba_element *b)
274 {
275
276 if (a->mbe_type == MAC_BIBA_TYPE_EQUAL ||
277 b->mbe_type == MAC_BIBA_TYPE_EQUAL)
278 return (1);
279
280 return (a->mbe_type == b->mbe_type && a->mbe_grade == b->mbe_grade);
281 }
282
283 static int
284 mac_biba_equal_effective(struct mac_biba *a, struct mac_biba *b)
285 {
286
287 KASSERT((a->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
288 ("mac_biba_equal_effective: a not effective"));
289 KASSERT((b->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
290 ("mac_biba_equal_effective: b not effective"));
291
292 return (mac_biba_equal_element(&a->mb_effective, &b->mb_effective));
293 }
294
295 static int
296 mac_biba_contains_equal(struct mac_biba *mac_biba)
297 {
298
299 if (mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE)
300 if (mac_biba->mb_effective.mbe_type == MAC_BIBA_TYPE_EQUAL)
301 return (1);
302
303 if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
304 if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL)
305 return (1);
306 if (mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
307 return (1);
308 }
309
310 return (0);
311 }
312
313 static int
314 mac_biba_subject_privileged(struct mac_biba *mac_biba)
315 {
316
317 KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAGS_BOTH) ==
318 MAC_BIBA_FLAGS_BOTH,
319 ("mac_biba_subject_privileged: subject doesn't have both labels"));
320
321 /* If the effective is EQUAL, it's ok. */
322 if (mac_biba->mb_effective.mbe_type == MAC_BIBA_TYPE_EQUAL)
323 return (0);
324
325 /* If either range endpoint is EQUAL, it's ok. */
326 if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL ||
327 mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
328 return (0);
329
330 /* If the range is low-high, it's ok. */
331 if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_LOW &&
332 mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_HIGH)
333 return (0);
334
335 /* It's not ok. */
336 return (EPERM);
337 }
338
339 static int
340 mac_biba_high_effective(struct mac_biba *mac_biba)
341 {
342
343 KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
344 ("mac_biba_equal_effective: mac_biba not effective"));
345
346 return (mac_biba->mb_effective.mbe_type == MAC_BIBA_TYPE_HIGH);
347 }
348
349 static int
350 mac_biba_valid(struct mac_biba *mac_biba)
351 {
352
353 if (mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
354 switch (mac_biba->mb_effective.mbe_type) {
355 case MAC_BIBA_TYPE_GRADE:
356 break;
357
358 case MAC_BIBA_TYPE_EQUAL:
359 case MAC_BIBA_TYPE_HIGH:
360 case MAC_BIBA_TYPE_LOW:
361 if (mac_biba->mb_effective.mbe_grade != 0 ||
362 !MAC_BIBA_BIT_SET_EMPTY(
363 mac_biba->mb_effective.mbe_compartments))
364 return (EINVAL);
365 break;
366
367 default:
368 return (EINVAL);
369 }
370 } else {
371 if (mac_biba->mb_effective.mbe_type != MAC_BIBA_TYPE_UNDEF)
372 return (EINVAL);
373 }
374
375 if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
376 switch (mac_biba->mb_rangelow.mbe_type) {
377 case MAC_BIBA_TYPE_GRADE:
378 break;
379
380 case MAC_BIBA_TYPE_EQUAL:
381 case MAC_BIBA_TYPE_HIGH:
382 case MAC_BIBA_TYPE_LOW:
383 if (mac_biba->mb_rangelow.mbe_grade != 0 ||
384 !MAC_BIBA_BIT_SET_EMPTY(
385 mac_biba->mb_rangelow.mbe_compartments))
386 return (EINVAL);
387 break;
388
389 default:
390 return (EINVAL);
391 }
392
393 switch (mac_biba->mb_rangehigh.mbe_type) {
394 case MAC_BIBA_TYPE_GRADE:
395 break;
396
397 case MAC_BIBA_TYPE_EQUAL:
398 case MAC_BIBA_TYPE_HIGH:
399 case MAC_BIBA_TYPE_LOW:
400 if (mac_biba->mb_rangehigh.mbe_grade != 0 ||
401 !MAC_BIBA_BIT_SET_EMPTY(
402 mac_biba->mb_rangehigh.mbe_compartments))
403 return (EINVAL);
404 break;
405
406 default:
407 return (EINVAL);
408 }
409 if (!mac_biba_dominate_element(&mac_biba->mb_rangehigh,
410 &mac_biba->mb_rangelow))
411 return (EINVAL);
412 } else {
413 if (mac_biba->mb_rangelow.mbe_type != MAC_BIBA_TYPE_UNDEF ||
414 mac_biba->mb_rangehigh.mbe_type != MAC_BIBA_TYPE_UNDEF)
415 return (EINVAL);
416 }
417
418 return (0);
419 }
420
421 static void
422 mac_biba_set_range(struct mac_biba *mac_biba, u_short typelow,
423 u_short gradelow, u_char *compartmentslow, u_short typehigh,
424 u_short gradehigh, u_char *compartmentshigh)
425 {
426
427 mac_biba->mb_rangelow.mbe_type = typelow;
428 mac_biba->mb_rangelow.mbe_grade = gradelow;
429 if (compartmentslow != NULL)
430 memcpy(mac_biba->mb_rangelow.mbe_compartments,
431 compartmentslow,
432 sizeof(mac_biba->mb_rangelow.mbe_compartments));
433 mac_biba->mb_rangehigh.mbe_type = typehigh;
434 mac_biba->mb_rangehigh.mbe_grade = gradehigh;
435 if (compartmentshigh != NULL)
436 memcpy(mac_biba->mb_rangehigh.mbe_compartments,
437 compartmentshigh,
438 sizeof(mac_biba->mb_rangehigh.mbe_compartments));
439 mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE;
440 }
441
442 static void
443 mac_biba_set_effective(struct mac_biba *mac_biba, u_short type, u_short grade,
444 u_char *compartments)
445 {
446
447 mac_biba->mb_effective.mbe_type = type;
448 mac_biba->mb_effective.mbe_grade = grade;
449 if (compartments != NULL)
450 memcpy(mac_biba->mb_effective.mbe_compartments, compartments,
451 sizeof(mac_biba->mb_effective.mbe_compartments));
452 mac_biba->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
453 }
454
455 static void
456 mac_biba_copy_range(struct mac_biba *labelfrom, struct mac_biba *labelto)
457 {
458
459 KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
460 ("mac_biba_copy_range: labelfrom not range"));
461
462 labelto->mb_rangelow = labelfrom->mb_rangelow;
463 labelto->mb_rangehigh = labelfrom->mb_rangehigh;
464 labelto->mb_flags |= MAC_BIBA_FLAG_RANGE;
465 }
466
467 static void
468 mac_biba_copy_effective(struct mac_biba *labelfrom, struct mac_biba *labelto)
469 {
470
471 KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
472 ("mac_biba_copy_effective: labelfrom not effective"));
473
474 labelto->mb_effective = labelfrom->mb_effective;
475 labelto->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
476 }
477
478 static void
479 mac_biba_copy(struct mac_biba *source, struct mac_biba *dest)
480 {
481
482 if (source->mb_flags & MAC_BIBA_FLAG_EFFECTIVE)
483 mac_biba_copy_effective(source, dest);
484 if (source->mb_flags & MAC_BIBA_FLAG_RANGE)
485 mac_biba_copy_range(source, dest);
486 }
487
488 /*
489 * Policy module operations.
490 */
491 static void
492 mac_biba_init(struct mac_policy_conf *conf)
493 {
494
495 zone_biba = uma_zcreate("mac_biba", sizeof(struct mac_biba), NULL,
496 NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
497 }
498
499 /*
500 * Label operations.
501 */
502 static void
503 mac_biba_init_label(struct label *label)
504 {
505
506 SLOT_SET(label, biba_alloc(M_WAITOK));
507 }
508
509 static int
510 mac_biba_init_label_waitcheck(struct label *label, int flag)
511 {
512
513 SLOT_SET(label, biba_alloc(flag));
514 if (SLOT(label) == NULL)
515 return (ENOMEM);
516
517 return (0);
518 }
519
520 static void
521 mac_biba_destroy_label(struct label *label)
522 {
523
524 biba_free(SLOT(label));
525 SLOT_SET(label, NULL);
526 }
527
528 /*
529 * mac_biba_element_to_string() accepts an sbuf and Biba element. It
530 * converts the Biba element to a string and stores the result in the
531 * sbuf; if there isn't space in the sbuf, -1 is returned.
532 */
533 static int
534 mac_biba_element_to_string(struct sbuf *sb, struct mac_biba_element *element)
535 {
536 int i, first;
537
538 switch (element->mbe_type) {
539 case MAC_BIBA_TYPE_HIGH:
540 return (sbuf_printf(sb, "high"));
541
542 case MAC_BIBA_TYPE_LOW:
543 return (sbuf_printf(sb, "low"));
544
545 case MAC_BIBA_TYPE_EQUAL:
546 return (sbuf_printf(sb, "equal"));
547
548 case MAC_BIBA_TYPE_GRADE:
549 if (sbuf_printf(sb, "%d", element->mbe_grade) == -1)
550 return (-1);
551
552 first = 1;
553 for (i = 1; i <= MAC_BIBA_MAX_COMPARTMENTS; i++) {
554 if (MAC_BIBA_BIT_TEST(i, element->mbe_compartments)) {
555 if (first) {
556 if (sbuf_putc(sb, ':') == -1)
557 return (-1);
558 if (sbuf_printf(sb, "%d", i) == -1)
559 return (-1);
560 first = 0;
561 } else {
562 if (sbuf_printf(sb, "+%d", i) == -1)
563 return (-1);
564 }
565 }
566 }
567 return (0);
568
569 default:
570 panic("mac_biba_element_to_string: invalid type (%d)",
571 element->mbe_type);
572 }
573 }
574
575 /*
576 * mac_biba_to_string() converts a Biba label to a string, and places
577 * the results in the passed sbuf. It returns 0 on success, or EINVAL
578 * if there isn't room in the sbuf. Note: the sbuf will be modified
579 * even in a failure case, so the caller may need to revert the sbuf
580 * by restoring the offset if that's undesired.
581 */
582 static int
583 mac_biba_to_string(struct sbuf *sb, struct mac_biba *mac_biba)
584 {
585
586 if (mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
587 if (mac_biba_element_to_string(sb, &mac_biba->mb_effective)
588 == -1)
589 return (EINVAL);
590 }
591
592 if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
593 if (sbuf_putc(sb, '(') == -1)
594 return (EINVAL);
595
596 if (mac_biba_element_to_string(sb, &mac_biba->mb_rangelow)
597 == -1)
598 return (EINVAL);
599
600 if (sbuf_putc(sb, '-') == -1)
601 return (EINVAL);
602
603 if (mac_biba_element_to_string(sb, &mac_biba->mb_rangehigh)
604 == -1)
605 return (EINVAL);
606
607 if (sbuf_putc(sb, ')') == -1)
608 return (EINVAL);
609 }
610
611 return (0);
612 }
613
614 static int
615 mac_biba_externalize_label(struct label *label, char *element_name,
616 struct sbuf *sb, int *claimed)
617 {
618 struct mac_biba *mac_biba;
619
620 if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
621 return (0);
622
623 (*claimed)++;
624
625 mac_biba = SLOT(label);
626 return (mac_biba_to_string(sb, mac_biba));
627 }
628
629 static int
630 mac_biba_parse_element(struct mac_biba_element *element, char *string)
631 {
632 char *compartment, *end, *grade;
633 int value;
634
635 if (strcmp(string, "high") == 0 ||
636 strcmp(string, "hi") == 0) {
637 element->mbe_type = MAC_BIBA_TYPE_HIGH;
638 element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
639 } else if (strcmp(string, "low") == 0 ||
640 strcmp(string, "lo") == 0) {
641 element->mbe_type = MAC_BIBA_TYPE_LOW;
642 element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
643 } else if (strcmp(string, "equal") == 0 ||
644 strcmp(string, "eq") == 0) {
645 element->mbe_type = MAC_BIBA_TYPE_EQUAL;
646 element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
647 } else {
648 element->mbe_type = MAC_BIBA_TYPE_GRADE;
649
650 /*
651 * Numeric grade piece of the element.
652 */
653 grade = strsep(&string, ":");
654 value = strtol(grade, &end, 10);
655 if (end == grade || *end != '\0')
656 return (EINVAL);
657 if (value < 0 || value > 65535)
658 return (EINVAL);
659 element->mbe_grade = value;
660
661 /*
662 * Optional compartment piece of the element. If none
663 * are included, we assume that the label has no
664 * compartments.
665 */
666 if (string == NULL)
667 return (0);
668 if (*string == '\0')
669 return (0);
670
671 while ((compartment = strsep(&string, "+")) != NULL) {
672 value = strtol(compartment, &end, 10);
673 if (compartment == end || *end != '\0')
674 return (EINVAL);
675 if (value < 1 || value > MAC_BIBA_MAX_COMPARTMENTS)
676 return (EINVAL);
677 MAC_BIBA_BIT_SET(value, element->mbe_compartments);
678 }
679 }
680
681 return (0);
682 }
683
684 /*
685 * Note: destructively consumes the string, make a local copy before
686 * calling if that's a problem.
687 */
688 static int
689 mac_biba_parse(struct mac_biba *mac_biba, char *string)
690 {
691 char *rangehigh, *rangelow, *effective;
692 int error;
693
694 effective = strsep(&string, "(");
695 if (*effective == '\0')
696 effective = NULL;
697
698 if (string != NULL) {
699 rangelow = strsep(&string, "-");
700 if (string == NULL)
701 return (EINVAL);
702 rangehigh = strsep(&string, ")");
703 if (string == NULL)
704 return (EINVAL);
705 if (*string != '\0')
706 return (EINVAL);
707 } else {
708 rangelow = NULL;
709 rangehigh = NULL;
710 }
711
712 KASSERT((rangelow != NULL && rangehigh != NULL) ||
713 (rangelow == NULL && rangehigh == NULL),
714 ("mac_biba_parse: range mismatch"));
715
716 bzero(mac_biba, sizeof(*mac_biba));
717 if (effective != NULL) {
718 error = mac_biba_parse_element(&mac_biba->mb_effective, effective);
719 if (error)
720 return (error);
721 mac_biba->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
722 }
723
724 if (rangelow != NULL) {
725 error = mac_biba_parse_element(&mac_biba->mb_rangelow,
726 rangelow);
727 if (error)
728 return (error);
729 error = mac_biba_parse_element(&mac_biba->mb_rangehigh,
730 rangehigh);
731 if (error)
732 return (error);
733 mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE;
734 }
735
736 error = mac_biba_valid(mac_biba);
737 if (error)
738 return (error);
739
740 return (0);
741 }
742
743 static int
744 mac_biba_internalize_label(struct label *label, char *element_name,
745 char *element_data, int *claimed)
746 {
747 struct mac_biba *mac_biba, mac_biba_temp;
748 int error;
749
750 if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
751 return (0);
752
753 (*claimed)++;
754
755 error = mac_biba_parse(&mac_biba_temp, element_data);
756 if (error)
757 return (error);
758
759 mac_biba = SLOT(label);
760 *mac_biba = mac_biba_temp;
761
762 return (0);
763 }
764
765 static void
766 mac_biba_copy_label(struct label *src, struct label *dest)
767 {
768
769 *SLOT(dest) = *SLOT(src);
770 }
771
772 /*
773 * Labeling event operations: file system objects, and things that look
774 * a lot like file system objects.
775 */
776 static void
777 mac_biba_create_devfs_device(struct mount *mp, struct cdev *dev,
778 struct devfs_dirent *devfs_dirent, struct label *label)
779 {
780 struct mac_biba *mac_biba;
781 int biba_type;
782
783 mac_biba = SLOT(label);
784 if (strcmp(dev->si_name, "null") == 0 ||
785 strcmp(dev->si_name, "zero") == 0 ||
786 strcmp(dev->si_name, "random") == 0 ||
787 strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
788 biba_type = MAC_BIBA_TYPE_EQUAL;
789 else if (ptys_equal &&
790 (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
791 strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
792 biba_type = MAC_BIBA_TYPE_EQUAL;
793 else
794 biba_type = MAC_BIBA_TYPE_HIGH;
795 mac_biba_set_effective(mac_biba, biba_type, 0, NULL);
796 }
797
798 static void
799 mac_biba_create_devfs_directory(struct mount *mp, char *dirname,
800 int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
801 {
802 struct mac_biba *mac_biba;
803
804 mac_biba = SLOT(label);
805 mac_biba_set_effective(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL);
806 }
807
808 static void
809 mac_biba_create_devfs_symlink(struct ucred *cred, struct mount *mp,
810 struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
811 struct label *delabel)
812 {
813 struct mac_biba *source, *dest;
814
815 source = SLOT(cred->cr_label);
816 dest = SLOT(delabel);
817
818 mac_biba_copy_effective(source, dest);
819 }
820
821 static void
822 mac_biba_create_mount(struct ucred *cred, struct mount *mp,
823 struct label *mntlabel, struct label *fslabel)
824 {
825 struct mac_biba *source, *dest;
826
827 source = SLOT(cred->cr_label);
828 dest = SLOT(mntlabel);
829 mac_biba_copy_effective(source, dest);
830 dest = SLOT(fslabel);
831 mac_biba_copy_effective(source, dest);
832 }
833
834 static void
835 mac_biba_create_root_mount(struct ucred *cred, struct mount *mp,
836 struct label *mntlabel, struct label *fslabel)
837 {
838 struct mac_biba *mac_biba;
839
840 /* Always mount root as high integrity. */
841 mac_biba = SLOT(fslabel);
842 mac_biba_set_effective(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL);
843 mac_biba = SLOT(mntlabel);
844 mac_biba_set_effective(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL);
845 }
846
847 static void
848 mac_biba_relabel_vnode(struct ucred *cred, struct vnode *vp,
849 struct label *vnodelabel, struct label *label)
850 {
851 struct mac_biba *source, *dest;
852
853 source = SLOT(label);
854 dest = SLOT(vnodelabel);
855
856 mac_biba_copy(source, dest);
857 }
858
859 static void
860 mac_biba_update_devfsdirent(struct mount *mp,
861 struct devfs_dirent *devfs_dirent, struct label *direntlabel,
862 struct vnode *vp, struct label *vnodelabel)
863 {
864 struct mac_biba *source, *dest;
865
866 source = SLOT(vnodelabel);
867 dest = SLOT(direntlabel);
868
869 mac_biba_copy(source, dest);
870 }
871
872 static void
873 mac_biba_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
874 struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
875 struct label *vlabel)
876 {
877 struct mac_biba *source, *dest;
878
879 source = SLOT(delabel);
880 dest = SLOT(vlabel);
881
882 mac_biba_copy_effective(source, dest);
883 }
884
885 static int
886 mac_biba_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
887 struct vnode *vp, struct label *vlabel)
888 {
889 struct mac_biba temp, *source, *dest;
890 int buflen, error;
891
892 source = SLOT(fslabel);
893 dest = SLOT(vlabel);
894
895 buflen = sizeof(temp);
896 bzero(&temp, buflen);
897
898 error = vn_extattr_get(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
899 MAC_BIBA_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
900 if (error == ENOATTR || error == EOPNOTSUPP) {
901 /* Fall back to the fslabel. */
902 mac_biba_copy_effective(source, dest);
903 return (0);
904 } else if (error)
905 return (error);
906
907 if (buflen != sizeof(temp)) {
908 printf("mac_biba_associate_vnode_extattr: bad size %d\n",
909 buflen);
910 return (EPERM);
911 }
912 if (mac_biba_valid(&temp) != 0) {
913 printf("mac_biba_associate_vnode_extattr: invalid\n");
914 return (EPERM);
915 }
916 if ((temp.mb_flags & MAC_BIBA_FLAGS_BOTH) != MAC_BIBA_FLAG_EFFECTIVE) {
917 printf("mac_biba_associate_vnode_extattr: not effective\n");
918 return (EPERM);
919 }
920
921 mac_biba_copy_effective(&temp, dest);
922 return (0);
923 }
924
925 static void
926 mac_biba_associate_vnode_singlelabel(struct mount *mp,
927 struct label *fslabel, struct vnode *vp, struct label *vlabel)
928 {
929 struct mac_biba *source, *dest;
930
931 source = SLOT(fslabel);
932 dest = SLOT(vlabel);
933
934 mac_biba_copy_effective(source, dest);
935 }
936
937 static int
938 mac_biba_create_vnode_extattr(struct ucred *cred, struct mount *mp,
939 struct label *fslabel, struct vnode *dvp, struct label *dlabel,
940 struct vnode *vp, struct label *vlabel, struct componentname *cnp)
941 {
942 struct mac_biba *source, *dest, temp;
943 size_t buflen;
944 int error;
945
946 buflen = sizeof(temp);
947 bzero(&temp, buflen);
948
949 source = SLOT(cred->cr_label);
950 dest = SLOT(vlabel);
951 mac_biba_copy_effective(source, &temp);
952
953 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
954 MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread);
955 if (error == 0)
956 mac_biba_copy_effective(source, dest);
957 return (error);
958 }
959
960 static int
961 mac_biba_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
962 struct label *vlabel, struct label *intlabel)
963 {
964 struct mac_biba *source, temp;
965 size_t buflen;
966 int error;
967
968 buflen = sizeof(temp);
969 bzero(&temp, buflen);
970
971 source = SLOT(intlabel);
972 if ((source->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) == 0)
973 return (0);
974
975 mac_biba_copy_effective(source, &temp);
976
977 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
978 MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread);
979 return (error);
980 }
981
982 /*
983 * Labeling event operations: IPC object.
984 */
985 static void
986 mac_biba_create_inpcb_from_socket(struct socket *so, struct label *solabel,
987 struct inpcb *inp, struct label *inplabel)
988 {
989 struct mac_biba *source, *dest;
990
991 source = SLOT(solabel);
992 dest = SLOT(inplabel);
993
994 mac_biba_copy_effective(source, dest);
995 }
996
997 static void
998 mac_biba_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
999 struct mbuf *m, struct label *mbuflabel)
1000 {
1001 struct mac_biba *source, *dest;
1002
1003 source = SLOT(socketlabel);
1004 dest = SLOT(mbuflabel);
1005
1006 mac_biba_copy_effective(source, dest);
1007 }
1008
1009 static void
1010 mac_biba_create_socket(struct ucred *cred, struct socket *socket,
1011 struct label *socketlabel)
1012 {
1013 struct mac_biba *source, *dest;
1014
1015 source = SLOT(cred->cr_label);
1016 dest = SLOT(socketlabel);
1017
1018 mac_biba_copy_effective(source, dest);
1019 }
1020
1021 static void
1022 mac_biba_create_pipe(struct ucred *cred, struct pipepair *pp,
1023 struct label *pipelabel)
1024 {
1025 struct mac_biba *source, *dest;
1026
1027 source = SLOT(cred->cr_label);
1028 dest = SLOT(pipelabel);
1029
1030 mac_biba_copy_effective(source, dest);
1031 }
1032
1033 static void
1034 mac_biba_create_socket_from_socket(struct socket *oldsocket,
1035 struct label *oldsocketlabel, struct socket *newsocket,
1036 struct label *newsocketlabel)
1037 {
1038 struct mac_biba *source, *dest;
1039
1040 source = SLOT(oldsocketlabel);
1041 dest = SLOT(newsocketlabel);
1042
1043 mac_biba_copy_effective(source, dest);
1044 }
1045
1046 static void
1047 mac_biba_relabel_socket(struct ucred *cred, struct socket *socket,
1048 struct label *socketlabel, struct label *newlabel)
1049 {
1050 struct mac_biba *source, *dest;
1051
1052 source = SLOT(newlabel);
1053 dest = SLOT(socketlabel);
1054
1055 mac_biba_copy(source, dest);
1056 }
1057
1058 static void
1059 mac_biba_relabel_pipe(struct ucred *cred, struct pipepair *pp,
1060 struct label *pipelabel, struct label *newlabel)
1061 {
1062 struct mac_biba *source, *dest;
1063
1064 source = SLOT(newlabel);
1065 dest = SLOT(pipelabel);
1066
1067 mac_biba_copy(source, dest);
1068 }
1069
1070 static void
1071 mac_biba_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1072 struct socket *socket, struct label *socketpeerlabel)
1073 {
1074 struct mac_biba *source, *dest;
1075
1076 source = SLOT(mbuflabel);
1077 dest = SLOT(socketpeerlabel);
1078
1079 mac_biba_copy_effective(source, dest);
1080 }
1081
1082 /*
1083 * Labeling event operations: network objects.
1084 */
1085 static void
1086 mac_biba_set_socket_peer_from_socket(struct socket *oldsocket,
1087 struct label *oldsocketlabel, struct socket *newsocket,
1088 struct label *newsocketpeerlabel)
1089 {
1090 struct mac_biba *source, *dest;
1091
1092 source = SLOT(oldsocketlabel);
1093 dest = SLOT(newsocketpeerlabel);
1094
1095 mac_biba_copy_effective(source, dest);
1096 }
1097
1098 static void
1099 mac_biba_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1100 struct label *bpflabel)
1101 {
1102 struct mac_biba *source, *dest;
1103
1104 source = SLOT(cred->cr_label);
1105 dest = SLOT(bpflabel);
1106
1107 mac_biba_copy_effective(source, dest);
1108 }
1109
1110 static void
1111 mac_biba_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1112 {
1113 char tifname[IFNAMSIZ], *p, *q;
1114 char tiflist[sizeof(trusted_interfaces)];
1115 struct mac_biba *dest;
1116 int len, type;
1117
1118 dest = SLOT(ifnetlabel);
1119
1120 if (ifnet->if_type == IFT_LOOP) {
1121 type = MAC_BIBA_TYPE_EQUAL;
1122 goto set;
1123 }
1124
1125 if (trust_all_interfaces) {
1126 type = MAC_BIBA_TYPE_HIGH;
1127 goto set;
1128 }
1129
1130 type = MAC_BIBA_TYPE_LOW;
1131
1132 if (trusted_interfaces[0] == '\0' ||
1133 !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1134 goto set;
1135
1136 bzero(tiflist, sizeof(tiflist));
1137 for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1138 if(*p != ' ' && *p != '\t')
1139 *q = *p;
1140
1141 for (p = q = tiflist;; p++) {
1142 if (*p == ',' || *p == '\0') {
1143 len = p - q;
1144 if (len < IFNAMSIZ) {
1145 bzero(tifname, sizeof(tifname));
1146 bcopy(q, tifname, len);
1147 if (strcmp(tifname, ifnet->if_xname) == 0) {
1148 type = MAC_BIBA_TYPE_HIGH;
1149 break;
1150 }
1151 } else {
1152 *p = '\0';
1153 printf("mac_biba warning: interface name "
1154 "\"%s\" is too long (must be < %d)\n",
1155 q, IFNAMSIZ);
1156 }
1157 if (*p == '\0')
1158 break;
1159 q = p + 1;
1160 }
1161 }
1162 set:
1163 mac_biba_set_effective(dest, type, 0, NULL);
1164 mac_biba_set_range(dest, type, 0, NULL, type, 0, NULL);
1165 }
1166
1167 static void
1168 mac_biba_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1169 struct ipq *ipq, struct label *ipqlabel)
1170 {
1171 struct mac_biba *source, *dest;
1172
1173 source = SLOT(fragmentlabel);
1174 dest = SLOT(ipqlabel);
1175
1176 mac_biba_copy_effective(source, dest);
1177 }
1178
1179 static void
1180 mac_biba_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1181 struct mbuf *datagram, struct label *datagramlabel)
1182 {
1183 struct mac_biba *source, *dest;
1184
1185 source = SLOT(ipqlabel);
1186 dest = SLOT(datagramlabel);
1187
1188 /* Just use the head, since we require them all to match. */
1189 mac_biba_copy_effective(source, dest);
1190 }
1191
1192 static void
1193 mac_biba_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1194 struct mbuf *fragment, struct label *fragmentlabel)
1195 {
1196 struct mac_biba *source, *dest;
1197
1198 source = SLOT(datagramlabel);
1199 dest = SLOT(fragmentlabel);
1200
1201 mac_biba_copy_effective(source, dest);
1202 }
1203
1204 static void
1205 mac_biba_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel,
1206 struct mbuf *m, struct label *mlabel)
1207 {
1208 struct mac_biba *source, *dest;
1209
1210 source = SLOT(inplabel);
1211 dest = SLOT(mlabel);
1212
1213 mac_biba_copy_effective(source, dest);
1214 }
1215
1216 static void
1217 mac_biba_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
1218 struct label *oldmbuflabel, struct mbuf *newmbuf,
1219 struct label *newmbuflabel)
1220 {
1221 struct mac_biba *source, *dest;
1222
1223 source = SLOT(oldmbuflabel);
1224 dest = SLOT(newmbuflabel);
1225
1226 /*
1227 * Because the source mbuf may not yet have been "created",
1228 * just initialized, we do a conditional copy. Since we don't
1229 * allow mbufs to have ranges, do a KASSERT to make sure that
1230 * doesn't happen.
1231 */
1232 KASSERT((source->mb_flags & MAC_BIBA_FLAG_RANGE) == 0,
1233 ("mac_biba_create_mbuf_from_mbuf: source mbuf has range"));
1234 mac_biba_copy(source, dest);
1235 }
1236
1237 static void
1238 mac_biba_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1239 struct mbuf *mbuf, struct label *mbuflabel)
1240 {
1241 struct mac_biba *dest;
1242
1243 dest = SLOT(mbuflabel);
1244
1245 mac_biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1246 }
1247
1248 static void
1249 mac_biba_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1250 struct mbuf *mbuf, struct label *mbuflabel)
1251 {
1252 struct mac_biba *source, *dest;
1253
1254 source = SLOT(bpflabel);
1255 dest = SLOT(mbuflabel);
1256
1257 mac_biba_copy_effective(source, dest);
1258 }
1259
1260 static void
1261 mac_biba_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1262 struct mbuf *m, struct label *mbuflabel)
1263 {
1264 struct mac_biba *source, *dest;
1265
1266 source = SLOT(ifnetlabel);
1267 dest = SLOT(mbuflabel);
1268
1269 mac_biba_copy_effective(source, dest);
1270 }
1271
1272 static void
1273 mac_biba_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1274 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1275 struct mbuf *newmbuf, struct label *newmbuflabel)
1276 {
1277 struct mac_biba *source, *dest;
1278
1279 source = SLOT(oldmbuflabel);
1280 dest = SLOT(newmbuflabel);
1281
1282 mac_biba_copy_effective(source, dest);
1283 }
1284
1285 static void
1286 mac_biba_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1287 struct mbuf *newmbuf, struct label *newmbuflabel)
1288 {
1289 struct mac_biba *source, *dest;
1290
1291 source = SLOT(oldmbuflabel);
1292 dest = SLOT(newmbuflabel);
1293
1294 mac_biba_copy_effective(source, dest);
1295 }
1296
1297 static int
1298 mac_biba_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1299 struct ipq *ipq, struct label *ipqlabel)
1300 {
1301 struct mac_biba *a, *b;
1302
1303 a = SLOT(ipqlabel);
1304 b = SLOT(fragmentlabel);
1305
1306 return (mac_biba_equal_effective(a, b));
1307 }
1308
1309 static void
1310 mac_biba_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1311 struct label *ifnetlabel, struct label *newlabel)
1312 {
1313 struct mac_biba *source, *dest;
1314
1315 source = SLOT(newlabel);
1316 dest = SLOT(ifnetlabel);
1317
1318 mac_biba_copy(source, dest);
1319 }
1320
1321 static void
1322 mac_biba_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1323 struct ipq *ipq, struct label *ipqlabel)
1324 {
1325
1326 /* NOOP: we only accept matching labels, so no need to update */
1327 }
1328
1329 static void
1330 mac_biba_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1331 struct inpcb *inp, struct label *inplabel)
1332 {
1333 struct mac_biba *source, *dest;
1334
1335 source = SLOT(solabel);
1336 dest = SLOT(inplabel);
1337
1338 mac_biba_copy(source, dest);
1339 }
1340
1341 /*
1342 * Labeling event operations: processes.
1343 */
1344 static void
1345 mac_biba_create_proc0(struct ucred *cred)
1346 {
1347 struct mac_biba *dest;
1348
1349 dest = SLOT(cred->cr_label);
1350
1351 mac_biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1352 mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL,
1353 MAC_BIBA_TYPE_HIGH, 0, NULL);
1354 }
1355
1356 static void
1357 mac_biba_create_proc1(struct ucred *cred)
1358 {
1359 struct mac_biba *dest;
1360
1361 dest = SLOT(cred->cr_label);
1362
1363 mac_biba_set_effective(dest, MAC_BIBA_TYPE_HIGH, 0, NULL);
1364 mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL,
1365 MAC_BIBA_TYPE_HIGH, 0, NULL);
1366 }
1367
1368 static void
1369 mac_biba_relabel_cred(struct ucred *cred, struct label *newlabel)
1370 {
1371 struct mac_biba *source, *dest;
1372
1373 source = SLOT(newlabel);
1374 dest = SLOT(cred->cr_label);
1375
1376 mac_biba_copy(source, dest);
1377 }
1378
1379 /*
1380 * Access control checks.
1381 */
1382 static int
1383 mac_biba_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1384 struct ifnet *ifnet, struct label *ifnetlabel)
1385 {
1386 struct mac_biba *a, *b;
1387
1388 if (!mac_biba_enabled)
1389 return (0);
1390
1391 a = SLOT(bpflabel);
1392 b = SLOT(ifnetlabel);
1393
1394 if (mac_biba_equal_effective(a, b))
1395 return (0);
1396 return (EACCES);
1397 }
1398
1399 static int
1400 mac_biba_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1401 {
1402 struct mac_biba *subj, *new;
1403 int error;
1404
1405 subj = SLOT(cred->cr_label);
1406 new = SLOT(newlabel);
1407
1408 /*
1409 * If there is a Biba label update for the credential, it may
1410 * be an update of the effective, range, or both.
1411 */
1412 error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1413 if (error)
1414 return (error);
1415
1416 /*
1417 * If the Biba label is to be changed, authorize as appropriate.
1418 */
1419 if (new->mb_flags & MAC_BIBA_FLAGS_BOTH) {
1420 /*
1421 * If the change request modifies both the Biba label
1422 * effective and range, check that the new effective will be
1423 * in the new range.
1424 */
1425 if ((new->mb_flags & MAC_BIBA_FLAGS_BOTH) ==
1426 MAC_BIBA_FLAGS_BOTH &&
1427 !mac_biba_effective_in_range(new, new))
1428 return (EINVAL);
1429
1430 /*
1431 * To change the Biba effective label on a credential, the
1432 * new effective label must be in the current range.
1433 */
1434 if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE &&
1435 !mac_biba_effective_in_range(new, subj))
1436 return (EPERM);
1437
1438 /*
1439 * To change the Biba range on a credential, the new
1440 * range label must be in the current range.
1441 */
1442 if (new->mb_flags & MAC_BIBA_FLAG_RANGE &&
1443 !mac_biba_range_in_range(new, subj))
1444 return (EPERM);
1445
1446 /*
1447 * To have EQUAL in any component of the new credential
1448 * Biba label, the subject must already have EQUAL in
1449 * their label.
1450 */
1451 if (mac_biba_contains_equal(new)) {
1452 error = mac_biba_subject_privileged(subj);
1453 if (error)
1454 return (error);
1455 }
1456 }
1457
1458 return (0);
1459 }
1460
1461 static int
1462 mac_biba_check_cred_visible(struct ucred *u1, struct ucred *u2)
1463 {
1464 struct mac_biba *subj, *obj;
1465
1466 if (!mac_biba_enabled)
1467 return (0);
1468
1469 subj = SLOT(u1->cr_label);
1470 obj = SLOT(u2->cr_label);
1471
1472 /* XXX: range */
1473 if (!mac_biba_dominate_effective(obj, subj))
1474 return (ESRCH);
1475
1476 return (0);
1477 }
1478
1479 static int
1480 mac_biba_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1481 struct label *ifnetlabel, struct label *newlabel)
1482 {
1483 struct mac_biba *subj, *new;
1484 int error;
1485
1486 subj = SLOT(cred->cr_label);
1487 new = SLOT(newlabel);
1488
1489 /*
1490 * If there is a Biba label update for the interface, it may
1491 * be an update of the effective, range, or both.
1492 */
1493 error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1494 if (error)
1495 return (error);
1496
1497 /*
1498 * Relabling network interfaces requires Biba privilege.
1499 */
1500 error = mac_biba_subject_privileged(subj);
1501 if (error)
1502 return (error);
1503
1504 return (0);
1505 }
1506
1507 static int
1508 mac_biba_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1509 struct mbuf *m, struct label *mbuflabel)
1510 {
1511 struct mac_biba *p, *i;
1512
1513 if (!mac_biba_enabled)
1514 return (0);
1515
1516 p = SLOT(mbuflabel);
1517 i = SLOT(ifnetlabel);
1518
1519 return (mac_biba_effective_in_range(p, i) ? 0 : EACCES);
1520 }
1521
1522 static int
1523 mac_biba_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1524 struct mbuf *m, struct label *mlabel)
1525 {
1526 struct mac_biba *p, *i;
1527
1528 if (!mac_biba_enabled)
1529 return (0);
1530
1531 p = SLOT(mlabel);
1532 i = SLOT(inplabel);
1533
1534 return (mac_biba_equal_effective(p, i) ? 0 : EACCES);
1535 }
1536
1537 static int
1538 mac_biba_check_kld_load(struct ucred *cred, struct vnode *vp,
1539 struct label *label)
1540 {
1541 struct mac_biba *subj, *obj;
1542 int error;
1543
1544 if (!mac_biba_enabled)
1545 return (0);
1546
1547 subj = SLOT(cred->cr_label);
1548
1549 error = mac_biba_subject_privileged(subj);
1550 if (error)
1551 return (error);
1552
1553 obj = SLOT(label);
1554 if (!mac_biba_high_effective(obj))
1555 return (EACCES);
1556
1557 return (0);
1558 }
1559
1560
1561 static int
1562 mac_biba_check_kld_unload(struct ucred *cred)
1563 {
1564 struct mac_biba *subj;
1565
1566 if (!mac_biba_enabled)
1567 return (0);
1568
1569 subj = SLOT(cred->cr_label);
1570
1571 return (mac_biba_subject_privileged(subj));
1572 }
1573
1574 static int
1575 mac_biba_check_mount_stat(struct ucred *cred, struct mount *mp,
1576 struct label *mntlabel)
1577 {
1578 struct mac_biba *subj, *obj;
1579
1580 if (!mac_biba_enabled)
1581 return (0);
1582
1583 subj = SLOT(cred->cr_label);
1584 obj = SLOT(mntlabel);
1585
1586 if (!mac_biba_dominate_effective(obj, subj))
1587 return (EACCES);
1588
1589 return (0);
1590 }
1591
1592 static int
1593 mac_biba_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
1594 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1595 {
1596
1597 if(!mac_biba_enabled)
1598 return (0);
1599
1600 /* XXX: This will be implemented soon... */
1601
1602 return (0);
1603 }
1604
1605 static int
1606 mac_biba_check_pipe_poll(struct ucred *cred, struct pipepair *pp,
1607 struct label *pipelabel)
1608 {
1609 struct mac_biba *subj, *obj;
1610
1611 if (!mac_biba_enabled)
1612 return (0);
1613
1614 subj = SLOT(cred->cr_label);
1615 obj = SLOT((pipelabel));
1616
1617 if (!mac_biba_dominate_effective(obj, subj))
1618 return (EACCES);
1619
1620 return (0);
1621 }
1622
1623 static int
1624 mac_biba_check_pipe_read(struct ucred *cred, struct pipepair *pp,
1625 struct label *pipelabel)
1626 {
1627 struct mac_biba *subj, *obj;
1628
1629 if (!mac_biba_enabled)
1630 return (0);
1631
1632 subj = SLOT(cred->cr_label);
1633 obj = SLOT((pipelabel));
1634
1635 if (!mac_biba_dominate_effective(obj, subj))
1636 return (EACCES);
1637
1638 return (0);
1639 }
1640
1641 static int
1642 mac_biba_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1643 struct label *pipelabel, struct label *newlabel)
1644 {
1645 struct mac_biba *subj, *obj, *new;
1646 int error;
1647
1648 new = SLOT(newlabel);
1649 subj = SLOT(cred->cr_label);
1650 obj = SLOT(pipelabel);
1651
1652 /*
1653 * If there is a Biba label update for a pipe, it must be a
1654 * effective update.
1655 */
1656 error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
1657 if (error)
1658 return (error);
1659
1660 /*
1661 * To perform a relabel of a pipe (Biba label or not), Biba must
1662 * authorize the relabel.
1663 */
1664 if (!mac_biba_effective_in_range(obj, subj))
1665 return (EPERM);
1666
1667 /*
1668 * If the Biba label is to be changed, authorize as appropriate.
1669 */
1670 if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
1671 /*
1672 * To change the Biba label on a pipe, the new pipe label
1673 * must be in the subject range.
1674 */
1675 if (!mac_biba_effective_in_range(new, subj))
1676 return (EPERM);
1677
1678 /*
1679 * To change the Biba label on a pipe to be EQUAL, the
1680 * subject must have appropriate privilege.
1681 */
1682 if (mac_biba_contains_equal(new)) {
1683 error = mac_biba_subject_privileged(subj);
1684 if (error)
1685 return (error);
1686 }
1687 }
1688
1689 return (0);
1690 }
1691
1692 static int
1693 mac_biba_check_pipe_stat(struct ucred *cred, struct pipepair *pp,
1694 struct label *pipelabel)
1695 {
1696 struct mac_biba *subj, *obj;
1697
1698 if (!mac_biba_enabled)
1699 return (0);
1700
1701 subj = SLOT(cred->cr_label);
1702 obj = SLOT((pipelabel));
1703
1704 if (!mac_biba_dominate_effective(obj, subj))
1705 return (EACCES);
1706
1707 return (0);
1708 }
1709
1710 static int
1711 mac_biba_check_pipe_write(struct ucred *cred, struct pipepair *pp,
1712 struct label *pipelabel)
1713 {
1714 struct mac_biba *subj, *obj;
1715
1716 if (!mac_biba_enabled)
1717 return (0);
1718
1719 subj = SLOT(cred->cr_label);
1720 obj = SLOT((pipelabel));
1721
1722 if (!mac_biba_dominate_effective(subj, obj))
1723 return (EACCES);
1724
1725 return (0);
1726 }
1727
1728 static int
1729 mac_biba_check_proc_debug(struct ucred *cred, struct proc *proc)
1730 {
1731 struct mac_biba *subj, *obj;
1732
1733 if (!mac_biba_enabled)
1734 return (0);
1735
1736 subj = SLOT(cred->cr_label);
1737 obj = SLOT(proc->p_ucred->cr_label);
1738
1739 /* XXX: range checks */
1740 if (!mac_biba_dominate_effective(obj, subj))
1741 return (ESRCH);
1742 if (!mac_biba_dominate_effective(subj, obj))
1743 return (EACCES);
1744
1745 return (0);
1746 }
1747
1748 static int
1749 mac_biba_check_proc_sched(struct ucred *cred, struct proc *proc)
1750 {
1751 struct mac_biba *subj, *obj;
1752
1753 if (!mac_biba_enabled)
1754 return (0);
1755
1756 subj = SLOT(cred->cr_label);
1757 obj = SLOT(proc->p_ucred->cr_label);
1758
1759 /* XXX: range checks */
1760 if (!mac_biba_dominate_effective(obj, subj))
1761 return (ESRCH);
1762 if (!mac_biba_dominate_effective(subj, obj))
1763 return (EACCES);
1764
1765 return (0);
1766 }
1767
1768 static int
1769 mac_biba_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1770 {
1771 struct mac_biba *subj, *obj;
1772
1773 if (!mac_biba_enabled)
1774 return (0);
1775
1776 subj = SLOT(cred->cr_label);
1777 obj = SLOT(proc->p_ucred->cr_label);
1778
1779 /* XXX: range checks */
1780 if (!mac_biba_dominate_effective(obj, subj))
1781 return (ESRCH);
1782 if (!mac_biba_dominate_effective(subj, obj))
1783 return (EACCES);
1784
1785 return (0);
1786 }
1787
1788 static int
1789 mac_biba_check_socket_deliver(struct socket *so, struct label *socketlabel,
1790 struct mbuf *m, struct label *mbuflabel)
1791 {
1792 struct mac_biba *p, *s;
1793
1794 if (!mac_biba_enabled)
1795 return (0);
1796
1797 p = SLOT(mbuflabel);
1798 s = SLOT(socketlabel);
1799
1800 return (mac_biba_equal_effective(p, s) ? 0 : EACCES);
1801 }
1802
1803 static int
1804 mac_biba_check_socket_relabel(struct ucred *cred, struct socket *so,
1805 struct label *socketlabel, struct label *newlabel)
1806 {
1807 struct mac_biba *subj, *obj, *new;
1808 int error;
1809
1810 new = SLOT(newlabel);
1811 subj = SLOT(cred->cr_label);
1812 obj = SLOT(socketlabel);
1813
1814 /*
1815 * If there is a Biba label update for the socket, it may be
1816 * an update of effective.
1817 */
1818 error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
1819 if (error)
1820 return (error);
1821
1822 /*
1823 * To relabel a socket, the old socket effective must be in the subject
1824 * range.
1825 */
1826 if (!mac_biba_effective_in_range(obj, subj))
1827 return (EPERM);
1828
1829 /*
1830 * If the Biba label is to be changed, authorize as appropriate.
1831 */
1832 if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
1833 /*
1834 * To relabel a socket, the new socket effective must be in
1835 * the subject range.
1836 */
1837 if (!mac_biba_effective_in_range(new, subj))
1838 return (EPERM);
1839
1840 /*
1841 * To change the Biba label on the socket to contain EQUAL,
1842 * the subject must have appropriate privilege.
1843 */
1844 if (mac_biba_contains_equal(new)) {
1845 error = mac_biba_subject_privileged(subj);
1846 if (error)
1847 return (error);
1848 }
1849 }
1850
1851 return (0);
1852 }
1853
1854 static int
1855 mac_biba_check_socket_visible(struct ucred *cred, struct socket *socket,
1856 struct label *socketlabel)
1857 {
1858 struct mac_biba *subj, *obj;
1859
1860 if (!mac_biba_enabled)
1861 return (0);
1862
1863 subj = SLOT(cred->cr_label);
1864 obj = SLOT(socketlabel);
1865
1866 if (!mac_biba_dominate_effective(obj, subj))
1867 return (ENOENT);
1868
1869 return (0);
1870 }
1871
1872 static int
1873 mac_biba_check_sysarch_ioperm(struct ucred *cred)
1874 {
1875 struct mac_biba *subj;
1876 int error;
1877
1878 if (!mac_biba_enabled)
1879 return (0);
1880
1881 subj = SLOT(cred->cr_label);
1882
1883 error = mac_biba_subject_privileged(subj);
1884 if (error)
1885 return (error);
1886
1887 return (0);
1888 }
1889
1890 static int
1891 mac_biba_check_system_acct(struct ucred *cred, struct vnode *vp,
1892 struct label *label)
1893 {
1894 struct mac_biba *subj, *obj;
1895 int error;
1896
1897 if (!mac_biba_enabled)
1898 return (0);
1899
1900 subj = SLOT(cred->cr_label);
1901
1902 error = mac_biba_subject_privileged(subj);
1903 if (error)
1904 return (error);
1905
1906 if (label == NULL)
1907 return (0);
1908
1909 obj = SLOT(label);
1910 if (!mac_biba_high_effective(obj))
1911 return (EACCES);
1912
1913 return (0);
1914 }
1915
1916 static int
1917 mac_biba_check_system_settime(struct ucred *cred)
1918 {
1919 struct mac_biba *subj;
1920 int error;
1921
1922 if (!mac_biba_enabled)
1923 return (0);
1924
1925 subj = SLOT(cred->cr_label);
1926
1927 error = mac_biba_subject_privileged(subj);
1928 if (error)
1929 return (error);
1930
1931 return (0);
1932 }
1933
1934 static int
1935 mac_biba_check_system_swapon(struct ucred *cred, struct vnode *vp,
1936 struct label *label)
1937 {
1938 struct mac_biba *subj, *obj;
1939 int error;
1940
1941 if (!mac_biba_enabled)
1942 return (0);
1943
1944 subj = SLOT(cred->cr_label);
1945 obj = SLOT(label);
1946
1947 error = mac_biba_subject_privileged(subj);
1948 if (error)
1949 return (error);
1950
1951 if (!mac_biba_high_effective(obj))
1952 return (EACCES);
1953
1954 return (0);
1955 }
1956
1957 static int
1958 mac_biba_check_system_swapoff(struct ucred *cred, struct vnode *vp,
1959 struct label *label)
1960 {
1961 struct mac_biba *subj, *obj;
1962 int error;
1963
1964 if (!mac_biba_enabled)
1965 return (0);
1966
1967 subj = SLOT(cred->cr_label);
1968 obj = SLOT(label);
1969
1970 error = mac_biba_subject_privileged(subj);
1971 if (error)
1972 return (error);
1973
1974 return (0);
1975 }
1976
1977 static int
1978 mac_biba_check_system_sysctl(struct ucred *cred, struct sysctl_oid *oidp,
1979 void *arg1, int arg2, struct sysctl_req *req)
1980 {
1981 struct mac_biba *subj;
1982 int error;
1983
1984 if (!mac_biba_enabled)
1985 return (0);
1986
1987 subj = SLOT(cred->cr_label);
1988
1989 /*
1990 * Treat sysctl variables without CTLFLAG_ANYBODY flag as
1991 * biba/high, but also require privilege to change them.
1992 */
1993 if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) {
1994 if (!mac_biba_subject_dominate_high(subj))
1995 return (EACCES);
1996
1997 error = mac_biba_subject_privileged(subj);
1998 if (error)
1999 return (error);
2000 }
2001
2002 return (0);
2003 }
2004
2005 static int
2006 mac_biba_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
2007 struct label *dlabel)
2008 {
2009 struct mac_biba *subj, *obj;
2010
2011 if (!mac_biba_enabled)
2012 return (0);
2013
2014 subj = SLOT(cred->cr_label);
2015 obj = SLOT(dlabel);
2016
2017 if (!mac_biba_dominate_effective(obj, subj))
2018 return (EACCES);
2019
2020 return (0);
2021 }
2022
2023 static int
2024 mac_biba_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
2025 struct label *dlabel)
2026 {
2027 struct mac_biba *subj, *obj;
2028
2029 if (!mac_biba_enabled)
2030 return (0);
2031
2032 subj = SLOT(cred->cr_label);
2033 obj = SLOT(dlabel);
2034
2035 if (!mac_biba_dominate_effective(obj, subj))
2036 return (EACCES);
2037
2038 return (0);
2039 }
2040
2041 static int
2042 mac_biba_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2043 struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2044 {
2045 struct mac_biba *subj, *obj;
2046
2047 if (!mac_biba_enabled)
2048 return (0);
2049
2050 subj = SLOT(cred->cr_label);
2051 obj = SLOT(dlabel);
2052
2053 if (!mac_biba_dominate_effective(subj, obj))
2054 return (EACCES);
2055
2056 return (0);
2057 }
2058
2059 static int
2060 mac_biba_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2061 struct label *dlabel, struct vnode *vp, struct label *label,
2062 struct componentname *cnp)
2063 {
2064 struct mac_biba *subj, *obj;
2065
2066 if (!mac_biba_enabled)
2067 return (0);
2068
2069 subj = SLOT(cred->cr_label);
2070 obj = SLOT(dlabel);
2071
2072 if (!mac_biba_dominate_effective(subj, obj))
2073 return (EACCES);
2074
2075 obj = SLOT(label);
2076
2077 if (!mac_biba_dominate_effective(subj, obj))
2078 return (EACCES);
2079
2080 return (0);
2081 }
2082
2083 static int
2084 mac_biba_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2085 struct label *label, acl_type_t type)
2086 {
2087 struct mac_biba *subj, *obj;
2088
2089 if (!mac_biba_enabled)
2090 return (0);
2091
2092 subj = SLOT(cred->cr_label);
2093 obj = SLOT(label);
2094
2095 if (!mac_biba_dominate_effective(subj, obj))
2096 return (EACCES);
2097
2098 return (0);
2099 }
2100
2101 static int
2102 mac_biba_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
2103 struct label *label, int attrnamespace, const char *name)
2104 {
2105 struct mac_biba *subj, *obj;
2106
2107 if (!mac_biba_enabled)
2108 return (0);
2109
2110 subj = SLOT(cred->cr_label);
2111 obj = SLOT(label);
2112
2113 if (!mac_biba_dominate_effective(subj, obj))
2114 return (EACCES);
2115
2116 return (0);
2117 }
2118
2119 static int
2120 mac_biba_check_vnode_exec(struct ucred *cred, struct vnode *vp,
2121 struct label *label, struct image_params *imgp,
2122 struct label *execlabel)
2123 {
2124 struct mac_biba *subj, *obj, *exec;
2125 int error;
2126
2127 if (execlabel != NULL) {
2128 /*
2129 * We currently don't permit labels to be changed at
2130 * exec-time as part of Biba, so disallow non-NULL
2131 * Biba label elements in the execlabel.
2132 */
2133 exec = SLOT(execlabel);
2134 error = biba_atmostflags(exec, 0);
2135 if (error)
2136 return (error);
2137 }
2138
2139 if (!mac_biba_enabled)
2140 return (0);
2141
2142 subj = SLOT(cred->cr_label);
2143 obj = SLOT(label);
2144
2145 if (!mac_biba_dominate_effective(obj, subj))
2146 return (EACCES);
2147
2148 return (0);
2149 }
2150
2151 static int
2152 mac_biba_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
2153 struct label *label, acl_type_t type)
2154 {
2155 struct mac_biba *subj, *obj;
2156
2157 if (!mac_biba_enabled)
2158 return (0);
2159
2160 subj = SLOT(cred->cr_label);
2161 obj = SLOT(label);
2162
2163 if (!mac_biba_dominate_effective(obj, subj))
2164 return (EACCES);
2165
2166 return (0);
2167 }
2168
2169 static int
2170 mac_biba_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2171 struct label *label, int attrnamespace, const char *name, struct uio *uio)
2172 {
2173 struct mac_biba *subj, *obj;
2174
2175 if (!mac_biba_enabled)
2176 return (0);
2177
2178 subj = SLOT(cred->cr_label);
2179 obj = SLOT(label);
2180
2181 if (!mac_biba_dominate_effective(obj, subj))
2182 return (EACCES);
2183
2184 return (0);
2185 }
2186
2187 static int
2188 mac_biba_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2189 struct label *dlabel, struct vnode *vp, struct label *label,
2190 struct componentname *cnp)
2191 {
2192 struct mac_biba *subj, *obj;
2193
2194 if (!mac_biba_enabled)
2195 return (0);
2196
2197 subj = SLOT(cred->cr_label);
2198 obj = SLOT(dlabel);
2199
2200 if (!mac_biba_dominate_effective(subj, obj))
2201 return (EACCES);
2202
2203 obj = SLOT(label);
2204
2205 if (!mac_biba_dominate_effective(subj, obj))
2206 return (EACCES);
2207
2208 return (0);
2209 }
2210
2211 static int
2212 mac_biba_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
2213 struct label *label, int attrnamespace)
2214 {
2215 struct mac_biba *subj, *obj;
2216
2217 if (!mac_biba_enabled)
2218 return (0);
2219
2220 subj = SLOT(cred->cr_label);
2221 obj = SLOT(label);
2222
2223 if (!mac_biba_dominate_effective(obj, subj))
2224 return (EACCES);
2225
2226 return (0);
2227 }
2228
2229 static int
2230 mac_biba_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2231 struct label *dlabel, struct componentname *cnp)
2232 {
2233 struct mac_biba *subj, *obj;
2234
2235 if (!mac_biba_enabled)
2236 return (0);
2237
2238 subj = SLOT(cred->cr_label);
2239 obj = SLOT(dlabel);
2240
2241 if (!mac_biba_dominate_effective(obj, subj))
2242 return (EACCES);
2243
2244 return (0);
2245 }
2246
2247 static int
2248 mac_biba_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2249 struct label *label, int prot)
2250 {
2251 struct mac_biba *subj, *obj;
2252
2253 /*
2254 * Rely on the use of open()-time protections to handle
2255 * non-revocation cases.
2256 */
2257 if (!mac_biba_enabled || !revocation_enabled)
2258 return (0);
2259
2260 subj = SLOT(cred->cr_label);
2261 obj = SLOT(label);
2262
2263 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2264 if (!mac_biba_dominate_effective(obj, subj))
2265 return (EACCES);
2266 }
2267 if (prot & VM_PROT_WRITE) {
2268 if (!mac_biba_dominate_effective(subj, obj))
2269 return (EACCES);
2270 }
2271
2272 return (0);
2273 }
2274
2275 static int
2276 mac_biba_check_vnode_open(struct ucred *cred, struct vnode *vp,
2277 struct label *vnodelabel, int acc_mode)
2278 {
2279 struct mac_biba *subj, *obj;
2280
2281 if (!mac_biba_enabled)
2282 return (0);
2283
2284 subj = SLOT(cred->cr_label);
2285 obj = SLOT(vnodelabel);
2286
2287 /* XXX privilege override for admin? */
2288 if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2289 if (!mac_biba_dominate_effective(obj, subj))
2290 return (EACCES);
2291 }
2292 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2293 if (!mac_biba_dominate_effective(subj, obj))
2294 return (EACCES);
2295 }
2296
2297 return (0);
2298 }
2299
2300 static int
2301 mac_biba_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2302 struct vnode *vp, struct label *label)
2303 {
2304 struct mac_biba *subj, *obj;
2305
2306 if (!mac_biba_enabled || !revocation_enabled)
2307 return (0);
2308
2309 subj = SLOT(active_cred->cr_label);
2310 obj = SLOT(label);
2311
2312 if (!mac_biba_dominate_effective(obj, subj))
2313 return (EACCES);
2314
2315 return (0);
2316 }
2317
2318 static int
2319 mac_biba_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2320 struct vnode *vp, struct label *label)
2321 {
2322 struct mac_biba *subj, *obj;
2323
2324 if (!mac_biba_enabled || !revocation_enabled)
2325 return (0);
2326
2327 subj = SLOT(active_cred->cr_label);
2328 obj = SLOT(label);
2329
2330 if (!mac_biba_dominate_effective(obj, subj))
2331 return (EACCES);
2332
2333 return (0);
2334 }
2335
2336 static int
2337 mac_biba_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
2338 struct label *dlabel)
2339 {
2340 struct mac_biba *subj, *obj;
2341
2342 if (!mac_biba_enabled)
2343 return (0);
2344
2345 subj = SLOT(cred->cr_label);
2346 obj = SLOT(dlabel);
2347
2348 if (!mac_biba_dominate_effective(obj, subj))
2349 return (EACCES);
2350
2351 return (0);
2352 }
2353
2354 static int
2355 mac_biba_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
2356 struct label *label)
2357 {
2358 struct mac_biba *subj, *obj;
2359
2360 if (!mac_biba_enabled)
2361 return (0);
2362
2363 subj = SLOT(cred->cr_label);
2364 obj = SLOT(label);
2365
2366 if (!mac_biba_dominate_effective(obj, subj))
2367 return (EACCES);
2368
2369 return (0);
2370 }
2371
2372 static int
2373 mac_biba_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2374 struct label *vnodelabel, struct label *newlabel)
2375 {
2376 struct mac_biba *old, *new, *subj;
2377 int error;
2378
2379 old = SLOT(vnodelabel);
2380 new = SLOT(newlabel);
2381 subj = SLOT(cred->cr_label);
2382
2383 /*
2384 * If there is a Biba label update for the vnode, it must be a
2385 * effective label.
2386 */
2387 error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
2388 if (error)
2389 return (error);
2390
2391 /*
2392 * To perform a relabel of the vnode (Biba label or not), Biba must
2393 * authorize the relabel.
2394 */
2395 if (!mac_biba_effective_in_range(old, subj))
2396 return (EPERM);
2397
2398 /*
2399 * If the Biba label is to be changed, authorize as appropriate.
2400 */
2401 if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
2402 /*
2403 * To change the Biba label on a vnode, the new vnode label
2404 * must be in the subject range.
2405 */
2406 if (!mac_biba_effective_in_range(new, subj))
2407 return (EPERM);
2408
2409 /*
2410 * To change the Biba label on the vnode to be EQUAL,
2411 * the subject must have appropriate privilege.
2412 */
2413 if (mac_biba_contains_equal(new)) {
2414 error = mac_biba_subject_privileged(subj);
2415 if (error)
2416 return (error);
2417 }
2418 }
2419
2420 return (0);
2421 }
2422
2423 static int
2424 mac_biba_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2425 struct label *dlabel, struct vnode *vp, struct label *label,
2426 struct componentname *cnp)
2427 {
2428 struct mac_biba *subj, *obj;
2429
2430 if (!mac_biba_enabled)
2431 return (0);
2432
2433 subj = SLOT(cred->cr_label);
2434 obj = SLOT(dlabel);
2435
2436 if (!mac_biba_dominate_effective(subj, obj))
2437 return (EACCES);
2438
2439 obj = SLOT(label);
2440
2441 if (!mac_biba_dominate_effective(subj, obj))
2442 return (EACCES);
2443
2444 return (0);
2445 }
2446
2447 static int
2448 mac_biba_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2449 struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2450 struct componentname *cnp)
2451 {
2452 struct mac_biba *subj, *obj;
2453
2454 if (!mac_biba_enabled)
2455 return (0);
2456
2457 subj = SLOT(cred->cr_label);
2458 obj = SLOT(dlabel);
2459
2460 if (!mac_biba_dominate_effective(subj, obj))
2461 return (EACCES);
2462
2463 if (vp != NULL) {
2464 obj = SLOT(label);
2465
2466 if (!mac_biba_dominate_effective(subj, obj))
2467 return (EACCES);
2468 }
2469
2470 return (0);
2471 }
2472
2473 static int
2474 mac_biba_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2475 struct label *label)
2476 {
2477 struct mac_biba *subj, *obj;
2478
2479 if (!mac_biba_enabled)
2480 return (0);
2481
2482 subj = SLOT(cred->cr_label);
2483 obj = SLOT(label);
2484
2485 if (!mac_biba_dominate_effective(subj, obj))
2486 return (EACCES);
2487
2488 return (0);
2489 }
2490
2491 static int
2492 mac_biba_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2493 struct label *label, acl_type_t type, struct acl *acl)
2494 {
2495 struct mac_biba *subj, *obj;
2496
2497 if (!mac_biba_enabled)
2498 return (0);
2499
2500 subj = SLOT(cred->cr_label);
2501 obj = SLOT(label);
2502
2503 if (!mac_biba_dominate_effective(subj, obj))
2504 return (EACCES);
2505
2506 return (0);
2507 }
2508
2509 static int
2510 mac_biba_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2511 struct label *vnodelabel, int attrnamespace, const char *name,
2512 struct uio *uio)
2513 {
2514 struct mac_biba *subj, *obj;
2515
2516 if (!mac_biba_enabled)
2517 return (0);
2518
2519 subj = SLOT(cred->cr_label);
2520 obj = SLOT(vnodelabel);
2521
2522 if (!mac_biba_dominate_effective(subj, obj))
2523 return (EACCES);
2524
2525 /* XXX: protect the MAC EA in a special way? */
2526
2527 return (0);
2528 }
2529
2530 static int
2531 mac_biba_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2532 struct label *vnodelabel, u_long flags)
2533 {
2534 struct mac_biba *subj, *obj;
2535
2536 if (!mac_biba_enabled)
2537 return (0);
2538
2539 subj = SLOT(cred->cr_label);
2540 obj = SLOT(vnodelabel);
2541
2542 if (!mac_biba_dominate_effective(subj, obj))
2543 return (EACCES);
2544
2545 return (0);
2546 }
2547
2548 static int
2549 mac_biba_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2550 struct label *vnodelabel, mode_t mode)
2551 {
2552 struct mac_biba *subj, *obj;
2553
2554 if (!mac_biba_enabled)
2555 return (0);
2556
2557 subj = SLOT(cred->cr_label);
2558 obj = SLOT(vnodelabel);
2559
2560 if (!mac_biba_dominate_effective(subj, obj))
2561 return (EACCES);
2562
2563 return (0);
2564 }
2565
2566 static int
2567 mac_biba_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2568 struct label *vnodelabel, uid_t uid, gid_t gid)
2569 {
2570 struct mac_biba *subj, *obj;
2571
2572 if (!mac_biba_enabled)
2573 return (0);
2574
2575 subj = SLOT(cred->cr_label);
2576 obj = SLOT(vnodelabel);
2577
2578 if (!mac_biba_dominate_effective(subj, obj))
2579 return (EACCES);
2580
2581 return (0);
2582 }
2583
2584 static int
2585 mac_biba_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2586 struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2587 {
2588 struct mac_biba *subj, *obj;
2589
2590 if (!mac_biba_enabled)
2591 return (0);
2592
2593 subj = SLOT(cred->cr_label);
2594 obj = SLOT(vnodelabel);
2595
2596 if (!mac_biba_dominate_effective(subj, obj))
2597 return (EACCES);
2598
2599 return (0);
2600 }
2601
2602 static int
2603 mac_biba_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2604 struct vnode *vp, struct label *vnodelabel)
2605 {
2606 struct mac_biba *subj, *obj;
2607
2608 if (!mac_biba_enabled)
2609 return (0);
2610
2611 subj = SLOT(active_cred->cr_label);
2612 obj = SLOT(vnodelabel);
2613
2614 if (!mac_biba_dominate_effective(obj, subj))
2615 return (EACCES);
2616
2617 return (0);
2618 }
2619
2620 static int
2621 mac_biba_check_vnode_write(struct ucred *active_cred,
2622 struct ucred *file_cred, struct vnode *vp, struct label *label)
2623 {
2624 struct mac_biba *subj, *obj;
2625
2626 if (!mac_biba_enabled || !revocation_enabled)
2627 return (0);
2628
2629 subj = SLOT(active_cred->cr_label);
2630 obj = SLOT(label);
2631
2632 if (!mac_biba_dominate_effective(subj, obj))
2633 return (EACCES);
2634
2635 return (0);
2636 }
2637
2638 static struct mac_policy_ops mac_biba_ops =
2639 {
2640 .mpo_init = mac_biba_init,
2641 .mpo_init_bpfdesc_label = mac_biba_init_label,
2642 .mpo_init_cred_label = mac_biba_init_label,
2643 .mpo_init_devfsdirent_label = mac_biba_init_label,
2644 .mpo_init_ifnet_label = mac_biba_init_label,
2645 .mpo_init_inpcb_label = mac_biba_init_label_waitcheck,
2646 .mpo_init_ipq_label = mac_biba_init_label_waitcheck,
2647 .mpo_init_mbuf_label = mac_biba_init_label_waitcheck,
2648 .mpo_init_mount_label = mac_biba_init_label,
2649 .mpo_init_mount_fs_label = mac_biba_init_label,
2650 .mpo_init_pipe_label = mac_biba_init_label,
2651 .mpo_init_socket_label = mac_biba_init_label_waitcheck,
2652 .mpo_init_socket_peer_label = mac_biba_init_label_waitcheck,
2653 .mpo_init_vnode_label = mac_biba_init_label,
2654 .mpo_destroy_bpfdesc_label = mac_biba_destroy_label,
2655 .mpo_destroy_cred_label = mac_biba_destroy_label,
2656 .mpo_destroy_devfsdirent_label = mac_biba_destroy_label,
2657 .mpo_destroy_ifnet_label = mac_biba_destroy_label,
2658 .mpo_destroy_inpcb_label = mac_biba_destroy_label,
2659 .mpo_destroy_ipq_label = mac_biba_destroy_label,
2660 .mpo_destroy_mbuf_label = mac_biba_destroy_label,
2661 .mpo_destroy_mount_label = mac_biba_destroy_label,
2662 .mpo_destroy_mount_fs_label = mac_biba_destroy_label,
2663 .mpo_destroy_pipe_label = mac_biba_destroy_label,
2664 .mpo_destroy_socket_label = mac_biba_destroy_label,
2665 .mpo_destroy_socket_peer_label = mac_biba_destroy_label,
2666 .mpo_destroy_vnode_label = mac_biba_destroy_label,
2667 .mpo_copy_cred_label = mac_biba_copy_label,
2668 .mpo_copy_ifnet_label = mac_biba_copy_label,
2669 .mpo_copy_mbuf_label = mac_biba_copy_label,
2670 .mpo_copy_pipe_label = mac_biba_copy_label,
2671 .mpo_copy_socket_label = mac_biba_copy_label,
2672 .mpo_copy_vnode_label = mac_biba_copy_label,
2673 .mpo_externalize_cred_label = mac_biba_externalize_label,
2674 .mpo_externalize_ifnet_label = mac_biba_externalize_label,
2675 .mpo_externalize_pipe_label = mac_biba_externalize_label,
2676 .mpo_externalize_socket_label = mac_biba_externalize_label,
2677 .mpo_externalize_socket_peer_label = mac_biba_externalize_label,
2678 .mpo_externalize_vnode_label = mac_biba_externalize_label,
2679 .mpo_internalize_cred_label = mac_biba_internalize_label,
2680 .mpo_internalize_ifnet_label = mac_biba_internalize_label,
2681 .mpo_internalize_pipe_label = mac_biba_internalize_label,
2682 .mpo_internalize_socket_label = mac_biba_internalize_label,
2683 .mpo_internalize_vnode_label = mac_biba_internalize_label,
2684 .mpo_create_devfs_device = mac_biba_create_devfs_device,
2685 .mpo_create_devfs_directory = mac_biba_create_devfs_directory,
2686 .mpo_create_devfs_symlink = mac_biba_create_devfs_symlink,
2687 .mpo_create_mount = mac_biba_create_mount,
2688 .mpo_create_root_mount = mac_biba_create_root_mount,
2689 .mpo_relabel_vnode = mac_biba_relabel_vnode,
2690 .mpo_update_devfsdirent = mac_biba_update_devfsdirent,
2691 .mpo_associate_vnode_devfs = mac_biba_associate_vnode_devfs,
2692 .mpo_associate_vnode_extattr = mac_biba_associate_vnode_extattr,
2693 .mpo_associate_vnode_singlelabel = mac_biba_associate_vnode_singlelabel,
2694 .mpo_create_vnode_extattr = mac_biba_create_vnode_extattr,
2695 .mpo_setlabel_vnode_extattr = mac_biba_setlabel_vnode_extattr,
2696 .mpo_create_mbuf_from_socket = mac_biba_create_mbuf_from_socket,
2697 .mpo_create_pipe = mac_biba_create_pipe,
2698 .mpo_create_socket = mac_biba_create_socket,
2699 .mpo_create_socket_from_socket = mac_biba_create_socket_from_socket,
2700 .mpo_relabel_pipe = mac_biba_relabel_pipe,
2701 .mpo_relabel_socket = mac_biba_relabel_socket,
2702 .mpo_set_socket_peer_from_mbuf = mac_biba_set_socket_peer_from_mbuf,
2703 .mpo_set_socket_peer_from_socket = mac_biba_set_socket_peer_from_socket,
2704 .mpo_create_bpfdesc = mac_biba_create_bpfdesc,
2705 .mpo_create_datagram_from_ipq = mac_biba_create_datagram_from_ipq,
2706 .mpo_create_fragment = mac_biba_create_fragment,
2707 .mpo_create_ifnet = mac_biba_create_ifnet,
2708 .mpo_create_inpcb_from_socket = mac_biba_create_inpcb_from_socket,
2709 .mpo_create_ipq = mac_biba_create_ipq,
2710 .mpo_create_mbuf_from_inpcb = mac_biba_create_mbuf_from_inpcb,
2711 .mpo_create_mbuf_from_mbuf = mac_biba_create_mbuf_from_mbuf,
2712 .mpo_create_mbuf_linklayer = mac_biba_create_mbuf_linklayer,
2713 .mpo_create_mbuf_from_bpfdesc = mac_biba_create_mbuf_from_bpfdesc,
2714 .mpo_create_mbuf_from_ifnet = mac_biba_create_mbuf_from_ifnet,
2715 .mpo_create_mbuf_multicast_encap = mac_biba_create_mbuf_multicast_encap,
2716 .mpo_create_mbuf_netlayer = mac_biba_create_mbuf_netlayer,
2717 .mpo_fragment_match = mac_biba_fragment_match,
2718 .mpo_relabel_ifnet = mac_biba_relabel_ifnet,
2719 .mpo_update_ipq = mac_biba_update_ipq,
2720 .mpo_inpcb_sosetlabel = mac_biba_inpcb_sosetlabel,
2721 .mpo_create_proc0 = mac_biba_create_proc0,
2722 .mpo_create_proc1 = mac_biba_create_proc1,
2723 .mpo_relabel_cred = mac_biba_relabel_cred,
2724 .mpo_check_bpfdesc_receive = mac_biba_check_bpfdesc_receive,
2725 .mpo_check_cred_relabel = mac_biba_check_cred_relabel,
2726 .mpo_check_cred_visible = mac_biba_check_cred_visible,
2727 .mpo_check_ifnet_relabel = mac_biba_check_ifnet_relabel,
2728 .mpo_check_ifnet_transmit = mac_biba_check_ifnet_transmit,
2729 .mpo_check_inpcb_deliver = mac_biba_check_inpcb_deliver,
2730 .mpo_check_kld_load = mac_biba_check_kld_load,
2731 .mpo_check_kld_unload = mac_biba_check_kld_unload,
2732 .mpo_check_mount_stat = mac_biba_check_mount_stat,
2733 .mpo_check_pipe_ioctl = mac_biba_check_pipe_ioctl,
2734 .mpo_check_pipe_poll = mac_biba_check_pipe_poll,
2735 .mpo_check_pipe_read = mac_biba_check_pipe_read,
2736 .mpo_check_pipe_relabel = mac_biba_check_pipe_relabel,
2737 .mpo_check_pipe_stat = mac_biba_check_pipe_stat,
2738 .mpo_check_pipe_write = mac_biba_check_pipe_write,
2739 .mpo_check_proc_debug = mac_biba_check_proc_debug,
2740 .mpo_check_proc_sched = mac_biba_check_proc_sched,
2741 .mpo_check_proc_signal = mac_biba_check_proc_signal,
2742 .mpo_check_socket_deliver = mac_biba_check_socket_deliver,
2743 .mpo_check_socket_relabel = mac_biba_check_socket_relabel,
2744 .mpo_check_socket_visible = mac_biba_check_socket_visible,
2745 .mpo_check_sysarch_ioperm = mac_biba_check_sysarch_ioperm,
2746 .mpo_check_system_acct = mac_biba_check_system_acct,
2747 .mpo_check_system_settime = mac_biba_check_system_settime,
2748 .mpo_check_system_swapon = mac_biba_check_system_swapon,
2749 .mpo_check_system_swapoff = mac_biba_check_system_swapoff,
2750 .mpo_check_system_sysctl = mac_biba_check_system_sysctl,
2751 .mpo_check_vnode_access = mac_biba_check_vnode_open,
2752 .mpo_check_vnode_chdir = mac_biba_check_vnode_chdir,
2753 .mpo_check_vnode_chroot = mac_biba_check_vnode_chroot,
2754 .mpo_check_vnode_create = mac_biba_check_vnode_create,
2755 .mpo_check_vnode_delete = mac_biba_check_vnode_delete,
2756 .mpo_check_vnode_deleteacl = mac_biba_check_vnode_deleteacl,
2757 .mpo_check_vnode_deleteextattr = mac_biba_check_vnode_deleteextattr,
2758 .mpo_check_vnode_exec = mac_biba_check_vnode_exec,
2759 .mpo_check_vnode_getacl = mac_biba_check_vnode_getacl,
2760 .mpo_check_vnode_getextattr = mac_biba_check_vnode_getextattr,
2761 .mpo_check_vnode_link = mac_biba_check_vnode_link,
2762 .mpo_check_vnode_listextattr = mac_biba_check_vnode_listextattr,
2763 .mpo_check_vnode_lookup = mac_biba_check_vnode_lookup,
2764 .mpo_check_vnode_mmap = mac_biba_check_vnode_mmap,
2765 .mpo_check_vnode_open = mac_biba_check_vnode_open,
2766 .mpo_check_vnode_poll = mac_biba_check_vnode_poll,
2767 .mpo_check_vnode_read = mac_biba_check_vnode_read,
2768 .mpo_check_vnode_readdir = mac_biba_check_vnode_readdir,
2769 .mpo_check_vnode_readlink = mac_biba_check_vnode_readlink,
2770 .mpo_check_vnode_relabel = mac_biba_check_vnode_relabel,
2771 .mpo_check_vnode_rename_from = mac_biba_check_vnode_rename_from,
2772 .mpo_check_vnode_rename_to = mac_biba_check_vnode_rename_to,
2773 .mpo_check_vnode_revoke = mac_biba_check_vnode_revoke,
2774 .mpo_check_vnode_setacl = mac_biba_check_vnode_setacl,
2775 .mpo_check_vnode_setextattr = mac_biba_check_vnode_setextattr,
2776 .mpo_check_vnode_setflags = mac_biba_check_vnode_setflags,
2777 .mpo_check_vnode_setmode = mac_biba_check_vnode_setmode,
2778 .mpo_check_vnode_setowner = mac_biba_check_vnode_setowner,
2779 .mpo_check_vnode_setutimes = mac_biba_check_vnode_setutimes,
2780 .mpo_check_vnode_stat = mac_biba_check_vnode_stat,
2781 .mpo_check_vnode_write = mac_biba_check_vnode_write,
2782 };
2783
2784 MAC_POLICY_SET(&mac_biba_ops, mac_biba, "TrustedBSD MAC/Biba",
2785 MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_biba_slot);
Cache object: 5a37756a4e0e9c6f41ab80eb1bbcee46
|