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