1 /*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, 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 Network
9 * Associates Laboratories, the Security Research Division of Network
10 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
11 * as part of the DARPA 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: src/sys/security/mac_mls/mac_mls.c,v 1.47.2.2 2003/06/02 18:59:29 rwatson Exp $
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/malloc.h>
50 #include <sys/mount.h>
51 #include <sys/proc.h>
52 #include <sys/sbuf.h>
53 #include <sys/systm.h>
54 #include <sys/sysproto.h>
55 #include <sys/sysent.h>
56 #include <sys/systm.h>
57 #include <sys/vnode.h>
58 #include <sys/file.h>
59 #include <sys/socket.h>
60 #include <sys/socketvar.h>
61 #include <sys/pipe.h>
62 #include <sys/sysctl.h>
63
64 #include <fs/devfs/devfs.h>
65
66 #include <net/bpfdesc.h>
67 #include <net/if.h>
68 #include <net/if_types.h>
69 #include <net/if_var.h>
70
71 #include <netinet/in.h>
72 #include <netinet/ip_var.h>
73
74 #include <vm/vm.h>
75
76 #include <sys/mac_policy.h>
77
78 #include <security/mac_mls/mac_mls.h>
79
80 SYSCTL_DECL(_security_mac);
81
82 SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
83 "TrustedBSD mac_mls policy controls");
84
85 static int mac_mls_label_size = sizeof(struct mac_mls);
86 SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
87 &mac_mls_label_size, 0, "Size of struct mac_mls");
88
89 static int mac_mls_enabled = 1;
90 SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
91 &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
92 TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
93
94 static int destroyed_not_inited;
95 SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
96 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
97
98 static int ptys_equal = 0;
99 SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
100 &ptys_equal, 0, "Label pty devices as mls/equal on create");
101 TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
102
103 static int revocation_enabled = 0;
104 SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
105 &revocation_enabled, 0, "Revoke access to objects on relabel");
106 TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
107
108 static int max_compartments = MAC_MLS_MAX_COMPARTMENTS;
109 SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
110 &max_compartments, 0, "Maximum compartments the policy supports");
111
112 static int mac_mls_slot;
113 #define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
114
115 MALLOC_DEFINE(M_MACMLS, "mls label", "MAC/MLS labels");
116
117 static __inline int
118 mls_bit_set_empty(u_char *set) {
119 int i;
120
121 for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
122 if (set[i] != 0)
123 return (0);
124 return (1);
125 }
126
127 static struct mac_mls *
128 mls_alloc(int flag)
129 {
130 struct mac_mls *mac_mls;
131
132 mac_mls = malloc(sizeof(struct mac_mls), M_MACMLS, M_ZERO | flag);
133
134 return (mac_mls);
135 }
136
137 static void
138 mls_free(struct mac_mls *mac_mls)
139 {
140
141 if (mac_mls != NULL)
142 free(mac_mls, M_MACMLS);
143 else
144 atomic_add_int(&destroyed_not_inited, 1);
145 }
146
147 static int
148 mls_atmostflags(struct mac_mls *mac_mls, int flags)
149 {
150
151 if ((mac_mls->mm_flags & flags) != mac_mls->mm_flags)
152 return (EINVAL);
153 return (0);
154 }
155
156 static int
157 mac_mls_dominate_element(struct mac_mls_element *a,
158 struct mac_mls_element *b)
159 {
160 int bit;
161
162 switch (a->mme_type) {
163 case MAC_MLS_TYPE_EQUAL:
164 case MAC_MLS_TYPE_HIGH:
165 return (1);
166
167 case MAC_MLS_TYPE_LOW:
168 switch (b->mme_type) {
169 case MAC_MLS_TYPE_LEVEL:
170 case MAC_MLS_TYPE_HIGH:
171 return (0);
172
173 case MAC_MLS_TYPE_EQUAL:
174 case MAC_MLS_TYPE_LOW:
175 return (1);
176
177 default:
178 panic("mac_mls_dominate_element: b->mme_type invalid");
179 }
180
181 case MAC_MLS_TYPE_LEVEL:
182 switch (b->mme_type) {
183 case MAC_MLS_TYPE_EQUAL:
184 case MAC_MLS_TYPE_LOW:
185 return (1);
186
187 case MAC_MLS_TYPE_HIGH:
188 return (0);
189
190 case MAC_MLS_TYPE_LEVEL:
191 for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
192 if (!MAC_MLS_BIT_TEST(bit,
193 a->mme_compartments) &&
194 MAC_MLS_BIT_TEST(bit, b->mme_compartments))
195 return (0);
196 return (a->mme_level >= b->mme_level);
197
198 default:
199 panic("mac_mls_dominate_element: b->mme_type invalid");
200 }
201
202 default:
203 panic("mac_mls_dominate_element: a->mme_type invalid");
204 }
205
206 return (0);
207 }
208
209 static int
210 mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
211 {
212
213 return (mac_mls_dominate_element(&rangeb->mm_rangehigh,
214 &rangea->mm_rangehigh) &&
215 mac_mls_dominate_element(&rangea->mm_rangelow,
216 &rangeb->mm_rangelow));
217 }
218
219 static int
220 mac_mls_single_in_range(struct mac_mls *single, struct mac_mls *range)
221 {
222
223 KASSERT((single->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
224 ("mac_mls_single_in_range: a not single"));
225 KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
226 ("mac_mls_single_in_range: b not range"));
227
228 return (mac_mls_dominate_element(&range->mm_rangehigh,
229 &single->mm_single) &&
230 mac_mls_dominate_element(&single->mm_single,
231 &range->mm_rangelow));
232
233 return (1);
234 }
235
236 static int
237 mac_mls_dominate_single(struct mac_mls *a, struct mac_mls *b)
238 {
239 KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
240 ("mac_mls_dominate_single: a not single"));
241 KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
242 ("mac_mls_dominate_single: b not single"));
243
244 return (mac_mls_dominate_element(&a->mm_single, &b->mm_single));
245 }
246
247 static int
248 mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
249 {
250
251 if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
252 b->mme_type == MAC_MLS_TYPE_EQUAL)
253 return (1);
254
255 return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
256 }
257
258 static int
259 mac_mls_equal_single(struct mac_mls *a, struct mac_mls *b)
260 {
261
262 KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
263 ("mac_mls_equal_single: a not single"));
264 KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
265 ("mac_mls_equal_single: b not single"));
266
267 return (mac_mls_equal_element(&a->mm_single, &b->mm_single));
268 }
269
270 static int
271 mac_mls_contains_equal(struct mac_mls *mac_mls)
272 {
273
274 if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE)
275 if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL)
276 return (1);
277
278 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
279 if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
280 return (1);
281 if (mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
282 return (1);
283 }
284
285 return (0);
286 }
287
288 static int
289 mac_mls_subject_equal_ok(struct mac_mls *mac_mls)
290 {
291
292 KASSERT((mac_mls->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH,
293 ("mac_mls_subject_equal_ok: subject doesn't have both labels"));
294
295 /* If the single is EQUAL, it's ok. */
296 if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL)
297 return (0);
298
299 /* If either range endpoint is EQUAL, it's ok. */
300 if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
301 mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
302 return (0);
303
304 /* If the range is low-high, it's ok. */
305 if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
306 mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
307 return (0);
308
309 /* It's not ok. */
310 return (EPERM);
311 }
312
313 static int
314 mac_mls_valid(struct mac_mls *mac_mls)
315 {
316
317 if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
318 switch (mac_mls->mm_single.mme_type) {
319 case MAC_MLS_TYPE_LEVEL:
320 break;
321
322 case MAC_MLS_TYPE_EQUAL:
323 case MAC_MLS_TYPE_HIGH:
324 case MAC_MLS_TYPE_LOW:
325 if (mac_mls->mm_single.mme_level != 0 ||
326 !MAC_MLS_BIT_SET_EMPTY(
327 mac_mls->mm_single.mme_compartments))
328 return (EINVAL);
329 break;
330
331 default:
332 return (EINVAL);
333 }
334 } else {
335 if (mac_mls->mm_single.mme_type != MAC_MLS_TYPE_UNDEF)
336 return (EINVAL);
337 }
338
339 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
340 switch (mac_mls->mm_rangelow.mme_type) {
341 case MAC_MLS_TYPE_LEVEL:
342 break;
343
344 case MAC_MLS_TYPE_EQUAL:
345 case MAC_MLS_TYPE_HIGH:
346 case MAC_MLS_TYPE_LOW:
347 if (mac_mls->mm_rangelow.mme_level != 0 ||
348 !MAC_MLS_BIT_SET_EMPTY(
349 mac_mls->mm_rangelow.mme_compartments))
350 return (EINVAL);
351 break;
352
353 default:
354 return (EINVAL);
355 }
356
357 switch (mac_mls->mm_rangehigh.mme_type) {
358 case MAC_MLS_TYPE_LEVEL:
359 break;
360
361 case MAC_MLS_TYPE_EQUAL:
362 case MAC_MLS_TYPE_HIGH:
363 case MAC_MLS_TYPE_LOW:
364 if (mac_mls->mm_rangehigh.mme_level != 0 ||
365 !MAC_MLS_BIT_SET_EMPTY(
366 mac_mls->mm_rangehigh.mme_compartments))
367 return (EINVAL);
368 break;
369
370 default:
371 return (EINVAL);
372 }
373 if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh,
374 &mac_mls->mm_rangelow))
375 return (EINVAL);
376 } else {
377 if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
378 mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
379 return (EINVAL);
380 }
381
382 return (0);
383 }
384
385 static void
386 mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow,
387 u_short levellow, u_char *compartmentslow, u_short typehigh,
388 u_short levelhigh, u_char *compartmentshigh)
389 {
390
391 mac_mls->mm_rangelow.mme_type = typelow;
392 mac_mls->mm_rangelow.mme_level = levellow;
393 if (compartmentslow != NULL)
394 memcpy(mac_mls->mm_rangelow.mme_compartments,
395 compartmentslow,
396 sizeof(mac_mls->mm_rangelow.mme_compartments));
397 mac_mls->mm_rangehigh.mme_type = typehigh;
398 mac_mls->mm_rangehigh.mme_level = levelhigh;
399 if (compartmentshigh != NULL)
400 memcpy(mac_mls->mm_rangehigh.mme_compartments,
401 compartmentshigh,
402 sizeof(mac_mls->mm_rangehigh.mme_compartments));
403 mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
404 }
405
406 static void
407 mac_mls_set_single(struct mac_mls *mac_mls, u_short type, u_short level,
408 u_char *compartments)
409 {
410
411 mac_mls->mm_single.mme_type = type;
412 mac_mls->mm_single.mme_level = level;
413 if (compartments != NULL)
414 memcpy(mac_mls->mm_single.mme_compartments, compartments,
415 sizeof(mac_mls->mm_single.mme_compartments));
416 mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE;
417 }
418
419 static void
420 mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
421 {
422
423 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
424 ("mac_mls_copy_range: labelfrom not range"));
425
426 labelto->mm_rangelow = labelfrom->mm_rangelow;
427 labelto->mm_rangehigh = labelfrom->mm_rangehigh;
428 labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
429 }
430
431 static void
432 mac_mls_copy_single(struct mac_mls *labelfrom, struct mac_mls *labelto)
433 {
434
435 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
436 ("mac_mls_copy_single: labelfrom not single"));
437
438 labelto->mm_single = labelfrom->mm_single;
439 labelto->mm_flags |= MAC_MLS_FLAG_SINGLE;
440 }
441
442 static void
443 mac_mls_copy(struct mac_mls *source, struct mac_mls *dest)
444 {
445
446 if (source->mm_flags & MAC_MLS_FLAG_SINGLE)
447 mac_mls_copy_single(source, dest);
448 if (source->mm_flags & MAC_MLS_FLAG_RANGE)
449 mac_mls_copy_range(source, dest);
450 }
451
452 /*
453 * Policy module operations.
454 */
455 static void
456 mac_mls_destroy(struct mac_policy_conf *conf)
457 {
458
459 }
460
461 static void
462 mac_mls_init(struct mac_policy_conf *conf)
463 {
464
465 }
466
467 /*
468 * Label operations.
469 */
470 static void
471 mac_mls_init_label(struct label *label)
472 {
473
474 SLOT(label) = mls_alloc(M_WAITOK);
475 }
476
477 static int
478 mac_mls_init_label_waitcheck(struct label *label, int flag)
479 {
480
481 SLOT(label) = mls_alloc(flag);
482 if (SLOT(label) == NULL)
483 return (ENOMEM);
484
485 return (0);
486 }
487
488 static void
489 mac_mls_destroy_label(struct label *label)
490 {
491
492 mls_free(SLOT(label));
493 SLOT(label) = NULL;
494 }
495
496 /*
497 * mac_mls_element_to_string() accepts an sbuf and MLS element. It
498 * converts the MLS element to a string and stores the result in the
499 * sbuf; if there isn't space in the sbuf, -1 is returned.
500 */
501 static int
502 mac_mls_element_to_string(struct sbuf *sb, struct mac_mls_element *element)
503 {
504 int i, first;
505
506 switch (element->mme_type) {
507 case MAC_MLS_TYPE_HIGH:
508 return (sbuf_printf(sb, "high"));
509
510 case MAC_MLS_TYPE_LOW:
511 return (sbuf_printf(sb, "low"));
512
513 case MAC_MLS_TYPE_EQUAL:
514 return (sbuf_printf(sb, "equal"));
515
516 case MAC_MLS_TYPE_LEVEL:
517 if (sbuf_printf(sb, "%d", element->mme_level) == -1)
518 return (-1);
519
520 first = 1;
521 for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) {
522 if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) {
523 if (first) {
524 if (sbuf_putc(sb, ':') == -1)
525 return (-1);
526 if (sbuf_printf(sb, "%d", i) == -1)
527 return (-1);
528 first = 0;
529 } else {
530 if (sbuf_printf(sb, "+%d", i) == -1)
531 return (-1);
532 }
533 }
534 }
535 return (0);
536
537 default:
538 panic("mac_mls_element_to_string: invalid type (%d)",
539 element->mme_type);
540 }
541 }
542
543 /*
544 * mac_mls_to_string() converts an MLS label to a string, placing the
545 * results in the passed string buffer. It returns 0 on success,
546 * or EINVAL if there isn't room in the buffer. The size of the
547 * string appended, leaving out the nul termination, is returned to
548 * the caller via *caller_len. Eventually, we should expose the
549 * sbuf to the caller rather than using C strings at this layer.
550 */
551 static int
552 mac_mls_to_string(char *string, size_t size, size_t *caller_len,
553 struct mac_mls *mac_mls)
554 {
555 struct sbuf sb;
556
557 sbuf_new(&sb, string, size, SBUF_FIXEDLEN);
558
559 if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
560 if (mac_mls_element_to_string(&sb, &mac_mls->mm_single)
561 == -1)
562 return (EINVAL);
563 }
564
565 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
566 if (sbuf_putc(&sb, '(') == -1)
567 return (EINVAL);
568
569 if (mac_mls_element_to_string(&sb, &mac_mls->mm_rangelow)
570 == -1)
571 return (EINVAL);
572
573 if (sbuf_putc(&sb, '-') == -1)
574 return (EINVAL);
575
576 if (mac_mls_element_to_string(&sb, &mac_mls->mm_rangehigh)
577 == -1)
578 return (EINVAL);
579
580 if (sbuf_putc(&sb, ')') == -1)
581 return (EINVAL);
582 }
583
584 sbuf_finish(&sb);
585 *caller_len = strlen(string);
586 return (0);
587 }
588
589 static int
590 mac_mls_externalize_label(struct label *label, char *element_name,
591 char *element_data, size_t size, size_t *len, int *claimed)
592 {
593 struct mac_mls *mac_mls;
594 int error;
595
596 if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
597 return (0);
598
599 (*claimed)++;
600
601 mac_mls = SLOT(label);
602
603 error = mac_mls_to_string(element_data, size, len, mac_mls);
604 if (error)
605 return (error);
606
607 return (0);
608 }
609
610 static int
611 mac_mls_parse_element(struct mac_mls_element *element, char *string)
612 {
613 char *compartment, *end, *level;
614 int value;
615
616 if (strcmp(string, "high") == 0 ||
617 strcmp(string, "hi") == 0) {
618 element->mme_type = MAC_MLS_TYPE_HIGH;
619 element->mme_level = MAC_MLS_TYPE_UNDEF;
620 } else if (strcmp(string, "low") == 0 ||
621 strcmp(string, "lo") == 0) {
622 element->mme_type = MAC_MLS_TYPE_LOW;
623 element->mme_level = MAC_MLS_TYPE_UNDEF;
624 } else if (strcmp(string, "equal") == 0 ||
625 strcmp(string, "eq") == 0) {
626 element->mme_type = MAC_MLS_TYPE_EQUAL;
627 element->mme_level = MAC_MLS_TYPE_UNDEF;
628 } else {
629 element->mme_type = MAC_MLS_TYPE_LEVEL;
630
631 /*
632 * Numeric level piece of the element.
633 */
634 level = strsep(&string, ":");
635 value = strtol(level, &end, 10);
636 if (end == level || *end != '\0')
637 return (EINVAL);
638 if (value < 0 || value > 65535)
639 return (EINVAL);
640 element->mme_level = value;
641
642 /*
643 * Optional compartment piece of the element. If none
644 * are included, we assume that the label has no
645 * compartments.
646 */
647 if (string == NULL)
648 return (0);
649 if (*string == '\0')
650 return (0);
651
652 while ((compartment = strsep(&string, "+")) != NULL) {
653 value = strtol(compartment, &end, 10);
654 if (compartment == end || *end != '\0')
655 return (EINVAL);
656 if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS)
657 return (EINVAL);
658 MAC_MLS_BIT_SET(value, element->mme_compartments);
659 }
660 }
661
662 return (0);
663 }
664
665 /*
666 * Note: destructively consumes the string, make a local copy before
667 * calling if that's a problem.
668 */
669 static int
670 mac_mls_parse(struct mac_mls *mac_mls, char *string)
671 {
672 char *rangehigh, *rangelow, *single;
673 int error;
674
675 single = strsep(&string, "(");
676 if (*single == '\0')
677 single = NULL;
678
679 if (string != NULL) {
680 rangelow = strsep(&string, "-");
681 if (string == NULL)
682 return (EINVAL);
683 rangehigh = strsep(&string, ")");
684 if (string == NULL)
685 return (EINVAL);
686 if (*string != '\0')
687 return (EINVAL);
688 } else {
689 rangelow = NULL;
690 rangehigh = NULL;
691 }
692
693 KASSERT((rangelow != NULL && rangehigh != NULL) ||
694 (rangelow == NULL && rangehigh == NULL),
695 ("mac_mls_parse: range mismatch"));
696
697 bzero(mac_mls, sizeof(*mac_mls));
698 if (single != NULL) {
699 error = mac_mls_parse_element(&mac_mls->mm_single, single);
700 if (error)
701 return (error);
702 mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE;
703 }
704
705 if (rangelow != NULL) {
706 error = mac_mls_parse_element(&mac_mls->mm_rangelow,
707 rangelow);
708 if (error)
709 return (error);
710 error = mac_mls_parse_element(&mac_mls->mm_rangehigh,
711 rangehigh);
712 if (error)
713 return (error);
714 mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
715 }
716
717 error = mac_mls_valid(mac_mls);
718 if (error)
719 return (error);
720
721 return (0);
722 }
723
724 static int
725 mac_mls_internalize_label(struct label *label, char *element_name,
726 char *element_data, int *claimed)
727 {
728 struct mac_mls *mac_mls, mac_mls_temp;
729 int error;
730
731 if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
732 return (0);
733
734 (*claimed)++;
735
736 error = mac_mls_parse(&mac_mls_temp, element_data);
737 if (error)
738 return (error);
739
740 mac_mls = SLOT(label);
741 *mac_mls = mac_mls_temp;
742
743 return (0);
744 }
745
746 static void
747 mac_mls_copy_label(struct label *src, struct label *dest)
748 {
749
750 *SLOT(dest) = *SLOT(src);
751 }
752
753 /*
754 * Labeling event operations: file system objects, and things that look
755 * a lot like file system objects.
756 */
757 static void
758 mac_mls_create_devfs_device(struct mount *mp, dev_t dev,
759 struct devfs_dirent *devfs_dirent, struct label *label)
760 {
761 struct mac_mls *mac_mls;
762 int mls_type;
763
764 mac_mls = SLOT(label);
765 if (strcmp(dev->si_name, "null") == 0 ||
766 strcmp(dev->si_name, "zero") == 0 ||
767 strcmp(dev->si_name, "random") == 0 ||
768 strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
769 mls_type = MAC_MLS_TYPE_EQUAL;
770 else if (strcmp(dev->si_name, "kmem") == 0 ||
771 strcmp(dev->si_name, "mem") == 0)
772 mls_type = MAC_MLS_TYPE_HIGH;
773 else if (ptys_equal &&
774 (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
775 strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
776 mls_type = MAC_MLS_TYPE_EQUAL;
777 else
778 mls_type = MAC_MLS_TYPE_LOW;
779 mac_mls_set_single(mac_mls, mls_type, 0, NULL);
780 }
781
782 static void
783 mac_mls_create_devfs_directory(struct mount *mp, char *dirname,
784 int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
785 {
786 struct mac_mls *mac_mls;
787
788 mac_mls = SLOT(label);
789 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
790 }
791
792 static void
793 mac_mls_create_devfs_symlink(struct ucred *cred, struct mount *mp,
794 struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
795 struct label *delabel)
796 {
797 struct mac_mls *source, *dest;
798
799 source = SLOT(&cred->cr_label);
800 dest = SLOT(delabel);
801
802 mac_mls_copy_single(source, dest);
803 }
804
805 static void
806 mac_mls_create_mount(struct ucred *cred, struct mount *mp,
807 struct label *mntlabel, struct label *fslabel)
808 {
809 struct mac_mls *source, *dest;
810
811 source = SLOT(&cred->cr_label);
812 dest = SLOT(mntlabel);
813 mac_mls_copy_single(source, dest);
814 dest = SLOT(fslabel);
815 mac_mls_copy_single(source, dest);
816 }
817
818 static void
819 mac_mls_create_root_mount(struct ucred *cred, struct mount *mp,
820 struct label *mntlabel, struct label *fslabel)
821 {
822 struct mac_mls *mac_mls;
823
824 /* Always mount root as high integrity. */
825 mac_mls = SLOT(fslabel);
826 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
827 mac_mls = SLOT(mntlabel);
828 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
829 }
830
831 static void
832 mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp,
833 struct label *vnodelabel, struct label *label)
834 {
835 struct mac_mls *source, *dest;
836
837 source = SLOT(label);
838 dest = SLOT(vnodelabel);
839
840 mac_mls_copy(source, dest);
841 }
842
843 static void
844 mac_mls_update_devfsdirent(struct mount *mp,
845 struct devfs_dirent *devfs_dirent, struct label *direntlabel,
846 struct vnode *vp, struct label *vnodelabel)
847 {
848 struct mac_mls *source, *dest;
849
850 source = SLOT(vnodelabel);
851 dest = SLOT(direntlabel);
852
853 mac_mls_copy_single(source, dest);
854 }
855
856 static void
857 mac_mls_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
858 struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
859 struct label *vlabel)
860 {
861 struct mac_mls *source, *dest;
862
863 source = SLOT(delabel);
864 dest = SLOT(vlabel);
865
866 mac_mls_copy_single(source, dest);
867 }
868
869 static int
870 mac_mls_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
871 struct vnode *vp, struct label *vlabel)
872 {
873 struct mac_mls temp, *source, *dest;
874 int buflen, error;
875
876 source = SLOT(fslabel);
877 dest = SLOT(vlabel);
878
879 buflen = sizeof(temp);
880 bzero(&temp, buflen);
881
882 error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
883 MAC_MLS_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
884 if (error == ENOATTR || error == EOPNOTSUPP) {
885 /* Fall back to the fslabel. */
886 mac_mls_copy_single(source, dest);
887 return (0);
888 } else if (error)
889 return (error);
890
891 if (buflen != sizeof(temp)) {
892 printf("mac_mls_associate_vnode_extattr: bad size %d\n",
893 buflen);
894 return (EPERM);
895 }
896 if (mac_mls_valid(&temp) != 0) {
897 printf("mac_mls_associate_vnode_extattr: invalid\n");
898 return (EPERM);
899 }
900 if ((temp.mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE) {
901 printf("mac_mls_associated_vnode_extattr: not single\n");
902 return (EPERM);
903 }
904
905 mac_mls_copy_single(&temp, dest);
906 return (0);
907 }
908
909 static void
910 mac_mls_associate_vnode_singlelabel(struct mount *mp,
911 struct label *fslabel, struct vnode *vp, struct label *vlabel)
912 {
913 struct mac_mls *source, *dest;
914
915 source = SLOT(fslabel);
916 dest = SLOT(vlabel);
917
918 mac_mls_copy_single(source, dest);
919 }
920
921 static int
922 mac_mls_create_vnode_extattr(struct ucred *cred, struct mount *mp,
923 struct label *fslabel, struct vnode *dvp, struct label *dlabel,
924 struct vnode *vp, struct label *vlabel, struct componentname *cnp)
925 {
926 struct mac_mls *source, *dest, temp;
927 size_t buflen;
928 int error;
929
930 buflen = sizeof(temp);
931 bzero(&temp, buflen);
932
933 source = SLOT(&cred->cr_label);
934 dest = SLOT(vlabel);
935 mac_mls_copy_single(source, &temp);
936
937 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
938 MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
939 if (error == 0)
940 mac_mls_copy_single(source, dest);
941 return (error);
942 }
943
944 static int
945 mac_mls_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
946 struct label *vlabel, struct label *intlabel)
947 {
948 struct mac_mls *source, temp;
949 size_t buflen;
950 int error;
951
952 buflen = sizeof(temp);
953 bzero(&temp, buflen);
954
955 source = SLOT(intlabel);
956 if ((source->mm_flags & MAC_MLS_FLAG_SINGLE) == 0)
957 return (0);
958
959 mac_mls_copy_single(source, &temp);
960
961 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
962 MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
963 return (error);
964 }
965
966 /*
967 * Labeling event operations: IPC object.
968 */
969 static void
970 mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
971 struct mbuf *m, struct label *mbuflabel)
972 {
973 struct mac_mls *source, *dest;
974
975 source = SLOT(socketlabel);
976 dest = SLOT(mbuflabel);
977
978 mac_mls_copy_single(source, dest);
979 }
980
981 static void
982 mac_mls_create_socket(struct ucred *cred, struct socket *socket,
983 struct label *socketlabel)
984 {
985 struct mac_mls *source, *dest;
986
987 source = SLOT(&cred->cr_label);
988 dest = SLOT(socketlabel);
989
990 mac_mls_copy_single(source, dest);
991 }
992
993 static void
994 mac_mls_create_pipe(struct ucred *cred, struct pipe *pipe,
995 struct label *pipelabel)
996 {
997 struct mac_mls *source, *dest;
998
999 source = SLOT(&cred->cr_label);
1000 dest = SLOT(pipelabel);
1001
1002 mac_mls_copy_single(source, dest);
1003 }
1004
1005 static void
1006 mac_mls_create_socket_from_socket(struct socket *oldsocket,
1007 struct label *oldsocketlabel, struct socket *newsocket,
1008 struct label *newsocketlabel)
1009 {
1010 struct mac_mls *source, *dest;
1011
1012 source = SLOT(oldsocketlabel);
1013 dest = SLOT(newsocketlabel);
1014
1015 mac_mls_copy_single(source, dest);
1016 }
1017
1018 static void
1019 mac_mls_relabel_socket(struct ucred *cred, struct socket *socket,
1020 struct label *socketlabel, struct label *newlabel)
1021 {
1022 struct mac_mls *source, *dest;
1023
1024 source = SLOT(newlabel);
1025 dest = SLOT(socketlabel);
1026
1027 mac_mls_copy(source, dest);
1028 }
1029
1030 static void
1031 mac_mls_relabel_pipe(struct ucred *cred, struct pipe *pipe,
1032 struct label *pipelabel, struct label *newlabel)
1033 {
1034 struct mac_mls *source, *dest;
1035
1036 source = SLOT(newlabel);
1037 dest = SLOT(pipelabel);
1038
1039 mac_mls_copy(source, dest);
1040 }
1041
1042 static void
1043 mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1044 struct socket *socket, struct label *socketpeerlabel)
1045 {
1046 struct mac_mls *source, *dest;
1047
1048 source = SLOT(mbuflabel);
1049 dest = SLOT(socketpeerlabel);
1050
1051 mac_mls_copy_single(source, dest);
1052 }
1053
1054 /*
1055 * Labeling event operations: network objects.
1056 */
1057 static void
1058 mac_mls_set_socket_peer_from_socket(struct socket *oldsocket,
1059 struct label *oldsocketlabel, struct socket *newsocket,
1060 struct label *newsocketpeerlabel)
1061 {
1062 struct mac_mls *source, *dest;
1063
1064 source = SLOT(oldsocketlabel);
1065 dest = SLOT(newsocketpeerlabel);
1066
1067 mac_mls_copy_single(source, dest);
1068 }
1069
1070 static void
1071 mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1072 struct label *bpflabel)
1073 {
1074 struct mac_mls *source, *dest;
1075
1076 source = SLOT(&cred->cr_label);
1077 dest = SLOT(bpflabel);
1078
1079 mac_mls_copy_single(source, dest);
1080 }
1081
1082 static void
1083 mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1084 {
1085 struct mac_mls *dest;
1086 int type;
1087
1088 dest = SLOT(ifnetlabel);
1089
1090 if (ifnet->if_type == IFT_LOOP)
1091 type = MAC_MLS_TYPE_EQUAL;
1092 else
1093 type = MAC_MLS_TYPE_LOW;
1094
1095 mac_mls_set_single(dest, type, 0, NULL);
1096 mac_mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1097 }
1098
1099 static void
1100 mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1101 struct ipq *ipq, struct label *ipqlabel)
1102 {
1103 struct mac_mls *source, *dest;
1104
1105 source = SLOT(fragmentlabel);
1106 dest = SLOT(ipqlabel);
1107
1108 mac_mls_copy_single(source, dest);
1109 }
1110
1111 static void
1112 mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1113 struct mbuf *datagram, struct label *datagramlabel)
1114 {
1115 struct mac_mls *source, *dest;
1116
1117 source = SLOT(ipqlabel);
1118 dest = SLOT(datagramlabel);
1119
1120 /* Just use the head, since we require them all to match. */
1121 mac_mls_copy_single(source, dest);
1122 }
1123
1124 static void
1125 mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1126 struct mbuf *fragment, struct label *fragmentlabel)
1127 {
1128 struct mac_mls *source, *dest;
1129
1130 source = SLOT(datagramlabel);
1131 dest = SLOT(fragmentlabel);
1132
1133 mac_mls_copy_single(source, dest);
1134 }
1135
1136 static void
1137 mac_mls_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
1138 struct label *oldmbuflabel, struct mbuf *newmbuf,
1139 struct label *newmbuflabel)
1140 {
1141 struct mac_mls *source, *dest;
1142
1143 source = SLOT(oldmbuflabel);
1144 dest = SLOT(newmbuflabel);
1145
1146 /*
1147 * Because the source mbuf may not yet have been "created",
1148 * just initialized, we do a conditional copy. Since we don't
1149 * allow mbufs to have ranges, do a KASSERT to make sure that
1150 * doesn't happen.
1151 */
1152 KASSERT((source->mm_flags & MAC_MLS_FLAG_RANGE) == 0,
1153 ("mac_mls_create_mbuf_from_mbuf: source mbuf has range"));
1154 mac_mls_copy(source, dest);
1155 }
1156
1157 static void
1158 mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1159 struct mbuf *mbuf, struct label *mbuflabel)
1160 {
1161 struct mac_mls *dest;
1162
1163 dest = SLOT(mbuflabel);
1164
1165 mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1166 }
1167
1168 static void
1169 mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1170 struct mbuf *mbuf, struct label *mbuflabel)
1171 {
1172 struct mac_mls *source, *dest;
1173
1174 source = SLOT(bpflabel);
1175 dest = SLOT(mbuflabel);
1176
1177 mac_mls_copy_single(source, dest);
1178 }
1179
1180 static void
1181 mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1182 struct mbuf *m, struct label *mbuflabel)
1183 {
1184 struct mac_mls *source, *dest;
1185
1186 source = SLOT(ifnetlabel);
1187 dest = SLOT(mbuflabel);
1188
1189 mac_mls_copy_single(source, dest);
1190 }
1191
1192 static void
1193 mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1194 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1195 struct mbuf *newmbuf, struct label *newmbuflabel)
1196 {
1197 struct mac_mls *source, *dest;
1198
1199 source = SLOT(oldmbuflabel);
1200 dest = SLOT(newmbuflabel);
1201
1202 mac_mls_copy_single(source, dest);
1203 }
1204
1205 static void
1206 mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1207 struct mbuf *newmbuf, struct label *newmbuflabel)
1208 {
1209 struct mac_mls *source, *dest;
1210
1211 source = SLOT(oldmbuflabel);
1212 dest = SLOT(newmbuflabel);
1213
1214 mac_mls_copy_single(source, dest);
1215 }
1216
1217 static int
1218 mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1219 struct ipq *ipq, struct label *ipqlabel)
1220 {
1221 struct mac_mls *a, *b;
1222
1223 a = SLOT(ipqlabel);
1224 b = SLOT(fragmentlabel);
1225
1226 return (mac_mls_equal_single(a, b));
1227 }
1228
1229 static void
1230 mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1231 struct label *ifnetlabel, struct label *newlabel)
1232 {
1233 struct mac_mls *source, *dest;
1234
1235 source = SLOT(newlabel);
1236 dest = SLOT(ifnetlabel);
1237
1238 mac_mls_copy(source, dest);
1239 }
1240
1241 static void
1242 mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1243 struct ipq *ipq, struct label *ipqlabel)
1244 {
1245
1246 /* NOOP: we only accept matching labels, so no need to update */
1247 }
1248
1249 /*
1250 * Labeling event operations: processes.
1251 */
1252 static void
1253 mac_mls_create_cred(struct ucred *cred_parent, struct ucred *cred_child)
1254 {
1255 struct mac_mls *source, *dest;
1256
1257 source = SLOT(&cred_parent->cr_label);
1258 dest = SLOT(&cred_child->cr_label);
1259
1260 mac_mls_copy_single(source, dest);
1261 mac_mls_copy_range(source, dest);
1262 }
1263
1264 static void
1265 mac_mls_create_proc0(struct ucred *cred)
1266 {
1267 struct mac_mls *dest;
1268
1269 dest = SLOT(&cred->cr_label);
1270
1271 mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1272 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
1273 0, NULL);
1274 }
1275
1276 static void
1277 mac_mls_create_proc1(struct ucred *cred)
1278 {
1279 struct mac_mls *dest;
1280
1281 dest = SLOT(&cred->cr_label);
1282
1283 mac_mls_set_single(dest, MAC_MLS_TYPE_LOW, 0, NULL);
1284 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
1285 0, NULL);
1286 }
1287
1288 static void
1289 mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel)
1290 {
1291 struct mac_mls *source, *dest;
1292
1293 source = SLOT(newlabel);
1294 dest = SLOT(&cred->cr_label);
1295
1296 mac_mls_copy(source, dest);
1297 }
1298
1299 /*
1300 * Access control checks.
1301 */
1302 static int
1303 mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1304 struct ifnet *ifnet, struct label *ifnetlabel)
1305 {
1306 struct mac_mls *a, *b;
1307
1308 if (!mac_mls_enabled)
1309 return (0);
1310
1311 a = SLOT(bpflabel);
1312 b = SLOT(ifnetlabel);
1313
1314 if (mac_mls_equal_single(a, b))
1315 return (0);
1316 return (EACCES);
1317 }
1318
1319 static int
1320 mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1321 {
1322 struct mac_mls *subj, *new;
1323 int error;
1324
1325 subj = SLOT(&cred->cr_label);
1326 new = SLOT(newlabel);
1327
1328 /*
1329 * If there is an MLS label update for the credential, it may be
1330 * an update of single, range, or both.
1331 */
1332 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
1333 if (error)
1334 return (error);
1335
1336 /*
1337 * If the MLS label is to be changed, authorize as appropriate.
1338 */
1339 if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
1340 /*
1341 * If the change request modifies both the MLS label single
1342 * and range, check that the new single will be in the
1343 * new range.
1344 */
1345 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
1346 MAC_MLS_FLAGS_BOTH &&
1347 !mac_mls_single_in_range(new, new))
1348 return (EINVAL);
1349
1350 /*
1351 * To change the MLS single label on a credential, the
1352 * new single label must be in the current range.
1353 */
1354 if (new->mm_flags & MAC_MLS_FLAG_SINGLE &&
1355 !mac_mls_single_in_range(new, subj))
1356 return (EPERM);
1357
1358 /*
1359 * To change the MLS range label on a credential, the
1360 * new range must be in the current range.
1361 */
1362 if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
1363 !mac_mls_range_in_range(new, subj))
1364 return (EPERM);
1365
1366 /*
1367 * To have EQUAL in any component of the new credential
1368 * MLS label, the subject must already have EQUAL in
1369 * their label.
1370 */
1371 if (mac_mls_contains_equal(new)) {
1372 error = mac_mls_subject_equal_ok(subj);
1373 if (error)
1374 return (error);
1375 }
1376 }
1377
1378 return (0);
1379 }
1380
1381 static int
1382 mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
1383 {
1384 struct mac_mls *subj, *obj;
1385
1386 if (!mac_mls_enabled)
1387 return (0);
1388
1389 subj = SLOT(&u1->cr_label);
1390 obj = SLOT(&u2->cr_label);
1391
1392 /* XXX: range */
1393 if (!mac_mls_dominate_single(subj, obj))
1394 return (ESRCH);
1395
1396 return (0);
1397 }
1398
1399 static int
1400 mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1401 struct label *ifnetlabel, struct label *newlabel)
1402 {
1403 struct mac_mls *subj, *new;
1404 int error;
1405
1406 subj = SLOT(&cred->cr_label);
1407 new = SLOT(newlabel);
1408
1409 /*
1410 * If there is an MLS label update for the interface, it may
1411 * be an update of single, range, or both.
1412 */
1413 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
1414 if (error)
1415 return (error);
1416
1417 /*
1418 * If the MLS label is to be changed, authorize as appropriate.
1419 */
1420 if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
1421 /*
1422 * Rely on traditional superuser status for the MLS
1423 * interface relabel requirements. XXX: This will go
1424 * away.
1425 */
1426 error = suser_cred(cred, 0);
1427 if (error)
1428 return (EPERM);
1429
1430 /*
1431 * XXXMAC: Additional consistency tests regarding the single
1432 * and the range of the new label might be performed here.
1433 */
1434 }
1435
1436 return (0);
1437 }
1438
1439 static int
1440 mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1441 struct mbuf *m, struct label *mbuflabel)
1442 {
1443 struct mac_mls *p, *i;
1444
1445 if (!mac_mls_enabled)
1446 return (0);
1447
1448 p = SLOT(mbuflabel);
1449 i = SLOT(ifnetlabel);
1450
1451 return (mac_mls_single_in_range(p, i) ? 0 : EACCES);
1452 }
1453
1454 static int
1455 mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp,
1456 struct label *mntlabel)
1457 {
1458 struct mac_mls *subj, *obj;
1459
1460 if (!mac_mls_enabled)
1461 return (0);
1462
1463 subj = SLOT(&cred->cr_label);
1464 obj = SLOT(mntlabel);
1465
1466 if (!mac_mls_dominate_single(subj, obj))
1467 return (EACCES);
1468
1469 return (0);
1470 }
1471
1472 static int
1473 mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1474 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1475 {
1476
1477 if(!mac_mls_enabled)
1478 return (0);
1479
1480 /* XXX: This will be implemented soon... */
1481
1482 return (0);
1483 }
1484
1485 static int
1486 mac_mls_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
1487 struct label *pipelabel)
1488 {
1489 struct mac_mls *subj, *obj;
1490
1491 if (!mac_mls_enabled)
1492 return (0);
1493
1494 subj = SLOT(&cred->cr_label);
1495 obj = SLOT((pipelabel));
1496
1497 if (!mac_mls_dominate_single(subj, obj))
1498 return (EACCES);
1499
1500 return (0);
1501 }
1502
1503 static int
1504 mac_mls_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1505 struct label *pipelabel)
1506 {
1507 struct mac_mls *subj, *obj;
1508
1509 if (!mac_mls_enabled)
1510 return (0);
1511
1512 subj = SLOT(&cred->cr_label);
1513 obj = SLOT((pipelabel));
1514
1515 if (!mac_mls_dominate_single(subj, obj))
1516 return (EACCES);
1517
1518 return (0);
1519 }
1520
1521 static int
1522 mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1523 struct label *pipelabel, struct label *newlabel)
1524 {
1525 struct mac_mls *subj, *obj, *new;
1526 int error;
1527
1528 new = SLOT(newlabel);
1529 subj = SLOT(&cred->cr_label);
1530 obj = SLOT(pipelabel);
1531
1532 /*
1533 * If there is an MLS label update for a pipe, it must be a
1534 * single update.
1535 */
1536 error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
1537 if (error)
1538 return (error);
1539
1540 /*
1541 * To perform a relabel of a pipe (MLS label or not), MLS must
1542 * authorize the relabel.
1543 */
1544 if (!mac_mls_single_in_range(obj, subj))
1545 return (EPERM);
1546
1547 /*
1548 * If the MLS label is to be changed, authorize as appropriate.
1549 */
1550 if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
1551 /*
1552 * To change the MLS label on a pipe, the new pipe label
1553 * must be in the subject range.
1554 */
1555 if (!mac_mls_single_in_range(new, subj))
1556 return (EPERM);
1557
1558 /*
1559 * To change the MLS label on a pipe to be EQUAL, the
1560 * subject must have appropriate privilege.
1561 */
1562 if (mac_mls_contains_equal(new)) {
1563 error = mac_mls_subject_equal_ok(subj);
1564 if (error)
1565 return (error);
1566 }
1567 }
1568
1569 return (0);
1570 }
1571
1572 static int
1573 mac_mls_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
1574 struct label *pipelabel)
1575 {
1576 struct mac_mls *subj, *obj;
1577
1578 if (!mac_mls_enabled)
1579 return (0);
1580
1581 subj = SLOT(&cred->cr_label);
1582 obj = SLOT((pipelabel));
1583
1584 if (!mac_mls_dominate_single(subj, obj))
1585 return (EACCES);
1586
1587 return (0);
1588 }
1589
1590 static int
1591 mac_mls_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1592 struct label *pipelabel)
1593 {
1594 struct mac_mls *subj, *obj;
1595
1596 if (!mac_mls_enabled)
1597 return (0);
1598
1599 subj = SLOT(&cred->cr_label);
1600 obj = SLOT((pipelabel));
1601
1602 if (!mac_mls_dominate_single(obj, subj))
1603 return (EACCES);
1604
1605 return (0);
1606 }
1607
1608 static int
1609 mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc)
1610 {
1611 struct mac_mls *subj, *obj;
1612
1613 if (!mac_mls_enabled)
1614 return (0);
1615
1616 subj = SLOT(&cred->cr_label);
1617 obj = SLOT(&proc->p_ucred->cr_label);
1618
1619 /* XXX: range checks */
1620 if (!mac_mls_dominate_single(subj, obj))
1621 return (ESRCH);
1622 if (!mac_mls_dominate_single(obj, subj))
1623 return (EACCES);
1624
1625 return (0);
1626 }
1627
1628 static int
1629 mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc)
1630 {
1631 struct mac_mls *subj, *obj;
1632
1633 if (!mac_mls_enabled)
1634 return (0);
1635
1636 subj = SLOT(&cred->cr_label);
1637 obj = SLOT(&proc->p_ucred->cr_label);
1638
1639 /* XXX: range checks */
1640 if (!mac_mls_dominate_single(subj, obj))
1641 return (ESRCH);
1642 if (!mac_mls_dominate_single(obj, subj))
1643 return (EACCES);
1644
1645 return (0);
1646 }
1647
1648 static int
1649 mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1650 {
1651 struct mac_mls *subj, *obj;
1652
1653 if (!mac_mls_enabled)
1654 return (0);
1655
1656 subj = SLOT(&cred->cr_label);
1657 obj = SLOT(&proc->p_ucred->cr_label);
1658
1659 /* XXX: range checks */
1660 if (!mac_mls_dominate_single(subj, obj))
1661 return (ESRCH);
1662 if (!mac_mls_dominate_single(obj, subj))
1663 return (EACCES);
1664
1665 return (0);
1666 }
1667
1668 static int
1669 mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel,
1670 struct mbuf *m, struct label *mbuflabel)
1671 {
1672 struct mac_mls *p, *s;
1673
1674 if (!mac_mls_enabled)
1675 return (0);
1676
1677 p = SLOT(mbuflabel);
1678 s = SLOT(socketlabel);
1679
1680 return (mac_mls_equal_single(p, s) ? 0 : EACCES);
1681 }
1682
1683 static int
1684 mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket,
1685 struct label *socketlabel, struct label *newlabel)
1686 {
1687 struct mac_mls *subj, *obj, *new;
1688 int error;
1689
1690 new = SLOT(newlabel);
1691 subj = SLOT(&cred->cr_label);
1692 obj = SLOT(socketlabel);
1693
1694 /*
1695 * If there is an MLS label update for the socket, it may be
1696 * an update of single.
1697 */
1698 error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
1699 if (error)
1700 return (error);
1701
1702 /*
1703 * To relabel a socket, the old socket single must be in the subject
1704 * range.
1705 */
1706 if (!mac_mls_single_in_range(obj, subj))
1707 return (EPERM);
1708
1709 /*
1710 * If the MLS label is to be changed, authorize as appropriate.
1711 */
1712 if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
1713 /*
1714 * To relabel a socket, the new socket single must be in
1715 * the subject range.
1716 */
1717 if (!mac_mls_single_in_range(new, subj))
1718 return (EPERM);
1719
1720 /*
1721 * To change the MLS label on the socket to contain EQUAL,
1722 * the subject must have appropriate privilege.
1723 */
1724 if (mac_mls_contains_equal(new)) {
1725 error = mac_mls_subject_equal_ok(subj);
1726 if (error)
1727 return (error);
1728 }
1729 }
1730
1731 return (0);
1732 }
1733
1734 static int
1735 mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket,
1736 struct label *socketlabel)
1737 {
1738 struct mac_mls *subj, *obj;
1739
1740 if (!mac_mls_enabled)
1741 return (0);
1742
1743 subj = SLOT(&cred->cr_label);
1744 obj = SLOT(socketlabel);
1745
1746 if (!mac_mls_dominate_single(subj, obj))
1747 return (ENOENT);
1748
1749 return (0);
1750 }
1751
1752 static int
1753 mac_mls_check_system_swapon(struct ucred *cred, struct vnode *vp,
1754 struct label *label)
1755 {
1756 struct mac_mls *subj, *obj;
1757
1758 if (!mac_mls_enabled)
1759 return (0);
1760
1761 subj = SLOT(&cred->cr_label);
1762 obj = SLOT(label);
1763
1764 if (!mac_mls_dominate_single(obj, subj) ||
1765 !mac_mls_dominate_single(subj, obj))
1766 return (EACCES);
1767
1768 return (0);
1769 }
1770
1771 static int
1772 mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
1773 struct label *dlabel)
1774 {
1775 struct mac_mls *subj, *obj;
1776
1777 if (!mac_mls_enabled)
1778 return (0);
1779
1780 subj = SLOT(&cred->cr_label);
1781 obj = SLOT(dlabel);
1782
1783 if (!mac_mls_dominate_single(subj, obj))
1784 return (EACCES);
1785
1786 return (0);
1787 }
1788
1789 static int
1790 mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
1791 struct label *dlabel)
1792 {
1793 struct mac_mls *subj, *obj;
1794
1795 if (!mac_mls_enabled)
1796 return (0);
1797
1798 subj = SLOT(&cred->cr_label);
1799 obj = SLOT(dlabel);
1800
1801 if (!mac_mls_dominate_single(subj, obj))
1802 return (EACCES);
1803
1804 return (0);
1805 }
1806
1807 static int
1808 mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1809 struct label *dlabel, struct componentname *cnp, struct vattr *vap)
1810 {
1811 struct mac_mls *subj, *obj;
1812
1813 if (!mac_mls_enabled)
1814 return (0);
1815
1816 subj = SLOT(&cred->cr_label);
1817 obj = SLOT(dlabel);
1818
1819 if (!mac_mls_dominate_single(obj, subj))
1820 return (EACCES);
1821
1822 return (0);
1823 }
1824
1825 static int
1826 mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
1827 struct label *dlabel, struct vnode *vp, struct label *label,
1828 struct componentname *cnp)
1829 {
1830 struct mac_mls *subj, *obj;
1831
1832 if (!mac_mls_enabled)
1833 return (0);
1834
1835 subj = SLOT(&cred->cr_label);
1836 obj = SLOT(dlabel);
1837
1838 if (!mac_mls_dominate_single(obj, subj))
1839 return (EACCES);
1840
1841 obj = SLOT(label);
1842
1843 if (!mac_mls_dominate_single(obj, subj))
1844 return (EACCES);
1845
1846 return (0);
1847 }
1848
1849 static int
1850 mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1851 struct label *label, acl_type_t type)
1852 {
1853 struct mac_mls *subj, *obj;
1854
1855 if (!mac_mls_enabled)
1856 return (0);
1857
1858 subj = SLOT(&cred->cr_label);
1859 obj = SLOT(label);
1860
1861 if (!mac_mls_dominate_single(obj, subj))
1862 return (EACCES);
1863
1864 return (0);
1865 }
1866
1867 static int
1868 mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1869 struct label *label, struct image_params *imgp,
1870 struct label *execlabel)
1871 {
1872 struct mac_mls *subj, *obj, *exec;
1873 int error;
1874
1875 if (execlabel != NULL) {
1876 /*
1877 * We currently don't permit labels to be changed at
1878 * exec-time as part of MLS, so disallow non-NULL
1879 * MLS label elements in the execlabel.
1880 */
1881 exec = SLOT(execlabel);
1882 error = mls_atmostflags(exec, 0);
1883 if (error)
1884 return (error);
1885 }
1886
1887 if (!mac_mls_enabled)
1888 return (0);
1889
1890 subj = SLOT(&cred->cr_label);
1891 obj = SLOT(label);
1892
1893 if (!mac_mls_dominate_single(subj, obj))
1894 return (EACCES);
1895
1896 return (0);
1897 }
1898
1899 static int
1900 mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
1901 struct label *label, acl_type_t type)
1902 {
1903 struct mac_mls *subj, *obj;
1904
1905 if (!mac_mls_enabled)
1906 return (0);
1907
1908 subj = SLOT(&cred->cr_label);
1909 obj = SLOT(label);
1910
1911 if (!mac_mls_dominate_single(subj, obj))
1912 return (EACCES);
1913
1914 return (0);
1915 }
1916
1917 static int
1918 mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1919 struct label *label, int attrnamespace, const char *name, struct uio *uio)
1920 {
1921 struct mac_mls *subj, *obj;
1922
1923 if (!mac_mls_enabled)
1924 return (0);
1925
1926 subj = SLOT(&cred->cr_label);
1927 obj = SLOT(label);
1928
1929 if (!mac_mls_dominate_single(subj, obj))
1930 return (EACCES);
1931
1932 return (0);
1933 }
1934
1935 static int
1936 mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1937 struct label *dlabel, struct vnode *vp, struct label *label,
1938 struct componentname *cnp)
1939 {
1940 struct mac_mls *subj, *obj;
1941
1942 if (!mac_mls_enabled)
1943 return (0);
1944
1945 subj = SLOT(&cred->cr_label);
1946 obj = SLOT(dlabel);
1947
1948 if (!mac_mls_dominate_single(obj, subj))
1949 return (EACCES);
1950
1951 obj = SLOT(dlabel);
1952 if (!mac_mls_dominate_single(obj, subj))
1953 return (EACCES);
1954
1955 return (0);
1956 }
1957
1958 static int
1959 mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1960 struct label *dlabel, struct componentname *cnp)
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(dlabel);
1969
1970 if (!mac_mls_dominate_single(subj, obj))
1971 return (EACCES);
1972
1973 return (0);
1974 }
1975
1976 static int
1977 mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
1978 struct label *label, int prot)
1979 {
1980 struct mac_mls *subj, *obj;
1981
1982 /*
1983 * Rely on the use of open()-time protections to handle
1984 * non-revocation cases.
1985 */
1986 if (!mac_mls_enabled || !revocation_enabled)
1987 return (0);
1988
1989 subj = SLOT(&cred->cr_label);
1990 obj = SLOT(label);
1991
1992 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
1993 if (!mac_mls_dominate_single(subj, obj))
1994 return (EACCES);
1995 }
1996 if (prot & VM_PROT_WRITE) {
1997 if (!mac_mls_dominate_single(obj, subj))
1998 return (EACCES);
1999 }
2000
2001 return (0);
2002 }
2003
2004 static int
2005 mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
2006 struct label *vnodelabel, int acc_mode)
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(vnodelabel);
2015
2016 /* XXX privilege override for admin? */
2017 if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2018 if (!mac_mls_dominate_single(subj, obj))
2019 return (EACCES);
2020 }
2021 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2022 if (!mac_mls_dominate_single(obj, subj))
2023 return (EACCES);
2024 }
2025
2026 return (0);
2027 }
2028
2029 static int
2030 mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2031 struct vnode *vp, struct label *label)
2032 {
2033 struct mac_mls *subj, *obj;
2034
2035 if (!mac_mls_enabled || !revocation_enabled)
2036 return (0);
2037
2038 subj = SLOT(&active_cred->cr_label);
2039 obj = SLOT(label);
2040
2041 if (!mac_mls_dominate_single(subj, obj))
2042 return (EACCES);
2043
2044 return (0);
2045 }
2046
2047 static int
2048 mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2049 struct vnode *vp, struct label *label)
2050 {
2051 struct mac_mls *subj, *obj;
2052
2053 if (!mac_mls_enabled || !revocation_enabled)
2054 return (0);
2055
2056 subj = SLOT(&active_cred->cr_label);
2057 obj = SLOT(label);
2058
2059 if (!mac_mls_dominate_single(subj, obj))
2060 return (EACCES);
2061
2062 return (0);
2063 }
2064
2065 static int
2066 mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
2067 struct label *dlabel)
2068 {
2069 struct mac_mls *subj, *obj;
2070
2071 if (!mac_mls_enabled)
2072 return (0);
2073
2074 subj = SLOT(&cred->cr_label);
2075 obj = SLOT(dlabel);
2076
2077 if (!mac_mls_dominate_single(subj, obj))
2078 return (EACCES);
2079
2080 return (0);
2081 }
2082
2083 static int
2084 mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
2085 struct label *vnodelabel)
2086 {
2087 struct mac_mls *subj, *obj;
2088
2089 if (!mac_mls_enabled)
2090 return (0);
2091
2092 subj = SLOT(&cred->cr_label);
2093 obj = SLOT(vnodelabel);
2094
2095 if (!mac_mls_dominate_single(subj, obj))
2096 return (EACCES);
2097
2098 return (0);
2099 }
2100
2101 static int
2102 mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2103 struct label *vnodelabel, struct label *newlabel)
2104 {
2105 struct mac_mls *old, *new, *subj;
2106 int error;
2107
2108 old = SLOT(vnodelabel);
2109 new = SLOT(newlabel);
2110 subj = SLOT(&cred->cr_label);
2111
2112 /*
2113 * If there is an MLS label update for the vnode, it must be a
2114 * single label.
2115 */
2116 error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
2117 if (error)
2118 return (error);
2119
2120 /*
2121 * To perform a relabel of the vnode (MLS label or not), MLS must
2122 * authorize the relabel.
2123 */
2124 if (!mac_mls_single_in_range(old, subj))
2125 return (EPERM);
2126
2127 /*
2128 * If the MLS label is to be changed, authorize as appropriate.
2129 */
2130 if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
2131 /*
2132 * To change the MLS label on a vnode, the new vnode label
2133 * must be in the subject range.
2134 */
2135 if (!mac_mls_single_in_range(new, subj))
2136 return (EPERM);
2137
2138 /*
2139 * To change the MLS label on the vnode to be EQUAL,
2140 * the subject must have appropriate privilege.
2141 */
2142 if (mac_mls_contains_equal(new)) {
2143 error = mac_mls_subject_equal_ok(subj);
2144 if (error)
2145 return (error);
2146 }
2147 }
2148
2149 return (0);
2150 }
2151
2152
2153 static int
2154 mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2155 struct label *dlabel, struct vnode *vp, struct label *label,
2156 struct componentname *cnp)
2157 {
2158 struct mac_mls *subj, *obj;
2159
2160 if (!mac_mls_enabled)
2161 return (0);
2162
2163 subj = SLOT(&cred->cr_label);
2164 obj = SLOT(dlabel);
2165
2166 if (!mac_mls_dominate_single(obj, subj))
2167 return (EACCES);
2168
2169 obj = SLOT(label);
2170
2171 if (!mac_mls_dominate_single(obj, subj))
2172 return (EACCES);
2173
2174 return (0);
2175 }
2176
2177 static int
2178 mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2179 struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2180 struct componentname *cnp)
2181 {
2182 struct mac_mls *subj, *obj;
2183
2184 if (!mac_mls_enabled)
2185 return (0);
2186
2187 subj = SLOT(&cred->cr_label);
2188 obj = SLOT(dlabel);
2189
2190 if (!mac_mls_dominate_single(obj, subj))
2191 return (EACCES);
2192
2193 if (vp != NULL) {
2194 obj = SLOT(label);
2195
2196 if (!mac_mls_dominate_single(obj, subj))
2197 return (EACCES);
2198 }
2199
2200 return (0);
2201 }
2202
2203 static int
2204 mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2205 struct label *label)
2206 {
2207 struct mac_mls *subj, *obj;
2208
2209 if (!mac_mls_enabled)
2210 return (0);
2211
2212 subj = SLOT(&cred->cr_label);
2213 obj = SLOT(label);
2214
2215 if (!mac_mls_dominate_single(obj, subj))
2216 return (EACCES);
2217
2218 return (0);
2219 }
2220
2221 static int
2222 mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2223 struct label *label, acl_type_t type, struct acl *acl)
2224 {
2225 struct mac_mls *subj, *obj;
2226
2227 if (!mac_mls_enabled)
2228 return (0);
2229
2230 subj = SLOT(&cred->cr_label);
2231 obj = SLOT(label);
2232
2233 if (!mac_mls_dominate_single(obj, subj))
2234 return (EACCES);
2235
2236 return (0);
2237 }
2238
2239 static int
2240 mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2241 struct label *vnodelabel, int attrnamespace, const char *name,
2242 struct uio *uio)
2243 {
2244 struct mac_mls *subj, *obj;
2245
2246 if (!mac_mls_enabled)
2247 return (0);
2248
2249 subj = SLOT(&cred->cr_label);
2250 obj = SLOT(vnodelabel);
2251
2252 if (!mac_mls_dominate_single(obj, subj))
2253 return (EACCES);
2254
2255 /* XXX: protect the MAC EA in a special way? */
2256
2257 return (0);
2258 }
2259
2260 static int
2261 mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2262 struct label *vnodelabel, u_long flags)
2263 {
2264 struct mac_mls *subj, *obj;
2265
2266 if (!mac_mls_enabled)
2267 return (0);
2268
2269 subj = SLOT(&cred->cr_label);
2270 obj = SLOT(vnodelabel);
2271
2272 if (!mac_mls_dominate_single(obj, subj))
2273 return (EACCES);
2274
2275 return (0);
2276 }
2277
2278 static int
2279 mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2280 struct label *vnodelabel, mode_t mode)
2281 {
2282 struct mac_mls *subj, *obj;
2283
2284 if (!mac_mls_enabled)
2285 return (0);
2286
2287 subj = SLOT(&cred->cr_label);
2288 obj = SLOT(vnodelabel);
2289
2290 if (!mac_mls_dominate_single(obj, subj))
2291 return (EACCES);
2292
2293 return (0);
2294 }
2295
2296 static int
2297 mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2298 struct label *vnodelabel, uid_t uid, gid_t gid)
2299 {
2300 struct mac_mls *subj, *obj;
2301
2302 if (!mac_mls_enabled)
2303 return (0);
2304
2305 subj = SLOT(&cred->cr_label);
2306 obj = SLOT(vnodelabel);
2307
2308 if (!mac_mls_dominate_single(obj, subj))
2309 return (EACCES);
2310
2311 return (0);
2312 }
2313
2314 static int
2315 mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2316 struct label *vnodelabel, struct timespec atime, struct timespec mtime)
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(vnodelabel);
2325
2326 if (!mac_mls_dominate_single(obj, subj))
2327 return (EACCES);
2328
2329 return (0);
2330 }
2331
2332 static int
2333 mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2334 struct vnode *vp, struct label *vnodelabel)
2335 {
2336 struct mac_mls *subj, *obj;
2337
2338 if (!mac_mls_enabled)
2339 return (0);
2340
2341 subj = SLOT(&active_cred->cr_label);
2342 obj = SLOT(vnodelabel);
2343
2344 if (!mac_mls_dominate_single(subj, obj))
2345 return (EACCES);
2346
2347 return (0);
2348 }
2349
2350 static int
2351 mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2352 struct vnode *vp, struct label *label)
2353 {
2354 struct mac_mls *subj, *obj;
2355
2356 if (!mac_mls_enabled || !revocation_enabled)
2357 return (0);
2358
2359 subj = SLOT(&active_cred->cr_label);
2360 obj = SLOT(label);
2361
2362 if (!mac_mls_dominate_single(obj, subj))
2363 return (EACCES);
2364
2365 return (0);
2366 }
2367
2368 static struct mac_policy_ops mac_mls_ops =
2369 {
2370 .mpo_destroy = mac_mls_destroy,
2371 .mpo_init = mac_mls_init,
2372 .mpo_init_bpfdesc_label = mac_mls_init_label,
2373 .mpo_init_cred_label = mac_mls_init_label,
2374 .mpo_init_devfsdirent_label = mac_mls_init_label,
2375 .mpo_init_ifnet_label = mac_mls_init_label,
2376 .mpo_init_ipq_label = mac_mls_init_label_waitcheck,
2377 .mpo_init_mbuf_label = mac_mls_init_label_waitcheck,
2378 .mpo_init_mount_label = mac_mls_init_label,
2379 .mpo_init_mount_fs_label = mac_mls_init_label,
2380 .mpo_init_pipe_label = mac_mls_init_label,
2381 .mpo_init_socket_label = mac_mls_init_label_waitcheck,
2382 .mpo_init_socket_peer_label = mac_mls_init_label_waitcheck,
2383 .mpo_init_vnode_label = mac_mls_init_label,
2384 .mpo_destroy_bpfdesc_label = mac_mls_destroy_label,
2385 .mpo_destroy_cred_label = mac_mls_destroy_label,
2386 .mpo_destroy_devfsdirent_label = mac_mls_destroy_label,
2387 .mpo_destroy_ifnet_label = mac_mls_destroy_label,
2388 .mpo_destroy_ipq_label = mac_mls_destroy_label,
2389 .mpo_destroy_mbuf_label = mac_mls_destroy_label,
2390 .mpo_destroy_mount_label = mac_mls_destroy_label,
2391 .mpo_destroy_mount_fs_label = mac_mls_destroy_label,
2392 .mpo_destroy_pipe_label = mac_mls_destroy_label,
2393 .mpo_destroy_socket_label = mac_mls_destroy_label,
2394 .mpo_destroy_socket_peer_label = mac_mls_destroy_label,
2395 .mpo_destroy_vnode_label = mac_mls_destroy_label,
2396 .mpo_copy_mbuf_label = mac_mls_copy_label,
2397 .mpo_copy_pipe_label = mac_mls_copy_label,
2398 .mpo_copy_vnode_label = mac_mls_copy_label,
2399 .mpo_externalize_cred_label = mac_mls_externalize_label,
2400 .mpo_externalize_ifnet_label = mac_mls_externalize_label,
2401 .mpo_externalize_pipe_label = mac_mls_externalize_label,
2402 .mpo_externalize_socket_label = mac_mls_externalize_label,
2403 .mpo_externalize_socket_peer_label = mac_mls_externalize_label,
2404 .mpo_externalize_vnode_label = mac_mls_externalize_label,
2405 .mpo_internalize_cred_label = mac_mls_internalize_label,
2406 .mpo_internalize_ifnet_label = mac_mls_internalize_label,
2407 .mpo_internalize_pipe_label = mac_mls_internalize_label,
2408 .mpo_internalize_socket_label = mac_mls_internalize_label,
2409 .mpo_internalize_vnode_label = mac_mls_internalize_label,
2410 .mpo_create_devfs_device = mac_mls_create_devfs_device,
2411 .mpo_create_devfs_directory = mac_mls_create_devfs_directory,
2412 .mpo_create_devfs_symlink = mac_mls_create_devfs_symlink,
2413 .mpo_create_mount = mac_mls_create_mount,
2414 .mpo_create_root_mount = mac_mls_create_root_mount,
2415 .mpo_relabel_vnode = mac_mls_relabel_vnode,
2416 .mpo_update_devfsdirent = mac_mls_update_devfsdirent,
2417 .mpo_associate_vnode_devfs = mac_mls_associate_vnode_devfs,
2418 .mpo_associate_vnode_extattr = mac_mls_associate_vnode_extattr,
2419 .mpo_associate_vnode_singlelabel = mac_mls_associate_vnode_singlelabel,
2420 .mpo_create_vnode_extattr = mac_mls_create_vnode_extattr,
2421 .mpo_setlabel_vnode_extattr = mac_mls_setlabel_vnode_extattr,
2422 .mpo_create_mbuf_from_socket = mac_mls_create_mbuf_from_socket,
2423 .mpo_create_pipe = mac_mls_create_pipe,
2424 .mpo_create_socket = mac_mls_create_socket,
2425 .mpo_create_socket_from_socket = mac_mls_create_socket_from_socket,
2426 .mpo_relabel_pipe = mac_mls_relabel_pipe,
2427 .mpo_relabel_socket = mac_mls_relabel_socket,
2428 .mpo_set_socket_peer_from_mbuf = mac_mls_set_socket_peer_from_mbuf,
2429 .mpo_set_socket_peer_from_socket = mac_mls_set_socket_peer_from_socket,
2430 .mpo_create_bpfdesc = mac_mls_create_bpfdesc,
2431 .mpo_create_datagram_from_ipq = mac_mls_create_datagram_from_ipq,
2432 .mpo_create_fragment = mac_mls_create_fragment,
2433 .mpo_create_ifnet = mac_mls_create_ifnet,
2434 .mpo_create_ipq = mac_mls_create_ipq,
2435 .mpo_create_mbuf_from_mbuf = mac_mls_create_mbuf_from_mbuf,
2436 .mpo_create_mbuf_linklayer = mac_mls_create_mbuf_linklayer,
2437 .mpo_create_mbuf_from_bpfdesc = mac_mls_create_mbuf_from_bpfdesc,
2438 .mpo_create_mbuf_from_ifnet = mac_mls_create_mbuf_from_ifnet,
2439 .mpo_create_mbuf_multicast_encap = mac_mls_create_mbuf_multicast_encap,
2440 .mpo_create_mbuf_netlayer = mac_mls_create_mbuf_netlayer,
2441 .mpo_fragment_match = mac_mls_fragment_match,
2442 .mpo_relabel_ifnet = mac_mls_relabel_ifnet,
2443 .mpo_update_ipq = mac_mls_update_ipq,
2444 .mpo_create_cred = mac_mls_create_cred,
2445 .mpo_create_proc0 = mac_mls_create_proc0,
2446 .mpo_create_proc1 = mac_mls_create_proc1,
2447 .mpo_relabel_cred = mac_mls_relabel_cred,
2448 .mpo_check_bpfdesc_receive = mac_mls_check_bpfdesc_receive,
2449 .mpo_check_cred_relabel = mac_mls_check_cred_relabel,
2450 .mpo_check_cred_visible = mac_mls_check_cred_visible,
2451 .mpo_check_ifnet_relabel = mac_mls_check_ifnet_relabel,
2452 .mpo_check_ifnet_transmit = mac_mls_check_ifnet_transmit,
2453 .mpo_check_mount_stat = mac_mls_check_mount_stat,
2454 .mpo_check_pipe_ioctl = mac_mls_check_pipe_ioctl,
2455 .mpo_check_pipe_poll = mac_mls_check_pipe_poll,
2456 .mpo_check_pipe_read = mac_mls_check_pipe_read,
2457 .mpo_check_pipe_relabel = mac_mls_check_pipe_relabel,
2458 .mpo_check_pipe_stat = mac_mls_check_pipe_stat,
2459 .mpo_check_pipe_write = mac_mls_check_pipe_write,
2460 .mpo_check_proc_debug = mac_mls_check_proc_debug,
2461 .mpo_check_proc_sched = mac_mls_check_proc_sched,
2462 .mpo_check_proc_signal = mac_mls_check_proc_signal,
2463 .mpo_check_socket_deliver = mac_mls_check_socket_deliver,
2464 .mpo_check_socket_relabel = mac_mls_check_socket_relabel,
2465 .mpo_check_socket_visible = mac_mls_check_socket_visible,
2466 .mpo_check_system_swapon = mac_mls_check_system_swapon,
2467 .mpo_check_vnode_access = mac_mls_check_vnode_open,
2468 .mpo_check_vnode_chdir = mac_mls_check_vnode_chdir,
2469 .mpo_check_vnode_chroot = mac_mls_check_vnode_chroot,
2470 .mpo_check_vnode_create = mac_mls_check_vnode_create,
2471 .mpo_check_vnode_delete = mac_mls_check_vnode_delete,
2472 .mpo_check_vnode_deleteacl = mac_mls_check_vnode_deleteacl,
2473 .mpo_check_vnode_exec = mac_mls_check_vnode_exec,
2474 .mpo_check_vnode_getacl = mac_mls_check_vnode_getacl,
2475 .mpo_check_vnode_getextattr = mac_mls_check_vnode_getextattr,
2476 .mpo_check_vnode_link = mac_mls_check_vnode_link,
2477 .mpo_check_vnode_lookup = mac_mls_check_vnode_lookup,
2478 .mpo_check_vnode_mmap = mac_mls_check_vnode_mmap,
2479 .mpo_check_vnode_mprotect = mac_mls_check_vnode_mmap,
2480 .mpo_check_vnode_open = mac_mls_check_vnode_open,
2481 .mpo_check_vnode_poll = mac_mls_check_vnode_poll,
2482 .mpo_check_vnode_read = mac_mls_check_vnode_read,
2483 .mpo_check_vnode_readdir = mac_mls_check_vnode_readdir,
2484 .mpo_check_vnode_readlink = mac_mls_check_vnode_readlink,
2485 .mpo_check_vnode_relabel = mac_mls_check_vnode_relabel,
2486 .mpo_check_vnode_rename_from = mac_mls_check_vnode_rename_from,
2487 .mpo_check_vnode_rename_to = mac_mls_check_vnode_rename_to,
2488 .mpo_check_vnode_revoke = mac_mls_check_vnode_revoke,
2489 .mpo_check_vnode_setacl = mac_mls_check_vnode_setacl,
2490 .mpo_check_vnode_setextattr = mac_mls_check_vnode_setextattr,
2491 .mpo_check_vnode_setflags = mac_mls_check_vnode_setflags,
2492 .mpo_check_vnode_setmode = mac_mls_check_vnode_setmode,
2493 .mpo_check_vnode_setowner = mac_mls_check_vnode_setowner,
2494 .mpo_check_vnode_setutimes = mac_mls_check_vnode_setutimes,
2495 .mpo_check_vnode_stat = mac_mls_check_vnode_stat,
2496 .mpo_check_vnode_write = mac_mls_check_vnode_write,
2497 };
2498
2499 MAC_POLICY_SET(&mac_mls_ops, mac_mls, "TrustedBSD MAC/MLS",
2500 MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_mls_slot);
Cache object: 1295fbd522a6283ba8ddaa3a1d1074af
|