2 * Copyright (c) 1999-2002 Robert N. M. Watson
3 * Copyright (c) 2001-2003 Networks Associates Technology, Inc.
6 * This software was developed by Robert Watson for the TrustedBSD Project.
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.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
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.
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
38 * Developed by the TrustedBSD Project.
39 * MLS fixed label mandatory confidentiality policy.
42 #include <sys/types.h>
43 #include <sys/param.h>
46 #include <sys/extattr.h>
47 #include <sys/kernel.h>
49 #include <sys/malloc.h>
50 #include <sys/mount.h>
53 #include <sys/systm.h>
54 #include <sys/sysproto.h>
55 #include <sys/sysent.h>
56 #include <sys/systm.h>
57 #include <sys/vnode.h>
59 #include <sys/socket.h>
60 #include <sys/socketvar.h>
62 #include <sys/sysctl.h>
64 #include <fs/devfs/devfs.h>
66 #include <net/bpfdesc.h>
68 #include <net/if_types.h>
69 #include <net/if_var.h>
71 #include <netinet/in.h>
72 #include <netinet/in_pcb.h>
73 #include <netinet/ip_var.h>
78 #include <sys/mac_policy.h>
80 #include <security/mac_mls/mac_mls.h>
82 SYSCTL_DECL(_security_mac);
84 SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
85 "TrustedBSD mac_mls policy controls");
87 static int mac_mls_label_size = sizeof(struct mac_mls);
88 SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
89 &mac_mls_label_size, 0, "Size of struct mac_mls");
91 static int mac_mls_enabled = 1;
92 SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
93 &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
94 TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
96 static int destroyed_not_inited;
97 SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
98 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
100 static int ptys_equal = 0;
101 SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
102 &ptys_equal, 0, "Label pty devices as mls/equal on create");
103 TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
105 static int revocation_enabled = 0;
106 SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
107 &revocation_enabled, 0, "Revoke access to objects on relabel");
108 TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
110 static int max_compartments = MAC_MLS_MAX_COMPARTMENTS;
111 SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
112 &max_compartments, 0, "Maximum compartments the policy supports");
114 static int mac_mls_slot;
115 #define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
116 #define SLOT_SET(l, val) (LABEL_TO_SLOT((l), mac_mls_slot).l_ptr = (val))
118 static uma_zone_t zone_mls;
121 mls_bit_set_empty(u_char *set) {
124 for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
130 static struct mac_mls *
134 return (uma_zalloc(zone_mls, flag | M_ZERO));
138 mls_free(struct mac_mls *mac_mls)
142 uma_zfree(zone_mls, mac_mls);
144 atomic_add_int(&destroyed_not_inited, 1);
148 mls_atmostflags(struct mac_mls *mac_mls, int flags)
151 if ((mac_mls->mm_flags & flags) != mac_mls->mm_flags)
157 mac_mls_dominate_element(struct mac_mls_element *a,
158 struct mac_mls_element *b)
162 switch (a->mme_type) {
163 case MAC_MLS_TYPE_EQUAL:
164 case MAC_MLS_TYPE_HIGH:
167 case MAC_MLS_TYPE_LOW:
168 switch (b->mme_type) {
169 case MAC_MLS_TYPE_LEVEL:
170 case MAC_MLS_TYPE_HIGH:
173 case MAC_MLS_TYPE_EQUAL:
174 case MAC_MLS_TYPE_LOW:
178 panic("mac_mls_dominate_element: b->mme_type invalid");
181 case MAC_MLS_TYPE_LEVEL:
182 switch (b->mme_type) {
183 case MAC_MLS_TYPE_EQUAL:
184 case MAC_MLS_TYPE_LOW:
187 case MAC_MLS_TYPE_HIGH:
190 case MAC_MLS_TYPE_LEVEL:
191 for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
192 if (!MAC_MLS_BIT_TEST(bit,
193 a->mme_compartments) &&
194 MAC_MLS_BIT_TEST(bit, b->mme_compartments))
196 return (a->mme_level >= b->mme_level);
199 panic("mac_mls_dominate_element: b->mme_type invalid");
203 panic("mac_mls_dominate_element: a->mme_type invalid");
210 mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
213 return (mac_mls_dominate_element(&rangeb->mm_rangehigh,
214 &rangea->mm_rangehigh) &&
215 mac_mls_dominate_element(&rangea->mm_rangelow,
216 &rangeb->mm_rangelow));
220 mac_mls_effective_in_range(struct mac_mls *effective, struct mac_mls *range)
223 KASSERT((effective->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
224 ("mac_mls_effective_in_range: a not effective"));
225 KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
226 ("mac_mls_effective_in_range: b not range"));
228 return (mac_mls_dominate_element(&range->mm_rangehigh,
229 &effective->mm_effective) &&
230 mac_mls_dominate_element(&effective->mm_effective,
231 &range->mm_rangelow));
237 mac_mls_dominate_effective(struct mac_mls *a, struct mac_mls *b)
239 KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
240 ("mac_mls_dominate_effective: a not effective"));
241 KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
242 ("mac_mls_dominate_effective: b not effective"));
244 return (mac_mls_dominate_element(&a->mm_effective, &b->mm_effective));
248 mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
251 if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
252 b->mme_type == MAC_MLS_TYPE_EQUAL)
255 return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
259 mac_mls_equal_effective(struct mac_mls *a, struct mac_mls *b)
262 KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
263 ("mac_mls_equal_effective: a not effective"));
264 KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
265 ("mac_mls_equal_effective: b not effective"));
267 return (mac_mls_equal_element(&a->mm_effective, &b->mm_effective));
271 mac_mls_contains_equal(struct mac_mls *mac_mls)
274 if (mac_mls->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
275 if (mac_mls->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
278 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
279 if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
281 if (mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
289 mac_mls_subject_privileged(struct mac_mls *mac_mls)
292 KASSERT((mac_mls->mm_flags & MAC_MLS_FLAGS_BOTH) ==
294 ("mac_mls_subject_privileged: subject doesn't have both labels"));
296 /* If the effective is EQUAL, it's ok. */
297 if (mac_mls->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
300 /* If either range endpoint is EQUAL, it's ok. */
301 if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
302 mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
305 /* If the range is low-high, it's ok. */
306 if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
307 mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
315 mac_mls_valid(struct mac_mls *mac_mls)
318 if (mac_mls->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
319 switch (mac_mls->mm_effective.mme_type) {
320 case MAC_MLS_TYPE_LEVEL:
323 case MAC_MLS_TYPE_EQUAL:
324 case MAC_MLS_TYPE_HIGH:
325 case MAC_MLS_TYPE_LOW:
326 if (mac_mls->mm_effective.mme_level != 0 ||
327 !MAC_MLS_BIT_SET_EMPTY(
328 mac_mls->mm_effective.mme_compartments))
336 if (mac_mls->mm_effective.mme_type != MAC_MLS_TYPE_UNDEF)
340 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
341 switch (mac_mls->mm_rangelow.mme_type) {
342 case MAC_MLS_TYPE_LEVEL:
345 case MAC_MLS_TYPE_EQUAL:
346 case MAC_MLS_TYPE_HIGH:
347 case MAC_MLS_TYPE_LOW:
348 if (mac_mls->mm_rangelow.mme_level != 0 ||
349 !MAC_MLS_BIT_SET_EMPTY(
350 mac_mls->mm_rangelow.mme_compartments))
358 switch (mac_mls->mm_rangehigh.mme_type) {
359 case MAC_MLS_TYPE_LEVEL:
362 case MAC_MLS_TYPE_EQUAL:
363 case MAC_MLS_TYPE_HIGH:
364 case MAC_MLS_TYPE_LOW:
365 if (mac_mls->mm_rangehigh.mme_level != 0 ||
366 !MAC_MLS_BIT_SET_EMPTY(
367 mac_mls->mm_rangehigh.mme_compartments))
374 if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh,
375 &mac_mls->mm_rangelow))
378 if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
379 mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
387 mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow,
388 u_short levellow, u_char *compartmentslow, u_short typehigh,
389 u_short levelhigh, u_char *compartmentshigh)
392 mac_mls->mm_rangelow.mme_type = typelow;
393 mac_mls->mm_rangelow.mme_level = levellow;
394 if (compartmentslow != NULL)
395 memcpy(mac_mls->mm_rangelow.mme_compartments,
397 sizeof(mac_mls->mm_rangelow.mme_compartments));
398 mac_mls->mm_rangehigh.mme_type = typehigh;
399 mac_mls->mm_rangehigh.mme_level = levelhigh;
400 if (compartmentshigh != NULL)
401 memcpy(mac_mls->mm_rangehigh.mme_compartments,
403 sizeof(mac_mls->mm_rangehigh.mme_compartments));
404 mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
408 mac_mls_set_effective(struct mac_mls *mac_mls, u_short type, u_short level,
409 u_char *compartments)
412 mac_mls->mm_effective.mme_type = type;
413 mac_mls->mm_effective.mme_level = level;
414 if (compartments != NULL)
415 memcpy(mac_mls->mm_effective.mme_compartments, compartments,
416 sizeof(mac_mls->mm_effective.mme_compartments));
417 mac_mls->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
421 mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
424 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
425 ("mac_mls_copy_range: labelfrom not range"));
427 labelto->mm_rangelow = labelfrom->mm_rangelow;
428 labelto->mm_rangehigh = labelfrom->mm_rangehigh;
429 labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
433 mac_mls_copy_effective(struct mac_mls *labelfrom, struct mac_mls *labelto)
436 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
437 ("mac_mls_copy_effective: labelfrom not effective"));
439 labelto->mm_effective = labelfrom->mm_effective;
440 labelto->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
444 mac_mls_copy(struct mac_mls *source, struct mac_mls *dest)
447 if (source->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
448 mac_mls_copy_effective(source, dest);
449 if (source->mm_flags & MAC_MLS_FLAG_RANGE)
450 mac_mls_copy_range(source, dest);
454 * Policy module operations.
457 mac_mls_init(struct mac_policy_conf *conf)
460 zone_mls = uma_zcreate("mac_mls", sizeof(struct mac_mls), NULL,
461 NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
468 mac_mls_init_label(struct label *label)
471 SLOT_SET(label, mls_alloc(M_WAITOK));
475 mac_mls_init_label_waitcheck(struct label *label, int flag)
478 SLOT_SET(label, mls_alloc(flag));
479 if (SLOT(label) == NULL)
486 mac_mls_destroy_label(struct label *label)
489 mls_free(SLOT(label));
490 SLOT_SET(label, NULL);
494 * mac_mls_element_to_string() accepts an sbuf and MLS element. It
495 * converts the MLS element to a string and stores the result in the
496 * sbuf; if there isn't space in the sbuf, -1 is returned.
499 mac_mls_element_to_string(struct sbuf *sb, struct mac_mls_element *element)
503 switch (element->mme_type) {
504 case MAC_MLS_TYPE_HIGH:
505 return (sbuf_printf(sb, "high"));
507 case MAC_MLS_TYPE_LOW:
508 return (sbuf_printf(sb, "low"));
510 case MAC_MLS_TYPE_EQUAL:
511 return (sbuf_printf(sb, "equal"));
513 case MAC_MLS_TYPE_LEVEL:
514 if (sbuf_printf(sb, "%d", element->mme_level) == -1)
518 for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) {
519 if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) {
521 if (sbuf_putc(sb, ':') == -1)
523 if (sbuf_printf(sb, "%d", i) == -1)
527 if (sbuf_printf(sb, "+%d", i) == -1)
535 panic("mac_mls_element_to_string: invalid type (%d)",
541 * mac_mls_to_string() converts an MLS label to a string, and places
542 * the results in the passed sbuf. It returns 0 on success, or EINVAL
543 * if there isn't room in the sbuf. Note: the sbuf will be modified
544 * even in a failure case, so the caller may need to revert the sbuf
545 * by restoring the offset if that's undesired.
548 mac_mls_to_string(struct sbuf *sb, struct mac_mls *mac_mls)
551 if (mac_mls->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
552 if (mac_mls_element_to_string(sb, &mac_mls->mm_effective)
557 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
558 if (sbuf_putc(sb, '(') == -1)
561 if (mac_mls_element_to_string(sb, &mac_mls->mm_rangelow)
565 if (sbuf_putc(sb, '-') == -1)
568 if (mac_mls_element_to_string(sb, &mac_mls->mm_rangehigh)
572 if (sbuf_putc(sb, ')') == -1)
580 mac_mls_externalize_label(struct label *label, char *element_name,
581 struct sbuf *sb, int *claimed)
583 struct mac_mls *mac_mls;
585 if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
590 mac_mls = SLOT(label);
592 return (mac_mls_to_string(sb, mac_mls));
596 mac_mls_parse_element(struct mac_mls_element *element, char *string)
598 char *compartment, *end, *level;
601 if (strcmp(string, "high") == 0 ||
602 strcmp(string, "hi") == 0) {
603 element->mme_type = MAC_MLS_TYPE_HIGH;
604 element->mme_level = MAC_MLS_TYPE_UNDEF;
605 } else if (strcmp(string, "low") == 0 ||
606 strcmp(string, "lo") == 0) {
607 element->mme_type = MAC_MLS_TYPE_LOW;
608 element->mme_level = MAC_MLS_TYPE_UNDEF;
609 } else if (strcmp(string, "equal") == 0 ||
610 strcmp(string, "eq") == 0) {
611 element->mme_type = MAC_MLS_TYPE_EQUAL;
612 element->mme_level = MAC_MLS_TYPE_UNDEF;
614 element->mme_type = MAC_MLS_TYPE_LEVEL;
617 * Numeric level piece of the element.
619 level = strsep(&string, ":");
620 value = strtol(level, &end, 10);
621 if (end == level || *end != '\0')
623 if (value < 0 || value > 65535)
625 element->mme_level = value;
628 * Optional compartment piece of the element. If none
629 * are included, we assume that the label has no
637 while ((compartment = strsep(&string, "+")) != NULL) {
638 value = strtol(compartment, &end, 10);
639 if (compartment == end || *end != '\0')
641 if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS)
643 MAC_MLS_BIT_SET(value, element->mme_compartments);
651 * Note: destructively consumes the string, make a local copy before
652 * calling if that's a problem.
655 mac_mls_parse(struct mac_mls *mac_mls, char *string)
657 char *rangehigh, *rangelow, *effective;
660 effective = strsep(&string, "(");
661 if (*effective == '\0')
664 if (string != NULL) {
665 rangelow = strsep(&string, "-");
668 rangehigh = strsep(&string, ")");
678 KASSERT((rangelow != NULL && rangehigh != NULL) ||
679 (rangelow == NULL && rangehigh == NULL),
680 ("mac_mls_parse: range mismatch"));
682 bzero(mac_mls, sizeof(*mac_mls));
683 if (effective != NULL) {
684 error = mac_mls_parse_element(&mac_mls->mm_effective, effective);
687 mac_mls->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
690 if (rangelow != NULL) {
691 error = mac_mls_parse_element(&mac_mls->mm_rangelow,
695 error = mac_mls_parse_element(&mac_mls->mm_rangehigh,
699 mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
702 error = mac_mls_valid(mac_mls);
710 mac_mls_internalize_label(struct label *label, char *element_name,
711 char *element_data, int *claimed)
713 struct mac_mls *mac_mls, mac_mls_temp;
716 if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
721 error = mac_mls_parse(&mac_mls_temp, element_data);
725 mac_mls = SLOT(label);
726 *mac_mls = mac_mls_temp;
732 mac_mls_copy_label(struct label *src, struct label *dest)
735 *SLOT(dest) = *SLOT(src);
739 * Labeling event operations: file system objects, and things that look
740 * a lot like file system objects.
743 mac_mls_create_devfs_device(struct mount *mp, struct cdev *dev,
744 struct devfs_dirent *devfs_dirent, struct label *label)
746 struct mac_mls *mac_mls;
749 mac_mls = SLOT(label);
750 if (strcmp(dev->si_name, "null") == 0 ||
751 strcmp(dev->si_name, "zero") == 0 ||
752 strcmp(dev->si_name, "random") == 0 ||
753 strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
754 mls_type = MAC_MLS_TYPE_EQUAL;
755 else if (strcmp(dev->si_name, "kmem") == 0 ||
756 strcmp(dev->si_name, "mem") == 0)
757 mls_type = MAC_MLS_TYPE_HIGH;
758 else if (ptys_equal &&
759 (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
760 strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
761 mls_type = MAC_MLS_TYPE_EQUAL;
763 mls_type = MAC_MLS_TYPE_LOW;
764 mac_mls_set_effective(mac_mls, mls_type, 0, NULL);
768 mac_mls_create_devfs_directory(struct mount *mp, char *dirname,
769 int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
771 struct mac_mls *mac_mls;
773 mac_mls = SLOT(label);
774 mac_mls_set_effective(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
778 mac_mls_create_devfs_symlink(struct ucred *cred, struct mount *mp,
779 struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
780 struct label *delabel)
782 struct mac_mls *source, *dest;
784 source = SLOT(cred->cr_label);
785 dest = SLOT(delabel);
787 mac_mls_copy_effective(source, dest);
791 mac_mls_create_mount(struct ucred *cred, struct mount *mp,
792 struct label *mntlabel, struct label *fslabel)
794 struct mac_mls *source, *dest;
796 source = SLOT(cred->cr_label);
797 dest = SLOT(mntlabel);
798 mac_mls_copy_effective(source, dest);
799 dest = SLOT(fslabel);
800 mac_mls_copy_effective(source, dest);
804 mac_mls_create_root_mount(struct ucred *cred, struct mount *mp,
805 struct label *mntlabel, struct label *fslabel)
807 struct mac_mls *mac_mls;
809 /* Always mount root as high integrity. */
810 mac_mls = SLOT(fslabel);
811 mac_mls_set_effective(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
812 mac_mls = SLOT(mntlabel);
813 mac_mls_set_effective(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
817 mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp,
818 struct label *vnodelabel, struct label *label)
820 struct mac_mls *source, *dest;
822 source = SLOT(label);
823 dest = SLOT(vnodelabel);
825 mac_mls_copy(source, dest);
829 mac_mls_update_devfsdirent(struct mount *mp,
830 struct devfs_dirent *devfs_dirent, struct label *direntlabel,
831 struct vnode *vp, struct label *vnodelabel)
833 struct mac_mls *source, *dest;
835 source = SLOT(vnodelabel);
836 dest = SLOT(direntlabel);
838 mac_mls_copy_effective(source, dest);
842 mac_mls_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
843 struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
844 struct label *vlabel)
846 struct mac_mls *source, *dest;
848 source = SLOT(delabel);
851 mac_mls_copy_effective(source, dest);
855 mac_mls_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
856 struct vnode *vp, struct label *vlabel)
858 struct mac_mls temp, *source, *dest;
861 source = SLOT(fslabel);
864 buflen = sizeof(temp);
865 bzero(&temp, buflen);
867 error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
868 MAC_MLS_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
869 if (error == ENOATTR || error == EOPNOTSUPP) {
870 /* Fall back to the fslabel. */
871 mac_mls_copy_effective(source, dest);
876 if (buflen != sizeof(temp)) {
877 printf("mac_mls_associate_vnode_extattr: bad size %d\n",
881 if (mac_mls_valid(&temp) != 0) {
882 printf("mac_mls_associate_vnode_extattr: invalid\n");
885 if ((temp.mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_EFFECTIVE) {
886 printf("mac_mls_associated_vnode_extattr: not effective\n");
890 mac_mls_copy_effective(&temp, dest);
895 mac_mls_associate_vnode_singlelabel(struct mount *mp,
896 struct label *fslabel, struct vnode *vp, struct label *vlabel)
898 struct mac_mls *source, *dest;
900 source = SLOT(fslabel);
903 mac_mls_copy_effective(source, dest);
907 mac_mls_create_vnode_extattr(struct ucred *cred, struct mount *mp,
908 struct label *fslabel, struct vnode *dvp, struct label *dlabel,
909 struct vnode *vp, struct label *vlabel, struct componentname *cnp)
911 struct mac_mls *source, *dest, temp;
915 buflen = sizeof(temp);
916 bzero(&temp, buflen);
918 source = SLOT(cred->cr_label);
920 mac_mls_copy_effective(source, &temp);
922 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
923 MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
925 mac_mls_copy_effective(source, dest);
930 mac_mls_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
931 struct label *vlabel, struct label *intlabel)
933 struct mac_mls *source, temp;
937 buflen = sizeof(temp);
938 bzero(&temp, buflen);
940 source = SLOT(intlabel);
941 if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
944 mac_mls_copy_effective(source, &temp);
946 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
947 MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
952 * Labeling event operations: IPC object.
955 mac_mls_create_inpcb_from_socket(struct socket *so, struct label *solabel,
956 struct inpcb *inp, struct label *inplabel)
958 struct mac_mls *source, *dest;
960 source = SLOT(solabel);
961 dest = SLOT(inplabel);
963 mac_mls_copy_effective(source, dest);
967 mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
968 struct mbuf *m, struct label *mbuflabel)
970 struct mac_mls *source, *dest;
972 source = SLOT(socketlabel);
973 dest = SLOT(mbuflabel);
975 mac_mls_copy_effective(source, dest);
979 mac_mls_create_socket(struct ucred *cred, struct socket *socket,
980 struct label *socketlabel)
982 struct mac_mls *source, *dest;
984 source = SLOT(cred->cr_label);
985 dest = SLOT(socketlabel);
987 mac_mls_copy_effective(source, dest);
991 mac_mls_create_pipe(struct ucred *cred, struct pipepair *pp,
992 struct label *pipelabel)
994 struct mac_mls *source, *dest;
996 source = SLOT(cred->cr_label);
997 dest = SLOT(pipelabel);
999 mac_mls_copy_effective(source, dest);
1003 mac_mls_create_socket_from_socket(struct socket *oldsocket,
1004 struct label *oldsocketlabel, struct socket *newsocket,
1005 struct label *newsocketlabel)
1007 struct mac_mls *source, *dest;
1009 source = SLOT(oldsocketlabel);
1010 dest = SLOT(newsocketlabel);
1012 mac_mls_copy_effective(source, dest);
1016 mac_mls_relabel_socket(struct ucred *cred, struct socket *socket,
1017 struct label *socketlabel, struct label *newlabel)
1019 struct mac_mls *source, *dest;
1021 source = SLOT(newlabel);
1022 dest = SLOT(socketlabel);
1024 mac_mls_copy(source, dest);
1028 mac_mls_relabel_pipe(struct ucred *cred, struct pipepair *pp,
1029 struct label *pipelabel, struct label *newlabel)
1031 struct mac_mls *source, *dest;
1033 source = SLOT(newlabel);
1034 dest = SLOT(pipelabel);
1036 mac_mls_copy(source, dest);
1040 mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1041 struct socket *socket, struct label *socketpeerlabel)
1043 struct mac_mls *source, *dest;
1045 source = SLOT(mbuflabel);
1046 dest = SLOT(socketpeerlabel);
1048 mac_mls_copy_effective(source, dest);
1052 * Labeling event operations: network objects.
1055 mac_mls_set_socket_peer_from_socket(struct socket *oldsocket,
1056 struct label *oldsocketlabel, struct socket *newsocket,
1057 struct label *newsocketpeerlabel)
1059 struct mac_mls *source, *dest;
1061 source = SLOT(oldsocketlabel);
1062 dest = SLOT(newsocketpeerlabel);
1064 mac_mls_copy_effective(source, dest);
1068 mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1069 struct label *bpflabel)
1071 struct mac_mls *source, *dest;
1073 source = SLOT(cred->cr_label);
1074 dest = SLOT(bpflabel);
1076 mac_mls_copy_effective(source, dest);
1080 mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1082 struct mac_mls *dest;
1085 dest = SLOT(ifnetlabel);
1087 if (ifnet->if_type == IFT_LOOP)
1088 type = MAC_MLS_TYPE_EQUAL;
1090 type = MAC_MLS_TYPE_LOW;
1092 mac_mls_set_effective(dest, type, 0, NULL);
1093 mac_mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1097 mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1098 struct ipq *ipq, struct label *ipqlabel)
1100 struct mac_mls *source, *dest;
1102 source = SLOT(fragmentlabel);
1103 dest = SLOT(ipqlabel);
1105 mac_mls_copy_effective(source, dest);
1109 mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1110 struct mbuf *datagram, struct label *datagramlabel)
1112 struct mac_mls *source, *dest;
1114 source = SLOT(ipqlabel);
1115 dest = SLOT(datagramlabel);
1117 /* Just use the head, since we require them all to match. */
1118 mac_mls_copy_effective(source, dest);
1122 mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1123 struct mbuf *fragment, struct label *fragmentlabel)
1125 struct mac_mls *source, *dest;
1127 source = SLOT(datagramlabel);
1128 dest = SLOT(fragmentlabel);
1130 mac_mls_copy_effective(source, dest);
1134 mac_mls_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel,
1135 struct mbuf *m, struct label *mlabel)
1137 struct mac_mls *source, *dest;
1139 source = SLOT(inplabel);
1140 dest = SLOT(mlabel);
1142 mac_mls_copy_effective(source, dest);
1146 mac_mls_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
1147 struct label *oldmbuflabel, struct mbuf *newmbuf,
1148 struct label *newmbuflabel)
1150 struct mac_mls *source, *dest;
1152 source = SLOT(oldmbuflabel);
1153 dest = SLOT(newmbuflabel);
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
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);
1167 mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1168 struct mbuf *mbuf, struct label *mbuflabel)
1170 struct mac_mls *dest;
1172 dest = SLOT(mbuflabel);
1174 mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1178 mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1179 struct mbuf *mbuf, struct label *mbuflabel)
1181 struct mac_mls *source, *dest;
1183 source = SLOT(bpflabel);
1184 dest = SLOT(mbuflabel);
1186 mac_mls_copy_effective(source, dest);
1190 mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1191 struct mbuf *m, struct label *mbuflabel)
1193 struct mac_mls *source, *dest;
1195 source = SLOT(ifnetlabel);
1196 dest = SLOT(mbuflabel);
1198 mac_mls_copy_effective(source, dest);
1202 mac_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)
1206 struct mac_mls *source, *dest;
1208 source = SLOT(oldmbuflabel);
1209 dest = SLOT(newmbuflabel);
1211 mac_mls_copy_effective(source, dest);
1215 mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1216 struct mbuf *newmbuf, struct label *newmbuflabel)
1218 struct mac_mls *source, *dest;
1220 source = SLOT(oldmbuflabel);
1221 dest = SLOT(newmbuflabel);
1223 mac_mls_copy_effective(source, dest);
1227 mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1228 struct ipq *ipq, struct label *ipqlabel)
1230 struct mac_mls *a, *b;
1233 b = SLOT(fragmentlabel);
1235 return (mac_mls_equal_effective(a, b));
1239 mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1240 struct label *ifnetlabel, struct label *newlabel)
1242 struct mac_mls *source, *dest;
1244 source = SLOT(newlabel);
1245 dest = SLOT(ifnetlabel);
1247 mac_mls_copy(source, dest);
1251 mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1252 struct ipq *ipq, struct label *ipqlabel)
1255 /* NOOP: we only accept matching labels, so no need to update */
1259 mac_mls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1260 struct inpcb *inp, struct label *inplabel)
1262 struct mac_mls *source, *dest;
1264 source = SLOT(solabel);
1265 dest = SLOT(inplabel);
1267 mac_mls_copy(source, dest);
1271 * Labeling event operations: processes.
1274 mac_mls_create_proc0(struct ucred *cred)
1276 struct mac_mls *dest;
1278 dest = SLOT(cred->cr_label);
1280 mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1281 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
1286 mac_mls_create_proc1(struct ucred *cred)
1288 struct mac_mls *dest;
1290 dest = SLOT(cred->cr_label);
1292 mac_mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL);
1293 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
1298 mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel)
1300 struct mac_mls *source, *dest;
1302 source = SLOT(newlabel);
1303 dest = SLOT(cred->cr_label);
1305 mac_mls_copy(source, dest);
1309 * Access control checks.
1312 mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1313 struct ifnet *ifnet, struct label *ifnetlabel)
1315 struct mac_mls *a, *b;
1317 if (!mac_mls_enabled)
1321 b = SLOT(ifnetlabel);
1323 if (mac_mls_equal_effective(a, b))
1329 mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1331 struct mac_mls *subj, *new;
1334 subj = SLOT(cred->cr_label);
1335 new = SLOT(newlabel);
1338 * If there is an MLS label update for the credential, it may be
1339 * an update of effective, range, or both.
1341 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
1346 * If the MLS label is to be changed, authorize as appropriate.
1348 if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
1350 * If the change request modifies both the MLS label effective
1351 * and range, check that the new effective will be in the
1354 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
1355 MAC_MLS_FLAGS_BOTH &&
1356 !mac_mls_effective_in_range(new, new))
1360 * To change the MLS effective label on a credential, the
1361 * new effective label must be in the current range.
1363 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE &&
1364 !mac_mls_effective_in_range(new, subj))
1368 * To change the MLS range label on a credential, the
1369 * new range must be in the current range.
1371 if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
1372 !mac_mls_range_in_range(new, subj))
1376 * To have EQUAL in any component of the new credential
1377 * MLS label, the subject must already have EQUAL in
1380 if (mac_mls_contains_equal(new)) {
1381 error = mac_mls_subject_privileged(subj);
1391 mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
1393 struct mac_mls *subj, *obj;
1395 if (!mac_mls_enabled)
1398 subj = SLOT(u1->cr_label);
1399 obj = SLOT(u2->cr_label);
1402 if (!mac_mls_dominate_effective(subj, obj))
1409 mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1410 struct label *ifnetlabel, struct label *newlabel)
1412 struct mac_mls *subj, *new;
1415 subj = SLOT(cred->cr_label);
1416 new = SLOT(newlabel);
1419 * If there is an MLS label update for the interface, it may
1420 * be an update of effective, range, or both.
1422 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
1427 * Relabeling network interfaces requires MLS privilege.
1429 error = mac_mls_subject_privileged(subj);
1435 mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1436 struct mbuf *m, struct label *mbuflabel)
1438 struct mac_mls *p, *i;
1440 if (!mac_mls_enabled)
1443 p = SLOT(mbuflabel);
1444 i = SLOT(ifnetlabel);
1446 return (mac_mls_effective_in_range(p, i) ? 0 : EACCES);
1450 mac_mls_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1451 struct mbuf *m, struct label *mlabel)
1453 struct mac_mls *p, *i;
1455 if (!mac_mls_enabled)
1461 return (mac_mls_equal_effective(p, i) ? 0 : EACCES);
1465 mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp,
1466 struct label *mntlabel)
1468 struct mac_mls *subj, *obj;
1470 if (!mac_mls_enabled)
1473 subj = SLOT(cred->cr_label);
1474 obj = SLOT(mntlabel);
1476 if (!mac_mls_dominate_effective(subj, obj))
1483 mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
1484 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1487 if(!mac_mls_enabled)
1490 /* XXX: This will be implemented soon... */
1496 mac_mls_check_pipe_poll(struct ucred *cred, struct pipepair *pp,
1497 struct label *pipelabel)
1499 struct mac_mls *subj, *obj;
1501 if (!mac_mls_enabled)
1504 subj = SLOT(cred->cr_label);
1505 obj = SLOT((pipelabel));
1507 if (!mac_mls_dominate_effective(subj, obj))
1514 mac_mls_check_pipe_read(struct ucred *cred, struct pipepair *pp,
1515 struct label *pipelabel)
1517 struct mac_mls *subj, *obj;
1519 if (!mac_mls_enabled)
1522 subj = SLOT(cred->cr_label);
1523 obj = SLOT((pipelabel));
1525 if (!mac_mls_dominate_effective(subj, obj))
1532 mac_mls_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1533 struct label *pipelabel, struct label *newlabel)
1535 struct mac_mls *subj, *obj, *new;
1538 new = SLOT(newlabel);
1539 subj = SLOT(cred->cr_label);
1540 obj = SLOT(pipelabel);
1543 * If there is an MLS label update for a pipe, it must be a
1546 error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1551 * To perform a relabel of a pipe (MLS label or not), MLS must
1552 * authorize the relabel.
1554 if (!mac_mls_effective_in_range(obj, subj))
1558 * If the MLS label is to be changed, authorize as appropriate.
1560 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1562 * To change the MLS label on a pipe, the new pipe label
1563 * must be in the subject range.
1565 if (!mac_mls_effective_in_range(new, subj))
1569 * To change the MLS label on a pipe to be EQUAL, the
1570 * subject must have appropriate privilege.
1572 if (mac_mls_contains_equal(new)) {
1573 error = mac_mls_subject_privileged(subj);
1583 mac_mls_check_pipe_stat(struct ucred *cred, struct pipepair *pp,
1584 struct label *pipelabel)
1586 struct mac_mls *subj, *obj;
1588 if (!mac_mls_enabled)
1591 subj = SLOT(cred->cr_label);
1592 obj = SLOT((pipelabel));
1594 if (!mac_mls_dominate_effective(subj, obj))
1601 mac_mls_check_pipe_write(struct ucred *cred, struct pipepair *pp,
1602 struct label *pipelabel)
1604 struct mac_mls *subj, *obj;
1606 if (!mac_mls_enabled)
1609 subj = SLOT(cred->cr_label);
1610 obj = SLOT((pipelabel));
1612 if (!mac_mls_dominate_effective(obj, subj))
1619 mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc)
1621 struct mac_mls *subj, *obj;
1623 if (!mac_mls_enabled)
1626 subj = SLOT(cred->cr_label);
1627 obj = SLOT(proc->p_ucred->cr_label);
1629 /* XXX: range checks */
1630 if (!mac_mls_dominate_effective(subj, obj))
1632 if (!mac_mls_dominate_effective(obj, subj))
1639 mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc)
1641 struct mac_mls *subj, *obj;
1643 if (!mac_mls_enabled)
1646 subj = SLOT(cred->cr_label);
1647 obj = SLOT(proc->p_ucred->cr_label);
1649 /* XXX: range checks */
1650 if (!mac_mls_dominate_effective(subj, obj))
1652 if (!mac_mls_dominate_effective(obj, subj))
1659 mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1661 struct mac_mls *subj, *obj;
1663 if (!mac_mls_enabled)
1666 subj = SLOT(cred->cr_label);
1667 obj = SLOT(proc->p_ucred->cr_label);
1669 /* XXX: range checks */
1670 if (!mac_mls_dominate_effective(subj, obj))
1672 if (!mac_mls_dominate_effective(obj, subj))
1679 mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel,
1680 struct mbuf *m, struct label *mbuflabel)
1682 struct mac_mls *p, *s;
1684 if (!mac_mls_enabled)
1687 p = SLOT(mbuflabel);
1688 s = SLOT(socketlabel);
1690 return (mac_mls_equal_effective(p, s) ? 0 : EACCES);
1694 mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket,
1695 struct label *socketlabel, struct label *newlabel)
1697 struct mac_mls *subj, *obj, *new;
1700 new = SLOT(newlabel);
1701 subj = SLOT(cred->cr_label);
1702 obj = SLOT(socketlabel);
1705 * If there is an MLS label update for the socket, it may be
1706 * an update of effective.
1708 error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1713 * To relabel a socket, the old socket effective must be in the subject
1716 if (!mac_mls_effective_in_range(obj, subj))
1720 * If the MLS label is to be changed, authorize as appropriate.
1722 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1724 * To relabel a socket, the new socket effective must be in
1725 * the subject range.
1727 if (!mac_mls_effective_in_range(new, subj))
1731 * To change the MLS label on the socket to contain EQUAL,
1732 * the subject must have appropriate privilege.
1734 if (mac_mls_contains_equal(new)) {
1735 error = mac_mls_subject_privileged(subj);
1745 mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket,
1746 struct label *socketlabel)
1748 struct mac_mls *subj, *obj;
1750 if (!mac_mls_enabled)
1753 subj = SLOT(cred->cr_label);
1754 obj = SLOT(socketlabel);
1756 if (!mac_mls_dominate_effective(subj, obj))
1763 mac_mls_check_system_swapon(struct ucred *cred, struct vnode *vp,
1764 struct label *label)
1766 struct mac_mls *subj, *obj;
1768 if (!mac_mls_enabled)
1771 subj = SLOT(cred->cr_label);
1774 if (!mac_mls_dominate_effective(obj, subj) ||
1775 !mac_mls_dominate_effective(subj, obj))
1782 mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
1783 struct label *dlabel)
1785 struct mac_mls *subj, *obj;
1787 if (!mac_mls_enabled)
1790 subj = SLOT(cred->cr_label);
1793 if (!mac_mls_dominate_effective(subj, obj))
1800 mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
1801 struct label *dlabel)
1803 struct mac_mls *subj, *obj;
1805 if (!mac_mls_enabled)
1808 subj = SLOT(cred->cr_label);
1811 if (!mac_mls_dominate_effective(subj, obj))
1818 mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1819 struct label *dlabel, struct componentname *cnp, struct vattr *vap)
1821 struct mac_mls *subj, *obj;
1823 if (!mac_mls_enabled)
1826 subj = SLOT(cred->cr_label);
1829 if (!mac_mls_dominate_effective(obj, subj))
1836 mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
1837 struct label *dlabel, struct vnode *vp, struct label *label,
1838 struct componentname *cnp)
1840 struct mac_mls *subj, *obj;
1842 if (!mac_mls_enabled)
1845 subj = SLOT(cred->cr_label);
1848 if (!mac_mls_dominate_effective(obj, subj))
1853 if (!mac_mls_dominate_effective(obj, subj))
1860 mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1861 struct label *label, acl_type_t type)
1863 struct mac_mls *subj, *obj;
1865 if (!mac_mls_enabled)
1868 subj = SLOT(cred->cr_label);
1871 if (!mac_mls_dominate_effective(obj, subj))
1878 mac_mls_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
1879 struct label *label, int attrnamespace, const char *name)
1881 struct mac_mls *subj, *obj;
1883 if (!mac_mls_enabled)
1886 subj = SLOT(cred->cr_label);
1889 if (!mac_mls_dominate_effective(obj, subj))
1896 mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1897 struct label *label, struct image_params *imgp,
1898 struct label *execlabel)
1900 struct mac_mls *subj, *obj, *exec;
1903 if (execlabel != NULL) {
1905 * We currently don't permit labels to be changed at
1906 * exec-time as part of MLS, so disallow non-NULL
1907 * MLS label elements in the execlabel.
1909 exec = SLOT(execlabel);
1910 error = mls_atmostflags(exec, 0);
1915 if (!mac_mls_enabled)
1918 subj = SLOT(cred->cr_label);
1921 if (!mac_mls_dominate_effective(subj, obj))
1928 mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
1929 struct label *label, acl_type_t type)
1931 struct mac_mls *subj, *obj;
1933 if (!mac_mls_enabled)
1936 subj = SLOT(cred->cr_label);
1939 if (!mac_mls_dominate_effective(subj, obj))
1946 mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1947 struct label *label, int attrnamespace, const char *name, struct uio *uio)
1949 struct mac_mls *subj, *obj;
1951 if (!mac_mls_enabled)
1954 subj = SLOT(cred->cr_label);
1957 if (!mac_mls_dominate_effective(subj, obj))
1964 mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1965 struct label *dlabel, struct vnode *vp, struct label *label,
1966 struct componentname *cnp)
1968 struct mac_mls *subj, *obj;
1970 if (!mac_mls_enabled)
1973 subj = SLOT(cred->cr_label);
1976 if (!mac_mls_dominate_effective(obj, subj))
1980 if (!mac_mls_dominate_effective(obj, subj))
1987 mac_mls_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
1988 struct label *label, int attrnamespace)
1991 struct mac_mls *subj, *obj;
1993 if (!mac_mls_enabled)
1996 subj = SLOT(cred->cr_label);
1999 if (!mac_mls_dominate_effective(subj, obj))
2006 mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2007 struct label *dlabel, struct componentname *cnp)
2009 struct mac_mls *subj, *obj;
2011 if (!mac_mls_enabled)
2014 subj = SLOT(cred->cr_label);
2017 if (!mac_mls_dominate_effective(subj, obj))
2024 mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2025 struct label *label, int prot)
2027 struct mac_mls *subj, *obj;
2030 * Rely on the use of open()-time protections to handle
2031 * non-revocation cases.
2033 if (!mac_mls_enabled || !revocation_enabled)
2036 subj = SLOT(cred->cr_label);
2039 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2040 if (!mac_mls_dominate_effective(subj, obj))
2043 if (prot & VM_PROT_WRITE) {
2044 if (!mac_mls_dominate_effective(obj, subj))
2052 mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
2053 struct label *vnodelabel, int acc_mode)
2055 struct mac_mls *subj, *obj;
2057 if (!mac_mls_enabled)
2060 subj = SLOT(cred->cr_label);
2061 obj = SLOT(vnodelabel);
2063 /* XXX privilege override for admin? */
2064 if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2065 if (!mac_mls_dominate_effective(subj, obj))
2068 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2069 if (!mac_mls_dominate_effective(obj, subj))
2077 mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2078 struct vnode *vp, struct label *label)
2080 struct mac_mls *subj, *obj;
2082 if (!mac_mls_enabled || !revocation_enabled)
2085 subj = SLOT(active_cred->cr_label);
2088 if (!mac_mls_dominate_effective(subj, obj))
2095 mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2096 struct vnode *vp, struct label *label)
2098 struct mac_mls *subj, *obj;
2100 if (!mac_mls_enabled || !revocation_enabled)
2103 subj = SLOT(active_cred->cr_label);
2106 if (!mac_mls_dominate_effective(subj, obj))
2113 mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
2114 struct label *dlabel)
2116 struct mac_mls *subj, *obj;
2118 if (!mac_mls_enabled)
2121 subj = SLOT(cred->cr_label);
2124 if (!mac_mls_dominate_effective(subj, obj))
2131 mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
2132 struct label *vnodelabel)
2134 struct mac_mls *subj, *obj;
2136 if (!mac_mls_enabled)
2139 subj = SLOT(cred->cr_label);
2140 obj = SLOT(vnodelabel);
2142 if (!mac_mls_dominate_effective(subj, obj))
2149 mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2150 struct label *vnodelabel, struct label *newlabel)
2152 struct mac_mls *old, *new, *subj;
2155 old = SLOT(vnodelabel);
2156 new = SLOT(newlabel);
2157 subj = SLOT(cred->cr_label);
2160 * If there is an MLS label update for the vnode, it must be a
2163 error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2168 * To perform a relabel of the vnode (MLS label or not), MLS must
2169 * authorize the relabel.
2171 if (!mac_mls_effective_in_range(old, subj))
2175 * If the MLS label is to be changed, authorize as appropriate.
2177 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2179 * To change the MLS label on a vnode, the new vnode label
2180 * must be in the subject range.
2182 if (!mac_mls_effective_in_range(new, subj))
2186 * To change the MLS label on the vnode to be EQUAL,
2187 * the subject must have appropriate privilege.
2189 if (mac_mls_contains_equal(new)) {
2190 error = mac_mls_subject_privileged(subj);
2201 mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2202 struct label *dlabel, struct vnode *vp, struct label *label,
2203 struct componentname *cnp)
2205 struct mac_mls *subj, *obj;
2207 if (!mac_mls_enabled)
2210 subj = SLOT(cred->cr_label);
2213 if (!mac_mls_dominate_effective(obj, subj))
2218 if (!mac_mls_dominate_effective(obj, subj))
2225 mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2226 struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2227 struct componentname *cnp)
2229 struct mac_mls *subj, *obj;
2231 if (!mac_mls_enabled)
2234 subj = SLOT(cred->cr_label);
2237 if (!mac_mls_dominate_effective(obj, subj))
2243 if (!mac_mls_dominate_effective(obj, subj))
2251 mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2252 struct label *label)
2254 struct mac_mls *subj, *obj;
2256 if (!mac_mls_enabled)
2259 subj = SLOT(cred->cr_label);
2262 if (!mac_mls_dominate_effective(obj, subj))
2269 mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2270 struct label *label, acl_type_t type, struct acl *acl)
2272 struct mac_mls *subj, *obj;
2274 if (!mac_mls_enabled)
2277 subj = SLOT(cred->cr_label);
2280 if (!mac_mls_dominate_effective(obj, subj))
2287 mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2288 struct label *vnodelabel, int attrnamespace, const char *name,
2291 struct mac_mls *subj, *obj;
2293 if (!mac_mls_enabled)
2296 subj = SLOT(cred->cr_label);
2297 obj = SLOT(vnodelabel);
2299 if (!mac_mls_dominate_effective(obj, subj))
2302 /* XXX: protect the MAC EA in a special way? */
2308 mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2309 struct label *vnodelabel, u_long flags)
2311 struct mac_mls *subj, *obj;
2313 if (!mac_mls_enabled)
2316 subj = SLOT(cred->cr_label);
2317 obj = SLOT(vnodelabel);
2319 if (!mac_mls_dominate_effective(obj, subj))
2326 mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2327 struct label *vnodelabel, mode_t mode)
2329 struct mac_mls *subj, *obj;
2331 if (!mac_mls_enabled)
2334 subj = SLOT(cred->cr_label);
2335 obj = SLOT(vnodelabel);
2337 if (!mac_mls_dominate_effective(obj, subj))
2344 mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2345 struct label *vnodelabel, uid_t uid, gid_t gid)
2347 struct mac_mls *subj, *obj;
2349 if (!mac_mls_enabled)
2352 subj = SLOT(cred->cr_label);
2353 obj = SLOT(vnodelabel);
2355 if (!mac_mls_dominate_effective(obj, subj))
2362 mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2363 struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2365 struct mac_mls *subj, *obj;
2367 if (!mac_mls_enabled)
2370 subj = SLOT(cred->cr_label);
2371 obj = SLOT(vnodelabel);
2373 if (!mac_mls_dominate_effective(obj, subj))
2380 mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2381 struct vnode *vp, struct label *vnodelabel)
2383 struct mac_mls *subj, *obj;
2385 if (!mac_mls_enabled)
2388 subj = SLOT(active_cred->cr_label);
2389 obj = SLOT(vnodelabel);
2391 if (!mac_mls_dominate_effective(subj, obj))
2398 mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2399 struct vnode *vp, struct label *label)
2401 struct mac_mls *subj, *obj;
2403 if (!mac_mls_enabled || !revocation_enabled)
2406 subj = SLOT(active_cred->cr_label);
2409 if (!mac_mls_dominate_effective(obj, subj))
2415 static struct mac_policy_ops mac_mls_ops =
2417 .mpo_init = mac_mls_init,
2418 .mpo_init_bpfdesc_label = mac_mls_init_label,
2419 .mpo_init_cred_label = mac_mls_init_label,
2420 .mpo_init_devfsdirent_label = mac_mls_init_label,
2421 .mpo_init_ifnet_label = mac_mls_init_label,
2422 .mpo_init_inpcb_label = mac_mls_init_label_waitcheck,
2423 .mpo_init_ipq_label = mac_mls_init_label_waitcheck,
2424 .mpo_init_mbuf_label = mac_mls_init_label_waitcheck,
2425 .mpo_init_mount_label = mac_mls_init_label,
2426 .mpo_init_mount_fs_label = mac_mls_init_label,
2427 .mpo_init_pipe_label = mac_mls_init_label,
2428 .mpo_init_socket_label = mac_mls_init_label_waitcheck,
2429 .mpo_init_socket_peer_label = mac_mls_init_label_waitcheck,
2430 .mpo_init_vnode_label = mac_mls_init_label,
2431 .mpo_destroy_bpfdesc_label = mac_mls_destroy_label,
2432 .mpo_destroy_cred_label = mac_mls_destroy_label,
2433 .mpo_destroy_devfsdirent_label = mac_mls_destroy_label,
2434 .mpo_destroy_ifnet_label = mac_mls_destroy_label,
2435 .mpo_destroy_inpcb_label = mac_mls_destroy_label,
2436 .mpo_destroy_ipq_label = mac_mls_destroy_label,
2437 .mpo_destroy_mbuf_label = mac_mls_destroy_label,
2438 .mpo_destroy_mount_label = mac_mls_destroy_label,
2439 .mpo_destroy_mount_fs_label = mac_mls_destroy_label,
2440 .mpo_destroy_pipe_label = mac_mls_destroy_label,
2441 .mpo_destroy_socket_label = mac_mls_destroy_label,
2442 .mpo_destroy_socket_peer_label = mac_mls_destroy_label,
2443 .mpo_destroy_vnode_label = mac_mls_destroy_label,
2444 .mpo_copy_cred_label = mac_mls_copy_label,
2445 .mpo_copy_ifnet_label = mac_mls_copy_label,
2446 .mpo_copy_mbuf_label = mac_mls_copy_label,
2447 .mpo_copy_pipe_label = mac_mls_copy_label,
2448 .mpo_copy_socket_label = mac_mls_copy_label,
2449 .mpo_copy_vnode_label = mac_mls_copy_label,
2450 .mpo_externalize_cred_label = mac_mls_externalize_label,
2451 .mpo_externalize_ifnet_label = mac_mls_externalize_label,
2452 .mpo_externalize_pipe_label = mac_mls_externalize_label,
2453 .mpo_externalize_socket_label = mac_mls_externalize_label,
2454 .mpo_externalize_socket_peer_label = mac_mls_externalize_label,
2455 .mpo_externalize_vnode_label = mac_mls_externalize_label,
2456 .mpo_internalize_cred_label = mac_mls_internalize_label,
2457 .mpo_internalize_ifnet_label = mac_mls_internalize_label,
2458 .mpo_internalize_pipe_label = mac_mls_internalize_label,
2459 .mpo_internalize_socket_label = mac_mls_internalize_label,
2460 .mpo_internalize_vnode_label = mac_mls_internalize_label,
2461 .mpo_create_devfs_device = mac_mls_create_devfs_device,
2462 .mpo_create_devfs_directory = mac_mls_create_devfs_directory,
2463 .mpo_create_devfs_symlink = mac_mls_create_devfs_symlink,
2464 .mpo_create_mount = mac_mls_create_mount,
2465 .mpo_create_root_mount = mac_mls_create_root_mount,
2466 .mpo_relabel_vnode = mac_mls_relabel_vnode,
2467 .mpo_update_devfsdirent = mac_mls_update_devfsdirent,
2468 .mpo_associate_vnode_devfs = mac_mls_associate_vnode_devfs,
2469 .mpo_associate_vnode_extattr = mac_mls_associate_vnode_extattr,
2470 .mpo_associate_vnode_singlelabel = mac_mls_associate_vnode_singlelabel,
2471 .mpo_create_vnode_extattr = mac_mls_create_vnode_extattr,
2472 .mpo_setlabel_vnode_extattr = mac_mls_setlabel_vnode_extattr,
2473 .mpo_create_mbuf_from_socket = mac_mls_create_mbuf_from_socket,
2474 .mpo_create_pipe = mac_mls_create_pipe,
2475 .mpo_create_socket = mac_mls_create_socket,
2476 .mpo_create_socket_from_socket = mac_mls_create_socket_from_socket,
2477 .mpo_relabel_pipe = mac_mls_relabel_pipe,
2478 .mpo_relabel_socket = mac_mls_relabel_socket,
2479 .mpo_set_socket_peer_from_mbuf = mac_mls_set_socket_peer_from_mbuf,
2480 .mpo_set_socket_peer_from_socket = mac_mls_set_socket_peer_from_socket,
2481 .mpo_create_bpfdesc = mac_mls_create_bpfdesc,
2482 .mpo_create_datagram_from_ipq = mac_mls_create_datagram_from_ipq,
2483 .mpo_create_fragment = mac_mls_create_fragment,
2484 .mpo_create_ifnet = mac_mls_create_ifnet,
2485 .mpo_create_inpcb_from_socket = mac_mls_create_inpcb_from_socket,
2486 .mpo_create_ipq = mac_mls_create_ipq,
2487 .mpo_create_mbuf_from_inpcb = mac_mls_create_mbuf_from_inpcb,
2488 .mpo_create_mbuf_from_mbuf = mac_mls_create_mbuf_from_mbuf,
2489 .mpo_create_mbuf_linklayer = mac_mls_create_mbuf_linklayer,
2490 .mpo_create_mbuf_from_bpfdesc = mac_mls_create_mbuf_from_bpfdesc,
2491 .mpo_create_mbuf_from_ifnet = mac_mls_create_mbuf_from_ifnet,
2492 .mpo_create_mbuf_multicast_encap = mac_mls_create_mbuf_multicast_encap,
2493 .mpo_create_mbuf_netlayer = mac_mls_create_mbuf_netlayer,
2494 .mpo_fragment_match = mac_mls_fragment_match,
2495 .mpo_relabel_ifnet = mac_mls_relabel_ifnet,
2496 .mpo_update_ipq = mac_mls_update_ipq,
2497 .mpo_inpcb_sosetlabel = mac_mls_inpcb_sosetlabel,
2498 .mpo_create_proc0 = mac_mls_create_proc0,
2499 .mpo_create_proc1 = mac_mls_create_proc1,
2500 .mpo_relabel_cred = mac_mls_relabel_cred,
2501 .mpo_check_bpfdesc_receive = mac_mls_check_bpfdesc_receive,
2502 .mpo_check_cred_relabel = mac_mls_check_cred_relabel,
2503 .mpo_check_cred_visible = mac_mls_check_cred_visible,
2504 .mpo_check_ifnet_relabel = mac_mls_check_ifnet_relabel,
2505 .mpo_check_ifnet_transmit = mac_mls_check_ifnet_transmit,
2506 .mpo_check_inpcb_deliver = mac_mls_check_inpcb_deliver,
2507 .mpo_check_mount_stat = mac_mls_check_mount_stat,
2508 .mpo_check_pipe_ioctl = mac_mls_check_pipe_ioctl,
2509 .mpo_check_pipe_poll = mac_mls_check_pipe_poll,
2510 .mpo_check_pipe_read = mac_mls_check_pipe_read,
2511 .mpo_check_pipe_relabel = mac_mls_check_pipe_relabel,
2512 .mpo_check_pipe_stat = mac_mls_check_pipe_stat,
2513 .mpo_check_pipe_write = mac_mls_check_pipe_write,
2514 .mpo_check_proc_debug = mac_mls_check_proc_debug,
2515 .mpo_check_proc_sched = mac_mls_check_proc_sched,
2516 .mpo_check_proc_signal = mac_mls_check_proc_signal,
2517 .mpo_check_socket_deliver = mac_mls_check_socket_deliver,
2518 .mpo_check_socket_relabel = mac_mls_check_socket_relabel,
2519 .mpo_check_socket_visible = mac_mls_check_socket_visible,
2520 .mpo_check_system_swapon = mac_mls_check_system_swapon,
2521 .mpo_check_vnode_access = mac_mls_check_vnode_open,
2522 .mpo_check_vnode_chdir = mac_mls_check_vnode_chdir,
2523 .mpo_check_vnode_chroot = mac_mls_check_vnode_chroot,
2524 .mpo_check_vnode_create = mac_mls_check_vnode_create,
2525 .mpo_check_vnode_delete = mac_mls_check_vnode_delete,
2526 .mpo_check_vnode_deleteacl = mac_mls_check_vnode_deleteacl,
2527 .mpo_check_vnode_deleteextattr = mac_mls_check_vnode_deleteextattr,
2528 .mpo_check_vnode_exec = mac_mls_check_vnode_exec,
2529 .mpo_check_vnode_getacl = mac_mls_check_vnode_getacl,
2530 .mpo_check_vnode_getextattr = mac_mls_check_vnode_getextattr,
2531 .mpo_check_vnode_link = mac_mls_check_vnode_link,
2532 .mpo_check_vnode_listextattr = mac_mls_check_vnode_listextattr,
2533 .mpo_check_vnode_lookup = mac_mls_check_vnode_lookup,
2534 .mpo_check_vnode_mmap = mac_mls_check_vnode_mmap,
2535 .mpo_check_vnode_mprotect = mac_mls_check_vnode_mmap,
2536 .mpo_check_vnode_open = mac_mls_check_vnode_open,
2537 .mpo_check_vnode_poll = mac_mls_check_vnode_poll,
2538 .mpo_check_vnode_read = mac_mls_check_vnode_read,
2539 .mpo_check_vnode_readdir = mac_mls_check_vnode_readdir,
2540 .mpo_check_vnode_readlink = mac_mls_check_vnode_readlink,
2541 .mpo_check_vnode_relabel = mac_mls_check_vnode_relabel,
2542 .mpo_check_vnode_rename_from = mac_mls_check_vnode_rename_from,
2543 .mpo_check_vnode_rename_to = mac_mls_check_vnode_rename_to,
2544 .mpo_check_vnode_revoke = mac_mls_check_vnode_revoke,
2545 .mpo_check_vnode_setacl = mac_mls_check_vnode_setacl,
2546 .mpo_check_vnode_setextattr = mac_mls_check_vnode_setextattr,
2547 .mpo_check_vnode_setflags = mac_mls_check_vnode_setflags,
2548 .mpo_check_vnode_setmode = mac_mls_check_vnode_setmode,
2549 .mpo_check_vnode_setowner = mac_mls_check_vnode_setowner,
2550 .mpo_check_vnode_setutimes = mac_mls_check_vnode_setutimes,
2551 .mpo_check_vnode_stat = mac_mls_check_vnode_stat,
2552 .mpo_check_vnode_write = mac_mls_check_vnode_write,
2555 MAC_POLICY_SET(&mac_mls_ops, mac_mls, "TrustedBSD MAC/MLS",
2556 MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_mls_slot);