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