]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/security/mac_mls/mac_mls.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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, "pts/", strlen("pts/")) == 0 ||
922             strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
923                 mls_type = MAC_MLS_TYPE_EQUAL;
924         else
925                 mls_type = MAC_MLS_TYPE_LOW;
926         mls_set_effective(mm, mls_type, 0, NULL);
927 }
928
929 static void
930 mls_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
931     struct devfs_dirent *de, struct label *delabel)
932 {
933         struct mac_mls *mm;
934
935         mm = SLOT(delabel);
936         mls_set_effective(mm, MAC_MLS_TYPE_LOW, 0, NULL);
937 }
938
939 static void
940 mls_devfs_create_symlink(struct ucred *cred, struct mount *mp,
941     struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
942     struct label *delabel)
943 {
944         struct mac_mls *source, *dest;
945
946         source = SLOT(cred->cr_label);
947         dest = SLOT(delabel);
948
949         mls_copy_effective(source, dest);
950 }
951
952 static void
953 mls_devfs_update(struct mount *mp, struct devfs_dirent *de,
954     struct label *delabel, struct vnode *vp, struct label *vplabel)
955 {
956         struct mac_mls *source, *dest;
957
958         source = SLOT(vplabel);
959         dest = SLOT(delabel);
960
961         mls_copy_effective(source, dest);
962 }
963
964 static void
965 mls_devfs_vnode_associate(struct mount *mp, struct label *mplabel,
966     struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
967     struct label *vplabel)
968 {
969         struct mac_mls *source, *dest;
970
971         source = SLOT(delabel);
972         dest = SLOT(vplabel);
973
974         mls_copy_effective(source, dest);
975 }
976
977 static int
978 mls_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
979     struct label *ifplabel, struct label *newlabel)
980 {
981         struct mac_mls *subj, *new;
982         int error;
983
984         subj = SLOT(cred->cr_label);
985         new = SLOT(newlabel);
986
987         /*
988          * If there is an MLS label update for the interface, it may be an
989          * update of effective, range, or both.
990          */
991         error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
992         if (error)
993                 return (error);
994
995         /*
996          * Relabeling network interfaces requires MLS privilege.
997          */
998         return (mls_subject_privileged(subj));
999 }
1000
1001 static int
1002 mls_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
1003     struct mbuf *m, struct label *mlabel)
1004 {
1005         struct mac_mls *p, *i;
1006
1007         if (!mls_enabled)
1008                 return (0);
1009
1010         p = SLOT(mlabel);
1011         i = SLOT(ifplabel);
1012
1013         return (mls_effective_in_range(p, i) ? 0 : EACCES);
1014 }
1015
1016 static void
1017 mls_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
1018 {
1019         struct mac_mls *dest;
1020         int type;
1021
1022         dest = SLOT(ifplabel);
1023
1024         if (ifp->if_type == IFT_LOOP)
1025                 type = MAC_MLS_TYPE_EQUAL;
1026         else
1027                 type = MAC_MLS_TYPE_LOW;
1028
1029         mls_set_effective(dest, type, 0, NULL);
1030         mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1031 }
1032
1033 static void
1034 mls_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1035     struct mbuf *m, struct label *mlabel)
1036 {
1037         struct mac_mls *source, *dest;
1038
1039         source = SLOT(ifplabel);
1040         dest = SLOT(mlabel);
1041
1042         mls_copy_effective(source, dest);
1043 }
1044
1045 static void
1046 mls_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1047     struct label *ifplabel, struct label *newlabel)
1048 {
1049         struct mac_mls *source, *dest;
1050
1051         source = SLOT(newlabel);
1052         dest = SLOT(ifplabel);
1053
1054         mls_copy(source, dest);
1055 }
1056
1057 static int
1058 mls_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1059     struct mbuf *m, struct label *mlabel)
1060 {
1061         struct mac_mls *p, *i;
1062
1063         if (!mls_enabled)
1064                 return (0);
1065
1066         p = SLOT(mlabel);
1067         i = SLOT(inplabel);
1068
1069         return (mls_equal_effective(p, i) ? 0 : EACCES);
1070 }
1071
1072 static int
1073 mls_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
1074     struct label *inplabel)
1075 {
1076         struct mac_mls *subj, *obj;
1077
1078         if (!mls_enabled)
1079                 return (0);
1080
1081         subj = SLOT(cred->cr_label);
1082         obj = SLOT(inplabel);
1083
1084         if (!mls_dominate_effective(subj, obj))
1085                 return (ENOENT);
1086
1087         return (0);
1088 }
1089
1090 static void
1091 mls_inpcb_create(struct socket *so, struct label *solabel, struct inpcb *inp,
1092     struct label *inplabel)
1093 {
1094         struct mac_mls *source, *dest;
1095
1096         source = SLOT(solabel);
1097         dest = SLOT(inplabel);
1098
1099         mls_copy_effective(source, dest);
1100 }
1101
1102 static void
1103 mls_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1104     struct mbuf *m, struct label *mlabel)
1105 {
1106         struct mac_mls *source, *dest;
1107
1108         source = SLOT(inplabel);
1109         dest = SLOT(mlabel);
1110
1111         mls_copy_effective(source, dest);
1112 }
1113
1114 static void
1115 mls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1116     struct inpcb *inp, struct label *inplabel)
1117 {
1118         struct mac_mls *source, *dest;
1119
1120         SOCK_LOCK_ASSERT(so);
1121
1122         source = SLOT(solabel);
1123         dest = SLOT(inplabel);
1124
1125         mls_copy(source, dest);
1126 }
1127
1128 static void
1129 mls_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1130     struct label *q6label)
1131 {
1132         struct mac_mls *source, *dest;
1133
1134         source = SLOT(mlabel);
1135         dest = SLOT(q6label);
1136
1137         mls_copy_effective(source, dest);
1138 }
1139
1140 static int
1141 mls_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1142     struct label *q6label)
1143 {
1144         struct mac_mls *a, *b;
1145
1146         a = SLOT(q6label);
1147         b = SLOT(mlabel);
1148
1149         return (mls_equal_effective(a, b));
1150 }
1151
1152 static void
1153 mls_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1154     struct label *mlabel)
1155 {
1156         struct mac_mls *source, *dest;
1157
1158         source = SLOT(q6label);
1159         dest = SLOT(mlabel);
1160
1161         /* Just use the head, since we require them all to match. */
1162         mls_copy_effective(source, dest);
1163 }
1164
1165 static void
1166 mls_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1167     struct label *q6label)
1168 {
1169
1170         /* NOOP: we only accept matching labels, so no need to update */
1171 }
1172
1173 static void
1174 mls_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1175     struct label *qlabel)
1176 {
1177         struct mac_mls *source, *dest;
1178
1179         source = SLOT(mlabel);
1180         dest = SLOT(qlabel);
1181
1182         mls_copy_effective(source, dest);
1183 }
1184
1185 static int
1186 mls_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1187     struct label *qlabel)
1188 {
1189         struct mac_mls *a, *b;
1190
1191         a = SLOT(qlabel);
1192         b = SLOT(mlabel);
1193
1194         return (mls_equal_effective(a, b));
1195 }
1196
1197 static void
1198 mls_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1199     struct label *mlabel)
1200 {
1201         struct mac_mls *source, *dest;
1202
1203         source = SLOT(qlabel);
1204         dest = SLOT(mlabel);
1205
1206         /* Just use the head, since we require them all to match. */
1207         mls_copy_effective(source, dest);
1208 }
1209
1210 static void
1211 mls_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1212     struct label *qlabel)
1213 {
1214
1215         /* NOOP: we only accept matching labels, so no need to update */
1216 }
1217
1218 static int
1219 mls_mount_check_stat(struct ucred *cred, struct mount *mp,
1220     struct label *mntlabel)
1221 {
1222         struct mac_mls *subj, *obj;
1223
1224         if (!mls_enabled)
1225                 return (0);
1226
1227         subj = SLOT(cred->cr_label);
1228         obj = SLOT(mntlabel);
1229
1230         if (!mls_dominate_effective(subj, obj))
1231                 return (EACCES);
1232
1233         return (0);
1234 }
1235
1236 static void
1237 mls_mount_create(struct ucred *cred, struct mount *mp, struct label *mplabel)
1238 {
1239         struct mac_mls *source, *dest;
1240
1241         source = SLOT(cred->cr_label);
1242         dest = SLOT(mplabel);
1243
1244         mls_copy_effective(source, dest);
1245 }
1246
1247 static void
1248 mls_netatalk_aarp_send(struct ifnet *ifp, struct label *ifplabel,
1249     struct mbuf *m, struct label *mlabel)
1250 {
1251         struct mac_mls *dest;
1252
1253         dest = SLOT(mlabel);
1254
1255         mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1256 }
1257
1258 static void
1259 mls_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1260     struct mbuf *m, struct label *mlabel)
1261 {
1262         struct mac_mls *dest;
1263
1264         dest = SLOT(mlabel);
1265
1266         mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1267 }
1268
1269 static void
1270 mls_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1271     struct mbuf *msend, struct label *msendlabel)
1272 {
1273         struct mac_mls *source, *dest;
1274
1275         source = SLOT(mrecvlabel);
1276         dest = SLOT(msendlabel);
1277
1278         mls_copy_effective(source, dest);
1279 }
1280
1281 static void
1282 mls_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1283 {
1284         struct mac_mls *dest;
1285
1286         dest = SLOT(mlabel);
1287
1288         /* XXX: where is the label for the firewall really comming from? */
1289         mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1290 }
1291
1292 static void
1293 mls_netinet_fragment(struct mbuf *m, struct label *mlabel, struct mbuf *frag,
1294     struct label *fraglabel)
1295 {
1296         struct mac_mls *source, *dest;
1297
1298         source = SLOT(mlabel);
1299         dest = SLOT(fraglabel);
1300
1301         mls_copy_effective(source, dest);
1302 }
1303
1304 static void
1305 mls_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1306     struct mbuf *msend, struct label *msendlabel)
1307 {
1308         struct mac_mls *source, *dest;
1309
1310         source = SLOT(mrecvlabel);
1311         dest = SLOT(msendlabel);
1312
1313         mls_copy_effective(source, dest);
1314 }
1315
1316 static void
1317 mls_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1318     struct mbuf *m, struct label *mlabel)
1319 {
1320         struct mac_mls *dest;
1321
1322         dest = SLOT(mlabel);
1323
1324         mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1325 }
1326
1327 static void
1328 mls_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1329     struct mbuf *m, struct label *mlabel)
1330 {
1331         struct mac_mls *dest;
1332
1333         dest = SLOT(mlabel);
1334
1335         mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1336 }
1337
1338 static int
1339 mls_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1340     struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1341 {
1342
1343         if (!mls_enabled)
1344                 return (0);
1345
1346         /* XXX: This will be implemented soon... */
1347
1348         return (0);
1349 }
1350
1351 static int
1352 mls_pipe_check_poll(struct ucred *cred, struct pipepair *pp,
1353     struct label *pplabel)
1354 {
1355         struct mac_mls *subj, *obj;
1356
1357         if (!mls_enabled)
1358                 return (0);
1359
1360         subj = SLOT(cred->cr_label);
1361         obj = SLOT(pplabel);
1362
1363         if (!mls_dominate_effective(subj, obj))
1364                 return (EACCES);
1365
1366         return (0);
1367 }
1368
1369 static int
1370 mls_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1371     struct label *pplabel)
1372 {
1373         struct mac_mls *subj, *obj;
1374
1375         if (!mls_enabled)
1376                 return (0);
1377
1378         subj = SLOT(cred->cr_label);
1379         obj = SLOT(pplabel);
1380
1381         if (!mls_dominate_effective(subj, obj))
1382                 return (EACCES);
1383
1384         return (0);
1385 }
1386
1387 static int
1388 mls_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1389     struct label *pplabel, struct label *newlabel)
1390 {
1391         struct mac_mls *subj, *obj, *new;
1392         int error;
1393
1394         new = SLOT(newlabel);
1395         subj = SLOT(cred->cr_label);
1396         obj = SLOT(pplabel);
1397
1398         /*
1399          * If there is an MLS label update for a pipe, it must be a effective
1400          * update.
1401          */
1402         error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1403         if (error)
1404                 return (error);
1405
1406         /*
1407          * To perform a relabel of a pipe (MLS label or not), MLS must
1408          * authorize the relabel.
1409          */
1410         if (!mls_effective_in_range(obj, subj))
1411                 return (EPERM);
1412
1413         /*
1414          * If the MLS label is to be changed, authorize as appropriate.
1415          */
1416         if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1417                 /*
1418                  * To change the MLS label on a pipe, the new pipe label must
1419                  * be in the subject range.
1420                  */
1421                 if (!mls_effective_in_range(new, subj))
1422                         return (EPERM);
1423
1424                 /*
1425                  * To change the MLS label on a pipe to be EQUAL, the subject
1426                  * must have appropriate privilege.
1427                  */
1428                 if (mls_contains_equal(new)) {
1429                         error = mls_subject_privileged(subj);
1430                         if (error)
1431                                 return (error);
1432                 }
1433         }
1434
1435         return (0);
1436 }
1437
1438 static int
1439 mls_pipe_check_stat(struct ucred *cred, struct pipepair *pp,
1440     struct label *pplabel)
1441 {
1442         struct mac_mls *subj, *obj;
1443
1444         if (!mls_enabled)
1445                 return (0);
1446
1447         subj = SLOT(cred->cr_label);
1448         obj = SLOT(pplabel);
1449
1450         if (!mls_dominate_effective(subj, obj))
1451                 return (EACCES);
1452
1453         return (0);
1454 }
1455
1456 static int
1457 mls_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1458     struct label *pplabel)
1459 {
1460         struct mac_mls *subj, *obj;
1461
1462         if (!mls_enabled)
1463                 return (0);
1464
1465         subj = SLOT(cred->cr_label);
1466         obj = SLOT(pplabel);
1467
1468         if (!mls_dominate_effective(obj, subj))
1469                 return (EACCES);
1470
1471         return (0);
1472 }
1473
1474 static void
1475 mls_pipe_create(struct ucred *cred, struct pipepair *pp,
1476     struct label *pplabel)
1477 {
1478         struct mac_mls *source, *dest;
1479
1480         source = SLOT(cred->cr_label);
1481         dest = SLOT(pplabel);
1482
1483         mls_copy_effective(source, dest);
1484 }
1485
1486 static void
1487 mls_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1488     struct label *pplabel, struct label *newlabel)
1489 {
1490         struct mac_mls *source, *dest;
1491
1492         source = SLOT(newlabel);
1493         dest = SLOT(pplabel);
1494
1495         mls_copy(source, dest);
1496 }
1497
1498 static int
1499 mls_posixsem_check_openunlink(struct ucred *cred, struct ksem *ks,
1500     struct label *kslabel)
1501 {
1502         struct mac_mls *subj, *obj;
1503
1504         if (!mls_enabled)
1505                 return (0);
1506
1507         subj = SLOT(cred->cr_label);
1508         obj = SLOT(kslabel);
1509
1510         if (!mls_dominate_effective(obj, subj))
1511                 return (EACCES);
1512
1513         return (0);
1514 }
1515
1516 static int
1517 mls_posixsem_check_rdonly(struct ucred *active_cred, struct ucred *file_cred,
1518     struct ksem *ks, struct label *kslabel)
1519 {
1520         struct mac_mls *subj, *obj;
1521
1522         if (!mls_enabled)
1523                 return (0);
1524
1525         subj = SLOT(active_cred->cr_label);
1526         obj = SLOT(kslabel);
1527
1528         if (!mls_dominate_effective(subj, obj))
1529                 return (EACCES);
1530
1531         return (0);
1532 }
1533
1534 static int
1535 mls_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred,
1536     struct ksem *ks, struct label *kslabel)
1537 {
1538         struct mac_mls *subj, *obj;
1539
1540         if (!mls_enabled)
1541                 return (0);
1542
1543         subj = SLOT(active_cred->cr_label);
1544         obj = SLOT(kslabel);
1545
1546         if (!mls_dominate_effective(obj, subj))
1547                 return (EACCES);
1548
1549         return (0);
1550 }
1551
1552 static void
1553 mls_posixsem_create(struct ucred *cred, struct ksem *ks,
1554     struct label *kslabel)
1555 {
1556         struct mac_mls *source, *dest;
1557
1558         source = SLOT(cred->cr_label);
1559         dest = SLOT(kslabel);
1560
1561         mls_copy_effective(source, dest);
1562 }
1563
1564 static int
1565 mls_proc_check_debug(struct ucred *cred, struct proc *p)
1566 {
1567         struct mac_mls *subj, *obj;
1568
1569         if (!mls_enabled)
1570                 return (0);
1571
1572         subj = SLOT(cred->cr_label);
1573         obj = SLOT(p->p_ucred->cr_label);
1574
1575         /* XXX: range checks */
1576         if (!mls_dominate_effective(subj, obj))
1577                 return (ESRCH);
1578         if (!mls_dominate_effective(obj, subj))
1579                 return (EACCES);
1580
1581         return (0);
1582 }
1583
1584 static int
1585 mls_proc_check_sched(struct ucred *cred, struct proc *p)
1586 {
1587         struct mac_mls *subj, *obj;
1588
1589         if (!mls_enabled)
1590                 return (0);
1591
1592         subj = SLOT(cred->cr_label);
1593         obj = SLOT(p->p_ucred->cr_label);
1594
1595         /* XXX: range checks */
1596         if (!mls_dominate_effective(subj, obj))
1597                 return (ESRCH);
1598         if (!mls_dominate_effective(obj, subj))
1599                 return (EACCES);
1600
1601         return (0);
1602 }
1603
1604 static int
1605 mls_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1606 {
1607         struct mac_mls *subj, *obj;
1608
1609         if (!mls_enabled)
1610                 return (0);
1611
1612         subj = SLOT(cred->cr_label);
1613         obj = SLOT(p->p_ucred->cr_label);
1614
1615         /* XXX: range checks */
1616         if (!mls_dominate_effective(subj, obj))
1617                 return (ESRCH);
1618         if (!mls_dominate_effective(obj, subj))
1619                 return (EACCES);
1620
1621         return (0);
1622 }
1623
1624 static int
1625 mls_socket_check_deliver(struct socket *so, struct label *solabel,
1626     struct mbuf *m, struct label *mlabel)
1627 {
1628         struct mac_mls *p, *s;
1629         int error;
1630
1631         if (!mls_enabled)
1632                 return (0);
1633
1634         p = SLOT(mlabel);
1635         s = SLOT(solabel);
1636
1637         SOCK_LOCK(so);
1638         error = mls_equal_effective(p, s) ? 0 : EACCES;
1639         SOCK_UNLOCK(so);
1640
1641         return (error);
1642 }
1643
1644 static int
1645 mls_socket_check_relabel(struct ucred *cred, struct socket *so,
1646     struct label *solabel, struct label *newlabel)
1647 {
1648         struct mac_mls *subj, *obj, *new;
1649         int error;
1650
1651         SOCK_LOCK_ASSERT(so);
1652
1653         new = SLOT(newlabel);
1654         subj = SLOT(cred->cr_label);
1655         obj = SLOT(solabel);
1656
1657         /*
1658          * If there is an MLS label update for the socket, it may be an
1659          * update of effective.
1660          */
1661         error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1662         if (error)
1663                 return (error);
1664
1665         /*
1666          * To relabel a socket, the old socket effective must be in the
1667          * subject range.
1668          */
1669         if (!mls_effective_in_range(obj, subj))
1670                 return (EPERM);
1671
1672         /*
1673          * If the MLS label is to be changed, authorize as appropriate.
1674          */
1675         if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1676                 /*
1677                  * To relabel a socket, the new socket effective must be in
1678                  * the subject range.
1679                  */
1680                 if (!mls_effective_in_range(new, subj))
1681                         return (EPERM);
1682
1683                 /*
1684                  * To change the MLS label on the socket to contain EQUAL,
1685                  * the subject must have appropriate privilege.
1686                  */
1687                 if (mls_contains_equal(new)) {
1688                         error = mls_subject_privileged(subj);
1689                         if (error)
1690                                 return (error);
1691                 }
1692         }
1693
1694         return (0);
1695 }
1696
1697 static int
1698 mls_socket_check_visible(struct ucred *cred, struct socket *so,
1699     struct label *solabel)
1700 {
1701         struct mac_mls *subj, *obj;
1702
1703         if (!mls_enabled)
1704                 return (0);
1705
1706         subj = SLOT(cred->cr_label);
1707         obj = SLOT(solabel);
1708
1709         SOCK_LOCK(so);
1710         if (!mls_dominate_effective(subj, obj)) {
1711                 SOCK_UNLOCK(so);
1712                 return (ENOENT);
1713         }
1714         SOCK_UNLOCK(so);
1715
1716         return (0);
1717 }
1718
1719 static void
1720 mls_socket_create(struct ucred *cred, struct socket *so,
1721     struct label *solabel)
1722 {
1723         struct mac_mls *source, *dest;
1724
1725         source = SLOT(cred->cr_label);
1726         dest = SLOT(solabel);
1727
1728         mls_copy_effective(source, dest);
1729 }
1730
1731 static void
1732 mls_socket_create_mbuf(struct socket *so, struct label *solabel,
1733     struct mbuf *m, struct label *mlabel)
1734 {
1735         struct mac_mls *source, *dest;
1736
1737         source = SLOT(solabel);
1738         dest = SLOT(mlabel);
1739
1740         SOCK_LOCK(so);
1741         mls_copy_effective(source, dest);
1742         SOCK_UNLOCK(so);
1743 }
1744
1745 static void
1746 mls_socket_newconn(struct socket *oldso, struct label *oldsolabel,
1747     struct socket *newso, struct label *newsolabel)
1748 {
1749         struct mac_mls source, *dest;
1750
1751         SOCK_LOCK(oldso);
1752         source = *SLOT(oldsolabel);
1753         SOCK_UNLOCK(oldso);
1754
1755         dest = SLOT(newsolabel);
1756
1757         SOCK_LOCK(newso);
1758         mls_copy_effective(&source, dest);
1759         SOCK_UNLOCK(newso);
1760 }
1761
1762 static void
1763 mls_socket_relabel(struct ucred *cred, struct socket *so,
1764     struct label *solabel, struct label *newlabel)
1765 {
1766         struct mac_mls *source, *dest;
1767
1768         SOCK_LOCK_ASSERT(so);
1769
1770         source = SLOT(newlabel);
1771         dest = SLOT(solabel);
1772
1773         mls_copy(source, dest);
1774 }
1775
1776 static void
1777 mls_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
1778     struct socket *so, struct label *sopeerlabel)
1779 {
1780         struct mac_mls *source, *dest;
1781
1782         source = SLOT(mlabel);
1783         dest = SLOT(sopeerlabel);
1784
1785         SOCK_LOCK(so);
1786         mls_copy_effective(source, dest);
1787         SOCK_UNLOCK(so);
1788 }
1789
1790 static void
1791 mls_socketpeer_set_from_socket(struct socket *oldso,
1792     struct label *oldsolabel, struct socket *newso,
1793     struct label *newsopeerlabel)
1794 {
1795         struct mac_mls source, *dest;
1796
1797         SOCK_LOCK(oldso);
1798         source = *SLOT(oldsolabel);
1799         SOCK_UNLOCK(oldso);
1800
1801         dest = SLOT(newsopeerlabel);
1802
1803         SOCK_LOCK(newso);
1804         mls_copy_effective(&source, dest);
1805         SOCK_UNLOCK(newso);
1806 }
1807
1808 static void
1809 mls_syncache_create(struct label *label, struct inpcb *inp)
1810 {
1811         struct mac_mls *source, *dest;
1812
1813         source = SLOT(inp->inp_label);
1814         dest = SLOT(label);
1815
1816         mls_copy_effective(source, dest);
1817 }
1818
1819 static void
1820 mls_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
1821     struct label *mlabel)
1822 {
1823         struct mac_mls *source, *dest;
1824
1825         source = SLOT(sc_label);
1826         dest = SLOT(mlabel);
1827
1828         mls_copy_effective(source, dest);
1829 }
1830
1831 static int
1832 mls_system_check_acct(struct ucred *cred, struct vnode *vp,
1833     struct label *vplabel)
1834 {
1835         struct mac_mls *subj, *obj;
1836
1837         if (!mls_enabled)
1838                 return (0);
1839
1840         subj = SLOT(cred->cr_label);
1841         obj = SLOT(vplabel);
1842
1843         if (!mls_dominate_effective(obj, subj) ||
1844             !mls_dominate_effective(subj, obj))
1845                 return (EACCES);
1846
1847         return (0);
1848 }
1849
1850 static int
1851 mls_system_check_auditctl(struct ucred *cred, struct vnode *vp,
1852     struct label *vplabel)
1853 {
1854         struct mac_mls *subj, *obj;
1855
1856         if (!mls_enabled)
1857                 return (0);
1858
1859         subj = SLOT(cred->cr_label);
1860         obj = SLOT(vplabel);
1861
1862         if (!mls_dominate_effective(obj, subj) ||
1863             !mls_dominate_effective(subj, obj))
1864                 return (EACCES);
1865
1866         return (0);
1867 }
1868
1869 static int
1870 mls_system_check_swapon(struct ucred *cred, struct vnode *vp,
1871     struct label *vplabel)
1872 {
1873         struct mac_mls *subj, *obj;
1874
1875         if (!mls_enabled)
1876                 return (0);
1877
1878         subj = SLOT(cred->cr_label);
1879         obj = SLOT(vplabel);
1880
1881         if (!mls_dominate_effective(obj, subj) ||
1882             !mls_dominate_effective(subj, obj))
1883                 return (EACCES);
1884
1885         return (0);
1886 }
1887
1888 static void
1889 mls_sysvmsg_cleanup(struct label *msglabel)
1890 {
1891
1892         bzero(SLOT(msglabel), sizeof(struct mac_mls));
1893 }
1894
1895 static void
1896 mls_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
1897     struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
1898 {
1899         struct mac_mls *source, *dest;
1900
1901         /* Ignore the msgq label. */
1902         source = SLOT(cred->cr_label);
1903         dest = SLOT(msglabel);
1904
1905         mls_copy_effective(source, dest);
1906 }
1907
1908 static int
1909 mls_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr,
1910     struct label *msglabel)
1911 {
1912         struct mac_mls *subj, *obj;
1913
1914         if (!mls_enabled)
1915                 return (0);
1916
1917         subj = SLOT(cred->cr_label);
1918         obj = SLOT(msglabel);
1919
1920         if (!mls_dominate_effective(subj, obj))
1921                 return (EACCES);
1922
1923         return (0);
1924 }
1925
1926 static int
1927 mls_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr,
1928     struct label *msglabel)
1929 {
1930         struct mac_mls *subj, *obj;
1931
1932         if (!mls_enabled)
1933                 return (0);
1934
1935         subj = SLOT(cred->cr_label);
1936         obj = SLOT(msglabel);
1937
1938         if (!mls_dominate_effective(obj, subj))
1939                 return (EACCES);
1940
1941         return (0);
1942 }
1943
1944 static int
1945 mls_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
1946     struct label *msqklabel)
1947 {
1948         struct mac_mls *subj, *obj;
1949
1950         if (!mls_enabled)
1951                 return (0);
1952
1953         subj = SLOT(cred->cr_label);
1954         obj = SLOT(msqklabel);
1955
1956         if (!mls_dominate_effective(subj, obj))
1957                 return (EACCES);
1958
1959         return (0);
1960 }
1961
1962 static int
1963 mls_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
1964     struct label *msqklabel)
1965 {
1966         struct mac_mls *subj, *obj;
1967
1968         if (!mls_enabled)
1969                 return (0);
1970
1971         subj = SLOT(cred->cr_label);
1972         obj = SLOT(msqklabel);
1973
1974         if (!mls_dominate_effective(obj, subj))
1975                 return (EACCES);
1976
1977         return (0);
1978 }
1979
1980 static int
1981 mls_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
1982     struct label *msqklabel)
1983 {
1984         struct mac_mls *subj, *obj;
1985
1986         if (!mls_enabled)
1987                 return (0);
1988
1989         subj = SLOT(cred->cr_label);
1990         obj = SLOT(msqklabel);
1991
1992         if (!mls_dominate_effective(subj, obj))
1993                 return (EACCES);
1994
1995         return (0);
1996 }
1997
1998 static int
1999 mls_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
2000     struct label *msqklabel, int cmd)
2001 {
2002         struct mac_mls *subj, *obj;
2003
2004         if (!mls_enabled)
2005                 return (0);
2006
2007         subj = SLOT(cred->cr_label);
2008         obj = SLOT(msqklabel);
2009
2010         switch(cmd) {
2011         case IPC_RMID:
2012         case IPC_SET:
2013                 if (!mls_dominate_effective(obj, subj))
2014                         return (EACCES);
2015                 break;
2016
2017         case IPC_STAT:
2018                 if (!mls_dominate_effective(subj, obj))
2019                         return (EACCES);
2020                 break;
2021
2022         default:
2023                 return (EACCES);
2024         }
2025
2026         return (0);
2027 }
2028
2029 static void
2030 mls_sysvmsq_cleanup(struct label *msqlabel)
2031 {
2032
2033         bzero(SLOT(msqlabel), sizeof(struct mac_mls));
2034 }
2035
2036 static void
2037 mls_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2038     struct label *msqlabel)
2039 {
2040         struct mac_mls *source, *dest;
2041
2042         source = SLOT(cred->cr_label);
2043         dest = SLOT(msqlabel);
2044
2045         mls_copy_effective(source, dest);
2046 }
2047
2048 static int
2049 mls_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
2050     struct label *semaklabel, int cmd)
2051 {
2052         struct mac_mls *subj, *obj;
2053
2054         if (!mls_enabled)
2055                 return (0);
2056
2057         subj = SLOT(cred->cr_label);
2058         obj = SLOT(semaklabel);
2059
2060         switch(cmd) {
2061         case IPC_RMID:
2062         case IPC_SET:
2063         case SETVAL:
2064         case SETALL:
2065                 if (!mls_dominate_effective(obj, subj))
2066                         return (EACCES);
2067                 break;
2068
2069         case IPC_STAT:
2070         case GETVAL:
2071         case GETPID:
2072         case GETNCNT:
2073         case GETZCNT:
2074         case GETALL:
2075                 if (!mls_dominate_effective(subj, obj))
2076                         return (EACCES);
2077                 break;
2078
2079         default:
2080                 return (EACCES);
2081         }
2082
2083         return (0);
2084 }
2085
2086 static int
2087 mls_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr,
2088     struct label *semaklabel)
2089 {
2090         struct mac_mls *subj, *obj;
2091
2092         if (!mls_enabled)
2093                 return (0);
2094
2095         subj = SLOT(cred->cr_label);
2096         obj = SLOT(semaklabel);
2097
2098         if (!mls_dominate_effective(subj, obj))
2099                 return (EACCES);
2100
2101         return (0);
2102 }
2103
2104 static int
2105 mls_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
2106     struct label *semaklabel, size_t accesstype)
2107 {
2108         struct mac_mls *subj, *obj;
2109
2110         if (!mls_enabled)
2111                 return (0);
2112
2113         subj = SLOT(cred->cr_label);
2114         obj = SLOT(semaklabel);
2115
2116         if( accesstype & SEM_R )
2117                 if (!mls_dominate_effective(subj, obj))
2118                         return (EACCES);
2119
2120         if( accesstype & SEM_A )
2121                 if (!mls_dominate_effective(obj, subj))
2122                         return (EACCES);
2123
2124         return (0);
2125 }
2126
2127 static void
2128 mls_sysvsem_cleanup(struct label *semalabel)
2129 {
2130
2131         bzero(SLOT(semalabel), sizeof(struct mac_mls));
2132 }
2133
2134 static void
2135 mls_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr,
2136     struct label *semalabel)
2137 {
2138         struct mac_mls *source, *dest;
2139
2140         source = SLOT(cred->cr_label);
2141         dest = SLOT(semalabel);
2142
2143         mls_copy_effective(source, dest);
2144 }
2145
2146 static int
2147 mls_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
2148     struct label *shmseglabel, int shmflg)
2149 {
2150         struct mac_mls *subj, *obj;
2151
2152         if (!mls_enabled)
2153                 return (0);
2154
2155         subj = SLOT(cred->cr_label);
2156         obj = SLOT(shmseglabel);
2157
2158         if (!mls_dominate_effective(subj, obj))
2159                 return (EACCES);
2160         if ((shmflg & SHM_RDONLY) == 0) {
2161                 if (!mls_dominate_effective(obj, subj))
2162                         return (EACCES);
2163         }
2164         
2165         return (0);
2166 }
2167
2168 static int
2169 mls_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
2170     struct label *shmseglabel, int cmd)
2171 {
2172         struct mac_mls *subj, *obj;
2173
2174         if (!mls_enabled)
2175                 return (0);
2176
2177         subj = SLOT(cred->cr_label);
2178         obj = SLOT(shmseglabel);
2179
2180         switch(cmd) {
2181         case IPC_RMID:
2182         case IPC_SET:
2183                 if (!mls_dominate_effective(obj, subj))
2184                         return (EACCES);
2185                 break;
2186
2187         case IPC_STAT:
2188         case SHM_STAT:
2189                 if (!mls_dominate_effective(subj, obj))
2190                         return (EACCES);
2191                 break;
2192
2193         default:
2194                 return (EACCES);
2195         }
2196
2197         return (0);
2198 }
2199
2200 static int
2201 mls_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
2202     struct label *shmseglabel, int shmflg)
2203 {
2204         struct mac_mls *subj, *obj;
2205
2206         if (!mls_enabled)
2207                 return (0);
2208
2209         subj = SLOT(cred->cr_label);
2210         obj = SLOT(shmseglabel);
2211
2212         if (!mls_dominate_effective(obj, subj))
2213                 return (EACCES);
2214
2215         return (0);
2216 }
2217
2218 static void
2219 mls_sysvshm_cleanup(struct label *shmlabel)
2220 {
2221
2222         bzero(SLOT(shmlabel), sizeof(struct mac_mls));
2223 }
2224
2225 static void
2226 mls_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr,
2227     struct label *shmlabel)
2228 {
2229         struct mac_mls *source, *dest;
2230
2231         source = SLOT(cred->cr_label);
2232         dest = SLOT(shmlabel);
2233
2234         mls_copy_effective(source, dest);
2235 }
2236
2237 static int
2238 mls_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2239     struct vnode *vp, struct label *vplabel)
2240 {
2241         struct mac_mls mm_temp, *source, *dest;
2242         int buflen, error;
2243
2244         source = SLOT(mplabel);
2245         dest = SLOT(vplabel);
2246
2247         buflen = sizeof(mm_temp);
2248         bzero(&mm_temp, buflen);
2249
2250         error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2251             MAC_MLS_EXTATTR_NAME, &buflen, (char *) &mm_temp, curthread);
2252         if (error == ENOATTR || error == EOPNOTSUPP) {
2253                 /* Fall back to the mntlabel. */
2254                 mls_copy_effective(source, dest);
2255                 return (0);
2256         } else if (error)
2257                 return (error);
2258
2259         if (buflen != sizeof(mm_temp)) {
2260                 printf("mls_vnode_associate_extattr: bad size %d\n", buflen);
2261                 return (EPERM);
2262         }
2263         if (mls_valid(&mm_temp) != 0) {
2264                 printf("mls_vnode_associate_extattr: invalid\n");
2265                 return (EPERM);
2266         }
2267         if ((mm_temp.mm_flags & MAC_MLS_FLAGS_BOTH) !=
2268             MAC_MLS_FLAG_EFFECTIVE) {
2269                 printf("mls_associated_vnode_extattr: not effective\n");
2270                 return (EPERM);
2271         }
2272
2273         mls_copy_effective(&mm_temp, dest);
2274         return (0);
2275 }
2276
2277 static void
2278 mls_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2279     struct vnode *vp, struct label *vplabel)
2280 {
2281         struct mac_mls *source, *dest;
2282
2283         source = SLOT(mplabel);
2284         dest = SLOT(vplabel);
2285
2286         mls_copy_effective(source, dest);
2287 }
2288
2289 static int
2290 mls_vnode_check_chdir(struct ucred *cred, struct vnode *dvp,
2291     struct label *dvplabel)
2292 {
2293         struct mac_mls *subj, *obj;
2294
2295         if (!mls_enabled)
2296                 return (0);
2297
2298         subj = SLOT(cred->cr_label);
2299         obj = SLOT(dvplabel);
2300
2301         if (!mls_dominate_effective(subj, obj))
2302                 return (EACCES);
2303
2304         return (0);
2305 }
2306
2307 static int
2308 mls_vnode_check_chroot(struct ucred *cred, struct vnode *dvp,
2309     struct label *dvplabel)
2310 {
2311         struct mac_mls *subj, *obj;
2312
2313         if (!mls_enabled)
2314                 return (0);
2315
2316         subj = SLOT(cred->cr_label);
2317         obj = SLOT(dvplabel);
2318
2319         if (!mls_dominate_effective(subj, obj))
2320                 return (EACCES);
2321
2322         return (0);
2323 }
2324
2325 static int
2326 mls_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2327     struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2328 {
2329         struct mac_mls *subj, *obj;
2330
2331         if (!mls_enabled)
2332                 return (0);
2333
2334         subj = SLOT(cred->cr_label);
2335         obj = SLOT(dvplabel);
2336
2337         if (!mls_dominate_effective(obj, subj))
2338                 return (EACCES);
2339
2340         return (0);
2341 }
2342
2343 static int
2344 mls_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2345     struct label *vplabel, acl_type_t type)
2346 {
2347         struct mac_mls *subj, *obj;
2348
2349         if (!mls_enabled)
2350                 return (0);
2351
2352         subj = SLOT(cred->cr_label);
2353         obj = SLOT(vplabel);
2354
2355         if (!mls_dominate_effective(obj, subj))
2356                 return (EACCES);
2357
2358         return (0);
2359 }
2360
2361 static int
2362 mls_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
2363     struct label *vplabel, int attrnamespace, const char *name)
2364 {
2365         struct mac_mls *subj, *obj;
2366
2367         if (!mls_enabled)
2368                 return (0);
2369
2370         subj = SLOT(cred->cr_label);
2371         obj = SLOT(vplabel);
2372
2373         if (!mls_dominate_effective(obj, subj))
2374                 return (EACCES);
2375
2376         return (0);
2377 }
2378
2379 static int
2380 mls_vnode_check_exec(struct ucred *cred, struct vnode *vp,
2381     struct label *vplabel, struct image_params *imgp,
2382     struct label *execlabel)
2383 {
2384         struct mac_mls *subj, *obj, *exec;
2385         int error;
2386
2387         if (execlabel != NULL) {
2388                 /*
2389                  * We currently don't permit labels to be changed at
2390                  * exec-time as part of MLS, so disallow non-NULL MLS label
2391                  * elements in the execlabel.
2392                  */
2393                 exec = SLOT(execlabel);
2394                 error = mls_atmostflags(exec, 0);
2395                 if (error)
2396                         return (error);
2397         }
2398
2399         if (!mls_enabled)
2400                 return (0);
2401
2402         subj = SLOT(cred->cr_label);
2403         obj = SLOT(vplabel);
2404
2405         if (!mls_dominate_effective(subj, obj))
2406                 return (EACCES);
2407
2408         return (0);
2409 }
2410
2411 static int
2412 mls_vnode_check_getacl(struct ucred *cred, struct vnode *vp,
2413     struct label *vplabel, acl_type_t type)
2414 {
2415         struct mac_mls *subj, *obj;
2416
2417         if (!mls_enabled)
2418                 return (0);
2419
2420         subj = SLOT(cred->cr_label);
2421         obj = SLOT(vplabel);
2422
2423         if (!mls_dominate_effective(subj, obj))
2424                 return (EACCES);
2425
2426         return (0);
2427 }
2428
2429 static int
2430 mls_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
2431     struct label *vplabel, int attrnamespace, const char *name)
2432 {
2433         struct mac_mls *subj, *obj;
2434
2435         if (!mls_enabled)
2436                 return (0);
2437
2438         subj = SLOT(cred->cr_label);
2439         obj = SLOT(vplabel);
2440
2441         if (!mls_dominate_effective(subj, obj))
2442                 return (EACCES);
2443
2444         return (0);
2445 }
2446
2447 static int
2448 mls_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2449     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2450     struct componentname *cnp)
2451 {
2452         struct mac_mls *subj, *obj;
2453
2454         if (!mls_enabled)
2455                 return (0);
2456
2457         subj = SLOT(cred->cr_label);
2458         obj = SLOT(dvplabel);
2459
2460         if (!mls_dominate_effective(obj, subj))
2461                 return (EACCES);
2462
2463         obj = SLOT(vplabel);
2464         if (!mls_dominate_effective(obj, subj))
2465                 return (EACCES);
2466
2467         return (0);
2468 }
2469
2470 static int
2471 mls_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
2472     struct label *vplabel, int attrnamespace)
2473 {
2474
2475         struct mac_mls *subj, *obj;
2476
2477         if (!mls_enabled)
2478                 return (0);
2479
2480         subj = SLOT(cred->cr_label);
2481         obj = SLOT(vplabel);
2482
2483         if (!mls_dominate_effective(subj, obj))
2484                 return (EACCES);
2485
2486         return (0);
2487 }
2488
2489 static int
2490 mls_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
2491     struct label *dvplabel, struct componentname *cnp)
2492 {
2493         struct mac_mls *subj, *obj;
2494
2495         if (!mls_enabled)
2496                 return (0);
2497
2498         subj = SLOT(cred->cr_label);
2499         obj = SLOT(dvplabel);
2500
2501         if (!mls_dominate_effective(subj, obj))
2502                 return (EACCES);
2503
2504         return (0);
2505 }
2506
2507 static int
2508 mls_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2509     struct label *vplabel, int prot, int flags)
2510 {
2511         struct mac_mls *subj, *obj;
2512
2513         /*
2514          * Rely on the use of open()-time protections to handle
2515          * non-revocation cases.
2516          */
2517         if (!mls_enabled || !revocation_enabled)
2518                 return (0);
2519
2520         subj = SLOT(cred->cr_label);
2521         obj = SLOT(vplabel);
2522
2523         if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2524                 if (!mls_dominate_effective(subj, obj))
2525                         return (EACCES);
2526         }
2527         if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2528                 if (!mls_dominate_effective(obj, subj))
2529                         return (EACCES);
2530         }
2531
2532         return (0);
2533 }
2534
2535 static int
2536 mls_vnode_check_open(struct ucred *cred, struct vnode *vp,
2537     struct label *vplabel, accmode_t accmode)
2538 {
2539         struct mac_mls *subj, *obj;
2540
2541         if (!mls_enabled)
2542                 return (0);
2543
2544         subj = SLOT(cred->cr_label);
2545         obj = SLOT(vplabel);
2546
2547         /* XXX privilege override for admin? */
2548         if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
2549                 if (!mls_dominate_effective(subj, obj))
2550                         return (EACCES);
2551         }
2552         if (accmode & VMODIFY_PERMS) {
2553                 if (!mls_dominate_effective(obj, subj))
2554                         return (EACCES);
2555         }
2556
2557         return (0);
2558 }
2559
2560 static int
2561 mls_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
2562     struct vnode *vp, struct label *vplabel)
2563 {
2564         struct mac_mls *subj, *obj;
2565
2566         if (!mls_enabled || !revocation_enabled)
2567                 return (0);
2568
2569         subj = SLOT(active_cred->cr_label);
2570         obj = SLOT(vplabel);
2571
2572         if (!mls_dominate_effective(subj, obj))
2573                 return (EACCES);
2574
2575         return (0);
2576 }
2577
2578 static int
2579 mls_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2580     struct vnode *vp, struct label *vplabel)
2581 {
2582         struct mac_mls *subj, *obj;
2583
2584         if (!mls_enabled || !revocation_enabled)
2585                 return (0);
2586
2587         subj = SLOT(active_cred->cr_label);
2588         obj = SLOT(vplabel);
2589
2590         if (!mls_dominate_effective(subj, obj))
2591                 return (EACCES);
2592
2593         return (0);
2594 }
2595
2596 static int
2597 mls_vnode_check_readdir(struct ucred *cred, struct vnode *dvp,
2598     struct label *dvplabel)
2599 {
2600         struct mac_mls *subj, *obj;
2601
2602         if (!mls_enabled)
2603                 return (0);
2604
2605         subj = SLOT(cred->cr_label);
2606         obj = SLOT(dvplabel);
2607
2608         if (!mls_dominate_effective(subj, obj))
2609                 return (EACCES);
2610
2611         return (0);
2612 }
2613
2614 static int
2615 mls_vnode_check_readlink(struct ucred *cred, struct vnode *vp,
2616     struct label *vplabel)
2617 {
2618         struct mac_mls *subj, *obj;
2619
2620         if (!mls_enabled)
2621                 return (0);
2622
2623         subj = SLOT(cred->cr_label);
2624         obj = SLOT(vplabel);
2625
2626         if (!mls_dominate_effective(subj, obj))
2627                 return (EACCES);
2628
2629         return (0);
2630 }
2631
2632 static int
2633 mls_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2634     struct label *vplabel, struct label *newlabel)
2635 {
2636         struct mac_mls *old, *new, *subj;
2637         int error;
2638
2639         old = SLOT(vplabel);
2640         new = SLOT(newlabel);
2641         subj = SLOT(cred->cr_label);
2642
2643         /*
2644          * If there is an MLS label update for the vnode, it must be a
2645          * effective label.
2646          */
2647         error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2648         if (error)
2649                 return (error);
2650
2651         /*
2652          * To perform a relabel of the vnode (MLS label or not), MLS must
2653          * authorize the relabel.
2654          */
2655         if (!mls_effective_in_range(old, subj))
2656                 return (EPERM);
2657
2658         /*
2659          * If the MLS label is to be changed, authorize as appropriate.
2660          */
2661         if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2662                 /*
2663                  * To change the MLS label on a vnode, the new vnode label
2664                  * must be in the subject range.
2665                  */
2666                 if (!mls_effective_in_range(new, subj))
2667                         return (EPERM);
2668
2669                 /*
2670                  * To change the MLS label on the vnode to be EQUAL, the
2671                  * subject must have appropriate privilege.
2672                  */
2673                 if (mls_contains_equal(new)) {
2674                         error = mls_subject_privileged(subj);
2675                         if (error)
2676                                 return (error);
2677                 }
2678         }
2679
2680         return (0);
2681 }
2682
2683 static int
2684 mls_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2685     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2686     struct componentname *cnp)
2687 {
2688         struct mac_mls *subj, *obj;
2689
2690         if (!mls_enabled)
2691                 return (0);
2692
2693         subj = SLOT(cred->cr_label);
2694         obj = SLOT(dvplabel);
2695
2696         if (!mls_dominate_effective(obj, subj))
2697                 return (EACCES);
2698
2699         obj = SLOT(vplabel);
2700
2701         if (!mls_dominate_effective(obj, subj))
2702                 return (EACCES);
2703
2704         return (0);
2705 }
2706
2707 static int
2708 mls_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2709     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2710     int samedir, struct componentname *cnp)
2711 {
2712         struct mac_mls *subj, *obj;
2713
2714         if (!mls_enabled)
2715                 return (0);
2716
2717         subj = SLOT(cred->cr_label);
2718         obj = SLOT(dvplabel);
2719
2720         if (!mls_dominate_effective(obj, subj))
2721                 return (EACCES);
2722
2723         if (vp != NULL) {
2724                 obj = SLOT(vplabel);
2725
2726                 if (!mls_dominate_effective(obj, subj))
2727                         return (EACCES);
2728         }
2729
2730         return (0);
2731 }
2732
2733 static int
2734 mls_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2735     struct label *vplabel)
2736 {
2737         struct mac_mls *subj, *obj;
2738
2739         if (!mls_enabled)
2740                 return (0);
2741
2742         subj = SLOT(cred->cr_label);
2743         obj = SLOT(vplabel);
2744
2745         if (!mls_dominate_effective(obj, subj))
2746                 return (EACCES);
2747
2748         return (0);
2749 }
2750
2751 static int
2752 mls_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2753     struct label *vplabel, acl_type_t type, struct acl *acl)
2754 {
2755         struct mac_mls *subj, *obj;
2756
2757         if (!mls_enabled)
2758                 return (0);
2759
2760         subj = SLOT(cred->cr_label);
2761         obj = SLOT(vplabel);
2762
2763         if (!mls_dominate_effective(obj, subj))
2764                 return (EACCES);
2765
2766         return (0);
2767 }
2768
2769 static int
2770 mls_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2771     struct label *vplabel, int attrnamespace, const char *name)
2772 {
2773         struct mac_mls *subj, *obj;
2774
2775         if (!mls_enabled)
2776                 return (0);
2777
2778         subj = SLOT(cred->cr_label);
2779         obj = SLOT(vplabel);
2780
2781         if (!mls_dominate_effective(obj, subj))
2782                 return (EACCES);
2783
2784         /* XXX: protect the MAC EA in a special way? */
2785
2786         return (0);
2787 }
2788
2789 static int
2790 mls_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
2791     struct label *vplabel, u_long flags)
2792 {
2793         struct mac_mls *subj, *obj;
2794
2795         if (!mls_enabled)
2796                 return (0);
2797
2798         subj = SLOT(cred->cr_label);
2799         obj = SLOT(vplabel);
2800
2801         if (!mls_dominate_effective(obj, subj))
2802                 return (EACCES);
2803
2804         return (0);
2805 }
2806
2807 static int
2808 mls_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
2809     struct label *vplabel, mode_t mode)
2810 {
2811         struct mac_mls *subj, *obj;
2812
2813         if (!mls_enabled)
2814                 return (0);
2815
2816         subj = SLOT(cred->cr_label);
2817         obj = SLOT(vplabel);
2818
2819         if (!mls_dominate_effective(obj, subj))
2820                 return (EACCES);
2821
2822         return (0);
2823 }
2824
2825 static int
2826 mls_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
2827     struct label *vplabel, uid_t uid, gid_t gid)
2828 {
2829         struct mac_mls *subj, *obj;
2830
2831         if (!mls_enabled)
2832                 return (0);
2833
2834         subj = SLOT(cred->cr_label);
2835         obj = SLOT(vplabel);
2836
2837         if (!mls_dominate_effective(obj, subj))
2838                 return (EACCES);
2839
2840         return (0);
2841 }
2842
2843 static int
2844 mls_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
2845     struct label *vplabel, struct timespec atime, struct timespec mtime)
2846 {
2847         struct mac_mls *subj, *obj;
2848
2849         if (!mls_enabled)
2850                 return (0);
2851
2852         subj = SLOT(cred->cr_label);
2853         obj = SLOT(vplabel);
2854
2855         if (!mls_dominate_effective(obj, subj))
2856                 return (EACCES);
2857
2858         return (0);
2859 }
2860
2861 static int
2862 mls_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
2863     struct vnode *vp, struct label *vplabel)
2864 {
2865         struct mac_mls *subj, *obj;
2866
2867         if (!mls_enabled)
2868                 return (0);
2869
2870         subj = SLOT(active_cred->cr_label);
2871         obj = SLOT(vplabel);
2872
2873         if (!mls_dominate_effective(subj, obj))
2874                 return (EACCES);
2875
2876         return (0);
2877 }
2878
2879 static int
2880 mls_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
2881     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2882     struct componentname *cnp)
2883 {
2884         struct mac_mls *subj, *obj;
2885
2886         if (!mls_enabled)
2887                 return (0);
2888
2889         subj = SLOT(cred->cr_label);
2890         obj = SLOT(dvplabel);
2891
2892         if (!mls_dominate_effective(obj, subj))
2893                 return (EACCES);
2894
2895         obj = SLOT(vplabel);
2896
2897         if (!mls_dominate_effective(obj, subj))
2898                 return (EACCES);
2899
2900         return (0);
2901 }
2902
2903 static int
2904 mls_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
2905     struct vnode *vp, struct label *vplabel)
2906 {
2907         struct mac_mls *subj, *obj;
2908
2909         if (!mls_enabled || !revocation_enabled)
2910                 return (0);
2911
2912         subj = SLOT(active_cred->cr_label);
2913         obj = SLOT(vplabel);
2914
2915         if (!mls_dominate_effective(obj, subj))
2916                 return (EACCES);
2917
2918         return (0);
2919 }
2920
2921 static int
2922 mls_vnode_create_extattr(struct ucred *cred, struct mount *mp,
2923     struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
2924     struct vnode *vp, struct label *vplabel, struct componentname *cnp)
2925 {
2926         struct mac_mls *source, *dest, mm_temp;
2927         size_t buflen;
2928         int error;
2929
2930         buflen = sizeof(mm_temp);
2931         bzero(&mm_temp, buflen);
2932
2933         source = SLOT(cred->cr_label);
2934         dest = SLOT(vplabel);
2935         mls_copy_effective(source, &mm_temp);
2936
2937         error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2938             MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
2939         if (error == 0)
2940                 mls_copy_effective(source, dest);
2941         return (error);
2942 }
2943
2944 static void
2945 mls_vnode_relabel(struct ucred *cred, struct vnode *vp,
2946     struct label *vplabel, struct label *label)
2947 {
2948         struct mac_mls *source, *dest;
2949
2950         source = SLOT(label);
2951         dest = SLOT(vplabel);
2952
2953         mls_copy(source, dest);
2954 }
2955
2956 static int
2957 mls_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
2958     struct label *vplabel, struct label *intlabel)
2959 {
2960         struct mac_mls *source, mm_temp;
2961         size_t buflen;
2962         int error;
2963
2964         buflen = sizeof(mm_temp);
2965         bzero(&mm_temp, buflen);
2966
2967         source = SLOT(intlabel);
2968         if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
2969                 return (0);
2970
2971         mls_copy_effective(source, &mm_temp);
2972
2973         error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2974             MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
2975         return (error);
2976 }
2977
2978 static struct mac_policy_ops mls_ops =
2979 {
2980         .mpo_init = mls_init,
2981
2982         .mpo_bpfdesc_check_receive = mls_bpfdesc_check_receive,
2983         .mpo_bpfdesc_create = mls_bpfdesc_create,
2984         .mpo_bpfdesc_create_mbuf = mls_bpfdesc_create_mbuf,
2985         .mpo_bpfdesc_destroy_label = mls_destroy_label,
2986         .mpo_bpfdesc_init_label = mls_init_label,
2987
2988         .mpo_cred_associate_nfsd = mls_cred_associate_nfsd,
2989         .mpo_cred_check_relabel = mls_cred_check_relabel,
2990         .mpo_cred_check_visible = mls_cred_check_visible,
2991         .mpo_cred_copy_label = mls_copy_label,
2992         .mpo_cred_create_init = mls_cred_create_init,
2993         .mpo_cred_create_swapper = mls_cred_create_swapper,
2994         .mpo_cred_destroy_label = mls_destroy_label,
2995         .mpo_cred_externalize_label = mls_externalize_label,
2996         .mpo_cred_init_label = mls_init_label,
2997         .mpo_cred_internalize_label = mls_internalize_label,
2998         .mpo_cred_relabel = mls_cred_relabel,
2999
3000         .mpo_devfs_create_device = mls_devfs_create_device,
3001         .mpo_devfs_create_directory = mls_devfs_create_directory,
3002         .mpo_devfs_create_symlink = mls_devfs_create_symlink,
3003         .mpo_devfs_destroy_label = mls_destroy_label,
3004         .mpo_devfs_init_label = mls_init_label,
3005         .mpo_devfs_update = mls_devfs_update,
3006         .mpo_devfs_vnode_associate = mls_devfs_vnode_associate,
3007
3008         .mpo_ifnet_check_relabel = mls_ifnet_check_relabel,
3009         .mpo_ifnet_check_transmit = mls_ifnet_check_transmit,
3010         .mpo_ifnet_copy_label = mls_copy_label,
3011         .mpo_ifnet_create = mls_ifnet_create,
3012         .mpo_ifnet_create_mbuf = mls_ifnet_create_mbuf,
3013         .mpo_ifnet_destroy_label = mls_destroy_label,
3014         .mpo_ifnet_externalize_label = mls_externalize_label,
3015         .mpo_ifnet_init_label = mls_init_label,
3016         .mpo_ifnet_internalize_label = mls_internalize_label,
3017         .mpo_ifnet_relabel = mls_ifnet_relabel,
3018
3019         .mpo_inpcb_check_deliver = mls_inpcb_check_deliver,
3020         .mpo_inpcb_check_visible = mls_inpcb_check_visible,
3021         .mpo_inpcb_create = mls_inpcb_create,
3022         .mpo_inpcb_create_mbuf = mls_inpcb_create_mbuf,
3023         .mpo_inpcb_destroy_label = mls_destroy_label,
3024         .mpo_inpcb_init_label = mls_init_label_waitcheck,
3025         .mpo_inpcb_sosetlabel = mls_inpcb_sosetlabel,
3026
3027         .mpo_ip6q_create = mls_ip6q_create,
3028         .mpo_ip6q_destroy_label = mls_destroy_label,
3029         .mpo_ip6q_init_label = mls_init_label_waitcheck,
3030         .mpo_ip6q_match = mls_ip6q_match,
3031         .mpo_ip6q_reassemble = mls_ip6q_reassemble,
3032         .mpo_ip6q_update = mls_ip6q_update,
3033
3034         .mpo_ipq_create = mls_ipq_create,
3035         .mpo_ipq_destroy_label = mls_destroy_label,
3036         .mpo_ipq_init_label = mls_init_label_waitcheck,
3037         .mpo_ipq_match = mls_ipq_match,
3038         .mpo_ipq_reassemble = mls_ipq_reassemble,
3039         .mpo_ipq_update = mls_ipq_update,
3040
3041         .mpo_mbuf_copy_label = mls_copy_label,
3042         .mpo_mbuf_destroy_label = mls_destroy_label,
3043         .mpo_mbuf_init_label = mls_init_label_waitcheck,
3044
3045         .mpo_mount_check_stat = mls_mount_check_stat,
3046         .mpo_mount_create = mls_mount_create,
3047         .mpo_mount_destroy_label = mls_destroy_label,
3048         .mpo_mount_init_label = mls_init_label,
3049
3050         .mpo_netatalk_aarp_send = mls_netatalk_aarp_send,
3051
3052         .mpo_netinet_arp_send = mls_netinet_arp_send,
3053         .mpo_netinet_firewall_reply = mls_netinet_firewall_reply,
3054         .mpo_netinet_firewall_send = mls_netinet_firewall_send,
3055         .mpo_netinet_fragment = mls_netinet_fragment,
3056         .mpo_netinet_icmp_reply = mls_netinet_icmp_reply,
3057         .mpo_netinet_igmp_send = mls_netinet_igmp_send,
3058
3059         .mpo_netinet6_nd6_send = mls_netinet6_nd6_send,
3060
3061         .mpo_pipe_check_ioctl = mls_pipe_check_ioctl,
3062         .mpo_pipe_check_poll = mls_pipe_check_poll,
3063         .mpo_pipe_check_read = mls_pipe_check_read,
3064         .mpo_pipe_check_relabel = mls_pipe_check_relabel,
3065         .mpo_pipe_check_stat = mls_pipe_check_stat,
3066         .mpo_pipe_check_write = mls_pipe_check_write,
3067         .mpo_pipe_copy_label = mls_copy_label,
3068         .mpo_pipe_create = mls_pipe_create,
3069         .mpo_pipe_destroy_label = mls_destroy_label,
3070         .mpo_pipe_externalize_label = mls_externalize_label,
3071         .mpo_pipe_init_label = mls_init_label,
3072         .mpo_pipe_internalize_label = mls_internalize_label,
3073         .mpo_pipe_relabel = mls_pipe_relabel,
3074
3075         .mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly,
3076         .mpo_posixsem_check_open = mls_posixsem_check_openunlink,
3077         .mpo_posixsem_check_post = mls_posixsem_check_write,
3078         .mpo_posixsem_check_stat = mls_posixsem_check_rdonly,
3079         .mpo_posixsem_check_unlink = mls_posixsem_check_openunlink,
3080         .mpo_posixsem_check_wait = mls_posixsem_check_write,
3081         .mpo_posixsem_create = mls_posixsem_create,
3082         .mpo_posixsem_destroy_label = mls_destroy_label,
3083         .mpo_posixsem_init_label = mls_init_label,
3084
3085         .mpo_proc_check_debug = mls_proc_check_debug,
3086         .mpo_proc_check_sched = mls_proc_check_sched,
3087         .mpo_proc_check_signal = mls_proc_check_signal,
3088
3089         .mpo_socket_check_deliver = mls_socket_check_deliver,
3090         .mpo_socket_check_relabel = mls_socket_check_relabel,
3091         .mpo_socket_check_visible = mls_socket_check_visible,
3092         .mpo_socket_copy_label = mls_copy_label,
3093         .mpo_socket_create = mls_socket_create,
3094         .mpo_socket_create_mbuf = mls_socket_create_mbuf,
3095         .mpo_socket_destroy_label = mls_destroy_label,
3096         .mpo_socket_externalize_label = mls_externalize_label,
3097         .mpo_socket_init_label = mls_init_label_waitcheck,
3098         .mpo_socket_internalize_label = mls_internalize_label,
3099         .mpo_socket_newconn = mls_socket_newconn,
3100         .mpo_socket_relabel = mls_socket_relabel,
3101
3102         .mpo_socketpeer_destroy_label = mls_destroy_label,
3103         .mpo_socketpeer_externalize_label = mls_externalize_label,
3104         .mpo_socketpeer_init_label = mls_init_label_waitcheck,
3105         .mpo_socketpeer_set_from_mbuf = mls_socketpeer_set_from_mbuf,
3106         .mpo_socketpeer_set_from_socket = mls_socketpeer_set_from_socket,
3107
3108         .mpo_syncache_create = mls_syncache_create,
3109         .mpo_syncache_create_mbuf = mls_syncache_create_mbuf,
3110         .mpo_syncache_destroy_label = mls_destroy_label,
3111         .mpo_syncache_init_label = mls_init_label_waitcheck,
3112
3113         .mpo_sysvmsg_cleanup = mls_sysvmsg_cleanup,
3114         .mpo_sysvmsg_create = mls_sysvmsg_create,
3115         .mpo_sysvmsg_destroy_label = mls_destroy_label,
3116         .mpo_sysvmsg_init_label = mls_init_label,
3117
3118         .mpo_sysvmsq_check_msgrcv = mls_sysvmsq_check_msgrcv,
3119         .mpo_sysvmsq_check_msgrmid = mls_sysvmsq_check_msgrmid,
3120         .mpo_sysvmsq_check_msqget = mls_sysvmsq_check_msqget,
3121         .mpo_sysvmsq_check_msqsnd = mls_sysvmsq_check_msqsnd,
3122         .mpo_sysvmsq_check_msqrcv = mls_sysvmsq_check_msqrcv,
3123         .mpo_sysvmsq_check_msqctl = mls_sysvmsq_check_msqctl,
3124         .mpo_sysvmsq_cleanup = mls_sysvmsq_cleanup,
3125         .mpo_sysvmsq_destroy_label = mls_destroy_label,
3126         .mpo_sysvmsq_init_label = mls_init_label,
3127         .mpo_sysvmsq_create = mls_sysvmsq_create,
3128
3129         .mpo_sysvsem_check_semctl = mls_sysvsem_check_semctl,
3130         .mpo_sysvsem_check_semget = mls_sysvsem_check_semget,
3131         .mpo_sysvsem_check_semop = mls_sysvsem_check_semop,
3132         .mpo_sysvsem_cleanup = mls_sysvsem_cleanup,
3133         .mpo_sysvsem_create = mls_sysvsem_create,
3134         .mpo_sysvsem_destroy_label = mls_destroy_label,
3135         .mpo_sysvsem_init_label = mls_init_label,
3136
3137         .mpo_sysvshm_check_shmat = mls_sysvshm_check_shmat,
3138         .mpo_sysvshm_check_shmctl = mls_sysvshm_check_shmctl,
3139         .mpo_sysvshm_check_shmget = mls_sysvshm_check_shmget,
3140         .mpo_sysvshm_cleanup = mls_sysvshm_cleanup,
3141         .mpo_sysvshm_create = mls_sysvshm_create,
3142         .mpo_sysvshm_destroy_label = mls_destroy_label,
3143         .mpo_sysvshm_init_label = mls_init_label,
3144
3145
3146         .mpo_system_check_acct = mls_system_check_acct,
3147         .mpo_system_check_auditctl = mls_system_check_auditctl,
3148         .mpo_system_check_swapon = mls_system_check_swapon,
3149
3150         .mpo_vnode_associate_extattr = mls_vnode_associate_extattr,
3151         .mpo_vnode_associate_singlelabel = mls_vnode_associate_singlelabel,
3152         .mpo_vnode_check_access = mls_vnode_check_open,
3153         .mpo_vnode_check_chdir = mls_vnode_check_chdir,
3154         .mpo_vnode_check_chroot = mls_vnode_check_chroot,
3155         .mpo_vnode_check_create = mls_vnode_check_create,
3156         .mpo_vnode_check_deleteacl = mls_vnode_check_deleteacl,
3157         .mpo_vnode_check_deleteextattr = mls_vnode_check_deleteextattr,
3158         .mpo_vnode_check_exec = mls_vnode_check_exec,
3159         .mpo_vnode_check_getacl = mls_vnode_check_getacl,
3160         .mpo_vnode_check_getextattr = mls_vnode_check_getextattr,
3161         .mpo_vnode_check_link = mls_vnode_check_link,
3162         .mpo_vnode_check_listextattr = mls_vnode_check_listextattr,
3163         .mpo_vnode_check_lookup = mls_vnode_check_lookup,
3164         .mpo_vnode_check_mmap = mls_vnode_check_mmap,
3165         .mpo_vnode_check_open = mls_vnode_check_open,
3166         .mpo_vnode_check_poll = mls_vnode_check_poll,
3167         .mpo_vnode_check_read = mls_vnode_check_read,
3168         .mpo_vnode_check_readdir = mls_vnode_check_readdir,
3169         .mpo_vnode_check_readlink = mls_vnode_check_readlink,
3170         .mpo_vnode_check_relabel = mls_vnode_check_relabel,
3171         .mpo_vnode_check_rename_from = mls_vnode_check_rename_from,
3172         .mpo_vnode_check_rename_to = mls_vnode_check_rename_to,
3173         .mpo_vnode_check_revoke = mls_vnode_check_revoke,
3174         .mpo_vnode_check_setacl = mls_vnode_check_setacl,
3175         .mpo_vnode_check_setextattr = mls_vnode_check_setextattr,
3176         .mpo_vnode_check_setflags = mls_vnode_check_setflags,
3177         .mpo_vnode_check_setmode = mls_vnode_check_setmode,
3178         .mpo_vnode_check_setowner = mls_vnode_check_setowner,
3179         .mpo_vnode_check_setutimes = mls_vnode_check_setutimes,
3180         .mpo_vnode_check_stat = mls_vnode_check_stat,
3181         .mpo_vnode_check_unlink = mls_vnode_check_unlink,
3182         .mpo_vnode_check_write = mls_vnode_check_write,
3183         .mpo_vnode_copy_label = mls_copy_label,
3184         .mpo_vnode_create_extattr = mls_vnode_create_extattr,
3185         .mpo_vnode_destroy_label = mls_destroy_label,
3186         .mpo_vnode_externalize_label = mls_externalize_label,
3187         .mpo_vnode_init_label = mls_init_label,
3188         .mpo_vnode_internalize_label = mls_internalize_label,
3189         .mpo_vnode_relabel = mls_vnode_relabel,
3190         .mpo_vnode_setlabel_extattr = mls_vnode_setlabel_extattr,
3191 };
3192
3193 MAC_POLICY_SET(&mls_ops, mac_mls, "TrustedBSD MAC/MLS",
3194     MPC_LOADTIME_FLAG_NOTLATE, &mls_slot);