mac_biba.c revision 112675
120253Sjoerg/*- 220302Sjoerg * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 320302Sjoerg * Copyright (c) 2001, 2002 Networks Associates Technology, Inc. 420253Sjoerg * All rights reserved. 520253Sjoerg * 620253Sjoerg * This software was developed by Robert Watson for the TrustedBSD Project. 720253Sjoerg * 820253Sjoerg * This software was developed for the FreeBSD Project in part by Network 920302Sjoerg * Associates Laboratories, the Security Research Division of Network 1020253Sjoerg * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 1120253Sjoerg * as part of the DARPA CHATS research program. 1220253Sjoerg * 1320253Sjoerg * Redistribution and use in source and binary forms, with or without 1420302Sjoerg * modification, are permitted provided that the following conditions 1520253Sjoerg * are met: 1620253Sjoerg * 1. Redistributions of source code must retain the above copyright 1720302Sjoerg * notice, this list of conditions and the following disclaimer. 1820253Sjoerg * 2. Redistributions in binary form must reproduce the above copyright 1920253Sjoerg * notice, this list of conditions and the following disclaimer in the 2020253Sjoerg * documentation and/or other materials provided with the distribution. 2120253Sjoerg * 2220253Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2320253Sjoerg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2420253Sjoerg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2544229Sdavidn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2620253Sjoerg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2720253Sjoerg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2830259Scharnier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2930259Scharnier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3050479Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3130259Scharnier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3230259Scharnier * SUCH DAMAGE. 3330259Scharnier * 3430259Scharnier * $FreeBSD: head/sys/security/mac_biba/mac_biba.c 112675 2003-03-26 15:12:03Z rwatson $ 3520253Sjoerg */ 3620253Sjoerg 3720253Sjoerg/* 3830259Scharnier * Developed by the TrustedBSD Project. 3920253Sjoerg * Biba fixed label mandatory integrity policy. 4020555Sdavidn */ 4120555Sdavidn 4220555Sdavidn#include <sys/types.h> 4330259Scharnier#include <sys/param.h> 4464918Sgreen#include <sys/acl.h> 4520253Sjoerg#include <sys/conf.h> 4620253Sjoerg#include <sys/extattr.h> 4720253Sjoerg#include <sys/kernel.h> 4823318Sache#include <sys/mac.h> 4922394Sdavidn#include <sys/malloc.h> 5052512Sdavidn#include <sys/mount.h> 5124214Sache#include <sys/proc.h> 5244386Sdavidn#include <sys/systm.h> 5320253Sjoerg#include <sys/sysproto.h> 5420253Sjoerg#include <sys/sysent.h> 5520253Sjoerg#include <sys/systm.h> 5620253Sjoerg#include <sys/vnode.h> 5720253Sjoerg#include <sys/file.h> 5820253Sjoerg#include <sys/socket.h> 5920253Sjoerg#include <sys/socketvar.h> 6020253Sjoerg#include <sys/pipe.h> 6120253Sjoerg#include <sys/sysctl.h> 6285145Sache 6320253Sjoerg#include <fs/devfs/devfs.h> 6420253Sjoerg 6520253Sjoerg#include <net/bpfdesc.h> 6620253Sjoerg#include <net/if.h> 6720253Sjoerg#include <net/if_types.h> 6820253Sjoerg#include <net/if_var.h> 6920253Sjoerg 7020253Sjoerg#include <netinet/in.h> 7120253Sjoerg#include <netinet/ip_var.h> 7220253Sjoerg 7320253Sjoerg#include <vm/vm.h> 7420253Sjoerg 7520253Sjoerg#include <sys/mac_policy.h> 7620253Sjoerg 7720253Sjoerg#include <security/mac_biba/mac_biba.h> 7820253Sjoerg 7920253SjoergSYSCTL_DECL(_security_mac); 8020253Sjoerg 81124382SiedowseSYSCTL_NODE(_security_mac, OID_AUTO, biba, CTLFLAG_RW, 0, 8220253Sjoerg "TrustedBSD mac_biba policy controls"); 8320253Sjoerg 8420253Sjoergstatic int mac_biba_label_size = sizeof(struct mac_biba); 8520253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, label_size, CTLFLAG_RD, 8620253Sjoerg &mac_biba_label_size, 0, "Size of struct mac_biba"); 8720253Sjoerg 8820253Sjoergstatic int mac_biba_enabled = 1; 8920253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, enabled, CTLFLAG_RW, 9020253Sjoerg &mac_biba_enabled, 0, "Enforce MAC/Biba policy"); 9120253SjoergTUNABLE_INT("security.mac.biba.enabled", &mac_biba_enabled); 9220253Sjoerg 9320253Sjoergstatic int destroyed_not_inited; 9420253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, destroyed_not_inited, CTLFLAG_RD, 9520253Sjoerg &destroyed_not_inited, 0, "Count of labels destroyed but not inited"); 9620253Sjoerg 9720253Sjoergstatic int trust_all_interfaces = 0; 9820253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, trust_all_interfaces, CTLFLAG_RD, 9952527Sdavidn &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/Biba"); 10020253SjoergTUNABLE_INT("security.mac.biba.trust_all_interfaces", &trust_all_interfaces); 10152512Sdavidn 10220253Sjoergstatic char trusted_interfaces[128]; 10320253SjoergSYSCTL_STRING(_security_mac_biba, OID_AUTO, trusted_interfaces, CTLFLAG_RD, 10420253Sjoerg trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/Biba"); 10520253SjoergTUNABLE_STR("security.mac.biba.trusted_interfaces", trusted_interfaces, 10620253Sjoerg sizeof(trusted_interfaces)); 10720253Sjoerg 10820747Sdavidnstatic int max_compartments = MAC_BIBA_MAX_COMPARTMENTS; 10982868SddSYSCTL_INT(_security_mac_biba, OID_AUTO, max_compartments, CTLFLAG_RD, 110167919Sle &max_compartments, 0, "Maximum supported compartments"); 111167919Sle 11220253Sjoergstatic int ptys_equal = 0; 11320253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, ptys_equal, CTLFLAG_RW, 11420253Sjoerg &ptys_equal, 0, "Label pty devices as biba/equal on create"); 11520253SjoergTUNABLE_INT("security.mac.biba.ptys_equal", &ptys_equal); 11620253Sjoerg 11720253Sjoergstatic int revocation_enabled = 0; 11820253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, revocation_enabled, CTLFLAG_RW, 11920253Sjoerg &revocation_enabled, 0, "Revoke access to objects on relabel"); 12020253SjoergTUNABLE_INT("security.mac.biba.revocation_enabled", &revocation_enabled); 12120253Sjoerg 12256000Sdavidnstatic int mac_biba_slot; 12320253Sjoerg#define SLOT(l) ((struct mac_biba *)LABEL_TO_SLOT((l), mac_biba_slot).l_ptr) 12420253Sjoerg 12556000SdavidnMALLOC_DEFINE(M_MACBIBA, "biba label", "MAC/Biba labels"); 12656000Sdavidn 12756000Sdavidnstatic __inline int 12820253Sjoergbiba_bit_set_empty(u_char *set) { 12920253Sjoerg int i; 13052512Sdavidn 13120253Sjoerg for (i = 0; i < MAC_BIBA_MAX_COMPARTMENTS >> 3; i++) 13220267Sjoerg if (set[i] != 0) 13320267Sjoerg return (0); 13420267Sjoerg return (1); 13520267Sjoerg} 13620267Sjoerg 13720267Sjoergstatic struct mac_biba * 13820267Sjoergbiba_alloc(int flag) 13920267Sjoerg{ 14020267Sjoerg struct mac_biba *mac_biba; 14120267Sjoerg 14220267Sjoerg mac_biba = malloc(sizeof(struct mac_biba), M_MACBIBA, M_ZERO | flag); 14320267Sjoerg 14420267Sjoerg return (mac_biba); 14520267Sjoerg} 14620253Sjoerg 14720253Sjoergstatic void 14820253Sjoergbiba_free(struct mac_biba *mac_biba) 14920253Sjoerg{ 15020267Sjoerg 15120253Sjoerg if (mac_biba != NULL) 15221052Sdavidn free(mac_biba, M_MACBIBA); 153167919Sle else 154167919Sle atomic_add_int(&destroyed_not_inited, 1); 155167919Sle} 156167919Sle 157167919Slestatic int 158219408Sjkimbiba_atmostflags(struct mac_biba *mac_biba, int flags) 159167919Sle{ 160168044Sle 161167919Sle if ((mac_biba->mb_flags & flags) != mac_biba->mb_flags) 16221052Sdavidn return (EINVAL); 16321052Sdavidn return (0); 16421052Sdavidn} 16521052Sdavidn 166224535Sdelphijstatic int 16721052Sdavidnmac_biba_dominate_element(struct mac_biba_element *a, 16821052Sdavidn struct mac_biba_element *b) 16921052Sdavidn{ 17021052Sdavidn int bit; 17121052Sdavidn 17221052Sdavidn switch (a->mbe_type) { 17330259Scharnier case MAC_BIBA_TYPE_EQUAL: 17421052Sdavidn case MAC_BIBA_TYPE_HIGH: 17521052Sdavidn return (1); 17621052Sdavidn 17721052Sdavidn case MAC_BIBA_TYPE_LOW: 17821242Sdavidn switch (b->mbe_type) { 17921242Sdavidn case MAC_BIBA_TYPE_GRADE: 18021242Sdavidn case MAC_BIBA_TYPE_HIGH: 18121242Sdavidn return (0); 18221242Sdavidn 18321242Sdavidn case MAC_BIBA_TYPE_EQUAL: 18421242Sdavidn case MAC_BIBA_TYPE_LOW: 18521242Sdavidn return (1); 18621242Sdavidn 187219408Sjkim default: 18821242Sdavidn panic("mac_biba_dominate_element: b->mbe_type invalid"); 189148584Spjd } 190148584Spjd 191148584Spjd case MAC_BIBA_TYPE_GRADE: 192148584Spjd switch (b->mbe_type) { 193148584Spjd case MAC_BIBA_TYPE_EQUAL: 19421242Sdavidn case MAC_BIBA_TYPE_LOW: 19521242Sdavidn return (1); 19621242Sdavidn 197130633Srobert case MAC_BIBA_TYPE_HIGH: 198130633Srobert return (0); 19921242Sdavidn 20021242Sdavidn case MAC_BIBA_TYPE_GRADE: 20121242Sdavidn for (bit = 1; bit <= MAC_BIBA_MAX_COMPARTMENTS; bit++) 20221242Sdavidn if (!MAC_BIBA_BIT_TEST(bit, 203219408Sjkim a->mbe_compartments) && 20421242Sdavidn MAC_BIBA_BIT_TEST(bit, b->mbe_compartments)) 20521242Sdavidn return (0); 20621242Sdavidn return (a->mbe_grade >= b->mbe_grade); 20730259Scharnier 20821242Sdavidn default: 20921242Sdavidn panic("mac_biba_dominate_element: b->mbe_type invalid"); 21021052Sdavidn } 21121242Sdavidn 212219408Sjkim default: 21330259Scharnier panic("mac_biba_dominate_element: a->mbe_type invalid"); 21421052Sdavidn } 21521052Sdavidn 21621052Sdavidn return (0); 21721052Sdavidn} 21830259Scharnier 21921052Sdavidnstatic int 22021052Sdavidnmac_biba_subject_dominate_high(struct mac_biba *mac_biba) 22120253Sjoerg{ 22220253Sjoerg struct mac_biba_element *element; 22320253Sjoerg 22421330Sdavidn KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0, 22521330Sdavidn ("mac_biba_single_in_range: mac_biba not single")); 22621330Sdavidn element = &mac_biba->mb_single; 22720253Sjoerg 22820253Sjoerg return (element->mbe_type == MAC_BIBA_TYPE_EQUAL || 22920253Sjoerg element->mbe_type == MAC_BIBA_TYPE_HIGH); 23020253Sjoerg} 23163596Sdavidn 23263596Sdavidnstatic int 23363596Sdavidnmac_biba_range_in_range(struct mac_biba *rangea, struct mac_biba *rangeb) 23463596Sdavidn{ 23563596Sdavidn 23663596Sdavidn return (mac_biba_dominate_element(&rangeb->mb_rangehigh, 23763596Sdavidn &rangea->mb_rangehigh) && 23863596Sdavidn mac_biba_dominate_element(&rangea->mb_rangelow, 23920253Sjoerg &rangeb->mb_rangelow)); 24020253Sjoerg} 24120253Sjoerg 24220679Sdavidnstatic int 24320253Sjoergmac_biba_single_in_range(struct mac_biba *single, struct mac_biba *range) 24420253Sjoerg{ 24552527Sdavidn 24620253Sjoerg KASSERT((single->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0, 24720747Sdavidn ("mac_biba_single_in_range: a not single")); 24844229Sdavidn KASSERT((range->mb_flags & MAC_BIBA_FLAG_RANGE) != 0, 24961957Sache ("mac_biba_single_in_range: b not range")); 25030259Scharnier 25120253Sjoerg return (mac_biba_dominate_element(&range->mb_rangehigh, 25220747Sdavidn &single->mb_single) && 25320747Sdavidn mac_biba_dominate_element(&single->mb_single, 25420253Sjoerg &range->mb_rangelow)); 25520747Sdavidn 25620253Sjoerg return (1); 25720253Sjoerg} 25852527Sdavidn 25920253Sjoergstatic int 26026088Sdavidnmac_biba_dominate_single(struct mac_biba *a, struct mac_biba *b) 26130259Scharnier{ 26220253Sjoerg KASSERT((a->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0, 26352527Sdavidn ("mac_biba_dominate_single: a not single")); 26420253Sjoerg KASSERT((b->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0, 26520253Sjoerg ("mac_biba_dominate_single: b not single")); 26620253Sjoerg 26763600Sdavidn return (mac_biba_dominate_element(&a->mb_single, &b->mb_single)); 26863600Sdavidn} 26920253Sjoerg 27020253Sjoergstatic int 27130259Scharniermac_biba_equal_element(struct mac_biba_element *a, struct mac_biba_element *b) 27220253Sjoerg{ 27320253Sjoerg 27420253Sjoerg if (a->mbe_type == MAC_BIBA_TYPE_EQUAL || 27520253Sjoerg b->mbe_type == MAC_BIBA_TYPE_EQUAL) 27620253Sjoerg return (1); 27720253Sjoerg 27820253Sjoerg return (a->mbe_type == b->mbe_type && a->mbe_grade == b->mbe_grade); 27920253Sjoerg} 28020253Sjoerg 28120253Sjoergstatic int 28220253Sjoergmac_biba_equal_single(struct mac_biba *a, struct mac_biba *b) 28320253Sjoerg{ 28420253Sjoerg 28520253Sjoerg KASSERT((a->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0, 28620253Sjoerg ("mac_biba_equal_single: a not single")); 28720267Sjoerg KASSERT((b->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0, 28830259Scharnier ("mac_biba_equal_single: b not single")); 28920267Sjoerg 29020253Sjoerg return (mac_biba_equal_element(&a->mb_single, &b->mb_single)); 29152527Sdavidn} 29220253Sjoerg 29320267Sjoergstatic int 29444386Sdavidnmac_biba_contains_equal(struct mac_biba *mac_biba) 29520253Sjoerg{ 29644229Sdavidn 29744229Sdavidn if (mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) 29844386Sdavidn if (mac_biba->mb_single.mbe_type == MAC_BIBA_TYPE_EQUAL) 29944229Sdavidn return (1); 30020267Sjoerg 30120253Sjoerg if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) { 30252527Sdavidn if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL) 30320253Sjoerg return (1); 30444229Sdavidn if (mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL) 30520253Sjoerg return (1); 30620253Sjoerg } 30720253Sjoerg 30820253Sjoerg return (0); 30930259Scharnier} 31020253Sjoerg 31120253Sjoergstatic int 31220253Sjoergmac_biba_subject_privileged(struct mac_biba *mac_biba) 31320253Sjoerg{ 31420253Sjoerg 31520253Sjoerg KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAGS_BOTH) == 31643780Sdes MAC_BIBA_FLAGS_BOTH, 31743780Sdes ("mac_biba_subject_privileged: subject doesn't have both labels")); 318242916Sbapt 31920253Sjoerg /* If the single is EQUAL, it's ok. */ 32020253Sjoerg if (mac_biba->mb_single.mbe_type == MAC_BIBA_TYPE_EQUAL) 32120253Sjoerg return (0); 32220253Sjoerg 32352527Sdavidn /* If either range endpoint is EQUAL, it's ok. */ 32420253Sjoerg if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL || 32520253Sjoerg mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL) 32620253Sjoerg return (0); 32752512Sdavidn 32852512Sdavidn /* If the range is low-high, it's ok. */ 32952527Sdavidn if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_LOW && 33020253Sjoerg mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_HIGH) 33144229Sdavidn return (0); 33220253Sjoerg 33320253Sjoerg /* It's not ok. */ 33420253Sjoerg return (EPERM); 33520253Sjoerg} 33620253Sjoerg 33744386Sdavidnstatic int 33844386Sdavidnmac_biba_high_single(struct mac_biba *mac_biba) 33944386Sdavidn{ 34020253Sjoerg 34120253Sjoerg KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0, 34230259Scharnier ("mac_biba_equal_single: mac_biba not single")); 34330259Scharnier 34420253Sjoerg return (mac_biba->mb_single.mbe_type == MAC_BIBA_TYPE_HIGH); 34552527Sdavidn} 34620253Sjoerg 34720253Sjoergstatic int 34820253Sjoergmac_biba_valid(struct mac_biba *mac_biba) 34920253Sjoerg{ 35052512Sdavidn 35152512Sdavidn if (mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) { 35252512Sdavidn switch (mac_biba->mb_single.mbe_type) { 35352512Sdavidn case MAC_BIBA_TYPE_GRADE: 35452512Sdavidn break; 35552512Sdavidn 35652512Sdavidn case MAC_BIBA_TYPE_EQUAL: 35752512Sdavidn case MAC_BIBA_TYPE_HIGH: 35852512Sdavidn case MAC_BIBA_TYPE_LOW: 35952512Sdavidn if (mac_biba->mb_single.mbe_grade != 0 || 36052512Sdavidn !MAC_BIBA_BIT_SET_EMPTY( 36152512Sdavidn mac_biba->mb_single.mbe_compartments)) 36252512Sdavidn return (EINVAL); 36352512Sdavidn break; 36452512Sdavidn 36552512Sdavidn default: 36652512Sdavidn return (EINVAL); 36752512Sdavidn } 36852527Sdavidn } else { 36952512Sdavidn if (mac_biba->mb_single.mbe_type != MAC_BIBA_TYPE_UNDEF) 37052512Sdavidn return (EINVAL); 37152512Sdavidn } 37252512Sdavidn 37352527Sdavidn if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) { 37452527Sdavidn switch (mac_biba->mb_rangelow.mbe_type) { 37552527Sdavidn case MAC_BIBA_TYPE_GRADE: 37652527Sdavidn break; 37752527Sdavidn 37820253Sjoerg case MAC_BIBA_TYPE_EQUAL: 37920253Sjoerg case MAC_BIBA_TYPE_HIGH: 38020253Sjoerg case MAC_BIBA_TYPE_LOW: 38120253Sjoerg if (mac_biba->mb_rangelow.mbe_grade != 0 || 38220253Sjoerg !MAC_BIBA_BIT_SET_EMPTY( 38330259Scharnier mac_biba->mb_rangelow.mbe_compartments)) 38420253Sjoerg return (EINVAL); 38544229Sdavidn break; 38644229Sdavidn 38785145Sache default: 38844229Sdavidn return (EINVAL); 38920747Sdavidn } 39085145Sache 39120747Sdavidn switch (mac_biba->mb_rangehigh.mbe_type) { 39244229Sdavidn case MAC_BIBA_TYPE_GRADE: 39344229Sdavidn break; 39444229Sdavidn 39544229Sdavidn case MAC_BIBA_TYPE_EQUAL: 39644229Sdavidn case MAC_BIBA_TYPE_HIGH: 39744229Sdavidn case MAC_BIBA_TYPE_LOW: 39844229Sdavidn if (mac_biba->mb_rangehigh.mbe_grade != 0 || 39944229Sdavidn !MAC_BIBA_BIT_SET_EMPTY( 40020253Sjoerg mac_biba->mb_rangehigh.mbe_compartments)) 40120253Sjoerg return (EINVAL); 40220253Sjoerg break; 40320253Sjoerg 40420253Sjoerg default: 40520253Sjoerg return (EINVAL); 406130633Srobert } 40720253Sjoerg if (!mac_biba_dominate_element(&mac_biba->mb_rangehigh, 40852502Sdavidn &mac_biba->mb_rangelow)) 40952502Sdavidn return (EINVAL); 41052502Sdavidn } else { 41152502Sdavidn if (mac_biba->mb_rangelow.mbe_type != MAC_BIBA_TYPE_UNDEF || 41256000Sdavidn mac_biba->mb_rangehigh.mbe_type != MAC_BIBA_TYPE_UNDEF) 41352502Sdavidn return (EINVAL); 41452502Sdavidn } 41521330Sdavidn 41652502Sdavidn return (0); 41752502Sdavidn} 41852502Sdavidn 41952502Sdavidnstatic void 42052502Sdavidnmac_biba_set_range(struct mac_biba *mac_biba, u_short typelow, 42156000Sdavidn u_short gradelow, u_char *compartmentslow, u_short typehigh, 42252502Sdavidn u_short gradehigh, u_char *compartmentshigh) 42352502Sdavidn{ 42452502Sdavidn 42520253Sjoerg mac_biba->mb_rangelow.mbe_type = typelow; 42620253Sjoerg mac_biba->mb_rangelow.mbe_grade = gradelow; 42720253Sjoerg if (compartmentslow != NULL) 42820253Sjoerg memcpy(mac_biba->mb_rangelow.mbe_compartments, 42944229Sdavidn compartmentslow, 43044229Sdavidn sizeof(mac_biba->mb_rangelow.mbe_compartments)); 43144229Sdavidn mac_biba->mb_rangehigh.mbe_type = typehigh; 43244229Sdavidn mac_biba->mb_rangehigh.mbe_grade = gradehigh; 43344229Sdavidn if (compartmentshigh != NULL) 43420253Sjoerg memcpy(mac_biba->mb_rangehigh.mbe_compartments, 43544229Sdavidn compartmentshigh, 43644229Sdavidn sizeof(mac_biba->mb_rangehigh.mbe_compartments)); 43744229Sdavidn mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE; 43844229Sdavidn} 43944229Sdavidn 44020253Sjoergstatic void 44144229Sdavidnmac_biba_set_single(struct mac_biba *mac_biba, u_short type, u_short grade, 44244229Sdavidn u_char *compartments) 44344229Sdavidn{ 44444229Sdavidn 44544229Sdavidn mac_biba->mb_single.mbe_type = type; 44644229Sdavidn mac_biba->mb_single.mbe_grade = grade; 44744229Sdavidn if (compartments != NULL) 44844229Sdavidn memcpy(mac_biba->mb_single.mbe_compartments, compartments, 44944229Sdavidn sizeof(mac_biba->mb_single.mbe_compartments)); 45044229Sdavidn mac_biba->mb_flags |= MAC_BIBA_FLAG_SINGLE; 45120253Sjoerg} 45220253Sjoerg 45320267Sjoergstatic void 45420253Sjoergmac_biba_copy_range(struct mac_biba *labelfrom, struct mac_biba *labelto) 45544386Sdavidn{ 45644386Sdavidn 45744386Sdavidn KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_RANGE) != 0, 45820253Sjoerg ("mac_biba_copy_range: labelfrom not range")); 45920253Sjoerg 46020253Sjoerg labelto->mb_rangelow = labelfrom->mb_rangelow; 46120253Sjoerg labelto->mb_rangehigh = labelfrom->mb_rangehigh; 46220253Sjoerg labelto->mb_flags |= MAC_BIBA_FLAG_RANGE; 46320253Sjoerg} 46430259Scharnier 46520679Sdavidnstatic void 46652527Sdavidnmac_biba_copy_single(struct mac_biba *labelfrom, struct mac_biba *labelto) 46720253Sjoerg{ 46852527Sdavidn 46961957Sache KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0, 47020253Sjoerg ("mac_biba_copy_single: labelfrom not single")); 47152527Sdavidn 47220253Sjoerg labelto->mb_single = labelfrom->mb_single; 47330259Scharnier labelto->mb_flags |= MAC_BIBA_FLAG_SINGLE; 47420253Sjoerg} 47530259Scharnier 47620253Sjoergstatic void 47720253Sjoergmac_biba_copy(struct mac_biba *source, struct mac_biba *dest) 47852527Sdavidn{ 47952527Sdavidn 48052527Sdavidn if (source->mb_flags & MAC_BIBA_FLAG_SINGLE) 48152527Sdavidn mac_biba_copy_single(source, dest); 48261762Sdavidn if (source->mb_flags & MAC_BIBA_FLAG_RANGE) 48352527Sdavidn mac_biba_copy_range(source, dest); 48452527Sdavidn} 48552527Sdavidn 48620253Sjoerg/* 48752527Sdavidn * Policy module operations. 48852527Sdavidn */ 48952527Sdavidnstatic void 49052527Sdavidnmac_biba_destroy(struct mac_policy_conf *conf) 49152527Sdavidn{ 49252527Sdavidn 49320253Sjoerg} 49420253Sjoerg 49520253Sjoergstatic void 49620253Sjoergmac_biba_init(struct mac_policy_conf *conf) 49752527Sdavidn{ 49852527Sdavidn 49952527Sdavidn} 50052527Sdavidn 50120253Sjoerg/* 50220253Sjoerg * Label operations. 50352527Sdavidn */ 50420267Sjoergstatic void 50552527Sdavidnmac_biba_init_label(struct label *label) 50652527Sdavidn{ 50752527Sdavidn 50852527Sdavidn SLOT(label) = biba_alloc(M_WAITOK); 50952527Sdavidn} 51052527Sdavidn 51120253Sjoergstatic int 51220253Sjoergmac_biba_init_label_waitcheck(struct label *label, int flag) 51320253Sjoerg{ 51420253Sjoerg 51552527Sdavidn SLOT(label) = biba_alloc(flag); 51652527Sdavidn if (SLOT(label) == NULL) 51752527Sdavidn return (ENOMEM); 51852527Sdavidn 51920253Sjoerg return (0); 52020253Sjoerg} 52120253Sjoerg 52252527Sdavidnstatic void 52352527Sdavidnmac_biba_destroy_label(struct label *label) 52452527Sdavidn{ 52552527Sdavidn 52652527Sdavidn biba_free(SLOT(label)); 52752527Sdavidn SLOT(label) = NULL; 52852527Sdavidn} 52952527Sdavidn 53052527Sdavidn/* 53120253Sjoerg * mac_biba_element_to_string() is basically an snprintf wrapper with 53252527Sdavidn * the same properties as snprintf(). It returns the length it would 53352527Sdavidn * have added to the string in the event the string is too short. 53452527Sdavidn */ 53552527Sdavidnstatic size_t 53652527Sdavidnmac_biba_element_to_string(char *string, size_t size, 53752527Sdavidn struct mac_biba_element *element) 53852527Sdavidn{ 53952527Sdavidn int pos, bit = 1; 54052527Sdavidn 54120747Sdavidn switch (element->mbe_type) { 542130629Srobert case MAC_BIBA_TYPE_HIGH: 543130629Srobert return (snprintf(string, size, "high")); 54420747Sdavidn 54520747Sdavidn case MAC_BIBA_TYPE_LOW: 54630259Scharnier return (snprintf(string, size, "low")); 54720747Sdavidn 54830259Scharnier case MAC_BIBA_TYPE_EQUAL: 54920747Sdavidn return (snprintf(string, size, "equal")); 55020747Sdavidn 551124382Siedowse case MAC_BIBA_TYPE_GRADE: 552124382Siedowse pos = snprintf(string, size, "%d:", element->mbe_grade); 55364918Sgreen for (bit = 1; bit <= MAC_BIBA_MAX_COMPARTMENTS; bit++) { 55464918Sgreen if (MAC_BIBA_BIT_TEST(bit, element->mbe_compartments)) 55564918Sgreen pos += snprintf(string + pos, size - pos, 55664918Sgreen "%d+", bit); 557253157Sdes } 55864918Sgreen if (string[pos - 1] == '+' || string[pos - 1] == ':') 55964918Sgreen string[--pos] = '\0'; 56020267Sjoerg return (pos); 56152527Sdavidn 56252527Sdavidn default: 56320267Sjoerg panic("mac_biba_element_to_string: invalid type (%d)", 56420253Sjoerg element->mbe_type); 56564918Sgreen } 56652527Sdavidn} 56752527Sdavidn 56852527Sdavidnstatic int 56952527Sdavidnmac_biba_to_string(char *string, size_t size, size_t *caller_len, 57052527Sdavidn struct mac_biba *mac_biba) 57120253Sjoerg{ 57230259Scharnier size_t left, len; 57344229Sdavidn char *curptr; 57430259Scharnier 57520253Sjoerg bzero(string, size); 57620253Sjoerg curptr = string; 57720253Sjoerg left = size; 57820253Sjoerg 57920253Sjoerg if (mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) { 58020253Sjoerg len = mac_biba_element_to_string(curptr, left, 58120253Sjoerg &mac_biba->mb_single); 58220253Sjoerg if (len >= left) 58320253Sjoerg return (EINVAL); 58420253Sjoerg left -= len; 58520253Sjoerg curptr += len; 58620253Sjoerg } 58720253Sjoerg 58864918Sgreen if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) { 58964918Sgreen len = snprintf(curptr, left, "("); 59064918Sgreen if (len >= left) 59164918Sgreen return (EINVAL); 59264918Sgreen left -= len; 59352527Sdavidn curptr += len; 59420253Sjoerg 59520253Sjoerg len = mac_biba_element_to_string(curptr, left, 59630259Scharnier &mac_biba->mb_rangelow); 59720253Sjoerg if (len >= left) 59820253Sjoerg return (EINVAL); 59920253Sjoerg left -= len; 60020253Sjoerg curptr += len; 60120253Sjoerg 60252527Sdavidn len = snprintf(curptr, left, "-"); 60352527Sdavidn if (len >= left) 60452527Sdavidn return (EINVAL); 60552527Sdavidn left -= len; 60652527Sdavidn curptr += len; 60752527Sdavidn 60852527Sdavidn len = mac_biba_element_to_string(curptr, left, 60920253Sjoerg &mac_biba->mb_rangehigh); 610124382Siedowse if (len >= left) 611124382Siedowse return (EINVAL); 61263572Sdavidn left -= len; 61363572Sdavidn curptr += len; 61463572Sdavidn 61563572Sdavidn len = snprintf(curptr, left, ")"); 61663572Sdavidn if (len >= left) 61763572Sdavidn return (EINVAL); 61820253Sjoerg left -= len; 619124382Siedowse curptr += len; 62020253Sjoerg } 62120253Sjoerg 62220253Sjoerg *caller_len = strlen(string); 62364918Sgreen return (0); 62420253Sjoerg} 62520253Sjoerg 62620253Sjoergstatic int 62720253Sjoergmac_biba_externalize_label(struct label *label, char *element_name, 62820253Sjoerg char *element_data, size_t size, size_t *len, int *claimed) 62920253Sjoerg{ 63020253Sjoerg struct mac_biba *mac_biba; 63120253Sjoerg int error; 63220253Sjoerg 63320253Sjoerg if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0) 634124382Siedowse return (0); 635124382Siedowse 636124382Siedowse (*claimed)++; 637124382Siedowse 63820253Sjoerg mac_biba = SLOT(label); 63920253Sjoerg error = mac_biba_to_string(element_data, size, len, mac_biba); 64020253Sjoerg if (error) 64120253Sjoerg return (error); 64220253Sjoerg 64320253Sjoerg *len = strlen(element_data); 64420253Sjoerg return (0); 64520253Sjoerg} 64620253Sjoerg 64720253Sjoergstatic int 648124382Siedowsemac_biba_parse_element(struct mac_biba_element *element, char *string) 649124382Siedowse{ 65020267Sjoerg 65120253Sjoerg if (strcmp(string, "high") == 0 || 65220253Sjoerg strcmp(string, "hi") == 0) { 653168045Sle element->mbe_type = MAC_BIBA_TYPE_HIGH; 65420253Sjoerg element->mbe_grade = MAC_BIBA_TYPE_UNDEF; 65520253Sjoerg } else if (strcmp(string, "low") == 0 || 65630259Scharnier strcmp(string, "lo") == 0) { 657124382Siedowse element->mbe_type = MAC_BIBA_TYPE_LOW; 658124382Siedowse element->mbe_grade = MAC_BIBA_TYPE_UNDEF; 659124382Siedowse } else if (strcmp(string, "equal") == 0 || 660124382Siedowse strcmp(string, "eq") == 0) { 661124382Siedowse element->mbe_type = MAC_BIBA_TYPE_EQUAL; 662124382Siedowse element->mbe_grade = MAC_BIBA_TYPE_UNDEF; 663124382Siedowse } else { 664124382Siedowse char *p0, *p1; 665124382Siedowse int d; 666124382Siedowse 667124382Siedowse p0 = string; 668124382Siedowse d = strtol(p0, &p1, 10); 66952527Sdavidn 67020253Sjoerg if (d < 0 || d > 65535) 67120253Sjoerg return (EINVAL); 67220267Sjoerg element->mbe_type = MAC_BIBA_TYPE_GRADE; 67320267Sjoerg element->mbe_grade = d; 67420267Sjoerg 67520267Sjoerg if (*p1 != ':') { 67620267Sjoerg if (p1 == p0 || *p1 != '\0') 67744386Sdavidn return (EINVAL); 67844386Sdavidn else 67944386Sdavidn return (0); 68020267Sjoerg } 68121330Sdavidn else 68252527Sdavidn if (*(p1 + 1) == '\0') 68352502Sdavidn return (0); 68452502Sdavidn 68552502Sdavidn while ((p0 = ++p1)) { 68652502Sdavidn d = strtol(p0, &p1, 10); 68752502Sdavidn if (d < 1 || d > MAC_BIBA_MAX_COMPARTMENTS) 68856000Sdavidn return (EINVAL); 68952502Sdavidn 69052502Sdavidn MAC_BIBA_BIT_SET(d, element->mbe_compartments); 69152502Sdavidn 69252502Sdavidn if (*p1 == '\0') 69352502Sdavidn break; 69452502Sdavidn if (p1 == p0 || *p1 != '+') 69552502Sdavidn return (EINVAL); 69656000Sdavidn } 69752502Sdavidn } 69852502Sdavidn 69952512Sdavidn return (0); 70052527Sdavidn} 70152527Sdavidn 70252527Sdavidn/* 70352527Sdavidn * Note: destructively consumes the string, make a local copy before 70452527Sdavidn * calling if that's a problem. 70552527Sdavidn */ 70656000Sdavidnstatic int 70752527Sdavidnmac_biba_parse(struct mac_biba *mac_biba, char *string) 70852527Sdavidn{ 70952527Sdavidn char *range, *rangeend, *rangehigh, *rangelow, *single; 71052527Sdavidn int error; 71152527Sdavidn 71252527Sdavidn /* Do we have a range? */ 71352527Sdavidn single = string; 71456000Sdavidn range = index(string, '('); 71552527Sdavidn if (range == single) 71652527Sdavidn single = NULL; 71752502Sdavidn rangelow = rangehigh = NULL; 71821330Sdavidn if (range != NULL) { 71921330Sdavidn /* Nul terminate the end of the single string. */ 72020253Sjoerg *range = '\0'; 72120253Sjoerg range++; 72220253Sjoerg rangelow = range; 72320253Sjoerg rangehigh = index(rangelow, '-'); 72420253Sjoerg if (rangehigh == NULL) 72520253Sjoerg return (EINVAL); 72620253Sjoerg rangehigh++; 72761759Sdavidn if (*rangelow == '\0' || *rangehigh == '\0') 72861759Sdavidn return (EINVAL); 72961759Sdavidn rangeend = index(rangehigh, ')'); 73061759Sdavidn if (rangeend == NULL) 73161759Sdavidn return (EINVAL); 73261759Sdavidn if (*(rangeend + 1) != '\0') 73361759Sdavidn return (EINVAL); 73461759Sdavidn /* Nul terminate the ends of the ranges. */ 73561759Sdavidn *(rangehigh - 1) = '\0'; 73661759Sdavidn *rangeend = '\0'; 73730259Scharnier } 73820253Sjoerg KASSERT((rangelow != NULL && rangehigh != NULL) || 73944229Sdavidn (rangelow == NULL && rangehigh == NULL), 74098744Sdwmalone ("mac_biba_internalize_label: range mismatch")); 74120253Sjoerg 74220253Sjoerg bzero(mac_biba, sizeof(*mac_biba)); 74320253Sjoerg if (single != NULL) { 74420253Sjoerg error = mac_biba_parse_element(&mac_biba->mb_single, single); 74520253Sjoerg if (error) 74620253Sjoerg return (error); 74720253Sjoerg mac_biba->mb_flags |= MAC_BIBA_FLAG_SINGLE; 74820253Sjoerg } 74920253Sjoerg 75020253Sjoerg if (rangelow != NULL) { 75144229Sdavidn error = mac_biba_parse_element(&mac_biba->mb_rangelow, 75244229Sdavidn rangelow); 75344229Sdavidn if (error) 75444229Sdavidn return (error); 75544229Sdavidn error = mac_biba_parse_element(&mac_biba->mb_rangehigh, 75620253Sjoerg rangehigh); 75720253Sjoerg if (error) 75852527Sdavidn return (error); 75920253Sjoerg mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE; 76082868Sdd } 76120253Sjoerg 76220253Sjoerg error = mac_biba_valid(mac_biba); 76320253Sjoerg if (error) 76444229Sdavidn return (error); 765168044Sle 76620253Sjoerg return (0); 76720253Sjoerg} 76820253Sjoerg 76952527Sdavidnstatic int 77082868Sddmac_biba_internalize_label(struct label *label, char *element_name, 77182868Sdd char *element_data, int *claimed) 77282868Sdd{ 77382868Sdd struct mac_biba *mac_biba, mac_biba_temp; 77482868Sdd int error; 77582868Sdd 77682868Sdd if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0) 77782868Sdd return (0); 77882868Sdd 77982868Sdd (*claimed)++; 78082868Sdd 78182868Sdd error = mac_biba_parse(&mac_biba_temp, element_data); 78282868Sdd if (error) 78382868Sdd return (error); 78482868Sdd 78582868Sdd mac_biba = SLOT(label); 78682868Sdd *mac_biba = mac_biba_temp; 78782868Sdd 78882868Sdd return (0); 78982868Sdd} 79082868Sdd 79182868Sddstatic void 79220267Sjoergmac_biba_copy_label(struct label *src, struct label *dest) 79320253Sjoerg{ 79420253Sjoerg 79520253Sjoerg *SLOT(dest) = *SLOT(src); 79620253Sjoerg} 79720253Sjoerg 79820253Sjoerg/* 79920253Sjoerg * Labeling event operations: file system objects, and things that look 80020253Sjoerg * a lot like file system objects. 80120253Sjoerg */ 80220253Sjoergstatic void 80320253Sjoergmac_biba_create_devfs_device(struct mount *mp, dev_t dev, 80420253Sjoerg struct devfs_dirent *devfs_dirent, struct label *label) 80520253Sjoerg{ 80620253Sjoerg struct mac_biba *mac_biba; 80720253Sjoerg int biba_type; 80820253Sjoerg 80944229Sdavidn mac_biba = SLOT(label); 81030259Scharnier if (strcmp(dev->si_name, "null") == 0 || 81120253Sjoerg strcmp(dev->si_name, "zero") == 0 || 81220253Sjoerg strcmp(dev->si_name, "random") == 0 || 81320253Sjoerg strncmp(dev->si_name, "fd/", strlen("fd/")) == 0) 81420253Sjoerg biba_type = MAC_BIBA_TYPE_EQUAL; 81520253Sjoerg else if (ptys_equal && 81620253Sjoerg (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 || 81720253Sjoerg strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0)) 81820253Sjoerg biba_type = MAC_BIBA_TYPE_EQUAL; 81920253Sjoerg else 82020253Sjoerg biba_type = MAC_BIBA_TYPE_HIGH; 82120253Sjoerg mac_biba_set_single(mac_biba, biba_type, 0, NULL); 82220253Sjoerg} 82320253Sjoerg 82420253Sjoergstatic void 82520253Sjoergmac_biba_create_devfs_directory(struct mount *mp, char *dirname, 82620253Sjoerg int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label) 82720253Sjoerg{ 82820253Sjoerg struct mac_biba *mac_biba; 82944229Sdavidn 83044229Sdavidn mac_biba = SLOT(label); 83144229Sdavidn mac_biba_set_single(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL); 83220253Sjoerg} 83344229Sdavidn 83420253Sjoergstatic void 83520253Sjoergmac_biba_create_devfs_symlink(struct ucred *cred, struct mount *mp, 83620253Sjoerg struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, 83720253Sjoerg struct label *delabel) 83820253Sjoerg{ 83920253Sjoerg struct mac_biba *source, *dest; 84020253Sjoerg 84120253Sjoerg source = SLOT(&cred->cr_label); 84220253Sjoerg dest = SLOT(delabel); 84320253Sjoerg 84420253Sjoerg mac_biba_copy_single(source, dest); 84530259Scharnier} 84620253Sjoerg 84720253Sjoergstatic void 84820253Sjoergmac_biba_create_mount(struct ucred *cred, struct mount *mp, 84920253Sjoerg struct label *mntlabel, struct label *fslabel) 85020253Sjoerg{ 85120253Sjoerg struct mac_biba *source, *dest; 85220253Sjoerg 85320253Sjoerg source = SLOT(&cred->cr_label); 85420253Sjoerg dest = SLOT(mntlabel); 85520253Sjoerg mac_biba_copy_single(source, dest); 85620253Sjoerg dest = SLOT(fslabel); 85720253Sjoerg mac_biba_copy_single(source, dest); 85820253Sjoerg} 85920253Sjoerg 86020253Sjoergstatic void 86120253Sjoergmac_biba_create_root_mount(struct ucred *cred, struct mount *mp, 86220253Sjoerg struct label *mntlabel, struct label *fslabel) 86320253Sjoerg{ 86420253Sjoerg struct mac_biba *mac_biba; 86520253Sjoerg 86620253Sjoerg /* Always mount root as high integrity. */ 86720253Sjoerg mac_biba = SLOT(fslabel); 86844229Sdavidn mac_biba_set_single(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL); 86920253Sjoerg mac_biba = SLOT(mntlabel); 87044229Sdavidn mac_biba_set_single(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL); 87120253Sjoerg} 87261957Sache 87330259Scharnierstatic void 87420253Sjoergmac_biba_relabel_vnode(struct ucred *cred, struct vnode *vp, 87520253Sjoerg struct label *vnodelabel, struct label *label) 87644229Sdavidn{ 87720267Sjoerg struct mac_biba *source, *dest; 87820253Sjoerg 87920253Sjoerg source = SLOT(label); 88020253Sjoerg dest = SLOT(vnodelabel); 88120253Sjoerg 88220253Sjoerg mac_biba_copy(source, dest); 88320253Sjoerg} 88420253Sjoerg 88520253Sjoergstatic void 88620253Sjoergmac_biba_update_devfsdirent(struct mount *mp, 88720253Sjoerg struct devfs_dirent *devfs_dirent, struct label *direntlabel, 88820253Sjoerg struct vnode *vp, struct label *vnodelabel) 88920253Sjoerg{ 89020253Sjoerg struct mac_biba *source, *dest; 89120253Sjoerg 89220253Sjoerg source = SLOT(vnodelabel); 89320253Sjoerg dest = SLOT(direntlabel); 89444229Sdavidn 89520253Sjoerg mac_biba_copy(source, dest); 89620253Sjoerg} 89720253Sjoerg 89820267Sjoergstatic void 89920267Sjoergmac_biba_associate_vnode_devfs(struct mount *mp, struct label *fslabel, 90020267Sjoerg struct devfs_dirent *de, struct label *delabel, struct vnode *vp, 90120267Sjoerg struct label *vlabel) 90220267Sjoerg{ 90320267Sjoerg struct mac_biba *source, *dest; 90420267Sjoerg 90520267Sjoerg source = SLOT(delabel); 90620267Sjoerg dest = SLOT(vlabel); 90744229Sdavidn 90820267Sjoerg mac_biba_copy_single(source, dest); 90920267Sjoerg} 91070486Sben 91120253Sjoergstatic int 91270486Sbenmac_biba_associate_vnode_extattr(struct mount *mp, struct label *fslabel, 91320253Sjoerg struct vnode *vp, struct label *vlabel) 91420253Sjoerg{ 91520253Sjoerg struct mac_biba temp, *source, *dest; 91620253Sjoerg int buflen, error; 91744229Sdavidn 91820253Sjoerg source = SLOT(fslabel); 91920253Sjoerg dest = SLOT(vlabel); 92020253Sjoerg 92120253Sjoerg buflen = sizeof(temp); 92220253Sjoerg bzero(&temp, buflen); 92320253Sjoerg 92420253Sjoerg error = vn_extattr_get(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE, 92520253Sjoerg MAC_BIBA_EXTATTR_NAME, &buflen, (char *) &temp, curthread); 92620253Sjoerg if (error == ENOATTR || error == EOPNOTSUPP) { 92727831Sdavidn /* Fall back to the fslabel. */ 92820253Sjoerg mac_biba_copy_single(source, dest); 92920253Sjoerg return (0); 93020253Sjoerg } else if (error) 93130259Scharnier return (error); 93220253Sjoerg 93320253Sjoerg if (buflen != sizeof(temp)) { 93420253Sjoerg printf("mac_biba_associate_vnode_extattr: bad size %d\n", 93520253Sjoerg buflen); 93620253Sjoerg return (EPERM); 93720253Sjoerg } 93820253Sjoerg if (mac_biba_valid(&temp) != 0) { 93920253Sjoerg printf("mac_biba_associate_vnode_extattr: invalid\n"); 94020253Sjoerg return (EPERM); 94120253Sjoerg } 94220253Sjoerg if ((temp.mb_flags & MAC_BIBA_FLAGS_BOTH) != MAC_BIBA_FLAG_SINGLE) { 94320253Sjoerg printf("mac_biba_associate_vnode_extattr: not single\n"); 94420253Sjoerg return (EPERM); 94520253Sjoerg } 94620253Sjoerg 94730259Scharnier mac_biba_copy_single(&temp, dest); 94820253Sjoerg return (0); 94920253Sjoerg} 95020253Sjoerg 95120253Sjoergstatic void 95220253Sjoergmac_biba_associate_vnode_singlelabel(struct mount *mp, 95320253Sjoerg struct label *fslabel, struct vnode *vp, struct label *vlabel) 95420253Sjoerg{ 95520253Sjoerg struct mac_biba *source, *dest; 95620253Sjoerg 95720253Sjoerg source = SLOT(fslabel); 95820253Sjoerg dest = SLOT(vlabel); 95920253Sjoerg 96020253Sjoerg mac_biba_copy_single(source, dest); 96120253Sjoerg} 96220253Sjoerg 96320253Sjoergstatic int 96420253Sjoergmac_biba_create_vnode_extattr(struct ucred *cred, struct mount *mp, 96530259Scharnier struct label *fslabel, struct vnode *dvp, struct label *dlabel, 96620253Sjoerg struct vnode *vp, struct label *vlabel, struct componentname *cnp) 96720253Sjoerg{ 96820253Sjoerg struct mac_biba *source, *dest, temp; 96920253Sjoerg size_t buflen; 97020253Sjoerg int error; 97120253Sjoerg 97220253Sjoerg buflen = sizeof(temp); 97320253Sjoerg bzero(&temp, buflen); 97420253Sjoerg 97520253Sjoerg source = SLOT(&cred->cr_label); 97620253Sjoerg dest = SLOT(vlabel); 97720253Sjoerg mac_biba_copy_single(source, &temp); 97820253Sjoerg 97920253Sjoerg error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE, 98020253Sjoerg MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread); 98120253Sjoerg if (error == 0) 98220253Sjoerg mac_biba_copy_single(source, dest); 983130633Srobert return (error); 98420253Sjoerg} 98520253Sjoerg 98620253Sjoergstatic int 98720253Sjoergmac_biba_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 98820253Sjoerg struct label *vlabel, struct label *intlabel) 98920253Sjoerg{ 99020253Sjoerg struct mac_biba *source, temp; 99120253Sjoerg size_t buflen; 99220253Sjoerg int error; 99320253Sjoerg 99420253Sjoerg buflen = sizeof(temp); 99520253Sjoerg bzero(&temp, buflen); 99620253Sjoerg 99720253Sjoerg source = SLOT(intlabel); 99820253Sjoerg if ((source->mb_flags & MAC_BIBA_FLAG_SINGLE) == 0) 99920253Sjoerg return (0); 100030259Scharnier 100130259Scharnier mac_biba_copy_single(source, &temp); 100220253Sjoerg 100320253Sjoerg error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE, 100420253Sjoerg MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread); 100520253Sjoerg return (error); 100620253Sjoerg} 100720253Sjoerg 100820253Sjoerg/* 100920253Sjoerg * Labeling event operations: IPC object. 101020253Sjoerg */ 101120253Sjoergstatic void 101220253Sjoergmac_biba_create_mbuf_from_socket(struct socket *so, struct label *socketlabel, 101320253Sjoerg struct mbuf *m, struct label *mbuflabel) 101420253Sjoerg{ 101520253Sjoerg struct mac_biba *source, *dest; 101620253Sjoerg 101720253Sjoerg source = SLOT(socketlabel); 1018179365Santoine dest = SLOT(mbuflabel); 101920253Sjoerg 1020179365Santoine mac_biba_copy_single(source, dest); 1021179365Santoine} 102220253Sjoerg 102320253Sjoergstatic void 102420253Sjoergmac_biba_create_socket(struct ucred *cred, struct socket *socket, 102520253Sjoerg struct label *socketlabel) 1026179365Santoine{ 102720253Sjoerg struct mac_biba *source, *dest; 102820253Sjoerg 102920253Sjoerg source = SLOT(&cred->cr_label); 103020253Sjoerg dest = SLOT(socketlabel); 103120253Sjoerg 103220253Sjoerg mac_biba_copy_single(source, dest); 1033179365Santoine} 1034181785Sache 1035179365Santoinestatic void 103620253Sjoergmac_biba_create_pipe(struct ucred *cred, struct pipe *pipe, 103720253Sjoerg struct label *pipelabel) 103820253Sjoerg{ 103920253Sjoerg struct mac_biba *source, *dest; 104020590Sdavidn 104120253Sjoerg source = SLOT(&cred->cr_label); 104220253Sjoerg dest = SLOT(pipelabel); 104320253Sjoerg 104420253Sjoerg mac_biba_copy_single(source, dest); 104520253Sjoerg} 104620253Sjoerg 104720253Sjoergstatic void 104820253Sjoergmac_biba_create_socket_from_socket(struct socket *oldsocket, 104973563Skris struct label *oldsocketlabel, struct socket *newsocket, 105020253Sjoerg struct label *newsocketlabel) 1051181785Sache{ 105220253Sjoerg struct mac_biba *source, *dest; 105320253Sjoerg 105420253Sjoerg source = SLOT(oldsocketlabel); 105520253Sjoerg dest = SLOT(newsocketlabel); 105620253Sjoerg 1057124382Siedowse mac_biba_copy_single(source, dest); 1058124382Siedowse} 105961957Sache 106020712Sdavidnstatic void 106120253Sjoergmac_biba_relabel_socket(struct ucred *cred, struct socket *socket, 106220253Sjoerg struct label *socketlabel, struct label *newlabel) 106320253Sjoerg{ 106420253Sjoerg struct mac_biba *source, *dest; 106520253Sjoerg 106620253Sjoerg source = SLOT(newlabel); 106720253Sjoerg dest = SLOT(socketlabel); 106820253Sjoerg 106920253Sjoerg mac_biba_copy(source, dest); 107020253Sjoerg} 107120253Sjoerg 107220253Sjoergstatic void 107320253Sjoergmac_biba_relabel_pipe(struct ucred *cred, struct pipe *pipe, 1074130633Srobert struct label *pipelabel, struct label *newlabel) 107520253Sjoerg{ 107620253Sjoerg struct mac_biba *source, *dest; 107720253Sjoerg 107820253Sjoerg source = SLOT(newlabel); 107920253Sjoerg dest = SLOT(pipelabel); 108020253Sjoerg 108120253Sjoerg mac_biba_copy(source, dest); 108244386Sdavidn} 108320253Sjoerg 108420253Sjoergstatic void 108520253Sjoergmac_biba_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel, 108620253Sjoerg struct socket *socket, struct label *socketpeerlabel) 108744386Sdavidn{ 108820253Sjoerg struct mac_biba *source, *dest; 108920253Sjoerg 109020267Sjoerg source = SLOT(mbuflabel); 109120253Sjoerg dest = SLOT(socketpeerlabel); 109244229Sdavidn 109320253Sjoerg mac_biba_copy_single(source, dest); 109420253Sjoerg} 109520590Sdavidn 109620590Sdavidn/* 109720253Sjoerg * Labeling event operations: network objects. 109820253Sjoerg */ 1099130633Srobertstatic void 110020253Sjoergmac_biba_set_socket_peer_from_socket(struct socket *oldsocket, 1101130633Srobert struct label *oldsocketlabel, struct socket *newsocket, 110220253Sjoerg struct label *newsocketpeerlabel) 1103130633Srobert{ 110420253Sjoerg struct mac_biba *source, *dest; 1105130633Srobert 1106130633Srobert source = SLOT(oldsocketlabel); 110720253Sjoerg dest = SLOT(newsocketpeerlabel); 110820253Sjoerg 110920253Sjoerg mac_biba_copy_single(source, dest); 111020253Sjoerg} 111120253Sjoerg 111220253Sjoergstatic void 111320253Sjoergmac_biba_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d, 111420253Sjoerg struct label *bpflabel) 111520253Sjoerg{ 111620253Sjoerg struct mac_biba *source, *dest; 111720253Sjoerg 111820253Sjoerg source = SLOT(&cred->cr_label); 111920253Sjoerg dest = SLOT(bpflabel); 112061957Sache 112120253Sjoerg mac_biba_copy_single(source, dest); 112220590Sdavidn} 112374569Sache 112461957Sachestatic void 112574569Sachemac_biba_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel) 112622394Sdavidn{ 112720747Sdavidn char tifname[IFNAMSIZ], ifname[IFNAMSIZ], *p, *q; 112820747Sdavidn char tiflist[sizeof(trusted_interfaces)]; 112920747Sdavidn struct mac_biba *dest; 113020747Sdavidn int len, type; 113120747Sdavidn 113220253Sjoerg dest = SLOT(ifnetlabel); 113320253Sjoerg 113420253Sjoerg if (ifnet->if_type == IFT_LOOP) { 113520590Sdavidn type = MAC_BIBA_TYPE_EQUAL; 113620590Sdavidn goto set; 113744229Sdavidn } 113820267Sjoerg 113944229Sdavidn if (trust_all_interfaces) { 114020267Sjoerg type = MAC_BIBA_TYPE_HIGH; 114120267Sjoerg goto set; 114220747Sdavidn } 114320267Sjoerg 114420267Sjoerg type = MAC_BIBA_TYPE_LOW; 114520267Sjoerg 114620747Sdavidn if (trusted_interfaces[0] == '\0' || 114720267Sjoerg !strvalid(trusted_interfaces, sizeof(trusted_interfaces))) 114820267Sjoerg goto set; 114920267Sjoerg 115020267Sjoerg bzero(tiflist, sizeof(tiflist)); 115120267Sjoerg for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++) 115244229Sdavidn if(*p != ' ' && *p != '\t') 115361957Sache *q = *p; 115420253Sjoerg 115520267Sjoerg snprintf(ifname, IFNAMSIZ, "%s%d", ifnet->if_name, ifnet->if_unit); 115620253Sjoerg 115720253Sjoerg for (p = q = tiflist;; p++) { 115820679Sdavidn if (*p == ',' || *p == '\0') { 115920679Sdavidn len = p - q; 116020253Sjoerg if (len < IFNAMSIZ) { 1161109961Sgad bzero(tifname, sizeof(tifname)); 1162109961Sgad bcopy(q, tifname, len); 1163109961Sgad if (strcmp(tifname, ifname) == 0) { 116420253Sjoerg type = MAC_BIBA_TYPE_HIGH; 1165109961Sgad break; 1166109961Sgad } 1167109961Sgad } else { 1168109961Sgad *p = '\0'; 1169109961Sgad printf("mac_biba warning: interface name " 1170109961Sgad "\"%s\" is too long (must be < %d)\n", 1171109961Sgad q, IFNAMSIZ); 1172109961Sgad } 1173109961Sgad if (*p == '\0') 1174109961Sgad break; 1175109961Sgad q = p + 1; 1176109961Sgad } 1177109961Sgad } 117820253Sjoergset: 1179109961Sgad mac_biba_set_single(dest, type, 0, NULL); 1180109961Sgad mac_biba_set_range(dest, type, 0, NULL, type, 0, NULL); 1181109961Sgad} 1182109961Sgad 1183109961Sgadstatic void 1184109961Sgadmac_biba_create_ipq(struct mbuf *fragment, struct label *fragmentlabel, 1185109961Sgad struct ipq *ipq, struct label *ipqlabel) 1186109961Sgad{ 1187109961Sgad struct mac_biba *source, *dest; 1188109961Sgad 1189109961Sgad source = SLOT(fragmentlabel); 1190109961Sgad dest = SLOT(ipqlabel); 1191109961Sgad 1192109961Sgad mac_biba_copy_single(source, dest); 1193109961Sgad} 1194109961Sgad 1195109961Sgadstatic void 1196109961Sgadmac_biba_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel, 1197109961Sgad struct mbuf *datagram, struct label *datagramlabel) 1198109961Sgad{ 1199109961Sgad struct mac_biba *source, *dest; 1200109961Sgad 1201109961Sgad source = SLOT(ipqlabel); 1202109961Sgad dest = SLOT(datagramlabel); 1203109961Sgad 1204109961Sgad /* Just use the head, since we require them all to match. */ 1205109961Sgad mac_biba_copy_single(source, dest); 1206109961Sgad} 1207229237Sdim 1208109961Sgadstatic void 1209109961Sgadmac_biba_create_fragment(struct mbuf *datagram, struct label *datagramlabel, 1210109961Sgad struct mbuf *fragment, struct label *fragmentlabel) 1211109961Sgad{ 1212109961Sgad struct mac_biba *source, *dest; 121320679Sdavidn 121420253Sjoerg source = SLOT(datagramlabel); 121520253Sjoerg dest = SLOT(fragmentlabel); 121620253Sjoerg 121720253Sjoerg mac_biba_copy_single(source, dest); 121820253Sjoerg} 121920253Sjoerg 122020253Sjoergstatic void 122120253Sjoergmac_biba_create_mbuf_from_mbuf(struct mbuf *oldmbuf, 122220253Sjoerg struct label *oldmbuflabel, struct mbuf *newmbuf, 122320253Sjoerg struct label *newmbuflabel) 122420253Sjoerg{ 122520253Sjoerg struct mac_biba *source, *dest; 122620253Sjoerg 122720253Sjoerg source = SLOT(oldmbuflabel); 122820253Sjoerg dest = SLOT(newmbuflabel); 122920253Sjoerg 123020253Sjoerg /* 123120253Sjoerg * Because the source mbuf may not yet have been "created", 123220253Sjoerg * just initialized, we do a conditional copy. Since we don't 123320253Sjoerg * allow mbufs to have ranges, do a KASSERT to make sure that 123420253Sjoerg * doesn't happen. 123520253Sjoerg */ 123620253Sjoerg KASSERT((source->mb_flags & MAC_BIBA_FLAG_RANGE) == 0, 123720253Sjoerg ("mac_biba_create_mbuf_from_mbuf: source mbuf has range")); 123820253Sjoerg mac_biba_copy(source, dest); 123920253Sjoerg} 124020253Sjoerg 124120747Sdavidnstatic void 124220747Sdavidnmac_biba_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel, 124385145Sache struct mbuf *mbuf, struct label *mbuflabel) 124420747Sdavidn{ 124585145Sache struct mac_biba *dest; 124685145Sache 124720747Sdavidn dest = SLOT(mbuflabel); 124821052Sdavidn 124921052Sdavidn mac_biba_set_single(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL); 125021052Sdavidn} 125121052Sdavidn 125220747Sdavidnstatic void 125321052Sdavidnmac_biba_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel, 125421052Sdavidn struct mbuf *mbuf, struct label *mbuflabel) 125521052Sdavidn{ 125621052Sdavidn struct mac_biba *source, *dest; 125721052Sdavidn 125821052Sdavidn source = SLOT(bpflabel); 125920747Sdavidn dest = SLOT(mbuflabel); 126021052Sdavidn 126120747Sdavidn mac_biba_copy_single(source, dest); 126221052Sdavidn} 126321052Sdavidn 126421052Sdavidnstatic void 126521052Sdavidnmac_biba_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel, 126620747Sdavidn struct mbuf *m, struct label *mbuflabel) 126720747Sdavidn{ 126820747Sdavidn struct mac_biba *source, *dest; 1269 1270 source = SLOT(ifnetlabel); 1271 dest = SLOT(mbuflabel); 1272 1273 mac_biba_copy_single(source, dest); 1274} 1275 1276static void 1277mac_biba_create_mbuf_multicast_encap(struct mbuf *oldmbuf, 1278 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel, 1279 struct mbuf *newmbuf, struct label *newmbuflabel) 1280{ 1281 struct mac_biba *source, *dest; 1282 1283 source = SLOT(oldmbuflabel); 1284 dest = SLOT(newmbuflabel); 1285 1286 mac_biba_copy_single(source, dest); 1287} 1288 1289static void 1290mac_biba_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel, 1291 struct mbuf *newmbuf, struct label *newmbuflabel) 1292{ 1293 struct mac_biba *source, *dest; 1294 1295 source = SLOT(oldmbuflabel); 1296 dest = SLOT(newmbuflabel); 1297 1298 mac_biba_copy_single(source, dest); 1299} 1300 1301static int 1302mac_biba_fragment_match(struct mbuf *fragment, struct label *fragmentlabel, 1303 struct ipq *ipq, struct label *ipqlabel) 1304{ 1305 struct mac_biba *a, *b; 1306 1307 a = SLOT(ipqlabel); 1308 b = SLOT(fragmentlabel); 1309 1310 return (mac_biba_equal_single(a, b)); 1311} 1312 1313static void 1314mac_biba_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet, 1315 struct label *ifnetlabel, struct label *newlabel) 1316{ 1317 struct mac_biba *source, *dest; 1318 1319 source = SLOT(newlabel); 1320 dest = SLOT(ifnetlabel); 1321 1322 mac_biba_copy(source, dest); 1323} 1324 1325static void 1326mac_biba_update_ipq(struct mbuf *fragment, struct label *fragmentlabel, 1327 struct ipq *ipq, struct label *ipqlabel) 1328{ 1329 1330 /* NOOP: we only accept matching labels, so no need to update */ 1331} 1332 1333/* 1334 * Labeling event operations: processes. 1335 */ 1336static void 1337mac_biba_create_cred(struct ucred *cred_parent, struct ucred *cred_child) 1338{ 1339 struct mac_biba *source, *dest; 1340 1341 source = SLOT(&cred_parent->cr_label); 1342 dest = SLOT(&cred_child->cr_label); 1343 1344 mac_biba_copy_single(source, dest); 1345 mac_biba_copy_range(source, dest); 1346} 1347 1348static void 1349mac_biba_create_proc0(struct ucred *cred) 1350{ 1351 struct mac_biba *dest; 1352 1353 dest = SLOT(&cred->cr_label); 1354 1355 mac_biba_set_single(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL); 1356 mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL, 1357 MAC_BIBA_TYPE_HIGH, 0, NULL); 1358} 1359 1360static void 1361mac_biba_create_proc1(struct ucred *cred) 1362{ 1363 struct mac_biba *dest; 1364 1365 dest = SLOT(&cred->cr_label); 1366 1367 mac_biba_set_single(dest, MAC_BIBA_TYPE_HIGH, 0, NULL); 1368 mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL, 1369 MAC_BIBA_TYPE_HIGH, 0, NULL); 1370} 1371 1372static void 1373mac_biba_relabel_cred(struct ucred *cred, struct label *newlabel) 1374{ 1375 struct mac_biba *source, *dest; 1376 1377 source = SLOT(newlabel); 1378 dest = SLOT(&cred->cr_label); 1379 1380 mac_biba_copy(source, dest); 1381} 1382 1383/* 1384 * Access control checks. 1385 */ 1386static int 1387mac_biba_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel, 1388 struct ifnet *ifnet, struct label *ifnetlabel) 1389{ 1390 struct mac_biba *a, *b; 1391 1392 if (!mac_biba_enabled) 1393 return (0); 1394 1395 a = SLOT(bpflabel); 1396 b = SLOT(ifnetlabel); 1397 1398 if (mac_biba_equal_single(a, b)) 1399 return (0); 1400 return (EACCES); 1401} 1402 1403static int 1404mac_biba_check_cred_relabel(struct ucred *cred, struct label *newlabel) 1405{ 1406 struct mac_biba *subj, *new; 1407 int error; 1408 1409 subj = SLOT(&cred->cr_label); 1410 new = SLOT(newlabel); 1411 1412 /* 1413 * If there is a Biba label update for the credential, it may 1414 * be an update of the single, range, or both. 1415 */ 1416 error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH); 1417 if (error) 1418 return (error); 1419 1420 /* 1421 * If the Biba label is to be changed, authorize as appropriate. 1422 */ 1423 if (new->mb_flags & MAC_BIBA_FLAGS_BOTH) { 1424 /* 1425 * If the change request modifies both the Biba label 1426 * single and range, check that the new single will be 1427 * in the new range. 1428 */ 1429 if ((new->mb_flags & MAC_BIBA_FLAGS_BOTH) == 1430 MAC_BIBA_FLAGS_BOTH && 1431 !mac_biba_single_in_range(new, new)) 1432 return (EINVAL); 1433 1434 /* 1435 * To change the Biba single label on a credential, the 1436 * new single label must be in the current range. 1437 */ 1438 if (new->mb_flags & MAC_BIBA_FLAG_SINGLE && 1439 !mac_biba_single_in_range(new, subj)) 1440 return (EPERM); 1441 1442 /* 1443 * To change the Biba range on a credential, the new 1444 * range label must be in the current range. 1445 */ 1446 if (new->mb_flags & MAC_BIBA_FLAG_RANGE && 1447 !mac_biba_range_in_range(new, subj)) 1448 return (EPERM); 1449 1450 /* 1451 * To have EQUAL in any component of the new credential 1452 * Biba label, the subject must already have EQUAL in 1453 * their label. 1454 */ 1455 if (mac_biba_contains_equal(new)) { 1456 error = mac_biba_subject_privileged(subj); 1457 if (error) 1458 return (error); 1459 } 1460 } 1461 1462 return (0); 1463} 1464 1465static int 1466mac_biba_check_cred_visible(struct ucred *u1, struct ucred *u2) 1467{ 1468 struct mac_biba *subj, *obj; 1469 1470 if (!mac_biba_enabled) 1471 return (0); 1472 1473 subj = SLOT(&u1->cr_label); 1474 obj = SLOT(&u2->cr_label); 1475 1476 /* XXX: range */ 1477 if (!mac_biba_dominate_single(obj, subj)) 1478 return (ESRCH); 1479 1480 return (0); 1481} 1482 1483static int 1484mac_biba_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet, 1485 struct label *ifnetlabel, struct label *newlabel) 1486{ 1487 struct mac_biba *subj, *new; 1488 int error; 1489 1490 subj = SLOT(&cred->cr_label); 1491 new = SLOT(newlabel); 1492 1493 /* 1494 * If there is a Biba label update for the interface, it may 1495 * be an update of the single, range, or both. 1496 */ 1497 error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH); 1498 if (error) 1499 return (error); 1500 1501 /* 1502 * Relabling network interfaces requires Biba privilege. 1503 */ 1504 error = mac_biba_subject_privileged(subj); 1505 if (error) 1506 return (error); 1507 1508 /* 1509 * If the Biba label is to be changed, authorize as appropriate. 1510 */ 1511 if (new->mb_flags & MAC_BIBA_FLAGS_BOTH) { 1512 /* 1513 * Rely on the traditional superuser status for the Biba 1514 * interface relabel requirements. XXXMAC: This will go 1515 * away. 1516 */ 1517 error = suser_cred(cred, 0); 1518 if (error) 1519 return (EPERM); 1520 1521 /* 1522 * XXXMAC: Additional consistency tests regarding the single 1523 * and the range of the new label might be performed here. 1524 */ 1525 } 1526 1527 return (0); 1528} 1529 1530static int 1531mac_biba_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel, 1532 struct mbuf *m, struct label *mbuflabel) 1533{ 1534 struct mac_biba *p, *i; 1535 1536 if (!mac_biba_enabled) 1537 return (0); 1538 1539 p = SLOT(mbuflabel); 1540 i = SLOT(ifnetlabel); 1541 1542 return (mac_biba_single_in_range(p, i) ? 0 : EACCES); 1543} 1544 1545static int 1546mac_biba_check_kld_load(struct ucred *cred, struct vnode *vp, 1547 struct label *label) 1548{ 1549 struct mac_biba *subj, *obj; 1550 int error; 1551 1552 if (!mac_biba_enabled) 1553 return (0); 1554 1555 subj = SLOT(&cred->cr_label); 1556 1557 error = mac_biba_subject_privileged(subj); 1558 if (error) 1559 return (error); 1560 1561 obj = SLOT(label); 1562 if (!mac_biba_high_single(obj)) 1563 return (EACCES); 1564 1565 return (0); 1566} 1567 1568 1569static int 1570mac_biba_check_kld_unload(struct ucred *cred) 1571{ 1572 struct mac_biba *subj; 1573 1574 if (!mac_biba_enabled) 1575 return (0); 1576 1577 subj = SLOT(&cred->cr_label); 1578 1579 return (mac_biba_subject_privileged(subj)); 1580} 1581 1582static int 1583mac_biba_check_mount_stat(struct ucred *cred, struct mount *mp, 1584 struct label *mntlabel) 1585{ 1586 struct mac_biba *subj, *obj; 1587 1588 if (!mac_biba_enabled) 1589 return (0); 1590 1591 subj = SLOT(&cred->cr_label); 1592 obj = SLOT(mntlabel); 1593 1594 if (!mac_biba_dominate_single(obj, subj)) 1595 return (EACCES); 1596 1597 return (0); 1598} 1599 1600static int 1601mac_biba_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, 1602 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data) 1603{ 1604 1605 if(!mac_biba_enabled) 1606 return (0); 1607 1608 /* XXX: This will be implemented soon... */ 1609 1610 return (0); 1611} 1612 1613static int 1614mac_biba_check_pipe_poll(struct ucred *cred, struct pipe *pipe, 1615 struct label *pipelabel) 1616{ 1617 struct mac_biba *subj, *obj; 1618 1619 if (!mac_biba_enabled) 1620 return (0); 1621 1622 subj = SLOT(&cred->cr_label); 1623 obj = SLOT((pipelabel)); 1624 1625 if (!mac_biba_dominate_single(obj, subj)) 1626 return (EACCES); 1627 1628 return (0); 1629} 1630 1631static int 1632mac_biba_check_pipe_read(struct ucred *cred, struct pipe *pipe, 1633 struct label *pipelabel) 1634{ 1635 struct mac_biba *subj, *obj; 1636 1637 if (!mac_biba_enabled) 1638 return (0); 1639 1640 subj = SLOT(&cred->cr_label); 1641 obj = SLOT((pipelabel)); 1642 1643 if (!mac_biba_dominate_single(obj, subj)) 1644 return (EACCES); 1645 1646 return (0); 1647} 1648 1649static int 1650mac_biba_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 1651 struct label *pipelabel, struct label *newlabel) 1652{ 1653 struct mac_biba *subj, *obj, *new; 1654 int error; 1655 1656 new = SLOT(newlabel); 1657 subj = SLOT(&cred->cr_label); 1658 obj = SLOT(pipelabel); 1659 1660 /* 1661 * If there is a Biba label update for a pipe, it must be a 1662 * single update. 1663 */ 1664 error = biba_atmostflags(new, MAC_BIBA_FLAG_SINGLE); 1665 if (error) 1666 return (error); 1667 1668 /* 1669 * To perform a relabel of a pipe (Biba label or not), Biba must 1670 * authorize the relabel. 1671 */ 1672 if (!mac_biba_single_in_range(obj, subj)) 1673 return (EPERM); 1674 1675 /* 1676 * If the Biba label is to be changed, authorize as appropriate. 1677 */ 1678 if (new->mb_flags & MAC_BIBA_FLAG_SINGLE) { 1679 /* 1680 * To change the Biba label on a pipe, the new pipe label 1681 * must be in the subject range. 1682 */ 1683 if (!mac_biba_single_in_range(new, subj)) 1684 return (EPERM); 1685 1686 /* 1687 * To change the Biba label on a pipe to be EQUAL, the 1688 * subject must have appropriate privilege. 1689 */ 1690 if (mac_biba_contains_equal(new)) { 1691 error = mac_biba_subject_privileged(subj); 1692 if (error) 1693 return (error); 1694 } 1695 } 1696 1697 return (0); 1698} 1699 1700static int 1701mac_biba_check_pipe_stat(struct ucred *cred, struct pipe *pipe, 1702 struct label *pipelabel) 1703{ 1704 struct mac_biba *subj, *obj; 1705 1706 if (!mac_biba_enabled) 1707 return (0); 1708 1709 subj = SLOT(&cred->cr_label); 1710 obj = SLOT((pipelabel)); 1711 1712 if (!mac_biba_dominate_single(obj, subj)) 1713 return (EACCES); 1714 1715 return (0); 1716} 1717 1718static int 1719mac_biba_check_pipe_write(struct ucred *cred, struct pipe *pipe, 1720 struct label *pipelabel) 1721{ 1722 struct mac_biba *subj, *obj; 1723 1724 if (!mac_biba_enabled) 1725 return (0); 1726 1727 subj = SLOT(&cred->cr_label); 1728 obj = SLOT((pipelabel)); 1729 1730 if (!mac_biba_dominate_single(subj, obj)) 1731 return (EACCES); 1732 1733 return (0); 1734} 1735 1736static int 1737mac_biba_check_proc_debug(struct ucred *cred, struct proc *proc) 1738{ 1739 struct mac_biba *subj, *obj; 1740 1741 if (!mac_biba_enabled) 1742 return (0); 1743 1744 subj = SLOT(&cred->cr_label); 1745 obj = SLOT(&proc->p_ucred->cr_label); 1746 1747 /* XXX: range checks */ 1748 if (!mac_biba_dominate_single(obj, subj)) 1749 return (ESRCH); 1750 if (!mac_biba_dominate_single(subj, obj)) 1751 return (EACCES); 1752 1753 return (0); 1754} 1755 1756static int 1757mac_biba_check_proc_sched(struct ucred *cred, struct proc *proc) 1758{ 1759 struct mac_biba *subj, *obj; 1760 1761 if (!mac_biba_enabled) 1762 return (0); 1763 1764 subj = SLOT(&cred->cr_label); 1765 obj = SLOT(&proc->p_ucred->cr_label); 1766 1767 /* XXX: range checks */ 1768 if (!mac_biba_dominate_single(obj, subj)) 1769 return (ESRCH); 1770 if (!mac_biba_dominate_single(subj, obj)) 1771 return (EACCES); 1772 1773 return (0); 1774} 1775 1776static int 1777mac_biba_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 1778{ 1779 struct mac_biba *subj, *obj; 1780 1781 if (!mac_biba_enabled) 1782 return (0); 1783 1784 subj = SLOT(&cred->cr_label); 1785 obj = SLOT(&proc->p_ucred->cr_label); 1786 1787 /* XXX: range checks */ 1788 if (!mac_biba_dominate_single(obj, subj)) 1789 return (ESRCH); 1790 if (!mac_biba_dominate_single(subj, obj)) 1791 return (EACCES); 1792 1793 return (0); 1794} 1795 1796static int 1797mac_biba_check_socket_deliver(struct socket *so, struct label *socketlabel, 1798 struct mbuf *m, struct label *mbuflabel) 1799{ 1800 struct mac_biba *p, *s; 1801 1802 if (!mac_biba_enabled) 1803 return (0); 1804 1805 p = SLOT(mbuflabel); 1806 s = SLOT(socketlabel); 1807 1808 return (mac_biba_equal_single(p, s) ? 0 : EACCES); 1809} 1810 1811static int 1812mac_biba_check_socket_relabel(struct ucred *cred, struct socket *so, 1813 struct label *socketlabel, struct label *newlabel) 1814{ 1815 struct mac_biba *subj, *obj, *new; 1816 int error; 1817 1818 new = SLOT(newlabel); 1819 subj = SLOT(&cred->cr_label); 1820 obj = SLOT(socketlabel); 1821 1822 /* 1823 * If there is a Biba label update for the socket, it may be 1824 * an update of single. 1825 */ 1826 error = biba_atmostflags(new, MAC_BIBA_FLAG_SINGLE); 1827 if (error) 1828 return (error); 1829 1830 /* 1831 * To relabel a socket, the old socket single must be in the subject 1832 * range. 1833 */ 1834 if (!mac_biba_single_in_range(obj, subj)) 1835 return (EPERM); 1836 1837 /* 1838 * If the Biba label is to be changed, authorize as appropriate. 1839 */ 1840 if (new->mb_flags & MAC_BIBA_FLAG_SINGLE) { 1841 /* 1842 * To relabel a socket, the new socket single must be in 1843 * the subject range. 1844 */ 1845 if (!mac_biba_single_in_range(new, subj)) 1846 return (EPERM); 1847 1848 /* 1849 * To change the Biba label on the socket to contain EQUAL, 1850 * the subject must have appropriate privilege. 1851 */ 1852 if (mac_biba_contains_equal(new)) { 1853 error = mac_biba_subject_privileged(subj); 1854 if (error) 1855 return (error); 1856 } 1857 } 1858 1859 return (0); 1860} 1861 1862static int 1863mac_biba_check_socket_visible(struct ucred *cred, struct socket *socket, 1864 struct label *socketlabel) 1865{ 1866 struct mac_biba *subj, *obj; 1867 1868 if (!mac_biba_enabled) 1869 return (0); 1870 1871 subj = SLOT(&cred->cr_label); 1872 obj = SLOT(socketlabel); 1873 1874 if (!mac_biba_dominate_single(obj, subj)) 1875 return (ENOENT); 1876 1877 return (0); 1878} 1879 1880static int 1881mac_biba_check_sysarch_ioperm(struct ucred *cred) 1882{ 1883 struct mac_biba *subj; 1884 int error; 1885 1886 if (!mac_biba_enabled) 1887 return (0); 1888 1889 subj = SLOT(&cred->cr_label); 1890 1891 error = mac_biba_subject_privileged(subj); 1892 if (error) 1893 return (error); 1894 1895 return (0); 1896} 1897 1898static int 1899mac_biba_check_system_acct(struct ucred *cred, struct vnode *vp, 1900 struct label *label) 1901{ 1902 struct mac_biba *subj, *obj; 1903 int error; 1904 1905 if (!mac_biba_enabled) 1906 return (0); 1907 1908 subj = SLOT(&cred->cr_label); 1909 1910 error = mac_biba_subject_privileged(subj); 1911 if (error) 1912 return (error); 1913 1914 if (label == NULL) 1915 return (0); 1916 1917 obj = SLOT(label); 1918 if (!mac_biba_high_single(obj)) 1919 return (EACCES); 1920 1921 return (0); 1922} 1923 1924static int 1925mac_biba_check_system_settime(struct ucred *cred) 1926{ 1927 struct mac_biba *subj; 1928 int error; 1929 1930 if (!mac_biba_enabled) 1931 return (0); 1932 1933 subj = SLOT(&cred->cr_label); 1934 1935 error = mac_biba_subject_privileged(subj); 1936 if (error) 1937 return (error); 1938 1939 return (0); 1940} 1941 1942static int 1943mac_biba_check_system_swapon(struct ucred *cred, struct vnode *vp, 1944 struct label *label) 1945{ 1946 struct mac_biba *subj, *obj; 1947 int error; 1948 1949 if (!mac_biba_enabled) 1950 return (0); 1951 1952 subj = SLOT(&cred->cr_label); 1953 obj = SLOT(label); 1954 1955 error = mac_biba_subject_privileged(subj); 1956 if (error) 1957 return (error); 1958 1959 if (!mac_biba_high_single(obj)) 1960 return (EACCES); 1961 1962 return (0); 1963} 1964 1965static int 1966mac_biba_check_system_swapoff(struct ucred *cred, struct vnode *vp, 1967 struct label *label) 1968{ 1969 struct mac_biba *subj, *obj; 1970 int error; 1971 1972 if (!mac_biba_enabled) 1973 return (0); 1974 1975 subj = SLOT(&cred->cr_label); 1976 obj = SLOT(label); 1977 1978 error = mac_biba_subject_privileged(subj); 1979 if (error) 1980 return (error); 1981 1982 return (0); 1983} 1984 1985static int 1986mac_biba_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 1987 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 1988{ 1989 struct mac_biba *subj; 1990 int error; 1991 1992 if (!mac_biba_enabled) 1993 return (0); 1994 1995 subj = SLOT(&cred->cr_label); 1996 1997 /* 1998 * In general, treat sysctl variables as biba/high, but also 1999 * require privilege to change them, since they are a 2000 * communications channel between grades. Exempt MIB 2001 * queries from this due to undocmented sysctl magic. 2002 * XXXMAC: This probably requires some more review. 2003 */ 2004 if (new != NULL) { 2005 if (namelen > 0 && name[0] == 0) 2006 return (0); 2007 2008 if (!mac_biba_subject_dominate_high(subj)) 2009 return (EACCES); 2010 2011 error = mac_biba_subject_privileged(subj); 2012 if (error) 2013 return (error); 2014 } 2015 2016 return (0); 2017} 2018 2019static int 2020mac_biba_check_vnode_chdir(struct ucred *cred, struct vnode *dvp, 2021 struct label *dlabel) 2022{ 2023 struct mac_biba *subj, *obj; 2024 2025 if (!mac_biba_enabled) 2026 return (0); 2027 2028 subj = SLOT(&cred->cr_label); 2029 obj = SLOT(dlabel); 2030 2031 if (!mac_biba_dominate_single(obj, subj)) 2032 return (EACCES); 2033 2034 return (0); 2035} 2036 2037static int 2038mac_biba_check_vnode_chroot(struct ucred *cred, struct vnode *dvp, 2039 struct label *dlabel) 2040{ 2041 struct mac_biba *subj, *obj; 2042 2043 if (!mac_biba_enabled) 2044 return (0); 2045 2046 subj = SLOT(&cred->cr_label); 2047 obj = SLOT(dlabel); 2048 2049 if (!mac_biba_dominate_single(obj, subj)) 2050 return (EACCES); 2051 2052 return (0); 2053} 2054 2055static int 2056mac_biba_check_vnode_create(struct ucred *cred, struct vnode *dvp, 2057 struct label *dlabel, struct componentname *cnp, struct vattr *vap) 2058{ 2059 struct mac_biba *subj, *obj; 2060 2061 if (!mac_biba_enabled) 2062 return (0); 2063 2064 subj = SLOT(&cred->cr_label); 2065 obj = SLOT(dlabel); 2066 2067 if (!mac_biba_dominate_single(subj, obj)) 2068 return (EACCES); 2069 2070 return (0); 2071} 2072 2073static int 2074mac_biba_check_vnode_delete(struct ucred *cred, struct vnode *dvp, 2075 struct label *dlabel, struct vnode *vp, struct label *label, 2076 struct componentname *cnp) 2077{ 2078 struct mac_biba *subj, *obj; 2079 2080 if (!mac_biba_enabled) 2081 return (0); 2082 2083 subj = SLOT(&cred->cr_label); 2084 obj = SLOT(dlabel); 2085 2086 if (!mac_biba_dominate_single(subj, obj)) 2087 return (EACCES); 2088 2089 obj = SLOT(label); 2090 2091 if (!mac_biba_dominate_single(subj, obj)) 2092 return (EACCES); 2093 2094 return (0); 2095} 2096 2097static int 2098mac_biba_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 2099 struct label *label, acl_type_t type) 2100{ 2101 struct mac_biba *subj, *obj; 2102 2103 if (!mac_biba_enabled) 2104 return (0); 2105 2106 subj = SLOT(&cred->cr_label); 2107 obj = SLOT(label); 2108 2109 if (!mac_biba_dominate_single(subj, obj)) 2110 return (EACCES); 2111 2112 return (0); 2113} 2114 2115static int 2116mac_biba_check_vnode_exec(struct ucred *cred, struct vnode *vp, 2117 struct label *label, struct image_params *imgp, 2118 struct label *execlabel) 2119{ 2120 struct mac_biba *subj, *obj, *exec; 2121 int error; 2122 2123 if (execlabel != NULL) { 2124 /* 2125 * We currently don't permit labels to be changed at 2126 * exec-time as part of Biba, so disallow non-NULL 2127 * Biba label elements in the execlabel. 2128 */ 2129 exec = SLOT(execlabel); 2130 error = biba_atmostflags(exec, 0); 2131 if (error) 2132 return (error); 2133 } 2134 2135 if (!mac_biba_enabled) 2136 return (0); 2137 2138 subj = SLOT(&cred->cr_label); 2139 obj = SLOT(label); 2140 2141 if (!mac_biba_dominate_single(obj, subj)) 2142 return (EACCES); 2143 2144 return (0); 2145} 2146 2147static int 2148mac_biba_check_vnode_getacl(struct ucred *cred, struct vnode *vp, 2149 struct label *label, acl_type_t type) 2150{ 2151 struct mac_biba *subj, *obj; 2152 2153 if (!mac_biba_enabled) 2154 return (0); 2155 2156 subj = SLOT(&cred->cr_label); 2157 obj = SLOT(label); 2158 2159 if (!mac_biba_dominate_single(obj, subj)) 2160 return (EACCES); 2161 2162 return (0); 2163} 2164 2165static int 2166mac_biba_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 2167 struct label *label, int attrnamespace, const char *name, struct uio *uio) 2168{ 2169 struct mac_biba *subj, *obj; 2170 2171 if (!mac_biba_enabled) 2172 return (0); 2173 2174 subj = SLOT(&cred->cr_label); 2175 obj = SLOT(label); 2176 2177 if (!mac_biba_dominate_single(obj, subj)) 2178 return (EACCES); 2179 2180 return (0); 2181} 2182 2183static int 2184mac_biba_check_vnode_link(struct ucred *cred, struct vnode *dvp, 2185 struct label *dlabel, struct vnode *vp, struct label *label, 2186 struct componentname *cnp) 2187{ 2188 struct mac_biba *subj, *obj; 2189 2190 if (!mac_biba_enabled) 2191 return (0); 2192 2193 subj = SLOT(&cred->cr_label); 2194 obj = SLOT(dlabel); 2195 2196 if (!mac_biba_dominate_single(subj, obj)) 2197 return (EACCES); 2198 2199 obj = SLOT(label); 2200 2201 if (!mac_biba_dominate_single(subj, obj)) 2202 return (EACCES); 2203 2204 return (0); 2205} 2206 2207static int 2208mac_biba_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 2209 struct label *dlabel, struct componentname *cnp) 2210{ 2211 struct mac_biba *subj, *obj; 2212 2213 if (!mac_biba_enabled) 2214 return (0); 2215 2216 subj = SLOT(&cred->cr_label); 2217 obj = SLOT(dlabel); 2218 2219 if (!mac_biba_dominate_single(obj, subj)) 2220 return (EACCES); 2221 2222 return (0); 2223} 2224 2225static int 2226mac_biba_check_vnode_mmap(struct ucred *cred, struct vnode *vp, 2227 struct label *label, int prot) 2228{ 2229 struct mac_biba *subj, *obj; 2230 2231 /* 2232 * Rely on the use of open()-time protections to handle 2233 * non-revocation cases. 2234 */ 2235 if (!mac_biba_enabled || !revocation_enabled) 2236 return (0); 2237 2238 subj = SLOT(&cred->cr_label); 2239 obj = SLOT(label); 2240 2241 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 2242 if (!mac_biba_dominate_single(obj, subj)) 2243 return (EACCES); 2244 } 2245 if (prot & VM_PROT_WRITE) { 2246 if (!mac_biba_dominate_single(subj, obj)) 2247 return (EACCES); 2248 } 2249 2250 return (0); 2251} 2252 2253static int 2254mac_biba_check_vnode_open(struct ucred *cred, struct vnode *vp, 2255 struct label *vnodelabel, int acc_mode) 2256{ 2257 struct mac_biba *subj, *obj; 2258 2259 if (!mac_biba_enabled) 2260 return (0); 2261 2262 subj = SLOT(&cred->cr_label); 2263 obj = SLOT(vnodelabel); 2264 2265 /* XXX privilege override for admin? */ 2266 if (acc_mode & (VREAD | VEXEC | VSTAT)) { 2267 if (!mac_biba_dominate_single(obj, subj)) 2268 return (EACCES); 2269 } 2270 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) { 2271 if (!mac_biba_dominate_single(subj, obj)) 2272 return (EACCES); 2273 } 2274 2275 return (0); 2276} 2277 2278static int 2279mac_biba_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 2280 struct vnode *vp, struct label *label) 2281{ 2282 struct mac_biba *subj, *obj; 2283 2284 if (!mac_biba_enabled || !revocation_enabled) 2285 return (0); 2286 2287 subj = SLOT(&active_cred->cr_label); 2288 obj = SLOT(label); 2289 2290 if (!mac_biba_dominate_single(obj, subj)) 2291 return (EACCES); 2292 2293 return (0); 2294} 2295 2296static int 2297mac_biba_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 2298 struct vnode *vp, struct label *label) 2299{ 2300 struct mac_biba *subj, *obj; 2301 2302 if (!mac_biba_enabled || !revocation_enabled) 2303 return (0); 2304 2305 subj = SLOT(&active_cred->cr_label); 2306 obj = SLOT(label); 2307 2308 if (!mac_biba_dominate_single(obj, subj)) 2309 return (EACCES); 2310 2311 return (0); 2312} 2313 2314static int 2315mac_biba_check_vnode_readdir(struct ucred *cred, struct vnode *dvp, 2316 struct label *dlabel) 2317{ 2318 struct mac_biba *subj, *obj; 2319 2320 if (!mac_biba_enabled) 2321 return (0); 2322 2323 subj = SLOT(&cred->cr_label); 2324 obj = SLOT(dlabel); 2325 2326 if (!mac_biba_dominate_single(obj, subj)) 2327 return (EACCES); 2328 2329 return (0); 2330} 2331 2332static int 2333mac_biba_check_vnode_readlink(struct ucred *cred, struct vnode *vp, 2334 struct label *label) 2335{ 2336 struct mac_biba *subj, *obj; 2337 2338 if (!mac_biba_enabled) 2339 return (0); 2340 2341 subj = SLOT(&cred->cr_label); 2342 obj = SLOT(label); 2343 2344 if (!mac_biba_dominate_single(obj, subj)) 2345 return (EACCES); 2346 2347 return (0); 2348} 2349 2350static int 2351mac_biba_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 2352 struct label *vnodelabel, struct label *newlabel) 2353{ 2354 struct mac_biba *old, *new, *subj; 2355 int error; 2356 2357 old = SLOT(vnodelabel); 2358 new = SLOT(newlabel); 2359 subj = SLOT(&cred->cr_label); 2360 2361 /* 2362 * If there is a Biba label update for the vnode, it must be a 2363 * single label. 2364 */ 2365 error = biba_atmostflags(new, MAC_BIBA_FLAG_SINGLE); 2366 if (error) 2367 return (error); 2368 2369 /* 2370 * To perform a relabel of the vnode (Biba label or not), Biba must 2371 * authorize the relabel. 2372 */ 2373 if (!mac_biba_single_in_range(old, subj)) 2374 return (EPERM); 2375 2376 /* 2377 * If the Biba label is to be changed, authorize as appropriate. 2378 */ 2379 if (new->mb_flags & MAC_BIBA_FLAG_SINGLE) { 2380 /* 2381 * To change the Biba label on a vnode, the new vnode label 2382 * must be in the subject range. 2383 */ 2384 if (!mac_biba_single_in_range(new, subj)) 2385 return (EPERM); 2386 2387 /* 2388 * To change the Biba label on the vnode to be EQUAL, 2389 * the subject must have appropriate privilege. 2390 */ 2391 if (mac_biba_contains_equal(new)) { 2392 error = mac_biba_subject_privileged(subj); 2393 if (error) 2394 return (error); 2395 } 2396 } 2397 2398 return (0); 2399} 2400 2401static int 2402mac_biba_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 2403 struct label *dlabel, struct vnode *vp, struct label *label, 2404 struct componentname *cnp) 2405{ 2406 struct mac_biba *subj, *obj; 2407 2408 if (!mac_biba_enabled) 2409 return (0); 2410 2411 subj = SLOT(&cred->cr_label); 2412 obj = SLOT(dlabel); 2413 2414 if (!mac_biba_dominate_single(subj, obj)) 2415 return (EACCES); 2416 2417 obj = SLOT(label); 2418 2419 if (!mac_biba_dominate_single(subj, obj)) 2420 return (EACCES); 2421 2422 return (0); 2423} 2424 2425static int 2426mac_biba_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 2427 struct label *dlabel, struct vnode *vp, struct label *label, int samedir, 2428 struct componentname *cnp) 2429{ 2430 struct mac_biba *subj, *obj; 2431 2432 if (!mac_biba_enabled) 2433 return (0); 2434 2435 subj = SLOT(&cred->cr_label); 2436 obj = SLOT(dlabel); 2437 2438 if (!mac_biba_dominate_single(subj, obj)) 2439 return (EACCES); 2440 2441 if (vp != NULL) { 2442 obj = SLOT(label); 2443 2444 if (!mac_biba_dominate_single(subj, obj)) 2445 return (EACCES); 2446 } 2447 2448 return (0); 2449} 2450 2451static int 2452mac_biba_check_vnode_revoke(struct ucred *cred, struct vnode *vp, 2453 struct label *label) 2454{ 2455 struct mac_biba *subj, *obj; 2456 2457 if (!mac_biba_enabled) 2458 return (0); 2459 2460 subj = SLOT(&cred->cr_label); 2461 obj = SLOT(label); 2462 2463 if (!mac_biba_dominate_single(subj, obj)) 2464 return (EACCES); 2465 2466 return (0); 2467} 2468 2469static int 2470mac_biba_check_vnode_setacl(struct ucred *cred, struct vnode *vp, 2471 struct label *label, acl_type_t type, struct acl *acl) 2472{ 2473 struct mac_biba *subj, *obj; 2474 2475 if (!mac_biba_enabled) 2476 return (0); 2477 2478 subj = SLOT(&cred->cr_label); 2479 obj = SLOT(label); 2480 2481 if (!mac_biba_dominate_single(subj, obj)) 2482 return (EACCES); 2483 2484 return (0); 2485} 2486 2487static int 2488mac_biba_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 2489 struct label *vnodelabel, int attrnamespace, const char *name, 2490 struct uio *uio) 2491{ 2492 struct mac_biba *subj, *obj; 2493 2494 if (!mac_biba_enabled) 2495 return (0); 2496 2497 subj = SLOT(&cred->cr_label); 2498 obj = SLOT(vnodelabel); 2499 2500 if (!mac_biba_dominate_single(subj, obj)) 2501 return (EACCES); 2502 2503 /* XXX: protect the MAC EA in a special way? */ 2504 2505 return (0); 2506} 2507 2508static int 2509mac_biba_check_vnode_setflags(struct ucred *cred, struct vnode *vp, 2510 struct label *vnodelabel, u_long flags) 2511{ 2512 struct mac_biba *subj, *obj; 2513 2514 if (!mac_biba_enabled) 2515 return (0); 2516 2517 subj = SLOT(&cred->cr_label); 2518 obj = SLOT(vnodelabel); 2519 2520 if (!mac_biba_dominate_single(subj, obj)) 2521 return (EACCES); 2522 2523 return (0); 2524} 2525 2526static int 2527mac_biba_check_vnode_setmode(struct ucred *cred, struct vnode *vp, 2528 struct label *vnodelabel, mode_t mode) 2529{ 2530 struct mac_biba *subj, *obj; 2531 2532 if (!mac_biba_enabled) 2533 return (0); 2534 2535 subj = SLOT(&cred->cr_label); 2536 obj = SLOT(vnodelabel); 2537 2538 if (!mac_biba_dominate_single(subj, obj)) 2539 return (EACCES); 2540 2541 return (0); 2542} 2543 2544static int 2545mac_biba_check_vnode_setowner(struct ucred *cred, struct vnode *vp, 2546 struct label *vnodelabel, uid_t uid, gid_t gid) 2547{ 2548 struct mac_biba *subj, *obj; 2549 2550 if (!mac_biba_enabled) 2551 return (0); 2552 2553 subj = SLOT(&cred->cr_label); 2554 obj = SLOT(vnodelabel); 2555 2556 if (!mac_biba_dominate_single(subj, obj)) 2557 return (EACCES); 2558 2559 return (0); 2560} 2561 2562static int 2563mac_biba_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 2564 struct label *vnodelabel, struct timespec atime, struct timespec mtime) 2565{ 2566 struct mac_biba *subj, *obj; 2567 2568 if (!mac_biba_enabled) 2569 return (0); 2570 2571 subj = SLOT(&cred->cr_label); 2572 obj = SLOT(vnodelabel); 2573 2574 if (!mac_biba_dominate_single(subj, obj)) 2575 return (EACCES); 2576 2577 return (0); 2578} 2579 2580static int 2581mac_biba_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 2582 struct vnode *vp, struct label *vnodelabel) 2583{ 2584 struct mac_biba *subj, *obj; 2585 2586 if (!mac_biba_enabled) 2587 return (0); 2588 2589 subj = SLOT(&active_cred->cr_label); 2590 obj = SLOT(vnodelabel); 2591 2592 if (!mac_biba_dominate_single(obj, subj)) 2593 return (EACCES); 2594 2595 return (0); 2596} 2597 2598static int 2599mac_biba_check_vnode_write(struct ucred *active_cred, 2600 struct ucred *file_cred, struct vnode *vp, struct label *label) 2601{ 2602 struct mac_biba *subj, *obj; 2603 2604 if (!mac_biba_enabled || !revocation_enabled) 2605 return (0); 2606 2607 subj = SLOT(&active_cred->cr_label); 2608 obj = SLOT(label); 2609 2610 if (!mac_biba_dominate_single(subj, obj)) 2611 return (EACCES); 2612 2613 return (0); 2614} 2615 2616static struct mac_policy_ops mac_biba_ops = 2617{ 2618 .mpo_destroy = mac_biba_destroy, 2619 .mpo_init = mac_biba_init, 2620 .mpo_init_bpfdesc_label = mac_biba_init_label, 2621 .mpo_init_cred_label = mac_biba_init_label, 2622 .mpo_init_devfsdirent_label = mac_biba_init_label, 2623 .mpo_init_ifnet_label = mac_biba_init_label, 2624 .mpo_init_ipq_label = mac_biba_init_label_waitcheck, 2625 .mpo_init_mbuf_label = mac_biba_init_label_waitcheck, 2626 .mpo_init_mount_label = mac_biba_init_label, 2627 .mpo_init_mount_fs_label = mac_biba_init_label, 2628 .mpo_init_pipe_label = mac_biba_init_label, 2629 .mpo_init_socket_label = mac_biba_init_label_waitcheck, 2630 .mpo_init_socket_peer_label = mac_biba_init_label_waitcheck, 2631 .mpo_init_vnode_label = mac_biba_init_label, 2632 .mpo_destroy_bpfdesc_label = mac_biba_destroy_label, 2633 .mpo_destroy_cred_label = mac_biba_destroy_label, 2634 .mpo_destroy_devfsdirent_label = mac_biba_destroy_label, 2635 .mpo_destroy_ifnet_label = mac_biba_destroy_label, 2636 .mpo_destroy_ipq_label = mac_biba_destroy_label, 2637 .mpo_destroy_mbuf_label = mac_biba_destroy_label, 2638 .mpo_destroy_mount_label = mac_biba_destroy_label, 2639 .mpo_destroy_mount_fs_label = mac_biba_destroy_label, 2640 .mpo_destroy_pipe_label = mac_biba_destroy_label, 2641 .mpo_destroy_socket_label = mac_biba_destroy_label, 2642 .mpo_destroy_socket_peer_label = mac_biba_destroy_label, 2643 .mpo_destroy_vnode_label = mac_biba_destroy_label, 2644 .mpo_copy_pipe_label = mac_biba_copy_label, 2645 .mpo_copy_vnode_label = mac_biba_copy_label, 2646 .mpo_externalize_cred_label = mac_biba_externalize_label, 2647 .mpo_externalize_ifnet_label = mac_biba_externalize_label, 2648 .mpo_externalize_pipe_label = mac_biba_externalize_label, 2649 .mpo_externalize_socket_label = mac_biba_externalize_label, 2650 .mpo_externalize_socket_peer_label = mac_biba_externalize_label, 2651 .mpo_externalize_vnode_label = mac_biba_externalize_label, 2652 .mpo_internalize_cred_label = mac_biba_internalize_label, 2653 .mpo_internalize_ifnet_label = mac_biba_internalize_label, 2654 .mpo_internalize_pipe_label = mac_biba_internalize_label, 2655 .mpo_internalize_socket_label = mac_biba_internalize_label, 2656 .mpo_internalize_vnode_label = mac_biba_internalize_label, 2657 .mpo_create_devfs_device = mac_biba_create_devfs_device, 2658 .mpo_create_devfs_directory = mac_biba_create_devfs_directory, 2659 .mpo_create_devfs_symlink = mac_biba_create_devfs_symlink, 2660 .mpo_create_mount = mac_biba_create_mount, 2661 .mpo_create_root_mount = mac_biba_create_root_mount, 2662 .mpo_relabel_vnode = mac_biba_relabel_vnode, 2663 .mpo_update_devfsdirent = mac_biba_update_devfsdirent, 2664 .mpo_associate_vnode_devfs = mac_biba_associate_vnode_devfs, 2665 .mpo_associate_vnode_extattr = mac_biba_associate_vnode_extattr, 2666 .mpo_associate_vnode_singlelabel = mac_biba_associate_vnode_singlelabel, 2667 .mpo_create_vnode_extattr = mac_biba_create_vnode_extattr, 2668 .mpo_setlabel_vnode_extattr = mac_biba_setlabel_vnode_extattr, 2669 .mpo_create_mbuf_from_socket = mac_biba_create_mbuf_from_socket, 2670 .mpo_create_pipe = mac_biba_create_pipe, 2671 .mpo_create_socket = mac_biba_create_socket, 2672 .mpo_create_socket_from_socket = mac_biba_create_socket_from_socket, 2673 .mpo_relabel_pipe = mac_biba_relabel_pipe, 2674 .mpo_relabel_socket = mac_biba_relabel_socket, 2675 .mpo_set_socket_peer_from_mbuf = mac_biba_set_socket_peer_from_mbuf, 2676 .mpo_set_socket_peer_from_socket = mac_biba_set_socket_peer_from_socket, 2677 .mpo_create_bpfdesc = mac_biba_create_bpfdesc, 2678 .mpo_create_datagram_from_ipq = mac_biba_create_datagram_from_ipq, 2679 .mpo_create_fragment = mac_biba_create_fragment, 2680 .mpo_create_ifnet = mac_biba_create_ifnet, 2681 .mpo_create_ipq = mac_biba_create_ipq, 2682 .mpo_create_mbuf_from_mbuf = mac_biba_create_mbuf_from_mbuf, 2683 .mpo_create_mbuf_linklayer = mac_biba_create_mbuf_linklayer, 2684 .mpo_create_mbuf_from_bpfdesc = mac_biba_create_mbuf_from_bpfdesc, 2685 .mpo_create_mbuf_from_ifnet = mac_biba_create_mbuf_from_ifnet, 2686 .mpo_create_mbuf_multicast_encap = mac_biba_create_mbuf_multicast_encap, 2687 .mpo_create_mbuf_netlayer = mac_biba_create_mbuf_netlayer, 2688 .mpo_fragment_match = mac_biba_fragment_match, 2689 .mpo_relabel_ifnet = mac_biba_relabel_ifnet, 2690 .mpo_update_ipq = mac_biba_update_ipq, 2691 .mpo_create_cred = mac_biba_create_cred, 2692 .mpo_create_proc0 = mac_biba_create_proc0, 2693 .mpo_create_proc1 = mac_biba_create_proc1, 2694 .mpo_relabel_cred = mac_biba_relabel_cred, 2695 .mpo_check_bpfdesc_receive = mac_biba_check_bpfdesc_receive, 2696 .mpo_check_cred_relabel = mac_biba_check_cred_relabel, 2697 .mpo_check_cred_visible = mac_biba_check_cred_visible, 2698 .mpo_check_ifnet_relabel = mac_biba_check_ifnet_relabel, 2699 .mpo_check_ifnet_transmit = mac_biba_check_ifnet_transmit, 2700 .mpo_check_kld_load = mac_biba_check_kld_load, 2701 .mpo_check_kld_unload = mac_biba_check_kld_unload, 2702 .mpo_check_mount_stat = mac_biba_check_mount_stat, 2703 .mpo_check_pipe_ioctl = mac_biba_check_pipe_ioctl, 2704 .mpo_check_pipe_poll = mac_biba_check_pipe_poll, 2705 .mpo_check_pipe_read = mac_biba_check_pipe_read, 2706 .mpo_check_pipe_relabel = mac_biba_check_pipe_relabel, 2707 .mpo_check_pipe_stat = mac_biba_check_pipe_stat, 2708 .mpo_check_pipe_write = mac_biba_check_pipe_write, 2709 .mpo_check_proc_debug = mac_biba_check_proc_debug, 2710 .mpo_check_proc_sched = mac_biba_check_proc_sched, 2711 .mpo_check_proc_signal = mac_biba_check_proc_signal, 2712 .mpo_check_socket_deliver = mac_biba_check_socket_deliver, 2713 .mpo_check_socket_relabel = mac_biba_check_socket_relabel, 2714 .mpo_check_socket_visible = mac_biba_check_socket_visible, 2715 .mpo_check_sysarch_ioperm = mac_biba_check_sysarch_ioperm, 2716 .mpo_check_system_acct = mac_biba_check_system_acct, 2717 .mpo_check_system_settime = mac_biba_check_system_settime, 2718 .mpo_check_system_swapon = mac_biba_check_system_swapon, 2719 .mpo_check_system_swapoff = mac_biba_check_system_swapoff, 2720 .mpo_check_system_sysctl = mac_biba_check_system_sysctl, 2721 .mpo_check_vnode_access = mac_biba_check_vnode_open, 2722 .mpo_check_vnode_chdir = mac_biba_check_vnode_chdir, 2723 .mpo_check_vnode_chroot = mac_biba_check_vnode_chroot, 2724 .mpo_check_vnode_create = mac_biba_check_vnode_create, 2725 .mpo_check_vnode_delete = mac_biba_check_vnode_delete, 2726 .mpo_check_vnode_deleteacl = mac_biba_check_vnode_deleteacl, 2727 .mpo_check_vnode_exec = mac_biba_check_vnode_exec, 2728 .mpo_check_vnode_getacl = mac_biba_check_vnode_getacl, 2729 .mpo_check_vnode_getextattr = mac_biba_check_vnode_getextattr, 2730 .mpo_check_vnode_link = mac_biba_check_vnode_link, 2731 .mpo_check_vnode_lookup = mac_biba_check_vnode_lookup, 2732 .mpo_check_vnode_mmap = mac_biba_check_vnode_mmap, 2733 .mpo_check_vnode_mprotect = mac_biba_check_vnode_mmap, 2734 .mpo_check_vnode_open = mac_biba_check_vnode_open, 2735 .mpo_check_vnode_poll = mac_biba_check_vnode_poll, 2736 .mpo_check_vnode_read = mac_biba_check_vnode_read, 2737 .mpo_check_vnode_readdir = mac_biba_check_vnode_readdir, 2738 .mpo_check_vnode_readlink = mac_biba_check_vnode_readlink, 2739 .mpo_check_vnode_relabel = mac_biba_check_vnode_relabel, 2740 .mpo_check_vnode_rename_from = mac_biba_check_vnode_rename_from, 2741 .mpo_check_vnode_rename_to = mac_biba_check_vnode_rename_to, 2742 .mpo_check_vnode_revoke = mac_biba_check_vnode_revoke, 2743 .mpo_check_vnode_setacl = mac_biba_check_vnode_setacl, 2744 .mpo_check_vnode_setextattr = mac_biba_check_vnode_setextattr, 2745 .mpo_check_vnode_setflags = mac_biba_check_vnode_setflags, 2746 .mpo_check_vnode_setmode = mac_biba_check_vnode_setmode, 2747 .mpo_check_vnode_setowner = mac_biba_check_vnode_setowner, 2748 .mpo_check_vnode_setutimes = mac_biba_check_vnode_setutimes, 2749 .mpo_check_vnode_stat = mac_biba_check_vnode_stat, 2750 .mpo_check_vnode_write = mac_biba_check_vnode_write, 2751}; 2752 2753MAC_POLICY_SET(&mac_biba_ops, trustedbsd_mac_biba, "TrustedBSD MAC/Biba", 2754 MPC_LOADTIME_FLAG_NOTLATE, &mac_biba_slot); 2755