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