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