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