mac_vfs.c revision 105598
10Sstevel@tonic-gate/*- 20Sstevel@tonic-gate * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 30Sstevel@tonic-gate * Copyright (c) 2001 Ilmar S. Habibulin 40Sstevel@tonic-gate * Copyright (c) 2001, 2002 Networks Associates Technology, Inc. 51676Sjpk * All rights reserved. 61676Sjpk * 70Sstevel@tonic-gate * This software was developed by Robert Watson and Ilmar Habibulin for the 80Sstevel@tonic-gate * TrustedBSD Project. 90Sstevel@tonic-gate * 100Sstevel@tonic-gate * This software was developed for the FreeBSD Project in part by NAI Labs, 110Sstevel@tonic-gate * the Security Research Division of Network Associates, Inc. under 120Sstevel@tonic-gate * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 130Sstevel@tonic-gate * CHATS research program. 140Sstevel@tonic-gate * 150Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 160Sstevel@tonic-gate * modification, are permitted provided that the following conditions 170Sstevel@tonic-gate * are met: 180Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 190Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 200Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 211735Skcpoon * notice, this list of conditions and the following disclaimer in the 220Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 2312869SKacheong.Poon@Sun.COM * 3. The names of the authors may not be used to endorse or promote 240Sstevel@tonic-gate * products derived from this software without specific prior written 250Sstevel@tonic-gate * permission. 260Sstevel@tonic-gate * 270Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 280Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 290Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 300Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 310Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 320Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 330Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 340Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 350Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 360Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 371676Sjpk * SUCH DAMAGE. 381676Sjpk * 390Sstevel@tonic-gate * $FreeBSD: head/sys/security/mac/mac_vfs.c 105598 2002-10-21 02:51:56Z brooks $ 400Sstevel@tonic-gate */ 410Sstevel@tonic-gate/* 420Sstevel@tonic-gate * Developed by the TrustedBSD Project. 430Sstevel@tonic-gate * 440Sstevel@tonic-gate * Framework for extensible kernel access control. Kernel and userland 450Sstevel@tonic-gate * interface to the framework, policy registration and composition. 460Sstevel@tonic-gate */ 470Sstevel@tonic-gate 480Sstevel@tonic-gate#include "opt_mac.h" 490Sstevel@tonic-gate#include "opt_devfs.h" 500Sstevel@tonic-gate 510Sstevel@tonic-gate#include <sys/param.h> 5212869SKacheong.Poon@Sun.COM#include <sys/extattr.h> 5312869SKacheong.Poon@Sun.COM#include <sys/kernel.h> 5412869SKacheong.Poon@Sun.COM#include <sys/lock.h> 5512869SKacheong.Poon@Sun.COM#include <sys/malloc.h> 5612869SKacheong.Poon@Sun.COM#include <sys/mutex.h> 5712869SKacheong.Poon@Sun.COM#include <sys/mac.h> 580Sstevel@tonic-gate#include <sys/module.h> 590Sstevel@tonic-gate#include <sys/proc.h> 600Sstevel@tonic-gate#include <sys/systm.h> 610Sstevel@tonic-gate#include <sys/sysproto.h> 620Sstevel@tonic-gate#include <sys/sysent.h> 633448Sdh155122#include <sys/vnode.h> 6411042SErik.Nordmark@Sun.COM#include <sys/mount.h> 653448Sdh155122#include <sys/file.h> 660Sstevel@tonic-gate#include <sys/namei.h> 670Sstevel@tonic-gate#include <sys/socket.h> 680Sstevel@tonic-gate#include <sys/pipe.h> 690Sstevel@tonic-gate#include <sys/socketvar.h> 700Sstevel@tonic-gate#include <sys/sysctl.h> 710Sstevel@tonic-gate 720Sstevel@tonic-gate#include <vm/vm.h> 730Sstevel@tonic-gate#include <vm/pmap.h> 740Sstevel@tonic-gate#include <vm/vm_map.h> 753448Sdh155122#include <vm/vm_object.h> 763448Sdh155122 7711042SErik.Nordmark@Sun.COM#include <sys/mac_policy.h> 781676Sjpk 791676Sjpk#include <fs/devfs/devfs.h> 800Sstevel@tonic-gate 810Sstevel@tonic-gate#include <net/bpfdesc.h> 820Sstevel@tonic-gate#include <net/if.h> 830Sstevel@tonic-gate#include <net/if_var.h> 840Sstevel@tonic-gate 850Sstevel@tonic-gate#include <netinet/in.h> 860Sstevel@tonic-gate#include <netinet/ip_var.h> 870Sstevel@tonic-gate 880Sstevel@tonic-gate#ifdef MAC 890Sstevel@tonic-gate 900Sstevel@tonic-gate/* 910Sstevel@tonic-gate * Declare that the kernel provides MAC support, version 1. This permits 920Sstevel@tonic-gate * modules to refuse to be loaded if the necessary support isn't present, 930Sstevel@tonic-gate * even if it's pre-boot. 943448Sdh155122 */ 950Sstevel@tonic-gateMODULE_VERSION(kernel_mac_support, 1); 960Sstevel@tonic-gate 973448Sdh155122SYSCTL_DECL(_security); 983448Sdh155122 993448Sdh155122SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 1000Sstevel@tonic-gate "TrustedBSD MAC policy controls"); 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate#if MAC_MAX_POLICIES > 32 1030Sstevel@tonic-gate#error "MAC_MAX_POLICIES too large" 1040Sstevel@tonic-gate#endif 1050Sstevel@tonic-gate 1060Sstevel@tonic-gatestatic unsigned int mac_max_policies = MAC_MAX_POLICIES; 1070Sstevel@tonic-gatestatic unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1; 1080Sstevel@tonic-gateSYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, 1090Sstevel@tonic-gate &mac_max_policies, 0, ""); 11011042SErik.Nordmark@Sun.COM 1116134Scasperstatic int mac_late = 0; 1120Sstevel@tonic-gate 1130Sstevel@tonic-gatestatic int mac_enforce_fs = 1; 1140Sstevel@tonic-gateSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 1151676Sjpk &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 1160Sstevel@tonic-gateTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 1170Sstevel@tonic-gate 1180Sstevel@tonic-gatestatic int mac_enforce_network = 1; 1190Sstevel@tonic-gateSYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 1200Sstevel@tonic-gate &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 1210Sstevel@tonic-gateTUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 1220Sstevel@tonic-gate 1230Sstevel@tonic-gatestatic int mac_enforce_pipe = 1; 1240Sstevel@tonic-gateSYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 1250Sstevel@tonic-gate &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 1260Sstevel@tonic-gateTUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 1270Sstevel@tonic-gate 1283448Sdh155122static int mac_enforce_process = 1; 12911042SErik.Nordmark@Sun.COMSYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 1300Sstevel@tonic-gate &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 1310Sstevel@tonic-gateTUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 1320Sstevel@tonic-gate 1330Sstevel@tonic-gatestatic int mac_enforce_socket = 1; 134852Svi117747SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 1350Sstevel@tonic-gate &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 1364505SkcpoonTUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 1374505Skcpoon 1380Sstevel@tonic-gatestatic int mac_enforce_vm = 1; 1390Sstevel@tonic-gateSYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 1400Sstevel@tonic-gate &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 1410Sstevel@tonic-gateTUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 1420Sstevel@tonic-gate 1430Sstevel@tonic-gatestatic int mac_label_size = sizeof(struct mac); 1440Sstevel@tonic-gateSYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, 1450Sstevel@tonic-gate &mac_label_size, 0, "Pre-compiled MAC label size"); 1460Sstevel@tonic-gate 1470Sstevel@tonic-gatestatic int mac_cache_fslabel_in_vnode = 1; 14811042SErik.Nordmark@Sun.COMSYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, 1490Sstevel@tonic-gate &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); 1500Sstevel@tonic-gateTUNABLE_INT("security.mac.cache_fslabel_in_vnode", 1510Sstevel@tonic-gate &mac_cache_fslabel_in_vnode); 1524505Skcpoon 1530Sstevel@tonic-gatestatic int mac_vnode_label_cache_hits = 0; 1540Sstevel@tonic-gateSYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, 1550Sstevel@tonic-gate &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); 1560Sstevel@tonic-gatestatic int mac_vnode_label_cache_misses = 0; 15711042SErik.Nordmark@Sun.COMSYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, 15811849SErik.Nordmark@Sun.COM &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); 15911042SErik.Nordmark@Sun.COM 16011042SErik.Nordmark@Sun.COMstatic int mac_mmap_revocation = 1; 16111042SErik.Nordmark@Sun.COMSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 16211042SErik.Nordmark@Sun.COM &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 16311042SErik.Nordmark@Sun.COM "relabel"); 1640Sstevel@tonic-gatestatic int mac_mmap_revocation_via_cow = 0; 1650Sstevel@tonic-gateSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 16611066Srafael.vanoni@sun.com &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 1670Sstevel@tonic-gate "copy-on-write semantics, or by removing all write access"); 16812869SKacheong.Poon@Sun.COM 16912869SKacheong.Poon@Sun.COM#ifdef MAC_DEBUG 17012869SKacheong.Poon@Sun.COMSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 17112869SKacheong.Poon@Sun.COM "TrustedBSD MAC debug info"); 17212869SKacheong.Poon@Sun.COM 17312869SKacheong.Poon@Sun.COMstatic int mac_debug_label_fallback = 0; 17412869SKacheong.Poon@Sun.COMSYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 17512869SKacheong.Poon@Sun.COM &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 17612869SKacheong.Poon@Sun.COM "when label is corrupted."); 17712869SKacheong.Poon@Sun.COMTUNABLE_INT("security.mac.debug_label_fallback", 17812869SKacheong.Poon@Sun.COM &mac_debug_label_fallback); 17912869SKacheong.Poon@Sun.COM 18012869SKacheong.Poon@Sun.COMSYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 18112869SKacheong.Poon@Sun.COM "TrustedBSD MAC object counters"); 18212869SKacheong.Poon@Sun.COM 18312869SKacheong.Poon@Sun.COMstatic unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 18412869SKacheong.Poon@Sun.COM nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 18512869SKacheong.Poon@Sun.COM nmacipqs, nmacpipes; 18612869SKacheong.Poon@Sun.COM 18712869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 18812869SKacheong.Poon@Sun.COM &nmacmbufs, 0, "number of mbufs in use"); 18912869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 19012869SKacheong.Poon@Sun.COM &nmaccreds, 0, "number of ucreds in use"); 19112869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 19212869SKacheong.Poon@Sun.COM &nmacifnets, 0, "number of ifnets in use"); 19312869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 19412869SKacheong.Poon@Sun.COM &nmacipqs, 0, "number of ipqs in use"); 19512869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 19612869SKacheong.Poon@Sun.COM &nmacbpfdescs, 0, "number of bpfdescs in use"); 19712869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 19812869SKacheong.Poon@Sun.COM &nmacsockets, 0, "number of sockets in use"); 19912869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 20012869SKacheong.Poon@Sun.COM &nmacpipes, 0, "number of pipes in use"); 20112869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 20212869SKacheong.Poon@Sun.COM &nmacmounts, 0, "number of mounts in use"); 20312869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 20412869SKacheong.Poon@Sun.COM &nmactemp, 0, "number of temporary labels in use"); 20512869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 20612869SKacheong.Poon@Sun.COM &nmacvnodes, 0, "number of vnodes in use"); 20712869SKacheong.Poon@Sun.COMSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 20812869SKacheong.Poon@Sun.COM &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 20912869SKacheong.Poon@Sun.COM#endif 21012869SKacheong.Poon@Sun.COM 21112869SKacheong.Poon@Sun.COMstatic int error_select(int error1, int error2); 2123448Sdh155122static int mac_externalize(struct label *label, struct mac *mac); 21311042SErik.Nordmark@Sun.COMstatic int mac_policy_register(struct mac_policy_conf *mpc); 2140Sstevel@tonic-gatestatic int mac_policy_unregister(struct mac_policy_conf *mpc); 21512869SKacheong.Poon@Sun.COM 2160Sstevel@tonic-gatestatic int mac_stdcreatevnode_ea(struct vnode *vp); 2170Sstevel@tonic-gatestatic void mac_check_vnode_mmap_downgrade(struct ucred *cred, 2180Sstevel@tonic-gate struct vnode *vp, int *prot); 2190Sstevel@tonic-gatestatic void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 2200Sstevel@tonic-gate struct ucred *cred, struct vm_map *map); 2210Sstevel@tonic-gate 2220Sstevel@tonic-gatestatic void mac_destroy_socket_label(struct label *label); 2230Sstevel@tonic-gate 2240Sstevel@tonic-gateMALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); 2250Sstevel@tonic-gateMALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate/* 2280Sstevel@tonic-gate * mac_policy_list_lock protects the consistency of 'mac_policy_list', 2290Sstevel@tonic-gate * the linked list of attached policy modules. Read-only consumers of 2300Sstevel@tonic-gate * the list must acquire a shared lock for the duration of their use; 2310Sstevel@tonic-gate * writers must acquire an exclusive lock. Note that for compound 23211042SErik.Nordmark@Sun.COM * operations, locks should be held for the entire compound operation, 23311042SErik.Nordmark@Sun.COM * and that this is not yet done for relabel requests. 23411042SErik.Nordmark@Sun.COM */ 23511042SErik.Nordmark@Sun.COMstatic struct mtx mac_policy_list_lock; 2360Sstevel@tonic-gatestatic LIST_HEAD(, mac_policy_conf) mac_policy_list; 2370Sstevel@tonic-gatestatic int mac_policy_list_busy; 2380Sstevel@tonic-gate#define MAC_POLICY_LIST_LOCKINIT() mtx_init(&mac_policy_list_lock, \ 2390Sstevel@tonic-gate "mac_policy_list_lock", NULL, MTX_DEF); 2400Sstevel@tonic-gate#define MAC_POLICY_LIST_LOCK() mtx_lock(&mac_policy_list_lock); 2418348SEric.Yu@Sun.COM#define MAC_POLICY_LIST_UNLOCK() mtx_unlock(&mac_policy_list_lock); 2428348SEric.Yu@Sun.COM 2438348SEric.Yu@Sun.COM#define MAC_POLICY_LIST_BUSY() do { \ 2448348SEric.Yu@Sun.COM MAC_POLICY_LIST_LOCK(); \ 2458348SEric.Yu@Sun.COM mac_policy_list_busy++; \ 2468348SEric.Yu@Sun.COM MAC_POLICY_LIST_UNLOCK(); \ 2478348SEric.Yu@Sun.COM} while (0) 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate#define MAC_POLICY_LIST_UNBUSY() do { \ 2500Sstevel@tonic-gate MAC_POLICY_LIST_LOCK(); \ 2510Sstevel@tonic-gate mac_policy_list_busy--; \ 2520Sstevel@tonic-gate if (mac_policy_list_busy < 0) \ 2530Sstevel@tonic-gate panic("Extra mac_policy_list_busy--"); \ 25411042SErik.Nordmark@Sun.COM MAC_POLICY_LIST_UNLOCK(); \ 2550Sstevel@tonic-gate} while (0) 25611042SErik.Nordmark@Sun.COM 25711042SErik.Nordmark@Sun.COM/* 25811042SErik.Nordmark@Sun.COM * MAC_CHECK performs the designated check by walking the policy 25911042SErik.Nordmark@Sun.COM * module list and checking with each as to how it feels about the 26011042SErik.Nordmark@Sun.COM * request. Note that it returns its value via 'error' in the scope 26111042SErik.Nordmark@Sun.COM * of the caller. 26211042SErik.Nordmark@Sun.COM */ 26311042SErik.Nordmark@Sun.COM#define MAC_CHECK(check, args...) do { \ 26411042SErik.Nordmark@Sun.COM struct mac_policy_conf *mpc; \ 26511042SErik.Nordmark@Sun.COM \ 2660Sstevel@tonic-gate error = 0; \ 2670Sstevel@tonic-gate MAC_POLICY_LIST_BUSY(); \ 2680Sstevel@tonic-gate LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 26911042SErik.Nordmark@Sun.COM if (mpc->mpc_ops->mpo_ ## check != NULL) \ 27011042SErik.Nordmark@Sun.COM error = error_select( \ 27111042SErik.Nordmark@Sun.COM mpc->mpc_ops->mpo_ ## check (args), \ 27211042SErik.Nordmark@Sun.COM error); \ 27311042SErik.Nordmark@Sun.COM } \ 27411042SErik.Nordmark@Sun.COM MAC_POLICY_LIST_UNBUSY(); \ 27511042SErik.Nordmark@Sun.COM} while (0) 27611042SErik.Nordmark@Sun.COM 27711042SErik.Nordmark@Sun.COM/* 27811042SErik.Nordmark@Sun.COM * MAC_BOOLEAN performs the designated boolean composition by walking 27911042SErik.Nordmark@Sun.COM * the module list, invoking each instance of the operation, and 28011042SErik.Nordmark@Sun.COM * combining the results using the passed C operator. Note that it 28111042SErik.Nordmark@Sun.COM * returns its value via 'result' in the scope of the caller, which 2820Sstevel@tonic-gate * should be initialized by the caller in a meaningful way to get 2830Sstevel@tonic-gate * a meaningful result. 2840Sstevel@tonic-gate */ 2850Sstevel@tonic-gate#define MAC_BOOLEAN(operation, composition, args...) do { \ 2860Sstevel@tonic-gate struct mac_policy_conf *mpc; \ 2870Sstevel@tonic-gate \ 2880Sstevel@tonic-gate MAC_POLICY_LIST_BUSY(); \ 2890Sstevel@tonic-gate LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 2901676Sjpk if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 2911676Sjpk result = result composition \ 2920Sstevel@tonic-gate mpc->mpc_ops->mpo_ ## operation (args); \ 2930Sstevel@tonic-gate } \ 294852Svi117747 MAC_POLICY_LIST_UNBUSY(); \ 295852Svi117747} while (0) 2960Sstevel@tonic-gate 297852Svi117747/* 2981676Sjpk * MAC_PERFORM performs the designated operation by walking the policy 2991676Sjpk * module list and invoking that operation for each policy. 3001676Sjpk */ 3010Sstevel@tonic-gate#define MAC_PERFORM(operation, args...) do { \ 3021676Sjpk struct mac_policy_conf *mpc; \ 3031676Sjpk \ 3040Sstevel@tonic-gate MAC_POLICY_LIST_BUSY(); \ 3050Sstevel@tonic-gate LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 3060Sstevel@tonic-gate if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 3070Sstevel@tonic-gate mpc->mpc_ops->mpo_ ## operation (args); \ 3080Sstevel@tonic-gate } \ 3090Sstevel@tonic-gate MAC_POLICY_LIST_UNBUSY(); \ 3100Sstevel@tonic-gate} while (0) 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate/* 3130Sstevel@tonic-gate * Initialize the MAC subsystem, including appropriate SMP locks. 3140Sstevel@tonic-gate */ 3150Sstevel@tonic-gatestatic void 3160Sstevel@tonic-gatemac_init(void) 3170Sstevel@tonic-gate{ 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate LIST_INIT(&mac_policy_list); 3200Sstevel@tonic-gate MAC_POLICY_LIST_LOCKINIT(); 3210Sstevel@tonic-gate} 322852Svi117747 32311042SErik.Nordmark@Sun.COM/* 3240Sstevel@tonic-gate * For the purposes of modules that want to know if they were loaded 3250Sstevel@tonic-gate * "early", set the mac_late flag once we've processed modules either 3260Sstevel@tonic-gate * linked into the kernel, or loaded before the kernel startup. 3270Sstevel@tonic-gate */ 3280Sstevel@tonic-gatestatic void 3290Sstevel@tonic-gatemac_late_init(void) 3300Sstevel@tonic-gate{ 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate mac_late = 1; 3330Sstevel@tonic-gate} 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate/* 336852Svi117747 * Allow MAC policy modules to register during boot, etc. 3370Sstevel@tonic-gate */ 3380Sstevel@tonic-gateint 3390Sstevel@tonic-gatemac_policy_modevent(module_t mod, int type, void *data) 3403448Sdh155122{ 34111042SErik.Nordmark@Sun.COM struct mac_policy_conf *mpc; 3420Sstevel@tonic-gate int error; 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate error = 0; 3450Sstevel@tonic-gate mpc = (struct mac_policy_conf *) data; 3464505Skcpoon 3474505Skcpoon switch (type) { 3480Sstevel@tonic-gate case MOD_LOAD: 3490Sstevel@tonic-gate if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 3500Sstevel@tonic-gate mac_late) { 3510Sstevel@tonic-gate printf("mac_policy_modevent: can't load %s policy " 352252Svi117747 "after booting\n", mpc->mpc_name); 353252Svi117747 error = EBUSY; 354252Svi117747 break; 355252Svi117747 } 356252Svi117747 error = mac_policy_register(mpc); 357252Svi117747 break; 3583448Sdh155122 case MOD_UNLOAD: 3593448Sdh155122 /* Don't unregister the module if it was never registered. */ 360252Svi117747 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 361252Svi117747 != 0) 362252Svi117747 error = mac_policy_unregister(mpc); 363252Svi117747 else 364252Svi117747 error = 0; 3650Sstevel@tonic-gate break; 366252Svi117747 default: 367852Svi117747 break; 368852Svi117747 } 369852Svi117747 370852Svi117747 return (error); 371852Svi117747} 372852Svi117747 373852Svi117747static int 374852Svi117747mac_policy_register(struct mac_policy_conf *mpc) 375852Svi117747{ 376852Svi117747 struct mac_policy_conf *tmpc; 377852Svi117747 struct mac_policy_op_entry *mpe; 378852Svi117747 int slot; 379852Svi117747 380852Svi117747 MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*mpc->mpc_ops), 381852Svi117747 M_MACOPVEC, M_WAITOK | M_ZERO); 382852Svi117747 for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) { 383852Svi117747 switch (mpe->mpe_constant) { 384852Svi117747 case MAC_OP_LAST: 385852Svi117747 /* 386852Svi117747 * Doesn't actually happen, but this allows checking 387852Svi117747 * that all enumerated values are handled. 388852Svi117747 */ 389852Svi117747 break; 390852Svi117747 case MAC_DESTROY: 391852Svi117747 mpc->mpc_ops->mpo_destroy = 392852Svi117747 mpe->mpe_function; 393852Svi117747 break; 394852Svi117747 case MAC_INIT: 395852Svi117747 mpc->mpc_ops->mpo_init = 396852Svi117747 mpe->mpe_function; 397852Svi117747 break; 398852Svi117747 case MAC_SYSCALL: 399852Svi117747 mpc->mpc_ops->mpo_syscall = 400852Svi117747 mpe->mpe_function; 401852Svi117747 break; 4023448Sdh155122 case MAC_INIT_BPFDESC_LABEL: 403852Svi117747 mpc->mpc_ops->mpo_init_bpfdesc_label = 404852Svi117747 mpe->mpe_function; 405852Svi117747 break; 40611042SErik.Nordmark@Sun.COM case MAC_INIT_CRED_LABEL: 407852Svi117747 mpc->mpc_ops->mpo_init_cred_label = 408852Svi117747 mpe->mpe_function; 409852Svi117747 break; 410852Svi117747 case MAC_INIT_DEVFSDIRENT_LABEL: 411852Svi117747 mpc->mpc_ops->mpo_init_devfsdirent_label = 412852Svi117747 mpe->mpe_function; 413852Svi117747 break; 414852Svi117747 case MAC_INIT_IFNET_LABEL: 415852Svi117747 mpc->mpc_ops->mpo_init_ifnet_label = 416852Svi117747 mpe->mpe_function; 417852Svi117747 break; 418852Svi117747 case MAC_INIT_IPQ_LABEL: 419852Svi117747 mpc->mpc_ops->mpo_init_ipq_label = 420852Svi117747 mpe->mpe_function; 421852Svi117747 break; 42211042SErik.Nordmark@Sun.COM case MAC_INIT_MBUF_LABEL: 42311042SErik.Nordmark@Sun.COM mpc->mpc_ops->mpo_init_mbuf_label = 424852Svi117747 mpe->mpe_function; 425852Svi117747 break; 426852Svi117747 case MAC_INIT_MOUNT_LABEL: 427852Svi117747 mpc->mpc_ops->mpo_init_mount_label = 428852Svi117747 mpe->mpe_function; 429852Svi117747 break; 430852Svi117747 case MAC_INIT_MOUNT_FS_LABEL: 431852Svi117747 mpc->mpc_ops->mpo_init_mount_fs_label = 432852Svi117747 mpe->mpe_function; 4330Sstevel@tonic-gate break; 4340Sstevel@tonic-gate case MAC_INIT_PIPE_LABEL: 4350Sstevel@tonic-gate mpc->mpc_ops->mpo_init_pipe_label = 4360Sstevel@tonic-gate mpe->mpe_function; 4370Sstevel@tonic-gate break; 4380Sstevel@tonic-gate case MAC_INIT_SOCKET_LABEL: 4390Sstevel@tonic-gate mpc->mpc_ops->mpo_init_socket_label = 4400Sstevel@tonic-gate mpe->mpe_function; 4410Sstevel@tonic-gate break; 4420Sstevel@tonic-gate case MAC_INIT_SOCKET_PEER_LABEL: 4430Sstevel@tonic-gate mpc->mpc_ops->mpo_init_socket_peer_label = 4440Sstevel@tonic-gate mpe->mpe_function; 4450Sstevel@tonic-gate break; 4460Sstevel@tonic-gate case MAC_INIT_TEMP_LABEL: 4470Sstevel@tonic-gate mpc->mpc_ops->mpo_init_temp_label = 4480Sstevel@tonic-gate mpe->mpe_function; 4490Sstevel@tonic-gate break; 4500Sstevel@tonic-gate case MAC_INIT_VNODE_LABEL: 4510Sstevel@tonic-gate mpc->mpc_ops->mpo_init_vnode_label = 4520Sstevel@tonic-gate mpe->mpe_function; 4530Sstevel@tonic-gate break; 4540Sstevel@tonic-gate case MAC_DESTROY_BPFDESC_LABEL: 4550Sstevel@tonic-gate mpc->mpc_ops->mpo_destroy_bpfdesc_label = 4560Sstevel@tonic-gate mpe->mpe_function; 4570Sstevel@tonic-gate break; 4580Sstevel@tonic-gate case MAC_DESTROY_CRED_LABEL: 4590Sstevel@tonic-gate mpc->mpc_ops->mpo_destroy_cred_label = 4600Sstevel@tonic-gate mpe->mpe_function; 4610Sstevel@tonic-gate break; 462852Svi117747 case MAC_DESTROY_DEVFSDIRENT_LABEL: 463852Svi117747 mpc->mpc_ops->mpo_destroy_devfsdirent_label = 4643448Sdh155122 mpe->mpe_function; 46511042SErik.Nordmark@Sun.COM break; 4660Sstevel@tonic-gate case MAC_DESTROY_IFNET_LABEL: 4670Sstevel@tonic-gate mpc->mpc_ops->mpo_destroy_ifnet_label = 4680Sstevel@tonic-gate mpe->mpe_function; 4690Sstevel@tonic-gate break; 4704505Skcpoon case MAC_DESTROY_IPQ_LABEL: 4714505Skcpoon mpc->mpc_ops->mpo_destroy_ipq_label = 4720Sstevel@tonic-gate mpe->mpe_function; 4730Sstevel@tonic-gate break; 4740Sstevel@tonic-gate case MAC_DESTROY_MBUF_LABEL: 4750Sstevel@tonic-gate mpc->mpc_ops->mpo_destroy_mbuf_label = 476252Svi117747 mpe->mpe_function; 477252Svi117747 break; 478252Svi117747 case MAC_DESTROY_MOUNT_LABEL: 479252Svi117747 mpc->mpc_ops->mpo_destroy_mount_label = 480252Svi117747 mpe->mpe_function; 4813448Sdh155122 break; 4823448Sdh155122 case MAC_DESTROY_MOUNT_FS_LABEL: 483252Svi117747 mpc->mpc_ops->mpo_destroy_mount_fs_label = 484252Svi117747 mpe->mpe_function; 485252Svi117747 break; 486252Svi117747 case MAC_DESTROY_PIPE_LABEL: 487252Svi117747 mpc->mpc_ops->mpo_destroy_pipe_label = 4880Sstevel@tonic-gate mpe->mpe_function; 489252Svi117747 break; 4900Sstevel@tonic-gate case MAC_DESTROY_SOCKET_LABEL: 4910Sstevel@tonic-gate mpc->mpc_ops->mpo_destroy_socket_label = 4920Sstevel@tonic-gate mpe->mpe_function; 4930Sstevel@tonic-gate break; 4940Sstevel@tonic-gate case MAC_DESTROY_SOCKET_PEER_LABEL: 4950Sstevel@tonic-gate mpc->mpc_ops->mpo_destroy_socket_peer_label = 4960Sstevel@tonic-gate mpe->mpe_function; 4970Sstevel@tonic-gate break; 498852Svi117747 case MAC_DESTROY_TEMP_LABEL: 499852Svi117747 mpc->mpc_ops->mpo_destroy_temp_label = 500852Svi117747 mpe->mpe_function; 501852Svi117747 break; 502852Svi117747 case MAC_DESTROY_VNODE_LABEL: 503852Svi117747 mpc->mpc_ops->mpo_destroy_vnode_label = 504852Svi117747 mpe->mpe_function; 505852Svi117747 break; 506852Svi117747 case MAC_EXTERNALIZE: 507852Svi117747 mpc->mpc_ops->mpo_externalize = 508852Svi117747 mpe->mpe_function; 509852Svi117747 break; 510852Svi117747 case MAC_INTERNALIZE: 511852Svi117747 mpc->mpc_ops->mpo_internalize = 512852Svi117747 mpe->mpe_function; 513852Svi117747 break; 514852Svi117747 case MAC_CREATE_DEVFS_DEVICE: 51511042SErik.Nordmark@Sun.COM mpc->mpc_ops->mpo_create_devfs_device = 51611042SErik.Nordmark@Sun.COM mpe->mpe_function; 517852Svi117747 break; 518852Svi117747 case MAC_CREATE_DEVFS_DIRECTORY: 5190Sstevel@tonic-gate mpc->mpc_ops->mpo_create_devfs_directory = 5200Sstevel@tonic-gate mpe->mpe_function; 5210Sstevel@tonic-gate break; 5220Sstevel@tonic-gate case MAC_CREATE_DEVFS_SYMLINK: 5230Sstevel@tonic-gate mpc->mpc_ops->mpo_create_devfs_symlink = 5240Sstevel@tonic-gate mpe->mpe_function; 5251676Sjpk break; 5261676Sjpk case MAC_CREATE_DEVFS_VNODE: 5271676Sjpk mpc->mpc_ops->mpo_create_devfs_vnode = 5281676Sjpk mpe->mpe_function; 5291676Sjpk break; 5300Sstevel@tonic-gate case MAC_STDCREATEVNODE_EA: 5311676Sjpk mpc->mpc_ops->mpo_stdcreatevnode_ea = 5321676Sjpk mpe->mpe_function; 5331676Sjpk break; 5341676Sjpk case MAC_CREATE_VNODE: 5350Sstevel@tonic-gate mpc->mpc_ops->mpo_create_vnode = 5361676Sjpk mpe->mpe_function; 5370Sstevel@tonic-gate break; 5380Sstevel@tonic-gate case MAC_CREATE_MOUNT: 5391676Sjpk mpc->mpc_ops->mpo_create_mount = 5401676Sjpk mpe->mpe_function; 5411676Sjpk break; 5420Sstevel@tonic-gate case MAC_CREATE_ROOT_MOUNT: 5430Sstevel@tonic-gate mpc->mpc_ops->mpo_create_root_mount = 5440Sstevel@tonic-gate mpe->mpe_function; 5450Sstevel@tonic-gate break; 5460Sstevel@tonic-gate case MAC_RELABEL_VNODE: 5473448Sdh155122 mpc->mpc_ops->mpo_relabel_vnode = 54811042SErik.Nordmark@Sun.COM mpe->mpe_function; 54911042SErik.Nordmark@Sun.COM break; 55011042SErik.Nordmark@Sun.COM case MAC_UPDATE_DEVFSDIRENT: 5510Sstevel@tonic-gate mpc->mpc_ops->mpo_update_devfsdirent = 5520Sstevel@tonic-gate mpe->mpe_function; 5530Sstevel@tonic-gate break; 5540Sstevel@tonic-gate case MAC_UPDATE_PROCFSVNODE: 5550Sstevel@tonic-gate mpc->mpc_ops->mpo_update_procfsvnode = 5560Sstevel@tonic-gate mpe->mpe_function; 5570Sstevel@tonic-gate break; 5580Sstevel@tonic-gate case MAC_UPDATE_VNODE_FROM_EXTATTR: 5590Sstevel@tonic-gate mpc->mpc_ops->mpo_update_vnode_from_extattr = 5600Sstevel@tonic-gate mpe->mpe_function; 5610Sstevel@tonic-gate break; 5620Sstevel@tonic-gate case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: 5630Sstevel@tonic-gate mpc->mpc_ops->mpo_update_vnode_from_externalized = 5640Sstevel@tonic-gate mpe->mpe_function; 5650Sstevel@tonic-gate break; 5660Sstevel@tonic-gate case MAC_UPDATE_VNODE_FROM_MOUNT: 5670Sstevel@tonic-gate mpc->mpc_ops->mpo_update_vnode_from_mount = 5680Sstevel@tonic-gate mpe->mpe_function; 5690Sstevel@tonic-gate break; 5703448Sdh155122 case MAC_CREATE_MBUF_FROM_SOCKET: 5713448Sdh155122 mpc->mpc_ops->mpo_create_mbuf_from_socket = 5720Sstevel@tonic-gate mpe->mpe_function; 5730Sstevel@tonic-gate break; 5740Sstevel@tonic-gate case MAC_CREATE_PIPE: 5750Sstevel@tonic-gate mpc->mpc_ops->mpo_create_pipe = 5760Sstevel@tonic-gate mpe->mpe_function; 5770Sstevel@tonic-gate break; 5780Sstevel@tonic-gate case MAC_CREATE_SOCKET: 5790Sstevel@tonic-gate mpc->mpc_ops->mpo_create_socket = 5800Sstevel@tonic-gate mpe->mpe_function; 5810Sstevel@tonic-gate break; 5820Sstevel@tonic-gate case MAC_CREATE_SOCKET_FROM_SOCKET: 5830Sstevel@tonic-gate mpc->mpc_ops->mpo_create_socket_from_socket = 5840Sstevel@tonic-gate mpe->mpe_function; 5850Sstevel@tonic-gate break; 5860Sstevel@tonic-gate case MAC_RELABEL_PIPE: 5870Sstevel@tonic-gate mpc->mpc_ops->mpo_relabel_pipe = 5880Sstevel@tonic-gate mpe->mpe_function; 5890Sstevel@tonic-gate break; 5900Sstevel@tonic-gate case MAC_RELABEL_SOCKET: 5910Sstevel@tonic-gate mpc->mpc_ops->mpo_relabel_socket = 5920Sstevel@tonic-gate mpe->mpe_function; 5930Sstevel@tonic-gate break; 5943448Sdh155122 case MAC_SET_SOCKET_PEER_FROM_MBUF: 5950Sstevel@tonic-gate mpc->mpc_ops->mpo_set_socket_peer_from_mbuf = 5960Sstevel@tonic-gate mpe->mpe_function; 5970Sstevel@tonic-gate break; 59811042SErik.Nordmark@Sun.COM case MAC_SET_SOCKET_PEER_FROM_SOCKET: 5990Sstevel@tonic-gate mpc->mpc_ops->mpo_set_socket_peer_from_socket = 60011042SErik.Nordmark@Sun.COM mpe->mpe_function; 6010Sstevel@tonic-gate break; 6020Sstevel@tonic-gate case MAC_CREATE_BPFDESC: 6030Sstevel@tonic-gate mpc->mpc_ops->mpo_create_bpfdesc = 6041676Sjpk mpe->mpe_function; 6051676Sjpk break; 6061676Sjpk case MAC_CREATE_DATAGRAM_FROM_IPQ: 6071676Sjpk mpc->mpc_ops->mpo_create_datagram_from_ipq = 6081676Sjpk mpe->mpe_function; 6091676Sjpk break; 61011042SErik.Nordmark@Sun.COM case MAC_CREATE_FRAGMENT: 61111042SErik.Nordmark@Sun.COM mpc->mpc_ops->mpo_create_fragment = 61211042SErik.Nordmark@Sun.COM mpe->mpe_function; 6131676Sjpk break; 6141676Sjpk case MAC_CREATE_IFNET: 6150Sstevel@tonic-gate mpc->mpc_ops->mpo_create_ifnet = 6160Sstevel@tonic-gate mpe->mpe_function; 61711042SErik.Nordmark@Sun.COM break; 6180Sstevel@tonic-gate case MAC_CREATE_IPQ: 6190Sstevel@tonic-gate mpc->mpc_ops->mpo_create_ipq = 6200Sstevel@tonic-gate mpe->mpe_function; 6210Sstevel@tonic-gate break; 6220Sstevel@tonic-gate case MAC_CREATE_MBUF_FROM_MBUF: 6230Sstevel@tonic-gate mpc->mpc_ops->mpo_create_mbuf_from_mbuf = 6240Sstevel@tonic-gate mpe->mpe_function; 6250Sstevel@tonic-gate break; 6260Sstevel@tonic-gate case MAC_CREATE_MBUF_LINKLAYER: 6270Sstevel@tonic-gate mpc->mpc_ops->mpo_create_mbuf_linklayer = 6280Sstevel@tonic-gate mpe->mpe_function; 6290Sstevel@tonic-gate break; 6300Sstevel@tonic-gate case MAC_CREATE_MBUF_FROM_BPFDESC: 6310Sstevel@tonic-gate mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc = 6320Sstevel@tonic-gate mpe->mpe_function; 6330Sstevel@tonic-gate break; 6340Sstevel@tonic-gate case MAC_CREATE_MBUF_FROM_IFNET: 6350Sstevel@tonic-gate mpc->mpc_ops->mpo_create_mbuf_from_ifnet = 6360Sstevel@tonic-gate mpe->mpe_function; 6370Sstevel@tonic-gate break; 6380Sstevel@tonic-gate case MAC_CREATE_MBUF_MULTICAST_ENCAP: 6391676Sjpk mpc->mpc_ops->mpo_create_mbuf_multicast_encap = 6401676Sjpk mpe->mpe_function; 64111042SErik.Nordmark@Sun.COM break; 6421676Sjpk case MAC_CREATE_MBUF_NETLAYER: 6431676Sjpk mpc->mpc_ops->mpo_create_mbuf_netlayer = 6441676Sjpk mpe->mpe_function; 6451676Sjpk break; 6461676Sjpk case MAC_FRAGMENT_MATCH: 6471676Sjpk mpc->mpc_ops->mpo_fragment_match = 6481676Sjpk mpe->mpe_function; 6491676Sjpk break; 65011042SErik.Nordmark@Sun.COM case MAC_RELABEL_IFNET: 65111042SErik.Nordmark@Sun.COM mpc->mpc_ops->mpo_relabel_ifnet = 65211042SErik.Nordmark@Sun.COM mpe->mpe_function; 65311042SErik.Nordmark@Sun.COM break; 65411042SErik.Nordmark@Sun.COM case MAC_UPDATE_IPQ: 65510352Sdanmcd@sun.com mpc->mpc_ops->mpo_update_ipq = 65610352Sdanmcd@sun.com mpe->mpe_function; 65710352Sdanmcd@sun.com break; 65811042SErik.Nordmark@Sun.COM case MAC_CREATE_CRED: 65911042SErik.Nordmark@Sun.COM mpc->mpc_ops->mpo_create_cred = 6601676Sjpk mpe->mpe_function; 6613448Sdh155122 break; 6623448Sdh155122 case MAC_EXECVE_TRANSITION: 6631676Sjpk mpc->mpc_ops->mpo_execve_transition = 6641676Sjpk mpe->mpe_function; 6651676Sjpk break; 6661676Sjpk case MAC_EXECVE_WILL_TRANSITION: 6671676Sjpk mpc->mpc_ops->mpo_execve_will_transition = 6681676Sjpk mpe->mpe_function; 6691676Sjpk break; 6701676Sjpk case MAC_CREATE_PROC0: 6711676Sjpk mpc->mpc_ops->mpo_create_proc0 = 6721676Sjpk mpe->mpe_function; 6731676Sjpk break; 6741676Sjpk case MAC_CREATE_PROC1: 6751676Sjpk mpc->mpc_ops->mpo_create_proc1 = 6761676Sjpk mpe->mpe_function; 6771676Sjpk break; 6781676Sjpk case MAC_RELABEL_CRED: 6791676Sjpk mpc->mpc_ops->mpo_relabel_cred = 6801676Sjpk mpe->mpe_function; 6811676Sjpk break; 6821676Sjpk case MAC_THREAD_USERRET: 6831676Sjpk mpc->mpc_ops->mpo_thread_userret = 6841676Sjpk mpe->mpe_function; 6851676Sjpk break; 6861676Sjpk case MAC_CHECK_BPFDESC_RECEIVE: 6871676Sjpk mpc->mpc_ops->mpo_check_bpfdesc_receive = 6883448Sdh155122 mpe->mpe_function; 6893448Sdh155122 break; 6903448Sdh155122 case MAC_CHECK_CRED_RELABEL: 6913448Sdh155122 mpc->mpc_ops->mpo_check_cred_relabel = 6921676Sjpk mpe->mpe_function; 6931676Sjpk break; 6941676Sjpk case MAC_CHECK_CRED_VISIBLE: 6951676Sjpk mpc->mpc_ops->mpo_check_cred_visible = 6961676Sjpk mpe->mpe_function; 6971676Sjpk break; 6981676Sjpk case MAC_CHECK_IFNET_RELABEL: 6991676Sjpk mpc->mpc_ops->mpo_check_ifnet_relabel = 7001676Sjpk mpe->mpe_function; 7011676Sjpk break; 7021676Sjpk case MAC_CHECK_IFNET_TRANSMIT: 7031676Sjpk mpc->mpc_ops->mpo_check_ifnet_transmit = 7041676Sjpk mpe->mpe_function; 7050Sstevel@tonic-gate break; 7060Sstevel@tonic-gate case MAC_CHECK_MOUNT_STAT: 7070Sstevel@tonic-gate mpc->mpc_ops->mpo_check_mount_stat = 7080Sstevel@tonic-gate mpe->mpe_function; 7090Sstevel@tonic-gate break; 7100Sstevel@tonic-gate case MAC_CHECK_PIPE_IOCTL: 71111042SErik.Nordmark@Sun.COM mpc->mpc_ops->mpo_check_pipe_ioctl = 7120Sstevel@tonic-gate mpe->mpe_function; 7133448Sdh155122 break; 7144505Skcpoon case MAC_CHECK_PIPE_POLL: 7150Sstevel@tonic-gate mpc->mpc_ops->mpo_check_pipe_poll = 7160Sstevel@tonic-gate mpe->mpe_function; 7170Sstevel@tonic-gate break; 7180Sstevel@tonic-gate case MAC_CHECK_PIPE_READ: 7190Sstevel@tonic-gate mpc->mpc_ops->mpo_check_pipe_read = 7200Sstevel@tonic-gate mpe->mpe_function; 7210Sstevel@tonic-gate break; 7221676Sjpk case MAC_CHECK_PIPE_RELABEL: 7230Sstevel@tonic-gate mpc->mpc_ops->mpo_check_pipe_relabel = 7240Sstevel@tonic-gate mpe->mpe_function; 7250Sstevel@tonic-gate break; 7260Sstevel@tonic-gate case MAC_CHECK_PIPE_STAT: 7271676Sjpk mpc->mpc_ops->mpo_check_pipe_stat = 7283448Sdh155122 mpe->mpe_function; 7291676Sjpk break; 7301676Sjpk case MAC_CHECK_PIPE_WRITE: 7311676Sjpk mpc->mpc_ops->mpo_check_pipe_write = 7321676Sjpk mpe->mpe_function; 7330Sstevel@tonic-gate break; 7340Sstevel@tonic-gate case MAC_CHECK_PROC_DEBUG: 7350Sstevel@tonic-gate mpc->mpc_ops->mpo_check_proc_debug = 7360Sstevel@tonic-gate mpe->mpe_function; 7370Sstevel@tonic-gate break; 7380Sstevel@tonic-gate case MAC_CHECK_PROC_SCHED: 7390Sstevel@tonic-gate mpc->mpc_ops->mpo_check_proc_sched = 7403448Sdh155122 mpe->mpe_function; 7413448Sdh155122 break; 7423448Sdh155122 case MAC_CHECK_PROC_SIGNAL: 7430Sstevel@tonic-gate mpc->mpc_ops->mpo_check_proc_signal = 7440Sstevel@tonic-gate mpe->mpe_function; 7453448Sdh155122 break; 7460Sstevel@tonic-gate case MAC_CHECK_SOCKET_BIND: 7471676Sjpk mpc->mpc_ops->mpo_check_socket_bind = 7481676Sjpk mpe->mpe_function; 7490Sstevel@tonic-gate break; 7500Sstevel@tonic-gate case MAC_CHECK_SOCKET_CONNECT: 7510Sstevel@tonic-gate mpc->mpc_ops->mpo_check_socket_connect = 7520Sstevel@tonic-gate mpe->mpe_function; 7530Sstevel@tonic-gate break; 7540Sstevel@tonic-gate case MAC_CHECK_SOCKET_DELIVER: 7551676Sjpk mpc->mpc_ops->mpo_check_socket_deliver = 7561676Sjpk mpe->mpe_function; 7570Sstevel@tonic-gate break; 7580Sstevel@tonic-gate case MAC_CHECK_SOCKET_LISTEN: 7590Sstevel@tonic-gate mpc->mpc_ops->mpo_check_socket_listen = 7600Sstevel@tonic-gate mpe->mpe_function; 7610Sstevel@tonic-gate break; 7620Sstevel@tonic-gate case MAC_CHECK_SOCKET_RECEIVE: 7630Sstevel@tonic-gate mpc->mpc_ops->mpo_check_socket_receive = 7640Sstevel@tonic-gate mpe->mpe_function; 7650Sstevel@tonic-gate break; 7660Sstevel@tonic-gate case MAC_CHECK_SOCKET_RELABEL: 7670Sstevel@tonic-gate mpc->mpc_ops->mpo_check_socket_relabel = 7680Sstevel@tonic-gate mpe->mpe_function; 7690Sstevel@tonic-gate break; 7700Sstevel@tonic-gate case MAC_CHECK_SOCKET_SEND: 7710Sstevel@tonic-gate mpc->mpc_ops->mpo_check_socket_send = 7723448Sdh155122 mpe->mpe_function; 7730Sstevel@tonic-gate break; 7740Sstevel@tonic-gate case MAC_CHECK_SOCKET_VISIBLE: 7751676Sjpk mpc->mpc_ops->mpo_check_socket_visible = 7760Sstevel@tonic-gate mpe->mpe_function; 7770Sstevel@tonic-gate break; 7783448Sdh155122 case MAC_CHECK_VNODE_ACCESS: 7793448Sdh155122 mpc->mpc_ops->mpo_check_vnode_access = 7800Sstevel@tonic-gate mpe->mpe_function; 7813448Sdh155122 break; 7821676Sjpk case MAC_CHECK_VNODE_CHDIR: 7831676Sjpk mpc->mpc_ops->mpo_check_vnode_chdir = 7841676Sjpk mpe->mpe_function; 7853448Sdh155122 break; 7861676Sjpk case MAC_CHECK_VNODE_CHROOT: 7871676Sjpk mpc->mpc_ops->mpo_check_vnode_chroot = 7883448Sdh155122 mpe->mpe_function; 7893448Sdh155122 break; 7900Sstevel@tonic-gate case MAC_CHECK_VNODE_CREATE: 7913448Sdh155122 mpc->mpc_ops->mpo_check_vnode_create = 7923448Sdh155122 mpe->mpe_function; 7930Sstevel@tonic-gate break; 7940Sstevel@tonic-gate case MAC_CHECK_VNODE_DELETE: 7950Sstevel@tonic-gate mpc->mpc_ops->mpo_check_vnode_delete = 7960Sstevel@tonic-gate mpe->mpe_function; 7970Sstevel@tonic-gate break; 7980Sstevel@tonic-gate case MAC_CHECK_VNODE_DELETEACL: 7990Sstevel@tonic-gate mpc->mpc_ops->mpo_check_vnode_deleteacl = 8000Sstevel@tonic-gate mpe->mpe_function; 8010Sstevel@tonic-gate break; 8020Sstevel@tonic-gate case MAC_CHECK_VNODE_EXEC: 8030Sstevel@tonic-gate mpc->mpc_ops->mpo_check_vnode_exec = 8040Sstevel@tonic-gate mpe->mpe_function; 8051676Sjpk break; 8061676Sjpk case MAC_CHECK_VNODE_GETACL: 8071676Sjpk mpc->mpc_ops->mpo_check_vnode_getacl = 8081676Sjpk mpe->mpe_function; 8091676Sjpk break; 8101676Sjpk case MAC_CHECK_VNODE_GETEXTATTR: 8111676Sjpk mpc->mpc_ops->mpo_check_vnode_getextattr = 8120Sstevel@tonic-gate mpe->mpe_function; 8130Sstevel@tonic-gate break; 814 case MAC_CHECK_VNODE_LINK: 815 mpc->mpc_ops->mpo_check_vnode_link = 816 mpe->mpe_function; 817 break; 818 case MAC_CHECK_VNODE_LOOKUP: 819 mpc->mpc_ops->mpo_check_vnode_lookup = 820 mpe->mpe_function; 821 break; 822 case MAC_CHECK_VNODE_MMAP: 823 mpc->mpc_ops->mpo_check_vnode_mmap = 824 mpe->mpe_function; 825 break; 826 case MAC_CHECK_VNODE_MMAP_DOWNGRADE: 827 mpc->mpc_ops->mpo_check_vnode_mmap_downgrade = 828 mpe->mpe_function; 829 break; 830 case MAC_CHECK_VNODE_MPROTECT: 831 mpc->mpc_ops->mpo_check_vnode_mprotect = 832 mpe->mpe_function; 833 break; 834 case MAC_CHECK_VNODE_OPEN: 835 mpc->mpc_ops->mpo_check_vnode_open = 836 mpe->mpe_function; 837 break; 838 case MAC_CHECK_VNODE_POLL: 839 mpc->mpc_ops->mpo_check_vnode_poll = 840 mpe->mpe_function; 841 break; 842 case MAC_CHECK_VNODE_READ: 843 mpc->mpc_ops->mpo_check_vnode_read = 844 mpe->mpe_function; 845 break; 846 case MAC_CHECK_VNODE_READDIR: 847 mpc->mpc_ops->mpo_check_vnode_readdir = 848 mpe->mpe_function; 849 break; 850 case MAC_CHECK_VNODE_READLINK: 851 mpc->mpc_ops->mpo_check_vnode_readlink = 852 mpe->mpe_function; 853 break; 854 case MAC_CHECK_VNODE_RELABEL: 855 mpc->mpc_ops->mpo_check_vnode_relabel = 856 mpe->mpe_function; 857 break; 858 case MAC_CHECK_VNODE_RENAME_FROM: 859 mpc->mpc_ops->mpo_check_vnode_rename_from = 860 mpe->mpe_function; 861 break; 862 case MAC_CHECK_VNODE_RENAME_TO: 863 mpc->mpc_ops->mpo_check_vnode_rename_to = 864 mpe->mpe_function; 865 break; 866 case MAC_CHECK_VNODE_REVOKE: 867 mpc->mpc_ops->mpo_check_vnode_revoke = 868 mpe->mpe_function; 869 break; 870 case MAC_CHECK_VNODE_SETACL: 871 mpc->mpc_ops->mpo_check_vnode_setacl = 872 mpe->mpe_function; 873 break; 874 case MAC_CHECK_VNODE_SETEXTATTR: 875 mpc->mpc_ops->mpo_check_vnode_setextattr = 876 mpe->mpe_function; 877 break; 878 case MAC_CHECK_VNODE_SETFLAGS: 879 mpc->mpc_ops->mpo_check_vnode_setflags = 880 mpe->mpe_function; 881 break; 882 case MAC_CHECK_VNODE_SETMODE: 883 mpc->mpc_ops->mpo_check_vnode_setmode = 884 mpe->mpe_function; 885 break; 886 case MAC_CHECK_VNODE_SETOWNER: 887 mpc->mpc_ops->mpo_check_vnode_setowner = 888 mpe->mpe_function; 889 break; 890 case MAC_CHECK_VNODE_SETUTIMES: 891 mpc->mpc_ops->mpo_check_vnode_setutimes = 892 mpe->mpe_function; 893 break; 894 case MAC_CHECK_VNODE_STAT: 895 mpc->mpc_ops->mpo_check_vnode_stat = 896 mpe->mpe_function; 897 break; 898 case MAC_CHECK_VNODE_WRITE: 899 mpc->mpc_ops->mpo_check_vnode_write = 900 mpe->mpe_function; 901 break; 902/* 903 default: 904 printf("MAC policy `%s': unknown operation %d\n", 905 mpc->mpc_name, mpe->mpe_constant); 906 return (EINVAL); 907*/ 908 } 909 } 910 MAC_POLICY_LIST_LOCK(); 911 if (mac_policy_list_busy > 0) { 912 MAC_POLICY_LIST_UNLOCK(); 913 FREE(mpc->mpc_ops, M_MACOPVEC); 914 mpc->mpc_ops = NULL; 915 return (EBUSY); 916 } 917 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 918 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 919 MAC_POLICY_LIST_UNLOCK(); 920 FREE(mpc->mpc_ops, M_MACOPVEC); 921 mpc->mpc_ops = NULL; 922 return (EEXIST); 923 } 924 } 925 if (mpc->mpc_field_off != NULL) { 926 slot = ffs(mac_policy_offsets_free); 927 if (slot == 0) { 928 MAC_POLICY_LIST_UNLOCK(); 929 FREE(mpc->mpc_ops, M_MACOPVEC); 930 mpc->mpc_ops = NULL; 931 return (ENOMEM); 932 } 933 slot--; 934 mac_policy_offsets_free &= ~(1 << slot); 935 *mpc->mpc_field_off = slot; 936 } 937 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 938 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 939 940 /* Per-policy initialization. */ 941 if (mpc->mpc_ops->mpo_init != NULL) 942 (*(mpc->mpc_ops->mpo_init))(mpc); 943 MAC_POLICY_LIST_UNLOCK(); 944 945 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 946 mpc->mpc_name); 947 948 return (0); 949} 950 951static int 952mac_policy_unregister(struct mac_policy_conf *mpc) 953{ 954 955 /* 956 * If we fail the load, we may get a request to unload. Check 957 * to see if we did the run-time registration, and if not, 958 * silently succeed. 959 */ 960 MAC_POLICY_LIST_LOCK(); 961 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 962 MAC_POLICY_LIST_UNLOCK(); 963 return (0); 964 } 965#if 0 966 /* 967 * Don't allow unloading modules with private data. 968 */ 969 if (mpc->mpc_field_off != NULL) { 970 MAC_POLICY_LIST_UNLOCK(); 971 return (EBUSY); 972 } 973#endif 974 /* 975 * Only allow the unload to proceed if the module is unloadable 976 * by its own definition. 977 */ 978 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 979 MAC_POLICY_LIST_UNLOCK(); 980 return (EBUSY); 981 } 982 /* 983 * Right now, we EBUSY if the list is in use. In the future, 984 * for reliability reasons, we might want to sleep and wakeup 985 * later to try again. 986 */ 987 if (mac_policy_list_busy > 0) { 988 MAC_POLICY_LIST_UNLOCK(); 989 return (EBUSY); 990 } 991 if (mpc->mpc_ops->mpo_destroy != NULL) 992 (*(mpc->mpc_ops->mpo_destroy))(mpc); 993 994 LIST_REMOVE(mpc, mpc_list); 995 MAC_POLICY_LIST_UNLOCK(); 996 997 FREE(mpc->mpc_ops, M_MACOPVEC); 998 mpc->mpc_ops = NULL; 999 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 1000 1001 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 1002 mpc->mpc_name); 1003 1004 return (0); 1005} 1006 1007/* 1008 * Define an error value precedence, and given two arguments, selects the 1009 * value with the higher precedence. 1010 */ 1011static int 1012error_select(int error1, int error2) 1013{ 1014 1015 /* Certain decision-making errors take top priority. */ 1016 if (error1 == EDEADLK || error2 == EDEADLK) 1017 return (EDEADLK); 1018 1019 /* Invalid arguments should be reported where possible. */ 1020 if (error1 == EINVAL || error2 == EINVAL) 1021 return (EINVAL); 1022 1023 /* Precedence goes to "visibility", with both process and file. */ 1024 if (error1 == ESRCH || error2 == ESRCH) 1025 return (ESRCH); 1026 1027 if (error1 == ENOENT || error2 == ENOENT) 1028 return (ENOENT); 1029 1030 /* Precedence goes to DAC/MAC protections. */ 1031 if (error1 == EACCES || error2 == EACCES) 1032 return (EACCES); 1033 1034 /* Precedence goes to privilege. */ 1035 if (error1 == EPERM || error2 == EPERM) 1036 return (EPERM); 1037 1038 /* Precedence goes to error over success; otherwise, arbitrary. */ 1039 if (error1 != 0) 1040 return (error1); 1041 return (error2); 1042} 1043 1044static void 1045mac_init_label(struct label *label) 1046{ 1047 1048 bzero(label, sizeof(*label)); 1049 label->l_flags = MAC_FLAG_INITIALIZED; 1050} 1051 1052static void 1053mac_destroy_label(struct label *label) 1054{ 1055 1056 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 1057 ("destroying uninitialized label")); 1058 1059 bzero(label, sizeof(*label)); 1060 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 1061} 1062 1063static void 1064mac_init_structmac(struct mac *mac) 1065{ 1066 1067 bzero(mac, sizeof(*mac)); 1068 mac->m_macflags = MAC_FLAG_INITIALIZED; 1069} 1070 1071void 1072mac_init_bpfdesc(struct bpf_d *bpf_d) 1073{ 1074 1075 mac_init_label(&bpf_d->bd_label); 1076 MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 1077#ifdef MAC_DEBUG 1078 atomic_add_int(&nmacbpfdescs, 1); 1079#endif 1080} 1081 1082void 1083mac_init_cred(struct ucred *cr) 1084{ 1085 1086 mac_init_label(&cr->cr_label); 1087 MAC_PERFORM(init_cred_label, &cr->cr_label); 1088#ifdef MAC_DEBUG 1089 atomic_add_int(&nmaccreds, 1); 1090#endif 1091} 1092 1093void 1094mac_init_devfsdirent(struct devfs_dirent *de) 1095{ 1096 1097 mac_init_label(&de->de_label); 1098 MAC_PERFORM(init_devfsdirent_label, &de->de_label); 1099#ifdef MAC_DEBUG 1100 atomic_add_int(&nmacdevfsdirents, 1); 1101#endif 1102} 1103 1104void 1105mac_init_ifnet(struct ifnet *ifp) 1106{ 1107 1108 mac_init_label(&ifp->if_label); 1109 MAC_PERFORM(init_ifnet_label, &ifp->if_label); 1110#ifdef MAC_DEBUG 1111 atomic_add_int(&nmacifnets, 1); 1112#endif 1113} 1114 1115void 1116mac_init_ipq(struct ipq *ipq) 1117{ 1118 1119 mac_init_label(&ipq->ipq_label); 1120 MAC_PERFORM(init_ipq_label, &ipq->ipq_label); 1121#ifdef MAC_DEBUG 1122 atomic_add_int(&nmacipqs, 1); 1123#endif 1124} 1125 1126int 1127mac_init_mbuf(struct mbuf *m, int flag) 1128{ 1129 int error; 1130 1131 KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 1132 1133 mac_init_label(&m->m_pkthdr.label); 1134 1135 MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag); 1136 if (error) { 1137 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 1138 mac_destroy_label(&m->m_pkthdr.label); 1139 } 1140 1141#ifdef MAC_DEBUG 1142 if (error == 0) 1143 atomic_add_int(&nmacmbufs, 1); 1144#endif 1145 return (error); 1146} 1147 1148void 1149mac_init_mount(struct mount *mp) 1150{ 1151 1152 mac_init_label(&mp->mnt_mntlabel); 1153 mac_init_label(&mp->mnt_fslabel); 1154 MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 1155 MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 1156#ifdef MAC_DEBUG 1157 atomic_add_int(&nmacmounts, 1); 1158#endif 1159} 1160 1161void 1162mac_init_pipe(struct pipe *pipe) 1163{ 1164 struct label *label; 1165 1166 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 1167 mac_init_label(label); 1168 pipe->pipe_label = label; 1169 pipe->pipe_peer->pipe_label = label; 1170 MAC_PERFORM(init_pipe_label, pipe->pipe_label); 1171#ifdef MAC_DEBUG 1172 atomic_add_int(&nmacpipes, 1); 1173#endif 1174} 1175 1176static int 1177mac_init_socket_label(struct label *label, int flag) 1178{ 1179 int error; 1180 1181 mac_init_label(label); 1182 1183 MAC_CHECK(init_socket_label, label, flag); 1184 if (error) { 1185 MAC_PERFORM(destroy_socket_label, label); 1186 mac_destroy_label(label); 1187 } 1188 1189#ifdef MAC_DEBUG 1190 if (error == 0) 1191 atomic_add_int(&nmacsockets, 1); 1192#endif 1193 1194 return (error); 1195} 1196 1197static int 1198mac_init_socket_peer_label(struct label *label, int flag) 1199{ 1200 int error; 1201 1202 mac_init_label(label); 1203 1204 MAC_CHECK(init_socket_peer_label, label, flag); 1205 if (error) { 1206 MAC_PERFORM(destroy_socket_label, label); 1207 mac_destroy_label(label); 1208 } 1209 1210 return (error); 1211} 1212 1213int 1214mac_init_socket(struct socket *socket, int flag) 1215{ 1216 int error; 1217 1218 error = mac_init_socket_label(&socket->so_label, flag); 1219 if (error) 1220 return (error); 1221 1222 error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 1223 if (error) 1224 mac_destroy_socket_label(&socket->so_label); 1225 1226 return (error); 1227} 1228 1229static void 1230mac_init_temp(struct label *label) 1231{ 1232 1233 mac_init_label(label); 1234 MAC_PERFORM(init_temp_label, label); 1235#ifdef MAC_DEBUG 1236 atomic_add_int(&nmactemp, 1); 1237#endif 1238} 1239 1240void 1241mac_init_vnode(struct vnode *vp) 1242{ 1243 1244 mac_init_label(&vp->v_label); 1245 MAC_PERFORM(init_vnode_label, &vp->v_label); 1246#ifdef MAC_DEBUG 1247 atomic_add_int(&nmacvnodes, 1); 1248#endif 1249} 1250 1251void 1252mac_destroy_bpfdesc(struct bpf_d *bpf_d) 1253{ 1254 1255 MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 1256 mac_destroy_label(&bpf_d->bd_label); 1257#ifdef MAC_DEBUG 1258 atomic_subtract_int(&nmacbpfdescs, 1); 1259#endif 1260} 1261 1262void 1263mac_destroy_cred(struct ucred *cr) 1264{ 1265 1266 MAC_PERFORM(destroy_cred_label, &cr->cr_label); 1267 mac_destroy_label(&cr->cr_label); 1268#ifdef MAC_DEBUG 1269 atomic_subtract_int(&nmaccreds, 1); 1270#endif 1271} 1272 1273void 1274mac_destroy_devfsdirent(struct devfs_dirent *de) 1275{ 1276 1277 MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 1278 mac_destroy_label(&de->de_label); 1279#ifdef MAC_DEBUG 1280 atomic_subtract_int(&nmacdevfsdirents, 1); 1281#endif 1282} 1283 1284void 1285mac_destroy_ifnet(struct ifnet *ifp) 1286{ 1287 1288 MAC_PERFORM(destroy_ifnet_label, &ifp->if_label); 1289 mac_destroy_label(&ifp->if_label); 1290#ifdef MAC_DEBUG 1291 atomic_subtract_int(&nmacifnets, 1); 1292#endif 1293} 1294 1295void 1296mac_destroy_ipq(struct ipq *ipq) 1297{ 1298 1299 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 1300 mac_destroy_label(&ipq->ipq_label); 1301#ifdef MAC_DEBUG 1302 atomic_subtract_int(&nmacipqs, 1); 1303#endif 1304} 1305 1306void 1307mac_destroy_mbuf(struct mbuf *m) 1308{ 1309 1310 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 1311 mac_destroy_label(&m->m_pkthdr.label); 1312#ifdef MAC_DEBUG 1313 atomic_subtract_int(&nmacmbufs, 1); 1314#endif 1315} 1316 1317void 1318mac_destroy_mount(struct mount *mp) 1319{ 1320 1321 MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 1322 MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 1323 mac_destroy_label(&mp->mnt_fslabel); 1324 mac_destroy_label(&mp->mnt_mntlabel); 1325#ifdef MAC_DEBUG 1326 atomic_subtract_int(&nmacmounts, 1); 1327#endif 1328} 1329 1330void 1331mac_destroy_pipe(struct pipe *pipe) 1332{ 1333 1334 MAC_PERFORM(destroy_pipe_label, pipe->pipe_label); 1335 mac_destroy_label(pipe->pipe_label); 1336 free(pipe->pipe_label, M_MACPIPELABEL); 1337#ifdef MAC_DEBUG 1338 atomic_subtract_int(&nmacpipes, 1); 1339#endif 1340} 1341 1342static void 1343mac_destroy_socket_label(struct label *label) 1344{ 1345 1346 MAC_PERFORM(destroy_socket_label, label); 1347 mac_destroy_label(label); 1348#ifdef MAC_DEBUG 1349 atomic_subtract_int(&nmacsockets, 1); 1350#endif 1351} 1352 1353static void 1354mac_destroy_socket_peer_label(struct label *label) 1355{ 1356 1357 MAC_PERFORM(destroy_socket_peer_label, label); 1358 mac_destroy_label(label); 1359} 1360 1361void 1362mac_destroy_socket(struct socket *socket) 1363{ 1364 1365 mac_destroy_socket_label(&socket->so_label); 1366 mac_destroy_socket_peer_label(&socket->so_peerlabel); 1367} 1368 1369static void 1370mac_destroy_temp(struct label *label) 1371{ 1372 1373 MAC_PERFORM(destroy_temp_label, label); 1374 mac_destroy_label(label); 1375#ifdef MAC_DEBUG 1376 atomic_subtract_int(&nmactemp, 1); 1377#endif 1378} 1379 1380void 1381mac_destroy_vnode(struct vnode *vp) 1382{ 1383 1384 MAC_PERFORM(destroy_vnode_label, &vp->v_label); 1385 mac_destroy_label(&vp->v_label); 1386#ifdef MAC_DEBUG 1387 atomic_subtract_int(&nmacvnodes, 1); 1388#endif 1389} 1390 1391static int 1392mac_externalize(struct label *label, struct mac *mac) 1393{ 1394 int error; 1395 1396 mac_init_structmac(mac); 1397 MAC_CHECK(externalize, label, mac); 1398 1399 return (error); 1400} 1401 1402static int 1403mac_internalize(struct label *label, struct mac *mac) 1404{ 1405 int error; 1406 1407 mac_init_temp(label); 1408 MAC_CHECK(internalize, label, mac); 1409 if (error) 1410 mac_destroy_temp(label); 1411 1412 return (error); 1413} 1414 1415/* 1416 * Initialize MAC label for the first kernel process, from which other 1417 * kernel processes and threads are spawned. 1418 */ 1419void 1420mac_create_proc0(struct ucred *cred) 1421{ 1422 1423 MAC_PERFORM(create_proc0, cred); 1424} 1425 1426/* 1427 * Initialize MAC label for the first userland process, from which other 1428 * userland processes and threads are spawned. 1429 */ 1430void 1431mac_create_proc1(struct ucred *cred) 1432{ 1433 1434 MAC_PERFORM(create_proc1, cred); 1435} 1436 1437void 1438mac_thread_userret(struct thread *td) 1439{ 1440 1441 MAC_PERFORM(thread_userret, td); 1442} 1443 1444/* 1445 * When a new process is created, its label must be initialized. Generally, 1446 * this involves inheritence from the parent process, modulo possible 1447 * deltas. This function allows that processing to take place. 1448 */ 1449void 1450mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 1451{ 1452 1453 MAC_PERFORM(create_cred, parent_cred, child_cred); 1454} 1455 1456void 1457mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 1458{ 1459 1460 MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 1461} 1462 1463void 1464mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) 1465{ 1466 1467 MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); 1468} 1469 1470/* 1471 * Support callout for policies that manage their own externalization 1472 * using extended attributes. 1473 */ 1474static int 1475mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) 1476{ 1477 int error; 1478 1479 MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, 1480 &mp->mnt_fslabel); 1481 1482 return (error); 1483} 1484 1485/* 1486 * Given an externalized mac label, internalize it and stamp it on a 1487 * vnode. 1488 */ 1489static int 1490mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac) 1491{ 1492 int error; 1493 1494 MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); 1495 1496 return (error); 1497} 1498 1499/* 1500 * Call out to individual policies to update the label in a vnode from 1501 * the mountpoint. 1502 */ 1503void 1504mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) 1505{ 1506 1507 MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, 1508 &mp->mnt_fslabel); 1509 1510 ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); 1511 if (mac_cache_fslabel_in_vnode) 1512 vp->v_vflag |= VV_CACHEDLABEL; 1513} 1514 1515/* 1516 * Implementation of VOP_REFRESHLABEL() that relies on extended attributes 1517 * to store label data. Can be referenced by filesystems supporting 1518 * extended attributes. 1519 */ 1520int 1521vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) 1522{ 1523 struct vnode *vp = ap->a_vp; 1524 struct mac extmac; 1525 int buflen, error; 1526 1527 ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); 1528 1529 /* 1530 * Call out to external policies first. Order doesn't really 1531 * matter, as long as failure of one assures failure of all. 1532 */ 1533 error = mac_update_vnode_from_extattr(vp, vp->v_mount); 1534 if (error) 1535 return (error); 1536 1537 buflen = sizeof(extmac); 1538 error = vn_extattr_get(vp, IO_NODELOCKED, 1539 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, 1540 (char *)&extmac, curthread); 1541 switch (error) { 1542 case 0: 1543 /* Got it */ 1544 break; 1545 1546 case ENOATTR: 1547 /* 1548 * Use the label from the mount point. 1549 */ 1550 mac_update_vnode_from_mount(vp, vp->v_mount); 1551 return (0); 1552 1553 case EOPNOTSUPP: 1554 default: 1555 /* Fail horribly. */ 1556 return (error); 1557 } 1558 1559 if (buflen != sizeof(extmac)) 1560 error = EPERM; /* Fail very closed. */ 1561 if (error == 0) 1562 error = mac_update_vnode_from_externalized(vp, &extmac); 1563 if (error == 0) 1564 vp->v_vflag |= VV_CACHEDLABEL; 1565 else { 1566 struct vattr va; 1567 1568 printf("Corrupted label on %s", 1569 vp->v_mount->mnt_stat.f_mntonname); 1570 if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) 1571 printf(" inum %ld", va.va_fileid); 1572#ifdef MAC_DEBUG 1573 if (mac_debug_label_fallback) { 1574 printf(", falling back.\n"); 1575 mac_update_vnode_from_mount(vp, vp->v_mount); 1576 error = 0; 1577 } else { 1578#endif 1579 printf(".\n"); 1580 error = EPERM; 1581#ifdef MAC_DEBUG 1582 } 1583#endif 1584 } 1585 1586 return (error); 1587} 1588 1589/* 1590 * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle 1591 * the labeling activity outselves. Filesystems should be careful not 1592 * to change their minds regarding whether they support vop_refreshlabel() 1593 * for a vnode or not. Don't cache the vnode here, allow the file 1594 * system code to determine if it's safe to cache. If we update from 1595 * the mount, don't cache since a change to the mount label should affect 1596 * all vnodes. 1597 */ 1598static int 1599vn_refreshlabel(struct vnode *vp, struct ucred *cred) 1600{ 1601 int error; 1602 1603 ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); 1604 1605 if (vp->v_mount == NULL) { 1606/* 1607 Eventually, we probably want to special-case refreshing 1608 of deadfs vnodes, and if there's a lock-free race somewhere, 1609 that case might be handled here. 1610 1611 mac_update_vnode_deadfs(vp); 1612 return (0); 1613 */ 1614 /* printf("vn_refreshlabel: null v_mount\n"); */ 1615 if (vp->v_type != VNON) 1616 printf( 1617 "vn_refreshlabel: null v_mount with non-VNON\n"); 1618 return (EBADF); 1619 } 1620 1621 if (vp->v_vflag & VV_CACHEDLABEL) { 1622 mac_vnode_label_cache_hits++; 1623 return (0); 1624 } else 1625 mac_vnode_label_cache_misses++; 1626 1627 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 1628 mac_update_vnode_from_mount(vp, vp->v_mount); 1629 return (0); 1630 } 1631 1632 error = VOP_REFRESHLABEL(vp, cred, curthread); 1633 switch (error) { 1634 case EOPNOTSUPP: 1635 /* 1636 * If labels are not supported on this vnode, fall back to 1637 * the label in the mount and propagate it to the vnode. 1638 * There should probably be some sort of policy/flag/decision 1639 * about doing this. 1640 */ 1641 mac_update_vnode_from_mount(vp, vp->v_mount); 1642 error = 0; 1643 default: 1644 return (error); 1645 } 1646} 1647 1648/* 1649 * Helper function for file systems using the vop_std*_ea() calls. This 1650 * function must be called after EA service is available for the vnode, 1651 * but before it's hooked up to the namespace so that the node persists 1652 * if there's a crash, or before it can be accessed. On successful 1653 * commit of the label to disk (etc), do cache the label. 1654 */ 1655int 1656vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) 1657{ 1658 struct mac extmac; 1659 int error; 1660 1661 ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); 1662 if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 1663 mac_update_vnode_from_mount(tvp, tvp->v_mount); 1664 } else { 1665 error = vn_refreshlabel(dvp, cred); 1666 if (error) 1667 return (error); 1668 1669 /* 1670 * Stick the label in the vnode. Then try to write to 1671 * disk. If we fail, return a failure to abort the 1672 * create operation. Really, this failure shouldn't 1673 * happen except in fairly unusual circumstances (out 1674 * of disk, etc). 1675 */ 1676 mac_create_vnode(cred, dvp, tvp); 1677 1678 error = mac_stdcreatevnode_ea(tvp); 1679 if (error) 1680 return (error); 1681 1682 /* 1683 * XXX: Eventually this will go away and all policies will 1684 * directly manage their extended attributes. 1685 */ 1686 error = mac_externalize(&tvp->v_label, &extmac); 1687 if (error) 1688 return (error); 1689 1690 error = vn_extattr_set(tvp, IO_NODELOCKED, 1691 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 1692 sizeof(extmac), (char *)&extmac, curthread); 1693 if (error == 0) 1694 tvp->v_vflag |= VV_CACHEDLABEL; 1695 else { 1696#if 0 1697 /* 1698 * In theory, we could have fall-back behavior here. 1699 * It would probably be incorrect. 1700 */ 1701#endif 1702 return (error); 1703 } 1704 } 1705 1706 return (0); 1707} 1708 1709void 1710mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) 1711{ 1712 int error; 1713 1714 ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 1715 1716 error = vn_refreshlabel(vp, old); 1717 if (error) { 1718 printf("mac_execve_transition: vn_refreshlabel returned %d\n", 1719 error); 1720 printf("mac_execve_transition: using old vnode label\n"); 1721 } 1722 1723 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); 1724} 1725 1726int 1727mac_execve_will_transition(struct ucred *old, struct vnode *vp) 1728{ 1729 int error, result; 1730 1731 error = vn_refreshlabel(vp, old); 1732 if (error) 1733 return (error); 1734 1735 result = 0; 1736 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); 1737 1738 return (result); 1739} 1740 1741int 1742mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) 1743{ 1744 int error; 1745 1746 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 1747 1748 if (!mac_enforce_fs) 1749 return (0); 1750 1751 error = vn_refreshlabel(vp, cred); 1752 if (error) 1753 return (error); 1754 1755 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); 1756 return (error); 1757} 1758 1759int 1760mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 1761{ 1762 int error; 1763 1764 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 1765 1766 if (!mac_enforce_fs) 1767 return (0); 1768 1769 error = vn_refreshlabel(dvp, cred); 1770 if (error) 1771 return (error); 1772 1773 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 1774 return (error); 1775} 1776 1777int 1778mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 1779{ 1780 int error; 1781 1782 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 1783 1784 if (!mac_enforce_fs) 1785 return (0); 1786 1787 error = vn_refreshlabel(dvp, cred); 1788 if (error) 1789 return (error); 1790 1791 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 1792 return (error); 1793} 1794 1795int 1796mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 1797 struct componentname *cnp, struct vattr *vap) 1798{ 1799 int error; 1800 1801 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 1802 1803 if (!mac_enforce_fs) 1804 return (0); 1805 1806 error = vn_refreshlabel(dvp, cred); 1807 if (error) 1808 return (error); 1809 1810 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 1811 return (error); 1812} 1813 1814int 1815mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 1816 struct componentname *cnp) 1817{ 1818 int error; 1819 1820 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 1821 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 1822 1823 if (!mac_enforce_fs) 1824 return (0); 1825 1826 error = vn_refreshlabel(dvp, cred); 1827 if (error) 1828 return (error); 1829 error = vn_refreshlabel(vp, cred); 1830 if (error) 1831 return (error); 1832 1833 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 1834 &vp->v_label, cnp); 1835 return (error); 1836} 1837 1838int 1839mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 1840 acl_type_t type) 1841{ 1842 int error; 1843 1844 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 1845 1846 if (!mac_enforce_fs) 1847 return (0); 1848 1849 error = vn_refreshlabel(vp, cred); 1850 if (error) 1851 return (error); 1852 1853 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 1854 return (error); 1855} 1856 1857int 1858mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) 1859{ 1860 int error; 1861 1862 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1863 1864 if (!mac_enforce_process && !mac_enforce_fs) 1865 return (0); 1866 1867 error = vn_refreshlabel(vp, cred); 1868 if (error) 1869 return (error); 1870 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); 1871 1872 return (error); 1873} 1874 1875int 1876mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 1877{ 1878 int error; 1879 1880 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 1881 1882 if (!mac_enforce_fs) 1883 return (0); 1884 1885 error = vn_refreshlabel(vp, cred); 1886 if (error) 1887 return (error); 1888 1889 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 1890 return (error); 1891} 1892 1893int 1894mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 1895 int attrnamespace, const char *name, struct uio *uio) 1896{ 1897 int error; 1898 1899 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 1900 1901 if (!mac_enforce_fs) 1902 return (0); 1903 1904 error = vn_refreshlabel(vp, cred); 1905 if (error) 1906 return (error); 1907 1908 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 1909 attrnamespace, name, uio); 1910 return (error); 1911} 1912 1913int 1914mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 1915 struct vnode *vp, struct componentname *cnp) 1916{ 1917 1918 int error; 1919 1920 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 1921 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 1922 1923 if (!mac_enforce_fs) 1924 return (0); 1925 1926 error = vn_refreshlabel(dvp, cred); 1927 if (error) 1928 return (error); 1929 1930 error = vn_refreshlabel(vp, cred); 1931 if (error) 1932 return (error); 1933 1934 MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 1935 &vp->v_label, cnp); 1936 return (error); 1937} 1938 1939int 1940mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 1941 struct componentname *cnp) 1942{ 1943 int error; 1944 1945 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 1946 1947 if (!mac_enforce_fs) 1948 return (0); 1949 1950 error = vn_refreshlabel(dvp, cred); 1951 if (error) 1952 return (error); 1953 1954 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 1955 return (error); 1956} 1957 1958int 1959mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 1960{ 1961 int error; 1962 1963 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1964 1965 if (!mac_enforce_fs || !mac_enforce_vm) 1966 return (0); 1967 1968 error = vn_refreshlabel(vp, cred); 1969 if (error) 1970 return (error); 1971 1972 MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1973 return (error); 1974} 1975 1976void 1977mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1978{ 1979 int result = *prot; 1980 1981 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1982 1983 if (!mac_enforce_fs || !mac_enforce_vm) 1984 return; 1985 1986 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1987 &result); 1988 1989 *prot = result; 1990} 1991 1992int 1993mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1994{ 1995 int error; 1996 1997 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1998 1999 if (!mac_enforce_fs || !mac_enforce_vm) 2000 return (0); 2001 2002 error = vn_refreshlabel(vp, cred); 2003 if (error) 2004 return (error); 2005 2006 MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 2007 return (error); 2008} 2009 2010int 2011mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) 2012{ 2013 int error; 2014 2015 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 2016 2017 if (!mac_enforce_fs) 2018 return (0); 2019 2020 error = vn_refreshlabel(vp, cred); 2021 if (error) 2022 return (error); 2023 2024 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 2025 return (error); 2026} 2027 2028int 2029mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 2030 struct vnode *vp) 2031{ 2032 int error; 2033 2034 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 2035 2036 if (!mac_enforce_fs) 2037 return (0); 2038 2039 error = vn_refreshlabel(vp, active_cred); 2040 if (error) 2041 return (error); 2042 2043 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 2044 &vp->v_label); 2045 2046 return (error); 2047} 2048 2049int 2050mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 2051 struct vnode *vp) 2052{ 2053 int error; 2054 2055 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 2056 2057 if (!mac_enforce_fs) 2058 return (0); 2059 2060 error = vn_refreshlabel(vp, active_cred); 2061 if (error) 2062 return (error); 2063 2064 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 2065 &vp->v_label); 2066 2067 return (error); 2068} 2069 2070int 2071mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 2072{ 2073 int error; 2074 2075 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 2076 2077 if (!mac_enforce_fs) 2078 return (0); 2079 2080 error = vn_refreshlabel(dvp, cred); 2081 if (error) 2082 return (error); 2083 2084 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 2085 return (error); 2086} 2087 2088int 2089mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 2090{ 2091 int error; 2092 2093 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 2094 2095 if (!mac_enforce_fs) 2096 return (0); 2097 2098 error = vn_refreshlabel(vp, cred); 2099 if (error) 2100 return (error); 2101 2102 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 2103 return (error); 2104} 2105 2106static int 2107mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 2108 struct label *newlabel) 2109{ 2110 int error; 2111 2112 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 2113 2114 error = vn_refreshlabel(vp, cred); 2115 if (error) 2116 return (error); 2117 2118 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 2119 2120 return (error); 2121} 2122 2123int 2124mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 2125 struct vnode *vp, struct componentname *cnp) 2126{ 2127 int error; 2128 2129 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 2130 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 2131 2132 if (!mac_enforce_fs) 2133 return (0); 2134 2135 error = vn_refreshlabel(dvp, cred); 2136 if (error) 2137 return (error); 2138 error = vn_refreshlabel(vp, cred); 2139 if (error) 2140 return (error); 2141 2142 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 2143 &vp->v_label, cnp); 2144 return (error); 2145} 2146 2147int 2148mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 2149 struct vnode *vp, int samedir, struct componentname *cnp) 2150{ 2151 int error; 2152 2153 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 2154 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 2155 2156 if (!mac_enforce_fs) 2157 return (0); 2158 2159 error = vn_refreshlabel(dvp, cred); 2160 if (error) 2161 return (error); 2162 if (vp != NULL) { 2163 error = vn_refreshlabel(vp, cred); 2164 if (error) 2165 return (error); 2166 } 2167 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 2168 vp != NULL ? &vp->v_label : NULL, samedir, cnp); 2169 return (error); 2170} 2171 2172int 2173mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 2174{ 2175 int error; 2176 2177 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 2178 2179 if (!mac_enforce_fs) 2180 return (0); 2181 2182 error = vn_refreshlabel(vp, cred); 2183 if (error) 2184 return (error); 2185 2186 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 2187 return (error); 2188} 2189 2190int 2191mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 2192 struct acl *acl) 2193{ 2194 int error; 2195 2196 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 2197 2198 if (!mac_enforce_fs) 2199 return (0); 2200 2201 error = vn_refreshlabel(vp, cred); 2202 if (error) 2203 return (error); 2204 2205 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 2206 return (error); 2207} 2208 2209int 2210mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 2211 int attrnamespace, const char *name, struct uio *uio) 2212{ 2213 int error; 2214 2215 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 2216 2217 if (!mac_enforce_fs) 2218 return (0); 2219 2220 error = vn_refreshlabel(vp, cred); 2221 if (error) 2222 return (error); 2223 2224 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 2225 attrnamespace, name, uio); 2226 return (error); 2227} 2228 2229int 2230mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 2231{ 2232 int error; 2233 2234 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 2235 2236 if (!mac_enforce_fs) 2237 return (0); 2238 2239 error = vn_refreshlabel(vp, cred); 2240 if (error) 2241 return (error); 2242 2243 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 2244 return (error); 2245} 2246 2247int 2248mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 2249{ 2250 int error; 2251 2252 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 2253 2254 if (!mac_enforce_fs) 2255 return (0); 2256 2257 error = vn_refreshlabel(vp, cred); 2258 if (error) 2259 return (error); 2260 2261 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 2262 return (error); 2263} 2264 2265int 2266mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 2267 gid_t gid) 2268{ 2269 int error; 2270 2271 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 2272 2273 if (!mac_enforce_fs) 2274 return (0); 2275 2276 error = vn_refreshlabel(vp, cred); 2277 if (error) 2278 return (error); 2279 2280 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 2281 return (error); 2282} 2283 2284int 2285mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 2286 struct timespec atime, struct timespec mtime) 2287{ 2288 int error; 2289 2290 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 2291 2292 if (!mac_enforce_fs) 2293 return (0); 2294 2295 error = vn_refreshlabel(vp, cred); 2296 if (error) 2297 return (error); 2298 2299 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 2300 mtime); 2301 return (error); 2302} 2303 2304int 2305mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 2306 struct vnode *vp) 2307{ 2308 int error; 2309 2310 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 2311 2312 if (!mac_enforce_fs) 2313 return (0); 2314 2315 error = vn_refreshlabel(vp, active_cred); 2316 if (error) 2317 return (error); 2318 2319 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 2320 &vp->v_label); 2321 return (error); 2322} 2323 2324int 2325mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 2326 struct vnode *vp) 2327{ 2328 int error; 2329 2330 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 2331 2332 if (!mac_enforce_fs) 2333 return (0); 2334 2335 error = vn_refreshlabel(vp, active_cred); 2336 if (error) 2337 return (error); 2338 2339 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 2340 &vp->v_label); 2341 2342 return (error); 2343} 2344 2345/* 2346 * When relabeling a process, call out to the policies for the maximum 2347 * permission allowed for each object type we know about in its 2348 * memory space, and revoke access (in the least surprising ways we 2349 * know) when necessary. The process lock is not held here. 2350 */ 2351static void 2352mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 2353{ 2354 2355 /* XXX freeze all other threads */ 2356 mac_cred_mmapped_drop_perms_recurse(td, cred, 2357 &td->td_proc->p_vmspace->vm_map); 2358 /* XXX allow other threads to continue */ 2359} 2360 2361static __inline const char * 2362prot2str(vm_prot_t prot) 2363{ 2364 2365 switch (prot & VM_PROT_ALL) { 2366 case VM_PROT_READ: 2367 return ("r--"); 2368 case VM_PROT_READ | VM_PROT_WRITE: 2369 return ("rw-"); 2370 case VM_PROT_READ | VM_PROT_EXECUTE: 2371 return ("r-x"); 2372 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 2373 return ("rwx"); 2374 case VM_PROT_WRITE: 2375 return ("-w-"); 2376 case VM_PROT_EXECUTE: 2377 return ("--x"); 2378 case VM_PROT_WRITE | VM_PROT_EXECUTE: 2379 return ("-wx"); 2380 default: 2381 return ("---"); 2382 } 2383} 2384 2385static void 2386mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 2387 struct vm_map *map) 2388{ 2389 struct vm_map_entry *vme; 2390 int result; 2391 vm_prot_t revokeperms; 2392 vm_object_t object; 2393 vm_ooffset_t offset; 2394 struct vnode *vp; 2395 2396 if (!mac_mmap_revocation) 2397 return; 2398 2399 vm_map_lock_read(map); 2400 for (vme = map->header.next; vme != &map->header; vme = vme->next) { 2401 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 2402 mac_cred_mmapped_drop_perms_recurse(td, cred, 2403 vme->object.sub_map); 2404 continue; 2405 } 2406 /* 2407 * Skip over entries that obviously are not shared. 2408 */ 2409 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 2410 !vme->max_protection) 2411 continue; 2412 /* 2413 * Drill down to the deepest backing object. 2414 */ 2415 offset = vme->offset; 2416 object = vme->object.vm_object; 2417 if (object == NULL) 2418 continue; 2419 while (object->backing_object != NULL) { 2420 object = object->backing_object; 2421 offset += object->backing_object_offset; 2422 } 2423 /* 2424 * At the moment, vm_maps and objects aren't considered 2425 * by the MAC system, so only things with backing by a 2426 * normal object (read: vnodes) are checked. 2427 */ 2428 if (object->type != OBJT_VNODE) 2429 continue; 2430 vp = (struct vnode *)object->handle; 2431 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2432 result = vme->max_protection; 2433 mac_check_vnode_mmap_downgrade(cred, vp, &result); 2434 VOP_UNLOCK(vp, 0, td); 2435 /* 2436 * Find out what maximum protection we may be allowing 2437 * now but a policy needs to get removed. 2438 */ 2439 revokeperms = vme->max_protection & ~result; 2440 if (!revokeperms) 2441 continue; 2442 printf("pid %ld: revoking %s perms from %#lx:%ld " 2443 "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 2444 prot2str(revokeperms), (u_long)vme->start, 2445 (long)(vme->end - vme->start), 2446 prot2str(vme->max_protection), prot2str(vme->protection)); 2447 vm_map_lock_upgrade(map); 2448 /* 2449 * This is the really simple case: if a map has more 2450 * max_protection than is allowed, but it's not being 2451 * actually used (that is, the current protection is 2452 * still allowed), we can just wipe it out and do 2453 * nothing more. 2454 */ 2455 if ((vme->protection & revokeperms) == 0) { 2456 vme->max_protection -= revokeperms; 2457 } else { 2458 if (revokeperms & VM_PROT_WRITE) { 2459 /* 2460 * In the more complicated case, flush out all 2461 * pending changes to the object then turn it 2462 * copy-on-write. 2463 */ 2464 vm_object_reference(object); 2465 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2466 vm_object_page_clean(object, 2467 OFF_TO_IDX(offset), 2468 OFF_TO_IDX(offset + vme->end - vme->start + 2469 PAGE_MASK), 2470 OBJPC_SYNC); 2471 VOP_UNLOCK(vp, 0, td); 2472 vm_object_deallocate(object); 2473 /* 2474 * Why bother if there's no read permissions 2475 * anymore? For the rest, we need to leave 2476 * the write permissions on for COW, or 2477 * remove them entirely if configured to. 2478 */ 2479 if (!mac_mmap_revocation_via_cow) { 2480 vme->max_protection &= ~VM_PROT_WRITE; 2481 vme->protection &= ~VM_PROT_WRITE; 2482 } if ((revokeperms & VM_PROT_READ) == 0) 2483 vme->eflags |= MAP_ENTRY_COW | 2484 MAP_ENTRY_NEEDS_COPY; 2485 } 2486 if (revokeperms & VM_PROT_EXECUTE) { 2487 vme->max_protection &= ~VM_PROT_EXECUTE; 2488 vme->protection &= ~VM_PROT_EXECUTE; 2489 } 2490 if (revokeperms & VM_PROT_READ) { 2491 vme->max_protection = 0; 2492 vme->protection = 0; 2493 } 2494 pmap_protect(map->pmap, vme->start, vme->end, 2495 vme->protection & ~revokeperms); 2496 vm_map_simplify_entry(map, vme); 2497 } 2498 vm_map_lock_downgrade(map); 2499 } 2500 vm_map_unlock_read(map); 2501} 2502 2503/* 2504 * When the subject's label changes, it may require revocation of privilege 2505 * to mapped objects. This can't be done on-the-fly later with a unified 2506 * buffer cache. 2507 */ 2508static void 2509mac_relabel_cred(struct ucred *cred, struct label *newlabel) 2510{ 2511 2512 MAC_PERFORM(relabel_cred, cred, newlabel); 2513} 2514 2515void 2516mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 2517{ 2518 2519 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 2520} 2521 2522void 2523mac_create_ifnet(struct ifnet *ifnet) 2524{ 2525 2526 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 2527} 2528 2529void 2530mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 2531{ 2532 2533 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 2534} 2535 2536void 2537mac_create_socket(struct ucred *cred, struct socket *socket) 2538{ 2539 2540 MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 2541} 2542 2543void 2544mac_create_pipe(struct ucred *cred, struct pipe *pipe) 2545{ 2546 2547 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 2548} 2549 2550void 2551mac_create_socket_from_socket(struct socket *oldsocket, 2552 struct socket *newsocket) 2553{ 2554 2555 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 2556 newsocket, &newsocket->so_label); 2557} 2558 2559static void 2560mac_relabel_socket(struct ucred *cred, struct socket *socket, 2561 struct label *newlabel) 2562{ 2563 2564 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 2565} 2566 2567static void 2568mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 2569{ 2570 2571 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 2572} 2573 2574void 2575mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 2576{ 2577 2578 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 2579 socket, &socket->so_peerlabel); 2580} 2581 2582void 2583mac_set_socket_peer_from_socket(struct socket *oldsocket, 2584 struct socket *newsocket) 2585{ 2586 2587 MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 2588 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 2589} 2590 2591void 2592mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 2593{ 2594 2595 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 2596 datagram, &datagram->m_pkthdr.label); 2597} 2598 2599void 2600mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 2601{ 2602 2603 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 2604 fragment, &fragment->m_pkthdr.label); 2605} 2606 2607void 2608mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 2609{ 2610 2611 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2612 &ipq->ipq_label); 2613} 2614 2615void 2616mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2617{ 2618 2619 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 2620 newmbuf, &newmbuf->m_pkthdr.label); 2621} 2622 2623void 2624mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 2625{ 2626 2627 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 2628 &mbuf->m_pkthdr.label); 2629} 2630 2631void 2632mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 2633{ 2634 2635 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 2636 &mbuf->m_pkthdr.label); 2637} 2638 2639void 2640mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 2641{ 2642 2643 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 2644 &mbuf->m_pkthdr.label); 2645} 2646 2647void 2648mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 2649 struct mbuf *newmbuf) 2650{ 2651 2652 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 2653 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 2654 &newmbuf->m_pkthdr.label); 2655} 2656 2657void 2658mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2659{ 2660 2661 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 2662 newmbuf, &newmbuf->m_pkthdr.label); 2663} 2664 2665int 2666mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 2667{ 2668 int result; 2669 2670 result = 1; 2671 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 2672 ipq, &ipq->ipq_label); 2673 2674 return (result); 2675} 2676 2677void 2678mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 2679{ 2680 2681 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2682 &ipq->ipq_label); 2683} 2684 2685void 2686mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 2687{ 2688 2689 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 2690 &mbuf->m_pkthdr.label); 2691} 2692 2693void 2694mac_create_mount(struct ucred *cred, struct mount *mp) 2695{ 2696 2697 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 2698 &mp->mnt_fslabel); 2699} 2700 2701void 2702mac_create_root_mount(struct ucred *cred, struct mount *mp) 2703{ 2704 2705 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 2706 &mp->mnt_fslabel); 2707} 2708 2709int 2710mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 2711{ 2712 int error; 2713 2714 if (!mac_enforce_network) 2715 return (0); 2716 2717 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 2718 &ifnet->if_label); 2719 2720 return (error); 2721} 2722 2723static int 2724mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 2725{ 2726 int error; 2727 2728 MAC_CHECK(check_cred_relabel, cred, newlabel); 2729 2730 return (error); 2731} 2732 2733int 2734mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 2735{ 2736 int error; 2737 2738 if (!mac_enforce_process) 2739 return (0); 2740 2741 MAC_CHECK(check_cred_visible, u1, u2); 2742 2743 return (error); 2744} 2745 2746int 2747mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 2748{ 2749 int error; 2750 2751 if (!mac_enforce_network) 2752 return (0); 2753 2754 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 2755 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 2756 if_printf(ifnet, "not initialized\n"); 2757 2758 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 2759 &mbuf->m_pkthdr.label); 2760 2761 return (error); 2762} 2763 2764int 2765mac_check_mount_stat(struct ucred *cred, struct mount *mount) 2766{ 2767 int error; 2768 2769 if (!mac_enforce_fs) 2770 return (0); 2771 2772 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 2773 2774 return (error); 2775} 2776 2777int 2778mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 2779 void *data) 2780{ 2781 int error; 2782 2783 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2784 2785 if (!mac_enforce_pipe) 2786 return (0); 2787 2788 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 2789 2790 return (error); 2791} 2792 2793int 2794mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 2795{ 2796 int error; 2797 2798 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2799 2800 if (!mac_enforce_pipe) 2801 return (0); 2802 2803 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2804 2805 return (error); 2806} 2807 2808int 2809mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2810{ 2811 int error; 2812 2813 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2814 2815 if (!mac_enforce_pipe) 2816 return (0); 2817 2818 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 2819 2820 return (error); 2821} 2822 2823static int 2824mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 2825 struct label *newlabel) 2826{ 2827 int error; 2828 2829 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2830 2831 if (!mac_enforce_pipe) 2832 return (0); 2833 2834 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 2835 2836 return (error); 2837} 2838 2839int 2840mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2841{ 2842 int error; 2843 2844 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2845 2846 if (!mac_enforce_pipe) 2847 return (0); 2848 2849 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2850 2851 return (error); 2852} 2853 2854int 2855mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2856{ 2857 int error; 2858 2859 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2860 2861 if (!mac_enforce_pipe) 2862 return (0); 2863 2864 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2865 2866 return (error); 2867} 2868 2869int 2870mac_check_proc_debug(struct ucred *cred, struct proc *proc) 2871{ 2872 int error; 2873 2874 PROC_LOCK_ASSERT(proc, MA_OWNED); 2875 2876 if (!mac_enforce_process) 2877 return (0); 2878 2879 MAC_CHECK(check_proc_debug, cred, proc); 2880 2881 return (error); 2882} 2883 2884int 2885mac_check_proc_sched(struct ucred *cred, struct proc *proc) 2886{ 2887 int error; 2888 2889 PROC_LOCK_ASSERT(proc, MA_OWNED); 2890 2891 if (!mac_enforce_process) 2892 return (0); 2893 2894 MAC_CHECK(check_proc_sched, cred, proc); 2895 2896 return (error); 2897} 2898 2899int 2900mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 2901{ 2902 int error; 2903 2904 PROC_LOCK_ASSERT(proc, MA_OWNED); 2905 2906 if (!mac_enforce_process) 2907 return (0); 2908 2909 MAC_CHECK(check_proc_signal, cred, proc, signum); 2910 2911 return (error); 2912} 2913 2914int 2915mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 2916 struct sockaddr *sockaddr) 2917{ 2918 int error; 2919 2920 if (!mac_enforce_socket) 2921 return (0); 2922 2923 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 2924 sockaddr); 2925 2926 return (error); 2927} 2928 2929int 2930mac_check_socket_connect(struct ucred *cred, struct socket *socket, 2931 struct sockaddr *sockaddr) 2932{ 2933 int error; 2934 2935 if (!mac_enforce_socket) 2936 return (0); 2937 2938 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 2939 sockaddr); 2940 2941 return (error); 2942} 2943 2944int 2945mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2946{ 2947 int error; 2948 2949 if (!mac_enforce_socket) 2950 return (0); 2951 2952 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2953 &mbuf->m_pkthdr.label); 2954 2955 return (error); 2956} 2957 2958int 2959mac_check_socket_listen(struct ucred *cred, struct socket *socket) 2960{ 2961 int error; 2962 2963 if (!mac_enforce_socket) 2964 return (0); 2965 2966 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 2967 return (error); 2968} 2969 2970int 2971mac_check_socket_receive(struct ucred *cred, struct socket *so) 2972{ 2973 int error; 2974 2975 if (!mac_enforce_socket) 2976 return (0); 2977 2978 MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2979 2980 return (error); 2981} 2982 2983static int 2984mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 2985 struct label *newlabel) 2986{ 2987 int error; 2988 2989 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 2990 newlabel); 2991 2992 return (error); 2993} 2994 2995int 2996mac_check_socket_send(struct ucred *cred, struct socket *so) 2997{ 2998 int error; 2999 3000 if (!mac_enforce_socket) 3001 return (0); 3002 3003 MAC_CHECK(check_socket_send, cred, so, &so->so_label); 3004 3005 return (error); 3006} 3007 3008int 3009mac_check_socket_visible(struct ucred *cred, struct socket *socket) 3010{ 3011 int error; 3012 3013 if (!mac_enforce_socket) 3014 return (0); 3015 3016 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 3017 3018 return (error); 3019} 3020 3021int 3022mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 3023 struct ifnet *ifnet) 3024{ 3025 struct mac label; 3026 int error; 3027 3028 error = mac_externalize(&ifnet->if_label, &label); 3029 if (error) 3030 return (error); 3031 3032 return (copyout(&label, ifr->ifr_ifru.ifru_data, sizeof(label))); 3033} 3034 3035int 3036mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 3037 struct ifnet *ifnet) 3038{ 3039 struct mac newlabel; 3040 struct label intlabel; 3041 int error; 3042 3043 error = copyin(ifr->ifr_ifru.ifru_data, &newlabel, sizeof(newlabel)); 3044 if (error) 3045 return (error); 3046 3047 error = mac_internalize(&intlabel, &newlabel); 3048 if (error) 3049 return (error); 3050 3051 /* 3052 * XXX: Note that this is a redundant privilege check, since 3053 * policies impose this check themselves if required by the 3054 * policy. Eventually, this should go away. 3055 */ 3056 error = suser_cred(cred, 0); 3057 if (error) 3058 goto out; 3059 3060 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 3061 &intlabel); 3062 if (error) 3063 goto out; 3064 3065 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 3066 3067out: 3068 mac_destroy_temp(&intlabel); 3069 return (error); 3070} 3071 3072void 3073mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp) 3074{ 3075 3076 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 3077} 3078 3079void 3080mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 3081{ 3082 3083 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 3084} 3085 3086void 3087mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 3088 struct devfs_dirent *de) 3089{ 3090 3091 MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de, 3092 &de->de_label); 3093} 3094 3095static int 3096mac_stdcreatevnode_ea(struct vnode *vp) 3097{ 3098 int error; 3099 3100 MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); 3101 3102 return (error); 3103} 3104 3105void 3106mac_create_devfs_directory(char *dirname, int dirnamelen, 3107 struct devfs_dirent *de) 3108{ 3109 3110 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 3111 &de->de_label); 3112} 3113 3114/* 3115 * When a new vnode is created, this call will initialize its label. 3116 */ 3117void 3118mac_create_vnode(struct ucred *cred, struct vnode *parent, 3119 struct vnode *child) 3120{ 3121 int error; 3122 3123 ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); 3124 ASSERT_VOP_LOCKED(child, "mac_create_vnode"); 3125 3126 error = vn_refreshlabel(parent, cred); 3127 if (error) { 3128 printf("mac_create_vnode: vn_refreshlabel returned %d\n", 3129 error); 3130 printf("mac_create_vnode: using old vnode label\n"); 3131 } 3132 3133 MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, 3134 &child->v_label); 3135} 3136 3137int 3138mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 3139 struct mac *extmac) 3140{ 3141 struct label intlabel; 3142 int error; 3143 3144 error = mac_internalize(&intlabel, extmac); 3145 if (error) 3146 return (error); 3147 3148 mac_check_socket_relabel(cred, so, &intlabel); 3149 if (error) { 3150 mac_destroy_temp(&intlabel); 3151 return (error); 3152 } 3153 3154 mac_relabel_socket(cred, so, &intlabel); 3155 3156 mac_destroy_temp(&intlabel); 3157 return (0); 3158} 3159 3160int 3161mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 3162{ 3163 int error; 3164 3165 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 3166 3167 error = mac_check_pipe_relabel(cred, pipe, label); 3168 if (error) 3169 return (error); 3170 3171 mac_relabel_pipe(cred, pipe, label); 3172 3173 return (0); 3174} 3175 3176int 3177mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 3178 struct mac *extmac) 3179{ 3180 3181 return (mac_externalize(&so->so_label, extmac)); 3182} 3183 3184int 3185mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 3186 struct mac *extmac) 3187{ 3188 3189 return (mac_externalize(&so->so_peerlabel, extmac)); 3190} 3191 3192/* 3193 * Implementation of VOP_SETLABEL() that relies on extended attributes 3194 * to store label data. Can be referenced by filesystems supporting 3195 * extended attributes. 3196 */ 3197int 3198vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 3199{ 3200 struct vnode *vp = ap->a_vp; 3201 struct label *intlabel = ap->a_label; 3202 struct mac extmac; 3203 int error; 3204 3205 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 3206 3207 /* 3208 * XXX: Eventually call out to EA check/set calls here. 3209 * Be particularly careful to avoid race conditions, 3210 * consistency problems, and stability problems when 3211 * dealing with multiple EAs. In particular, we require 3212 * the ability to write multiple EAs on the same file in 3213 * a single transaction, which the current EA interface 3214 * does not provide. 3215 */ 3216 3217 error = mac_externalize(intlabel, &extmac); 3218 if (error) 3219 return (error); 3220 3221 error = vn_extattr_set(vp, IO_NODELOCKED, 3222 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 3223 sizeof(extmac), (char *)&extmac, curthread); 3224 if (error) 3225 return (error); 3226 3227 mac_relabel_vnode(ap->a_cred, vp, intlabel); 3228 3229 vp->v_vflag |= VV_CACHEDLABEL; 3230 3231 return (0); 3232} 3233 3234static int 3235vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 3236{ 3237 int error; 3238 3239 if (vp->v_mount == NULL) { 3240 /* printf("vn_setlabel: null v_mount\n"); */ 3241 if (vp->v_type != VNON) 3242 printf("vn_setlabel: null v_mount with non-VNON\n"); 3243 return (EBADF); 3244 } 3245 3246 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 3247 return (EOPNOTSUPP); 3248 3249 /* 3250 * Multi-phase commit. First check the policies to confirm the 3251 * change is OK. Then commit via the filesystem. Finally, 3252 * update the actual vnode label. Question: maybe the filesystem 3253 * should update the vnode at the end as part of VOP_SETLABEL()? 3254 */ 3255 error = mac_check_vnode_relabel(cred, vp, intlabel); 3256 if (error) 3257 return (error); 3258 3259 /* 3260 * VADMIN provides the opportunity for the filesystem to make 3261 * decisions about who is and is not able to modify labels 3262 * and protections on files. This might not be right. We can't 3263 * assume VOP_SETLABEL() will do it, because we might implement 3264 * that as part of vop_stdsetlabel_ea(). 3265 */ 3266 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 3267 if (error) 3268 return (error); 3269 3270 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 3271 if (error) 3272 return (error); 3273 3274 return (0); 3275} 3276 3277/* 3278 * MPSAFE 3279 */ 3280int 3281__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3282{ 3283 struct mac extmac; 3284 int error; 3285 3286 error = mac_externalize(&td->td_ucred->cr_label, &extmac); 3287 if (error == 0) 3288 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 3289 3290 return (error); 3291} 3292 3293/* 3294 * MPSAFE 3295 */ 3296int 3297__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3298{ 3299 struct ucred *newcred, *oldcred; 3300 struct proc *p; 3301 struct mac extmac; 3302 struct label intlabel; 3303 int error; 3304 3305 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 3306 if (error) 3307 return (error); 3308 3309 error = mac_internalize(&intlabel, &extmac); 3310 if (error) 3311 return (error); 3312 3313 newcred = crget(); 3314 3315 p = td->td_proc; 3316 PROC_LOCK(p); 3317 oldcred = p->p_ucred; 3318 3319 error = mac_check_cred_relabel(oldcred, &intlabel); 3320 if (error) { 3321 PROC_UNLOCK(p); 3322 mac_destroy_temp(&intlabel); 3323 crfree(newcred); 3324 return (error); 3325 } 3326 3327 setsugid(p); 3328 crcopy(newcred, oldcred); 3329 mac_relabel_cred(newcred, &intlabel); 3330 p->p_ucred = newcred; 3331 3332 /* 3333 * Grab additional reference for use while revoking mmaps, prior 3334 * to releasing the proc lock and sharing the cred. 3335 */ 3336 crhold(newcred); 3337 PROC_UNLOCK(p); 3338 3339 mtx_lock(&Giant); 3340 mac_cred_mmapped_drop_perms(td, newcred); 3341 mtx_unlock(&Giant); 3342 3343 crfree(newcred); /* Free revocation reference. */ 3344 crfree(oldcred); 3345 mac_destroy_temp(&intlabel); 3346 return (0); 3347} 3348 3349/* 3350 * MPSAFE 3351 */ 3352int 3353__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3354{ 3355 struct file *fp; 3356 struct mac extmac; 3357 struct vnode *vp; 3358 struct pipe *pipe; 3359 int error; 3360 3361 mtx_lock(&Giant); 3362 3363 error = fget(td, SCARG(uap, fd), &fp); 3364 if (error) 3365 goto out; 3366 3367 switch (fp->f_type) { 3368 case DTYPE_FIFO: 3369 case DTYPE_VNODE: 3370 vp = (struct vnode *)fp->f_data; 3371 3372 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3373 error = vn_refreshlabel(vp, td->td_ucred); 3374 if (error == 0) 3375 error = mac_externalize(&vp->v_label, &extmac); 3376 VOP_UNLOCK(vp, 0, td); 3377 break; 3378 case DTYPE_PIPE: 3379 pipe = (struct pipe *)fp->f_data; 3380 error = mac_externalize(pipe->pipe_label, &extmac); 3381 break; 3382 default: 3383 error = EINVAL; 3384 } 3385 3386 if (error == 0) 3387 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 3388 3389 fdrop(fp, td); 3390 3391out: 3392 mtx_unlock(&Giant); 3393 return (error); 3394} 3395 3396/* 3397 * MPSAFE 3398 */ 3399int 3400__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3401{ 3402 struct nameidata nd; 3403 struct mac extmac; 3404 int error; 3405 3406 mtx_lock(&Giant); 3407 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 3408 SCARG(uap, path_p), td); 3409 error = namei(&nd); 3410 if (error) 3411 goto out; 3412 3413 error = vn_refreshlabel(nd.ni_vp, td->td_ucred); 3414 if (error == 0) 3415 error = mac_externalize(&nd.ni_vp->v_label, &extmac); 3416 NDFREE(&nd, 0); 3417 if (error) 3418 goto out; 3419 3420 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 3421 3422out: 3423 mtx_unlock(&Giant); 3424 return (error); 3425} 3426 3427/* 3428 * MPSAFE 3429 */ 3430int 3431__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3432{ 3433 struct file *fp; 3434 struct mac extmac; 3435 struct label intlabel; 3436 struct mount *mp; 3437 struct vnode *vp; 3438 struct pipe *pipe; 3439 int error; 3440 3441 mtx_lock(&Giant); 3442 error = fget(td, SCARG(uap, fd), &fp); 3443 if (error) 3444 goto out1; 3445 3446 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 3447 if (error) 3448 goto out2; 3449 3450 error = mac_internalize(&intlabel, &extmac); 3451 if (error) 3452 goto out2; 3453 3454 switch (fp->f_type) { 3455 case DTYPE_FIFO: 3456 case DTYPE_VNODE: 3457 vp = (struct vnode *)fp->f_data; 3458 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3459 if (error != 0) 3460 break; 3461 3462 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3463 error = vn_setlabel(vp, &intlabel, td->td_ucred); 3464 VOP_UNLOCK(vp, 0, td); 3465 vn_finished_write(mp); 3466 mac_destroy_temp(&intlabel); 3467 break; 3468 case DTYPE_PIPE: 3469 pipe = (struct pipe *)fp->f_data; 3470 PIPE_LOCK(pipe); 3471 error = mac_pipe_label_set(td->td_ucred, pipe, &intlabel); 3472 PIPE_UNLOCK(pipe); 3473 break; 3474 default: 3475 error = EINVAL; 3476 } 3477 3478out2: 3479 fdrop(fp, td); 3480out1: 3481 mtx_unlock(&Giant); 3482 return (error); 3483} 3484 3485/* 3486 * MPSAFE 3487 */ 3488int 3489__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3490{ 3491 struct nameidata nd; 3492 struct mac extmac; 3493 struct label intlabel; 3494 struct mount *mp; 3495 int error; 3496 3497 mtx_lock(&Giant); 3498 3499 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 3500 if (error) 3501 goto out; 3502 3503 error = mac_internalize(&intlabel, &extmac); 3504 if (error) 3505 goto out; 3506 3507 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 3508 SCARG(uap, path_p), td); 3509 error = namei(&nd); 3510 if (error) 3511 goto out2; 3512 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3513 if (error) 3514 goto out2; 3515 3516 error = vn_setlabel(nd.ni_vp, &intlabel, td->td_ucred); 3517 3518 vn_finished_write(mp); 3519out2: 3520 mac_destroy_temp(&intlabel); 3521 NDFREE(&nd, 0); 3522out: 3523 mtx_unlock(&Giant); 3524 return (error); 3525} 3526 3527int 3528mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3529{ 3530 struct mac_policy_conf *mpc; 3531 char target[MAC_MAX_POLICY_NAME]; 3532 int error; 3533 3534 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL); 3535 if (error) 3536 return (error); 3537 3538 error = ENOSYS; 3539 MAC_POLICY_LIST_BUSY(); 3540 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 3541 if (strcmp(mpc->mpc_name, target) == 0 && 3542 mpc->mpc_ops->mpo_syscall != NULL) { 3543 error = mpc->mpc_ops->mpo_syscall(td, 3544 SCARG(uap, call), SCARG(uap, arg)); 3545 goto out; 3546 } 3547 } 3548 3549out: 3550 MAC_POLICY_LIST_UNBUSY(); 3551 return (error); 3552} 3553 3554SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 3555SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 3556 3557#else /* !MAC */ 3558 3559int 3560__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3561{ 3562 3563 return (ENOSYS); 3564} 3565 3566int 3567__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3568{ 3569 3570 return (ENOSYS); 3571} 3572 3573int 3574__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3575{ 3576 3577 return (ENOSYS); 3578} 3579 3580int 3581__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3582{ 3583 3584 return (ENOSYS); 3585} 3586 3587int 3588__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3589{ 3590 3591 return (ENOSYS); 3592} 3593 3594int 3595__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3596{ 3597 3598 return (ENOSYS); 3599} 3600 3601int 3602mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3603{ 3604 3605 return (ENOSYS); 3606} 3607 3608#endif /* !MAC */ 3609