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