17bc82500SRobert Watson /*- 2471e5756SRobert Watson * Copyright (c) 1999-2002, 2006 Robert N. M. Watson 37bc82500SRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 4f0c2044bSRobert Watson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 5aed55708SRobert Watson * Copyright (c) 2005-2006 SPARTA, Inc. 67bc82500SRobert Watson * All rights reserved. 77bc82500SRobert Watson * 87bc82500SRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the 97bc82500SRobert Watson * TrustedBSD Project. 107bc82500SRobert Watson * 116201265bSRobert Watson * This software was developed for the FreeBSD Project in part by Network 126201265bSRobert Watson * Associates Laboratories, the Security Research Division of Network 136201265bSRobert Watson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 146201265bSRobert Watson * as part of the DARPA CHATS research program. 157bc82500SRobert Watson * 1649bb6870SRobert Watson * This software was enhanced by SPARTA ISSO under SPAWAR contract 1749bb6870SRobert Watson * N66001-04-C-6019 ("SEFOS"). 1849bb6870SRobert Watson * 197bc82500SRobert Watson * Redistribution and use in source and binary forms, with or without 207bc82500SRobert Watson * modification, are permitted provided that the following conditions 217bc82500SRobert Watson * are met: 227bc82500SRobert Watson * 1. Redistributions of source code must retain the above copyright 237bc82500SRobert Watson * notice, this list of conditions and the following disclaimer. 247bc82500SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 257bc82500SRobert Watson * notice, this list of conditions and the following disclaimer in the 267bc82500SRobert Watson * documentation and/or other materials provided with the distribution. 277bc82500SRobert Watson * 287bc82500SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 297bc82500SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 307bc82500SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 317bc82500SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 327bc82500SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 337bc82500SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 347bc82500SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 357bc82500SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 367bc82500SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 377bc82500SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 387bc82500SRobert Watson * SUCH DAMAGE. 397bc82500SRobert Watson */ 40677b542eSDavid E. O'Brien 41c8e7bf92SRobert Watson /*- 42471e5756SRobert Watson * Framework for extensible kernel access control. This file contains core 43471e5756SRobert Watson * kernel infrastructure for the TrustedBSD MAC Framework, including policy 44471e5756SRobert Watson * registration, versioning, locking, error composition operator, and system 45471e5756SRobert Watson * calls. 46471e5756SRobert Watson * 47471e5756SRobert Watson * The MAC Framework implements three programming interfaces: 48471e5756SRobert Watson * 49471e5756SRobert Watson * - The kernel MAC interface, defined in mac_framework.h, and invoked 50471e5756SRobert Watson * throughout the kernel to request security decisions, notify of security 51471e5756SRobert Watson * related events, etc. 52471e5756SRobert Watson * 53471e5756SRobert Watson * - The MAC policy module interface, defined in mac_policy.h, which is 54471e5756SRobert Watson * implemented by MAC policy modules and invoked by the MAC Framework to 55471e5756SRobert Watson * forward kernel security requests and notifications to policy modules. 56471e5756SRobert Watson * 57471e5756SRobert Watson * - The user MAC API, defined in mac.h, which allows user programs to query 58471e5756SRobert Watson * and set label state on objects. 59471e5756SRobert Watson * 60471e5756SRobert Watson * The majority of the MAC Framework implementation may be found in 61471e5756SRobert Watson * src/sys/security/mac. Sample policy modules may be found in 6249869305STom Rhodes * src/sys/security/mac_*. 637bc82500SRobert Watson */ 647bc82500SRobert Watson 65677b542eSDavid E. O'Brien #include <sys/cdefs.h> 66677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 67677b542eSDavid E. O'Brien 687bc82500SRobert Watson #include "opt_mac.h" 69f9d0d524SRobert Watson 707bc82500SRobert Watson #include <sys/param.h> 71a96acd1aSRobert Watson #include <sys/condvar.h> 7295fab37eSRobert Watson #include <sys/extattr.h> 73670cb89bSRobert Watson #include <sys/imgact.h> 7495fab37eSRobert Watson #include <sys/kernel.h> 7595fab37eSRobert Watson #include <sys/lock.h> 76b656366bSBruce Evans #include <sys/malloc.h> 7795fab37eSRobert Watson #include <sys/mutex.h> 7895fab37eSRobert Watson #include <sys/mac.h> 797ba28492SRobert Watson #include <sys/module.h> 8095fab37eSRobert Watson #include <sys/proc.h> 81f51e5803SRobert Watson #include <sys/sbuf.h> 8295fab37eSRobert Watson #include <sys/systm.h> 837bc82500SRobert Watson #include <sys/sysproto.h> 847bc82500SRobert Watson #include <sys/sysent.h> 8595fab37eSRobert Watson #include <sys/vnode.h> 8695fab37eSRobert Watson #include <sys/mount.h> 8795fab37eSRobert Watson #include <sys/file.h> 8895fab37eSRobert Watson #include <sys/namei.h> 8995fab37eSRobert Watson #include <sys/socket.h> 9095fab37eSRobert Watson #include <sys/pipe.h> 9195fab37eSRobert Watson #include <sys/socketvar.h> 9295fab37eSRobert Watson #include <sys/sysctl.h> 9395fab37eSRobert Watson 9495fab37eSRobert Watson #include <vm/vm.h> 9595fab37eSRobert Watson #include <vm/pmap.h> 9695fab37eSRobert Watson #include <vm/vm_map.h> 9795fab37eSRobert Watson #include <vm/vm_object.h> 9895fab37eSRobert Watson 9995fab37eSRobert Watson #include <fs/devfs/devfs.h> 10095fab37eSRobert Watson 10195fab37eSRobert Watson #include <net/bpfdesc.h> 10295fab37eSRobert Watson #include <net/if.h> 10395fab37eSRobert Watson #include <net/if_var.h> 10495fab37eSRobert Watson 10595fab37eSRobert Watson #include <netinet/in.h> 10695fab37eSRobert Watson #include <netinet/ip_var.h> 10795fab37eSRobert Watson 108aed55708SRobert Watson #include <security/mac/mac_framework.h> 1096fa0475dSRobert Watson #include <security/mac/mac_internal.h> 1100efd6615SRobert Watson #include <security/mac/mac_policy.h> 1116fa0475dSRobert Watson 11295fab37eSRobert Watson #ifdef MAC 11395fab37eSRobert Watson 1147ba28492SRobert Watson /* 115471e5756SRobert Watson * Root sysctl node for all MAC and MAC policy controls. 1167ba28492SRobert Watson */ 11795fab37eSRobert Watson SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 11895fab37eSRobert Watson "TrustedBSD MAC policy controls"); 119b2f0927aSRobert Watson 12017041e67SRobert Watson /* 121471e5756SRobert Watson * Declare that the kernel provides MAC support, version 3 (FreeBSD 7.x). 122471e5756SRobert Watson * This permits modules to refuse to be loaded if the necessary support isn't 123471e5756SRobert Watson * present, even if it's pre-boot. 124471e5756SRobert Watson */ 125471e5756SRobert Watson #define MAC_VERSION 3 126471e5756SRobert Watson static unsigned int mac_version = MAC_VERSION; 127471e5756SRobert Watson 128471e5756SRobert Watson MODULE_VERSION(kernel_mac_support, MAC_VERSION); 129471e5756SRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, version, CTLFLAG_RD, &mac_version, 0, 130471e5756SRobert Watson ""); 131471e5756SRobert Watson 132471e5756SRobert Watson /* 13317041e67SRobert Watson * Labels consist of a indexed set of "slots", which are allocated policies 13417041e67SRobert Watson * as required. The MAC Framework maintains a bitmask of slots allocated so 13517041e67SRobert Watson * far to prevent reuse. Slots cannot be reused, as the MAC Framework 13617041e67SRobert Watson * guarantees that newly allocated slots in labels will be NULL unless 13717041e67SRobert Watson * otherwise initialized, and because we do not have a mechanism to garbage 13817041e67SRobert Watson * collect slots on policy unload. As labeled policies tend to be statically 13917041e67SRobert Watson * loaded during boot, and not frequently unloaded and reloaded, this is not 14017041e67SRobert Watson * generally an issue. 14117041e67SRobert Watson */ 142b2aef571SRobert Watson #if MAC_MAX_SLOTS > 32 143b2aef571SRobert Watson #error "MAC_MAX_SLOTS too large" 14495fab37eSRobert Watson #endif 145a13c67daSRobert Watson 146b2aef571SRobert Watson static unsigned int mac_max_slots = MAC_MAX_SLOTS; 147b2aef571SRobert Watson static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 148471e5756SRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, &mac_max_slots, 149471e5756SRobert Watson 0, ""); 15095fab37eSRobert Watson 151a67fe518SRobert Watson /* 152a67fe518SRobert Watson * Has the kernel started generating labeled objects yet? All read/write 153a67fe518SRobert Watson * access to this variable is serialized during the boot process. Following 154a67fe518SRobert Watson * the end of serialization, we don't update this flag; no locking. 155a67fe518SRobert Watson */ 156089c1bdaSRobert Watson int mac_late = 0; 157763bbd2fSRobert Watson 158225bff6fSRobert Watson /* 15917041e67SRobert Watson * Flag to indicate whether or not we should allocate label storage for new 16017041e67SRobert Watson * mbufs. Since most dynamic policies we currently work with don't rely on 16117041e67SRobert Watson * mbuf labeling, try to avoid paying the cost of mtag allocation unless 16217041e67SRobert Watson * specifically notified of interest. One result of this is that if a 16317041e67SRobert Watson * dynamically loaded policy requests mbuf labels, it must be able to deal 16417041e67SRobert Watson * with a NULL label being returned on any mbufs that were already in flight 16517041e67SRobert Watson * when the policy was loaded. Since the policy already has to deal with 16617041e67SRobert Watson * uninitialized labels, this probably won't be a problem. Note: currently 16717041e67SRobert Watson * no locking. Will this be a problem? 16817041e67SRobert Watson * 16917041e67SRobert Watson * In the future, we may want to allow objects to request labeling on a per- 17017041e67SRobert Watson * object type basis, rather than globally for all objects. 171225bff6fSRobert Watson */ 17219c3e120SRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 173089c1bdaSRobert Watson int mac_labelmbufs = 0; 174225bff6fSRobert Watson #endif 175225bff6fSRobert Watson 17695fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 17795fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 17895fab37eSRobert Watson 179f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 18095fab37eSRobert Watson 18195fab37eSRobert Watson /* 18217041e67SRobert Watson * mac_static_policy_list holds a list of policy modules that are not loaded 18317041e67SRobert Watson * while the system is "live", and cannot be unloaded. These policies can be 18417041e67SRobert Watson * invoked without holding the busy count. 18541a17fe3SRobert Watson * 18641a17fe3SRobert Watson * mac_policy_list stores the list of dynamic policies. A busy count is 18717041e67SRobert Watson * maintained for the list, stored in mac_policy_busy. The busy count is 18817041e67SRobert Watson * protected by mac_policy_mtx; the list may be modified only while the busy 18917041e67SRobert Watson * count is 0, requiring that the lock be held to prevent new references to 19017041e67SRobert Watson * the list from being acquired. For almost all operations, incrementing the 19117041e67SRobert Watson * busy count is sufficient to guarantee consistency, as the list cannot be 19217041e67SRobert Watson * modified while the busy count is elevated. For a few special operations 19317041e67SRobert Watson * involving a change to the list of active policies, the mtx itself must be 19417041e67SRobert Watson * held. A condition variable, mac_policy_cv, is used to signal potential 19517041e67SRobert Watson * exclusive consumers that they should try to acquire the lock if a first 19617041e67SRobert Watson * attempt at exclusive access fails. 19717041e67SRobert Watson * 19817041e67SRobert Watson * This design intentionally avoids fairness, and may starve attempts to 19917041e67SRobert Watson * acquire an exclusive lock on a busy system. This is required because we 20017041e67SRobert Watson * do not ever want acquiring a read reference to perform an unbounded length 20117041e67SRobert Watson * sleep. Read references are acquired in ithreads, network isrs, etc, and 20217041e67SRobert Watson * any unbounded blocking could lead quickly to deadlock. 20317041e67SRobert Watson * 20417041e67SRobert Watson * Another reason for never blocking on read references is that the MAC 20517041e67SRobert Watson * Framework may recurse: if a policy calls a VOP, for example, this might 20617041e67SRobert Watson * lead to vnode life cycle operations (such as init/destroy). 207471e5756SRobert Watson * 208471e5756SRobert Watson * If the kernel option MAC_STATIC has been compiled in, all locking becomes 209471e5756SRobert Watson * a no-op, and the global list of policies is not allowed to change after 210471e5756SRobert Watson * early boot. 21195fab37eSRobert Watson */ 2120a05006dSRobert Watson #ifndef MAC_STATIC 21341a17fe3SRobert Watson static struct mtx mac_policy_mtx; 21441a17fe3SRobert Watson static struct cv mac_policy_cv; 21541a17fe3SRobert Watson static int mac_policy_count; 2160a05006dSRobert Watson #endif 217089c1bdaSRobert Watson struct mac_policy_list_head mac_policy_list; 218089c1bdaSRobert Watson struct mac_policy_list_head mac_static_policy_list; 219a96acd1aSRobert Watson 220a96acd1aSRobert Watson /* 22117041e67SRobert Watson * We manually invoke WITNESS_WARN() to allow Witness to generate warnings 22217041e67SRobert Watson * even if we don't end up ever triggering the wait at run-time. The 22317041e67SRobert Watson * consumer of the exclusive interface must not hold any locks (other than 22417041e67SRobert Watson * potentially Giant) since we may sleep for long (potentially indefinite) 22517041e67SRobert Watson * periods of time waiting for the framework to become quiescent so that a 22617041e67SRobert Watson * policy list change may be made. 227a96acd1aSRobert Watson */ 228089c1bdaSRobert Watson void 22941a17fe3SRobert Watson mac_policy_grab_exclusive(void) 23041a17fe3SRobert Watson { 231c8e7bf92SRobert Watson 2320a05006dSRobert Watson #ifndef MAC_STATIC 2331e4cadcbSRobert Watson if (!mac_late) 2341e4cadcbSRobert Watson return; 2351e4cadcbSRobert Watson 23641a17fe3SRobert Watson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 23741a17fe3SRobert Watson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 23841a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 23941a17fe3SRobert Watson while (mac_policy_count != 0) 24041a17fe3SRobert Watson cv_wait(&mac_policy_cv, &mac_policy_mtx); 2410a05006dSRobert Watson #endif 24241a17fe3SRobert Watson } 24395fab37eSRobert Watson 244089c1bdaSRobert Watson void 24541a17fe3SRobert Watson mac_policy_assert_exclusive(void) 24641a17fe3SRobert Watson { 247c8e7bf92SRobert Watson 2480a05006dSRobert Watson #ifndef MAC_STATIC 2491e4cadcbSRobert Watson if (!mac_late) 2501e4cadcbSRobert Watson return; 2511e4cadcbSRobert Watson 25241a17fe3SRobert Watson mtx_assert(&mac_policy_mtx, MA_OWNED); 25341a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 25441a17fe3SRobert Watson ("mac_policy_assert_exclusive(): not exclusive")); 2550a05006dSRobert Watson #endif 25641a17fe3SRobert Watson } 257225bff6fSRobert Watson 258089c1bdaSRobert Watson void 25941a17fe3SRobert Watson mac_policy_release_exclusive(void) 26041a17fe3SRobert Watson { 26195fab37eSRobert Watson 2620a05006dSRobert Watson #ifndef MAC_STATIC 2631e4cadcbSRobert Watson if (!mac_late) 2641e4cadcbSRobert Watson return; 2651e4cadcbSRobert Watson 26641a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 26741a17fe3SRobert Watson ("mac_policy_release_exclusive(): not exclusive")); 26841a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 26941a17fe3SRobert Watson cv_signal(&mac_policy_cv); 2700a05006dSRobert Watson #endif 27141a17fe3SRobert Watson } 27241a17fe3SRobert Watson 273089c1bdaSRobert Watson void 27441a17fe3SRobert Watson mac_policy_list_busy(void) 27541a17fe3SRobert Watson { 276c8e7bf92SRobert Watson 2770a05006dSRobert Watson #ifndef MAC_STATIC 2781e4cadcbSRobert Watson if (!mac_late) 2791e4cadcbSRobert Watson return; 2801e4cadcbSRobert Watson 28141a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 28241a17fe3SRobert Watson mac_policy_count++; 28341a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 2840a05006dSRobert Watson #endif 28541a17fe3SRobert Watson } 28641a17fe3SRobert Watson 287089c1bdaSRobert Watson int 28841a17fe3SRobert Watson mac_policy_list_conditional_busy(void) 28941a17fe3SRobert Watson { 2900a05006dSRobert Watson #ifndef MAC_STATIC 29141a17fe3SRobert Watson int ret; 29241a17fe3SRobert Watson 2931e4cadcbSRobert Watson if (!mac_late) 2941e4cadcbSRobert Watson return (1); 2951e4cadcbSRobert Watson 29641a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 29741a17fe3SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { 29841a17fe3SRobert Watson mac_policy_count++; 29941a17fe3SRobert Watson ret = 1; 30041a17fe3SRobert Watson } else 30141a17fe3SRobert Watson ret = 0; 30241a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 30341a17fe3SRobert Watson return (ret); 3040a05006dSRobert Watson #else 3051e4cadcbSRobert Watson if (!mac_late) 3061e4cadcbSRobert Watson return (1); 3071e4cadcbSRobert Watson 3080a05006dSRobert Watson return (1); 3090a05006dSRobert Watson #endif 31041a17fe3SRobert Watson } 31141a17fe3SRobert Watson 312089c1bdaSRobert Watson void 31341a17fe3SRobert Watson mac_policy_list_unbusy(void) 31441a17fe3SRobert Watson { 315c8e7bf92SRobert Watson 3160a05006dSRobert Watson #ifndef MAC_STATIC 3171e4cadcbSRobert Watson if (!mac_late) 3181e4cadcbSRobert Watson return; 3191e4cadcbSRobert Watson 32041a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 32141a17fe3SRobert Watson mac_policy_count--; 32241a17fe3SRobert Watson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 32341a17fe3SRobert Watson if (mac_policy_count == 0) 32441a17fe3SRobert Watson cv_signal(&mac_policy_cv); 32541a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 3260a05006dSRobert Watson #endif 32741a17fe3SRobert Watson } 32895fab37eSRobert Watson 32995fab37eSRobert Watson /* 33095fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 33195fab37eSRobert Watson */ 33295fab37eSRobert Watson static void 33395fab37eSRobert Watson mac_init(void) 33495fab37eSRobert Watson { 33595fab37eSRobert Watson 33641a17fe3SRobert Watson LIST_INIT(&mac_static_policy_list); 33795fab37eSRobert Watson LIST_INIT(&mac_policy_list); 338eca8a663SRobert Watson mac_labelzone_init(); 33941a17fe3SRobert Watson 3400a05006dSRobert Watson #ifndef MAC_STATIC 34141a17fe3SRobert Watson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 34241a17fe3SRobert Watson cv_init(&mac_policy_cv, "mac_policy_cv"); 3430a05006dSRobert Watson #endif 34495fab37eSRobert Watson } 34595fab37eSRobert Watson 34695fab37eSRobert Watson /* 34717041e67SRobert Watson * For the purposes of modules that want to know if they were loaded "early", 34817041e67SRobert Watson * set the mac_late flag once we've processed modules either linked into the 34917041e67SRobert Watson * kernel, or loaded before the kernel startup. 35095fab37eSRobert Watson */ 35195fab37eSRobert Watson static void 35295fab37eSRobert Watson mac_late_init(void) 35395fab37eSRobert Watson { 35495fab37eSRobert Watson 35595fab37eSRobert Watson mac_late = 1; 35695fab37eSRobert Watson } 35795fab37eSRobert Watson 35895fab37eSRobert Watson /* 359225bff6fSRobert Watson * After the policy list has changed, walk the list to update any global 36019c3e120SRobert Watson * flags. Currently, we support only one flag, and it's conditionally 36117041e67SRobert Watson * defined; as a result, the entire function is conditional. Eventually, the 36217041e67SRobert Watson * #else case might also iterate across the policies. 363225bff6fSRobert Watson */ 364225bff6fSRobert Watson static void 365225bff6fSRobert Watson mac_policy_updateflags(void) 366225bff6fSRobert Watson { 367225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 36819c3e120SRobert Watson struct mac_policy_conf *tmpc; 369225bff6fSRobert Watson int labelmbufs; 370225bff6fSRobert Watson 37141a17fe3SRobert Watson mac_policy_assert_exclusive(); 372225bff6fSRobert Watson 373225bff6fSRobert Watson labelmbufs = 0; 37441a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 37541a17fe3SRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 37641a17fe3SRobert Watson labelmbufs++; 37741a17fe3SRobert Watson } 378225bff6fSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 379225bff6fSRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 380225bff6fSRobert Watson labelmbufs++; 381225bff6fSRobert Watson } 382225bff6fSRobert Watson mac_labelmbufs = (labelmbufs != 0); 383225bff6fSRobert Watson #endif 384225bff6fSRobert Watson } 385225bff6fSRobert Watson 386225bff6fSRobert Watson /* 38795fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 38895fab37eSRobert Watson */ 38995fab37eSRobert Watson int 39095fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 39195fab37eSRobert Watson { 39295fab37eSRobert Watson struct mac_policy_conf *mpc; 39395fab37eSRobert Watson int error; 39495fab37eSRobert Watson 39595fab37eSRobert Watson error = 0; 39695fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 39795fab37eSRobert Watson 3980a05006dSRobert Watson #ifdef MAC_STATIC 3990a05006dSRobert Watson if (mac_late) { 4000a05006dSRobert Watson printf("mac_policy_modevent: MAC_STATIC and late\n"); 4010a05006dSRobert Watson return (EBUSY); 4020a05006dSRobert Watson } 4030a05006dSRobert Watson #endif 4040a05006dSRobert Watson 40595fab37eSRobert Watson switch (type) { 40695fab37eSRobert Watson case MOD_LOAD: 40795fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 40895fab37eSRobert Watson mac_late) { 40995fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 41095fab37eSRobert Watson "after booting\n", mpc->mpc_name); 41195fab37eSRobert Watson error = EBUSY; 41295fab37eSRobert Watson break; 41395fab37eSRobert Watson } 41495fab37eSRobert Watson error = mac_policy_register(mpc); 41595fab37eSRobert Watson break; 41695fab37eSRobert Watson case MOD_UNLOAD: 41795fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 41895fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 41995fab37eSRobert Watson != 0) 42095fab37eSRobert Watson error = mac_policy_unregister(mpc); 42195fab37eSRobert Watson else 42295fab37eSRobert Watson error = 0; 42395fab37eSRobert Watson break; 42495fab37eSRobert Watson default: 4253e019deaSPoul-Henning Kamp error = EOPNOTSUPP; 42695fab37eSRobert Watson break; 42795fab37eSRobert Watson } 42895fab37eSRobert Watson 42995fab37eSRobert Watson return (error); 43095fab37eSRobert Watson } 43195fab37eSRobert Watson 43295fab37eSRobert Watson static int 43395fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 43495fab37eSRobert Watson { 43595fab37eSRobert Watson struct mac_policy_conf *tmpc; 43641a17fe3SRobert Watson int error, slot, static_entry; 43795fab37eSRobert Watson 43841a17fe3SRobert Watson error = 0; 43941a17fe3SRobert Watson 44041a17fe3SRobert Watson /* 44117041e67SRobert Watson * We don't technically need exclusive access while !mac_late, but 44217041e67SRobert Watson * hold it for assertion consistency. 44341a17fe3SRobert Watson */ 44441a17fe3SRobert Watson mac_policy_grab_exclusive(); 44541a17fe3SRobert Watson 44641a17fe3SRobert Watson /* 44717041e67SRobert Watson * If the module can potentially be unloaded, or we're loading late, 44817041e67SRobert Watson * we have to stick it in the non-static list and pay an extra 44917041e67SRobert Watson * performance overhead. Otherwise, we can pay a light locking cost 45017041e67SRobert Watson * and stick it in the static list. 45141a17fe3SRobert Watson */ 45241a17fe3SRobert Watson static_entry = (!mac_late && 45341a17fe3SRobert Watson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 45441a17fe3SRobert Watson 45541a17fe3SRobert Watson if (static_entry) { 45641a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 45741a17fe3SRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 45841a17fe3SRobert Watson error = EEXIST; 45941a17fe3SRobert Watson goto out; 46041a17fe3SRobert Watson } 46141a17fe3SRobert Watson } 46241a17fe3SRobert Watson } else { 46395fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 46495fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 46541a17fe3SRobert Watson error = EEXIST; 46641a17fe3SRobert Watson goto out; 46741a17fe3SRobert Watson } 46895fab37eSRobert Watson } 46995fab37eSRobert Watson } 47095fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 471b2aef571SRobert Watson slot = ffs(mac_slot_offsets_free); 47295fab37eSRobert Watson if (slot == 0) { 47341a17fe3SRobert Watson error = ENOMEM; 47441a17fe3SRobert Watson goto out; 47595fab37eSRobert Watson } 47695fab37eSRobert Watson slot--; 477b2aef571SRobert Watson mac_slot_offsets_free &= ~(1 << slot); 47895fab37eSRobert Watson *mpc->mpc_field_off = slot; 47995fab37eSRobert Watson } 48095fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 48141a17fe3SRobert Watson 48241a17fe3SRobert Watson /* 48317041e67SRobert Watson * If we're loading a MAC module after the framework has initialized, 48417041e67SRobert Watson * it has to go into the dynamic list. If we're loading it before 48517041e67SRobert Watson * we've finished initializing, it can go into the static list with 48617041e67SRobert Watson * weaker locker requirements. 48741a17fe3SRobert Watson */ 48841a17fe3SRobert Watson if (static_entry) 48941a17fe3SRobert Watson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 49041a17fe3SRobert Watson else 49195fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 49295fab37eSRobert Watson 49317041e67SRobert Watson /* 49417041e67SRobert Watson * Per-policy initialization. Currently, this takes place under the 49517041e67SRobert Watson * exclusive lock, so policies must not sleep in their init method. 49617041e67SRobert Watson * In the future, we may want to separate "init" from "start", with 49717041e67SRobert Watson * "init" occuring without the lock held. Likewise, on tear-down, 49817041e67SRobert Watson * breaking out "stop" from "destroy". 49917041e67SRobert Watson */ 50095fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 50195fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 502225bff6fSRobert Watson mac_policy_updateflags(); 50395fab37eSRobert Watson 50495fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 50595fab37eSRobert Watson mpc->mpc_name); 50695fab37eSRobert Watson 50741a17fe3SRobert Watson out: 50841a17fe3SRobert Watson mac_policy_release_exclusive(); 50941a17fe3SRobert Watson return (error); 51095fab37eSRobert Watson } 51195fab37eSRobert Watson 51295fab37eSRobert Watson static int 51395fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 51495fab37eSRobert Watson { 51595fab37eSRobert Watson 516ea599aa0SRobert Watson /* 51717041e67SRobert Watson * If we fail the load, we may get a request to unload. Check to see 51817041e67SRobert Watson * if we did the run-time registration, and if not, silently succeed. 519ea599aa0SRobert Watson */ 52041a17fe3SRobert Watson mac_policy_grab_exclusive(); 521ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 52241a17fe3SRobert Watson mac_policy_release_exclusive(); 523ea599aa0SRobert Watson return (0); 524ea599aa0SRobert Watson } 52595fab37eSRobert Watson #if 0 52695fab37eSRobert Watson /* 52795fab37eSRobert Watson * Don't allow unloading modules with private data. 52895fab37eSRobert Watson */ 529ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 530ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 53195fab37eSRobert Watson return (EBUSY); 532ea599aa0SRobert Watson } 53395fab37eSRobert Watson #endif 534ea599aa0SRobert Watson /* 53517041e67SRobert Watson * Only allow the unload to proceed if the module is unloadable by 53617041e67SRobert Watson * its own definition. 537ea599aa0SRobert Watson */ 538ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 53941a17fe3SRobert Watson mac_policy_release_exclusive(); 54095fab37eSRobert Watson return (EBUSY); 541ea599aa0SRobert Watson } 54295fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 54395fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 54495fab37eSRobert Watson 54595fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 5469aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 547225bff6fSRobert Watson mac_policy_updateflags(); 54841a17fe3SRobert Watson 54941a17fe3SRobert Watson mac_policy_release_exclusive(); 550a96acd1aSRobert Watson 55195fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 55295fab37eSRobert Watson mpc->mpc_name); 55395fab37eSRobert Watson 55495fab37eSRobert Watson return (0); 55595fab37eSRobert Watson } 55695fab37eSRobert Watson 55795fab37eSRobert Watson /* 55895fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 55995fab37eSRobert Watson * value with the higher precedence. 56095fab37eSRobert Watson */ 5619e7bf51cSRobert Watson int 5629e7bf51cSRobert Watson mac_error_select(int error1, int error2) 56395fab37eSRobert Watson { 56495fab37eSRobert Watson 56595fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 56695fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 56795fab37eSRobert Watson return (EDEADLK); 56895fab37eSRobert Watson 56995fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 57095fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 57195fab37eSRobert Watson return (EINVAL); 57295fab37eSRobert Watson 57395fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 57495fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 57595fab37eSRobert Watson return (ESRCH); 57695fab37eSRobert Watson 57795fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 57895fab37eSRobert Watson return (ENOENT); 57995fab37eSRobert Watson 58095fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 58195fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 58295fab37eSRobert Watson return (EACCES); 58395fab37eSRobert Watson 58495fab37eSRobert Watson /* Precedence goes to privilege. */ 58595fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 58695fab37eSRobert Watson return (EPERM); 58795fab37eSRobert Watson 58895fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 58995fab37eSRobert Watson if (error1 != 0) 59095fab37eSRobert Watson return (error1); 59195fab37eSRobert Watson return (error2); 59295fab37eSRobert Watson } 59395fab37eSRobert Watson 5946fa0475dSRobert Watson void 59508bcdc58SRobert Watson mac_init_label(struct label *label) 59608bcdc58SRobert Watson { 59708bcdc58SRobert Watson 59808bcdc58SRobert Watson bzero(label, sizeof(*label)); 59908bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 60008bcdc58SRobert Watson } 60108bcdc58SRobert Watson 6026fa0475dSRobert Watson void 60308bcdc58SRobert Watson mac_destroy_label(struct label *label) 60408bcdc58SRobert Watson { 60508bcdc58SRobert Watson 60608bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 60708bcdc58SRobert Watson ("destroying uninitialized label")); 60808bcdc58SRobert Watson 60908bcdc58SRobert Watson bzero(label, sizeof(*label)); 61008bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 61108bcdc58SRobert Watson } 61208bcdc58SRobert Watson 6135e7ce478SRobert Watson int 614f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 615f7b951a8SRobert Watson { 616f7b951a8SRobert Watson 617cc7b13bfSRobert Watson if (mac->m_buflen < 0 || 618cc7b13bfSRobert Watson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 619f7b951a8SRobert Watson return (EINVAL); 620f7b951a8SRobert Watson 621f7b951a8SRobert Watson return (0); 622f7b951a8SRobert Watson } 623f7b951a8SRobert Watson 624f0ab0442SRobert Watson /* 625f0ab0442SRobert Watson * MPSAFE 626f0ab0442SRobert Watson */ 627f7b951a8SRobert Watson int 628f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 629f7b951a8SRobert Watson { 630f7b951a8SRobert Watson char *elements, *buffer; 631f7b951a8SRobert Watson struct mac mac; 632f7b951a8SRobert Watson struct proc *tproc; 633f7b951a8SRobert Watson struct ucred *tcred; 634f7b951a8SRobert Watson int error; 635f7b951a8SRobert Watson 636d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 637f7b951a8SRobert Watson if (error) 638f7b951a8SRobert Watson return (error); 639f7b951a8SRobert Watson 640f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 641f7b951a8SRobert Watson if (error) 642f7b951a8SRobert Watson return (error); 643f7b951a8SRobert Watson 644f7b951a8SRobert Watson tproc = pfind(uap->pid); 645f7b951a8SRobert Watson if (tproc == NULL) 646f7b951a8SRobert Watson return (ESRCH); 647f7b951a8SRobert Watson 648f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 649f7b951a8SRobert Watson error = p_cansee(td, tproc); 650f7b951a8SRobert Watson if (error == 0) 651f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 652f7b951a8SRobert Watson PROC_UNLOCK(tproc); 653f7b951a8SRobert Watson if (error) 654f7b951a8SRobert Watson return (error); 655f7b951a8SRobert Watson 656a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 657f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 658f7b951a8SRobert Watson if (error) { 659f7b951a8SRobert Watson free(elements, M_MACTEMP); 660f7b951a8SRobert Watson crfree(tcred); 661f7b951a8SRobert Watson return (error); 662f7b951a8SRobert Watson } 663f7b951a8SRobert Watson 664a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 665eca8a663SRobert Watson error = mac_externalize_cred_label(tcred->cr_label, elements, 66683b7b0edSRobert Watson buffer, mac.m_buflen); 667f7b951a8SRobert Watson if (error == 0) 668f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 669f7b951a8SRobert Watson 670f7b951a8SRobert Watson free(buffer, M_MACTEMP); 671f7b951a8SRobert Watson free(elements, M_MACTEMP); 672f7b951a8SRobert Watson crfree(tcred); 673f7b951a8SRobert Watson return (error); 674f7b951a8SRobert Watson } 675f7b951a8SRobert Watson 67695fab37eSRobert Watson /* 67795fab37eSRobert Watson * MPSAFE 67895fab37eSRobert Watson */ 67995fab37eSRobert Watson int 68095fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 68195fab37eSRobert Watson { 682f7b951a8SRobert Watson char *elements, *buffer; 683f7b951a8SRobert Watson struct mac mac; 68495fab37eSRobert Watson int error; 68595fab37eSRobert Watson 686f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 687f7b951a8SRobert Watson if (error) 688f7b951a8SRobert Watson return (error); 68995fab37eSRobert Watson 690f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 691f7b951a8SRobert Watson if (error) 692f7b951a8SRobert Watson return (error); 693f7b951a8SRobert Watson 694a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 695f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 696f7b951a8SRobert Watson if (error) { 697f7b951a8SRobert Watson free(elements, M_MACTEMP); 698f7b951a8SRobert Watson return (error); 699f7b951a8SRobert Watson } 700f7b951a8SRobert Watson 701a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 702eca8a663SRobert Watson error = mac_externalize_cred_label(td->td_ucred->cr_label, 70383b7b0edSRobert Watson elements, buffer, mac.m_buflen); 704f7b951a8SRobert Watson if (error == 0) 705f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 706f7b951a8SRobert Watson 707f7b951a8SRobert Watson free(buffer, M_MACTEMP); 708f7b951a8SRobert Watson free(elements, M_MACTEMP); 70995fab37eSRobert Watson return (error); 71095fab37eSRobert Watson } 71195fab37eSRobert Watson 71295fab37eSRobert Watson /* 71395fab37eSRobert Watson * MPSAFE 71495fab37eSRobert Watson */ 71595fab37eSRobert Watson int 71695fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 71795fab37eSRobert Watson { 71895fab37eSRobert Watson struct ucred *newcred, *oldcred; 719eca8a663SRobert Watson struct label *intlabel; 720f7b951a8SRobert Watson struct proc *p; 721f7b951a8SRobert Watson struct mac mac; 722f7b951a8SRobert Watson char *buffer; 72395fab37eSRobert Watson int error; 72495fab37eSRobert Watson 725f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 72695fab37eSRobert Watson if (error) 72795fab37eSRobert Watson return (error); 72895fab37eSRobert Watson 729f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 73095fab37eSRobert Watson if (error) 73195fab37eSRobert Watson return (error); 73295fab37eSRobert Watson 733a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 734f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 735f7b951a8SRobert Watson if (error) { 736f7b951a8SRobert Watson free(buffer, M_MACTEMP); 737f7b951a8SRobert Watson return (error); 738f7b951a8SRobert Watson } 739f7b951a8SRobert Watson 740eca8a663SRobert Watson intlabel = mac_cred_label_alloc(); 741eca8a663SRobert Watson error = mac_internalize_cred_label(intlabel, buffer); 742f7b951a8SRobert Watson free(buffer, M_MACTEMP); 743eca8a663SRobert Watson if (error) 744eca8a663SRobert Watson goto out; 745f7b951a8SRobert Watson 74695fab37eSRobert Watson newcred = crget(); 74795fab37eSRobert Watson 74895fab37eSRobert Watson p = td->td_proc; 74995fab37eSRobert Watson PROC_LOCK(p); 75095fab37eSRobert Watson oldcred = p->p_ucred; 75195fab37eSRobert Watson 752eca8a663SRobert Watson error = mac_check_cred_relabel(oldcred, intlabel); 75395fab37eSRobert Watson if (error) { 75495fab37eSRobert Watson PROC_UNLOCK(p); 75595fab37eSRobert Watson crfree(newcred); 756f7b951a8SRobert Watson goto out; 75795fab37eSRobert Watson } 75895fab37eSRobert Watson 75995fab37eSRobert Watson setsugid(p); 76095fab37eSRobert Watson crcopy(newcred, oldcred); 761eca8a663SRobert Watson mac_relabel_cred(newcred, intlabel); 76295fab37eSRobert Watson p->p_ucred = newcred; 763e5cb5e37SRobert Watson 764e5cb5e37SRobert Watson /* 76517041e67SRobert Watson * Grab additional reference for use while revoking mmaps, prior to 76617041e67SRobert Watson * releasing the proc lock and sharing the cred. 767e5cb5e37SRobert Watson */ 768e5cb5e37SRobert Watson crhold(newcred); 76995fab37eSRobert Watson PROC_UNLOCK(p); 770e5cb5e37SRobert Watson 771e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 772e5cb5e37SRobert Watson 773e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 77495fab37eSRobert Watson crfree(oldcred); 775f7b951a8SRobert Watson 776f7b951a8SRobert Watson out: 777eca8a663SRobert Watson mac_cred_label_free(intlabel); 778f7b951a8SRobert Watson return (error); 77995fab37eSRobert Watson } 78095fab37eSRobert Watson 78195fab37eSRobert Watson /* 78295fab37eSRobert Watson * MPSAFE 78395fab37eSRobert Watson */ 78495fab37eSRobert Watson int 78595fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 78695fab37eSRobert Watson { 787f7b951a8SRobert Watson char *elements, *buffer; 788eca8a663SRobert Watson struct label *intlabel; 78995fab37eSRobert Watson struct file *fp; 790f7b951a8SRobert Watson struct mac mac; 79195fab37eSRobert Watson struct vnode *vp; 79295fab37eSRobert Watson struct pipe *pipe; 793b0323ea3SRobert Watson struct socket *so; 794f7b951a8SRobert Watson short label_type; 7959eea3d85SChristian S.J. Peron int vfslocked, error; 79695fab37eSRobert Watson 797f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 798f7b951a8SRobert Watson if (error) 799f7b951a8SRobert Watson return (error); 80095fab37eSRobert Watson 801f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 802f7b951a8SRobert Watson if (error) 803f7b951a8SRobert Watson return (error); 804f7b951a8SRobert Watson 805a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 806f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 807f7b951a8SRobert Watson if (error) { 808f7b951a8SRobert Watson free(elements, M_MACTEMP); 809f7b951a8SRobert Watson return (error); 810f7b951a8SRobert Watson } 811f7b951a8SRobert Watson 812a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 813d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 81495fab37eSRobert Watson if (error) 81595fab37eSRobert Watson goto out; 81695fab37eSRobert Watson 817f7b951a8SRobert Watson label_type = fp->f_type; 81895fab37eSRobert Watson switch (fp->f_type) { 81995fab37eSRobert Watson case DTYPE_FIFO: 82095fab37eSRobert Watson case DTYPE_VNODE: 8213b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 822eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 8239eea3d85SChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(vp->v_mount); 82495fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 825eca8a663SRobert Watson mac_copy_vnode_label(vp->v_label, intlabel); 82695fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 8279eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 828f0ab0442SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, 829f0ab0442SRobert Watson buffer, mac.m_buflen); 830f0ab0442SRobert Watson mac_vnode_label_free(intlabel); 83195fab37eSRobert Watson break; 832f0ab0442SRobert Watson 83395fab37eSRobert Watson case DTYPE_PIPE: 83448e3128bSMatthew Dillon pipe = fp->f_data; 835eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 836f7b951a8SRobert Watson PIPE_LOCK(pipe); 8374795b82cSRobert Watson mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 838f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 839eca8a663SRobert Watson error = mac_externalize_pipe_label(intlabel, elements, 84083b7b0edSRobert Watson buffer, mac.m_buflen); 841eca8a663SRobert Watson mac_pipe_label_free(intlabel); 842f7b951a8SRobert Watson break; 84395fab37eSRobert Watson 844b0323ea3SRobert Watson case DTYPE_SOCKET: 845b0323ea3SRobert Watson so = fp->f_data; 846b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 847f0c2044bSRobert Watson NET_LOCK_GIANT(); 848f0c2044bSRobert Watson SOCK_LOCK(so); 849b0323ea3SRobert Watson mac_copy_socket_label(so->so_label, intlabel); 850f0c2044bSRobert Watson SOCK_UNLOCK(so); 851f0c2044bSRobert Watson NET_UNLOCK_GIANT(); 852b0323ea3SRobert Watson error = mac_externalize_socket_label(intlabel, elements, 853b0323ea3SRobert Watson buffer, mac.m_buflen); 854b0323ea3SRobert Watson mac_socket_label_free(intlabel); 855b0323ea3SRobert Watson break; 856b0323ea3SRobert Watson 857f0ab0442SRobert Watson default: 858f0ab0442SRobert Watson error = EINVAL; 859f0ab0442SRobert Watson } 860f0ab0442SRobert Watson fdrop(fp, td); 86195fab37eSRobert Watson if (error == 0) 862f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 86395fab37eSRobert Watson 86495fab37eSRobert Watson out: 865f7b951a8SRobert Watson free(buffer, M_MACTEMP); 866f7b951a8SRobert Watson free(elements, M_MACTEMP); 86795fab37eSRobert Watson return (error); 86895fab37eSRobert Watson } 86995fab37eSRobert Watson 87095fab37eSRobert Watson /* 87195fab37eSRobert Watson * MPSAFE 87295fab37eSRobert Watson */ 87395fab37eSRobert Watson int 87495fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 87595fab37eSRobert Watson { 876f7b951a8SRobert Watson char *elements, *buffer; 87795fab37eSRobert Watson struct nameidata nd; 878eca8a663SRobert Watson struct label *intlabel; 879f7b951a8SRobert Watson struct mac mac; 8809eea3d85SChristian S.J. Peron int vfslocked, error; 88195fab37eSRobert Watson 882f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 883f7b951a8SRobert Watson if (error) 884f7b951a8SRobert Watson return (error); 885f7b951a8SRobert Watson 886f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 887f7b951a8SRobert Watson if (error) 888f7b951a8SRobert Watson return (error); 889f7b951a8SRobert Watson 890a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 891f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 892f7b951a8SRobert Watson if (error) { 893f7b951a8SRobert Watson free(elements, M_MACTEMP); 894f7b951a8SRobert Watson return (error); 895f7b951a8SRobert Watson } 896f7b951a8SRobert Watson 897a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 8989eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 8999eea3d85SChristian S.J. Peron uap->path_p, td); 90095fab37eSRobert Watson error = namei(&nd); 90195fab37eSRobert Watson if (error) 90295fab37eSRobert Watson goto out; 90395fab37eSRobert Watson 904eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 9059eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 906eca8a663SRobert Watson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 907eca8a663SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, buffer, 90883b7b0edSRobert Watson mac.m_buflen); 909f7b951a8SRobert Watson 91095fab37eSRobert Watson NDFREE(&nd, 0); 9119eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 912eca8a663SRobert Watson mac_vnode_label_free(intlabel); 913f7b951a8SRobert Watson if (error == 0) 914f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 915f7b951a8SRobert Watson 916f7b951a8SRobert Watson out: 917f7b951a8SRobert Watson free(buffer, M_MACTEMP); 918f7b951a8SRobert Watson free(elements, M_MACTEMP); 919f7b951a8SRobert Watson 920f7b951a8SRobert Watson return (error); 921f7b951a8SRobert Watson } 922f7b951a8SRobert Watson 923f7b951a8SRobert Watson /* 924f7b951a8SRobert Watson * MPSAFE 925f7b951a8SRobert Watson */ 926f7b951a8SRobert Watson int 927f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 928f7b951a8SRobert Watson { 929f7b951a8SRobert Watson char *elements, *buffer; 930f7b951a8SRobert Watson struct nameidata nd; 931eca8a663SRobert Watson struct label *intlabel; 932f7b951a8SRobert Watson struct mac mac; 9339eea3d85SChristian S.J. Peron int vfslocked, error; 934f7b951a8SRobert Watson 935f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 936f7b951a8SRobert Watson if (error) 937f7b951a8SRobert Watson return (error); 938f7b951a8SRobert Watson 939f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 940f7b951a8SRobert Watson if (error) 941f7b951a8SRobert Watson return (error); 942f7b951a8SRobert Watson 943a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 944f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 945f7b951a8SRobert Watson if (error) { 946f7b951a8SRobert Watson free(elements, M_MACTEMP); 947f7b951a8SRobert Watson return (error); 948f7b951a8SRobert Watson } 949f7b951a8SRobert Watson 950a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 9519eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 9529eea3d85SChristian S.J. Peron uap->path_p, td); 953f7b951a8SRobert Watson error = namei(&nd); 95495fab37eSRobert Watson if (error) 95595fab37eSRobert Watson goto out; 95695fab37eSRobert Watson 957eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 9589eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 959eca8a663SRobert Watson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 960eca8a663SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, buffer, 96183b7b0edSRobert Watson mac.m_buflen); 962f7b951a8SRobert Watson NDFREE(&nd, 0); 9639eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 964eca8a663SRobert Watson mac_vnode_label_free(intlabel); 965f7b951a8SRobert Watson 966f7b951a8SRobert Watson if (error == 0) 967f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 96895fab37eSRobert Watson 96995fab37eSRobert Watson out: 970f7b951a8SRobert Watson free(buffer, M_MACTEMP); 971f7b951a8SRobert Watson free(elements, M_MACTEMP); 972f7b951a8SRobert Watson 97395fab37eSRobert Watson return (error); 97495fab37eSRobert Watson } 97595fab37eSRobert Watson 97695fab37eSRobert Watson /* 97795fab37eSRobert Watson * MPSAFE 97895fab37eSRobert Watson */ 97995fab37eSRobert Watson int 98095fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 98195fab37eSRobert Watson { 982eca8a663SRobert Watson struct label *intlabel; 983f7b951a8SRobert Watson struct pipe *pipe; 984b0323ea3SRobert Watson struct socket *so; 985f7b951a8SRobert Watson struct file *fp; 98695fab37eSRobert Watson struct mount *mp; 98795fab37eSRobert Watson struct vnode *vp; 988f7b951a8SRobert Watson struct mac mac; 989f7b951a8SRobert Watson char *buffer; 9909eea3d85SChristian S.J. Peron int error, vfslocked; 99195fab37eSRobert Watson 992f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 993f7b951a8SRobert Watson if (error) 994f7b951a8SRobert Watson return (error); 995f7b951a8SRobert Watson 996f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 997f7b951a8SRobert Watson if (error) 998f7b951a8SRobert Watson return (error); 999f7b951a8SRobert Watson 1000a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1001f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1002f7b951a8SRobert Watson if (error) { 1003f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1004f7b951a8SRobert Watson return (error); 1005f7b951a8SRobert Watson } 1006f7b951a8SRobert Watson 1007d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 100895fab37eSRobert Watson if (error) 1009f7b951a8SRobert Watson goto out; 101095fab37eSRobert Watson 101195fab37eSRobert Watson switch (fp->f_type) { 101295fab37eSRobert Watson case DTYPE_FIFO: 101395fab37eSRobert Watson case DTYPE_VNODE: 1014eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 1015eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 1016f7b951a8SRobert Watson if (error) { 1017eca8a663SRobert Watson mac_vnode_label_free(intlabel); 1018f7b951a8SRobert Watson break; 1019f7b951a8SRobert Watson } 10203b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 10219eea3d85SChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(vp->v_mount); 102295fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 1023f7b951a8SRobert Watson if (error != 0) { 10249eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 1025eca8a663SRobert Watson mac_vnode_label_free(intlabel); 102695fab37eSRobert Watson break; 1027f7b951a8SRobert Watson } 102895fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1029eca8a663SRobert Watson error = vn_setlabel(vp, intlabel, td->td_ucred); 103095fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 103195fab37eSRobert Watson vn_finished_write(mp); 10329eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 1033eca8a663SRobert Watson mac_vnode_label_free(intlabel); 103495fab37eSRobert Watson break; 1035f7b951a8SRobert Watson 103695fab37eSRobert Watson case DTYPE_PIPE: 1037eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 1038eca8a663SRobert Watson error = mac_internalize_pipe_label(intlabel, buffer); 1039f7b951a8SRobert Watson if (error == 0) { 104048e3128bSMatthew Dillon pipe = fp->f_data; 10411aa37f53SRobert Watson PIPE_LOCK(pipe); 10424795b82cSRobert Watson error = mac_pipe_label_set(td->td_ucred, 10434795b82cSRobert Watson pipe->pipe_pair, intlabel); 10441aa37f53SRobert Watson PIPE_UNLOCK(pipe); 1045f7b951a8SRobert Watson } 1046eca8a663SRobert Watson mac_pipe_label_free(intlabel); 104795fab37eSRobert Watson break; 1048f7b951a8SRobert Watson 1049b0323ea3SRobert Watson case DTYPE_SOCKET: 1050b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 1051b0323ea3SRobert Watson error = mac_internalize_socket_label(intlabel, buffer); 1052b0323ea3SRobert Watson if (error == 0) { 1053b0323ea3SRobert Watson so = fp->f_data; 1054f0c2044bSRobert Watson NET_LOCK_GIANT(); 1055b0323ea3SRobert Watson error = mac_socket_label_set(td->td_ucred, so, 1056b0323ea3SRobert Watson intlabel); 1057f0c2044bSRobert Watson NET_UNLOCK_GIANT(); 1058b0323ea3SRobert Watson } 1059b0323ea3SRobert Watson mac_socket_label_free(intlabel); 1060b0323ea3SRobert Watson break; 1061b0323ea3SRobert Watson 106295fab37eSRobert Watson default: 106395fab37eSRobert Watson error = EINVAL; 106495fab37eSRobert Watson } 106595fab37eSRobert Watson fdrop(fp, td); 1066f7b951a8SRobert Watson out: 1067f7b951a8SRobert Watson free(buffer, M_MACTEMP); 106895fab37eSRobert Watson return (error); 106995fab37eSRobert Watson } 107095fab37eSRobert Watson 107195fab37eSRobert Watson /* 107295fab37eSRobert Watson * MPSAFE 107395fab37eSRobert Watson */ 107495fab37eSRobert Watson int 107595fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 107695fab37eSRobert Watson { 1077eca8a663SRobert Watson struct label *intlabel; 1078f7b951a8SRobert Watson struct nameidata nd; 107995fab37eSRobert Watson struct mount *mp; 1080f7b951a8SRobert Watson struct mac mac; 1081f7b951a8SRobert Watson char *buffer; 10829eea3d85SChristian S.J. Peron int vfslocked, error; 108395fab37eSRobert Watson 1084f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 108595fab37eSRobert Watson if (error) 1086f7b951a8SRobert Watson return (error); 108795fab37eSRobert Watson 1088f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 108995fab37eSRobert Watson if (error) 1090f7b951a8SRobert Watson return (error); 109195fab37eSRobert Watson 1092a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1093f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1094f7b951a8SRobert Watson if (error) { 1095f7b951a8SRobert Watson free(buffer, M_MACTEMP); 109695fab37eSRobert Watson return (error); 109795fab37eSRobert Watson } 109895fab37eSRobert Watson 1099eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 1100eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 1101f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1102eca8a663SRobert Watson if (error) 1103eca8a663SRobert Watson goto out; 1104f7b951a8SRobert Watson 11059eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 11069eea3d85SChristian S.J. Peron uap->path_p, td); 1107f7b951a8SRobert Watson error = namei(&nd); 11089eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 1109f7b951a8SRobert Watson if (error == 0) { 1110f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1111d50ef66dSTor Egge if (error == 0) { 1112eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 1113f7b951a8SRobert Watson td->td_ucred); 1114f7b951a8SRobert Watson vn_finished_write(mp); 1115f7b951a8SRobert Watson } 1116d50ef66dSTor Egge } 1117f7b951a8SRobert Watson 1118f7b951a8SRobert Watson NDFREE(&nd, 0); 11199eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 1120eca8a663SRobert Watson out: 1121eca8a663SRobert Watson mac_vnode_label_free(intlabel); 1122f7b951a8SRobert Watson return (error); 1123f7b951a8SRobert Watson } 1124f7b951a8SRobert Watson 1125f7b951a8SRobert Watson /* 1126f7b951a8SRobert Watson * MPSAFE 1127f7b951a8SRobert Watson */ 1128f7b951a8SRobert Watson int 1129f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1130f7b951a8SRobert Watson { 1131eca8a663SRobert Watson struct label *intlabel; 1132f7b951a8SRobert Watson struct nameidata nd; 1133f7b951a8SRobert Watson struct mount *mp; 1134f7b951a8SRobert Watson struct mac mac; 1135f7b951a8SRobert Watson char *buffer; 11369eea3d85SChristian S.J. Peron int vfslocked, error; 1137f7b951a8SRobert Watson 1138f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1139f7b951a8SRobert Watson if (error) 1140f7b951a8SRobert Watson return (error); 1141f7b951a8SRobert Watson 1142f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 1143f7b951a8SRobert Watson if (error) 1144f7b951a8SRobert Watson return (error); 1145f7b951a8SRobert Watson 1146a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1147f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1148f7b951a8SRobert Watson if (error) { 1149f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1150f7b951a8SRobert Watson return (error); 1151f7b951a8SRobert Watson } 1152f7b951a8SRobert Watson 1153eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 1154eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 1155f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1156eca8a663SRobert Watson if (error) 1157eca8a663SRobert Watson goto out; 1158f7b951a8SRobert Watson 11599eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 11609eea3d85SChristian S.J. Peron uap->path_p, td); 1161f7b951a8SRobert Watson error = namei(&nd); 11629eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 1163f7b951a8SRobert Watson if (error == 0) { 1164f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1165d50ef66dSTor Egge if (error == 0) { 1166eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 1167f7b951a8SRobert Watson td->td_ucred); 1168f7b951a8SRobert Watson vn_finished_write(mp); 1169f7b951a8SRobert Watson } 1170d50ef66dSTor Egge } 1171f7b951a8SRobert Watson 1172f7b951a8SRobert Watson NDFREE(&nd, 0); 11739eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 1174eca8a663SRobert Watson out: 1175eca8a663SRobert Watson mac_vnode_label_free(intlabel); 1176f7b951a8SRobert Watson return (error); 1177f7b951a8SRobert Watson } 1178f7b951a8SRobert Watson 1179f7b951a8SRobert Watson /* 1180f7b951a8SRobert Watson * MPSAFE 1181f7b951a8SRobert Watson */ 118227f2eac7SRobert Watson int 118327f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 118427f2eac7SRobert Watson { 118527f2eac7SRobert Watson struct mac_policy_conf *mpc; 118627f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 118741a17fe3SRobert Watson int entrycount, error; 118827f2eac7SRobert Watson 1189d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 119027f2eac7SRobert Watson if (error) 119127f2eac7SRobert Watson return (error); 119227f2eac7SRobert Watson 119327f2eac7SRobert Watson error = ENOSYS; 1194a6a65b05SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 119527f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 119627f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 119727f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 1198d1e405c5SAlfred Perlstein uap->call, uap->arg); 119927f2eac7SRobert Watson goto out; 120027f2eac7SRobert Watson } 120127f2eac7SRobert Watson } 120227f2eac7SRobert Watson 120341a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 120441a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 120541a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 120641a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 120741a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 120841a17fe3SRobert Watson uap->call, uap->arg); 120941a17fe3SRobert Watson break; 121041a17fe3SRobert Watson } 121141a17fe3SRobert Watson } 121241a17fe3SRobert Watson mac_policy_list_unbusy(); 121341a17fe3SRobert Watson } 121427f2eac7SRobert Watson out: 121527f2eac7SRobert Watson return (error); 121627f2eac7SRobert Watson } 121727f2eac7SRobert Watson 121895fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 121995fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 122095fab37eSRobert Watson 122195fab37eSRobert Watson #else /* !MAC */ 12227bc82500SRobert Watson 12237bc82500SRobert Watson int 1224f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1225f7b951a8SRobert Watson { 1226f7b951a8SRobert Watson 1227f7b951a8SRobert Watson return (ENOSYS); 1228f7b951a8SRobert Watson } 1229f7b951a8SRobert Watson 1230f7b951a8SRobert Watson int 12317bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 12327bc82500SRobert Watson { 12337bc82500SRobert Watson 12347bc82500SRobert Watson return (ENOSYS); 12357bc82500SRobert Watson } 12367bc82500SRobert Watson 12377bc82500SRobert Watson int 12387bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 12397bc82500SRobert Watson { 12407bc82500SRobert Watson 12417bc82500SRobert Watson return (ENOSYS); 12427bc82500SRobert Watson } 12437bc82500SRobert Watson 12447bc82500SRobert Watson int 12457bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 12467bc82500SRobert Watson { 12477bc82500SRobert Watson 12487bc82500SRobert Watson return (ENOSYS); 12497bc82500SRobert Watson } 12507bc82500SRobert Watson 12517bc82500SRobert Watson int 12527bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 12537bc82500SRobert Watson { 12547bc82500SRobert Watson 12557bc82500SRobert Watson return (ENOSYS); 12567bc82500SRobert Watson } 12577bc82500SRobert Watson 12587bc82500SRobert Watson int 1259f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1260f7b951a8SRobert Watson { 1261f7b951a8SRobert Watson 1262f7b951a8SRobert Watson return (ENOSYS); 1263f7b951a8SRobert Watson } 1264f7b951a8SRobert Watson 1265f7b951a8SRobert Watson int 12667bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 12677bc82500SRobert Watson { 12687bc82500SRobert Watson 12697bc82500SRobert Watson return (ENOSYS); 12707bc82500SRobert Watson } 12717bc82500SRobert Watson 12727bc82500SRobert Watson int 12737bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 12747bc82500SRobert Watson { 12757bc82500SRobert Watson 12767bc82500SRobert Watson return (ENOSYS); 12777bc82500SRobert Watson } 127895fab37eSRobert Watson 127927f2eac7SRobert Watson int 1280f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1281f7b951a8SRobert Watson { 1282f7b951a8SRobert Watson 1283f7b951a8SRobert Watson return (ENOSYS); 1284f7b951a8SRobert Watson } 1285f7b951a8SRobert Watson 1286f7b951a8SRobert Watson int 128727f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 128827f2eac7SRobert Watson { 128927f2eac7SRobert Watson 129027f2eac7SRobert Watson return (ENOSYS); 129127f2eac7SRobert Watson } 129227f2eac7SRobert Watson 129319b78822SRobert Watson #endif /* !MAC */ 1294