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