]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/security/mac_mls/mac_mls.c
MFC r362623:
[FreeBSD/stable/8.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         if (vplabel == NULL)
1841                 return (0);
1842
1843         subj = SLOT(cred->cr_label);
1844         obj = SLOT(vplabel);
1845
1846         if (!mls_dominate_effective(obj, subj) ||
1847             !mls_dominate_effective(subj, obj))
1848                 return (EACCES);
1849
1850         return (0);
1851 }
1852
1853 static int
1854 mls_system_check_auditctl(struct ucred *cred, struct vnode *vp,
1855     struct label *vplabel)
1856 {
1857         struct mac_mls *subj, *obj;
1858
1859         if (!mls_enabled)
1860                 return (0);
1861
1862         subj = SLOT(cred->cr_label);
1863         obj = SLOT(vplabel);
1864
1865         if (!mls_dominate_effective(obj, subj) ||
1866             !mls_dominate_effective(subj, obj))
1867                 return (EACCES);
1868
1869         return (0);
1870 }
1871
1872 static int
1873 mls_system_check_swapon(struct ucred *cred, struct vnode *vp,
1874     struct label *vplabel)
1875 {
1876         struct mac_mls *subj, *obj;
1877
1878         if (!mls_enabled)
1879                 return (0);
1880
1881         subj = SLOT(cred->cr_label);
1882         obj = SLOT(vplabel);
1883
1884         if (!mls_dominate_effective(obj, subj) ||
1885             !mls_dominate_effective(subj, obj))
1886                 return (EACCES);
1887
1888         return (0);
1889 }
1890
1891 static void
1892 mls_sysvmsg_cleanup(struct label *msglabel)
1893 {
1894
1895         bzero(SLOT(msglabel), sizeof(struct mac_mls));
1896 }
1897
1898 static void
1899 mls_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
1900     struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
1901 {
1902         struct mac_mls *source, *dest;
1903
1904         /* Ignore the msgq label. */
1905         source = SLOT(cred->cr_label);
1906         dest = SLOT(msglabel);
1907
1908         mls_copy_effective(source, dest);
1909 }
1910
1911 static int
1912 mls_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr,
1913     struct label *msglabel)
1914 {
1915         struct mac_mls *subj, *obj;
1916
1917         if (!mls_enabled)
1918                 return (0);
1919
1920         subj = SLOT(cred->cr_label);
1921         obj = SLOT(msglabel);
1922
1923         if (!mls_dominate_effective(subj, obj))
1924                 return (EACCES);
1925
1926         return (0);
1927 }
1928
1929 static int
1930 mls_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr,
1931     struct label *msglabel)
1932 {
1933         struct mac_mls *subj, *obj;
1934
1935         if (!mls_enabled)
1936                 return (0);
1937
1938         subj = SLOT(cred->cr_label);
1939         obj = SLOT(msglabel);
1940
1941         if (!mls_dominate_effective(obj, subj))
1942                 return (EACCES);
1943
1944         return (0);
1945 }
1946
1947 static int
1948 mls_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
1949     struct label *msqklabel)
1950 {
1951         struct mac_mls *subj, *obj;
1952
1953         if (!mls_enabled)
1954                 return (0);
1955
1956         subj = SLOT(cred->cr_label);
1957         obj = SLOT(msqklabel);
1958
1959         if (!mls_dominate_effective(subj, obj))
1960                 return (EACCES);
1961
1962         return (0);
1963 }
1964
1965 static int
1966 mls_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
1967     struct label *msqklabel)
1968 {
1969         struct mac_mls *subj, *obj;
1970
1971         if (!mls_enabled)
1972                 return (0);
1973
1974         subj = SLOT(cred->cr_label);
1975         obj = SLOT(msqklabel);
1976
1977         if (!mls_dominate_effective(obj, subj))
1978                 return (EACCES);
1979
1980         return (0);
1981 }
1982
1983 static int
1984 mls_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
1985     struct label *msqklabel)
1986 {
1987         struct mac_mls *subj, *obj;
1988
1989         if (!mls_enabled)
1990                 return (0);
1991
1992         subj = SLOT(cred->cr_label);
1993         obj = SLOT(msqklabel);
1994
1995         if (!mls_dominate_effective(subj, obj))
1996                 return (EACCES);
1997
1998         return (0);
1999 }
2000
2001 static int
2002 mls_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
2003     struct label *msqklabel, int cmd)
2004 {
2005         struct mac_mls *subj, *obj;
2006
2007         if (!mls_enabled)
2008                 return (0);
2009
2010         subj = SLOT(cred->cr_label);
2011         obj = SLOT(msqklabel);
2012
2013         switch(cmd) {
2014         case IPC_RMID:
2015         case IPC_SET:
2016                 if (!mls_dominate_effective(obj, subj))
2017                         return (EACCES);
2018                 break;
2019
2020         case IPC_STAT:
2021                 if (!mls_dominate_effective(subj, obj))
2022                         return (EACCES);
2023                 break;
2024
2025         default:
2026                 return (EACCES);
2027         }
2028
2029         return (0);
2030 }
2031
2032 static void
2033 mls_sysvmsq_cleanup(struct label *msqlabel)
2034 {
2035
2036         bzero(SLOT(msqlabel), sizeof(struct mac_mls));
2037 }
2038
2039 static void
2040 mls_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2041     struct label *msqlabel)
2042 {
2043         struct mac_mls *source, *dest;
2044
2045         source = SLOT(cred->cr_label);
2046         dest = SLOT(msqlabel);
2047
2048         mls_copy_effective(source, dest);
2049 }
2050
2051 static int
2052 mls_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
2053     struct label *semaklabel, int cmd)
2054 {
2055         struct mac_mls *subj, *obj;
2056
2057         if (!mls_enabled)
2058                 return (0);
2059
2060         subj = SLOT(cred->cr_label);
2061         obj = SLOT(semaklabel);
2062
2063         switch(cmd) {
2064         case IPC_RMID:
2065         case IPC_SET:
2066         case SETVAL:
2067         case SETALL:
2068                 if (!mls_dominate_effective(obj, subj))
2069                         return (EACCES);
2070                 break;
2071
2072         case IPC_STAT:
2073         case GETVAL:
2074         case GETPID:
2075         case GETNCNT:
2076         case GETZCNT:
2077         case GETALL:
2078                 if (!mls_dominate_effective(subj, obj))
2079                         return (EACCES);
2080                 break;
2081
2082         default:
2083                 return (EACCES);
2084         }
2085
2086         return (0);
2087 }
2088
2089 static int
2090 mls_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr,
2091     struct label *semaklabel)
2092 {
2093         struct mac_mls *subj, *obj;
2094
2095         if (!mls_enabled)
2096                 return (0);
2097
2098         subj = SLOT(cred->cr_label);
2099         obj = SLOT(semaklabel);
2100
2101         if (!mls_dominate_effective(subj, obj))
2102                 return (EACCES);
2103
2104         return (0);
2105 }
2106
2107 static int
2108 mls_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
2109     struct label *semaklabel, size_t accesstype)
2110 {
2111         struct mac_mls *subj, *obj;
2112
2113         if (!mls_enabled)
2114                 return (0);
2115
2116         subj = SLOT(cred->cr_label);
2117         obj = SLOT(semaklabel);
2118
2119         if( accesstype & SEM_R )
2120                 if (!mls_dominate_effective(subj, obj))
2121                         return (EACCES);
2122
2123         if( accesstype & SEM_A )
2124                 if (!mls_dominate_effective(obj, subj))
2125                         return (EACCES);
2126
2127         return (0);
2128 }
2129
2130 static void
2131 mls_sysvsem_cleanup(struct label *semalabel)
2132 {
2133
2134         bzero(SLOT(semalabel), sizeof(struct mac_mls));
2135 }
2136
2137 static void
2138 mls_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr,
2139     struct label *semalabel)
2140 {
2141         struct mac_mls *source, *dest;
2142
2143         source = SLOT(cred->cr_label);
2144         dest = SLOT(semalabel);
2145
2146         mls_copy_effective(source, dest);
2147 }
2148
2149 static int
2150 mls_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
2151     struct label *shmseglabel, int shmflg)
2152 {
2153         struct mac_mls *subj, *obj;
2154
2155         if (!mls_enabled)
2156                 return (0);
2157
2158         subj = SLOT(cred->cr_label);
2159         obj = SLOT(shmseglabel);
2160
2161         if (!mls_dominate_effective(subj, obj))
2162                 return (EACCES);
2163         if ((shmflg & SHM_RDONLY) == 0) {
2164                 if (!mls_dominate_effective(obj, subj))
2165                         return (EACCES);
2166         }
2167         
2168         return (0);
2169 }
2170
2171 static int
2172 mls_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
2173     struct label *shmseglabel, int cmd)
2174 {
2175         struct mac_mls *subj, *obj;
2176
2177         if (!mls_enabled)
2178                 return (0);
2179
2180         subj = SLOT(cred->cr_label);
2181         obj = SLOT(shmseglabel);
2182
2183         switch(cmd) {
2184         case IPC_RMID:
2185         case IPC_SET:
2186                 if (!mls_dominate_effective(obj, subj))
2187                         return (EACCES);
2188                 break;
2189
2190         case IPC_STAT:
2191         case SHM_STAT:
2192                 if (!mls_dominate_effective(subj, obj))
2193                         return (EACCES);
2194                 break;
2195
2196         default:
2197                 return (EACCES);
2198         }
2199
2200         return (0);
2201 }
2202
2203 static int
2204 mls_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
2205     struct label *shmseglabel, int shmflg)
2206 {
2207         struct mac_mls *subj, *obj;
2208
2209         if (!mls_enabled)
2210                 return (0);
2211
2212         subj = SLOT(cred->cr_label);
2213         obj = SLOT(shmseglabel);
2214
2215         if (!mls_dominate_effective(obj, subj))
2216                 return (EACCES);
2217
2218         return (0);
2219 }
2220
2221 static void
2222 mls_sysvshm_cleanup(struct label *shmlabel)
2223 {
2224
2225         bzero(SLOT(shmlabel), sizeof(struct mac_mls));
2226 }
2227
2228 static void
2229 mls_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr,
2230     struct label *shmlabel)
2231 {
2232         struct mac_mls *source, *dest;
2233
2234         source = SLOT(cred->cr_label);
2235         dest = SLOT(shmlabel);
2236
2237         mls_copy_effective(source, dest);
2238 }
2239
2240 static int
2241 mls_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2242     struct vnode *vp, struct label *vplabel)
2243 {
2244         struct mac_mls mm_temp, *source, *dest;
2245         int buflen, error;
2246
2247         source = SLOT(mplabel);
2248         dest = SLOT(vplabel);
2249
2250         buflen = sizeof(mm_temp);
2251         bzero(&mm_temp, buflen);
2252
2253         error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2254             MAC_MLS_EXTATTR_NAME, &buflen, (char *) &mm_temp, curthread);
2255         if (error == ENOATTR || error == EOPNOTSUPP) {
2256                 /* Fall back to the mntlabel. */
2257                 mls_copy_effective(source, dest);
2258                 return (0);
2259         } else if (error)
2260                 return (error);
2261
2262         if (buflen != sizeof(mm_temp)) {
2263                 printf("mls_vnode_associate_extattr: bad size %d\n", buflen);
2264                 return (EPERM);
2265         }
2266         if (mls_valid(&mm_temp) != 0) {
2267                 printf("mls_vnode_associate_extattr: invalid\n");
2268                 return (EPERM);
2269         }
2270         if ((mm_temp.mm_flags & MAC_MLS_FLAGS_BOTH) !=
2271             MAC_MLS_FLAG_EFFECTIVE) {
2272                 printf("mls_associated_vnode_extattr: not effective\n");
2273                 return (EPERM);
2274         }
2275
2276         mls_copy_effective(&mm_temp, dest);
2277         return (0);
2278 }
2279
2280 static void
2281 mls_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2282     struct vnode *vp, struct label *vplabel)
2283 {
2284         struct mac_mls *source, *dest;
2285
2286         source = SLOT(mplabel);
2287         dest = SLOT(vplabel);
2288
2289         mls_copy_effective(source, dest);
2290 }
2291
2292 static int
2293 mls_vnode_check_chdir(struct ucred *cred, struct vnode *dvp,
2294     struct label *dvplabel)
2295 {
2296         struct mac_mls *subj, *obj;
2297
2298         if (!mls_enabled)
2299                 return (0);
2300
2301         subj = SLOT(cred->cr_label);
2302         obj = SLOT(dvplabel);
2303
2304         if (!mls_dominate_effective(subj, obj))
2305                 return (EACCES);
2306
2307         return (0);
2308 }
2309
2310 static int
2311 mls_vnode_check_chroot(struct ucred *cred, struct vnode *dvp,
2312     struct label *dvplabel)
2313 {
2314         struct mac_mls *subj, *obj;
2315
2316         if (!mls_enabled)
2317                 return (0);
2318
2319         subj = SLOT(cred->cr_label);
2320         obj = SLOT(dvplabel);
2321
2322         if (!mls_dominate_effective(subj, obj))
2323                 return (EACCES);
2324
2325         return (0);
2326 }
2327
2328 static int
2329 mls_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2330     struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2331 {
2332         struct mac_mls *subj, *obj;
2333
2334         if (!mls_enabled)
2335                 return (0);
2336
2337         subj = SLOT(cred->cr_label);
2338         obj = SLOT(dvplabel);
2339
2340         if (!mls_dominate_effective(obj, subj))
2341                 return (EACCES);
2342
2343         return (0);
2344 }
2345
2346 static int
2347 mls_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2348     struct label *vplabel, acl_type_t type)
2349 {
2350         struct mac_mls *subj, *obj;
2351
2352         if (!mls_enabled)
2353                 return (0);
2354
2355         subj = SLOT(cred->cr_label);
2356         obj = SLOT(vplabel);
2357
2358         if (!mls_dominate_effective(obj, subj))
2359                 return (EACCES);
2360
2361         return (0);
2362 }
2363
2364 static int
2365 mls_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
2366     struct label *vplabel, int attrnamespace, const char *name)
2367 {
2368         struct mac_mls *subj, *obj;
2369
2370         if (!mls_enabled)
2371                 return (0);
2372
2373         subj = SLOT(cred->cr_label);
2374         obj = SLOT(vplabel);
2375
2376         if (!mls_dominate_effective(obj, subj))
2377                 return (EACCES);
2378
2379         return (0);
2380 }
2381
2382 static int
2383 mls_vnode_check_exec(struct ucred *cred, struct vnode *vp,
2384     struct label *vplabel, struct image_params *imgp,
2385     struct label *execlabel)
2386 {
2387         struct mac_mls *subj, *obj, *exec;
2388         int error;
2389
2390         if (execlabel != NULL) {
2391                 /*
2392                  * We currently don't permit labels to be changed at
2393                  * exec-time as part of MLS, so disallow non-NULL MLS label
2394                  * elements in the execlabel.
2395                  */
2396                 exec = SLOT(execlabel);
2397                 error = mls_atmostflags(exec, 0);
2398                 if (error)
2399                         return (error);
2400         }
2401
2402         if (!mls_enabled)
2403                 return (0);
2404
2405         subj = SLOT(cred->cr_label);
2406         obj = SLOT(vplabel);
2407
2408         if (!mls_dominate_effective(subj, obj))
2409                 return (EACCES);
2410
2411         return (0);
2412 }
2413
2414 static int
2415 mls_vnode_check_getacl(struct ucred *cred, struct vnode *vp,
2416     struct label *vplabel, acl_type_t type)
2417 {
2418         struct mac_mls *subj, *obj;
2419
2420         if (!mls_enabled)
2421                 return (0);
2422
2423         subj = SLOT(cred->cr_label);
2424         obj = SLOT(vplabel);
2425
2426         if (!mls_dominate_effective(subj, obj))
2427                 return (EACCES);
2428
2429         return (0);
2430 }
2431
2432 static int
2433 mls_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
2434     struct label *vplabel, int attrnamespace, const char *name)
2435 {
2436         struct mac_mls *subj, *obj;
2437
2438         if (!mls_enabled)
2439                 return (0);
2440
2441         subj = SLOT(cred->cr_label);
2442         obj = SLOT(vplabel);
2443
2444         if (!mls_dominate_effective(subj, obj))
2445                 return (EACCES);
2446
2447         return (0);
2448 }
2449
2450 static int
2451 mls_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2452     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2453     struct componentname *cnp)
2454 {
2455         struct mac_mls *subj, *obj;
2456
2457         if (!mls_enabled)
2458                 return (0);
2459
2460         subj = SLOT(cred->cr_label);
2461         obj = SLOT(dvplabel);
2462
2463         if (!mls_dominate_effective(obj, subj))
2464                 return (EACCES);
2465
2466         obj = SLOT(vplabel);
2467         if (!mls_dominate_effective(obj, subj))
2468                 return (EACCES);
2469
2470         return (0);
2471 }
2472
2473 static int
2474 mls_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
2475     struct label *vplabel, int attrnamespace)
2476 {
2477
2478         struct mac_mls *subj, *obj;
2479
2480         if (!mls_enabled)
2481                 return (0);
2482
2483         subj = SLOT(cred->cr_label);
2484         obj = SLOT(vplabel);
2485
2486         if (!mls_dominate_effective(subj, obj))
2487                 return (EACCES);
2488
2489         return (0);
2490 }
2491
2492 static int
2493 mls_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
2494     struct label *dvplabel, struct componentname *cnp)
2495 {
2496         struct mac_mls *subj, *obj;
2497
2498         if (!mls_enabled)
2499                 return (0);
2500
2501         subj = SLOT(cred->cr_label);
2502         obj = SLOT(dvplabel);
2503
2504         if (!mls_dominate_effective(subj, obj))
2505                 return (EACCES);
2506
2507         return (0);
2508 }
2509
2510 static int
2511 mls_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2512     struct label *vplabel, int prot, int flags)
2513 {
2514         struct mac_mls *subj, *obj;
2515
2516         /*
2517          * Rely on the use of open()-time protections to handle
2518          * non-revocation cases.
2519          */
2520         if (!mls_enabled || !revocation_enabled)
2521                 return (0);
2522
2523         subj = SLOT(cred->cr_label);
2524         obj = SLOT(vplabel);
2525
2526         if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2527                 if (!mls_dominate_effective(subj, obj))
2528                         return (EACCES);
2529         }
2530         if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2531                 if (!mls_dominate_effective(obj, subj))
2532                         return (EACCES);
2533         }
2534
2535         return (0);
2536 }
2537
2538 static int
2539 mls_vnode_check_open(struct ucred *cred, struct vnode *vp,
2540     struct label *vplabel, accmode_t accmode)
2541 {
2542         struct mac_mls *subj, *obj;
2543
2544         if (!mls_enabled)
2545                 return (0);
2546
2547         subj = SLOT(cred->cr_label);
2548         obj = SLOT(vplabel);
2549
2550         /* XXX privilege override for admin? */
2551         if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
2552                 if (!mls_dominate_effective(subj, obj))
2553                         return (EACCES);
2554         }
2555         if (accmode & VMODIFY_PERMS) {
2556                 if (!mls_dominate_effective(obj, subj))
2557                         return (EACCES);
2558         }
2559
2560         return (0);
2561 }
2562
2563 static int
2564 mls_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
2565     struct vnode *vp, struct label *vplabel)
2566 {
2567         struct mac_mls *subj, *obj;
2568
2569         if (!mls_enabled || !revocation_enabled)
2570                 return (0);
2571
2572         subj = SLOT(active_cred->cr_label);
2573         obj = SLOT(vplabel);
2574
2575         if (!mls_dominate_effective(subj, obj))
2576                 return (EACCES);
2577
2578         return (0);
2579 }
2580
2581 static int
2582 mls_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2583     struct vnode *vp, struct label *vplabel)
2584 {
2585         struct mac_mls *subj, *obj;
2586
2587         if (!mls_enabled || !revocation_enabled)
2588                 return (0);
2589
2590         subj = SLOT(active_cred->cr_label);
2591         obj = SLOT(vplabel);
2592
2593         if (!mls_dominate_effective(subj, obj))
2594                 return (EACCES);
2595
2596         return (0);
2597 }
2598
2599 static int
2600 mls_vnode_check_readdir(struct ucred *cred, struct vnode *dvp,
2601     struct label *dvplabel)
2602 {
2603         struct mac_mls *subj, *obj;
2604
2605         if (!mls_enabled)
2606                 return (0);
2607
2608         subj = SLOT(cred->cr_label);
2609         obj = SLOT(dvplabel);
2610
2611         if (!mls_dominate_effective(subj, obj))
2612                 return (EACCES);
2613
2614         return (0);
2615 }
2616
2617 static int
2618 mls_vnode_check_readlink(struct ucred *cred, struct vnode *vp,
2619     struct label *vplabel)
2620 {
2621         struct mac_mls *subj, *obj;
2622
2623         if (!mls_enabled)
2624                 return (0);
2625
2626         subj = SLOT(cred->cr_label);
2627         obj = SLOT(vplabel);
2628
2629         if (!mls_dominate_effective(subj, obj))
2630                 return (EACCES);
2631
2632         return (0);
2633 }
2634
2635 static int
2636 mls_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2637     struct label *vplabel, struct label *newlabel)
2638 {
2639         struct mac_mls *old, *new, *subj;
2640         int error;
2641
2642         old = SLOT(vplabel);
2643         new = SLOT(newlabel);
2644         subj = SLOT(cred->cr_label);
2645
2646         /*
2647          * If there is an MLS label update for the vnode, it must be a
2648          * effective label.
2649          */
2650         error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2651         if (error)
2652                 return (error);
2653
2654         /*
2655          * To perform a relabel of the vnode (MLS label or not), MLS must
2656          * authorize the relabel.
2657          */
2658         if (!mls_effective_in_range(old, subj))
2659                 return (EPERM);
2660
2661         /*
2662          * If the MLS label is to be changed, authorize as appropriate.
2663          */
2664         if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2665                 /*
2666                  * To change the MLS label on a vnode, the new vnode label
2667                  * must be in the subject range.
2668                  */
2669                 if (!mls_effective_in_range(new, subj))
2670                         return (EPERM);
2671
2672                 /*
2673                  * To change the MLS label on the vnode to be EQUAL, the
2674                  * subject must have appropriate privilege.
2675                  */
2676                 if (mls_contains_equal(new)) {
2677                         error = mls_subject_privileged(subj);
2678                         if (error)
2679                                 return (error);
2680                 }
2681         }
2682
2683         return (0);
2684 }
2685
2686 static int
2687 mls_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2688     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2689     struct componentname *cnp)
2690 {
2691         struct mac_mls *subj, *obj;
2692
2693         if (!mls_enabled)
2694                 return (0);
2695
2696         subj = SLOT(cred->cr_label);
2697         obj = SLOT(dvplabel);
2698
2699         if (!mls_dominate_effective(obj, subj))
2700                 return (EACCES);
2701
2702         obj = SLOT(vplabel);
2703
2704         if (!mls_dominate_effective(obj, subj))
2705                 return (EACCES);
2706
2707         return (0);
2708 }
2709
2710 static int
2711 mls_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2712     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2713     int samedir, struct componentname *cnp)
2714 {
2715         struct mac_mls *subj, *obj;
2716
2717         if (!mls_enabled)
2718                 return (0);
2719
2720         subj = SLOT(cred->cr_label);
2721         obj = SLOT(dvplabel);
2722
2723         if (!mls_dominate_effective(obj, subj))
2724                 return (EACCES);
2725
2726         if (vp != NULL) {
2727                 obj = SLOT(vplabel);
2728
2729                 if (!mls_dominate_effective(obj, subj))
2730                         return (EACCES);
2731         }
2732
2733         return (0);
2734 }
2735
2736 static int
2737 mls_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2738     struct label *vplabel)
2739 {
2740         struct mac_mls *subj, *obj;
2741
2742         if (!mls_enabled)
2743                 return (0);
2744
2745         subj = SLOT(cred->cr_label);
2746         obj = SLOT(vplabel);
2747
2748         if (!mls_dominate_effective(obj, subj))
2749                 return (EACCES);
2750
2751         return (0);
2752 }
2753
2754 static int
2755 mls_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2756     struct label *vplabel, acl_type_t type, struct acl *acl)
2757 {
2758         struct mac_mls *subj, *obj;
2759
2760         if (!mls_enabled)
2761                 return (0);
2762
2763         subj = SLOT(cred->cr_label);
2764         obj = SLOT(vplabel);
2765
2766         if (!mls_dominate_effective(obj, subj))
2767                 return (EACCES);
2768
2769         return (0);
2770 }
2771
2772 static int
2773 mls_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2774     struct label *vplabel, int attrnamespace, const char *name)
2775 {
2776         struct mac_mls *subj, *obj;
2777
2778         if (!mls_enabled)
2779                 return (0);
2780
2781         subj = SLOT(cred->cr_label);
2782         obj = SLOT(vplabel);
2783
2784         if (!mls_dominate_effective(obj, subj))
2785                 return (EACCES);
2786
2787         /* XXX: protect the MAC EA in a special way? */
2788
2789         return (0);
2790 }
2791
2792 static int
2793 mls_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
2794     struct label *vplabel, u_long flags)
2795 {
2796         struct mac_mls *subj, *obj;
2797
2798         if (!mls_enabled)
2799                 return (0);
2800
2801         subj = SLOT(cred->cr_label);
2802         obj = SLOT(vplabel);
2803
2804         if (!mls_dominate_effective(obj, subj))
2805                 return (EACCES);
2806
2807         return (0);
2808 }
2809
2810 static int
2811 mls_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
2812     struct label *vplabel, mode_t mode)
2813 {
2814         struct mac_mls *subj, *obj;
2815
2816         if (!mls_enabled)
2817                 return (0);
2818
2819         subj = SLOT(cred->cr_label);
2820         obj = SLOT(vplabel);
2821
2822         if (!mls_dominate_effective(obj, subj))
2823                 return (EACCES);
2824
2825         return (0);
2826 }
2827
2828 static int
2829 mls_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
2830     struct label *vplabel, uid_t uid, gid_t gid)
2831 {
2832         struct mac_mls *subj, *obj;
2833
2834         if (!mls_enabled)
2835                 return (0);
2836
2837         subj = SLOT(cred->cr_label);
2838         obj = SLOT(vplabel);
2839
2840         if (!mls_dominate_effective(obj, subj))
2841                 return (EACCES);
2842
2843         return (0);
2844 }
2845
2846 static int
2847 mls_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
2848     struct label *vplabel, struct timespec atime, struct timespec mtime)
2849 {
2850         struct mac_mls *subj, *obj;
2851
2852         if (!mls_enabled)
2853                 return (0);
2854
2855         subj = SLOT(cred->cr_label);
2856         obj = SLOT(vplabel);
2857
2858         if (!mls_dominate_effective(obj, subj))
2859                 return (EACCES);
2860
2861         return (0);
2862 }
2863
2864 static int
2865 mls_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
2866     struct vnode *vp, struct label *vplabel)
2867 {
2868         struct mac_mls *subj, *obj;
2869
2870         if (!mls_enabled)
2871                 return (0);
2872
2873         subj = SLOT(active_cred->cr_label);
2874         obj = SLOT(vplabel);
2875
2876         if (!mls_dominate_effective(subj, obj))
2877                 return (EACCES);
2878
2879         return (0);
2880 }
2881
2882 static int
2883 mls_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
2884     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2885     struct componentname *cnp)
2886 {
2887         struct mac_mls *subj, *obj;
2888
2889         if (!mls_enabled)
2890                 return (0);
2891
2892         subj = SLOT(cred->cr_label);
2893         obj = SLOT(dvplabel);
2894
2895         if (!mls_dominate_effective(obj, subj))
2896                 return (EACCES);
2897
2898         obj = SLOT(vplabel);
2899
2900         if (!mls_dominate_effective(obj, subj))
2901                 return (EACCES);
2902
2903         return (0);
2904 }
2905
2906 static int
2907 mls_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
2908     struct vnode *vp, struct label *vplabel)
2909 {
2910         struct mac_mls *subj, *obj;
2911
2912         if (!mls_enabled || !revocation_enabled)
2913                 return (0);
2914
2915         subj = SLOT(active_cred->cr_label);
2916         obj = SLOT(vplabel);
2917
2918         if (!mls_dominate_effective(obj, subj))
2919                 return (EACCES);
2920
2921         return (0);
2922 }
2923
2924 static int
2925 mls_vnode_create_extattr(struct ucred *cred, struct mount *mp,
2926     struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
2927     struct vnode *vp, struct label *vplabel, struct componentname *cnp)
2928 {
2929         struct mac_mls *source, *dest, mm_temp;
2930         size_t buflen;
2931         int error;
2932
2933         buflen = sizeof(mm_temp);
2934         bzero(&mm_temp, buflen);
2935
2936         source = SLOT(cred->cr_label);
2937         dest = SLOT(vplabel);
2938         mls_copy_effective(source, &mm_temp);
2939
2940         error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2941             MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
2942         if (error == 0)
2943                 mls_copy_effective(source, dest);
2944         return (error);
2945 }
2946
2947 static void
2948 mls_vnode_relabel(struct ucred *cred, struct vnode *vp,
2949     struct label *vplabel, struct label *label)
2950 {
2951         struct mac_mls *source, *dest;
2952
2953         source = SLOT(label);
2954         dest = SLOT(vplabel);
2955
2956         mls_copy(source, dest);
2957 }
2958
2959 static int
2960 mls_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
2961     struct label *vplabel, struct label *intlabel)
2962 {
2963         struct mac_mls *source, mm_temp;
2964         size_t buflen;
2965         int error;
2966
2967         buflen = sizeof(mm_temp);
2968         bzero(&mm_temp, buflen);
2969
2970         source = SLOT(intlabel);
2971         if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
2972                 return (0);
2973
2974         mls_copy_effective(source, &mm_temp);
2975
2976         error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2977             MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
2978         return (error);
2979 }
2980
2981 static struct mac_policy_ops mls_ops =
2982 {
2983         .mpo_init = mls_init,
2984
2985         .mpo_bpfdesc_check_receive = mls_bpfdesc_check_receive,
2986         .mpo_bpfdesc_create = mls_bpfdesc_create,
2987         .mpo_bpfdesc_create_mbuf = mls_bpfdesc_create_mbuf,
2988         .mpo_bpfdesc_destroy_label = mls_destroy_label,
2989         .mpo_bpfdesc_init_label = mls_init_label,
2990
2991         .mpo_cred_associate_nfsd = mls_cred_associate_nfsd,
2992         .mpo_cred_check_relabel = mls_cred_check_relabel,
2993         .mpo_cred_check_visible = mls_cred_check_visible,
2994         .mpo_cred_copy_label = mls_copy_label,
2995         .mpo_cred_create_init = mls_cred_create_init,
2996         .mpo_cred_create_swapper = mls_cred_create_swapper,
2997         .mpo_cred_destroy_label = mls_destroy_label,
2998         .mpo_cred_externalize_label = mls_externalize_label,
2999         .mpo_cred_init_label = mls_init_label,
3000         .mpo_cred_internalize_label = mls_internalize_label,
3001         .mpo_cred_relabel = mls_cred_relabel,
3002
3003         .mpo_devfs_create_device = mls_devfs_create_device,
3004         .mpo_devfs_create_directory = mls_devfs_create_directory,
3005         .mpo_devfs_create_symlink = mls_devfs_create_symlink,
3006         .mpo_devfs_destroy_label = mls_destroy_label,
3007         .mpo_devfs_init_label = mls_init_label,
3008         .mpo_devfs_update = mls_devfs_update,
3009         .mpo_devfs_vnode_associate = mls_devfs_vnode_associate,
3010
3011         .mpo_ifnet_check_relabel = mls_ifnet_check_relabel,
3012         .mpo_ifnet_check_transmit = mls_ifnet_check_transmit,
3013         .mpo_ifnet_copy_label = mls_copy_label,
3014         .mpo_ifnet_create = mls_ifnet_create,
3015         .mpo_ifnet_create_mbuf = mls_ifnet_create_mbuf,
3016         .mpo_ifnet_destroy_label = mls_destroy_label,
3017         .mpo_ifnet_externalize_label = mls_externalize_label,
3018         .mpo_ifnet_init_label = mls_init_label,
3019         .mpo_ifnet_internalize_label = mls_internalize_label,
3020         .mpo_ifnet_relabel = mls_ifnet_relabel,
3021
3022         .mpo_inpcb_check_deliver = mls_inpcb_check_deliver,
3023         .mpo_inpcb_check_visible = mls_inpcb_check_visible,
3024         .mpo_inpcb_create = mls_inpcb_create,
3025         .mpo_inpcb_create_mbuf = mls_inpcb_create_mbuf,
3026         .mpo_inpcb_destroy_label = mls_destroy_label,
3027         .mpo_inpcb_init_label = mls_init_label_waitcheck,
3028         .mpo_inpcb_sosetlabel = mls_inpcb_sosetlabel,
3029
3030         .mpo_ip6q_create = mls_ip6q_create,
3031         .mpo_ip6q_destroy_label = mls_destroy_label,
3032         .mpo_ip6q_init_label = mls_init_label_waitcheck,
3033         .mpo_ip6q_match = mls_ip6q_match,
3034         .mpo_ip6q_reassemble = mls_ip6q_reassemble,
3035         .mpo_ip6q_update = mls_ip6q_update,
3036
3037         .mpo_ipq_create = mls_ipq_create,
3038         .mpo_ipq_destroy_label = mls_destroy_label,
3039         .mpo_ipq_init_label = mls_init_label_waitcheck,
3040         .mpo_ipq_match = mls_ipq_match,
3041         .mpo_ipq_reassemble = mls_ipq_reassemble,
3042         .mpo_ipq_update = mls_ipq_update,
3043
3044         .mpo_mbuf_copy_label = mls_copy_label,
3045         .mpo_mbuf_destroy_label = mls_destroy_label,
3046         .mpo_mbuf_init_label = mls_init_label_waitcheck,
3047
3048         .mpo_mount_check_stat = mls_mount_check_stat,
3049         .mpo_mount_create = mls_mount_create,
3050         .mpo_mount_destroy_label = mls_destroy_label,
3051         .mpo_mount_init_label = mls_init_label,
3052
3053         .mpo_netatalk_aarp_send = mls_netatalk_aarp_send,
3054
3055         .mpo_netinet_arp_send = mls_netinet_arp_send,
3056         .mpo_netinet_firewall_reply = mls_netinet_firewall_reply,
3057         .mpo_netinet_firewall_send = mls_netinet_firewall_send,
3058         .mpo_netinet_fragment = mls_netinet_fragment,
3059         .mpo_netinet_icmp_reply = mls_netinet_icmp_reply,
3060         .mpo_netinet_igmp_send = mls_netinet_igmp_send,
3061
3062         .mpo_netinet6_nd6_send = mls_netinet6_nd6_send,
3063
3064         .mpo_pipe_check_ioctl = mls_pipe_check_ioctl,
3065         .mpo_pipe_check_poll = mls_pipe_check_poll,
3066         .mpo_pipe_check_read = mls_pipe_check_read,
3067         .mpo_pipe_check_relabel = mls_pipe_check_relabel,
3068         .mpo_pipe_check_stat = mls_pipe_check_stat,
3069         .mpo_pipe_check_write = mls_pipe_check_write,
3070         .mpo_pipe_copy_label = mls_copy_label,
3071         .mpo_pipe_create = mls_pipe_create,
3072         .mpo_pipe_destroy_label = mls_destroy_label,
3073         .mpo_pipe_externalize_label = mls_externalize_label,
3074         .mpo_pipe_init_label = mls_init_label,
3075         .mpo_pipe_internalize_label = mls_internalize_label,
3076         .mpo_pipe_relabel = mls_pipe_relabel,
3077
3078         .mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly,
3079         .mpo_posixsem_check_open = mls_posixsem_check_openunlink,
3080         .mpo_posixsem_check_post = mls_posixsem_check_write,
3081         .mpo_posixsem_check_stat = mls_posixsem_check_rdonly,
3082         .mpo_posixsem_check_unlink = mls_posixsem_check_openunlink,
3083         .mpo_posixsem_check_wait = mls_posixsem_check_write,
3084         .mpo_posixsem_create = mls_posixsem_create,
3085         .mpo_posixsem_destroy_label = mls_destroy_label,
3086         .mpo_posixsem_init_label = mls_init_label,
3087
3088         .mpo_proc_check_debug = mls_proc_check_debug,
3089         .mpo_proc_check_sched = mls_proc_check_sched,
3090         .mpo_proc_check_signal = mls_proc_check_signal,
3091
3092         .mpo_socket_check_deliver = mls_socket_check_deliver,
3093         .mpo_socket_check_relabel = mls_socket_check_relabel,
3094         .mpo_socket_check_visible = mls_socket_check_visible,
3095         .mpo_socket_copy_label = mls_copy_label,
3096         .mpo_socket_create = mls_socket_create,
3097         .mpo_socket_create_mbuf = mls_socket_create_mbuf,
3098         .mpo_socket_destroy_label = mls_destroy_label,
3099         .mpo_socket_externalize_label = mls_externalize_label,
3100         .mpo_socket_init_label = mls_init_label_waitcheck,
3101         .mpo_socket_internalize_label = mls_internalize_label,
3102         .mpo_socket_newconn = mls_socket_newconn,
3103         .mpo_socket_relabel = mls_socket_relabel,
3104
3105         .mpo_socketpeer_destroy_label = mls_destroy_label,
3106         .mpo_socketpeer_externalize_label = mls_externalize_label,
3107         .mpo_socketpeer_init_label = mls_init_label_waitcheck,
3108         .mpo_socketpeer_set_from_mbuf = mls_socketpeer_set_from_mbuf,
3109         .mpo_socketpeer_set_from_socket = mls_socketpeer_set_from_socket,
3110
3111         .mpo_syncache_create = mls_syncache_create,
3112         .mpo_syncache_create_mbuf = mls_syncache_create_mbuf,
3113         .mpo_syncache_destroy_label = mls_destroy_label,
3114         .mpo_syncache_init_label = mls_init_label_waitcheck,
3115
3116         .mpo_sysvmsg_cleanup = mls_sysvmsg_cleanup,
3117         .mpo_sysvmsg_create = mls_sysvmsg_create,
3118         .mpo_sysvmsg_destroy_label = mls_destroy_label,
3119         .mpo_sysvmsg_init_label = mls_init_label,
3120
3121         .mpo_sysvmsq_check_msgrcv = mls_sysvmsq_check_msgrcv,
3122         .mpo_sysvmsq_check_msgrmid = mls_sysvmsq_check_msgrmid,
3123         .mpo_sysvmsq_check_msqget = mls_sysvmsq_check_msqget,
3124         .mpo_sysvmsq_check_msqsnd = mls_sysvmsq_check_msqsnd,
3125         .mpo_sysvmsq_check_msqrcv = mls_sysvmsq_check_msqrcv,
3126         .mpo_sysvmsq_check_msqctl = mls_sysvmsq_check_msqctl,
3127         .mpo_sysvmsq_cleanup = mls_sysvmsq_cleanup,
3128         .mpo_sysvmsq_destroy_label = mls_destroy_label,
3129         .mpo_sysvmsq_init_label = mls_init_label,
3130         .mpo_sysvmsq_create = mls_sysvmsq_create,
3131
3132         .mpo_sysvsem_check_semctl = mls_sysvsem_check_semctl,
3133         .mpo_sysvsem_check_semget = mls_sysvsem_check_semget,
3134         .mpo_sysvsem_check_semop = mls_sysvsem_check_semop,
3135         .mpo_sysvsem_cleanup = mls_sysvsem_cleanup,
3136         .mpo_sysvsem_create = mls_sysvsem_create,
3137         .mpo_sysvsem_destroy_label = mls_destroy_label,
3138         .mpo_sysvsem_init_label = mls_init_label,
3139
3140         .mpo_sysvshm_check_shmat = mls_sysvshm_check_shmat,
3141         .mpo_sysvshm_check_shmctl = mls_sysvshm_check_shmctl,
3142         .mpo_sysvshm_check_shmget = mls_sysvshm_check_shmget,
3143         .mpo_sysvshm_cleanup = mls_sysvshm_cleanup,
3144         .mpo_sysvshm_create = mls_sysvshm_create,
3145         .mpo_sysvshm_destroy_label = mls_destroy_label,
3146         .mpo_sysvshm_init_label = mls_init_label,
3147
3148
3149         .mpo_system_check_acct = mls_system_check_acct,
3150         .mpo_system_check_auditctl = mls_system_check_auditctl,
3151         .mpo_system_check_swapon = mls_system_check_swapon,
3152
3153         .mpo_vnode_associate_extattr = mls_vnode_associate_extattr,
3154         .mpo_vnode_associate_singlelabel = mls_vnode_associate_singlelabel,
3155         .mpo_vnode_check_access = mls_vnode_check_open,
3156         .mpo_vnode_check_chdir = mls_vnode_check_chdir,
3157         .mpo_vnode_check_chroot = mls_vnode_check_chroot,
3158         .mpo_vnode_check_create = mls_vnode_check_create,
3159         .mpo_vnode_check_deleteacl = mls_vnode_check_deleteacl,
3160         .mpo_vnode_check_deleteextattr = mls_vnode_check_deleteextattr,
3161         .mpo_vnode_check_exec = mls_vnode_check_exec,
3162         .mpo_vnode_check_getacl = mls_vnode_check_getacl,
3163         .mpo_vnode_check_getextattr = mls_vnode_check_getextattr,
3164         .mpo_vnode_check_link = mls_vnode_check_link,
3165         .mpo_vnode_check_listextattr = mls_vnode_check_listextattr,
3166         .mpo_vnode_check_lookup = mls_vnode_check_lookup,
3167         .mpo_vnode_check_mmap = mls_vnode_check_mmap,
3168         .mpo_vnode_check_open = mls_vnode_check_open,
3169         .mpo_vnode_check_poll = mls_vnode_check_poll,
3170         .mpo_vnode_check_read = mls_vnode_check_read,
3171         .mpo_vnode_check_readdir = mls_vnode_check_readdir,
3172         .mpo_vnode_check_readlink = mls_vnode_check_readlink,
3173         .mpo_vnode_check_relabel = mls_vnode_check_relabel,
3174         .mpo_vnode_check_rename_from = mls_vnode_check_rename_from,
3175         .mpo_vnode_check_rename_to = mls_vnode_check_rename_to,
3176         .mpo_vnode_check_revoke = mls_vnode_check_revoke,
3177         .mpo_vnode_check_setacl = mls_vnode_check_setacl,
3178         .mpo_vnode_check_setextattr = mls_vnode_check_setextattr,
3179         .mpo_vnode_check_setflags = mls_vnode_check_setflags,
3180         .mpo_vnode_check_setmode = mls_vnode_check_setmode,
3181         .mpo_vnode_check_setowner = mls_vnode_check_setowner,
3182         .mpo_vnode_check_setutimes = mls_vnode_check_setutimes,
3183         .mpo_vnode_check_stat = mls_vnode_check_stat,
3184         .mpo_vnode_check_unlink = mls_vnode_check_unlink,
3185         .mpo_vnode_check_write = mls_vnode_check_write,
3186         .mpo_vnode_copy_label = mls_copy_label,
3187         .mpo_vnode_create_extattr = mls_vnode_create_extattr,
3188         .mpo_vnode_destroy_label = mls_destroy_label,
3189         .mpo_vnode_externalize_label = mls_externalize_label,
3190         .mpo_vnode_init_label = mls_init_label,
3191         .mpo_vnode_internalize_label = mls_internalize_label,
3192         .mpo_vnode_relabel = mls_vnode_relabel,
3193         .mpo_vnode_setlabel_extattr = mls_vnode_setlabel_extattr,
3194 };
3195
3196 MAC_POLICY_SET(&mls_ops, mac_mls, "TrustedBSD MAC/MLS",
3197     MPC_LOADTIME_FLAG_NOTLATE, &mls_slot);