1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed by Robert Watson for the TrustedBSD Project.
7 *
8 * This software was developed for the FreeBSD Project in part by Network
9 * Associates Laboratories, the Security Research Division of Network
10 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
11 * as part of the DARPA CHATS research program.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $FreeBSD: head/sys/security/mac_mls/mac_mls.c 123173 2003-12-06 21:48:03Z rwatson $
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
82SYSCTL_DECL(_security_mac);
83
84SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
85 "TrustedBSD mac_mls policy controls");
86
87static int mac_mls_label_size = sizeof(struct mac_mls);
88SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
89 &mac_mls_label_size, 0, "Size of struct mac_mls");
90
91static int mac_mls_enabled = 1;
92SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
93 &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
94TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
95
96static int destroyed_not_inited;
97SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
98 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
99
100static int ptys_equal = 0;
101SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
102 &ptys_equal, 0, "Label pty devices as mls/equal on create");
103TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
104
105static int revocation_enabled = 0;
106SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
107 &revocation_enabled, 0, "Revoke access to objects on relabel");
108TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
109
110static int max_compartments = MAC_MLS_MAX_COMPARTMENTS;
111SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
112 &max_compartments, 0, "Maximum compartments the policy supports");
113
114static int mac_mls_slot;
115#define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
116
117static uma_zone_t zone_mls;
118
119static __inline int
120mls_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
129static struct mac_mls *
130mls_alloc(int flag)
131{
132
133 return (uma_zalloc(zone_mls, flag | M_ZERO));
134}
135
136static void
137mls_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
146static int
147mls_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
155static int
156mac_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
208static int
209mac_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
218static int
219mac_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
235static int
236mac_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
246static int
247mac_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
257static int
258mac_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
269static int
270mac_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
287static int
288mac_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
313static int
314mac_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
385static void
386mac_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
406static void
407mac_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
419static void
420mac_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
431static void
432mac_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
442static void
443mac_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 */
455static void
456mac_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 */
466static void
467mac_mls_init_label(struct label *label)
468{
469
470 SLOT(label) = mls_alloc(M_WAITOK);
471}
472
473static int
474mac_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
484static void
485mac_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 */
497static int
498mac_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 */
546static int
547mac_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
578static int
579mac_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
594static int
595mac_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 */
653static int
654mac_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
708static int
709mac_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
730static void
731mac_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 */
741static void
742mac_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
766static void
767mac_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
776static void
777mac_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
789static void
790mac_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
802static void
803mac_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
815static void
816mac_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
827static void
828mac_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
840static void
841mac_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
853static int
854mac_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
893static void
894mac_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
905static int
906mac_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
928static int
929mac_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 */
953static void
954mac_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
965static void
966mac_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
977static void
978mac_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
989static void
990mac_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
1001static void
1002mac_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
1014static void
1015mac_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
1026static void
1027mac_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
1038static void
1039mac_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 */
1053static void
1054mac_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
1066static void
1067mac_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
1078static void
1079mac_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
1095static void
1096mac_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
1107static void
1108mac_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
1120static void
1121mac_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
1132static void
1133mac_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
1153static void
1154mac_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
1164static void
1165mac_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
1176static void
1177mac_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
1188static void
1189mac_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
1201static void
1202mac_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
1213static int
1214mac_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
1225static void
1226mac_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
1237static void
1238mac_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
1245static void
1246mac_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 */
1260static void
1261mac_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
1272static void
1273mac_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
1284static void
1285mac_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 */
1298static int
1299mac_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
1315static int
1316mac_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
1377static int
1378mac_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
1395static int
1396mac_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
1421static int
1422mac_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
1436static int
1437mac_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
1451static int
1452mac_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
1469static int
1470mac_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
1482static int
1483mac_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
1500static int
1501mac_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
1518static int
1519mac_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
1569static int
1570mac_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
1587static int
1588mac_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
1605static int
1606mac_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
1625static int
1626mac_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
1645static int
1646mac_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
1665static int
1666mac_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
1680static int
1681mac_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
1731static int
1732mac_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
1749static int
1750mac_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
1768static int
1769mac_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
1786static int
1787mac_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
1804static int
1805mac_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
1822static int
1823mac_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
1846static int
1847mac_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
1864static int
1865mac_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
1882static int
1883mac_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
1914static int
1915mac_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
1932static int
1933mac_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
1950static int
1951mac_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
1973static int
1974mac_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
1992static int
1993mac_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
2010static int
2011mac_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
2038static int
2039mac_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
2063static int
2064mac_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
2081static int
2082mac_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
2099static int
2100mac_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
2117static int
2118mac_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
2135static int
2136mac_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
2187static int
2188mac_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
2211static int
2212mac_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
2237static int
2238mac_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
2255static int
2256mac_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
2273static int
2274mac_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
2294static int
2295mac_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
2312static int
2313mac_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
2330static int
2331mac_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
2348static int
2349mac_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
2366static int
2367mac_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
2384static int
2385mac_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
2402static 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
2540MAC_POLICY_SET(&mac_mls_ops, mac_mls, "TrustedBSD MAC/MLS",
2541 MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_mls_slot);
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed by Robert Watson for the TrustedBSD Project.
7 *
8 * This software was developed for the FreeBSD Project in part by Network
9 * Associates Laboratories, the Security Research Division of Network
10 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
11 * as part of the DARPA CHATS research program.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $FreeBSD: head/sys/security/mac_mls/mac_mls.c 123173 2003-12-06 21:48:03Z rwatson $
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
82SYSCTL_DECL(_security_mac);
83
84SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
85 "TrustedBSD mac_mls policy controls");
86
87static int mac_mls_label_size = sizeof(struct mac_mls);
88SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
89 &mac_mls_label_size, 0, "Size of struct mac_mls");
90
91static int mac_mls_enabled = 1;
92SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
93 &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
94TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
95
96static int destroyed_not_inited;
97SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
98 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
99
100static int ptys_equal = 0;
101SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
102 &ptys_equal, 0, "Label pty devices as mls/equal on create");
103TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
104
105static int revocation_enabled = 0;
106SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
107 &revocation_enabled, 0, "Revoke access to objects on relabel");
108TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
109
110static int max_compartments = MAC_MLS_MAX_COMPARTMENTS;
111SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
112 &max_compartments, 0, "Maximum compartments the policy supports");
113
114static int mac_mls_slot;
115#define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
116
117static uma_zone_t zone_mls;
118
119static __inline int
120mls_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
129static struct mac_mls *
130mls_alloc(int flag)
131{
132
133 return (uma_zalloc(zone_mls, flag | M_ZERO));
134}
135
136static void
137mls_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
146static int
147mls_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
155static int
156mac_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
208static int
209mac_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
218static int
219mac_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
235static int
236mac_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
246static int
247mac_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
257static int
258mac_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
269static int
270mac_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
287static int
288mac_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
313static int
314mac_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
385static void
386mac_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
406static void
407mac_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
419static void
420mac_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
431static void
432mac_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
442static void
443mac_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 */
455static void
456mac_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 */
466static void
467mac_mls_init_label(struct label *label)
468{
469
470 SLOT(label) = mls_alloc(M_WAITOK);
471}
472
473static int
474mac_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
484static void
485mac_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 */
497static int
498mac_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 */
546static int
547mac_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
578static int
579mac_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
594static int
595mac_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 */
653static int
654mac_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
708static int
709mac_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
730static void
731mac_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 */
741static void
742mac_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
766static void
767mac_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
776static void
777mac_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
789static void
790mac_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
802static void
803mac_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
815static void
816mac_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
827static void
828mac_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
840static void
841mac_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
853static int
854mac_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
893static void
894mac_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
905static int
906mac_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
928static int
929mac_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 */
953static void
954mac_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
965static void
966mac_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
977static void
978mac_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
989static void
990mac_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
1001static void
1002mac_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
1014static void
1015mac_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
1026static void
1027mac_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
1038static void
1039mac_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 */
1053static void
1054mac_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
1066static void
1067mac_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
1078static void
1079mac_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
1095static void
1096mac_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
1107static void
1108mac_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
1120static void
1121mac_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
1132static void
1133mac_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
1153static void
1154mac_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
1164static void
1165mac_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
1176static void
1177mac_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
1188static void
1189mac_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
1201static void
1202mac_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
1213static int
1214mac_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
1225static void
1226mac_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
1237static void
1238mac_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
1245static void
1246mac_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 */
1260static void
1261mac_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
1272static void
1273mac_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
1284static void
1285mac_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 */
1298static int
1299mac_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
1315static int
1316mac_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
1377static int
1378mac_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
1395static int
1396mac_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
1421static int
1422mac_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
1436static int
1437mac_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
1451static int
1452mac_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
1469static int
1470mac_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
1482static int
1483mac_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
1500static int
1501mac_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
1518static int
1519mac_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
1569static int
1570mac_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
1587static int
1588mac_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
1605static int
1606mac_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
1625static int
1626mac_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
1645static int
1646mac_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
1665static int
1666mac_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
1680static int
1681mac_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
1731static int
1732mac_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
1749static int
1750mac_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
1768static int
1769mac_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
1786static int
1787mac_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
1804static int
1805mac_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
1822static int
1823mac_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
1846static int
1847mac_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
1864static int
1865mac_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
1882static int
1883mac_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
1914static int
1915mac_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
1932static int
1933mac_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
1950static int
1951mac_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
1973static int
1974mac_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
1992static int
1993mac_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
2010static int
2011mac_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
2038static int
2039mac_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
2063static int
2064mac_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
2081static int
2082mac_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
2099static int
2100mac_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
2117static int
2118mac_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
2135static int
2136mac_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
2187static int
2188mac_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
2211static int
2212mac_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
2237static int
2238mac_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
2255static int
2256mac_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
2273static int
2274mac_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
2294static int
2295mac_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
2312static int
2313mac_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
2330static int
2331mac_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
2348static int
2349mac_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
2366static int
2367mac_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
2384static int
2385mac_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
2402static 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
2540MAC_POLICY_SET(&mac_mls_ops, mac_mls, "TrustedBSD MAC/MLS",
2541 MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_mls_slot);