mac_vfs.c revision 107271
118334Speter/*- 290075Sobrien * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 390075Sobrien * Copyright (c) 2001 Ilmar S. Habibulin 418334Speter * Copyright (c) 2001, 2002 Networks Associates Technology, Inc. 590075Sobrien * All rights reserved. 618334Speter * 790075Sobrien * This software was developed by Robert Watson and Ilmar Habibulin for the 890075Sobrien * TrustedBSD Project. 990075Sobrien * 1090075Sobrien * This software was developed for the FreeBSD Project in part by Network 1118334Speter * Associates Laboratories, the Security Research Division of Network 1290075Sobrien * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 1390075Sobrien * as part of the DARPA CHATS research program. 1490075Sobrien * 1590075Sobrien * Redistribution and use in source and binary forms, with or without 1618334Speter * modification, are permitted provided that the following conditions 1718334Speter * are met: 1890075Sobrien * 1. Redistributions of source code must retain the above copyright 1990075Sobrien * notice, this list of conditions and the following disclaimer. 2090075Sobrien * 2. Redistributions in binary form must reproduce the above copyright 2118334Speter * notice, this list of conditions and the following disclaimer in the 2218334Speter * documentation and/or other materials provided with the distribution. 2318334Speter * 2450397Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2552284Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2652284Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2752284Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2890075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2952284Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3018334Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3118334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3290075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3318334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3490075Sobrien * SUCH DAMAGE. 3590075Sobrien * 3618334Speter * $FreeBSD: head/sys/security/mac/mac_vfs.c 107271 2002-11-26 17:11:57Z rwatson $ 3790075Sobrien */ 3890075Sobrien/* 3918334Speter * Developed by the TrustedBSD Project. 4018334Speter * 4190075Sobrien * Framework for extensible kernel access control. Kernel and userland 4290075Sobrien * interface to the framework, policy registration and composition. 4318334Speter */ 4418334Speter 4518334Speter#include "opt_mac.h" 4618334Speter#include "opt_devfs.h" 4718334Speter 4818334Speter#include <sys/param.h> 4918334Speter#include <sys/condvar.h> 5018334Speter#include <sys/extattr.h> 5118334Speter#include <sys/imgact.h> 5218334Speter#include <sys/kernel.h> 5390075Sobrien#include <sys/lock.h> 5418334Speter#include <sys/malloc.h> 5590075Sobrien#include <sys/mutex.h> 5618334Speter#include <sys/mac.h> 5718334Speter#include <sys/module.h> 5818334Speter#include <sys/proc.h> 5918334Speter#include <sys/systm.h> 6050397Sobrien#include <sys/sysproto.h> 6118334Speter#include <sys/sysent.h> 6218334Speter#include <sys/vnode.h> 6318334Speter#include <sys/mount.h> 6418334Speter#include <sys/file.h> 6518334Speter#include <sys/namei.h> 6618334Speter#include <sys/socket.h> 6718334Speter#include <sys/pipe.h> 6818334Speter#include <sys/socketvar.h> 6918334Speter#include <sys/sysctl.h> 7018334Speter 7118334Speter#include <vm/vm.h> 7218334Speter#include <vm/pmap.h> 7318334Speter#include <vm/vm_map.h> 7418334Speter#include <vm/vm_object.h> 7518334Speter 7618334Speter#include <sys/mac_policy.h> 7718334Speter 7818334Speter#include <fs/devfs/devfs.h> 7918334Speter 8018334Speter#include <net/bpfdesc.h> 8118334Speter#include <net/if.h> 8218334Speter#include <net/if_var.h> 8318334Speter 8418334Speter#include <netinet/in.h> 8518334Speter#include <netinet/ip_var.h> 8618334Speter 8718334Speter#ifdef MAC 8890075Sobrien 8990075Sobrien/* 9018334Speter * Declare that the kernel provides MAC support, version 1. This permits 9190075Sobrien * modules to refuse to be loaded if the necessary support isn't present, 9252284Sobrien * even if it's pre-boot. 9352284Sobrien */ 9452284SobrienMODULE_VERSION(kernel_mac_support, 1); 9590075Sobrien 9652284SobrienSYSCTL_DECL(_security); 9752284Sobrien 9852284SobrienSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 9990075Sobrien "TrustedBSD MAC policy controls"); 10090075Sobrien 10190075Sobrien#if MAC_MAX_POLICIES > 32 10290075Sobrien#error "MAC_MAX_POLICIES too large" 10318334Speter#endif 10490075Sobrien 10590075Sobrienstatic unsigned int mac_max_policies = MAC_MAX_POLICIES; 10690075Sobrienstatic unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1; 10790075SobrienSYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, 10890075Sobrien &mac_max_policies, 0, ""); 10990075Sobrien 11090075Sobrien/* 11190075Sobrien * Has the kernel started generating labeled objects yet? All read/write 11290075Sobrien * access to this variable is serialized during the boot process. Following 11390075Sobrien * the end of serialization, we don't update this flag; no locking. 11450397Sobrien */ 11590075Sobrienstatic int mac_late = 0; 11650397Sobrien 11790075Sobrien/* 11890075Sobrien * Warn about EA transactions only the first time they happen. 11990075Sobrien * Weak coherency, no locking. 12090075Sobrien */ 12118334Speterstatic int ea_warn_once = 0; 12218334Speter 12318334Speterstatic int mac_enforce_fs = 1; 12418334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 12518334Speter &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 12618334SpeterTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 12718334Speter 12818334Speterstatic int mac_enforce_kld = 1; 12918334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW, 13018334Speter &mac_enforce_kld, 0, "Enforce MAC policy on kld operations"); 13118334SpeterTUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld); 13218334Speter 13318334Speterstatic int mac_enforce_network = 1; 13418334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 13518334Speter &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 13618334SpeterTUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 13718334Speter 13818334Speterstatic int mac_enforce_pipe = 1; 13918334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 14018334Speter &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 14118334SpeterTUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 14218334Speter 14318334Speterstatic int mac_enforce_process = 1; 14418334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 14518334Speter &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 14618334SpeterTUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 14718334Speter 14818334Speterstatic int mac_enforce_socket = 1; 14918334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 15018334Speter &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 15118334SpeterTUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 15218334Speter 15318334Speterstatic int mac_enforce_system = 1; 15418334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW, 15518334Speter &mac_enforce_system, 0, "Enforce MAC policy on system operations"); 15618334SpeterTUNABLE_INT("security.mac.enforce_system", &mac_enforce_system); 15718334Speter 15818334Speterstatic int mac_enforce_vm = 1; 15918334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 16018334Speter &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 16118334SpeterTUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 16218334Speter 16318334Speterstatic int mac_mmap_revocation = 1; 16418334SpeterSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 16550397Sobrien &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 16618334Speter "relabel"); 16750397Sobrienstatic int mac_mmap_revocation_via_cow = 0; 16818334SpeterSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 16952284Sobrien &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 17018334Speter "copy-on-write semantics, or by removing all write access"); 17118334Speter 17218334Speter#ifdef MAC_DEBUG 17318334SpeterSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 17418334Speter "TrustedBSD MAC debug info"); 17518334Speter 17618334Speterstatic int mac_debug_label_fallback = 0; 17718334SpeterSYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 17818334Speter &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 17918334Speter "when label is corrupted."); 18018334SpeterTUNABLE_INT("security.mac.debug_label_fallback", 18118334Speter &mac_debug_label_fallback); 18218334Speter 18318334SpeterSYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 18418334Speter "TrustedBSD MAC object counters"); 18518334Speter 18618334Speterstatic unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 18718334Speter nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 18818334Speter nmacipqs, nmacpipes, nmacprocs; 18996263Sobrien 19096263SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 19196263Sobrien &nmacmbufs, 0, "number of mbufs in use"); 19296263SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 19396263Sobrien &nmaccreds, 0, "number of ucreds in use"); 19496263SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 19596263Sobrien &nmacifnets, 0, "number of ifnets in use"); 19618334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 19796263Sobrien &nmacipqs, 0, "number of ipqs in use"); 19896263SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 19918334Speter &nmacbpfdescs, 0, "number of bpfdescs in use"); 20018334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 20118334Speter &nmacsockets, 0, "number of sockets in use"); 20218334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 20318334Speter &nmacpipes, 0, "number of pipes in use"); 20450397SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD, 20518334Speter &nmacprocs, 0, "number of procs in use"); 20618334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 20718334Speter &nmacmounts, 0, "number of mounts in use"); 20818334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 20918334Speter &nmactemp, 0, "number of temporary labels in use"); 21050397SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 21118334Speter &nmacvnodes, 0, "number of vnodes in use"); 21218334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 21318334Speter &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 21418334Speter#endif 21552284Sobrien 21652284Sobrienstatic int error_select(int error1, int error2); 21752284Sobrienstatic int mac_policy_register(struct mac_policy_conf *mpc); 21852284Sobrienstatic int mac_policy_unregister(struct mac_policy_conf *mpc); 21952284Sobrien 22052284Sobrienstatic void mac_check_vnode_mmap_downgrade(struct ucred *cred, 22152284Sobrien struct vnode *vp, int *prot); 22252284Sobrienstatic void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 22352284Sobrien struct ucred *cred, struct vm_map *map); 22452284Sobrien 22552284Sobrienstatic void mac_destroy_socket_label(struct label *label); 22652284Sobrien 22752284Sobrienstatic int mac_setlabel_vnode_extattr(struct ucred *cred, 22852284Sobrien struct vnode *vp, struct label *intlabel); 22952284Sobrien 23052284SobrienMALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 23190075SobrienMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 23290075Sobrien 23390075Sobrien/* 23490075Sobrien * mac_policy_list stores the list of active policies. A busy count is 23552284Sobrien * maintained for the list, stored in mac_policy_busy. The busy count 23690075Sobrien * is protected by mac_policy_list_lock; the list may be modified only 23790075Sobrien * while the busy count is 0, requiring that the lock be held to 23890075Sobrien * prevent new references to the list from being acquired. For almost 23990075Sobrien * all operations, incrementing the busy count is sufficient to 24090075Sobrien * guarantee consistency, as the list cannot be modified while the 24190075Sobrien * busy count is elevated. For a few special operations involving a 24290075Sobrien * change to the list of active policies, the lock itself must be held. 24390075Sobrien * A condition variable, mac_policy_list_not_busy, is used to signal 24452284Sobrien * potential exclusive consumers that they should try to acquire the 24552284Sobrien * lock if a first attempt at exclusive access fails. 24652284Sobrien */ 24752284Sobrienstatic struct mtx mac_policy_list_lock; 24852284Sobrienstatic struct cv mac_policy_list_not_busy; 24952284Sobrienstatic LIST_HEAD(, mac_policy_conf) mac_policy_list; 25052284Sobrienstatic int mac_policy_list_busy; 25152284Sobrien 25252284Sobrien#define MAC_POLICY_LIST_LOCKINIT() do { \ 25352284Sobrien mtx_init(&mac_policy_list_lock, "mac_policy_list_lock", NULL, \ 25490075Sobrien MTX_DEF); \ 25552284Sobrien cv_init(&mac_policy_list_not_busy, "mac_policy_list_not_busy"); \ 25652284Sobrien} while (0) 25790075Sobrien 25852284Sobrien#define MAC_POLICY_LIST_LOCK() do { \ 25952284Sobrien mtx_lock(&mac_policy_list_lock); \ 26052284Sobrien} while (0) 26152284Sobrien 26252284Sobrien#define MAC_POLICY_LIST_UNLOCK() do { \ 26390075Sobrien mtx_unlock(&mac_policy_list_lock); \ 26452284Sobrien} while (0) 26552284Sobrien 26652284Sobrien/* 26752284Sobrien * We manually invoke WITNESS_SLEEP() to allow Witness to generate 26852284Sobrien * warnings even if we don't end up ever triggering the wait at 26952284Sobrien * run-time. The consumer of the exclusive interface must not hold 27052284Sobrien * any locks (other than potentially Giant) since we may sleep for 27152284Sobrien * long (potentially indefinite) periods of time waiting for the 27252284Sobrien * framework to become quiescent so that a policy list change may 27352284Sobrien * be made. 27490075Sobrien */ 27552284Sobrien#define MAC_POLICY_LIST_EXCLUSIVE() do { \ 27652284Sobrien WITNESS_SLEEP(1, NULL); \ 27790075Sobrien mtx_lock(&mac_policy_list_lock); \ 27852284Sobrien while (mac_policy_list_busy != 0) \ 27952284Sobrien cv_wait(&mac_policy_list_not_busy, \ 28052284Sobrien &mac_policy_list_lock); \ 28152284Sobrien} while (0) 28252284Sobrien 28390075Sobrien#define MAC_POLICY_LIST_BUSY() do { \ 28452284Sobrien MAC_POLICY_LIST_LOCK(); \ 28552284Sobrien mac_policy_list_busy++; \ 28652284Sobrien MAC_POLICY_LIST_UNLOCK(); \ 28752284Sobrien} while (0) 28852284Sobrien 28952284Sobrien#define MAC_POLICY_LIST_UNBUSY() do { \ 29090075Sobrien MAC_POLICY_LIST_LOCK(); \ 29152284Sobrien mac_policy_list_busy--; \ 29252284Sobrien KASSERT(mac_policy_list_busy >= 0, ("MAC_POLICY_LIST_LOCK")); \ 29390075Sobrien if (mac_policy_list_busy == 0) \ 29452284Sobrien cv_signal(&mac_policy_list_not_busy); \ 29552284Sobrien MAC_POLICY_LIST_UNLOCK(); \ 29652284Sobrien} while (0) 29752284Sobrien 29852284Sobrien/* 29990075Sobrien * MAC_CHECK performs the designated check by walking the policy 30052284Sobrien * module list and checking with each as to how it feels about the 30152284Sobrien * request. Note that it returns its value via 'error' in the scope 30290075Sobrien * of the caller. 30352284Sobrien */ 30452284Sobrien#define MAC_CHECK(check, args...) do { \ 30590075Sobrien struct mac_policy_conf *mpc; \ 30652284Sobrien \ 30752284Sobrien error = 0; \ 30852284Sobrien MAC_POLICY_LIST_BUSY(); \ 30952284Sobrien LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 31052284Sobrien if (mpc->mpc_ops->mpo_ ## check != NULL) \ 31190075Sobrien error = error_select( \ 31252284Sobrien mpc->mpc_ops->mpo_ ## check (args), \ 31352284Sobrien error); \ 31452284Sobrien } \ 31552284Sobrien MAC_POLICY_LIST_UNBUSY(); \ 31652284Sobrien} while (0) 31752284Sobrien 31852284Sobrien/* 31952284Sobrien * MAC_BOOLEAN performs the designated boolean composition by walking 32052284Sobrien * the module list, invoking each instance of the operation, and 32152284Sobrien * combining the results using the passed C operator. Note that it 32252284Sobrien * returns its value via 'result' in the scope of the caller, which 32352284Sobrien * should be initialized by the caller in a meaningful way to get 32452284Sobrien * a meaningful result. 32552284Sobrien */ 32652284Sobrien#define MAC_BOOLEAN(operation, composition, args...) do { \ 32752284Sobrien struct mac_policy_conf *mpc; \ 32852284Sobrien \ 32952284Sobrien MAC_POLICY_LIST_BUSY(); \ 33052284Sobrien LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 33152284Sobrien if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 33252284Sobrien result = result composition \ 33352284Sobrien mpc->mpc_ops->mpo_ ## operation (args); \ 33452284Sobrien } \ 33552284Sobrien MAC_POLICY_LIST_UNBUSY(); \ 33652284Sobrien} while (0) 33752284Sobrien 33852284Sobrien#define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \ 33952284Sobrien outbuflen) do { \ 34052284Sobrien char *curptr, *curptr_start, *element_name, *element_temp; \ 34152284Sobrien size_t left, left_start, len; \ 34252284Sobrien int claimed, first, first_start, ignorenotfound; \ 34352284Sobrien \ 34452284Sobrien error = 0; \ 34552284Sobrien element_temp = elementlist; \ 34652284Sobrien curptr = outbuf; \ 34752284Sobrien curptr[0] = '\0'; \ 34852284Sobrien left = outbuflen; \ 34952284Sobrien first = 1; \ 35052284Sobrien while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 35152284Sobrien curptr_start = curptr; \ 35252284Sobrien left_start = left; \ 35352284Sobrien first_start = first; \ 35452284Sobrien if (element_name[0] == '?') { \ 35552284Sobrien element_name++; \ 35652284Sobrien ignorenotfound = 1; \ 35752284Sobrien } else \ 35852284Sobrien ignorenotfound = 0; \ 35952284Sobrien claimed = 0; \ 36052284Sobrien if (first) { \ 36152284Sobrien len = snprintf(curptr, left, "%s/", \ 36252284Sobrien element_name); \ 36352284Sobrien first = 0; \ 36490075Sobrien } else \ 36590075Sobrien len = snprintf(curptr, left, ",%s/", \ 36690075Sobrien element_name); \ 36790075Sobrien if (len >= left) { \ 36890075Sobrien error = EINVAL; /* XXXMAC: E2BIG */ \ 36990075Sobrien break; \ 37090075Sobrien } \ 37190075Sobrien curptr += len; \ 37290075Sobrien left -= len; \ 37390075Sobrien \ 37490075Sobrien MAC_CHECK(externalize_ ## type, label, element_name, \ 37590075Sobrien curptr, left, &len, &claimed); \ 37652284Sobrien if (error) \ 37752284Sobrien break; \ 37852284Sobrien if (claimed == 1) { \ 37952284Sobrien if (len >= outbuflen) { \ 38052284Sobrien error = EINVAL; /* XXXMAC: E2BIG */ \ 38152284Sobrien break; \ 38252284Sobrien } \ 38352284Sobrien curptr += len; \ 38452284Sobrien left -= len; \ 38552284Sobrien } else if (claimed == 0 && ignorenotfound) { \ 38652284Sobrien /* \ 38752284Sobrien * Revert addition of the label element \ 38852284Sobrien * name. \ 38952284Sobrien */ \ 39052284Sobrien curptr = curptr_start; \ 39152284Sobrien *curptr = '\0'; \ 39252284Sobrien left = left_start; \ 39352284Sobrien first = first_start; \ 39490075Sobrien } else { \ 39590075Sobrien error = EINVAL; /* XXXMAC: ENOLABEL */ \ 39652284Sobrien break; \ 39752284Sobrien } \ 39852284Sobrien } \ 39952284Sobrien} while (0) 40052284Sobrien 40152284Sobrien#define MAC_INTERNALIZE(type, label, instring) do { \ 40252284Sobrien char *element, *element_name, *element_data; \ 40352284Sobrien int claimed; \ 40490075Sobrien \ 40552284Sobrien error = 0; \ 40652284Sobrien element = instring; \ 40752284Sobrien while ((element_name = strsep(&element, ",")) != NULL) { \ 40852284Sobrien element_data = element_name; \ 40952284Sobrien element_name = strsep(&element_data, "/"); \ 41052284Sobrien if (element_data == NULL) { \ 41152284Sobrien error = EINVAL; \ 41252284Sobrien break; \ 41352284Sobrien } \ 41452284Sobrien claimed = 0; \ 41552284Sobrien MAC_CHECK(internalize_ ## type, label, element_name, \ 41652284Sobrien element_data, &claimed); \ 41752284Sobrien if (error) \ 41852284Sobrien break; \ 41952284Sobrien if (claimed != 1) { \ 42090075Sobrien /* XXXMAC: Another error here? */ \ 42152284Sobrien error = EINVAL; \ 42252284Sobrien break; \ 42352284Sobrien } \ 42452284Sobrien } \ 42552284Sobrien} while (0) 42690075Sobrien 42752284Sobrien/* 42852284Sobrien * MAC_PERFORM performs the designated operation by walking the policy 42952284Sobrien * module list and invoking that operation for each policy. 43052284Sobrien */ 43152284Sobrien#define MAC_PERFORM(operation, args...) do { \ 43252284Sobrien struct mac_policy_conf *mpc; \ 43352284Sobrien \ 43452284Sobrien MAC_POLICY_LIST_BUSY(); \ 43552284Sobrien LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 43652284Sobrien if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 43752284Sobrien mpc->mpc_ops->mpo_ ## operation (args); \ 43852284Sobrien } \ 43952284Sobrien MAC_POLICY_LIST_UNBUSY(); \ 44090075Sobrien} while (0) 44152284Sobrien 44252284Sobrien/* 44352284Sobrien * Initialize the MAC subsystem, including appropriate SMP locks. 44452284Sobrien */ 44552284Sobrienstatic void 44690075Sobrienmac_init(void) 44752284Sobrien{ 44852284Sobrien 44952284Sobrien LIST_INIT(&mac_policy_list); 45052284Sobrien MAC_POLICY_LIST_LOCKINIT(); 45152284Sobrien} 45252284Sobrien 45352284Sobrien/* 45452284Sobrien * For the purposes of modules that want to know if they were loaded 45552284Sobrien * "early", set the mac_late flag once we've processed modules either 45652284Sobrien * linked into the kernel, or loaded before the kernel startup. 45790075Sobrien */ 45852284Sobrienstatic void 45952284Sobrienmac_late_init(void) 46052284Sobrien{ 46152284Sobrien 46252284Sobrien mac_late = 1; 46390075Sobrien} 46452284Sobrien 46552284Sobrien/* 46690075Sobrien * Allow MAC policy modules to register during boot, etc. 46752284Sobrien */ 46852284Sobrienint 46952284Sobrienmac_policy_modevent(module_t mod, int type, void *data) 47052284Sobrien{ 47152284Sobrien struct mac_policy_conf *mpc; 47290075Sobrien int error; 47352284Sobrien 47452284Sobrien error = 0; 47552284Sobrien mpc = (struct mac_policy_conf *) data; 47652284Sobrien 47752284Sobrien switch (type) { 47852284Sobrien case MOD_LOAD: 47952284Sobrien if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 48052284Sobrien mac_late) { 48152284Sobrien printf("mac_policy_modevent: can't load %s policy " 48252284Sobrien "after booting\n", mpc->mpc_name); 48352284Sobrien error = EBUSY; 48452284Sobrien break; 48552284Sobrien } 48652284Sobrien error = mac_policy_register(mpc); 48752284Sobrien break; 48852284Sobrien case MOD_UNLOAD: 48952284Sobrien /* Don't unregister the module if it was never registered. */ 49052284Sobrien if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 49152284Sobrien != 0) 49252284Sobrien error = mac_policy_unregister(mpc); 49352284Sobrien else 49452284Sobrien error = 0; 49552284Sobrien break; 49652284Sobrien default: 49752284Sobrien break; 49852284Sobrien } 49952284Sobrien 50052284Sobrien return (error); 50152284Sobrien} 50252284Sobrien 50352284Sobrienstatic int 50452284Sobrienmac_policy_register(struct mac_policy_conf *mpc) 50552284Sobrien{ 50652284Sobrien struct mac_policy_conf *tmpc; 50752284Sobrien int slot; 50852284Sobrien 50952284Sobrien MAC_POLICY_LIST_EXCLUSIVE(); 51052284Sobrien LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 51152284Sobrien if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 51252284Sobrien MAC_POLICY_LIST_UNLOCK(); 51352284Sobrien return (EEXIST); 51452284Sobrien } 51552284Sobrien } 51652284Sobrien if (mpc->mpc_field_off != NULL) { 51752284Sobrien slot = ffs(mac_policy_offsets_free); 51852284Sobrien if (slot == 0) { 51952284Sobrien MAC_POLICY_LIST_UNLOCK(); 52052284Sobrien return (ENOMEM); 52152284Sobrien } 52252284Sobrien slot--; 52352284Sobrien mac_policy_offsets_free &= ~(1 << slot); 52452284Sobrien *mpc->mpc_field_off = slot; 52590075Sobrien } 52652284Sobrien mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 52752284Sobrien LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 52852284Sobrien 52952284Sobrien /* Per-policy initialization. */ 53052284Sobrien if (mpc->mpc_ops->mpo_init != NULL) 53190075Sobrien (*(mpc->mpc_ops->mpo_init))(mpc); 53252284Sobrien MAC_POLICY_LIST_UNLOCK(); 53352284Sobrien 53452284Sobrien printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 53552284Sobrien mpc->mpc_name); 53652284Sobrien 53752284Sobrien return (0); 53852284Sobrien} 53952284Sobrien 54052284Sobrienstatic int 54152284Sobrienmac_policy_unregister(struct mac_policy_conf *mpc) 54252284Sobrien{ 54390075Sobrien 54452284Sobrien /* 54552284Sobrien * If we fail the load, we may get a request to unload. Check 54690075Sobrien * to see if we did the run-time registration, and if not, 54752284Sobrien * silently succeed. 54852284Sobrien */ 54952284Sobrien MAC_POLICY_LIST_EXCLUSIVE(); 55052284Sobrien if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 55152284Sobrien MAC_POLICY_LIST_UNLOCK(); 55252284Sobrien return (0); 55352284Sobrien } 55452284Sobrien#if 0 55552284Sobrien /* 55652284Sobrien * Don't allow unloading modules with private data. 55790075Sobrien */ 55852284Sobrien if (mpc->mpc_field_off != NULL) { 55952284Sobrien MAC_POLICY_LIST_UNLOCK(); 56052284Sobrien return (EBUSY); 56152284Sobrien } 56252284Sobrien#endif 56390075Sobrien /* 56452284Sobrien * Only allow the unload to proceed if the module is unloadable 56552284Sobrien * by its own definition. 56690075Sobrien */ 56752284Sobrien if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 56852284Sobrien MAC_POLICY_LIST_UNLOCK(); 56952284Sobrien return (EBUSY); 57052284Sobrien } 57152284Sobrien if (mpc->mpc_ops->mpo_destroy != NULL) 57290075Sobrien (*(mpc->mpc_ops->mpo_destroy))(mpc); 57352284Sobrien 57452284Sobrien LIST_REMOVE(mpc, mpc_list); 57552284Sobrien mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 57652284Sobrien 57752284Sobrien MAC_POLICY_LIST_UNLOCK(); 57852284Sobrien 57952284Sobrien printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 58052284Sobrien mpc->mpc_name); 58152284Sobrien 58252284Sobrien return (0); 58352284Sobrien} 58452284Sobrien 58552284Sobrien/* 58652284Sobrien * Define an error value precedence, and given two arguments, selects the 58752284Sobrien * value with the higher precedence. 58852284Sobrien */ 58952284Sobrienstatic int 59052284Sobrienerror_select(int error1, int error2) 59152284Sobrien{ 59252284Sobrien 59352284Sobrien /* Certain decision-making errors take top priority. */ 59452284Sobrien if (error1 == EDEADLK || error2 == EDEADLK) 59552284Sobrien return (EDEADLK); 59652284Sobrien 59752284Sobrien /* Invalid arguments should be reported where possible. */ 59852284Sobrien if (error1 == EINVAL || error2 == EINVAL) 59952284Sobrien return (EINVAL); 60052284Sobrien 60152284Sobrien /* Precedence goes to "visibility", with both process and file. */ 60252284Sobrien if (error1 == ESRCH || error2 == ESRCH) 60352284Sobrien return (ESRCH); 60452284Sobrien 60552284Sobrien if (error1 == ENOENT || error2 == ENOENT) 60652284Sobrien return (ENOENT); 60752284Sobrien 60852284Sobrien /* Precedence goes to DAC/MAC protections. */ 60952284Sobrien if (error1 == EACCES || error2 == EACCES) 61090075Sobrien return (EACCES); 61190075Sobrien 61290075Sobrien /* Precedence goes to privilege. */ 61390075Sobrien if (error1 == EPERM || error2 == EPERM) 61490075Sobrien return (EPERM); 61590075Sobrien 61690075Sobrien /* Precedence goes to error over success; otherwise, arbitrary. */ 61790075Sobrien if (error1 != 0) 61890075Sobrien return (error1); 61990075Sobrien return (error2); 62090075Sobrien} 62190075Sobrien 62290075Sobrienstatic void 62390075Sobrienmac_init_label(struct label *label) 62490075Sobrien{ 62590075Sobrien 62690075Sobrien bzero(label, sizeof(*label)); 62790075Sobrien label->l_flags = MAC_FLAG_INITIALIZED; 62890075Sobrien} 62918334Speter 63018334Speterstatic void 63118334Spetermac_destroy_label(struct label *label) 63218334Speter{ 63318334Speter 63418334Speter KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 63518334Speter ("destroying uninitialized label")); 63618334Speter 63718334Speter bzero(label, sizeof(*label)); 63818334Speter /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 63918334Speter} 64018334Speter 64118334Spetervoid 64218334Spetermac_init_bpfdesc(struct bpf_d *bpf_d) 64318334Speter{ 64418334Speter 64518334Speter mac_init_label(&bpf_d->bd_label); 64618334Speter MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 64718334Speter#ifdef MAC_DEBUG 64818334Speter atomic_add_int(&nmacbpfdescs, 1); 64918334Speter#endif 65018334Speter} 65118334Speter 65218334Speterstatic void 65318334Spetermac_init_cred_label(struct label *label) 65490075Sobrien{ 65518334Speter 65618334Speter mac_init_label(label); 65718334Speter MAC_PERFORM(init_cred_label, label); 65818334Speter#ifdef MAC_DEBUG 65918334Speter atomic_add_int(&nmaccreds, 1); 66018334Speter#endif 66118334Speter} 66218334Speter 66318334Spetervoid 66418334Spetermac_init_cred(struct ucred *cred) 66518334Speter{ 66618334Speter 66718334Speter mac_init_cred_label(&cred->cr_label); 66818334Speter} 66918334Speter 67018334Spetervoid 67118334Spetermac_init_devfsdirent(struct devfs_dirent *de) 67218334Speter{ 67318334Speter 67418334Speter mac_init_label(&de->de_label); 67518334Speter MAC_PERFORM(init_devfsdirent_label, &de->de_label); 67618334Speter#ifdef MAC_DEBUG 67718334Speter atomic_add_int(&nmacdevfsdirents, 1); 67818334Speter#endif 67918334Speter} 68018334Speter 68118334Speterstatic void 68218334Spetermac_init_ifnet_label(struct label *label) 68318334Speter{ 68418334Speter 68518334Speter mac_init_label(label); 68618334Speter MAC_PERFORM(init_ifnet_label, label); 68718334Speter#ifdef MAC_DEBUG 68818334Speter atomic_add_int(&nmacifnets, 1); 68990075Sobrien#endif 69018334Speter} 69118334Speter 69218334Spetervoid 69390075Sobrienmac_init_ifnet(struct ifnet *ifp) 69418334Speter{ 69518334Speter 69618334Speter mac_init_ifnet_label(&ifp->if_label); 69718334Speter} 69818334Speter 69918334Spetervoid 70018334Spetermac_init_ipq(struct ipq *ipq) 70118334Speter{ 70218334Speter 70318334Speter mac_init_label(&ipq->ipq_label); 70418334Speter MAC_PERFORM(init_ipq_label, &ipq->ipq_label); 70518334Speter#ifdef MAC_DEBUG 70618334Speter atomic_add_int(&nmacipqs, 1); 70718334Speter#endif 70818334Speter} 70918334Speter 71018334Speterint 71118334Spetermac_init_mbuf(struct mbuf *m, int flag) 71218334Speter{ 71318334Speter int error; 71418334Speter 71518334Speter KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 71618334Speter 71718334Speter mac_init_label(&m->m_pkthdr.label); 71818334Speter 71918334Speter MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag); 72018334Speter if (error) { 72118334Speter MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 72218334Speter mac_destroy_label(&m->m_pkthdr.label); 72318334Speter } 72418334Speter 72518334Speter#ifdef MAC_DEBUG 72618334Speter if (error == 0) 72718334Speter atomic_add_int(&nmacmbufs, 1); 72818334Speter#endif 72918334Speter return (error); 73090075Sobrien} 73190075Sobrien 73218334Spetervoid 73318334Spetermac_init_mount(struct mount *mp) 73418334Speter{ 73518334Speter 73618334Speter mac_init_label(&mp->mnt_mntlabel); 73718334Speter mac_init_label(&mp->mnt_fslabel); 73818334Speter MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 73918334Speter MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 74018334Speter#ifdef MAC_DEBUG 74150397Sobrien atomic_add_int(&nmacmounts, 1); 74218334Speter#endif 74318334Speter} 74418334Speter 74518334Speterstatic void 74618334Spetermac_init_pipe_label(struct label *label) 74790075Sobrien{ 74818334Speter 74918334Speter mac_init_label(label); 75018334Speter MAC_PERFORM(init_pipe_label, label); 75118334Speter#ifdef MAC_DEBUG 75218334Speter atomic_add_int(&nmacpipes, 1); 75318334Speter#endif 75418334Speter} 75590075Sobrien 75690075Sobrienvoid 75790075Sobrienmac_init_pipe(struct pipe *pipe) 75890075Sobrien{ 75990075Sobrien struct label *label; 76090075Sobrien 76190075Sobrien label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 76290075Sobrien pipe->pipe_label = label; 76318334Speter pipe->pipe_peer->pipe_label = label; 76490075Sobrien mac_init_pipe_label(label); 76518334Speter} 76690075Sobrien 76790075Sobrienvoid 76890075Sobrienmac_init_proc(struct proc *p) 76990075Sobrien{ 77090075Sobrien 77190075Sobrien mac_init_label(&p->p_label); 77290075Sobrien MAC_PERFORM(init_proc_label, &p->p_label); 77318334Speter#ifdef MAC_DEBUG 77490075Sobrien atomic_add_int(&nmacprocs, 1); 77518334Speter#endif 77690075Sobrien} 77790075Sobrien 77890075Sobrienstatic int 77990075Sobrienmac_init_socket_label(struct label *label, int flag) 78090075Sobrien{ 78190075Sobrien int error; 78290075Sobrien 78390075Sobrien mac_init_label(label); 78418334Speter 78518334Speter MAC_CHECK(init_socket_label, label, flag); 78618334Speter if (error) { 78718334Speter MAC_PERFORM(destroy_socket_label, label); 78890075Sobrien mac_destroy_label(label); 78918334Speter } 79018334Speter 79118334Speter#ifdef MAC_DEBUG 79290075Sobrien if (error == 0) 79318334Speter atomic_add_int(&nmacsockets, 1); 79418334Speter#endif 79518334Speter 79690075Sobrien return (error); 79718334Speter} 79818334Speter 79918334Speterstatic int 80018334Spetermac_init_socket_peer_label(struct label *label, int flag) 80118334Speter{ 80218334Speter int error; 80318334Speter 80418334Speter mac_init_label(label); 80518334Speter 80618334Speter MAC_CHECK(init_socket_peer_label, label, flag); 80718334Speter if (error) { 80818334Speter MAC_PERFORM(destroy_socket_label, label); 80918334Speter mac_destroy_label(label); 81018334Speter } 81118334Speter 81218334Speter return (error); 81318334Speter} 81418334Speter 81518334Speterint 81618334Spetermac_init_socket(struct socket *socket, int flag) 81718334Speter{ 81818334Speter int error; 81918334Speter 82018334Speter error = mac_init_socket_label(&socket->so_label, flag); 82118334Speter if (error) 82218334Speter return (error); 82318334Speter 82418334Speter error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 82518334Speter if (error) 82618334Speter mac_destroy_socket_label(&socket->so_label); 82718334Speter 82818334Speter return (error); 82918334Speter} 83018334Speter 83118334Spetervoid 83218334Spetermac_init_vnode_label(struct label *label) 83318334Speter{ 83418334Speter 83518334Speter mac_init_label(label); 83618334Speter MAC_PERFORM(init_vnode_label, label); 83718334Speter#ifdef MAC_DEBUG 83818334Speter atomic_add_int(&nmacvnodes, 1); 83918334Speter#endif 84018334Speter} 84118334Speter 84218334Spetervoid 84318334Spetermac_init_vnode(struct vnode *vp) 84418334Speter{ 84518334Speter 84618334Speter mac_init_vnode_label(&vp->v_label); 84718334Speter} 84818334Speter 84918334Spetervoid 85018334Spetermac_destroy_bpfdesc(struct bpf_d *bpf_d) 85118334Speter{ 85218334Speter 85318334Speter MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 85418334Speter mac_destroy_label(&bpf_d->bd_label); 85518334Speter#ifdef MAC_DEBUG 85618334Speter atomic_subtract_int(&nmacbpfdescs, 1); 85718334Speter#endif 85818334Speter} 85918334Speter 86018334Speterstatic void 86118334Spetermac_destroy_cred_label(struct label *label) 86290075Sobrien{ 86318334Speter 86418334Speter MAC_PERFORM(destroy_cred_label, label); 86518334Speter mac_destroy_label(label); 86618334Speter#ifdef MAC_DEBUG 86718334Speter atomic_subtract_int(&nmaccreds, 1); 86818334Speter#endif 86918334Speter} 87018334Speter 87118334Spetervoid 87218334Spetermac_destroy_cred(struct ucred *cred) 87318334Speter{ 87418334Speter 87518334Speter mac_destroy_cred_label(&cred->cr_label); 87618334Speter} 87718334Speter 87818334Spetervoid 87918334Spetermac_destroy_devfsdirent(struct devfs_dirent *de) 88018334Speter{ 88118334Speter 88218334Speter MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 88318334Speter mac_destroy_label(&de->de_label); 88418334Speter#ifdef MAC_DEBUG 88518334Speter atomic_subtract_int(&nmacdevfsdirents, 1); 88618334Speter#endif 88718334Speter} 88818334Speter 88918334Speterstatic void 89018334Spetermac_destroy_ifnet_label(struct label *label) 89118334Speter{ 89218334Speter 89318334Speter MAC_PERFORM(destroy_ifnet_label, label); 89418334Speter mac_destroy_label(label); 89518334Speter#ifdef MAC_DEBUG 89618334Speter atomic_subtract_int(&nmacifnets, 1); 89718334Speter#endif 89818334Speter} 89918334Speter 90018334Spetervoid 90118334Spetermac_destroy_ifnet(struct ifnet *ifp) 90218334Speter{ 90318334Speter 90418334Speter mac_destroy_ifnet_label(&ifp->if_label); 90518334Speter} 90618334Speter 90718334Spetervoid 90818334Spetermac_destroy_ipq(struct ipq *ipq) 90918334Speter{ 91018334Speter 91118334Speter MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 91218334Speter mac_destroy_label(&ipq->ipq_label); 91318334Speter#ifdef MAC_DEBUG 91418334Speter atomic_subtract_int(&nmacipqs, 1); 91518334Speter#endif 91618334Speter} 91718334Speter 91818334Spetervoid 91918334Spetermac_destroy_mbuf(struct mbuf *m) 92018334Speter{ 92118334Speter 92218334Speter MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 92318334Speter mac_destroy_label(&m->m_pkthdr.label); 92418334Speter#ifdef MAC_DEBUG 92518334Speter atomic_subtract_int(&nmacmbufs, 1); 92618334Speter#endif 92718334Speter} 92818334Speter 92918334Spetervoid 93018334Spetermac_destroy_mount(struct mount *mp) 93118334Speter{ 93218334Speter 93318334Speter MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 93418334Speter MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 93518334Speter mac_destroy_label(&mp->mnt_fslabel); 93650397Sobrien mac_destroy_label(&mp->mnt_mntlabel); 93750397Sobrien#ifdef MAC_DEBUG 93818334Speter atomic_subtract_int(&nmacmounts, 1); 93918334Speter#endif 94018334Speter} 94118334Speter 94218334Speterstatic void 94318334Spetermac_destroy_pipe_label(struct label *label) 94418334Speter{ 94518334Speter 94618334Speter MAC_PERFORM(destroy_pipe_label, label); 94718334Speter mac_destroy_label(label); 94818334Speter#ifdef MAC_DEBUG 94918334Speter atomic_subtract_int(&nmacpipes, 1); 95018334Speter#endif 95118334Speter} 95218334Speter 95318334Spetervoid 95418334Spetermac_destroy_pipe(struct pipe *pipe) 95518334Speter{ 95618334Speter 95718334Speter mac_destroy_pipe_label(pipe->pipe_label); 95818334Speter free(pipe->pipe_label, M_MACPIPELABEL); 95918334Speter} 96018334Speter 96118334Spetervoid 96218334Spetermac_destroy_proc(struct proc *p) 96318334Speter{ 96418334Speter 96518334Speter MAC_PERFORM(destroy_proc_label, &p->p_label); 96618334Speter mac_destroy_label(&p->p_label); 96718334Speter#ifdef MAC_DEBUG 96818334Speter atomic_subtract_int(&nmacprocs, 1); 96918334Speter#endif 97018334Speter} 97118334Speter 97218334Speterstatic void 97318334Spetermac_destroy_socket_label(struct label *label) 97418334Speter{ 97518334Speter 97618334Speter MAC_PERFORM(destroy_socket_label, label); 97718334Speter mac_destroy_label(label); 97818334Speter#ifdef MAC_DEBUG 97918334Speter atomic_subtract_int(&nmacsockets, 1); 98018334Speter#endif 98118334Speter} 98218334Speter 98318334Speterstatic void 98418334Spetermac_destroy_socket_peer_label(struct label *label) 98518334Speter{ 98618334Speter 98718334Speter MAC_PERFORM(destroy_socket_peer_label, label); 98818334Speter mac_destroy_label(label); 98918334Speter} 99018334Speter 99118334Spetervoid 99218334Spetermac_destroy_socket(struct socket *socket) 99318334Speter{ 99418334Speter 99518334Speter mac_destroy_socket_label(&socket->so_label); 99618334Speter mac_destroy_socket_peer_label(&socket->so_peerlabel); 99718334Speter} 99818334Speter 99918334Spetervoid 100018334Spetermac_destroy_vnode_label(struct label *label) 100118334Speter{ 100218334Speter 100318334Speter MAC_PERFORM(destroy_vnode_label, label); 100418334Speter mac_destroy_label(label); 100518334Speter#ifdef MAC_DEBUG 100618334Speter atomic_subtract_int(&nmacvnodes, 1); 100718334Speter#endif 100818334Speter} 100918334Speter 101018334Spetervoid 101118334Spetermac_destroy_vnode(struct vnode *vp) 101218334Speter{ 101318334Speter 101418334Speter mac_destroy_vnode_label(&vp->v_label); 101518334Speter} 101618334Speter 101718334Speterstatic void 101818334Spetermac_copy_pipe_label(struct label *src, struct label *dest) 101918334Speter{ 102018334Speter 102118334Speter MAC_PERFORM(copy_pipe_label, src, dest); 102218334Speter} 102318334Speter 102418334Spetervoid 102518334Spetermac_copy_vnode_label(struct label *src, struct label *dest) 102618334Speter{ 102718334Speter 102818334Speter MAC_PERFORM(copy_vnode_label, src, dest); 102918334Speter} 103018334Speter 103118334Speterstatic int 103218334Spetermac_check_structmac_consistent(struct mac *mac) 103318334Speter{ 103418334Speter 103518334Speter if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 103618334Speter return (EINVAL); 103718334Speter 103818334Speter return (0); 103918334Speter} 104018334Speter 104118334Speterstatic int 104218334Spetermac_externalize_cred_label(struct label *label, char *elements, 104318334Speter char *outbuf, size_t outbuflen, int flags) 104418334Speter{ 104518334Speter int error; 104618334Speter 104718334Speter MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen); 104818334Speter 104918334Speter return (error); 105018334Speter} 105118334Speter 105218334Speterstatic int 105318334Spetermac_externalize_ifnet_label(struct label *label, char *elements, 105418334Speter char *outbuf, size_t outbuflen, int flags) 105518334Speter{ 105650397Sobrien int error; 105718334Speter 105818334Speter MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen); 105918334Speter 106018334Speter return (error); 106118334Speter} 106218334Speter 106318334Speterstatic int 106418334Spetermac_externalize_pipe_label(struct label *label, char *elements, 106518334Speter char *outbuf, size_t outbuflen, int flags) 106618334Speter{ 106718334Speter int error; 106818334Speter 106918334Speter MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen); 107018334Speter 107118334Speter return (error); 107218334Speter} 107318334Speter 107418334Speterstatic int 107518334Spetermac_externalize_socket_label(struct label *label, char *elements, 107618334Speter char *outbuf, size_t outbuflen, int flags) 107718334Speter{ 107818334Speter int error; 107918334Speter 108018334Speter MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen); 108118334Speter 108218334Speter return (error); 108318334Speter} 108418334Speter 108518334Speterstatic int 108618334Spetermac_externalize_socket_peer_label(struct label *label, char *elements, 108718334Speter char *outbuf, size_t outbuflen, int flags) 108818334Speter{ 108918334Speter int error; 109018334Speter 109118334Speter MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen); 109218334Speter 109318334Speter return (error); 109418334Speter} 109518334Speter 109618334Speterstatic int 109718334Spetermac_externalize_vnode_label(struct label *label, char *elements, 109818334Speter char *outbuf, size_t outbuflen, int flags) 109918334Speter{ 110018334Speter int error; 110118334Speter 110218334Speter MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen); 110318334Speter 110418334Speter return (error); 110518334Speter} 110618334Speter 110718334Speterstatic int 110818334Spetermac_internalize_cred_label(struct label *label, char *string) 110918334Speter{ 111018334Speter int error; 111118334Speter 111218334Speter MAC_INTERNALIZE(cred_label, label, string); 111318334Speter 111418334Speter return (error); 111518334Speter} 111618334Speter 111718334Speterstatic int 111818334Spetermac_internalize_ifnet_label(struct label *label, char *string) 111918334Speter{ 112018334Speter int error; 112118334Speter 112218334Speter MAC_INTERNALIZE(ifnet_label, label, string); 112318334Speter 112418334Speter return (error); 112518334Speter} 112618334Speter 112718334Speterstatic int 112818334Spetermac_internalize_pipe_label(struct label *label, char *string) 112918334Speter{ 113018334Speter int error; 113118334Speter 113218334Speter MAC_INTERNALIZE(pipe_label, label, string); 113318334Speter 113418334Speter return (error); 113518334Speter} 113618334Speter 113718334Speterstatic int 113818334Spetermac_internalize_socket_label(struct label *label, char *string) 113918334Speter{ 114018334Speter int error; 114118334Speter 114218334Speter MAC_INTERNALIZE(socket_label, label, string); 114318334Speter 114418334Speter return (error); 114518334Speter} 114618334Speter 114718334Speterstatic int 114818334Spetermac_internalize_vnode_label(struct label *label, char *string) 114918334Speter{ 115018334Speter int error; 115118334Speter 115218334Speter MAC_INTERNALIZE(vnode_label, label, string); 115318334Speter 115418334Speter return (error); 115518334Speter} 115618334Speter 115718334Speter/* 115818334Speter * Initialize MAC label for the first kernel process, from which other 115918334Speter * kernel processes and threads are spawned. 116018334Speter */ 116118334Spetervoid 116218334Spetermac_create_proc0(struct ucred *cred) 116318334Speter{ 116418334Speter 116518334Speter MAC_PERFORM(create_proc0, cred); 116618334Speter} 116718334Speter 116818334Speter/* 116918334Speter * Initialize MAC label for the first userland process, from which other 117050397Sobrien * userland processes and threads are spawned. 117118334Speter */ 117218334Spetervoid 117318334Spetermac_create_proc1(struct ucred *cred) 117418334Speter{ 117518334Speter 117618334Speter MAC_PERFORM(create_proc1, cred); 117718334Speter} 117818334Speter 117918334Spetervoid 118018334Spetermac_thread_userret(struct thread *td) 118118334Speter{ 118218334Speter 118318334Speter MAC_PERFORM(thread_userret, td); 118418334Speter} 118518334Speter 118618334Speter/* 118718334Speter * When a new process is created, its label must be initialized. Generally, 118818334Speter * this involves inheritence from the parent process, modulo possible 118918334Speter * deltas. This function allows that processing to take place. 119018334Speter */ 119118334Spetervoid 119218334Spetermac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 119318334Speter{ 119418334Speter 119590075Sobrien MAC_PERFORM(create_cred, parent_cred, child_cred); 119652284Sobrien} 119718334Speter 119818334Spetervoid 119918334Spetermac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 120018334Speter{ 120118334Speter 120218334Speter MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 120318334Speter} 120418334Speter 120518334Spetervoid 120618334Spetermac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 120718334Speter struct vnode *vp) 120818334Speter{ 120918334Speter 121018334Speter MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, 121118334Speter &de->de_label, vp, &vp->v_label); 121218334Speter} 121318334Speter 121418334Speterint 121518334Spetermac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 121618334Speter{ 121718334Speter int error; 121850397Sobrien 121918334Speter ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 122018334Speter 122118334Speter MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, 122218334Speter &vp->v_label); 122318334Speter 122418334Speter return (error); 122518334Speter} 122618334Speter 122718334Spetervoid 122818334Spetermac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 122918334Speter{ 123018334Speter 123118334Speter MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, 123218334Speter &vp->v_label); 123318334Speter} 123418334Speter 123518334Speterint 123618334Spetermac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 123718334Speter struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 123818334Speter{ 123918334Speter int error; 124050397Sobrien 124150397Sobrien ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 124290075Sobrien ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 124350397Sobrien 124450397Sobrien error = VOP_OPENEXTATTR(vp, cred, curthread); 124518334Speter if (error == EOPNOTSUPP) { 124618334Speter /* XXX: Optionally abort if transactions not supported. */ 124718334Speter if (ea_warn_once == 0) { 124818334Speter printf("Warning: transactions not supported " 124990075Sobrien "in EA write.\n"); 125090075Sobrien ea_warn_once = 1; 125118334Speter } 125290075Sobrien } else if (error) 125390075Sobrien return (error); 125490075Sobrien 125590075Sobrien MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, 125618334Speter dvp, &dvp->v_label, vp, &vp->v_label, cnp); 125718334Speter 125818334Speter if (error) { 125918334Speter VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 126090075Sobrien return (error); 126150397Sobrien } 126290075Sobrien 126390075Sobrien error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 126490075Sobrien 126550397Sobrien if (error == EOPNOTSUPP) 126618334Speter error = 0; /* XXX */ 126718334Speter 126818334Speter return (error); 126918334Speter} 127018334Speter 127118334Speterstatic int 127218334Spetermac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 127318334Speter struct label *intlabel) 127490075Sobrien{ 127518334Speter int error; 127618334Speter 127718334Speter ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 127818334Speter 127918334Speter error = VOP_OPENEXTATTR(vp, cred, curthread); 128018334Speter if (error == EOPNOTSUPP) { 128118334Speter /* XXX: Optionally abort if transactions not supported. */ 128250397Sobrien if (ea_warn_once == 0) { 128350397Sobrien printf("Warning: transactions not supported " 128450397Sobrien "in EA write.\n"); 128518334Speter ea_warn_once = 1; 128652284Sobrien } 128752284Sobrien } else if (error) 128852284Sobrien return (error); 128952284Sobrien 129052284Sobrien MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); 129150397Sobrien 129290075Sobrien if (error) { 129318334Speter VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 129418334Speter return (error); 129590075Sobrien } 129618334Speter 129718334Speter error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 129818334Speter 129918334Speter if (error == EOPNOTSUPP) 130018334Speter error = 0; /* XXX */ 130118334Speter 130218334Speter return (error); 130318334Speter} 130418334Speter 130518334Speterint 130618334Spetermac_execve_enter(struct image_params *imgp, struct mac *mac_p, 130718334Speter struct label *execlabelstorage) 130818334Speter{ 130918334Speter struct mac mac; 131018334Speter char *buffer; 131118334Speter int error; 131218334Speter 131318334Speter if (mac_p == NULL) 131418334Speter return (0); 131518334Speter 131618334Speter error = copyin(mac_p, &mac, sizeof(mac)); 131718334Speter if (error) 131818334Speter return (error); 131918334Speter 132018334Speter error = mac_check_structmac_consistent(&mac); 132118334Speter if (error) 132218334Speter return (error); 132318334Speter 132418334Speter buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 132518334Speter error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 132618334Speter if (error) { 132718334Speter free(buffer, M_MACTEMP); 132818334Speter return (error); 132918334Speter } 133018334Speter 133118334Speter mac_init_cred_label(execlabelstorage); 133218334Speter error = mac_internalize_cred_label(execlabelstorage, buffer); 133318334Speter free(buffer, M_MACTEMP); 133418334Speter if (error) { 133518334Speter mac_destroy_cred_label(execlabelstorage); 133618334Speter return (error); 133718334Speter } 133818334Speter imgp->execlabel = execlabelstorage; 133918334Speter return (0); 134018334Speter} 134118334Speter 134218334Spetervoid 134318334Spetermac_execve_exit(struct image_params *imgp) 134418334Speter{ 134518334Speter if (imgp->execlabel != NULL) 134618334Speter mac_destroy_cred_label(imgp->execlabel); 134718334Speter} 134818334Speter 134918334Spetervoid 135018334Spetermac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, 135118334Speter struct label *interpvnodelabel, struct image_params *imgp) 135218334Speter{ 135318334Speter 135418334Speter ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 135518334Speter 135618334Speter if (!mac_enforce_process && !mac_enforce_fs) 135718334Speter return; 135818334Speter 135918334Speter MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, 136018334Speter interpvnodelabel, imgp, imgp->execlabel); 136118334Speter} 136218334Speter 136318334Speterint 136418334Spetermac_execve_will_transition(struct ucred *old, struct vnode *vp, 136518334Speter struct label *interpvnodelabel, struct image_params *imgp) 136618334Speter{ 136752284Sobrien int result; 136852284Sobrien 136918334Speter ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 137018334Speter 137118334Speter if (!mac_enforce_process && !mac_enforce_fs) 137218334Speter return (0); 137318334Speter 137418334Speter result = 0; 137518334Speter MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, 137618334Speter interpvnodelabel, imgp, imgp->execlabel); 137718334Speter 137818334Speter return (result); 137918334Speter} 138018334Speter 138118334Speterint 138218334Spetermac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 138318334Speter{ 138418334Speter int error; 138518334Speter 138618334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 138718334Speter 138818334Speter if (!mac_enforce_fs) 138918334Speter return (0); 139018334Speter 139118334Speter MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode); 139218334Speter return (error); 139318334Speter} 139418334Speter 139518334Speterint 139618334Spetermac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 139718334Speter{ 139818334Speter int error; 139918334Speter 140018334Speter ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 140118334Speter 140218334Speter if (!mac_enforce_fs) 140318334Speter return (0); 140418334Speter 140518334Speter MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 140618334Speter return (error); 140718334Speter} 140818334Speter 140918334Speterint 141018334Spetermac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 141118334Speter{ 141218334Speter int error; 141318334Speter 141418334Speter ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 141518334Speter 141618334Speter if (!mac_enforce_fs) 141718334Speter return (0); 141818334Speter 141918334Speter MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 142018334Speter return (error); 142118334Speter} 142218334Speter 142318334Speterint 142418334Spetermac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 142518334Speter struct componentname *cnp, struct vattr *vap) 142618334Speter{ 142718334Speter int error; 142818334Speter 142918334Speter ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 143018334Speter 143118334Speter if (!mac_enforce_fs) 143218334Speter return (0); 143318334Speter 143418334Speter MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 143518334Speter return (error); 143618334Speter} 143718334Speter 143818334Speterint 143918334Spetermac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 144018334Speter struct componentname *cnp) 144118334Speter{ 144218334Speter int error; 144318334Speter 144418334Speter ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 144518334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 144618334Speter 144718334Speter if (!mac_enforce_fs) 144818334Speter return (0); 144918334Speter 145018334Speter MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 145118334Speter &vp->v_label, cnp); 145218334Speter return (error); 145318334Speter} 145418334Speter 145518334Speterint 145618334Spetermac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 145718334Speter acl_type_t type) 145818334Speter{ 145918334Speter int error; 146018334Speter 146118334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 146218334Speter 146318334Speter if (!mac_enforce_fs) 146418334Speter return (0); 146518334Speter 146618334Speter MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 146750397Sobrien return (error); 146850397Sobrien} 146950397Sobrien 147052284Sobrienint 147152284Sobrienmac_check_vnode_exec(struct ucred *cred, struct vnode *vp, 147252284Sobrien struct image_params *imgp) 147352284Sobrien{ 147452284Sobrien int error; 147550397Sobrien 147690075Sobrien ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 147718334Speter 147818334Speter if (!mac_enforce_process && !mac_enforce_fs) 147918334Speter return (0); 148018334Speter 148118334Speter MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp, 148218334Speter imgp->execlabel); 148318334Speter 148418334Speter return (error); 148518334Speter} 148618334Speter 148718334Speterint 148818334Spetermac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 148918334Speter{ 149018334Speter int error; 149118334Speter 149218334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 149318334Speter 149418334Speter if (!mac_enforce_fs) 149518334Speter return (0); 149618334Speter 149718334Speter MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 149818334Speter return (error); 149918334Speter} 150018334Speter 150118334Speterint 150218334Spetermac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 150318334Speter int attrnamespace, const char *name, struct uio *uio) 150418334Speter{ 150518334Speter int error; 150618334Speter 150718334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 150818334Speter 150918334Speter if (!mac_enforce_fs) 151018334Speter return (0); 151118334Speter 151218334Speter MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 151318334Speter attrnamespace, name, uio); 151418334Speter return (error); 151518334Speter} 151618334Speter 151718334Speterint 151818334Spetermac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 151952284Sobrien struct vnode *vp, struct componentname *cnp) 152018334Speter{ 152118334Speter int error; 152218334Speter 152318334Speter ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 152452284Sobrien ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 152518334Speter 152618334Speter if (!mac_enforce_fs) 152718334Speter return (0); 152818334Speter 152918334Speter MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 153018334Speter &vp->v_label, cnp); 153118334Speter return (error); 153252284Sobrien} 153318334Speter 153418334Speterint 153518334Spetermac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 153618334Speter struct componentname *cnp) 153718334Speter{ 153818334Speter int error; 153918334Speter 154018334Speter ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 154118334Speter 154218334Speter if (!mac_enforce_fs) 154318334Speter return (0); 154418334Speter 154518334Speter MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 154618334Speter return (error); 154718334Speter} 154818334Speter 154918334Speterint 155018334Spetermac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 155118334Speter{ 155218334Speter int error; 155318334Speter 155418334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 155518334Speter 155618334Speter if (!mac_enforce_fs || !mac_enforce_vm) 155718334Speter return (0); 155818334Speter 155918334Speter MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 156018334Speter return (error); 156190075Sobrien} 156290075Sobrien 156390075Sobrienvoid 156418334Spetermac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 156518334Speter{ 156618334Speter int result = *prot; 156718334Speter 156818334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 156918334Speter 157018334Speter if (!mac_enforce_fs || !mac_enforce_vm) 157118334Speter return; 157218334Speter 157318334Speter MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 157418334Speter &result); 157518334Speter 157618334Speter *prot = result; 157718334Speter} 157818334Speter 157918334Speterint 158018334Spetermac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 158118334Speter{ 158218334Speter int error; 158318334Speter 158418334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 158518334Speter 158618334Speter if (!mac_enforce_fs || !mac_enforce_vm) 158718334Speter return (0); 158818334Speter 158918334Speter MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 159018334Speter return (error); 159118334Speter} 159218334Speter 159318334Speterint 159418334Spetermac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 159518334Speter{ 159618334Speter int error; 159790075Sobrien 159890075Sobrien ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 159990075Sobrien 160090075Sobrien if (!mac_enforce_fs) 160118334Speter return (0); 160218334Speter 160318334Speter MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 160418334Speter return (error); 160518334Speter} 160618334Speter 160718334Speterint 160818334Spetermac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 160918334Speter struct vnode *vp) 161018334Speter{ 161118334Speter int error; 161218334Speter 161318334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 161418334Speter 161518334Speter if (!mac_enforce_fs) 161690075Sobrien return (0); 161790075Sobrien 161890075Sobrien MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 161990075Sobrien &vp->v_label); 162018334Speter 162118334Speter return (error); 162218334Speter} 162318334Speter 162418334Speterint 162518334Spetermac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 162618334Speter struct vnode *vp) 162718334Speter{ 162818334Speter int error; 162918334Speter 163018334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 163118334Speter 163218334Speter if (!mac_enforce_fs) 163318334Speter return (0); 163418334Speter 163518334Speter MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 163618334Speter &vp->v_label); 163718334Speter 163818334Speter return (error); 163918334Speter} 164018334Speter 164118334Speterint 164218334Spetermac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 164318334Speter{ 164418334Speter int error; 164518334Speter 164618334Speter ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 164718334Speter 164818334Speter if (!mac_enforce_fs) 164918334Speter return (0); 165018334Speter 165118334Speter MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 165218334Speter return (error); 165318334Speter} 165418334Speter 165518334Speterint 165618334Spetermac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 165718334Speter{ 165818334Speter int error; 165918334Speter 166018334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 166118334Speter 166218334Speter if (!mac_enforce_fs) 166318334Speter return (0); 166418334Speter 166518334Speter MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 166618334Speter return (error); 166718334Speter} 166818334Speter 166918334Speterstatic int 167018334Spetermac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 167118334Speter struct label *newlabel) 167218334Speter{ 167318334Speter int error; 167418334Speter 167518334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 167618334Speter 167718334Speter MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 167818334Speter 167918334Speter return (error); 168018334Speter} 168118334Speter 168218334Speterint 168318334Spetermac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 168418334Speter struct vnode *vp, struct componentname *cnp) 168518334Speter{ 168618334Speter int error; 168718334Speter 168818334Speter ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 168918334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 169018334Speter 169118334Speter if (!mac_enforce_fs) 169218334Speter return (0); 169318334Speter 169418334Speter MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 169518334Speter &vp->v_label, cnp); 169652284Sobrien return (error); 169718334Speter} 169852284Sobrien 169952284Sobrienint 170052284Sobrienmac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 170152284Sobrien struct vnode *vp, int samedir, struct componentname *cnp) 170252284Sobrien{ 170352284Sobrien int error; 170418334Speter 170552284Sobrien ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 170652284Sobrien ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 170752284Sobrien 170852284Sobrien if (!mac_enforce_fs) 170952284Sobrien return (0); 171052284Sobrien 171118334Speter MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 171252284Sobrien vp != NULL ? &vp->v_label : NULL, samedir, cnp); 171352284Sobrien return (error); 171418334Speter} 171518334Speter 171618334Speterint 171718334Spetermac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 171818334Speter{ 171918334Speter int error; 172018334Speter 172118334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 172218334Speter 172318334Speter if (!mac_enforce_fs) 172418334Speter return (0); 172518334Speter 172618334Speter MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 172718334Speter return (error); 172818334Speter} 172950397Sobrien 173050397Sobrienint 173118334Spetermac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 173218334Speter struct acl *acl) 173318334Speter{ 173418334Speter int error; 173518334Speter 173618334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 173718334Speter 173818334Speter if (!mac_enforce_fs) 173918334Speter return (0); 174018334Speter 174118334Speter MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 174218334Speter return (error); 174318334Speter} 174418334Speter 174518334Speterint 174618334Spetermac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 174718334Speter int attrnamespace, const char *name, struct uio *uio) 174818334Speter{ 174918334Speter int error; 175018334Speter 175118334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 175218334Speter 175318334Speter if (!mac_enforce_fs) 175418334Speter return (0); 175518334Speter 175618334Speter MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 175718334Speter attrnamespace, name, uio); 175818334Speter return (error); 175918334Speter} 176018334Speter 176118334Speterint 176218334Spetermac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 176318334Speter{ 176418334Speter int error; 176518334Speter 176618334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 176718334Speter 176890075Sobrien if (!mac_enforce_fs) 176918334Speter return (0); 177018334Speter 177118334Speter MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 177218334Speter return (error); 177318334Speter} 177418334Speter 177518334Speterint 177650397Sobrienmac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 177718334Speter{ 177818334Speter int error; 177918334Speter 178018334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 178118334Speter 178218334Speter if (!mac_enforce_fs) 178318334Speter return (0); 178418334Speter 178518334Speter MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 178618334Speter return (error); 178718334Speter} 178818334Speter 178918334Speterint 179018334Spetermac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 179118334Speter gid_t gid) 179218334Speter{ 179318334Speter int error; 179418334Speter 179518334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 179618334Speter 179718334Speter if (!mac_enforce_fs) 179818334Speter return (0); 179918334Speter 180018334Speter MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 180118334Speter return (error); 180218334Speter} 180318334Speter 180418334Speterint 180518334Spetermac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 180618334Speter struct timespec atime, struct timespec mtime) 180718334Speter{ 180818334Speter int error; 180918334Speter 181018334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 181118334Speter 181218334Speter if (!mac_enforce_fs) 181318334Speter return (0); 181418334Speter 181518334Speter MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 181618334Speter mtime); 181718334Speter return (error); 181818334Speter} 181918334Speter 182018334Speterint 182118334Spetermac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 182218334Speter struct vnode *vp) 182318334Speter{ 182418334Speter int error; 182518334Speter 182618334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 182718334Speter 182818334Speter if (!mac_enforce_fs) 182918334Speter return (0); 183018334Speter 183118334Speter MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 183218334Speter &vp->v_label); 183318334Speter return (error); 183418334Speter} 183518334Speter 183618334Speterint 183718334Spetermac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 183818334Speter struct vnode *vp) 183918334Speter{ 184018334Speter int error; 184118334Speter 184218334Speter ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 184318334Speter 184418334Speter if (!mac_enforce_fs) 184518334Speter return (0); 184618334Speter 184718334Speter MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 184818334Speter &vp->v_label); 184918334Speter 185018334Speter return (error); 185118334Speter} 185218334Speter 185318334Speter/* 185418334Speter * When relabeling a process, call out to the policies for the maximum 185518334Speter * permission allowed for each object type we know about in its 185618334Speter * memory space, and revoke access (in the least surprising ways we 185718334Speter * know) when necessary. The process lock is not held here. 185818334Speter */ 185918334Spetervoid 186018334Spetermac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 186118334Speter{ 186218334Speter 186318334Speter /* XXX freeze all other threads */ 186418334Speter mac_cred_mmapped_drop_perms_recurse(td, cred, 186518334Speter &td->td_proc->p_vmspace->vm_map); 186618334Speter /* XXX allow other threads to continue */ 186718334Speter} 186818334Speter 186918334Speterstatic __inline const char * 187018334Speterprot2str(vm_prot_t prot) 187190075Sobrien{ 187218334Speter 187318334Speter switch (prot & VM_PROT_ALL) { 187418334Speter case VM_PROT_READ: 187518334Speter return ("r--"); 187618334Speter case VM_PROT_READ | VM_PROT_WRITE: 187718334Speter return ("rw-"); 187818334Speter case VM_PROT_READ | VM_PROT_EXECUTE: 187918334Speter return ("r-x"); 188018334Speter case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 188118334Speter return ("rwx"); 188218334Speter case VM_PROT_WRITE: 188318334Speter return ("-w-"); 188418334Speter case VM_PROT_EXECUTE: 188518334Speter return ("--x"); 188618334Speter case VM_PROT_WRITE | VM_PROT_EXECUTE: 188718334Speter return ("-wx"); 188818334Speter default: 188918334Speter return ("---"); 189018334Speter } 189118334Speter} 189218334Speter 189318334Speterstatic void 189418334Spetermac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 189518334Speter struct vm_map *map) 189618334Speter{ 189718334Speter struct vm_map_entry *vme; 189818334Speter int result; 189918334Speter vm_prot_t revokeperms; 190018334Speter vm_object_t object; 190118334Speter vm_ooffset_t offset; 190218334Speter struct vnode *vp; 190318334Speter 190418334Speter if (!mac_mmap_revocation) 190518334Speter return; 190618334Speter 190718334Speter vm_map_lock_read(map); 190818334Speter for (vme = map->header.next; vme != &map->header; vme = vme->next) { 190918334Speter if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 191018334Speter mac_cred_mmapped_drop_perms_recurse(td, cred, 191118334Speter vme->object.sub_map); 191218334Speter continue; 191318334Speter } 191418334Speter /* 191518334Speter * Skip over entries that obviously are not shared. 191618334Speter */ 191718334Speter if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 191818334Speter !vme->max_protection) 191918334Speter continue; 192050397Sobrien /* 192118334Speter * Drill down to the deepest backing object. 192218334Speter */ 192318334Speter offset = vme->offset; 192418334Speter object = vme->object.vm_object; 192518334Speter if (object == NULL) 192618334Speter continue; 192718334Speter while (object->backing_object != NULL) { 192818334Speter object = object->backing_object; 192918334Speter offset += object->backing_object_offset; 193018334Speter } 193118334Speter /* 193218334Speter * At the moment, vm_maps and objects aren't considered 193318334Speter * by the MAC system, so only things with backing by a 193418334Speter * normal object (read: vnodes) are checked. 193518334Speter */ 193618334Speter if (object->type != OBJT_VNODE) 193718334Speter continue; 193818334Speter vp = (struct vnode *)object->handle; 193918334Speter vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 194018334Speter result = vme->max_protection; 194118334Speter mac_check_vnode_mmap_downgrade(cred, vp, &result); 194218334Speter VOP_UNLOCK(vp, 0, td); 194318334Speter /* 194418334Speter * Find out what maximum protection we may be allowing 194518334Speter * now but a policy needs to get removed. 194618334Speter */ 194718334Speter revokeperms = vme->max_protection & ~result; 194818334Speter if (!revokeperms) 194918334Speter continue; 195018334Speter printf("pid %ld: revoking %s perms from %#lx:%ld " 195118334Speter "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 195290075Sobrien prot2str(revokeperms), (u_long)vme->start, 195318334Speter (long)(vme->end - vme->start), 195418334Speter prot2str(vme->max_protection), prot2str(vme->protection)); 195518334Speter vm_map_lock_upgrade(map); 195690075Sobrien /* 195718334Speter * This is the really simple case: if a map has more 195818334Speter * max_protection than is allowed, but it's not being 195918334Speter * actually used (that is, the current protection is 196018334Speter * still allowed), we can just wipe it out and do 196118334Speter * nothing more. 196218334Speter */ 196318334Speter if ((vme->protection & revokeperms) == 0) { 196418334Speter vme->max_protection -= revokeperms; 196518334Speter } else { 196618334Speter if (revokeperms & VM_PROT_WRITE) { 196718334Speter /* 196818334Speter * In the more complicated case, flush out all 196918334Speter * pending changes to the object then turn it 197018334Speter * copy-on-write. 197118334Speter */ 197218334Speter vm_object_reference(object); 197318334Speter vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 197490075Sobrien vm_object_page_clean(object, 197590075Sobrien OFF_TO_IDX(offset), 197618334Speter OFF_TO_IDX(offset + vme->end - vme->start + 197718334Speter PAGE_MASK), 197818334Speter OBJPC_SYNC); 197918334Speter VOP_UNLOCK(vp, 0, td); 198018334Speter vm_object_deallocate(object); 198118334Speter /* 198218334Speter * Why bother if there's no read permissions 198318334Speter * anymore? For the rest, we need to leave 198418334Speter * the write permissions on for COW, or 198518334Speter * remove them entirely if configured to. 198618334Speter */ 198718334Speter if (!mac_mmap_revocation_via_cow) { 198890075Sobrien vme->max_protection &= ~VM_PROT_WRITE; 198918334Speter vme->protection &= ~VM_PROT_WRITE; 199018334Speter } if ((revokeperms & VM_PROT_READ) == 0) 199190075Sobrien vme->eflags |= MAP_ENTRY_COW | 199218334Speter MAP_ENTRY_NEEDS_COPY; 199318334Speter } 199418334Speter if (revokeperms & VM_PROT_EXECUTE) { 199518334Speter vme->max_protection &= ~VM_PROT_EXECUTE; 199690075Sobrien vme->protection &= ~VM_PROT_EXECUTE; 199790075Sobrien } 199818334Speter if (revokeperms & VM_PROT_READ) { 199918334Speter vme->max_protection = 0; 200018334Speter vme->protection = 0; 200118334Speter } 200218334Speter pmap_protect(map->pmap, vme->start, vme->end, 200318334Speter vme->protection & ~revokeperms); 200418334Speter vm_map_simplify_entry(map, vme); 200518334Speter } 200618334Speter vm_map_lock_downgrade(map); 200718334Speter } 200818334Speter vm_map_unlock_read(map); 200918334Speter} 201018334Speter 201118334Speter/* 201218334Speter * When the subject's label changes, it may require revocation of privilege 201318334Speter * to mapped objects. This can't be done on-the-fly later with a unified 201418334Speter * buffer cache. 201518334Speter */ 201618334Speterstatic void 201718334Spetermac_relabel_cred(struct ucred *cred, struct label *newlabel) 201818334Speter{ 201918334Speter 202090075Sobrien MAC_PERFORM(relabel_cred, cred, newlabel); 202190075Sobrien} 202290075Sobrien 202390075Sobrienvoid 202418334Spetermac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 202590075Sobrien{ 202618334Speter 202718334Speter MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 202818334Speter} 202918334Speter 203018334Spetervoid 203118334Spetermac_create_ifnet(struct ifnet *ifnet) 203218334Speter{ 203318334Speter 203418334Speter MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 203518334Speter} 203618334Speter 203718334Spetervoid 203818334Spetermac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 203918334Speter{ 204018334Speter 204118334Speter MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 204290075Sobrien} 204390075Sobrien 204490075Sobrienvoid 204590075Sobrienmac_create_socket(struct ucred *cred, struct socket *socket) 204690075Sobrien{ 204790075Sobrien 204890075Sobrien MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 204990075Sobrien} 205090075Sobrien 205190075Sobrienvoid 205290075Sobrienmac_create_pipe(struct ucred *cred, struct pipe *pipe) 205390075Sobrien{ 205490075Sobrien 205590075Sobrien MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 205690075Sobrien} 205790075Sobrien 205890075Sobrienvoid 205990075Sobrienmac_create_socket_from_socket(struct socket *oldsocket, 206018334Speter struct socket *newsocket) 206118334Speter{ 206218334Speter 206318334Speter MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 206418334Speter newsocket, &newsocket->so_label); 206518334Speter} 206618334Speter 206718334Speterstatic void 206818334Spetermac_relabel_socket(struct ucred *cred, struct socket *socket, 206918334Speter struct label *newlabel) 207018334Speter{ 207118334Speter 207218334Speter MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 207318334Speter} 207418334Speter 207518334Speterstatic void 207618334Spetermac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 207718334Speter{ 207818334Speter 207918334Speter MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 208018334Speter} 208190075Sobrien 208218334Spetervoid 208318334Spetermac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 208418334Speter{ 208518334Speter 208618334Speter MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 208718334Speter socket, &socket->so_peerlabel); 208818334Speter} 208918334Speter 209018334Spetervoid 209118334Spetermac_set_socket_peer_from_socket(struct socket *oldsocket, 209218334Speter struct socket *newsocket) 209318334Speter{ 209418334Speter 209518334Speter MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 209618334Speter &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 209718334Speter} 209818334Speter 209918334Spetervoid 210090075Sobrienmac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 210118334Speter{ 210218334Speter 210318334Speter MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 210418334Speter datagram, &datagram->m_pkthdr.label); 210518334Speter} 210618334Speter 210718334Spetervoid 210818334Spetermac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 210918334Speter{ 211018334Speter 211118334Speter MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 211218334Speter fragment, &fragment->m_pkthdr.label); 211318334Speter} 211490075Sobrien 211518334Spetervoid 211618334Spetermac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 211790075Sobrien{ 211818334Speter 211918334Speter MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 212018334Speter &ipq->ipq_label); 212118334Speter} 212218334Speter 212318334Spetervoid 212418334Spetermac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 212518334Speter{ 212618334Speter 212718334Speter MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 212818334Speter newmbuf, &newmbuf->m_pkthdr.label); 212918334Speter} 213018334Speter 213118334Spetervoid 213218334Spetermac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 213318334Speter{ 213418334Speter 213518334Speter MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 213618334Speter &mbuf->m_pkthdr.label); 213718334Speter} 213818334Speter 213918334Spetervoid 214018334Spetermac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 214118334Speter{ 214218334Speter 214318334Speter MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 214418334Speter &mbuf->m_pkthdr.label); 214518334Speter} 214618334Speter 214718334Spetervoid 214818334Spetermac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 214918334Speter{ 215018334Speter 215118334Speter MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 215218334Speter &mbuf->m_pkthdr.label); 215318334Speter} 215418334Speter 215518334Spetervoid 215618334Spetermac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 215718334Speter struct mbuf *newmbuf) 215818334Speter{ 215918334Speter 216018334Speter MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 216118334Speter &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 216218334Speter &newmbuf->m_pkthdr.label); 216318334Speter} 216418334Speter 216518334Spetervoid 216618334Spetermac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 216718334Speter{ 216818334Speter 216918334Speter MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 217018334Speter newmbuf, &newmbuf->m_pkthdr.label); 217118334Speter} 217218334Speter 217318334Speterint 217418334Spetermac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 217518334Speter{ 217618334Speter int result; 217718334Speter 217818334Speter result = 1; 217918334Speter MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 218018334Speter ipq, &ipq->ipq_label); 218118334Speter 218218334Speter return (result); 218318334Speter} 218418334Speter 218518334Spetervoid 218618334Spetermac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 218718334Speter{ 218818334Speter 218918334Speter MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 219018334Speter &ipq->ipq_label); 219118334Speter} 219218334Speter 219318334Spetervoid 219418334Spetermac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 219518334Speter{ 219618334Speter 219718334Speter MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 219890075Sobrien &mbuf->m_pkthdr.label); 219918334Speter} 220018334Speter 220118334Spetervoid 220218334Spetermac_create_mount(struct ucred *cred, struct mount *mp) 220318334Speter{ 220418334Speter 220518334Speter MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 220618334Speter &mp->mnt_fslabel); 220750397Sobrien} 220850397Sobrien 220918334Spetervoid 221018334Spetermac_create_root_mount(struct ucred *cred, struct mount *mp) 221118334Speter{ 221218334Speter 221390075Sobrien MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 221418334Speter &mp->mnt_fslabel); 221518334Speter} 221618334Speter 221718334Speterint 221818334Spetermac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 221918334Speter{ 222018334Speter int error; 222118334Speter 222218334Speter if (!mac_enforce_network) 222318334Speter return (0); 222418334Speter 222518334Speter MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 222618334Speter &ifnet->if_label); 222718334Speter 222818334Speter return (error); 222918334Speter} 223018334Speter 223118334Speterstatic int 223218334Spetermac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 223318334Speter{ 223418334Speter int error; 223518334Speter 223618334Speter MAC_CHECK(check_cred_relabel, cred, newlabel); 223718334Speter 223818334Speter return (error); 223918334Speter} 224018334Speter 224118334Speterint 224218334Spetermac_check_cred_visible(struct ucred *u1, struct ucred *u2) 224318334Speter{ 224418334Speter int error; 224518334Speter 224618334Speter if (!mac_enforce_process) 224718334Speter return (0); 224818334Speter 224918334Speter MAC_CHECK(check_cred_visible, u1, u2); 225018334Speter 225118334Speter return (error); 225250397Sobrien} 225350397Sobrien 225418334Speterint 225518334Spetermac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 225618334Speter{ 225718334Speter int error; 225818334Speter 225918334Speter if (!mac_enforce_network) 226018334Speter return (0); 226118334Speter 226218334Speter KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 226318334Speter if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 226418334Speter if_printf(ifnet, "not initialized\n"); 226518334Speter 226618334Speter MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 226718334Speter &mbuf->m_pkthdr.label); 226890075Sobrien 226918334Speter return (error); 227018334Speter} 227118334Speter 227218334Speterint 227318334Spetermac_check_kenv_dump(struct ucred *cred) 227450397Sobrien{ 227518334Speter int error; 227618334Speter 227718334Speter if (!mac_enforce_system) 227818334Speter return (0); 227918334Speter 228018334Speter MAC_CHECK(check_kenv_dump, cred); 228118334Speter 228218334Speter return (error); 228318334Speter} 228418334Speter 228518334Speterint 228618334Spetermac_check_kenv_get(struct ucred *cred, char *name) 228718334Speter{ 228818334Speter int error; 228918334Speter 229018334Speter if (!mac_enforce_system) 229118334Speter return (0); 229218334Speter 229318334Speter MAC_CHECK(check_kenv_get, cred, name); 229418334Speter 229518334Speter return (error); 229618334Speter} 229718334Speter 229818334Speterint 229918334Spetermac_check_kenv_set(struct ucred *cred, char *name, char *value) 230018334Speter{ 230118334Speter int error; 230218334Speter 230318334Speter if (!mac_enforce_system) 230418334Speter return (0); 230518334Speter 230618334Speter MAC_CHECK(check_kenv_set, cred, name, value); 230718334Speter 230818334Speter return (error); 230918334Speter} 231018334Speter 231118334Speterint 231218334Spetermac_check_kenv_unset(struct ucred *cred, char *name) 231318334Speter{ 231418334Speter int error; 231518334Speter 231618334Speter if (!mac_enforce_system) 231718334Speter return (0); 231818334Speter 231918334Speter MAC_CHECK(check_kenv_unset, cred, name); 232018334Speter 232118334Speter return (error); 232218334Speter} 232318334Speter 232490075Sobrienint 232518334Spetermac_check_kld_load(struct ucred *cred, struct vnode *vp) 232618334Speter{ 232790075Sobrien int error; 232890075Sobrien 232990075Sobrien ASSERT_VOP_LOCKED(vp, "mac_check_kld_load"); 233090075Sobrien 233118334Speter if (!mac_enforce_kld) 233218334Speter return (0); 233318334Speter 233418334Speter MAC_CHECK(check_kld_load, cred, vp, &vp->v_label); 233518334Speter 233618334Speter return (error); 233718334Speter} 233818334Speter 233918334Speterint 234018334Spetermac_check_kld_stat(struct ucred *cred) 234118334Speter{ 234218334Speter int error; 234318334Speter 234418334Speter if (!mac_enforce_kld) 234552284Sobrien return (0); 234618334Speter 234718334Speter MAC_CHECK(check_kld_stat, cred); 234890075Sobrien 234918334Speter return (error); 235018334Speter} 235118334Speter 235290075Sobrienint 235318334Spetermac_check_kld_unload(struct ucred *cred) 235418334Speter{ 235518334Speter int error; 235618334Speter 235790075Sobrien if (!mac_enforce_kld) 235890075Sobrien return (0); 235990075Sobrien 236018334Speter MAC_CHECK(check_kld_unload, cred); 236190075Sobrien 236290075Sobrien return (error); 236318334Speter} 236418334Speter 236518334Speterint 236690075Sobrienmac_check_mount_stat(struct ucred *cred, struct mount *mount) 236790075Sobrien{ 236890075Sobrien int error; 236990075Sobrien 237090075Sobrien if (!mac_enforce_fs) 237190075Sobrien return (0); 237290075Sobrien 237390075Sobrien MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 237490075Sobrien 237590075Sobrien return (error); 237690075Sobrien} 237790075Sobrien 237890075Sobrienint 237990075Sobrienmac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 238090075Sobrien void *data) 238190075Sobrien{ 238218334Speter int error; 238318334Speter 238418334Speter PIPE_LOCK_ASSERT(pipe, MA_OWNED); 238518334Speter 238618334Speter if (!mac_enforce_pipe) 238718334Speter return (0); 238818334Speter 238918334Speter MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 239018334Speter 239118334Speter return (error); 239218334Speter} 239318334Speter 239418334Speterint 239590075Sobrienmac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 239690075Sobrien{ 239718334Speter int error; 239818334Speter 239918334Speter PIPE_LOCK_ASSERT(pipe, MA_OWNED); 240018334Speter 240118334Speter if (!mac_enforce_pipe) 240218334Speter return (0); 240350397Sobrien 240450397Sobrien MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 240550397Sobrien 240650397Sobrien return (error); 240750397Sobrien} 240850397Sobrien 240950397Sobrienint 241018334Spetermac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 241118334Speter{ 241218334Speter int error; 241318334Speter 241418334Speter PIPE_LOCK_ASSERT(pipe, MA_OWNED); 241518334Speter 241618334Speter if (!mac_enforce_pipe) 241718334Speter return (0); 241818334Speter 241918334Speter MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 242018334Speter 242118334Speter return (error); 242218334Speter} 242390075Sobrien 242490075Sobrienstatic int 242518334Spetermac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 242618334Speter struct label *newlabel) 242718334Speter{ 242890075Sobrien int error; 242990075Sobrien 243018334Speter PIPE_LOCK_ASSERT(pipe, MA_OWNED); 243190075Sobrien 243290075Sobrien if (!mac_enforce_pipe) 243318334Speter return (0); 243418334Speter 243518334Speter MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 243618334Speter 243718334Speter return (error); 243818334Speter} 243918334Speter 244018334Speterint 244118334Spetermac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 244218334Speter{ 244318334Speter int error; 244418334Speter 244518334Speter PIPE_LOCK_ASSERT(pipe, MA_OWNED); 244618334Speter 244718334Speter if (!mac_enforce_pipe) 244818334Speter return (0); 244918334Speter 245018334Speter MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 245118334Speter 245218334Speter return (error); 245318334Speter} 245418334Speter 245518334Speterint 245618334Spetermac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 245718334Speter{ 245890075Sobrien int error; 245918334Speter 246018334Speter PIPE_LOCK_ASSERT(pipe, MA_OWNED); 246118334Speter 246290075Sobrien if (!mac_enforce_pipe) 246318334Speter return (0); 246418334Speter 246518334Speter MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 246618334Speter 246718334Speter return (error); 246818334Speter} 246918334Speter 247018334Speterint 247118334Spetermac_check_proc_debug(struct ucred *cred, struct proc *proc) 247218334Speter{ 247318334Speter int error; 247418334Speter 247518334Speter PROC_LOCK_ASSERT(proc, MA_OWNED); 247618334Speter 247718334Speter if (!mac_enforce_process) 247818334Speter return (0); 247918334Speter 248018334Speter MAC_CHECK(check_proc_debug, cred, proc); 248118334Speter 248218334Speter return (error); 248318334Speter} 248418334Speter 248590075Sobrienint 248690075Sobrienmac_check_proc_sched(struct ucred *cred, struct proc *proc) 248790075Sobrien{ 248890075Sobrien int error; 248990075Sobrien 249018334Speter PROC_LOCK_ASSERT(proc, MA_OWNED); 249190075Sobrien 249290075Sobrien if (!mac_enforce_process) 249318334Speter return (0); 249418334Speter 249518334Speter MAC_CHECK(check_proc_sched, cred, proc); 249618334Speter 249718334Speter return (error); 249818334Speter} 249918334Speter 250018334Speterint 250118334Spetermac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 250218334Speter{ 250318334Speter int error; 250418334Speter 250518334Speter PROC_LOCK_ASSERT(proc, MA_OWNED); 250690075Sobrien 250718334Speter if (!mac_enforce_process) 250818334Speter return (0); 250990075Sobrien 251018334Speter MAC_CHECK(check_proc_signal, cred, proc, signum); 251118334Speter 251218334Speter return (error); 251318334Speter} 251418334Speter 251518334Speterint 251690075Sobrienmac_check_socket_bind(struct ucred *ucred, struct socket *socket, 251790075Sobrien struct sockaddr *sockaddr) 251818334Speter{ 251918334Speter int error; 252090075Sobrien 252190075Sobrien if (!mac_enforce_socket) 252218334Speter return (0); 252318334Speter 252418334Speter MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 252518334Speter sockaddr); 252618334Speter 252718334Speter return (error); 252818334Speter} 252918334Speter 253018334Speterint 253118334Spetermac_check_socket_connect(struct ucred *cred, struct socket *socket, 253218334Speter struct sockaddr *sockaddr) 253318334Speter{ 253418334Speter int error; 253518334Speter 253618334Speter if (!mac_enforce_socket) 253790075Sobrien return (0); 253890075Sobrien 253918334Speter MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 254018334Speter sockaddr); 254118334Speter 254218334Speter return (error); 254318334Speter} 254418334Speter 254518334Speterint 254618334Spetermac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 254718334Speter{ 254818334Speter int error; 254918334Speter 255018334Speter if (!mac_enforce_socket) 255118334Speter return (0); 255218334Speter 255318334Speter MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 255418334Speter &mbuf->m_pkthdr.label); 255518334Speter 255618334Speter return (error); 255718334Speter} 255818334Speter 255918334Speterint 256018334Spetermac_check_socket_listen(struct ucred *cred, struct socket *socket) 256118334Speter{ 256218334Speter int error; 256318334Speter 256490075Sobrien if (!mac_enforce_socket) 256590075Sobrien return (0); 256618334Speter 256718334Speter MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 256818334Speter return (error); 256918334Speter} 257018334Speter 257118334Speterint 257218334Spetermac_check_socket_receive(struct ucred *cred, struct socket *so) 257318334Speter{ 257418334Speter int error; 257518334Speter 257618334Speter if (!mac_enforce_socket) 257718334Speter return (0); 257818334Speter 257918334Speter MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 258018334Speter 258118334Speter return (error); 258218334Speter} 258318334Speter 258418334Speterstatic int 258518334Spetermac_check_socket_relabel(struct ucred *cred, struct socket *socket, 258618334Speter struct label *newlabel) 258718334Speter{ 258818334Speter int error; 258990075Sobrien 259018334Speter MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 259118334Speter newlabel); 259218334Speter 259318334Speter return (error); 259418334Speter} 259518334Speter 259618334Speterint 259718334Spetermac_check_socket_send(struct ucred *cred, struct socket *so) 259818334Speter{ 259990075Sobrien int error; 260018334Speter 260118334Speter if (!mac_enforce_socket) 260218334Speter return (0); 260318334Speter 260418334Speter MAC_CHECK(check_socket_send, cred, so, &so->so_label); 260590075Sobrien 260618334Speter return (error); 260718334Speter} 260818334Speter 260918334Speterint 261018334Spetermac_check_socket_visible(struct ucred *cred, struct socket *socket) 261118334Speter{ 261218334Speter int error; 261318334Speter 261418334Speter if (!mac_enforce_socket) 261590075Sobrien return (0); 261618334Speter 261790075Sobrien MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 261818334Speter 261918334Speter return (error); 262018334Speter} 262118334Speter 262218334Speterint 262318334Spetermac_check_system_acct(struct ucred *cred, struct vnode *vp) 262418334Speter{ 262518334Speter int error; 262618334Speter 262718334Speter if (vp != NULL) { 262818334Speter ASSERT_VOP_LOCKED(vp, "mac_check_system_acct"); 262918334Speter } 263018334Speter 263118334Speter if (!mac_enforce_system) 263218334Speter return (0); 263318334Speter 263418334Speter MAC_CHECK(check_system_acct, cred, vp, 263518334Speter vp != NULL ? &vp->v_label : NULL); 263618334Speter 263718334Speter return (error); 263818334Speter} 263918334Speter 264018334Speterint 264118334Spetermac_check_system_nfsd(struct ucred *cred) 264218334Speter{ 264318334Speter int error; 264418334Speter 264518334Speter if (!mac_enforce_system) 264618334Speter return (0); 264718334Speter 264818334Speter MAC_CHECK(check_system_nfsd, cred); 264918334Speter 265018334Speter return (error); 265118334Speter} 265218334Speter 265318334Speterint 265418334Spetermac_check_system_reboot(struct ucred *cred, int howto) 265518334Speter{ 265618334Speter int error; 265718334Speter 265818334Speter if (!mac_enforce_system) 265990075Sobrien return (0); 266090075Sobrien 266118334Speter MAC_CHECK(check_system_reboot, cred, howto); 266218334Speter 266318334Speter return (error); 266418334Speter} 266518334Speter 266618334Speterint 266750397Sobrienmac_check_system_settime(struct ucred *cred) 266850397Sobrien{ 266950397Sobrien int error; 267050397Sobrien 267118334Speter if (!mac_enforce_system) 267218334Speter return (0); 267318334Speter 267418334Speter MAC_CHECK(check_system_settime, cred); 267590075Sobrien 267618334Speter return (error); 267718334Speter} 267890075Sobrien 267918334Speterint 268018334Spetermac_check_system_swapon(struct ucred *cred, struct vnode *vp) 268118334Speter{ 268218334Speter int error; 268318334Speter 268418334Speter ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 268518334Speter 268618334Speter if (!mac_enforce_system) 268718334Speter return (0); 268818334Speter 268918334Speter MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 269018334Speter return (error); 269118334Speter} 269218334Speter 269318334Speterint 269418334Spetermac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 269518334Speter void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 269618334Speter{ 269718334Speter int error; 269818334Speter 269918334Speter /* 270018334Speter * XXXMAC: We're very much like to assert the SYSCTL_LOCK here, 270118334Speter * but since it's not exported from kern_sysctl.c, we can't. 270218334Speter */ 270318334Speter if (!mac_enforce_system) 270418334Speter return (0); 270518334Speter 270618334Speter MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp, 270718334Speter inkernel, new, newlen); 270818334Speter 270918334Speter return (error); 271018334Speter} 271118334Speter 271218334Speterint 271318334Spetermac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 271418334Speter struct ifnet *ifnet) 271518334Speter{ 271618334Speter char *elements, *buffer; 271718334Speter struct mac mac; 271818334Speter int error; 271918334Speter 272018334Speter error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 272118334Speter if (error) 272218334Speter return (error); 272318334Speter 272418334Speter error = mac_check_structmac_consistent(&mac); 272518334Speter if (error) 272618334Speter return (error); 272718334Speter 272818334Speter elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 272918334Speter error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 273018334Speter if (error) { 273118334Speter free(elements, M_MACTEMP); 273218334Speter return (error); 273318334Speter } 273418334Speter 273518334Speter buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 273618334Speter error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 273718334Speter buffer, mac.m_buflen, M_WAITOK); 273818334Speter if (error == 0) 273918334Speter error = copyout(buffer, mac.m_string, strlen(buffer)+1); 274018334Speter 274118334Speter free(buffer, M_MACTEMP); 274296263Sobrien free(elements, M_MACTEMP); 274318334Speter 274418334Speter return (error); 274518334Speter} 274618334Speter 274796263Sobrienint 274896263Sobrienmac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 274996263Sobrien struct ifnet *ifnet) 275096263Sobrien{ 275196263Sobrien struct label intlabel; 275296263Sobrien struct mac mac; 275396263Sobrien char *buffer; 275490075Sobrien int error; 275590075Sobrien 275618334Speter error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 275718334Speter if (error) 275818334Speter return (error); 275918334Speter 276018334Speter error = mac_check_structmac_consistent(&mac); 276118334Speter if (error) 276218334Speter return (error); 276318334Speter 276418334Speter buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 276518334Speter error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 276618334Speter if (error) { 276718334Speter free(buffer, M_MACTEMP); 276818334Speter return (error); 276918334Speter } 277018334Speter 277118334Speter mac_init_ifnet_label(&intlabel); 277218334Speter error = mac_internalize_ifnet_label(&intlabel, buffer); 277318334Speter free(buffer, M_MACTEMP); 277418334Speter if (error) { 277518334Speter mac_destroy_ifnet_label(&intlabel); 277618334Speter return (error); 277718334Speter } 277818334Speter 277918334Speter /* 278018334Speter * XXX: Note that this is a redundant privilege check, since 278118334Speter * policies impose this check themselves if required by the 278218334Speter * policy. Eventually, this should go away. 278318334Speter */ 278418334Speter error = suser_cred(cred, 0); 278518334Speter if (error) { 278618334Speter mac_destroy_ifnet_label(&intlabel); 278718334Speter return (error); 278818334Speter } 278950397Sobrien 279018334Speter MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 279118334Speter &intlabel); 279218334Speter if (error) { 279318334Speter mac_destroy_ifnet_label(&intlabel); 279418334Speter return (error); 279518334Speter } 279618334Speter 279750397Sobrien MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 279850397Sobrien 279918334Speter mac_destroy_ifnet_label(&intlabel); 280018334Speter return (0); 280150397Sobrien} 280250397Sobrien 280318334Spetervoid 280418334Spetermac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 280518334Speter{ 280618334Speter 280718334Speter MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 280818334Speter} 280918334Speter 281052284Sobrienvoid 281118334Spetermac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 281218334Speter struct devfs_dirent *de) 281390075Sobrien{ 281490075Sobrien 281518334Speter MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de, 281690075Sobrien &de->de_label); 281790075Sobrien} 281890075Sobrien 281990075Sobrienvoid 282090075Sobrienmac_create_devfs_directory(char *dirname, int dirnamelen, 282190075Sobrien struct devfs_dirent *de) 282290075Sobrien{ 282390075Sobrien 282418334Speter MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 282518334Speter &de->de_label); 282618334Speter} 282718334Speter 282818334Speterint 282918334Spetermac_setsockopt_label_set(struct ucred *cred, struct socket *so, 283050397Sobrien struct mac *mac) 283150397Sobrien{ 283250397Sobrien struct label intlabel; 283318334Speter char *buffer; 283418334Speter int error; 283518334Speter 283618334Speter error = mac_check_structmac_consistent(mac); 283718334Speter if (error) 283818334Speter return (error); 283918334Speter 284018334Speter buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 284118334Speter error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 284218334Speter if (error) { 284318334Speter free(buffer, M_MACTEMP); 284418334Speter return (error); 284518334Speter } 284618334Speter 284718334Speter mac_init_socket_label(&intlabel, M_WAITOK); 284818334Speter error = mac_internalize_socket_label(&intlabel, buffer); 284918334Speter free(buffer, M_MACTEMP); 285018334Speter if (error) { 285118334Speter mac_destroy_socket_label(&intlabel); 285218334Speter return (error); 285318334Speter } 285418334Speter 285518334Speter mac_check_socket_relabel(cred, so, &intlabel); 285618334Speter if (error) { 285718334Speter mac_destroy_socket_label(&intlabel); 285818334Speter return (error); 285918334Speter } 286018334Speter 286118334Speter mac_relabel_socket(cred, so, &intlabel); 286218334Speter 286318334Speter mac_destroy_socket_label(&intlabel); 286418334Speter return (0); 286518334Speter} 286618334Speter 286718334Speterint 286818334Spetermac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 286970635Sobrien{ 287018334Speter int error; 287118334Speter 287270635Sobrien PIPE_LOCK_ASSERT(pipe, MA_OWNED); 287370635Sobrien 287470635Sobrien error = mac_check_pipe_relabel(cred, pipe, label); 287570635Sobrien if (error) 287690075Sobrien return (error); 287790075Sobrien 287890075Sobrien mac_relabel_pipe(cred, pipe, label); 287990075Sobrien 288090075Sobrien return (0); 288190075Sobrien} 288290075Sobrien 288390075Sobrienint 288490075Sobrienmac_getsockopt_label_get(struct ucred *cred, struct socket *so, 288590075Sobrien struct mac *mac) 288690075Sobrien{ 288790075Sobrien char *buffer, *elements; 288890075Sobrien int error; 288990075Sobrien 289090075Sobrien error = mac_check_structmac_consistent(mac); 289152284Sobrien if (error) 289290075Sobrien return (error); 289390075Sobrien 289490075Sobrien elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 289590075Sobrien error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 289652284Sobrien if (error) { 289790075Sobrien free(elements, M_MACTEMP); 289890075Sobrien return (error); 289990075Sobrien } 290090075Sobrien 290190075Sobrien buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 290290075Sobrien error = mac_externalize_socket_label(&so->so_label, elements, 290390075Sobrien buffer, mac->m_buflen, M_WAITOK); 290490075Sobrien if (error == 0) 290590075Sobrien error = copyout(buffer, mac->m_string, strlen(buffer)+1); 290652284Sobrien 290718334Speter free(buffer, M_MACTEMP); 290818334Speter free(elements, M_MACTEMP); 290918334Speter 291018334Speter return (error); 291118334Speter} 291218334Speter 291318334Speterint 291418334Spetermac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 291518334Speter struct mac *mac) 291696263Sobrien{ 291718334Speter char *elements, *buffer; 291896263Sobrien int error; 291996263Sobrien 292096263Sobrien error = mac_check_structmac_consistent(mac); 292196263Sobrien if (error) 292296263Sobrien return (error); 292396263Sobrien 292496263Sobrien elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 292518334Speter error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 292618334Speter if (error) { 292718334Speter free(elements, M_MACTEMP); 292818334Speter return (error); 292918334Speter } 293090075Sobrien 293190075Sobrien buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 293218334Speter error = mac_externalize_socket_peer_label(&so->so_peerlabel, 293318334Speter elements, buffer, mac->m_buflen, M_WAITOK); 293418334Speter if (error == 0) 293518334Speter error = copyout(buffer, mac->m_string, strlen(buffer)+1); 293618334Speter 293718334Speter free(buffer, M_MACTEMP); 293818334Speter free(elements, M_MACTEMP); 293918334Speter 294018334Speter return (error); 294118334Speter} 294218334Speter 294318334Speter/* 294418334Speter * Implementation of VOP_SETLABEL() that relies on extended attributes 294518334Speter * to store label data. Can be referenced by filesystems supporting 294618334Speter * extended attributes. 294718334Speter */ 294818334Speterint 294918334Spetervop_stdsetlabel_ea(struct vop_setlabel_args *ap) 295018334Speter{ 295118334Speter struct vnode *vp = ap->a_vp; 295218334Speter struct label *intlabel = ap->a_label; 295318334Speter int error; 295418334Speter 295518334Speter ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 295618334Speter 295718334Speter if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 295818334Speter return (EOPNOTSUPP); 295918334Speter 296050397Sobrien error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 296150397Sobrien if (error) 296252284Sobrien return (error); 296390075Sobrien 296490075Sobrien mac_relabel_vnode(ap->a_cred, vp, intlabel); 296590075Sobrien 296690075Sobrien return (0); 296790075Sobrien} 296890075Sobrien 296990075Sobrienstatic int 297090075Sobrienvn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 297190075Sobrien{ 297218334Speter int error; 297370635Sobrien 297470635Sobrien if (vp->v_mount == NULL) { 297570635Sobrien /* printf("vn_setlabel: null v_mount\n"); */ 297618334Speter if (vp->v_type != VNON) 297718334Speter printf("vn_setlabel: null v_mount with non-VNON\n"); 297818334Speter return (EBADF); 297918334Speter } 298018334Speter 298118334Speter if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 298290075Sobrien return (EOPNOTSUPP); 298390075Sobrien 298490075Sobrien /* 298590075Sobrien * Multi-phase commit. First check the policies to confirm the 298690075Sobrien * change is OK. Then commit via the filesystem. Finally, 298790075Sobrien * update the actual vnode label. Question: maybe the filesystem 298890075Sobrien * should update the vnode at the end as part of VOP_SETLABEL()? 298918334Speter */ 299018334Speter error = mac_check_vnode_relabel(cred, vp, intlabel); 299118334Speter if (error) 299218334Speter return (error); 299318334Speter 299418334Speter /* 299518334Speter * VADMIN provides the opportunity for the filesystem to make 299618334Speter * decisions about who is and is not able to modify labels 299718334Speter * and protections on files. This might not be right. We can't 299818334Speter * assume VOP_SETLABEL() will do it, because we might implement 299918334Speter * that as part of vop_stdsetlabel_ea(). 300018334Speter */ 300118334Speter error = VOP_ACCESS(vp, VADMIN, cred, curthread); 300218334Speter if (error) 300318334Speter return (error); 300418334Speter 300518334Speter error = VOP_SETLABEL(vp, intlabel, cred, curthread); 300618334Speter if (error) 300718334Speter return (error); 300818334Speter 300918334Speter return (0); 301090075Sobrien} 301190075Sobrien 301290075Sobrienint 301318334Speter__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 301490075Sobrien{ 301590075Sobrien char *elements, *buffer; 301690075Sobrien struct mac mac; 301790075Sobrien struct proc *tproc; 301890075Sobrien struct ucred *tcred; 301990075Sobrien int error; 302090075Sobrien 302190075Sobrien error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac)); 302290075Sobrien if (error) 302390075Sobrien return (error); 302490075Sobrien 302590075Sobrien error = mac_check_structmac_consistent(&mac); 302690075Sobrien if (error) 302790075Sobrien return (error); 302890075Sobrien 302990075Sobrien tproc = pfind(uap->pid); 303090075Sobrien if (tproc == NULL) 303190075Sobrien return (ESRCH); 303290075Sobrien 303390075Sobrien tcred = NULL; /* Satisfy gcc. */ 303490075Sobrien error = p_cansee(td, tproc); 303590075Sobrien if (error == 0) 303690075Sobrien tcred = crhold(tproc->p_ucred); 303790075Sobrien PROC_UNLOCK(tproc); 303890075Sobrien if (error) 303990075Sobrien return (error); 304090075Sobrien 304190075Sobrien elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 304290075Sobrien error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 304390075Sobrien if (error) { 304490075Sobrien free(elements, M_MACTEMP); 304590075Sobrien crfree(tcred); 304690075Sobrien return (error); 304790075Sobrien } 304890075Sobrien 304990075Sobrien buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 305090075Sobrien error = mac_externalize_cred_label(&tcred->cr_label, elements, 305190075Sobrien buffer, mac.m_buflen, M_WAITOK); 305290075Sobrien if (error == 0) 305390075Sobrien error = copyout(buffer, mac.m_string, strlen(buffer)+1); 305490075Sobrien 305590075Sobrien free(buffer, M_MACTEMP); 305690075Sobrien free(elements, M_MACTEMP); 305790075Sobrien crfree(tcred); 305818334Speter return (error); 305918334Speter} 306090075Sobrien 306118334Speter/* 306290075Sobrien * MPSAFE 306390075Sobrien */ 306490075Sobrienint 306590075Sobrien__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 306690075Sobrien{ 306790075Sobrien char *elements, *buffer; 306818334Speter struct mac mac; 306990075Sobrien int error; 307090075Sobrien 307190075Sobrien error = copyin(uap->mac_p, &mac, sizeof(mac)); 307290075Sobrien if (error) 307318334Speter return (error); 307490075Sobrien 307590075Sobrien error = mac_check_structmac_consistent(&mac); 307690075Sobrien if (error) 307718334Speter return (error); 307890075Sobrien 307990075Sobrien elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 308090075Sobrien error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 308118334Speter if (error) { 308218334Speter free(elements, M_MACTEMP); 308318334Speter return (error); 308418334Speter } 308518334Speter 308618334Speter buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 308718334Speter error = mac_externalize_cred_label(&td->td_ucred->cr_label, 308818334Speter elements, buffer, mac.m_buflen, M_WAITOK); 308918334Speter if (error == 0) 309018334Speter error = copyout(buffer, mac.m_string, strlen(buffer)+1); 309118334Speter 309218334Speter free(buffer, M_MACTEMP); 309318334Speter free(elements, M_MACTEMP); 309418334Speter return (error); 309518334Speter} 309618334Speter 309718334Speter/* 309890075Sobrien * MPSAFE 309990075Sobrien */ 310018334Speterint 310118334Speter__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 310290075Sobrien{ 310390075Sobrien struct ucred *newcred, *oldcred; 310418334Speter struct label intlabel; 310518334Speter struct proc *p; 310652284Sobrien struct mac mac; 310752284Sobrien char *buffer; 310852284Sobrien int error; 310952284Sobrien 311052284Sobrien error = copyin(uap->mac_p, &mac, sizeof(mac)); 311152284Sobrien if (error) 311252284Sobrien return (error); 311352284Sobrien 311418334Speter error = mac_check_structmac_consistent(&mac); 311518334Speter if (error) 311618334Speter return (error); 311718334Speter 311818334Speter buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 311918334Speter error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 312018334Speter if (error) { 312118334Speter free(buffer, M_MACTEMP); 312290075Sobrien return (error); 312390075Sobrien } 312490075Sobrien 312590075Sobrien mac_init_cred_label(&intlabel); 312690075Sobrien error = mac_internalize_cred_label(&intlabel, buffer); 312718334Speter free(buffer, M_MACTEMP); 312818334Speter if (error) { 312918334Speter mac_destroy_cred_label(&intlabel); 313018334Speter return (error); 313118334Speter } 313218334Speter 313318334Speter newcred = crget(); 313418334Speter 313518334Speter p = td->td_proc; 313618334Speter PROC_LOCK(p); 313718334Speter oldcred = p->p_ucred; 313890075Sobrien 313990075Sobrien error = mac_check_cred_relabel(oldcred, &intlabel); 314090075Sobrien if (error) { 314118334Speter PROC_UNLOCK(p); 314218334Speter crfree(newcred); 314318334Speter goto out; 314418334Speter } 314518334Speter 314618334Speter setsugid(p); 314718334Speter crcopy(newcred, oldcred); 314818334Speter mac_relabel_cred(newcred, &intlabel); 314990075Sobrien p->p_ucred = newcred; 315090075Sobrien 315190075Sobrien /* 315218334Speter * Grab additional reference for use while revoking mmaps, prior 315318334Speter * to releasing the proc lock and sharing the cred. 315418334Speter */ 315518334Speter crhold(newcred); 315618334Speter PROC_UNLOCK(p); 315718334Speter 315890075Sobrien if (mac_enforce_vm) { 315990075Sobrien mtx_lock(&Giant); 316018334Speter mac_cred_mmapped_drop_perms(td, newcred); 316118334Speter mtx_unlock(&Giant); 316218334Speter } 316390075Sobrien 316418334Speter crfree(newcred); /* Free revocation reference. */ 316518334Speter crfree(oldcred); 316618334Speter 316718334Speterout: 316818334Speter mac_destroy_cred_label(&intlabel); 316990075Sobrien return (error); 317018334Speter} 317118334Speter 317250397Sobrien/* 317350397Sobrien * MPSAFE 317450397Sobrien */ 317518334Speterint 317690075Sobrien__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 317718334Speter{ 317818334Speter char *elements, *buffer; 317950397Sobrien struct label intlabel; 318050397Sobrien struct file *fp; 318150397Sobrien struct mac mac; 318250397Sobrien struct vnode *vp; 318318334Speter struct pipe *pipe; 318450397Sobrien short label_type; 318550397Sobrien int error; 318650397Sobrien 318750397Sobrien error = copyin(uap->mac_p, &mac, sizeof(mac)); 318850397Sobrien if (error) 318990075Sobrien return (error); 319050397Sobrien 319190075Sobrien error = mac_check_structmac_consistent(&mac); 319218334Speter if (error) 319390075Sobrien return (error); 319490075Sobrien 319590075Sobrien elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 319618334Speter error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 319718334Speter if (error) { 319818334Speter free(elements, M_MACTEMP); 319990075Sobrien return (error); 320090075Sobrien } 320190075Sobrien 320290075Sobrien buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 320318334Speter mtx_lock(&Giant); /* VFS */ 320418334Speter error = fget(td, SCARG(uap, fd), &fp); 320518334Speter if (error) 320690075Sobrien goto out; 320718334Speter 320818334Speter label_type = fp->f_type; 320950397Sobrien switch (fp->f_type) { 321050397Sobrien case DTYPE_FIFO: 321118334Speter case DTYPE_VNODE: 321218334Speter vp = (struct vnode *)fp->f_data; 321318334Speter 321418334Speter mac_init_vnode_label(&intlabel); 321518334Speter 321690075Sobrien vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 321790075Sobrien mac_copy_vnode_label(&vp->v_label, &intlabel); 321818334Speter VOP_UNLOCK(vp, 0, td); 321950397Sobrien 322050397Sobrien break; 322150397Sobrien case DTYPE_PIPE: 322250397Sobrien pipe = (struct pipe *)fp->f_data; 322350397Sobrien 322450397Sobrien mac_init_pipe_label(&intlabel); 322518334Speter 322618334Speter PIPE_LOCK(pipe); 322718334Speter mac_copy_pipe_label(pipe->pipe_label, &intlabel); 322890075Sobrien PIPE_UNLOCK(pipe); 322990075Sobrien break; 323090075Sobrien default: 323118334Speter error = EINVAL; 323218334Speter fdrop(fp, td); 323318334Speter goto out; 323418334Speter } 323590075Sobrien fdrop(fp, td); 323618334Speter 323718334Speter switch (label_type) { 323818334Speter case DTYPE_FIFO: 323918334Speter case DTYPE_VNODE: 324018334Speter if (error == 0) 324190075Sobrien error = mac_externalize_vnode_label(&intlabel, 324290075Sobrien elements, buffer, mac.m_buflen, M_WAITOK); 324390075Sobrien mac_destroy_vnode_label(&intlabel); 324490075Sobrien break; 324590075Sobrien case DTYPE_PIPE: 324690075Sobrien error = mac_externalize_pipe_label(&intlabel, elements, 324790075Sobrien buffer, mac.m_buflen, M_WAITOK); 324890075Sobrien mac_destroy_pipe_label(&intlabel); 324990075Sobrien break; 325090075Sobrien default: 325190075Sobrien panic("__mac_get_fd: corrupted label_type"); 325290075Sobrien } 325390075Sobrien 325490075Sobrien if (error == 0) 325590075Sobrien error = copyout(buffer, mac.m_string, strlen(buffer)+1); 325690075Sobrien 325790075Sobrienout: 325890075Sobrien mtx_unlock(&Giant); /* VFS */ 325990075Sobrien free(buffer, M_MACTEMP); 326090075Sobrien free(elements, M_MACTEMP); 326190075Sobrien 326290075Sobrien return (error); 326390075Sobrien} 326490075Sobrien 326590075Sobrien/* 326690075Sobrien * MPSAFE 326790075Sobrien */ 326890075Sobrienint 326990075Sobrien__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 327090075Sobrien{ 327190075Sobrien char *elements, *buffer; 327290075Sobrien struct nameidata nd; 327390075Sobrien struct label intlabel; 327490075Sobrien struct mac mac; 327590075Sobrien int error; 327690075Sobrien 327790075Sobrien error = copyin(uap->mac_p, &mac, sizeof(mac)); 327890075Sobrien if (error) 327990075Sobrien return (error); 328090075Sobrien 328190075Sobrien error = mac_check_structmac_consistent(&mac); 328290075Sobrien if (error) 328390075Sobrien return (error); 328490075Sobrien 328590075Sobrien elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 328690075Sobrien error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 328790075Sobrien if (error) { 328890075Sobrien free(elements, M_MACTEMP); 328990075Sobrien return (error); 329090075Sobrien } 329190075Sobrien 329290075Sobrien buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 329390075Sobrien mtx_lock(&Giant); /* VFS */ 329490075Sobrien NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 329590075Sobrien td); 329690075Sobrien error = namei(&nd); 329790075Sobrien if (error) 329890075Sobrien goto out; 329990075Sobrien 330090075Sobrien mac_init_vnode_label(&intlabel); 330190075Sobrien mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 330290075Sobrien error = mac_externalize_vnode_label(&intlabel, elements, buffer, 330390075Sobrien mac.m_buflen, M_WAITOK); 330490075Sobrien 330590075Sobrien NDFREE(&nd, 0); 330690075Sobrien mac_destroy_vnode_label(&intlabel); 330790075Sobrien 330890075Sobrien if (error == 0) 330990075Sobrien error = copyout(buffer, mac.m_string, strlen(buffer)+1); 331090075Sobrien 331190075Sobrienout: 331290075Sobrien mtx_unlock(&Giant); /* VFS */ 331390075Sobrien 331490075Sobrien free(buffer, M_MACTEMP); 331590075Sobrien free(elements, M_MACTEMP); 331690075Sobrien 331790075Sobrien return (error); 331890075Sobrien} 331990075Sobrien 332090075Sobrien/* 332190075Sobrien * MPSAFE 332290075Sobrien */ 332390075Sobrienint 332490075Sobrien__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 332590075Sobrien{ 332690075Sobrien char *elements, *buffer; 332790075Sobrien struct nameidata nd; 332890075Sobrien struct label intlabel; 332990075Sobrien struct mac mac; 333090075Sobrien int error; 333190075Sobrien 333290075Sobrien error = copyin(uap->mac_p, &mac, sizeof(mac)); 333390075Sobrien if (error) 333490075Sobrien return (error); 333590075Sobrien 333652284Sobrien error = mac_check_structmac_consistent(&mac); 333752284Sobrien if (error) 333852284Sobrien return (error); 333952284Sobrien 334052284Sobrien elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 334152284Sobrien error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 334252284Sobrien if (error) { 334352284Sobrien free(elements, M_MACTEMP); 334452284Sobrien return (error); 334590075Sobrien } 334652284Sobrien 334752284Sobrien buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 334852284Sobrien mtx_lock(&Giant); /* VFS */ 334952284Sobrien NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 335052284Sobrien td); 335152284Sobrien error = namei(&nd); 335252284Sobrien if (error) 335352284Sobrien goto out; 335490075Sobrien 335552284Sobrien mac_init_vnode_label(&intlabel); 335652284Sobrien mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 335752284Sobrien error = mac_externalize_vnode_label(&intlabel, elements, buffer, 335852284Sobrien mac.m_buflen, M_WAITOK); 335952284Sobrien NDFREE(&nd, 0); 336052284Sobrien mac_destroy_vnode_label(&intlabel); 336152284Sobrien 336290075Sobrien if (error == 0) 336390075Sobrien error = copyout(buffer, mac.m_string, strlen(buffer)+1); 336490075Sobrien 336590075Sobrienout: 336652284Sobrien mtx_unlock(&Giant); /* VFS */ 336790075Sobrien 336890075Sobrien free(buffer, M_MACTEMP); 336990075Sobrien free(elements, M_MACTEMP); 337090075Sobrien 337190075Sobrien return (error); 337290075Sobrien} 337352284Sobrien 337452284Sobrien/* 337552284Sobrien * MPSAFE 337652284Sobrien */ 337752284Sobrienint 337852284Sobrien__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 337952284Sobrien{ 338052284Sobrien struct label intlabel; 338152284Sobrien struct pipe *pipe; 338252284Sobrien struct file *fp; 338352284Sobrien struct mount *mp; 338490075Sobrien struct vnode *vp; 338552284Sobrien struct mac mac; 338652284Sobrien char *buffer; 338790075Sobrien int error; 338890075Sobrien 338990075Sobrien error = copyin(uap->mac_p, &mac, sizeof(mac)); 339090075Sobrien if (error) 339152284Sobrien return (error); 339252284Sobrien 339390075Sobrien error = mac_check_structmac_consistent(&mac); 339452284Sobrien if (error) 339590075Sobrien return (error); 339690075Sobrien 339790075Sobrien buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 339890075Sobrien error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 339990075Sobrien if (error) { 340018334Speter free(buffer, M_MACTEMP); 340190075Sobrien return (error); 340218334Speter } 340390075Sobrien 340418334Speter mtx_lock(&Giant); /* VFS */ 340518334Speter 340618334Speter error = fget(td, SCARG(uap, fd), &fp); 340718334Speter if (error) 340818334Speter goto out; 340990075Sobrien 341090075Sobrien switch (fp->f_type) { 341190075Sobrien case DTYPE_FIFO: 341290075Sobrien case DTYPE_VNODE: 341390075Sobrien mac_init_vnode_label(&intlabel); 341490075Sobrien error = mac_internalize_vnode_label(&intlabel, buffer); 341518334Speter if (error) { 341690075Sobrien mac_destroy_vnode_label(&intlabel); 341790075Sobrien break; 341890075Sobrien } 341918334Speter 342018334Speter vp = (struct vnode *)fp->f_data; 342150397Sobrien error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 342218334Speter if (error != 0) { 342318334Speter mac_destroy_vnode_label(&intlabel); 342418334Speter break; 342518334Speter } 342618334Speter 342718334Speter vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 342818334Speter error = vn_setlabel(vp, &intlabel, td->td_ucred); 342918334Speter VOP_UNLOCK(vp, 0, td); 343018334Speter vn_finished_write(mp); 343118334Speter 343218334Speter mac_destroy_vnode_label(&intlabel); 343318334Speter break; 343418334Speter 343518334Speter case DTYPE_PIPE: 343618334Speter mac_init_pipe_label(&intlabel); 343718334Speter error = mac_internalize_pipe_label(&intlabel, buffer); 343818334Speter if (error == 0) { 343918334Speter pipe = (struct pipe *)fp->f_data; 344018334Speter PIPE_LOCK(pipe); 344118334Speter error = mac_pipe_label_set(td->td_ucred, pipe, 344218334Speter &intlabel); 344318334Speter PIPE_UNLOCK(pipe); 344418334Speter } 344518334Speter 344618334Speter mac_destroy_pipe_label(&intlabel); 344718334Speter break; 344818334Speter 344950397Sobrien default: 345090075Sobrien error = EINVAL; 345190075Sobrien } 345290075Sobrien 345390075Sobrien fdrop(fp, td); 345450397Sobrienout: 345550397Sobrien mtx_unlock(&Giant); /* VFS */ 345618334Speter 345718334Speter free(buffer, M_MACTEMP); 345818334Speter 345918334Speter return (error); 346018334Speter} 346118334Speter 346218334Speter/* 346318334Speter * MPSAFE 346418334Speter */ 346518334Speterint 346618334Speter__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 346718334Speter{ 346818334Speter struct label intlabel; 346918334Speter struct nameidata nd; 347018334Speter struct mount *mp; 347118334Speter struct mac mac; 347218334Speter char *buffer; 347318334Speter int error; 347418334Speter 347518334Speter error = copyin(uap->mac_p, &mac, sizeof(mac)); 347618334Speter if (error) 347718334Speter return (error); 347818334Speter 347918334Speter error = mac_check_structmac_consistent(&mac); 348018334Speter if (error) 348118334Speter return (error); 348218334Speter 348350397Sobrien buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 348490075Sobrien error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 348590075Sobrien if (error) { 348690075Sobrien free(buffer, M_MACTEMP); 348790075Sobrien return (error); 348850397Sobrien } 348950397Sobrien 349018334Speter mac_init_vnode_label(&intlabel); 349118334Speter error = mac_internalize_vnode_label(&intlabel, buffer); 349218334Speter free(buffer, M_MACTEMP); 349318334Speter if (error) { 349418334Speter mac_destroy_vnode_label(&intlabel); 349518334Speter return (error); 349618334Speter } 349718334Speter 349818334Speter mtx_lock(&Giant); /* VFS */ 349918334Speter 350018334Speter NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 350118334Speter td); 350218334Speter error = namei(&nd); 350318334Speter if (error == 0) { 350418334Speter error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 350518334Speter if (error == 0) 350618334Speter error = vn_setlabel(nd.ni_vp, &intlabel, 350718334Speter td->td_ucred); 350818334Speter vn_finished_write(mp); 350918334Speter } 351018334Speter 351118334Speter NDFREE(&nd, 0); 351218334Speter mtx_unlock(&Giant); /* VFS */ 351318334Speter mac_destroy_vnode_label(&intlabel); 351418334Speter 351518334Speter return (error); 351618334Speter} 351750397Sobrien 351890075Sobrien/* 351990075Sobrien * MPSAFE 352090075Sobrien */ 352190075Sobrienint 352250397Sobrien__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 352350397Sobrien{ 352418334Speter struct label intlabel; 352518334Speter struct nameidata nd; 352618334Speter struct mount *mp; 352718334Speter struct mac mac; 352818334Speter char *buffer; 352918334Speter int error; 353018334Speter 353118334Speter error = copyin(uap->mac_p, &mac, sizeof(mac)); 353218334Speter if (error) 353318334Speter return (error); 353418334Speter 353518334Speter error = mac_check_structmac_consistent(&mac); 353618334Speter if (error) 353718334Speter return (error); 353818334Speter 353918334Speter buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 354018334Speter error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 354118334Speter if (error) { 354218334Speter free(buffer, M_MACTEMP); 354318334Speter return (error); 354418334Speter } 354518334Speter 354618334Speter mac_init_vnode_label(&intlabel); 354718334Speter error = mac_internalize_vnode_label(&intlabel, buffer); 354818334Speter free(buffer, M_MACTEMP); 354918334Speter if (error) { 355018334Speter mac_destroy_vnode_label(&intlabel); 355150397Sobrien return (error); 355290075Sobrien } 355390075Sobrien 355490075Sobrien mtx_lock(&Giant); /* VFS */ 355590075Sobrien 355650397Sobrien NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 355750397Sobrien td); 355818334Speter error = namei(&nd); 355918334Speter if (error == 0) { 356018334Speter error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 356118334Speter if (error == 0) 356218334Speter error = vn_setlabel(nd.ni_vp, &intlabel, 356318334Speter td->td_ucred); 356418334Speter vn_finished_write(mp); 356518334Speter } 356618334Speter 356718334Speter NDFREE(&nd, 0); 356818334Speter mtx_unlock(&Giant); /* VFS */ 356918334Speter mac_destroy_vnode_label(&intlabel); 357018334Speter 357118334Speter return (error); 357218334Speter} 357318334Speter 357418334Speter/* 357518334Speter * MPSAFE 357618334Speter */ 357718334Speterint 357818334Spetermac_syscall(struct thread *td, struct mac_syscall_args *uap) 357918334Speter{ 358018334Speter struct mac_policy_conf *mpc; 358118334Speter char target[MAC_MAX_POLICY_NAME]; 358218334Speter int error; 358318334Speter 358418334Speter error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL); 358550397Sobrien if (error) 358690075Sobrien return (error); 358790075Sobrien 358890075Sobrien error = ENOSYS; 358990075Sobrien MAC_POLICY_LIST_BUSY(); 359050397Sobrien LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 359150397Sobrien if (strcmp(mpc->mpc_name, target) == 0 && 359218334Speter mpc->mpc_ops->mpo_syscall != NULL) { 359318334Speter error = mpc->mpc_ops->mpo_syscall(td, 359418334Speter SCARG(uap, call), SCARG(uap, arg)); 359518334Speter goto out; 359618334Speter } 359718334Speter } 359818334Speter 359918334Speterout: 360018334Speter MAC_POLICY_LIST_UNBUSY(); 360118334Speter return (error); 360218334Speter} 360318334Speter 360418334SpeterSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 360518334SpeterSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 360690075Sobrien 360790075Sobrien#else /* !MAC */ 360890075Sobrien 360918334Speterint 361018334Speter__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 361118334Speter{ 361218334Speter 361318334Speter return (ENOSYS); 361418334Speter} 361518334Speter 361618334Speterint 361718334Speter__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 361890075Sobrien{ 361990075Sobrien 362018334Speter return (ENOSYS); 362150397Sobrien} 362250397Sobrien 362350397Sobrienint 362450397Sobrien__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 362550397Sobrien{ 362690075Sobrien 362790075Sobrien return (ENOSYS); 362890075Sobrien} 362990075Sobrien 363090075Sobrienint 363190075Sobrien__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 363290075Sobrien{ 363390075Sobrien 363490075Sobrien return (ENOSYS); 363590075Sobrien} 363618334Speter 363718334Speterint 363818334Speter__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 363918334Speter{ 364018334Speter 364118334Speter return (ENOSYS); 364218334Speter} 364318334Speter 364490075Sobrienint 364518334Speter__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 364618334Speter{ 364718334Speter 364818334Speter return (ENOSYS); 364918334Speter} 365018334Speter 365118334Speterint 365218334Speter__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 365318334Speter{ 365418334Speter 365518334Speter return (ENOSYS); 365618334Speter} 365718334Speter 365818334Speterint 365918334Speter__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 366018334Speter{ 366118334Speter 366218334Speter return (ENOSYS); 366318334Speter} 366418334Speter 366518334Speterint 366618334Speter__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 366718334Speter{ 366818334Speter 366918334Speter return (ENOSYS); 367018334Speter} 367118334Speter 367218334Speterint 367318334Spetermac_syscall(struct thread *td, struct mac_syscall_args *uap) 367418334Speter{ 367518334Speter 367618334Speter return (ENOSYS); 367718334Speter} 367818334Speter 367918334Speter#endif 368018334Speter