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