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