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