1 /*-
2 * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
3 * Copyright (c) 2001-2005 McAfee, Inc.
4 * Copyright (c) 2006 SPARTA, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson for the TrustedBSD Project.
8 *
9 * This software was developed for the FreeBSD Project in part by McAfee
10 * Research, the Security Research Division of McAfee, Inc. under
11 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
12 * CHATS research program.
13 *
14 * This software was enhanced by SPARTA ISSO under SPAWAR contract
15 * N66001-04-C-6019 ("SEFOS").
16 *
17 * This software was developed at the University of Cambridge Computer
18 * Laboratory with support from a grant from Google, Inc.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 */
41
42 /*
43 * Developed by the TrustedBSD Project.
44 *
45 * MLS fixed label mandatory confidentiality policy.
46 */
47
48 #include <sys/types.h>
49 #include <sys/param.h>
50 #include <sys/acl.h>
51 #include <sys/conf.h>
52 #include <sys/extattr.h>
53 #include <sys/kernel.h>
54 #include <sys/ksem.h>
55 #include <sys/mman.h>
56 #include <sys/malloc.h>
57 #include <sys/mount.h>
58 #include <sys/proc.h>
59 #include <sys/sbuf.h>
60 #include <sys/systm.h>
61 #include <sys/sysproto.h>
62 #include <sys/sysent.h>
63 #include <sys/systm.h>
64 #include <sys/vnode.h>
65 #include <sys/file.h>
66 #include <sys/socket.h>
67 #include <sys/socketvar.h>
68 #include <sys/pipe.h>
69 #include <sys/sx.h>
70 #include <sys/sysctl.h>
71 #include <sys/msg.h>
72 #include <sys/sem.h>
73 #include <sys/shm.h>
74
75 #include <fs/devfs/devfs.h>
76
77 #include <net/bpfdesc.h>
78 #include <net/if.h>
79 #include <net/if_types.h>
80 #include <net/if_var.h>
81
82 #include <netinet/in.h>
83 #include <netinet/in_pcb.h>
84 #include <netinet/ip_var.h>
85
86 #include <vm/uma.h>
87 #include <vm/vm.h>
88
89 #include <security/mac/mac_policy.h>
90 #include <security/mac_mls/mac_mls.h>
91
92 static SYSCTL_NODE(_security_mac, OID_AUTO, mls,
93 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
94 "TrustedBSD mac_mls policy controls");
95
96 static int mls_label_size = sizeof(struct mac_mls);
97 SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
98 &mls_label_size, 0, "Size of struct mac_mls");
99
100 static int mls_enabled = 1;
101 SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RWTUN, &mls_enabled, 0,
102 "Enforce MAC/MLS policy");
103
104 static int destroyed_not_inited;
105 SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
106 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
107
108 static int ptys_equal = 0;
109 SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RWTUN,
110 &ptys_equal, 0, "Label pty devices as mls/equal on create");
111
112 static int revocation_enabled = 0;
113 SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RWTUN,
114 &revocation_enabled, 0, "Revoke access to objects on relabel");
115
116 static int max_compartments = MAC_MLS_MAX_COMPARTMENTS;
117 SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
118 &max_compartments, 0, "Maximum compartments the policy supports");
119
120 static int mls_slot;
121 #define SLOT(l) ((struct mac_mls *)mac_label_get((l), mls_slot))
122 #define SLOT_SET(l, val) mac_label_set((l), mls_slot, (uintptr_t)(val))
123
124 static uma_zone_t zone_mls;
125
126 static __inline int
mls_bit_set_empty(u_char * set)127 mls_bit_set_empty(u_char *set) {
128 int i;
129
130 for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
131 if (set[i] != 0)
132 return (0);
133 return (1);
134 }
135
136 static struct mac_mls *
mls_alloc(int flag)137 mls_alloc(int flag)
138 {
139
140 return (uma_zalloc(zone_mls, flag | M_ZERO));
141 }
142
143 static void
mls_free(struct mac_mls * mm)144 mls_free(struct mac_mls *mm)
145 {
146
147 if (mm != NULL)
148 uma_zfree(zone_mls, mm);
149 else
150 atomic_add_int(&destroyed_not_inited, 1);
151 }
152
153 static int
mls_atmostflags(struct mac_mls * mm,int flags)154 mls_atmostflags(struct mac_mls *mm, int flags)
155 {
156
157 if ((mm->mm_flags & flags) != mm->mm_flags)
158 return (EINVAL);
159 return (0);
160 }
161
162 static int
mls_dominate_element(struct mac_mls_element * a,struct mac_mls_element * b)163 mls_dominate_element(struct mac_mls_element *a, struct mac_mls_element *b)
164 {
165 int bit;
166
167 switch (a->mme_type) {
168 case MAC_MLS_TYPE_EQUAL:
169 case MAC_MLS_TYPE_HIGH:
170 return (1);
171
172 case MAC_MLS_TYPE_LOW:
173 switch (b->mme_type) {
174 case MAC_MLS_TYPE_LEVEL:
175 case MAC_MLS_TYPE_HIGH:
176 return (0);
177
178 case MAC_MLS_TYPE_EQUAL:
179 case MAC_MLS_TYPE_LOW:
180 return (1);
181
182 default:
183 panic("mls_dominate_element: b->mme_type invalid");
184 }
185
186 case MAC_MLS_TYPE_LEVEL:
187 switch (b->mme_type) {
188 case MAC_MLS_TYPE_EQUAL:
189 case MAC_MLS_TYPE_LOW:
190 return (1);
191
192 case MAC_MLS_TYPE_HIGH:
193 return (0);
194
195 case MAC_MLS_TYPE_LEVEL:
196 for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
197 if (!MAC_MLS_BIT_TEST(bit,
198 a->mme_compartments) &&
199 MAC_MLS_BIT_TEST(bit, b->mme_compartments))
200 return (0);
201 return (a->mme_level >= b->mme_level);
202
203 default:
204 panic("mls_dominate_element: b->mme_type invalid");
205 }
206
207 default:
208 panic("mls_dominate_element: a->mme_type invalid");
209 }
210
211 return (0);
212 }
213
214 static int
mls_range_in_range(struct mac_mls * rangea,struct mac_mls * rangeb)215 mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
216 {
217
218 return (mls_dominate_element(&rangeb->mm_rangehigh,
219 &rangea->mm_rangehigh) &&
220 mls_dominate_element(&rangea->mm_rangelow,
221 &rangeb->mm_rangelow));
222 }
223
224 static int
mls_effective_in_range(struct mac_mls * effective,struct mac_mls * range)225 mls_effective_in_range(struct mac_mls *effective, struct mac_mls *range)
226 {
227
228 KASSERT((effective->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
229 ("mls_effective_in_range: a not effective"));
230 KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
231 ("mls_effective_in_range: b not range"));
232
233 return (mls_dominate_element(&range->mm_rangehigh,
234 &effective->mm_effective) &&
235 mls_dominate_element(&effective->mm_effective,
236 &range->mm_rangelow));
237
238 return (1);
239 }
240
241 static int
mls_dominate_effective(struct mac_mls * a,struct mac_mls * b)242 mls_dominate_effective(struct mac_mls *a, struct mac_mls *b)
243 {
244 KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
245 ("mls_dominate_effective: a not effective"));
246 KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
247 ("mls_dominate_effective: b not effective"));
248
249 return (mls_dominate_element(&a->mm_effective, &b->mm_effective));
250 }
251
252 static int
mls_equal_element(struct mac_mls_element * a,struct mac_mls_element * b)253 mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
254 {
255
256 if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
257 b->mme_type == MAC_MLS_TYPE_EQUAL)
258 return (1);
259
260 return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
261 }
262
263 static int
mls_equal_effective(struct mac_mls * a,struct mac_mls * b)264 mls_equal_effective(struct mac_mls *a, struct mac_mls *b)
265 {
266
267 KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
268 ("mls_equal_effective: a not effective"));
269 KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
270 ("mls_equal_effective: b not effective"));
271
272 return (mls_equal_element(&a->mm_effective, &b->mm_effective));
273 }
274
275 static int
mls_contains_equal(struct mac_mls * mm)276 mls_contains_equal(struct mac_mls *mm)
277 {
278
279 if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
280 if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
281 return (1);
282
283 if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
284 if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
285 return (1);
286 if (mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
287 return (1);
288 }
289
290 return (0);
291 }
292
293 static int
mls_subject_privileged(struct mac_mls * mm)294 mls_subject_privileged(struct mac_mls *mm)
295 {
296
297 KASSERT((mm->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH,
298 ("mls_subject_privileged: subject doesn't have both labels"));
299
300 /* If the effective is EQUAL, it's ok. */
301 if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
302 return (0);
303
304 /* If either range endpoint is EQUAL, it's ok. */
305 if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
306 mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
307 return (0);
308
309 /* If the range is low-high, it's ok. */
310 if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
311 mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
312 return (0);
313
314 /* It's not ok. */
315 return (EPERM);
316 }
317
318 static int
mls_valid(struct mac_mls * mm)319 mls_valid(struct mac_mls *mm)
320 {
321
322 if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
323 switch (mm->mm_effective.mme_type) {
324 case MAC_MLS_TYPE_LEVEL:
325 break;
326
327 case MAC_MLS_TYPE_EQUAL:
328 case MAC_MLS_TYPE_HIGH:
329 case MAC_MLS_TYPE_LOW:
330 if (mm->mm_effective.mme_level != 0 ||
331 !MAC_MLS_BIT_SET_EMPTY(
332 mm->mm_effective.mme_compartments))
333 return (EINVAL);
334 break;
335
336 default:
337 return (EINVAL);
338 }
339 } else {
340 if (mm->mm_effective.mme_type != MAC_MLS_TYPE_UNDEF)
341 return (EINVAL);
342 }
343
344 if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
345 switch (mm->mm_rangelow.mme_type) {
346 case MAC_MLS_TYPE_LEVEL:
347 break;
348
349 case MAC_MLS_TYPE_EQUAL:
350 case MAC_MLS_TYPE_HIGH:
351 case MAC_MLS_TYPE_LOW:
352 if (mm->mm_rangelow.mme_level != 0 ||
353 !MAC_MLS_BIT_SET_EMPTY(
354 mm->mm_rangelow.mme_compartments))
355 return (EINVAL);
356 break;
357
358 default:
359 return (EINVAL);
360 }
361
362 switch (mm->mm_rangehigh.mme_type) {
363 case MAC_MLS_TYPE_LEVEL:
364 break;
365
366 case MAC_MLS_TYPE_EQUAL:
367 case MAC_MLS_TYPE_HIGH:
368 case MAC_MLS_TYPE_LOW:
369 if (mm->mm_rangehigh.mme_level != 0 ||
370 !MAC_MLS_BIT_SET_EMPTY(
371 mm->mm_rangehigh.mme_compartments))
372 return (EINVAL);
373 break;
374
375 default:
376 return (EINVAL);
377 }
378 if (!mls_dominate_element(&mm->mm_rangehigh,
379 &mm->mm_rangelow))
380 return (EINVAL);
381 } else {
382 if (mm->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
383 mm->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
384 return (EINVAL);
385 }
386
387 return (0);
388 }
389
390 static void
mls_set_range(struct mac_mls * mm,u_short typelow,u_short levellow,u_char * compartmentslow,u_short typehigh,u_short levelhigh,u_char * compartmentshigh)391 mls_set_range(struct mac_mls *mm, u_short typelow, u_short levellow,
392 u_char *compartmentslow, u_short typehigh, u_short levelhigh,
393 u_char *compartmentshigh)
394 {
395
396 mm->mm_rangelow.mme_type = typelow;
397 mm->mm_rangelow.mme_level = levellow;
398 if (compartmentslow != NULL)
399 memcpy(mm->mm_rangelow.mme_compartments, compartmentslow,
400 sizeof(mm->mm_rangelow.mme_compartments));
401 mm->mm_rangehigh.mme_type = typehigh;
402 mm->mm_rangehigh.mme_level = levelhigh;
403 if (compartmentshigh != NULL)
404 memcpy(mm->mm_rangehigh.mme_compartments, compartmentshigh,
405 sizeof(mm->mm_rangehigh.mme_compartments));
406 mm->mm_flags |= MAC_MLS_FLAG_RANGE;
407 }
408
409 static void
mls_set_effective(struct mac_mls * mm,u_short type,u_short level,u_char * compartments)410 mls_set_effective(struct mac_mls *mm, u_short type, u_short level,
411 u_char *compartments)
412 {
413
414 mm->mm_effective.mme_type = type;
415 mm->mm_effective.mme_level = level;
416 if (compartments != NULL)
417 memcpy(mm->mm_effective.mme_compartments, compartments,
418 sizeof(mm->mm_effective.mme_compartments));
419 mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
420 }
421
422 static void
mls_copy_range(struct mac_mls * labelfrom,struct mac_mls * labelto)423 mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
424 {
425
426 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
427 ("mls_copy_range: labelfrom not range"));
428
429 labelto->mm_rangelow = labelfrom->mm_rangelow;
430 labelto->mm_rangehigh = labelfrom->mm_rangehigh;
431 labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
432 }
433
434 static void
mls_copy_effective(struct mac_mls * labelfrom,struct mac_mls * labelto)435 mls_copy_effective(struct mac_mls *labelfrom, struct mac_mls *labelto)
436 {
437
438 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
439 ("mls_copy_effective: labelfrom not effective"));
440
441 labelto->mm_effective = labelfrom->mm_effective;
442 labelto->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
443 }
444
445 static void
mls_copy(struct mac_mls * source,struct mac_mls * dest)446 mls_copy(struct mac_mls *source, struct mac_mls *dest)
447 {
448
449 if (source->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
450 mls_copy_effective(source, dest);
451 if (source->mm_flags & MAC_MLS_FLAG_RANGE)
452 mls_copy_range(source, dest);
453 }
454
455 /*
456 * Policy module operations.
457 */
458 static void
mls_init(struct mac_policy_conf * conf)459 mls_init(struct mac_policy_conf *conf)
460 {
461
462 zone_mls = uma_zcreate("mac_mls", sizeof(struct mac_mls), NULL,
463 NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
464 }
465
466 /*
467 * Label operations.
468 */
469 static void
mls_init_label(struct label * label)470 mls_init_label(struct label *label)
471 {
472
473 SLOT_SET(label, mls_alloc(M_WAITOK));
474 }
475
476 static int
mls_init_label_waitcheck(struct label * label,int flag)477 mls_init_label_waitcheck(struct label *label, int flag)
478 {
479
480 SLOT_SET(label, mls_alloc(flag));
481 if (SLOT(label) == NULL)
482 return (ENOMEM);
483
484 return (0);
485 }
486
487 static void
mls_destroy_label(struct label * label)488 mls_destroy_label(struct label *label)
489 {
490
491 mls_free(SLOT(label));
492 SLOT_SET(label, NULL);
493 }
494
495 /*
496 * mls_element_to_string() accepts an sbuf and MLS element. It converts the
497 * MLS element to a string and stores the result in the sbuf; if there isn't
498 * space in the sbuf, -1 is returned.
499 */
500 static int
mls_element_to_string(struct sbuf * sb,struct mac_mls_element * element)501 mls_element_to_string(struct sbuf *sb, struct mac_mls_element *element)
502 {
503 int i, first;
504
505 switch (element->mme_type) {
506 case MAC_MLS_TYPE_HIGH:
507 return (sbuf_printf(sb, "high"));
508
509 case MAC_MLS_TYPE_LOW:
510 return (sbuf_printf(sb, "low"));
511
512 case MAC_MLS_TYPE_EQUAL:
513 return (sbuf_printf(sb, "equal"));
514
515 case MAC_MLS_TYPE_LEVEL:
516 if (sbuf_printf(sb, "%d", element->mme_level) == -1)
517 return (-1);
518
519 first = 1;
520 for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) {
521 if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) {
522 if (first) {
523 if (sbuf_putc(sb, ':') == -1)
524 return (-1);
525 if (sbuf_printf(sb, "%d", i) == -1)
526 return (-1);
527 first = 0;
528 } else {
529 if (sbuf_printf(sb, "+%d", i) == -1)
530 return (-1);
531 }
532 }
533 }
534 return (0);
535
536 default:
537 panic("mls_element_to_string: invalid type (%d)",
538 element->mme_type);
539 }
540 }
541
542 /*
543 * mls_to_string() converts an MLS label to a string, and places the results
544 * in the passed sbuf. It returns 0 on success, or EINVAL if there isn't
545 * room in the sbuf. Note: the sbuf will be modified even in a failure case,
546 * so the caller may need to revert the sbuf by restoring the offset if
547 * that's undesired.
548 */
549 static int
mls_to_string(struct sbuf * sb,struct mac_mls * mm)550 mls_to_string(struct sbuf *sb, struct mac_mls *mm)
551 {
552
553 if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
554 if (mls_element_to_string(sb, &mm->mm_effective) == -1)
555 return (EINVAL);
556 }
557
558 if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
559 if (sbuf_putc(sb, '(') == -1)
560 return (EINVAL);
561
562 if (mls_element_to_string(sb, &mm->mm_rangelow) == -1)
563 return (EINVAL);
564
565 if (sbuf_putc(sb, '-') == -1)
566 return (EINVAL);
567
568 if (mls_element_to_string(sb, &mm->mm_rangehigh) == -1)
569 return (EINVAL);
570
571 if (sbuf_putc(sb, ')') == -1)
572 return (EINVAL);
573 }
574
575 return (0);
576 }
577
578 static int
mls_externalize_label(struct label * label,char * element_name,struct sbuf * sb,int * claimed)579 mls_externalize_label(struct label *label, char *element_name,
580 struct sbuf *sb, int *claimed)
581 {
582 struct mac_mls *mm;
583
584 if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
585 return (0);
586
587 (*claimed)++;
588
589 mm = SLOT(label);
590
591 return (mls_to_string(sb, mm));
592 }
593
594 static int
mls_parse_element(struct mac_mls_element * element,char * string)595 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 || 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 || strcmp(string, "lo") == 0) {
604 element->mme_type = MAC_MLS_TYPE_LOW;
605 element->mme_level = MAC_MLS_TYPE_UNDEF;
606 } else if (strcmp(string, "equal") == 0 ||
607 strcmp(string, "eq") == 0) {
608 element->mme_type = MAC_MLS_TYPE_EQUAL;
609 element->mme_level = MAC_MLS_TYPE_UNDEF;
610 } else {
611 element->mme_type = MAC_MLS_TYPE_LEVEL;
612
613 /*
614 * Numeric level piece of the element.
615 */
616 level = strsep(&string, ":");
617 value = strtol(level, &end, 10);
618 if (end == level || *end != '\0')
619 return (EINVAL);
620 if (value < 0 || value > 65535)
621 return (EINVAL);
622 element->mme_level = value;
623
624 /*
625 * Optional compartment piece of the element. If none are
626 * included, we assume that the label has no compartments.
627 */
628 if (string == NULL)
629 return (0);
630 if (*string == '\0')
631 return (0);
632
633 while ((compartment = strsep(&string, "+")) != NULL) {
634 value = strtol(compartment, &end, 10);
635 if (compartment == end || *end != '\0')
636 return (EINVAL);
637 if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS)
638 return (EINVAL);
639 MAC_MLS_BIT_SET(value, element->mme_compartments);
640 }
641 }
642
643 return (0);
644 }
645
646 /*
647 * Note: destructively consumes the string, make a local copy before calling
648 * if that's a problem.
649 */
650 static int
mls_parse(struct mac_mls * mm,char * string)651 mls_parse(struct mac_mls *mm, char *string)
652 {
653 char *rangehigh, *rangelow, *effective;
654 int error;
655
656 effective = strsep(&string, "(");
657 if (*effective == '\0')
658 effective = NULL;
659
660 if (string != NULL) {
661 rangelow = strsep(&string, "-");
662 if (string == NULL)
663 return (EINVAL);
664 rangehigh = strsep(&string, ")");
665 if (string == NULL)
666 return (EINVAL);
667 if (*string != '\0')
668 return (EINVAL);
669 } else {
670 rangelow = NULL;
671 rangehigh = NULL;
672 }
673
674 KASSERT((rangelow != NULL && rangehigh != NULL) ||
675 (rangelow == NULL && rangehigh == NULL),
676 ("mls_parse: range mismatch"));
677
678 bzero(mm, sizeof(*mm));
679 if (effective != NULL) {
680 error = mls_parse_element(&mm->mm_effective, effective);
681 if (error)
682 return (error);
683 mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
684 }
685
686 if (rangelow != NULL) {
687 error = mls_parse_element(&mm->mm_rangelow, rangelow);
688 if (error)
689 return (error);
690 error = mls_parse_element(&mm->mm_rangehigh, rangehigh);
691 if (error)
692 return (error);
693 mm->mm_flags |= MAC_MLS_FLAG_RANGE;
694 }
695
696 error = mls_valid(mm);
697 if (error)
698 return (error);
699
700 return (0);
701 }
702
703 static int
mls_internalize_label(struct label * label,char * element_name,char * element_data,int * claimed)704 mls_internalize_label(struct label *label, char *element_name,
705 char *element_data, int *claimed)
706 {
707 struct mac_mls *mm, mm_temp;
708 int error;
709
710 if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
711 return (0);
712
713 (*claimed)++;
714
715 error = mls_parse(&mm_temp, element_data);
716 if (error)
717 return (error);
718
719 mm = SLOT(label);
720 *mm = mm_temp;
721
722 return (0);
723 }
724
725 static void
mls_copy_label(struct label * src,struct label * dest)726 mls_copy_label(struct label *src, struct label *dest)
727 {
728
729 *SLOT(dest) = *SLOT(src);
730 }
731
732 /*
733 * Object-specific entry point implementations are sorted alphabetically by
734 * object type name and then by operation.
735 */
736 static int
mls_bpfdesc_check_receive(struct bpf_d * d,struct label * dlabel,struct ifnet * ifp,struct label * ifplabel)737 mls_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel,
738 struct ifnet *ifp, struct label *ifplabel)
739 {
740 struct mac_mls *a, *b;
741
742 if (!mls_enabled)
743 return (0);
744
745 a = SLOT(dlabel);
746 b = SLOT(ifplabel);
747
748 if (mls_equal_effective(a, b))
749 return (0);
750 return (EACCES);
751 }
752
753 static void
mls_bpfdesc_create(struct ucred * cred,struct bpf_d * d,struct label * dlabel)754 mls_bpfdesc_create(struct ucred *cred, struct bpf_d *d, struct label *dlabel)
755 {
756 struct mac_mls *source, *dest;
757
758 source = SLOT(cred->cr_label);
759 dest = SLOT(dlabel);
760
761 mls_copy_effective(source, dest);
762 }
763
764 static void
mls_bpfdesc_create_mbuf(struct bpf_d * d,struct label * dlabel,struct mbuf * m,struct label * mlabel)765 mls_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel,
766 struct mbuf *m, struct label *mlabel)
767 {
768 struct mac_mls *source, *dest;
769
770 source = SLOT(dlabel);
771 dest = SLOT(mlabel);
772
773 mls_copy_effective(source, dest);
774 }
775
776 static void
mls_cred_associate_nfsd(struct ucred * cred)777 mls_cred_associate_nfsd(struct ucred *cred)
778 {
779 struct mac_mls *label;
780
781 label = SLOT(cred->cr_label);
782 mls_set_effective(label, MAC_MLS_TYPE_LOW, 0, NULL);
783 mls_set_range(label, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
784 NULL);
785 }
786
787 static int
mls_cred_check_relabel(struct ucred * cred,struct label * newlabel)788 mls_cred_check_relabel(struct ucred *cred, struct label *newlabel)
789 {
790 struct mac_mls *subj, *new;
791 int error;
792
793 subj = SLOT(cred->cr_label);
794 new = SLOT(newlabel);
795
796 /*
797 * If there is an MLS label update for the credential, it may be an
798 * update of effective, range, or both.
799 */
800 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
801 if (error)
802 return (error);
803
804 /*
805 * If the MLS label is to be changed, authorize as appropriate.
806 */
807 if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
808 /*
809 * If the change request modifies both the MLS label
810 * effective and range, check that the new effective will be
811 * in the new range.
812 */
813 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
814 MAC_MLS_FLAGS_BOTH && !mls_effective_in_range(new, new))
815 return (EINVAL);
816
817 /*
818 * To change the MLS effective label on a credential, the new
819 * effective label must be in the current range.
820 */
821 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE &&
822 !mls_effective_in_range(new, subj))
823 return (EPERM);
824
825 /*
826 * To change the MLS range label on a credential, the new
827 * range must be in the current range.
828 */
829 if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
830 !mls_range_in_range(new, subj))
831 return (EPERM);
832
833 /*
834 * To have EQUAL in any component of the new credential MLS
835 * label, the subject must already have EQUAL in their label.
836 */
837 if (mls_contains_equal(new)) {
838 error = mls_subject_privileged(subj);
839 if (error)
840 return (error);
841 }
842 }
843
844 return (0);
845 }
846
847 static int
mls_cred_check_visible(struct ucred * cr1,struct ucred * cr2)848 mls_cred_check_visible(struct ucred *cr1, struct ucred *cr2)
849 {
850 struct mac_mls *subj, *obj;
851
852 if (!mls_enabled)
853 return (0);
854
855 subj = SLOT(cr1->cr_label);
856 obj = SLOT(cr2->cr_label);
857
858 /* XXX: range */
859 if (!mls_dominate_effective(subj, obj))
860 return (ESRCH);
861
862 return (0);
863 }
864
865 static void
mls_cred_create_init(struct ucred * cred)866 mls_cred_create_init(struct ucred *cred)
867 {
868 struct mac_mls *dest;
869
870 dest = SLOT(cred->cr_label);
871
872 mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL);
873 mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
874 NULL);
875 }
876
877 static void
mls_cred_create_swapper(struct ucred * cred)878 mls_cred_create_swapper(struct ucred *cred)
879 {
880 struct mac_mls *dest;
881
882 dest = SLOT(cred->cr_label);
883
884 mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
885 mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
886 NULL);
887 }
888
889 static void
mls_cred_relabel(struct ucred * cred,struct label * newlabel)890 mls_cred_relabel(struct ucred *cred, struct label *newlabel)
891 {
892 struct mac_mls *source, *dest;
893
894 source = SLOT(newlabel);
895 dest = SLOT(cred->cr_label);
896
897 mls_copy(source, dest);
898 }
899
900 static void
mls_devfs_create_device(struct ucred * cred,struct mount * mp,struct cdev * dev,struct devfs_dirent * de,struct label * delabel)901 mls_devfs_create_device(struct ucred *cred, struct mount *mp,
902 struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
903 {
904 struct mac_mls *mm;
905 const char *dn;
906 int mls_type;
907
908 mm = SLOT(delabel);
909 dn = devtoname(dev);
910 if (strcmp(dn, "null") == 0 ||
911 strcmp(dn, "zero") == 0 ||
912 strcmp(dn, "random") == 0 ||
913 strncmp(dn, "fd/", strlen("fd/")) == 0)
914 mls_type = MAC_MLS_TYPE_EQUAL;
915 else if (strcmp(dn, "kmem") == 0 ||
916 strcmp(dn, "mem") == 0)
917 mls_type = MAC_MLS_TYPE_HIGH;
918 else if (ptys_equal &&
919 (strncmp(dn, "ttyp", strlen("ttyp")) == 0 ||
920 strncmp(dn, "pts/", strlen("pts/")) == 0 ||
921 strncmp(dn, "ptyp", strlen("ptyp")) == 0))
922 mls_type = MAC_MLS_TYPE_EQUAL;
923 else
924 mls_type = MAC_MLS_TYPE_LOW;
925 mls_set_effective(mm, mls_type, 0, NULL);
926 }
927
928 static void
mls_devfs_create_directory(struct mount * mp,char * dirname,int dirnamelen,struct devfs_dirent * de,struct label * delabel)929 mls_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
930 struct devfs_dirent *de, struct label *delabel)
931 {
932 struct mac_mls *mm;
933
934 mm = SLOT(delabel);
935 mls_set_effective(mm, MAC_MLS_TYPE_LOW, 0, NULL);
936 }
937
938 static void
mls_devfs_create_symlink(struct ucred * cred,struct mount * mp,struct devfs_dirent * dd,struct label * ddlabel,struct devfs_dirent * de,struct label * delabel)939 mls_devfs_create_symlink(struct ucred *cred, struct mount *mp,
940 struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
941 struct label *delabel)
942 {
943 struct mac_mls *source, *dest;
944
945 source = SLOT(cred->cr_label);
946 dest = SLOT(delabel);
947
948 mls_copy_effective(source, dest);
949 }
950
951 static void
mls_devfs_update(struct mount * mp,struct devfs_dirent * de,struct label * delabel,struct vnode * vp,struct label * vplabel)952 mls_devfs_update(struct mount *mp, struct devfs_dirent *de,
953 struct label *delabel, struct vnode *vp, struct label *vplabel)
954 {
955 struct mac_mls *source, *dest;
956
957 source = SLOT(vplabel);
958 dest = SLOT(delabel);
959
960 mls_copy_effective(source, dest);
961 }
962
963 static void
mls_devfs_vnode_associate(struct mount * mp,struct label * mplabel,struct devfs_dirent * de,struct label * delabel,struct vnode * vp,struct label * vplabel)964 mls_devfs_vnode_associate(struct mount *mp, struct label *mplabel,
965 struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
966 struct label *vplabel)
967 {
968 struct mac_mls *source, *dest;
969
970 source = SLOT(delabel);
971 dest = SLOT(vplabel);
972
973 mls_copy_effective(source, dest);
974 }
975
976 static int
mls_ifnet_check_relabel(struct ucred * cred,struct ifnet * ifp,struct label * ifplabel,struct label * newlabel)977 mls_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
978 struct label *ifplabel, struct label *newlabel)
979 {
980 struct mac_mls *subj, *new;
981 int error;
982
983 subj = SLOT(cred->cr_label);
984 new = SLOT(newlabel);
985
986 /*
987 * If there is an MLS label update for the interface, it may be an
988 * update of effective, range, or both.
989 */
990 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
991 if (error)
992 return (error);
993
994 /*
995 * Relabeling network interfaces requires MLS privilege.
996 */
997 return (mls_subject_privileged(subj));
998 }
999
1000 static int
mls_ifnet_check_transmit(struct ifnet * ifp,struct label * ifplabel,struct mbuf * m,struct label * mlabel)1001 mls_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
1002 struct mbuf *m, struct label *mlabel)
1003 {
1004 struct mac_mls *p, *i;
1005
1006 if (!mls_enabled)
1007 return (0);
1008
1009 p = SLOT(mlabel);
1010 i = SLOT(ifplabel);
1011
1012 return (mls_effective_in_range(p, i) ? 0 : EACCES);
1013 }
1014
1015 static void
mls_ifnet_create(struct ifnet * ifp,struct label * ifplabel)1016 mls_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
1017 {
1018 struct mac_mls *dest;
1019 int type;
1020
1021 dest = SLOT(ifplabel);
1022
1023 if (if_gettype(ifp) == IFT_LOOP)
1024 type = MAC_MLS_TYPE_EQUAL;
1025 else
1026 type = MAC_MLS_TYPE_LOW;
1027
1028 mls_set_effective(dest, type, 0, NULL);
1029 mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1030 }
1031
1032 static void
mls_ifnet_create_mbuf(struct ifnet * ifp,struct label * ifplabel,struct mbuf * m,struct label * mlabel)1033 mls_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1034 struct mbuf *m, struct label *mlabel)
1035 {
1036 struct mac_mls *source, *dest;
1037
1038 source = SLOT(ifplabel);
1039 dest = SLOT(mlabel);
1040
1041 mls_copy_effective(source, dest);
1042 }
1043
1044 static void
mls_ifnet_relabel(struct ucred * cred,struct ifnet * ifp,struct label * ifplabel,struct label * newlabel)1045 mls_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1046 struct label *ifplabel, struct label *newlabel)
1047 {
1048 struct mac_mls *source, *dest;
1049
1050 source = SLOT(newlabel);
1051 dest = SLOT(ifplabel);
1052
1053 mls_copy(source, dest);
1054 }
1055
1056 static int
mls_inpcb_check_deliver(struct inpcb * inp,struct label * inplabel,struct mbuf * m,struct label * mlabel)1057 mls_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1058 struct mbuf *m, struct label *mlabel)
1059 {
1060 struct mac_mls *p, *i;
1061
1062 if (!mls_enabled)
1063 return (0);
1064
1065 p = SLOT(mlabel);
1066 i = SLOT(inplabel);
1067
1068 return (mls_equal_effective(p, i) ? 0 : EACCES);
1069 }
1070
1071 static int
mls_inpcb_check_visible(struct ucred * cred,struct inpcb * inp,struct label * inplabel)1072 mls_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
1073 struct label *inplabel)
1074 {
1075 struct mac_mls *subj, *obj;
1076
1077 if (!mls_enabled)
1078 return (0);
1079
1080 subj = SLOT(cred->cr_label);
1081 obj = SLOT(inplabel);
1082
1083 if (!mls_dominate_effective(subj, obj))
1084 return (ENOENT);
1085
1086 return (0);
1087 }
1088
1089 static void
mls_inpcb_create(struct socket * so,struct label * solabel,struct inpcb * inp,struct label * inplabel)1090 mls_inpcb_create(struct socket *so, struct label *solabel, struct inpcb *inp,
1091 struct label *inplabel)
1092 {
1093 struct mac_mls *source, *dest;
1094
1095 source = SLOT(solabel);
1096 dest = SLOT(inplabel);
1097
1098 mls_copy_effective(source, dest);
1099 }
1100
1101 static void
mls_inpcb_create_mbuf(struct inpcb * inp,struct label * inplabel,struct mbuf * m,struct label * mlabel)1102 mls_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1103 struct mbuf *m, struct label *mlabel)
1104 {
1105 struct mac_mls *source, *dest;
1106
1107 source = SLOT(inplabel);
1108 dest = SLOT(mlabel);
1109
1110 mls_copy_effective(source, dest);
1111 }
1112
1113 static void
mls_inpcb_sosetlabel(struct socket * so,struct label * solabel,struct inpcb * inp,struct label * inplabel)1114 mls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1115 struct inpcb *inp, struct label *inplabel)
1116 {
1117 struct mac_mls *source, *dest;
1118
1119 SOCK_LOCK_ASSERT(so);
1120
1121 source = SLOT(solabel);
1122 dest = SLOT(inplabel);
1123
1124 mls_copy(source, dest);
1125 }
1126
1127 static void
mls_ip6q_create(struct mbuf * m,struct label * mlabel,struct ip6q * q6,struct label * q6label)1128 mls_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1129 struct label *q6label)
1130 {
1131 struct mac_mls *source, *dest;
1132
1133 source = SLOT(mlabel);
1134 dest = SLOT(q6label);
1135
1136 mls_copy_effective(source, dest);
1137 }
1138
1139 static int
mls_ip6q_match(struct mbuf * m,struct label * mlabel,struct ip6q * q6,struct label * q6label)1140 mls_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1141 struct label *q6label)
1142 {
1143 struct mac_mls *a, *b;
1144
1145 a = SLOT(q6label);
1146 b = SLOT(mlabel);
1147
1148 return (mls_equal_effective(a, b));
1149 }
1150
1151 static void
mls_ip6q_reassemble(struct ip6q * q6,struct label * q6label,struct mbuf * m,struct label * mlabel)1152 mls_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1153 struct label *mlabel)
1154 {
1155 struct mac_mls *source, *dest;
1156
1157 source = SLOT(q6label);
1158 dest = SLOT(mlabel);
1159
1160 /* Just use the head, since we require them all to match. */
1161 mls_copy_effective(source, dest);
1162 }
1163
1164 static void
mls_ip6q_update(struct mbuf * m,struct label * mlabel,struct ip6q * q6,struct label * q6label)1165 mls_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1166 struct label *q6label)
1167 {
1168
1169 /* NOOP: we only accept matching labels, so no need to update */
1170 }
1171
1172 static void
mls_ipq_create(struct mbuf * m,struct label * mlabel,struct ipq * q,struct label * qlabel)1173 mls_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1174 struct label *qlabel)
1175 {
1176 struct mac_mls *source, *dest;
1177
1178 source = SLOT(mlabel);
1179 dest = SLOT(qlabel);
1180
1181 mls_copy_effective(source, dest);
1182 }
1183
1184 static int
mls_ipq_match(struct mbuf * m,struct label * mlabel,struct ipq * q,struct label * qlabel)1185 mls_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1186 struct label *qlabel)
1187 {
1188 struct mac_mls *a, *b;
1189
1190 a = SLOT(qlabel);
1191 b = SLOT(mlabel);
1192
1193 return (mls_equal_effective(a, b));
1194 }
1195
1196 static void
mls_ipq_reassemble(struct ipq * q,struct label * qlabel,struct mbuf * m,struct label * mlabel)1197 mls_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1198 struct label *mlabel)
1199 {
1200 struct mac_mls *source, *dest;
1201
1202 source = SLOT(qlabel);
1203 dest = SLOT(mlabel);
1204
1205 /* Just use the head, since we require them all to match. */
1206 mls_copy_effective(source, dest);
1207 }
1208
1209 static void
mls_ipq_update(struct mbuf * m,struct label * mlabel,struct ipq * q,struct label * qlabel)1210 mls_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1211 struct label *qlabel)
1212 {
1213
1214 /* NOOP: we only accept matching labels, so no need to update */
1215 }
1216
1217 static int
mls_mount_check_stat(struct ucred * cred,struct mount * mp,struct label * mntlabel)1218 mls_mount_check_stat(struct ucred *cred, struct mount *mp,
1219 struct label *mntlabel)
1220 {
1221 struct mac_mls *subj, *obj;
1222
1223 if (!mls_enabled)
1224 return (0);
1225
1226 subj = SLOT(cred->cr_label);
1227 obj = SLOT(mntlabel);
1228
1229 if (!mls_dominate_effective(subj, obj))
1230 return (EACCES);
1231
1232 return (0);
1233 }
1234
1235 static void
mls_mount_create(struct ucred * cred,struct mount * mp,struct label * mplabel)1236 mls_mount_create(struct ucred *cred, struct mount *mp, struct label *mplabel)
1237 {
1238 struct mac_mls *source, *dest;
1239
1240 source = SLOT(cred->cr_label);
1241 dest = SLOT(mplabel);
1242
1243 mls_copy_effective(source, dest);
1244 }
1245
1246 static void
mls_netinet_arp_send(struct ifnet * ifp,struct label * ifplabel,struct mbuf * m,struct label * mlabel)1247 mls_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1248 struct mbuf *m, struct label *mlabel)
1249 {
1250 struct mac_mls *dest;
1251
1252 dest = SLOT(mlabel);
1253
1254 mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1255 }
1256
1257 static void
mls_netinet_firewall_reply(struct mbuf * mrecv,struct label * mrecvlabel,struct mbuf * msend,struct label * msendlabel)1258 mls_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1259 struct mbuf *msend, struct label *msendlabel)
1260 {
1261 struct mac_mls *source, *dest;
1262
1263 source = SLOT(mrecvlabel);
1264 dest = SLOT(msendlabel);
1265
1266 mls_copy_effective(source, dest);
1267 }
1268
1269 static void
mls_netinet_firewall_send(struct mbuf * m,struct label * mlabel)1270 mls_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1271 {
1272 struct mac_mls *dest;
1273
1274 dest = SLOT(mlabel);
1275
1276 /* XXX: where is the label for the firewall really coming from? */
1277 mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1278 }
1279
1280 static void
mls_netinet_fragment(struct mbuf * m,struct label * mlabel,struct mbuf * frag,struct label * fraglabel)1281 mls_netinet_fragment(struct mbuf *m, struct label *mlabel, struct mbuf *frag,
1282 struct label *fraglabel)
1283 {
1284 struct mac_mls *source, *dest;
1285
1286 source = SLOT(mlabel);
1287 dest = SLOT(fraglabel);
1288
1289 mls_copy_effective(source, dest);
1290 }
1291
1292 static void
mls_netinet_icmp_reply(struct mbuf * mrecv,struct label * mrecvlabel,struct mbuf * msend,struct label * msendlabel)1293 mls_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1294 struct mbuf *msend, struct label *msendlabel)
1295 {
1296 struct mac_mls *source, *dest;
1297
1298 source = SLOT(mrecvlabel);
1299 dest = SLOT(msendlabel);
1300
1301 mls_copy_effective(source, dest);
1302 }
1303
1304 static void
mls_netinet_igmp_send(struct ifnet * ifp,struct label * ifplabel,struct mbuf * m,struct label * mlabel)1305 mls_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1306 struct mbuf *m, struct label *mlabel)
1307 {
1308 struct mac_mls *dest;
1309
1310 dest = SLOT(mlabel);
1311
1312 mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1313 }
1314
1315 static void
mls_netinet6_nd6_send(struct ifnet * ifp,struct label * ifplabel,struct mbuf * m,struct label * mlabel)1316 mls_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1317 struct mbuf *m, struct label *mlabel)
1318 {
1319 struct mac_mls *dest;
1320
1321 dest = SLOT(mlabel);
1322
1323 mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1324 }
1325
1326 static int
mls_pipe_check_ioctl(struct ucred * cred,struct pipepair * pp,struct label * pplabel,unsigned long cmd,void * data)1327 mls_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1328 struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1329 {
1330
1331 if (!mls_enabled)
1332 return (0);
1333
1334 /* XXX: This will be implemented soon... */
1335
1336 return (0);
1337 }
1338
1339 static int
mls_pipe_check_poll(struct ucred * cred,struct pipepair * pp,struct label * pplabel)1340 mls_pipe_check_poll(struct ucred *cred, struct pipepair *pp,
1341 struct label *pplabel)
1342 {
1343 struct mac_mls *subj, *obj;
1344
1345 if (!mls_enabled)
1346 return (0);
1347
1348 subj = SLOT(cred->cr_label);
1349 obj = SLOT(pplabel);
1350
1351 if (!mls_dominate_effective(subj, obj))
1352 return (EACCES);
1353
1354 return (0);
1355 }
1356
1357 static int
mls_pipe_check_read(struct ucred * cred,struct pipepair * pp,struct label * pplabel)1358 mls_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1359 struct label *pplabel)
1360 {
1361 struct mac_mls *subj, *obj;
1362
1363 if (!mls_enabled)
1364 return (0);
1365
1366 subj = SLOT(cred->cr_label);
1367 obj = SLOT(pplabel);
1368
1369 if (!mls_dominate_effective(subj, obj))
1370 return (EACCES);
1371
1372 return (0);
1373 }
1374
1375 static int
mls_pipe_check_relabel(struct ucred * cred,struct pipepair * pp,struct label * pplabel,struct label * newlabel)1376 mls_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1377 struct label *pplabel, struct label *newlabel)
1378 {
1379 struct mac_mls *subj, *obj, *new;
1380 int error;
1381
1382 new = SLOT(newlabel);
1383 subj = SLOT(cred->cr_label);
1384 obj = SLOT(pplabel);
1385
1386 /*
1387 * If there is an MLS label update for a pipe, it must be a effective
1388 * update.
1389 */
1390 error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1391 if (error)
1392 return (error);
1393
1394 /*
1395 * To perform a relabel of a pipe (MLS label or not), MLS must
1396 * authorize the relabel.
1397 */
1398 if (!mls_effective_in_range(obj, subj))
1399 return (EPERM);
1400
1401 /*
1402 * If the MLS label is to be changed, authorize as appropriate.
1403 */
1404 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1405 /*
1406 * To change the MLS label on a pipe, the new pipe label must
1407 * be in the subject range.
1408 */
1409 if (!mls_effective_in_range(new, subj))
1410 return (EPERM);
1411
1412 /*
1413 * To change the MLS label on a pipe to be EQUAL, the subject
1414 * must have appropriate privilege.
1415 */
1416 if (mls_contains_equal(new)) {
1417 error = mls_subject_privileged(subj);
1418 if (error)
1419 return (error);
1420 }
1421 }
1422
1423 return (0);
1424 }
1425
1426 static int
mls_pipe_check_stat(struct ucred * cred,struct pipepair * pp,struct label * pplabel)1427 mls_pipe_check_stat(struct ucred *cred, struct pipepair *pp,
1428 struct label *pplabel)
1429 {
1430 struct mac_mls *subj, *obj;
1431
1432 if (!mls_enabled)
1433 return (0);
1434
1435 subj = SLOT(cred->cr_label);
1436 obj = SLOT(pplabel);
1437
1438 if (!mls_dominate_effective(subj, obj))
1439 return (EACCES);
1440
1441 return (0);
1442 }
1443
1444 static int
mls_pipe_check_write(struct ucred * cred,struct pipepair * pp,struct label * pplabel)1445 mls_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1446 struct label *pplabel)
1447 {
1448 struct mac_mls *subj, *obj;
1449
1450 if (!mls_enabled)
1451 return (0);
1452
1453 subj = SLOT(cred->cr_label);
1454 obj = SLOT(pplabel);
1455
1456 if (!mls_dominate_effective(obj, subj))
1457 return (EACCES);
1458
1459 return (0);
1460 }
1461
1462 static void
mls_pipe_create(struct ucred * cred,struct pipepair * pp,struct label * pplabel)1463 mls_pipe_create(struct ucred *cred, struct pipepair *pp,
1464 struct label *pplabel)
1465 {
1466 struct mac_mls *source, *dest;
1467
1468 source = SLOT(cred->cr_label);
1469 dest = SLOT(pplabel);
1470
1471 mls_copy_effective(source, dest);
1472 }
1473
1474 static void
mls_pipe_relabel(struct ucred * cred,struct pipepair * pp,struct label * pplabel,struct label * newlabel)1475 mls_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1476 struct label *pplabel, struct label *newlabel)
1477 {
1478 struct mac_mls *source, *dest;
1479
1480 source = SLOT(newlabel);
1481 dest = SLOT(pplabel);
1482
1483 mls_copy(source, dest);
1484 }
1485
1486 static int
mls_posixsem_check_openunlink(struct ucred * cred,struct ksem * ks,struct label * kslabel)1487 mls_posixsem_check_openunlink(struct ucred *cred, struct ksem *ks,
1488 struct label *kslabel)
1489 {
1490 struct mac_mls *subj, *obj;
1491
1492 if (!mls_enabled)
1493 return (0);
1494
1495 subj = SLOT(cred->cr_label);
1496 obj = SLOT(kslabel);
1497
1498 if (!mls_dominate_effective(obj, subj))
1499 return (EACCES);
1500
1501 return (0);
1502 }
1503
1504 static int
mls_posixsem_check_rdonly(struct ucred * active_cred,struct ucred * file_cred,struct ksem * ks,struct label * kslabel)1505 mls_posixsem_check_rdonly(struct ucred *active_cred, struct ucred *file_cred,
1506 struct ksem *ks, struct label *kslabel)
1507 {
1508 struct mac_mls *subj, *obj;
1509
1510 if (!mls_enabled)
1511 return (0);
1512
1513 subj = SLOT(active_cred->cr_label);
1514 obj = SLOT(kslabel);
1515
1516 if (!mls_dominate_effective(subj, obj))
1517 return (EACCES);
1518
1519 return (0);
1520 }
1521
1522 static int
mls_posixsem_check_setmode(struct ucred * cred,struct ksem * ks,struct label * shmlabel,mode_t mode)1523 mls_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
1524 struct label *shmlabel, mode_t mode)
1525 {
1526 struct mac_mls *subj, *obj;
1527
1528 if (!mls_enabled)
1529 return (0);
1530
1531 subj = SLOT(cred->cr_label);
1532 obj = SLOT(shmlabel);
1533
1534 if (!mls_dominate_effective(obj, subj))
1535 return (EACCES);
1536
1537 return (0);
1538 }
1539
1540 static int
mls_posixsem_check_setowner(struct ucred * cred,struct ksem * ks,struct label * shmlabel,uid_t uid,gid_t gid)1541 mls_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
1542 struct label *shmlabel, uid_t uid, gid_t gid)
1543 {
1544 struct mac_mls *subj, *obj;
1545
1546 if (!mls_enabled)
1547 return (0);
1548
1549 subj = SLOT(cred->cr_label);
1550 obj = SLOT(shmlabel);
1551
1552 if (!mls_dominate_effective(obj, subj))
1553 return (EACCES);
1554
1555 return (0);
1556 }
1557
1558 static int
mls_posixsem_check_write(struct ucred * active_cred,struct ucred * file_cred,struct ksem * ks,struct label * kslabel)1559 mls_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred,
1560 struct ksem *ks, struct label *kslabel)
1561 {
1562 struct mac_mls *subj, *obj;
1563
1564 if (!mls_enabled)
1565 return (0);
1566
1567 subj = SLOT(active_cred->cr_label);
1568 obj = SLOT(kslabel);
1569
1570 if (!mls_dominate_effective(obj, subj))
1571 return (EACCES);
1572
1573 return (0);
1574 }
1575
1576 static void
mls_posixsem_create(struct ucred * cred,struct ksem * ks,struct label * kslabel)1577 mls_posixsem_create(struct ucred *cred, struct ksem *ks,
1578 struct label *kslabel)
1579 {
1580 struct mac_mls *source, *dest;
1581
1582 source = SLOT(cred->cr_label);
1583 dest = SLOT(kslabel);
1584
1585 mls_copy_effective(source, dest);
1586 }
1587
1588 static int
mls_posixshm_check_mmap(struct ucred * cred,struct shmfd * shmfd,struct label * shmlabel,int prot,int flags)1589 mls_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
1590 struct label *shmlabel, int prot, int flags)
1591 {
1592 struct mac_mls *subj, *obj;
1593
1594 if (!mls_enabled)
1595 return (0);
1596
1597 subj = SLOT(cred->cr_label);
1598 obj = SLOT(shmlabel);
1599
1600 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
1601 if (!mls_dominate_effective(subj, obj))
1602 return (EACCES);
1603 }
1604 if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
1605 if (!mls_dominate_effective(obj, subj))
1606 return (EACCES);
1607 }
1608
1609 return (0);
1610 }
1611
1612 static int
mls_posixshm_check_open(struct ucred * cred,struct shmfd * shmfd,struct label * shmlabel,accmode_t accmode)1613 mls_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
1614 struct label *shmlabel, accmode_t accmode)
1615 {
1616 struct mac_mls *subj, *obj;
1617
1618 if (!mls_enabled)
1619 return (0);
1620
1621 subj = SLOT(cred->cr_label);
1622 obj = SLOT(shmlabel);
1623
1624 if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
1625 if (!mls_dominate_effective(subj, obj))
1626 return (EACCES);
1627 }
1628 if (accmode & VMODIFY_PERMS) {
1629 if (!mls_dominate_effective(obj, subj))
1630 return (EACCES);
1631 }
1632
1633 return (0);
1634 }
1635
1636 static int
mls_posixshm_check_read(struct ucred * active_cred,struct ucred * file_cred,struct shmfd * shm,struct label * shmlabel)1637 mls_posixshm_check_read(struct ucred *active_cred, struct ucred *file_cred,
1638 struct shmfd *shm, struct label *shmlabel)
1639 {
1640 struct mac_mls *subj, *obj;
1641
1642 if (!mls_enabled || !revocation_enabled)
1643 return (0);
1644
1645 subj = SLOT(active_cred->cr_label);
1646 obj = SLOT(shmlabel);
1647
1648 if (!mls_dominate_effective(subj, obj))
1649 return (EACCES);
1650
1651 return (0);
1652 }
1653
1654 static int
mls_posixshm_check_setmode(struct ucred * cred,struct shmfd * shmfd,struct label * shmlabel,mode_t mode)1655 mls_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
1656 struct label *shmlabel, mode_t mode)
1657 {
1658 struct mac_mls *subj, *obj;
1659
1660 if (!mls_enabled)
1661 return (0);
1662
1663 subj = SLOT(cred->cr_label);
1664 obj = SLOT(shmlabel);
1665
1666 if (!mls_dominate_effective(obj, subj))
1667 return (EACCES);
1668
1669 return (0);
1670 }
1671
1672 static int
mls_posixshm_check_setowner(struct ucred * cred,struct shmfd * shmfd,struct label * shmlabel,uid_t uid,gid_t gid)1673 mls_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
1674 struct label *shmlabel, uid_t uid, gid_t gid)
1675 {
1676 struct mac_mls *subj, *obj;
1677
1678 if (!mls_enabled)
1679 return (0);
1680
1681 subj = SLOT(cred->cr_label);
1682 obj = SLOT(shmlabel);
1683
1684 if (!mls_dominate_effective(obj, subj))
1685 return (EACCES);
1686
1687 return (0);
1688 }
1689
1690 static int
mls_posixshm_check_stat(struct ucred * active_cred,struct ucred * file_cred,struct shmfd * shmfd,struct label * shmlabel)1691 mls_posixshm_check_stat(struct ucred *active_cred, struct ucred *file_cred,
1692 struct shmfd *shmfd, struct label *shmlabel)
1693 {
1694 struct mac_mls *subj, *obj;
1695
1696 if (!mls_enabled)
1697 return (0);
1698
1699 subj = SLOT(active_cred->cr_label);
1700 obj = SLOT(shmlabel);
1701
1702 if (!mls_dominate_effective(subj, obj))
1703 return (EACCES);
1704
1705 return (0);
1706 }
1707
1708 static int
mls_posixshm_check_truncate(struct ucred * active_cred,struct ucred * file_cred,struct shmfd * shmfd,struct label * shmlabel)1709 mls_posixshm_check_truncate(struct ucred *active_cred,
1710 struct ucred *file_cred, struct shmfd *shmfd, struct label *shmlabel)
1711 {
1712 struct mac_mls *subj, *obj;
1713
1714 if (!mls_enabled)
1715 return (0);
1716
1717 subj = SLOT(active_cred->cr_label);
1718 obj = SLOT(shmlabel);
1719
1720 if (!mls_dominate_effective(obj, subj))
1721 return (EACCES);
1722
1723 return (0);
1724 }
1725
1726 static int
mls_posixshm_check_unlink(struct ucred * cred,struct shmfd * shmfd,struct label * shmlabel)1727 mls_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
1728 struct label *shmlabel)
1729 {
1730 struct mac_mls *subj, *obj;
1731
1732 if (!mls_enabled)
1733 return (0);
1734
1735 subj = SLOT(cred->cr_label);
1736 obj = SLOT(shmlabel);
1737
1738 if (!mls_dominate_effective(obj, subj))
1739 return (EACCES);
1740
1741 return (0);
1742 }
1743
1744 static int
mls_posixshm_check_write(struct ucred * active_cred,struct ucred * file_cred,struct shmfd * shm,struct label * shmlabel)1745 mls_posixshm_check_write(struct ucred *active_cred, struct ucred *file_cred,
1746 struct shmfd *shm, struct label *shmlabel)
1747 {
1748 struct mac_mls *subj, *obj;
1749
1750 if (!mls_enabled || !revocation_enabled)
1751 return (0);
1752
1753 subj = SLOT(active_cred->cr_label);
1754 obj = SLOT(shmlabel);
1755
1756 if (!mls_dominate_effective(subj, obj))
1757 return (EACCES);
1758
1759 return (0);
1760 }
1761
1762 static void
mls_posixshm_create(struct ucred * cred,struct shmfd * shmfd,struct label * shmlabel)1763 mls_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
1764 struct label *shmlabel)
1765 {
1766 struct mac_mls *source, *dest;
1767
1768 source = SLOT(cred->cr_label);
1769 dest = SLOT(shmlabel);
1770
1771 mls_copy_effective(source, dest);
1772 }
1773
1774 static int
mls_proc_check_debug(struct ucred * cred,struct proc * p)1775 mls_proc_check_debug(struct ucred *cred, struct proc *p)
1776 {
1777 struct mac_mls *subj, *obj;
1778
1779 if (!mls_enabled)
1780 return (0);
1781
1782 subj = SLOT(cred->cr_label);
1783 obj = SLOT(p->p_ucred->cr_label);
1784
1785 /* XXX: range checks */
1786 if (!mls_dominate_effective(subj, obj))
1787 return (ESRCH);
1788 if (!mls_dominate_effective(obj, subj))
1789 return (EACCES);
1790
1791 return (0);
1792 }
1793
1794 static int
mls_proc_check_sched(struct ucred * cred,struct proc * p)1795 mls_proc_check_sched(struct ucred *cred, struct proc *p)
1796 {
1797 struct mac_mls *subj, *obj;
1798
1799 if (!mls_enabled)
1800 return (0);
1801
1802 subj = SLOT(cred->cr_label);
1803 obj = SLOT(p->p_ucred->cr_label);
1804
1805 /* XXX: range checks */
1806 if (!mls_dominate_effective(subj, obj))
1807 return (ESRCH);
1808 if (!mls_dominate_effective(obj, subj))
1809 return (EACCES);
1810
1811 return (0);
1812 }
1813
1814 static int
mls_proc_check_signal(struct ucred * cred,struct proc * p,int signum)1815 mls_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1816 {
1817 struct mac_mls *subj, *obj;
1818
1819 if (!mls_enabled)
1820 return (0);
1821
1822 subj = SLOT(cred->cr_label);
1823 obj = SLOT(p->p_ucred->cr_label);
1824
1825 /* XXX: range checks */
1826 if (!mls_dominate_effective(subj, obj))
1827 return (ESRCH);
1828 if (!mls_dominate_effective(obj, subj))
1829 return (EACCES);
1830
1831 return (0);
1832 }
1833
1834 static int
mls_socket_check_deliver(struct socket * so,struct label * solabel,struct mbuf * m,struct label * mlabel)1835 mls_socket_check_deliver(struct socket *so, struct label *solabel,
1836 struct mbuf *m, struct label *mlabel)
1837 {
1838 struct mac_mls *p, *s;
1839 int error;
1840
1841 if (!mls_enabled)
1842 return (0);
1843
1844 p = SLOT(mlabel);
1845 s = SLOT(solabel);
1846
1847 SOCK_LOCK(so);
1848 error = mls_equal_effective(p, s) ? 0 : EACCES;
1849 SOCK_UNLOCK(so);
1850
1851 return (error);
1852 }
1853
1854 static int
mls_socket_check_relabel(struct ucred * cred,struct socket * so,struct label * solabel,struct label * newlabel)1855 mls_socket_check_relabel(struct ucred *cred, struct socket *so,
1856 struct label *solabel, struct label *newlabel)
1857 {
1858 struct mac_mls *subj, *obj, *new;
1859 int error;
1860
1861 SOCK_LOCK_ASSERT(so);
1862
1863 new = SLOT(newlabel);
1864 subj = SLOT(cred->cr_label);
1865 obj = SLOT(solabel);
1866
1867 /*
1868 * If there is an MLS label update for the socket, it may be an
1869 * update of effective.
1870 */
1871 error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1872 if (error)
1873 return (error);
1874
1875 /*
1876 * To relabel a socket, the old socket effective must be in the
1877 * subject range.
1878 */
1879 if (!mls_effective_in_range(obj, subj))
1880 return (EPERM);
1881
1882 /*
1883 * If the MLS label is to be changed, authorize as appropriate.
1884 */
1885 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1886 /*
1887 * To relabel a socket, the new socket effective must be in
1888 * the subject range.
1889 */
1890 if (!mls_effective_in_range(new, subj))
1891 return (EPERM);
1892
1893 /*
1894 * To change the MLS label on the socket to contain EQUAL,
1895 * the subject must have appropriate privilege.
1896 */
1897 if (mls_contains_equal(new)) {
1898 error = mls_subject_privileged(subj);
1899 if (error)
1900 return (error);
1901 }
1902 }
1903
1904 return (0);
1905 }
1906
1907 static int
mls_socket_check_visible(struct ucred * cred,struct socket * so,struct label * solabel)1908 mls_socket_check_visible(struct ucred *cred, struct socket *so,
1909 struct label *solabel)
1910 {
1911 struct mac_mls *subj, *obj;
1912
1913 if (!mls_enabled)
1914 return (0);
1915
1916 subj = SLOT(cred->cr_label);
1917 obj = SLOT(solabel);
1918
1919 SOCK_LOCK(so);
1920 if (!mls_dominate_effective(subj, obj)) {
1921 SOCK_UNLOCK(so);
1922 return (ENOENT);
1923 }
1924 SOCK_UNLOCK(so);
1925
1926 return (0);
1927 }
1928
1929 static void
mls_socket_create(struct ucred * cred,struct socket * so,struct label * solabel)1930 mls_socket_create(struct ucred *cred, struct socket *so,
1931 struct label *solabel)
1932 {
1933 struct mac_mls *source, *dest;
1934
1935 source = SLOT(cred->cr_label);
1936 dest = SLOT(solabel);
1937
1938 mls_copy_effective(source, dest);
1939 }
1940
1941 static void
mls_socket_create_mbuf(struct socket * so,struct label * solabel,struct mbuf * m,struct label * mlabel)1942 mls_socket_create_mbuf(struct socket *so, struct label *solabel,
1943 struct mbuf *m, struct label *mlabel)
1944 {
1945 struct mac_mls *source, *dest;
1946
1947 source = SLOT(solabel);
1948 dest = SLOT(mlabel);
1949
1950 SOCK_LOCK(so);
1951 mls_copy_effective(source, dest);
1952 SOCK_UNLOCK(so);
1953 }
1954
1955 static void
mls_socket_newconn(struct socket * oldso,struct label * oldsolabel,struct socket * newso,struct label * newsolabel)1956 mls_socket_newconn(struct socket *oldso, struct label *oldsolabel,
1957 struct socket *newso, struct label *newsolabel)
1958 {
1959 struct mac_mls source, *dest;
1960
1961 SOCK_LOCK(oldso);
1962 source = *SLOT(oldsolabel);
1963 SOCK_UNLOCK(oldso);
1964
1965 dest = SLOT(newsolabel);
1966
1967 SOCK_LOCK(newso);
1968 mls_copy_effective(&source, dest);
1969 SOCK_UNLOCK(newso);
1970 }
1971
1972 static void
mls_socket_relabel(struct ucred * cred,struct socket * so,struct label * solabel,struct label * newlabel)1973 mls_socket_relabel(struct ucred *cred, struct socket *so,
1974 struct label *solabel, struct label *newlabel)
1975 {
1976 struct mac_mls *source, *dest;
1977
1978 SOCK_LOCK_ASSERT(so);
1979
1980 source = SLOT(newlabel);
1981 dest = SLOT(solabel);
1982
1983 mls_copy(source, dest);
1984 }
1985
1986 static void
mls_socketpeer_set_from_mbuf(struct mbuf * m,struct label * mlabel,struct socket * so,struct label * sopeerlabel)1987 mls_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
1988 struct socket *so, struct label *sopeerlabel)
1989 {
1990 struct mac_mls *source, *dest;
1991
1992 source = SLOT(mlabel);
1993 dest = SLOT(sopeerlabel);
1994
1995 SOCK_LOCK(so);
1996 mls_copy_effective(source, dest);
1997 SOCK_UNLOCK(so);
1998 }
1999
2000 static void
mls_socketpeer_set_from_socket(struct socket * oldso,struct label * oldsolabel,struct socket * newso,struct label * newsopeerlabel)2001 mls_socketpeer_set_from_socket(struct socket *oldso,
2002 struct label *oldsolabel, struct socket *newso,
2003 struct label *newsopeerlabel)
2004 {
2005 struct mac_mls source, *dest;
2006
2007 SOCK_LOCK(oldso);
2008 source = *SLOT(oldsolabel);
2009 SOCK_UNLOCK(oldso);
2010
2011 dest = SLOT(newsopeerlabel);
2012
2013 SOCK_LOCK(newso);
2014 mls_copy_effective(&source, dest);
2015 SOCK_UNLOCK(newso);
2016 }
2017
2018 static void
mls_syncache_create(struct label * label,struct inpcb * inp)2019 mls_syncache_create(struct label *label, struct inpcb *inp)
2020 {
2021 struct mac_mls *source, *dest;
2022
2023 source = SLOT(inp->inp_label);
2024 dest = SLOT(label);
2025
2026 mls_copy_effective(source, dest);
2027 }
2028
2029 static void
mls_syncache_create_mbuf(struct label * sc_label,struct mbuf * m,struct label * mlabel)2030 mls_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
2031 struct label *mlabel)
2032 {
2033 struct mac_mls *source, *dest;
2034
2035 source = SLOT(sc_label);
2036 dest = SLOT(mlabel);
2037
2038 mls_copy_effective(source, dest);
2039 }
2040
2041 static int
mls_system_check_acct(struct ucred * cred,struct vnode * vp,struct label * vplabel)2042 mls_system_check_acct(struct ucred *cred, struct vnode *vp,
2043 struct label *vplabel)
2044 {
2045 struct mac_mls *subj, *obj;
2046
2047 if (!mls_enabled)
2048 return (0);
2049
2050 if (vplabel == NULL)
2051 return (0);
2052
2053 subj = SLOT(cred->cr_label);
2054 obj = SLOT(vplabel);
2055
2056 if (!mls_dominate_effective(obj, subj) ||
2057 !mls_dominate_effective(subj, obj))
2058 return (EACCES);
2059
2060 return (0);
2061 }
2062
2063 static int
mls_system_check_auditctl(struct ucred * cred,struct vnode * vp,struct label * vplabel)2064 mls_system_check_auditctl(struct ucred *cred, struct vnode *vp,
2065 struct label *vplabel)
2066 {
2067 struct mac_mls *subj, *obj;
2068
2069 if (!mls_enabled)
2070 return (0);
2071
2072 subj = SLOT(cred->cr_label);
2073 obj = SLOT(vplabel);
2074
2075 if (!mls_dominate_effective(obj, subj) ||
2076 !mls_dominate_effective(subj, obj))
2077 return (EACCES);
2078
2079 return (0);
2080 }
2081
2082 static int
mls_system_check_swapon(struct ucred * cred,struct vnode * vp,struct label * vplabel)2083 mls_system_check_swapon(struct ucred *cred, struct vnode *vp,
2084 struct label *vplabel)
2085 {
2086 struct mac_mls *subj, *obj;
2087
2088 if (!mls_enabled)
2089 return (0);
2090
2091 subj = SLOT(cred->cr_label);
2092 obj = SLOT(vplabel);
2093
2094 if (!mls_dominate_effective(obj, subj) ||
2095 !mls_dominate_effective(subj, obj))
2096 return (EACCES);
2097
2098 return (0);
2099 }
2100
2101 static void
mls_sysvmsg_cleanup(struct label * msglabel)2102 mls_sysvmsg_cleanup(struct label *msglabel)
2103 {
2104
2105 bzero(SLOT(msglabel), sizeof(struct mac_mls));
2106 }
2107
2108 static void
mls_sysvmsg_create(struct ucred * cred,struct msqid_kernel * msqkptr,struct label * msqlabel,struct msg * msgptr,struct label * msglabel)2109 mls_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2110 struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
2111 {
2112 struct mac_mls *source, *dest;
2113
2114 /* Ignore the msgq label. */
2115 source = SLOT(cred->cr_label);
2116 dest = SLOT(msglabel);
2117
2118 mls_copy_effective(source, dest);
2119 }
2120
2121 static int
mls_sysvmsq_check_msgrcv(struct ucred * cred,struct msg * msgptr,struct label * msglabel)2122 mls_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr,
2123 struct label *msglabel)
2124 {
2125 struct mac_mls *subj, *obj;
2126
2127 if (!mls_enabled)
2128 return (0);
2129
2130 subj = SLOT(cred->cr_label);
2131 obj = SLOT(msglabel);
2132
2133 if (!mls_dominate_effective(subj, obj))
2134 return (EACCES);
2135
2136 return (0);
2137 }
2138
2139 static int
mls_sysvmsq_check_msgrmid(struct ucred * cred,struct msg * msgptr,struct label * msglabel)2140 mls_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr,
2141 struct label *msglabel)
2142 {
2143 struct mac_mls *subj, *obj;
2144
2145 if (!mls_enabled)
2146 return (0);
2147
2148 subj = SLOT(cred->cr_label);
2149 obj = SLOT(msglabel);
2150
2151 if (!mls_dominate_effective(obj, subj))
2152 return (EACCES);
2153
2154 return (0);
2155 }
2156
2157 static int
mls_sysvmsq_check_msqget(struct ucred * cred,struct msqid_kernel * msqkptr,struct label * msqklabel)2158 mls_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
2159 struct label *msqklabel)
2160 {
2161 struct mac_mls *subj, *obj;
2162
2163 if (!mls_enabled)
2164 return (0);
2165
2166 subj = SLOT(cred->cr_label);
2167 obj = SLOT(msqklabel);
2168
2169 if (!mls_dominate_effective(subj, obj))
2170 return (EACCES);
2171
2172 return (0);
2173 }
2174
2175 static int
mls_sysvmsq_check_msqsnd(struct ucred * cred,struct msqid_kernel * msqkptr,struct label * msqklabel)2176 mls_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
2177 struct label *msqklabel)
2178 {
2179 struct mac_mls *subj, *obj;
2180
2181 if (!mls_enabled)
2182 return (0);
2183
2184 subj = SLOT(cred->cr_label);
2185 obj = SLOT(msqklabel);
2186
2187 if (!mls_dominate_effective(obj, subj))
2188 return (EACCES);
2189
2190 return (0);
2191 }
2192
2193 static int
mls_sysvmsq_check_msqrcv(struct ucred * cred,struct msqid_kernel * msqkptr,struct label * msqklabel)2194 mls_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
2195 struct label *msqklabel)
2196 {
2197 struct mac_mls *subj, *obj;
2198
2199 if (!mls_enabled)
2200 return (0);
2201
2202 subj = SLOT(cred->cr_label);
2203 obj = SLOT(msqklabel);
2204
2205 if (!mls_dominate_effective(subj, obj))
2206 return (EACCES);
2207
2208 return (0);
2209 }
2210
2211 static int
mls_sysvmsq_check_msqctl(struct ucred * cred,struct msqid_kernel * msqkptr,struct label * msqklabel,int cmd)2212 mls_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
2213 struct label *msqklabel, int cmd)
2214 {
2215 struct mac_mls *subj, *obj;
2216
2217 if (!mls_enabled)
2218 return (0);
2219
2220 subj = SLOT(cred->cr_label);
2221 obj = SLOT(msqklabel);
2222
2223 switch(cmd) {
2224 case IPC_RMID:
2225 case IPC_SET:
2226 if (!mls_dominate_effective(obj, subj))
2227 return (EACCES);
2228 break;
2229
2230 case IPC_STAT:
2231 if (!mls_dominate_effective(subj, obj))
2232 return (EACCES);
2233 break;
2234
2235 default:
2236 return (EACCES);
2237 }
2238
2239 return (0);
2240 }
2241
2242 static void
mls_sysvmsq_cleanup(struct label * msqlabel)2243 mls_sysvmsq_cleanup(struct label *msqlabel)
2244 {
2245
2246 bzero(SLOT(msqlabel), sizeof(struct mac_mls));
2247 }
2248
2249 static void
mls_sysvmsq_create(struct ucred * cred,struct msqid_kernel * msqkptr,struct label * msqlabel)2250 mls_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2251 struct label *msqlabel)
2252 {
2253 struct mac_mls *source, *dest;
2254
2255 source = SLOT(cred->cr_label);
2256 dest = SLOT(msqlabel);
2257
2258 mls_copy_effective(source, dest);
2259 }
2260
2261 static int
mls_sysvsem_check_semctl(struct ucred * cred,struct semid_kernel * semakptr,struct label * semaklabel,int cmd)2262 mls_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
2263 struct label *semaklabel, int cmd)
2264 {
2265 struct mac_mls *subj, *obj;
2266
2267 if (!mls_enabled)
2268 return (0);
2269
2270 subj = SLOT(cred->cr_label);
2271 obj = SLOT(semaklabel);
2272
2273 switch(cmd) {
2274 case IPC_RMID:
2275 case IPC_SET:
2276 case SETVAL:
2277 case SETALL:
2278 if (!mls_dominate_effective(obj, subj))
2279 return (EACCES);
2280 break;
2281
2282 case IPC_STAT:
2283 case GETVAL:
2284 case GETPID:
2285 case GETNCNT:
2286 case GETZCNT:
2287 case GETALL:
2288 if (!mls_dominate_effective(subj, obj))
2289 return (EACCES);
2290 break;
2291
2292 default:
2293 return (EACCES);
2294 }
2295
2296 return (0);
2297 }
2298
2299 static int
mls_sysvsem_check_semget(struct ucred * cred,struct semid_kernel * semakptr,struct label * semaklabel)2300 mls_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr,
2301 struct label *semaklabel)
2302 {
2303 struct mac_mls *subj, *obj;
2304
2305 if (!mls_enabled)
2306 return (0);
2307
2308 subj = SLOT(cred->cr_label);
2309 obj = SLOT(semaklabel);
2310
2311 if (!mls_dominate_effective(subj, obj))
2312 return (EACCES);
2313
2314 return (0);
2315 }
2316
2317 static int
mls_sysvsem_check_semop(struct ucred * cred,struct semid_kernel * semakptr,struct label * semaklabel,size_t accesstype)2318 mls_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
2319 struct label *semaklabel, size_t accesstype)
2320 {
2321 struct mac_mls *subj, *obj;
2322
2323 if (!mls_enabled)
2324 return (0);
2325
2326 subj = SLOT(cred->cr_label);
2327 obj = SLOT(semaklabel);
2328
2329 if( accesstype & SEM_R )
2330 if (!mls_dominate_effective(subj, obj))
2331 return (EACCES);
2332
2333 if( accesstype & SEM_A )
2334 if (!mls_dominate_effective(obj, subj))
2335 return (EACCES);
2336
2337 return (0);
2338 }
2339
2340 static void
mls_sysvsem_cleanup(struct label * semalabel)2341 mls_sysvsem_cleanup(struct label *semalabel)
2342 {
2343
2344 bzero(SLOT(semalabel), sizeof(struct mac_mls));
2345 }
2346
2347 static void
mls_sysvsem_create(struct ucred * cred,struct semid_kernel * semakptr,struct label * semalabel)2348 mls_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr,
2349 struct label *semalabel)
2350 {
2351 struct mac_mls *source, *dest;
2352
2353 source = SLOT(cred->cr_label);
2354 dest = SLOT(semalabel);
2355
2356 mls_copy_effective(source, dest);
2357 }
2358
2359 static int
mls_sysvshm_check_shmat(struct ucred * cred,struct shmid_kernel * shmsegptr,struct label * shmseglabel,int shmflg)2360 mls_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
2361 struct label *shmseglabel, int shmflg)
2362 {
2363 struct mac_mls *subj, *obj;
2364
2365 if (!mls_enabled)
2366 return (0);
2367
2368 subj = SLOT(cred->cr_label);
2369 obj = SLOT(shmseglabel);
2370
2371 if (!mls_dominate_effective(subj, obj))
2372 return (EACCES);
2373 if ((shmflg & SHM_RDONLY) == 0) {
2374 if (!mls_dominate_effective(obj, subj))
2375 return (EACCES);
2376 }
2377
2378 return (0);
2379 }
2380
2381 static int
mls_sysvshm_check_shmctl(struct ucred * cred,struct shmid_kernel * shmsegptr,struct label * shmseglabel,int cmd)2382 mls_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
2383 struct label *shmseglabel, int cmd)
2384 {
2385 struct mac_mls *subj, *obj;
2386
2387 if (!mls_enabled)
2388 return (0);
2389
2390 subj = SLOT(cred->cr_label);
2391 obj = SLOT(shmseglabel);
2392
2393 switch(cmd) {
2394 case IPC_RMID:
2395 case IPC_SET:
2396 if (!mls_dominate_effective(obj, subj))
2397 return (EACCES);
2398 break;
2399
2400 case IPC_STAT:
2401 case SHM_STAT:
2402 if (!mls_dominate_effective(subj, obj))
2403 return (EACCES);
2404 break;
2405
2406 default:
2407 return (EACCES);
2408 }
2409
2410 return (0);
2411 }
2412
2413 static int
mls_sysvshm_check_shmget(struct ucred * cred,struct shmid_kernel * shmsegptr,struct label * shmseglabel,int shmflg)2414 mls_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
2415 struct label *shmseglabel, int shmflg)
2416 {
2417 struct mac_mls *subj, *obj;
2418
2419 if (!mls_enabled)
2420 return (0);
2421
2422 subj = SLOT(cred->cr_label);
2423 obj = SLOT(shmseglabel);
2424
2425 if (!mls_dominate_effective(obj, subj))
2426 return (EACCES);
2427
2428 return (0);
2429 }
2430
2431 static void
mls_sysvshm_cleanup(struct label * shmlabel)2432 mls_sysvshm_cleanup(struct label *shmlabel)
2433 {
2434
2435 bzero(SLOT(shmlabel), sizeof(struct mac_mls));
2436 }
2437
2438 static void
mls_sysvshm_create(struct ucred * cred,struct shmid_kernel * shmsegptr,struct label * shmlabel)2439 mls_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr,
2440 struct label *shmlabel)
2441 {
2442 struct mac_mls *source, *dest;
2443
2444 source = SLOT(cred->cr_label);
2445 dest = SLOT(shmlabel);
2446
2447 mls_copy_effective(source, dest);
2448 }
2449
2450 static int
mls_vnode_associate_extattr(struct mount * mp,struct label * mplabel,struct vnode * vp,struct label * vplabel)2451 mls_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2452 struct vnode *vp, struct label *vplabel)
2453 {
2454 struct mac_mls mm_temp, *source, *dest;
2455 int buflen, error;
2456
2457 source = SLOT(mplabel);
2458 dest = SLOT(vplabel);
2459
2460 buflen = sizeof(mm_temp);
2461 bzero(&mm_temp, buflen);
2462
2463 error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2464 MAC_MLS_EXTATTR_NAME, &buflen, (char *) &mm_temp, curthread);
2465 if (error == ENOATTR || error == EOPNOTSUPP) {
2466 /* Fall back to the mntlabel. */
2467 mls_copy_effective(source, dest);
2468 return (0);
2469 } else if (error)
2470 return (error);
2471
2472 if (buflen != sizeof(mm_temp)) {
2473 printf("mls_vnode_associate_extattr: bad size %d\n", buflen);
2474 return (EPERM);
2475 }
2476 if (mls_valid(&mm_temp) != 0) {
2477 printf("mls_vnode_associate_extattr: invalid\n");
2478 return (EPERM);
2479 }
2480 if ((mm_temp.mm_flags & MAC_MLS_FLAGS_BOTH) !=
2481 MAC_MLS_FLAG_EFFECTIVE) {
2482 printf("mls_associated_vnode_extattr: not effective\n");
2483 return (EPERM);
2484 }
2485
2486 mls_copy_effective(&mm_temp, dest);
2487 return (0);
2488 }
2489
2490 static void
mls_vnode_associate_singlelabel(struct mount * mp,struct label * mplabel,struct vnode * vp,struct label * vplabel)2491 mls_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2492 struct vnode *vp, struct label *vplabel)
2493 {
2494 struct mac_mls *source, *dest;
2495
2496 source = SLOT(mplabel);
2497 dest = SLOT(vplabel);
2498
2499 mls_copy_effective(source, dest);
2500 }
2501
2502 static int
mls_vnode_check_chdir(struct ucred * cred,struct vnode * dvp,struct label * dvplabel)2503 mls_vnode_check_chdir(struct ucred *cred, struct vnode *dvp,
2504 struct label *dvplabel)
2505 {
2506 struct mac_mls *subj, *obj;
2507
2508 if (!mls_enabled)
2509 return (0);
2510
2511 subj = SLOT(cred->cr_label);
2512 obj = SLOT(dvplabel);
2513
2514 if (!mls_dominate_effective(subj, obj))
2515 return (EACCES);
2516
2517 return (0);
2518 }
2519
2520 static int
mls_vnode_check_chroot(struct ucred * cred,struct vnode * dvp,struct label * dvplabel)2521 mls_vnode_check_chroot(struct ucred *cred, struct vnode *dvp,
2522 struct label *dvplabel)
2523 {
2524 struct mac_mls *subj, *obj;
2525
2526 if (!mls_enabled)
2527 return (0);
2528
2529 subj = SLOT(cred->cr_label);
2530 obj = SLOT(dvplabel);
2531
2532 if (!mls_dominate_effective(subj, obj))
2533 return (EACCES);
2534
2535 return (0);
2536 }
2537
2538 static int
mls_vnode_check_create(struct ucred * cred,struct vnode * dvp,struct label * dvplabel,struct componentname * cnp,struct vattr * vap)2539 mls_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2540 struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2541 {
2542 struct mac_mls *subj, *obj;
2543
2544 if (!mls_enabled)
2545 return (0);
2546
2547 subj = SLOT(cred->cr_label);
2548 obj = SLOT(dvplabel);
2549
2550 if (!mls_dominate_effective(obj, subj))
2551 return (EACCES);
2552
2553 return (0);
2554 }
2555
2556 static int
mls_vnode_check_deleteacl(struct ucred * cred,struct vnode * vp,struct label * vplabel,acl_type_t type)2557 mls_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2558 struct label *vplabel, acl_type_t type)
2559 {
2560 struct mac_mls *subj, *obj;
2561
2562 if (!mls_enabled)
2563 return (0);
2564
2565 subj = SLOT(cred->cr_label);
2566 obj = SLOT(vplabel);
2567
2568 if (!mls_dominate_effective(obj, subj))
2569 return (EACCES);
2570
2571 return (0);
2572 }
2573
2574 static int
mls_vnode_check_deleteextattr(struct ucred * cred,struct vnode * vp,struct label * vplabel,int attrnamespace,const char * name)2575 mls_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
2576 struct label *vplabel, int attrnamespace, const char *name)
2577 {
2578 struct mac_mls *subj, *obj;
2579
2580 if (!mls_enabled)
2581 return (0);
2582
2583 subj = SLOT(cred->cr_label);
2584 obj = SLOT(vplabel);
2585
2586 if (!mls_dominate_effective(obj, subj))
2587 return (EACCES);
2588
2589 return (0);
2590 }
2591
2592 static int
mls_vnode_check_exec(struct ucred * cred,struct vnode * vp,struct label * vplabel,struct image_params * imgp,struct label * execlabel)2593 mls_vnode_check_exec(struct ucred *cred, struct vnode *vp,
2594 struct label *vplabel, struct image_params *imgp,
2595 struct label *execlabel)
2596 {
2597 struct mac_mls *subj, *obj, *exec;
2598 int error;
2599
2600 if (execlabel != NULL) {
2601 /*
2602 * We currently don't permit labels to be changed at
2603 * exec-time as part of MLS, so disallow non-NULL MLS label
2604 * elements in the execlabel.
2605 */
2606 exec = SLOT(execlabel);
2607 error = mls_atmostflags(exec, 0);
2608 if (error)
2609 return (error);
2610 }
2611
2612 if (!mls_enabled)
2613 return (0);
2614
2615 subj = SLOT(cred->cr_label);
2616 obj = SLOT(vplabel);
2617
2618 if (!mls_dominate_effective(subj, obj))
2619 return (EACCES);
2620
2621 return (0);
2622 }
2623
2624 static int
mls_vnode_check_getacl(struct ucred * cred,struct vnode * vp,struct label * vplabel,acl_type_t type)2625 mls_vnode_check_getacl(struct ucred *cred, struct vnode *vp,
2626 struct label *vplabel, acl_type_t type)
2627 {
2628 struct mac_mls *subj, *obj;
2629
2630 if (!mls_enabled)
2631 return (0);
2632
2633 subj = SLOT(cred->cr_label);
2634 obj = SLOT(vplabel);
2635
2636 if (!mls_dominate_effective(subj, obj))
2637 return (EACCES);
2638
2639 return (0);
2640 }
2641
2642 static int
mls_vnode_check_getextattr(struct ucred * cred,struct vnode * vp,struct label * vplabel,int attrnamespace,const char * name)2643 mls_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
2644 struct label *vplabel, int attrnamespace, const char *name)
2645 {
2646 struct mac_mls *subj, *obj;
2647
2648 if (!mls_enabled)
2649 return (0);
2650
2651 subj = SLOT(cred->cr_label);
2652 obj = SLOT(vplabel);
2653
2654 if (!mls_dominate_effective(subj, obj))
2655 return (EACCES);
2656
2657 return (0);
2658 }
2659
2660 static int
mls_vnode_check_link(struct ucred * cred,struct vnode * dvp,struct label * dvplabel,struct vnode * vp,struct label * vplabel,struct componentname * cnp)2661 mls_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2662 struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2663 struct componentname *cnp)
2664 {
2665 struct mac_mls *subj, *obj;
2666
2667 if (!mls_enabled)
2668 return (0);
2669
2670 subj = SLOT(cred->cr_label);
2671 obj = SLOT(dvplabel);
2672
2673 if (!mls_dominate_effective(obj, subj))
2674 return (EACCES);
2675
2676 obj = SLOT(vplabel);
2677 if (!mls_dominate_effective(obj, subj))
2678 return (EACCES);
2679
2680 return (0);
2681 }
2682
2683 static int
mls_vnode_check_listextattr(struct ucred * cred,struct vnode * vp,struct label * vplabel,int attrnamespace)2684 mls_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
2685 struct label *vplabel, int attrnamespace)
2686 {
2687
2688 struct mac_mls *subj, *obj;
2689
2690 if (!mls_enabled)
2691 return (0);
2692
2693 subj = SLOT(cred->cr_label);
2694 obj = SLOT(vplabel);
2695
2696 if (!mls_dominate_effective(subj, obj))
2697 return (EACCES);
2698
2699 return (0);
2700 }
2701
2702 static int
mls_vnode_check_lookup(struct ucred * cred,struct vnode * dvp,struct label * dvplabel,struct componentname * cnp)2703 mls_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
2704 struct label *dvplabel, struct componentname *cnp)
2705 {
2706 struct mac_mls *subj, *obj;
2707
2708 if (!mls_enabled)
2709 return (0);
2710
2711 subj = SLOT(cred->cr_label);
2712 obj = SLOT(dvplabel);
2713
2714 if (!mls_dominate_effective(subj, obj))
2715 return (EACCES);
2716
2717 return (0);
2718 }
2719
2720 static int
mls_vnode_check_mmap(struct ucred * cred,struct vnode * vp,struct label * vplabel,int prot,int flags)2721 mls_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2722 struct label *vplabel, int prot, int flags)
2723 {
2724 struct mac_mls *subj, *obj;
2725
2726 /*
2727 * Rely on the use of open()-time protections to handle
2728 * non-revocation cases.
2729 */
2730 if (!mls_enabled || !revocation_enabled)
2731 return (0);
2732
2733 subj = SLOT(cred->cr_label);
2734 obj = SLOT(vplabel);
2735
2736 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2737 if (!mls_dominate_effective(subj, obj))
2738 return (EACCES);
2739 }
2740 if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2741 if (!mls_dominate_effective(obj, subj))
2742 return (EACCES);
2743 }
2744
2745 return (0);
2746 }
2747
2748 static int
mls_vnode_check_open(struct ucred * cred,struct vnode * vp,struct label * vplabel,accmode_t accmode)2749 mls_vnode_check_open(struct ucred *cred, struct vnode *vp,
2750 struct label *vplabel, accmode_t accmode)
2751 {
2752 struct mac_mls *subj, *obj;
2753
2754 if (!mls_enabled)
2755 return (0);
2756
2757 subj = SLOT(cred->cr_label);
2758 obj = SLOT(vplabel);
2759
2760 /* XXX privilege override for admin? */
2761 if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
2762 if (!mls_dominate_effective(subj, obj))
2763 return (EACCES);
2764 }
2765 if (accmode & VMODIFY_PERMS) {
2766 if (!mls_dominate_effective(obj, subj))
2767 return (EACCES);
2768 }
2769
2770 return (0);
2771 }
2772
2773 static int
mls_vnode_check_poll(struct ucred * active_cred,struct ucred * file_cred,struct vnode * vp,struct label * vplabel)2774 mls_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
2775 struct vnode *vp, struct label *vplabel)
2776 {
2777 struct mac_mls *subj, *obj;
2778
2779 if (!mls_enabled || !revocation_enabled)
2780 return (0);
2781
2782 subj = SLOT(active_cred->cr_label);
2783 obj = SLOT(vplabel);
2784
2785 if (!mls_dominate_effective(subj, obj))
2786 return (EACCES);
2787
2788 return (0);
2789 }
2790
2791 static int
mls_vnode_check_read(struct ucred * active_cred,struct ucred * file_cred,struct vnode * vp,struct label * vplabel)2792 mls_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2793 struct vnode *vp, struct label *vplabel)
2794 {
2795 struct mac_mls *subj, *obj;
2796
2797 if (!mls_enabled || !revocation_enabled)
2798 return (0);
2799
2800 subj = SLOT(active_cred->cr_label);
2801 obj = SLOT(vplabel);
2802
2803 if (!mls_dominate_effective(subj, obj))
2804 return (EACCES);
2805
2806 return (0);
2807 }
2808
2809 static int
mls_vnode_check_readdir(struct ucred * cred,struct vnode * dvp,struct label * dvplabel)2810 mls_vnode_check_readdir(struct ucred *cred, struct vnode *dvp,
2811 struct label *dvplabel)
2812 {
2813 struct mac_mls *subj, *obj;
2814
2815 if (!mls_enabled)
2816 return (0);
2817
2818 subj = SLOT(cred->cr_label);
2819 obj = SLOT(dvplabel);
2820
2821 if (!mls_dominate_effective(subj, obj))
2822 return (EACCES);
2823
2824 return (0);
2825 }
2826
2827 static int
mls_vnode_check_readlink(struct ucred * cred,struct vnode * vp,struct label * vplabel)2828 mls_vnode_check_readlink(struct ucred *cred, struct vnode *vp,
2829 struct label *vplabel)
2830 {
2831 struct mac_mls *subj, *obj;
2832
2833 if (!mls_enabled)
2834 return (0);
2835
2836 subj = SLOT(cred->cr_label);
2837 obj = SLOT(vplabel);
2838
2839 if (!mls_dominate_effective(subj, obj))
2840 return (EACCES);
2841
2842 return (0);
2843 }
2844
2845 static int
mls_vnode_check_relabel(struct ucred * cred,struct vnode * vp,struct label * vplabel,struct label * newlabel)2846 mls_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2847 struct label *vplabel, struct label *newlabel)
2848 {
2849 struct mac_mls *old, *new, *subj;
2850 int error;
2851
2852 old = SLOT(vplabel);
2853 new = SLOT(newlabel);
2854 subj = SLOT(cred->cr_label);
2855
2856 /*
2857 * If there is an MLS label update for the vnode, it must be a
2858 * effective label.
2859 */
2860 error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2861 if (error)
2862 return (error);
2863
2864 /*
2865 * To perform a relabel of the vnode (MLS label or not), MLS must
2866 * authorize the relabel.
2867 */
2868 if (!mls_effective_in_range(old, subj))
2869 return (EPERM);
2870
2871 /*
2872 * If the MLS label is to be changed, authorize as appropriate.
2873 */
2874 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2875 /*
2876 * To change the MLS label on a vnode, the new vnode label
2877 * must be in the subject range.
2878 */
2879 if (!mls_effective_in_range(new, subj))
2880 return (EPERM);
2881
2882 /*
2883 * To change the MLS label on the vnode to be EQUAL, the
2884 * subject must have appropriate privilege.
2885 */
2886 if (mls_contains_equal(new)) {
2887 error = mls_subject_privileged(subj);
2888 if (error)
2889 return (error);
2890 }
2891 }
2892
2893 return (0);
2894 }
2895
2896 static int
mls_vnode_check_rename_from(struct ucred * cred,struct vnode * dvp,struct label * dvplabel,struct vnode * vp,struct label * vplabel,struct componentname * cnp)2897 mls_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2898 struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2899 struct componentname *cnp)
2900 {
2901 struct mac_mls *subj, *obj;
2902
2903 if (!mls_enabled)
2904 return (0);
2905
2906 subj = SLOT(cred->cr_label);
2907 obj = SLOT(dvplabel);
2908
2909 if (!mls_dominate_effective(obj, subj))
2910 return (EACCES);
2911
2912 obj = SLOT(vplabel);
2913
2914 if (!mls_dominate_effective(obj, subj))
2915 return (EACCES);
2916
2917 return (0);
2918 }
2919
2920 static int
mls_vnode_check_rename_to(struct ucred * cred,struct vnode * dvp,struct label * dvplabel,struct vnode * vp,struct label * vplabel,int samedir,struct componentname * cnp)2921 mls_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2922 struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2923 int samedir, struct componentname *cnp)
2924 {
2925 struct mac_mls *subj, *obj;
2926
2927 if (!mls_enabled)
2928 return (0);
2929
2930 subj = SLOT(cred->cr_label);
2931 obj = SLOT(dvplabel);
2932
2933 if (!mls_dominate_effective(obj, subj))
2934 return (EACCES);
2935
2936 if (vp != NULL) {
2937 obj = SLOT(vplabel);
2938
2939 if (!mls_dominate_effective(obj, subj))
2940 return (EACCES);
2941 }
2942
2943 return (0);
2944 }
2945
2946 static int
mls_vnode_check_revoke(struct ucred * cred,struct vnode * vp,struct label * vplabel)2947 mls_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2948 struct label *vplabel)
2949 {
2950 struct mac_mls *subj, *obj;
2951
2952 if (!mls_enabled)
2953 return (0);
2954
2955 subj = SLOT(cred->cr_label);
2956 obj = SLOT(vplabel);
2957
2958 if (!mls_dominate_effective(obj, subj))
2959 return (EACCES);
2960
2961 return (0);
2962 }
2963
2964 static int
mls_vnode_check_setacl(struct ucred * cred,struct vnode * vp,struct label * vplabel,acl_type_t type,struct acl * acl)2965 mls_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2966 struct label *vplabel, acl_type_t type, struct acl *acl)
2967 {
2968 struct mac_mls *subj, *obj;
2969
2970 if (!mls_enabled)
2971 return (0);
2972
2973 subj = SLOT(cred->cr_label);
2974 obj = SLOT(vplabel);
2975
2976 if (!mls_dominate_effective(obj, subj))
2977 return (EACCES);
2978
2979 return (0);
2980 }
2981
2982 static int
mls_vnode_check_setextattr(struct ucred * cred,struct vnode * vp,struct label * vplabel,int attrnamespace,const char * name)2983 mls_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2984 struct label *vplabel, int attrnamespace, const char *name)
2985 {
2986 struct mac_mls *subj, *obj;
2987
2988 if (!mls_enabled)
2989 return (0);
2990
2991 subj = SLOT(cred->cr_label);
2992 obj = SLOT(vplabel);
2993
2994 if (!mls_dominate_effective(obj, subj))
2995 return (EACCES);
2996
2997 /* XXX: protect the MAC EA in a special way? */
2998
2999 return (0);
3000 }
3001
3002 static int
mls_vnode_check_setflags(struct ucred * cred,struct vnode * vp,struct label * vplabel,u_long flags)3003 mls_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
3004 struct label *vplabel, u_long flags)
3005 {
3006 struct mac_mls *subj, *obj;
3007
3008 if (!mls_enabled)
3009 return (0);
3010
3011 subj = SLOT(cred->cr_label);
3012 obj = SLOT(vplabel);
3013
3014 if (!mls_dominate_effective(obj, subj))
3015 return (EACCES);
3016
3017 return (0);
3018 }
3019
3020 static int
mls_vnode_check_setmode(struct ucred * cred,struct vnode * vp,struct label * vplabel,mode_t mode)3021 mls_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
3022 struct label *vplabel, mode_t mode)
3023 {
3024 struct mac_mls *subj, *obj;
3025
3026 if (!mls_enabled)
3027 return (0);
3028
3029 subj = SLOT(cred->cr_label);
3030 obj = SLOT(vplabel);
3031
3032 if (!mls_dominate_effective(obj, subj))
3033 return (EACCES);
3034
3035 return (0);
3036 }
3037
3038 static int
mls_vnode_check_setowner(struct ucred * cred,struct vnode * vp,struct label * vplabel,uid_t uid,gid_t gid)3039 mls_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
3040 struct label *vplabel, uid_t uid, gid_t gid)
3041 {
3042 struct mac_mls *subj, *obj;
3043
3044 if (!mls_enabled)
3045 return (0);
3046
3047 subj = SLOT(cred->cr_label);
3048 obj = SLOT(vplabel);
3049
3050 if (!mls_dominate_effective(obj, subj))
3051 return (EACCES);
3052
3053 return (0);
3054 }
3055
3056 static int
mls_vnode_check_setutimes(struct ucred * cred,struct vnode * vp,struct label * vplabel,struct timespec atime,struct timespec mtime)3057 mls_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
3058 struct label *vplabel, struct timespec atime, struct timespec mtime)
3059 {
3060 struct mac_mls *subj, *obj;
3061
3062 if (!mls_enabled)
3063 return (0);
3064
3065 subj = SLOT(cred->cr_label);
3066 obj = SLOT(vplabel);
3067
3068 if (!mls_dominate_effective(obj, subj))
3069 return (EACCES);
3070
3071 return (0);
3072 }
3073
3074 static int
mls_vnode_check_stat(struct ucred * active_cred,struct ucred * file_cred,struct vnode * vp,struct label * vplabel)3075 mls_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
3076 struct vnode *vp, struct label *vplabel)
3077 {
3078 struct mac_mls *subj, *obj;
3079
3080 if (!mls_enabled)
3081 return (0);
3082
3083 subj = SLOT(active_cred->cr_label);
3084 obj = SLOT(vplabel);
3085
3086 if (!mls_dominate_effective(subj, obj))
3087 return (EACCES);
3088
3089 return (0);
3090 }
3091
3092 static int
mls_vnode_check_unlink(struct ucred * cred,struct vnode * dvp,struct label * dvplabel,struct vnode * vp,struct label * vplabel,struct componentname * cnp)3093 mls_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
3094 struct label *dvplabel, struct vnode *vp, struct label *vplabel,
3095 struct componentname *cnp)
3096 {
3097 struct mac_mls *subj, *obj;
3098
3099 if (!mls_enabled)
3100 return (0);
3101
3102 subj = SLOT(cred->cr_label);
3103 obj = SLOT(dvplabel);
3104
3105 if (!mls_dominate_effective(obj, subj))
3106 return (EACCES);
3107
3108 obj = SLOT(vplabel);
3109
3110 if (!mls_dominate_effective(obj, subj))
3111 return (EACCES);
3112
3113 return (0);
3114 }
3115
3116 static int
mls_vnode_check_write(struct ucred * active_cred,struct ucred * file_cred,struct vnode * vp,struct label * vplabel)3117 mls_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
3118 struct vnode *vp, struct label *vplabel)
3119 {
3120 struct mac_mls *subj, *obj;
3121
3122 if (!mls_enabled || !revocation_enabled)
3123 return (0);
3124
3125 subj = SLOT(active_cred->cr_label);
3126 obj = SLOT(vplabel);
3127
3128 if (!mls_dominate_effective(obj, subj))
3129 return (EACCES);
3130
3131 return (0);
3132 }
3133
3134 static int
mls_vnode_create_extattr(struct ucred * cred,struct mount * mp,struct label * mplabel,struct vnode * dvp,struct label * dvplabel,struct vnode * vp,struct label * vplabel,struct componentname * cnp)3135 mls_vnode_create_extattr(struct ucred *cred, struct mount *mp,
3136 struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
3137 struct vnode *vp, struct label *vplabel, struct componentname *cnp)
3138 {
3139 struct mac_mls *source, *dest, mm_temp;
3140 size_t buflen;
3141 int error;
3142
3143 buflen = sizeof(mm_temp);
3144 bzero(&mm_temp, buflen);
3145
3146 source = SLOT(cred->cr_label);
3147 dest = SLOT(vplabel);
3148 mls_copy_effective(source, &mm_temp);
3149
3150 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
3151 MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
3152 if (error == 0)
3153 mls_copy_effective(source, dest);
3154 return (error);
3155 }
3156
3157 static void
mls_vnode_relabel(struct ucred * cred,struct vnode * vp,struct label * vplabel,struct label * label)3158 mls_vnode_relabel(struct ucred *cred, struct vnode *vp,
3159 struct label *vplabel, struct label *label)
3160 {
3161 struct mac_mls *source, *dest;
3162
3163 source = SLOT(label);
3164 dest = SLOT(vplabel);
3165
3166 mls_copy(source, dest);
3167 }
3168
3169 static int
mls_vnode_setlabel_extattr(struct ucred * cred,struct vnode * vp,struct label * vplabel,struct label * intlabel)3170 mls_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
3171 struct label *vplabel, struct label *intlabel)
3172 {
3173 struct mac_mls *source, mm_temp;
3174 size_t buflen;
3175 int error;
3176
3177 buflen = sizeof(mm_temp);
3178 bzero(&mm_temp, buflen);
3179
3180 source = SLOT(intlabel);
3181 if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
3182 return (0);
3183
3184 mls_copy_effective(source, &mm_temp);
3185
3186 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
3187 MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
3188 return (error);
3189 }
3190
3191 static struct mac_policy_ops mls_ops =
3192 {
3193 .mpo_init = mls_init,
3194
3195 .mpo_bpfdesc_check_receive = mls_bpfdesc_check_receive,
3196 .mpo_bpfdesc_create = mls_bpfdesc_create,
3197 .mpo_bpfdesc_create_mbuf = mls_bpfdesc_create_mbuf,
3198 .mpo_bpfdesc_destroy_label = mls_destroy_label,
3199 .mpo_bpfdesc_init_label = mls_init_label,
3200
3201 .mpo_cred_associate_nfsd = mls_cred_associate_nfsd,
3202 .mpo_cred_check_relabel = mls_cred_check_relabel,
3203 .mpo_cred_check_visible = mls_cred_check_visible,
3204 .mpo_cred_copy_label = mls_copy_label,
3205 .mpo_cred_create_init = mls_cred_create_init,
3206 .mpo_cred_create_swapper = mls_cred_create_swapper,
3207 .mpo_cred_destroy_label = mls_destroy_label,
3208 .mpo_cred_externalize_label = mls_externalize_label,
3209 .mpo_cred_init_label = mls_init_label,
3210 .mpo_cred_internalize_label = mls_internalize_label,
3211 .mpo_cred_relabel = mls_cred_relabel,
3212
3213 .mpo_devfs_create_device = mls_devfs_create_device,
3214 .mpo_devfs_create_directory = mls_devfs_create_directory,
3215 .mpo_devfs_create_symlink = mls_devfs_create_symlink,
3216 .mpo_devfs_destroy_label = mls_destroy_label,
3217 .mpo_devfs_init_label = mls_init_label,
3218 .mpo_devfs_update = mls_devfs_update,
3219 .mpo_devfs_vnode_associate = mls_devfs_vnode_associate,
3220
3221 .mpo_ifnet_check_relabel = mls_ifnet_check_relabel,
3222 .mpo_ifnet_check_transmit = mls_ifnet_check_transmit,
3223 .mpo_ifnet_copy_label = mls_copy_label,
3224 .mpo_ifnet_create = mls_ifnet_create,
3225 .mpo_ifnet_create_mbuf = mls_ifnet_create_mbuf,
3226 .mpo_ifnet_destroy_label = mls_destroy_label,
3227 .mpo_ifnet_externalize_label = mls_externalize_label,
3228 .mpo_ifnet_init_label = mls_init_label,
3229 .mpo_ifnet_internalize_label = mls_internalize_label,
3230 .mpo_ifnet_relabel = mls_ifnet_relabel,
3231
3232 .mpo_inpcb_check_deliver = mls_inpcb_check_deliver,
3233 .mpo_inpcb_check_visible = mls_inpcb_check_visible,
3234 .mpo_inpcb_create = mls_inpcb_create,
3235 .mpo_inpcb_create_mbuf = mls_inpcb_create_mbuf,
3236 .mpo_inpcb_destroy_label = mls_destroy_label,
3237 .mpo_inpcb_init_label = mls_init_label_waitcheck,
3238 .mpo_inpcb_sosetlabel = mls_inpcb_sosetlabel,
3239
3240 .mpo_ip6q_create = mls_ip6q_create,
3241 .mpo_ip6q_destroy_label = mls_destroy_label,
3242 .mpo_ip6q_init_label = mls_init_label_waitcheck,
3243 .mpo_ip6q_match = mls_ip6q_match,
3244 .mpo_ip6q_reassemble = mls_ip6q_reassemble,
3245 .mpo_ip6q_update = mls_ip6q_update,
3246
3247 .mpo_ipq_create = mls_ipq_create,
3248 .mpo_ipq_destroy_label = mls_destroy_label,
3249 .mpo_ipq_init_label = mls_init_label_waitcheck,
3250 .mpo_ipq_match = mls_ipq_match,
3251 .mpo_ipq_reassemble = mls_ipq_reassemble,
3252 .mpo_ipq_update = mls_ipq_update,
3253
3254 .mpo_mbuf_copy_label = mls_copy_label,
3255 .mpo_mbuf_destroy_label = mls_destroy_label,
3256 .mpo_mbuf_init_label = mls_init_label_waitcheck,
3257
3258 .mpo_mount_check_stat = mls_mount_check_stat,
3259 .mpo_mount_create = mls_mount_create,
3260 .mpo_mount_destroy_label = mls_destroy_label,
3261 .mpo_mount_init_label = mls_init_label,
3262
3263 .mpo_netinet_arp_send = mls_netinet_arp_send,
3264 .mpo_netinet_firewall_reply = mls_netinet_firewall_reply,
3265 .mpo_netinet_firewall_send = mls_netinet_firewall_send,
3266 .mpo_netinet_fragment = mls_netinet_fragment,
3267 .mpo_netinet_icmp_reply = mls_netinet_icmp_reply,
3268 .mpo_netinet_igmp_send = mls_netinet_igmp_send,
3269
3270 .mpo_netinet6_nd6_send = mls_netinet6_nd6_send,
3271
3272 .mpo_pipe_check_ioctl = mls_pipe_check_ioctl,
3273 .mpo_pipe_check_poll = mls_pipe_check_poll,
3274 .mpo_pipe_check_read = mls_pipe_check_read,
3275 .mpo_pipe_check_relabel = mls_pipe_check_relabel,
3276 .mpo_pipe_check_stat = mls_pipe_check_stat,
3277 .mpo_pipe_check_write = mls_pipe_check_write,
3278 .mpo_pipe_copy_label = mls_copy_label,
3279 .mpo_pipe_create = mls_pipe_create,
3280 .mpo_pipe_destroy_label = mls_destroy_label,
3281 .mpo_pipe_externalize_label = mls_externalize_label,
3282 .mpo_pipe_init_label = mls_init_label,
3283 .mpo_pipe_internalize_label = mls_internalize_label,
3284 .mpo_pipe_relabel = mls_pipe_relabel,
3285
3286 .mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly,
3287 .mpo_posixsem_check_open = mls_posixsem_check_openunlink,
3288 .mpo_posixsem_check_post = mls_posixsem_check_write,
3289 .mpo_posixsem_check_setmode = mls_posixsem_check_setmode,
3290 .mpo_posixsem_check_setowner = mls_posixsem_check_setowner,
3291 .mpo_posixsem_check_stat = mls_posixsem_check_rdonly,
3292 .mpo_posixsem_check_unlink = mls_posixsem_check_openunlink,
3293 .mpo_posixsem_check_wait = mls_posixsem_check_write,
3294 .mpo_posixsem_create = mls_posixsem_create,
3295 .mpo_posixsem_destroy_label = mls_destroy_label,
3296 .mpo_posixsem_init_label = mls_init_label,
3297
3298 .mpo_posixshm_check_mmap = mls_posixshm_check_mmap,
3299 .mpo_posixshm_check_open = mls_posixshm_check_open,
3300 .mpo_posixshm_check_read = mls_posixshm_check_read,
3301 .mpo_posixshm_check_setmode = mls_posixshm_check_setmode,
3302 .mpo_posixshm_check_setowner = mls_posixshm_check_setowner,
3303 .mpo_posixshm_check_stat = mls_posixshm_check_stat,
3304 .mpo_posixshm_check_truncate = mls_posixshm_check_truncate,
3305 .mpo_posixshm_check_unlink = mls_posixshm_check_unlink,
3306 .mpo_posixshm_check_write = mls_posixshm_check_write,
3307 .mpo_posixshm_create = mls_posixshm_create,
3308 .mpo_posixshm_destroy_label = mls_destroy_label,
3309 .mpo_posixshm_init_label = mls_init_label,
3310
3311 .mpo_proc_check_debug = mls_proc_check_debug,
3312 .mpo_proc_check_sched = mls_proc_check_sched,
3313 .mpo_proc_check_signal = mls_proc_check_signal,
3314
3315 .mpo_socket_check_deliver = mls_socket_check_deliver,
3316 .mpo_socket_check_relabel = mls_socket_check_relabel,
3317 .mpo_socket_check_visible = mls_socket_check_visible,
3318 .mpo_socket_copy_label = mls_copy_label,
3319 .mpo_socket_create = mls_socket_create,
3320 .mpo_socket_create_mbuf = mls_socket_create_mbuf,
3321 .mpo_socket_destroy_label = mls_destroy_label,
3322 .mpo_socket_externalize_label = mls_externalize_label,
3323 .mpo_socket_init_label = mls_init_label_waitcheck,
3324 .mpo_socket_internalize_label = mls_internalize_label,
3325 .mpo_socket_newconn = mls_socket_newconn,
3326 .mpo_socket_relabel = mls_socket_relabel,
3327
3328 .mpo_socketpeer_destroy_label = mls_destroy_label,
3329 .mpo_socketpeer_externalize_label = mls_externalize_label,
3330 .mpo_socketpeer_init_label = mls_init_label_waitcheck,
3331 .mpo_socketpeer_set_from_mbuf = mls_socketpeer_set_from_mbuf,
3332 .mpo_socketpeer_set_from_socket = mls_socketpeer_set_from_socket,
3333
3334 .mpo_syncache_create = mls_syncache_create,
3335 .mpo_syncache_create_mbuf = mls_syncache_create_mbuf,
3336 .mpo_syncache_destroy_label = mls_destroy_label,
3337 .mpo_syncache_init_label = mls_init_label_waitcheck,
3338
3339 .mpo_sysvmsg_cleanup = mls_sysvmsg_cleanup,
3340 .mpo_sysvmsg_create = mls_sysvmsg_create,
3341 .mpo_sysvmsg_destroy_label = mls_destroy_label,
3342 .mpo_sysvmsg_init_label = mls_init_label,
3343
3344 .mpo_sysvmsq_check_msgrcv = mls_sysvmsq_check_msgrcv,
3345 .mpo_sysvmsq_check_msgrmid = mls_sysvmsq_check_msgrmid,
3346 .mpo_sysvmsq_check_msqget = mls_sysvmsq_check_msqget,
3347 .mpo_sysvmsq_check_msqsnd = mls_sysvmsq_check_msqsnd,
3348 .mpo_sysvmsq_check_msqrcv = mls_sysvmsq_check_msqrcv,
3349 .mpo_sysvmsq_check_msqctl = mls_sysvmsq_check_msqctl,
3350 .mpo_sysvmsq_cleanup = mls_sysvmsq_cleanup,
3351 .mpo_sysvmsq_destroy_label = mls_destroy_label,
3352 .mpo_sysvmsq_init_label = mls_init_label,
3353 .mpo_sysvmsq_create = mls_sysvmsq_create,
3354
3355 .mpo_sysvsem_check_semctl = mls_sysvsem_check_semctl,
3356 .mpo_sysvsem_check_semget = mls_sysvsem_check_semget,
3357 .mpo_sysvsem_check_semop = mls_sysvsem_check_semop,
3358 .mpo_sysvsem_cleanup = mls_sysvsem_cleanup,
3359 .mpo_sysvsem_create = mls_sysvsem_create,
3360 .mpo_sysvsem_destroy_label = mls_destroy_label,
3361 .mpo_sysvsem_init_label = mls_init_label,
3362
3363 .mpo_sysvshm_check_shmat = mls_sysvshm_check_shmat,
3364 .mpo_sysvshm_check_shmctl = mls_sysvshm_check_shmctl,
3365 .mpo_sysvshm_check_shmget = mls_sysvshm_check_shmget,
3366 .mpo_sysvshm_cleanup = mls_sysvshm_cleanup,
3367 .mpo_sysvshm_create = mls_sysvshm_create,
3368 .mpo_sysvshm_destroy_label = mls_destroy_label,
3369 .mpo_sysvshm_init_label = mls_init_label,
3370
3371 .mpo_system_check_acct = mls_system_check_acct,
3372 .mpo_system_check_auditctl = mls_system_check_auditctl,
3373 .mpo_system_check_swapon = mls_system_check_swapon,
3374
3375 .mpo_vnode_associate_extattr = mls_vnode_associate_extattr,
3376 .mpo_vnode_associate_singlelabel = mls_vnode_associate_singlelabel,
3377 .mpo_vnode_check_access = mls_vnode_check_open,
3378 .mpo_vnode_check_chdir = mls_vnode_check_chdir,
3379 .mpo_vnode_check_chroot = mls_vnode_check_chroot,
3380 .mpo_vnode_check_create = mls_vnode_check_create,
3381 .mpo_vnode_check_deleteacl = mls_vnode_check_deleteacl,
3382 .mpo_vnode_check_deleteextattr = mls_vnode_check_deleteextattr,
3383 .mpo_vnode_check_exec = mls_vnode_check_exec,
3384 .mpo_vnode_check_getacl = mls_vnode_check_getacl,
3385 .mpo_vnode_check_getextattr = mls_vnode_check_getextattr,
3386 .mpo_vnode_check_link = mls_vnode_check_link,
3387 .mpo_vnode_check_listextattr = mls_vnode_check_listextattr,
3388 .mpo_vnode_check_lookup = mls_vnode_check_lookup,
3389 .mpo_vnode_check_mmap = mls_vnode_check_mmap,
3390 .mpo_vnode_check_open = mls_vnode_check_open,
3391 .mpo_vnode_check_poll = mls_vnode_check_poll,
3392 .mpo_vnode_check_read = mls_vnode_check_read,
3393 .mpo_vnode_check_readdir = mls_vnode_check_readdir,
3394 .mpo_vnode_check_readlink = mls_vnode_check_readlink,
3395 .mpo_vnode_check_relabel = mls_vnode_check_relabel,
3396 .mpo_vnode_check_rename_from = mls_vnode_check_rename_from,
3397 .mpo_vnode_check_rename_to = mls_vnode_check_rename_to,
3398 .mpo_vnode_check_revoke = mls_vnode_check_revoke,
3399 .mpo_vnode_check_setacl = mls_vnode_check_setacl,
3400 .mpo_vnode_check_setextattr = mls_vnode_check_setextattr,
3401 .mpo_vnode_check_setflags = mls_vnode_check_setflags,
3402 .mpo_vnode_check_setmode = mls_vnode_check_setmode,
3403 .mpo_vnode_check_setowner = mls_vnode_check_setowner,
3404 .mpo_vnode_check_setutimes = mls_vnode_check_setutimes,
3405 .mpo_vnode_check_stat = mls_vnode_check_stat,
3406 .mpo_vnode_check_unlink = mls_vnode_check_unlink,
3407 .mpo_vnode_check_write = mls_vnode_check_write,
3408 .mpo_vnode_copy_label = mls_copy_label,
3409 .mpo_vnode_create_extattr = mls_vnode_create_extattr,
3410 .mpo_vnode_destroy_label = mls_destroy_label,
3411 .mpo_vnode_externalize_label = mls_externalize_label,
3412 .mpo_vnode_init_label = mls_init_label,
3413 .mpo_vnode_internalize_label = mls_internalize_label,
3414 .mpo_vnode_relabel = mls_vnode_relabel,
3415 .mpo_vnode_setlabel_extattr = mls_vnode_setlabel_extattr,
3416 };
3417
3418 MAC_POLICY_SET(&mls_ops, mac_mls, "TrustedBSD MAC/MLS",
3419 MPC_LOADTIME_FLAG_NOTLATE, &mls_slot);
3420