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