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