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