17bc82500SRobert Watson /*- 2f6a41092SRobert Watson * Copyright (c) 1999-2002 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 /*- 42c8e7bf92SRobert Watson * Framework for extensible kernel access control. This file contains 43c8e7bf92SRobert Watson * Kernel and userland interface to the framework, policy registration 44c8e7bf92SRobert Watson * and composition. Per-object interfaces, controls, and labeling may be 4549869305STom Rhodes * found in src/sys/security/mac/. Sample policies may be found in 4649869305STom Rhodes * src/sys/security/mac_*. 477bc82500SRobert Watson */ 487bc82500SRobert Watson 49677b542eSDavid E. O'Brien #include <sys/cdefs.h> 50677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 51677b542eSDavid E. O'Brien 527bc82500SRobert Watson #include "opt_mac.h" 53f9d0d524SRobert Watson 547bc82500SRobert Watson #include <sys/param.h> 55a96acd1aSRobert Watson #include <sys/condvar.h> 5695fab37eSRobert Watson #include <sys/extattr.h> 57670cb89bSRobert Watson #include <sys/imgact.h> 5895fab37eSRobert Watson #include <sys/kernel.h> 5995fab37eSRobert Watson #include <sys/lock.h> 60b656366bSBruce Evans #include <sys/malloc.h> 6195fab37eSRobert Watson #include <sys/mutex.h> 6295fab37eSRobert Watson #include <sys/mac.h> 637ba28492SRobert Watson #include <sys/module.h> 6495fab37eSRobert Watson #include <sys/proc.h> 65f51e5803SRobert Watson #include <sys/sbuf.h> 6695fab37eSRobert Watson #include <sys/systm.h> 677bc82500SRobert Watson #include <sys/sysproto.h> 687bc82500SRobert Watson #include <sys/sysent.h> 6995fab37eSRobert Watson #include <sys/vnode.h> 7095fab37eSRobert Watson #include <sys/mount.h> 7195fab37eSRobert Watson #include <sys/file.h> 7295fab37eSRobert Watson #include <sys/namei.h> 7395fab37eSRobert Watson #include <sys/socket.h> 7495fab37eSRobert Watson #include <sys/pipe.h> 7595fab37eSRobert Watson #include <sys/socketvar.h> 7695fab37eSRobert Watson #include <sys/sysctl.h> 7795fab37eSRobert Watson 7895fab37eSRobert Watson #include <vm/vm.h> 7995fab37eSRobert Watson #include <vm/pmap.h> 8095fab37eSRobert Watson #include <vm/vm_map.h> 8195fab37eSRobert Watson #include <vm/vm_object.h> 8295fab37eSRobert Watson 8395fab37eSRobert Watson #include <sys/mac_policy.h> 8495fab37eSRobert Watson 8595fab37eSRobert Watson #include <fs/devfs/devfs.h> 8695fab37eSRobert Watson 8795fab37eSRobert Watson #include <net/bpfdesc.h> 8895fab37eSRobert Watson #include <net/if.h> 8995fab37eSRobert Watson #include <net/if_var.h> 9095fab37eSRobert Watson 9195fab37eSRobert Watson #include <netinet/in.h> 9295fab37eSRobert Watson #include <netinet/ip_var.h> 9395fab37eSRobert Watson 94aed55708SRobert Watson #include <security/mac/mac_framework.h> 956fa0475dSRobert Watson #include <security/mac/mac_internal.h> 966fa0475dSRobert Watson 9795fab37eSRobert Watson #ifdef MAC 9895fab37eSRobert Watson 997ba28492SRobert Watson /* 1007ba28492SRobert Watson * Declare that the kernel provides MAC support, version 1. This permits 1017ba28492SRobert Watson * modules to refuse to be loaded if the necessary support isn't present, 1027ba28492SRobert Watson * even if it's pre-boot. 1037ba28492SRobert Watson */ 10449bb6870SRobert Watson MODULE_VERSION(kernel_mac_support, 3); 1057ba28492SRobert Watson 10695fab37eSRobert Watson SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 10795fab37eSRobert Watson "TrustedBSD MAC policy controls"); 108b2f0927aSRobert Watson 109b2aef571SRobert Watson #if MAC_MAX_SLOTS > 32 110b2aef571SRobert Watson #error "MAC_MAX_SLOTS too large" 11195fab37eSRobert Watson #endif 112a13c67daSRobert Watson 113b2aef571SRobert Watson static unsigned int mac_max_slots = MAC_MAX_SLOTS; 114b2aef571SRobert Watson static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 115b2aef571SRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 116b2aef571SRobert Watson &mac_max_slots, 0, ""); 11795fab37eSRobert Watson 118a67fe518SRobert Watson /* 119a67fe518SRobert Watson * Has the kernel started generating labeled objects yet? All read/write 120a67fe518SRobert Watson * access to this variable is serialized during the boot process. Following 121a67fe518SRobert Watson * the end of serialization, we don't update this flag; no locking. 122a67fe518SRobert Watson */ 123089c1bdaSRobert Watson int mac_late = 0; 124763bbd2fSRobert Watson 125225bff6fSRobert Watson /* 126225bff6fSRobert Watson * Flag to indicate whether or not we should allocate label storage for 127225bff6fSRobert Watson * new mbufs. Since most dynamic policies we currently work with don't 128225bff6fSRobert Watson * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 129225bff6fSRobert Watson * unless specifically notified of interest. One result of this is 130225bff6fSRobert Watson * that if a dynamically loaded policy requests mbuf labels, it must 131225bff6fSRobert Watson * be able to deal with a NULL label being returned on any mbufs that 132225bff6fSRobert Watson * were already in flight when the policy was loaded. Since the policy 133225bff6fSRobert Watson * already has to deal with uninitialized labels, this probably won't 134225bff6fSRobert Watson * be a problem. Note: currently no locking. Will this be a problem? 135225bff6fSRobert Watson */ 13619c3e120SRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 137089c1bdaSRobert Watson int mac_labelmbufs = 0; 138225bff6fSRobert Watson #endif 139225bff6fSRobert Watson 14095fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 14195fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 14295fab37eSRobert Watson 143f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 14495fab37eSRobert Watson 14595fab37eSRobert Watson /* 14641a17fe3SRobert Watson * mac_static_policy_list holds a list of policy modules that are not 14741a17fe3SRobert Watson * loaded while the system is "live", and cannot be unloaded. These 14841a17fe3SRobert Watson * policies can be invoked without holding the busy count. 14941a17fe3SRobert Watson * 15041a17fe3SRobert Watson * mac_policy_list stores the list of dynamic policies. A busy count is 151a96acd1aSRobert Watson * maintained for the list, stored in mac_policy_busy. The busy count 15241a17fe3SRobert Watson * is protected by mac_policy_mtx; the list may be modified only 153a96acd1aSRobert Watson * while the busy count is 0, requiring that the lock be held to 154a96acd1aSRobert Watson * prevent new references to the list from being acquired. For almost 155a96acd1aSRobert Watson * all operations, incrementing the busy count is sufficient to 156a96acd1aSRobert Watson * guarantee consistency, as the list cannot be modified while the 157a96acd1aSRobert Watson * busy count is elevated. For a few special operations involving a 15841a17fe3SRobert Watson * change to the list of active policies, the mtx itself must be held. 15941a17fe3SRobert Watson * A condition variable, mac_policy_cv, is used to signal potential 16041a17fe3SRobert Watson * exclusive consumers that they should try to acquire the lock if a 16141a17fe3SRobert Watson * first attempt at exclusive access fails. 16295fab37eSRobert Watson */ 1630a05006dSRobert Watson #ifndef MAC_STATIC 16441a17fe3SRobert Watson static struct mtx mac_policy_mtx; 16541a17fe3SRobert Watson static struct cv mac_policy_cv; 16641a17fe3SRobert Watson static int mac_policy_count; 1670a05006dSRobert Watson #endif 168089c1bdaSRobert Watson struct mac_policy_list_head mac_policy_list; 169089c1bdaSRobert Watson struct mac_policy_list_head mac_static_policy_list; 170a96acd1aSRobert Watson 171a96acd1aSRobert Watson /* 17226306795SJohn Baldwin * We manually invoke WITNESS_WARN() to allow Witness to generate 173a96acd1aSRobert Watson * warnings even if we don't end up ever triggering the wait at 174a96acd1aSRobert Watson * run-time. The consumer of the exclusive interface must not hold 175a96acd1aSRobert Watson * any locks (other than potentially Giant) since we may sleep for 176a96acd1aSRobert Watson * long (potentially indefinite) periods of time waiting for the 177a96acd1aSRobert Watson * framework to become quiescent so that a policy list change may 178a96acd1aSRobert Watson * be made. 179a96acd1aSRobert Watson */ 180089c1bdaSRobert Watson void 18141a17fe3SRobert Watson mac_policy_grab_exclusive(void) 18241a17fe3SRobert Watson { 183c8e7bf92SRobert Watson 1840a05006dSRobert Watson #ifndef MAC_STATIC 1851e4cadcbSRobert Watson if (!mac_late) 1861e4cadcbSRobert Watson return; 1871e4cadcbSRobert Watson 18841a17fe3SRobert Watson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 18941a17fe3SRobert Watson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 19041a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 19141a17fe3SRobert Watson while (mac_policy_count != 0) 19241a17fe3SRobert Watson cv_wait(&mac_policy_cv, &mac_policy_mtx); 1930a05006dSRobert Watson #endif 19441a17fe3SRobert Watson } 19595fab37eSRobert Watson 196089c1bdaSRobert Watson void 19741a17fe3SRobert Watson mac_policy_assert_exclusive(void) 19841a17fe3SRobert Watson { 199c8e7bf92SRobert Watson 2000a05006dSRobert Watson #ifndef MAC_STATIC 2011e4cadcbSRobert Watson if (!mac_late) 2021e4cadcbSRobert Watson return; 2031e4cadcbSRobert Watson 20441a17fe3SRobert Watson mtx_assert(&mac_policy_mtx, MA_OWNED); 20541a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 20641a17fe3SRobert Watson ("mac_policy_assert_exclusive(): not exclusive")); 2070a05006dSRobert Watson #endif 20841a17fe3SRobert Watson } 209225bff6fSRobert Watson 210089c1bdaSRobert Watson void 21141a17fe3SRobert Watson mac_policy_release_exclusive(void) 21241a17fe3SRobert Watson { 21395fab37eSRobert Watson 2140a05006dSRobert Watson #ifndef MAC_STATIC 2151e4cadcbSRobert Watson if (!mac_late) 2161e4cadcbSRobert Watson return; 2171e4cadcbSRobert Watson 21841a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 21941a17fe3SRobert Watson ("mac_policy_release_exclusive(): not exclusive")); 22041a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 22141a17fe3SRobert Watson cv_signal(&mac_policy_cv); 2220a05006dSRobert Watson #endif 22341a17fe3SRobert Watson } 22441a17fe3SRobert Watson 225089c1bdaSRobert Watson void 22641a17fe3SRobert Watson mac_policy_list_busy(void) 22741a17fe3SRobert Watson { 228c8e7bf92SRobert Watson 2290a05006dSRobert Watson #ifndef MAC_STATIC 2301e4cadcbSRobert Watson if (!mac_late) 2311e4cadcbSRobert Watson return; 2321e4cadcbSRobert Watson 23341a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 23441a17fe3SRobert Watson mac_policy_count++; 23541a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 2360a05006dSRobert Watson #endif 23741a17fe3SRobert Watson } 23841a17fe3SRobert Watson 239089c1bdaSRobert Watson int 24041a17fe3SRobert Watson mac_policy_list_conditional_busy(void) 24141a17fe3SRobert Watson { 2420a05006dSRobert Watson #ifndef MAC_STATIC 24341a17fe3SRobert Watson int ret; 24441a17fe3SRobert Watson 2451e4cadcbSRobert Watson if (!mac_late) 2461e4cadcbSRobert Watson return (1); 2471e4cadcbSRobert Watson 24841a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 24941a17fe3SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { 25041a17fe3SRobert Watson mac_policy_count++; 25141a17fe3SRobert Watson ret = 1; 25241a17fe3SRobert Watson } else 25341a17fe3SRobert Watson ret = 0; 25441a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 25541a17fe3SRobert Watson return (ret); 2560a05006dSRobert Watson #else 2571e4cadcbSRobert Watson if (!mac_late) 2581e4cadcbSRobert Watson return (1); 2591e4cadcbSRobert Watson 2600a05006dSRobert Watson return (1); 2610a05006dSRobert Watson #endif 26241a17fe3SRobert Watson } 26341a17fe3SRobert Watson 264089c1bdaSRobert Watson void 26541a17fe3SRobert Watson mac_policy_list_unbusy(void) 26641a17fe3SRobert Watson { 267c8e7bf92SRobert Watson 2680a05006dSRobert Watson #ifndef MAC_STATIC 2691e4cadcbSRobert Watson if (!mac_late) 2701e4cadcbSRobert Watson return; 2711e4cadcbSRobert Watson 27241a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 27341a17fe3SRobert Watson mac_policy_count--; 27441a17fe3SRobert Watson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 27541a17fe3SRobert Watson if (mac_policy_count == 0) 27641a17fe3SRobert Watson cv_signal(&mac_policy_cv); 27741a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 2780a05006dSRobert Watson #endif 27941a17fe3SRobert Watson } 28095fab37eSRobert Watson 28195fab37eSRobert Watson /* 28295fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 28395fab37eSRobert Watson */ 28495fab37eSRobert Watson static void 28595fab37eSRobert Watson mac_init(void) 28695fab37eSRobert Watson { 28795fab37eSRobert Watson 28841a17fe3SRobert Watson LIST_INIT(&mac_static_policy_list); 28995fab37eSRobert Watson LIST_INIT(&mac_policy_list); 290eca8a663SRobert Watson mac_labelzone_init(); 29141a17fe3SRobert Watson 2920a05006dSRobert Watson #ifndef MAC_STATIC 29341a17fe3SRobert Watson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 29441a17fe3SRobert Watson cv_init(&mac_policy_cv, "mac_policy_cv"); 2950a05006dSRobert Watson #endif 29695fab37eSRobert Watson } 29795fab37eSRobert Watson 29895fab37eSRobert Watson /* 29995fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 30095fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 30195fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 30295fab37eSRobert Watson */ 30395fab37eSRobert Watson static void 30495fab37eSRobert Watson mac_late_init(void) 30595fab37eSRobert Watson { 30695fab37eSRobert Watson 30795fab37eSRobert Watson mac_late = 1; 30895fab37eSRobert Watson } 30995fab37eSRobert Watson 31095fab37eSRobert Watson /* 311225bff6fSRobert Watson * After the policy list has changed, walk the list to update any global 31219c3e120SRobert Watson * flags. Currently, we support only one flag, and it's conditionally 31319c3e120SRobert Watson * defined; as a result, the entire function is conditional. Eventually, 31419c3e120SRobert Watson * the #else case might also iterate across the policies. 315225bff6fSRobert Watson */ 316225bff6fSRobert Watson static void 317225bff6fSRobert Watson mac_policy_updateflags(void) 318225bff6fSRobert Watson { 319225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 32019c3e120SRobert Watson struct mac_policy_conf *tmpc; 321225bff6fSRobert Watson int labelmbufs; 322225bff6fSRobert Watson 32341a17fe3SRobert Watson mac_policy_assert_exclusive(); 324225bff6fSRobert Watson 325225bff6fSRobert Watson labelmbufs = 0; 32641a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 32741a17fe3SRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 32841a17fe3SRobert Watson labelmbufs++; 32941a17fe3SRobert Watson } 330225bff6fSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 331225bff6fSRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 332225bff6fSRobert Watson labelmbufs++; 333225bff6fSRobert Watson } 334225bff6fSRobert Watson mac_labelmbufs = (labelmbufs != 0); 335225bff6fSRobert Watson #endif 336225bff6fSRobert Watson } 337225bff6fSRobert Watson 338225bff6fSRobert Watson /* 33995fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 34095fab37eSRobert Watson */ 34195fab37eSRobert Watson int 34295fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 34395fab37eSRobert Watson { 34495fab37eSRobert Watson struct mac_policy_conf *mpc; 34595fab37eSRobert Watson int error; 34695fab37eSRobert Watson 34795fab37eSRobert Watson error = 0; 34895fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 34995fab37eSRobert Watson 3500a05006dSRobert Watson #ifdef MAC_STATIC 3510a05006dSRobert Watson if (mac_late) { 3520a05006dSRobert Watson printf("mac_policy_modevent: MAC_STATIC and late\n"); 3530a05006dSRobert Watson return (EBUSY); 3540a05006dSRobert Watson } 3550a05006dSRobert Watson #endif 3560a05006dSRobert Watson 35795fab37eSRobert Watson switch (type) { 35895fab37eSRobert Watson case MOD_LOAD: 35995fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 36095fab37eSRobert Watson mac_late) { 36195fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 36295fab37eSRobert Watson "after booting\n", mpc->mpc_name); 36395fab37eSRobert Watson error = EBUSY; 36495fab37eSRobert Watson break; 36595fab37eSRobert Watson } 36695fab37eSRobert Watson error = mac_policy_register(mpc); 36795fab37eSRobert Watson break; 36895fab37eSRobert Watson case MOD_UNLOAD: 36995fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 37095fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 37195fab37eSRobert Watson != 0) 37295fab37eSRobert Watson error = mac_policy_unregister(mpc); 37395fab37eSRobert Watson else 37495fab37eSRobert Watson error = 0; 37595fab37eSRobert Watson break; 37695fab37eSRobert Watson default: 3773e019deaSPoul-Henning Kamp error = EOPNOTSUPP; 37895fab37eSRobert Watson break; 37995fab37eSRobert Watson } 38095fab37eSRobert Watson 38195fab37eSRobert Watson return (error); 38295fab37eSRobert Watson } 38395fab37eSRobert Watson 38495fab37eSRobert Watson static int 38595fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 38695fab37eSRobert Watson { 38795fab37eSRobert Watson struct mac_policy_conf *tmpc; 38841a17fe3SRobert Watson int error, slot, static_entry; 38995fab37eSRobert Watson 39041a17fe3SRobert Watson error = 0; 39141a17fe3SRobert Watson 39241a17fe3SRobert Watson /* 39341a17fe3SRobert Watson * We don't technically need exclusive access while !mac_late, 39441a17fe3SRobert Watson * but hold it for assertion consistency. 39541a17fe3SRobert Watson */ 39641a17fe3SRobert Watson mac_policy_grab_exclusive(); 39741a17fe3SRobert Watson 39841a17fe3SRobert Watson /* 39941a17fe3SRobert Watson * If the module can potentially be unloaded, or we're loading 40041a17fe3SRobert Watson * late, we have to stick it in the non-static list and pay 40141a17fe3SRobert Watson * an extra performance overhead. Otherwise, we can pay a 40241a17fe3SRobert Watson * light locking cost and stick it in the static list. 40341a17fe3SRobert Watson */ 40441a17fe3SRobert Watson static_entry = (!mac_late && 40541a17fe3SRobert Watson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 40641a17fe3SRobert Watson 40741a17fe3SRobert Watson if (static_entry) { 40841a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 40941a17fe3SRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 41041a17fe3SRobert Watson error = EEXIST; 41141a17fe3SRobert Watson goto out; 41241a17fe3SRobert Watson } 41341a17fe3SRobert Watson } 41441a17fe3SRobert Watson } else { 41595fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 41695fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 41741a17fe3SRobert Watson error = EEXIST; 41841a17fe3SRobert Watson goto out; 41941a17fe3SRobert Watson } 42095fab37eSRobert Watson } 42195fab37eSRobert Watson } 42295fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 423b2aef571SRobert Watson slot = ffs(mac_slot_offsets_free); 42495fab37eSRobert Watson if (slot == 0) { 42541a17fe3SRobert Watson error = ENOMEM; 42641a17fe3SRobert Watson goto out; 42795fab37eSRobert Watson } 42895fab37eSRobert Watson slot--; 429b2aef571SRobert Watson mac_slot_offsets_free &= ~(1 << slot); 43095fab37eSRobert Watson *mpc->mpc_field_off = slot; 43195fab37eSRobert Watson } 43295fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 43341a17fe3SRobert Watson 43441a17fe3SRobert Watson /* 43541a17fe3SRobert Watson * If we're loading a MAC module after the framework has 43641a17fe3SRobert Watson * initialized, it has to go into the dynamic list. If 43741a17fe3SRobert Watson * we're loading it before we've finished initializing, 43841a17fe3SRobert Watson * it can go into the static list with weaker locker 43941a17fe3SRobert Watson * requirements. 44041a17fe3SRobert Watson */ 44141a17fe3SRobert Watson if (static_entry) 44241a17fe3SRobert Watson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 44341a17fe3SRobert Watson else 44495fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 44595fab37eSRobert Watson 44695fab37eSRobert Watson /* Per-policy initialization. */ 44795fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 44895fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 449225bff6fSRobert Watson mac_policy_updateflags(); 45095fab37eSRobert Watson 45195fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 45295fab37eSRobert Watson mpc->mpc_name); 45395fab37eSRobert Watson 45441a17fe3SRobert Watson out: 45541a17fe3SRobert Watson mac_policy_release_exclusive(); 45641a17fe3SRobert Watson return (error); 45795fab37eSRobert Watson } 45895fab37eSRobert Watson 45995fab37eSRobert Watson static int 46095fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 46195fab37eSRobert Watson { 46295fab37eSRobert Watson 463ea599aa0SRobert Watson /* 464ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 465ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 466ea599aa0SRobert Watson * silently succeed. 467ea599aa0SRobert Watson */ 46841a17fe3SRobert Watson mac_policy_grab_exclusive(); 469ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 47041a17fe3SRobert Watson mac_policy_release_exclusive(); 471ea599aa0SRobert Watson return (0); 472ea599aa0SRobert Watson } 47395fab37eSRobert Watson #if 0 47495fab37eSRobert Watson /* 47595fab37eSRobert Watson * Don't allow unloading modules with private data. 47695fab37eSRobert Watson */ 477ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 478ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 47995fab37eSRobert Watson return (EBUSY); 480ea599aa0SRobert Watson } 48195fab37eSRobert Watson #endif 482ea599aa0SRobert Watson /* 483ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 484ea599aa0SRobert Watson * by its own definition. 485ea599aa0SRobert Watson */ 486ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 48741a17fe3SRobert Watson mac_policy_release_exclusive(); 48895fab37eSRobert Watson return (EBUSY); 489ea599aa0SRobert Watson } 49095fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 49195fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 49295fab37eSRobert Watson 49395fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 4949aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 495225bff6fSRobert Watson mac_policy_updateflags(); 49641a17fe3SRobert Watson 49741a17fe3SRobert Watson mac_policy_release_exclusive(); 498a96acd1aSRobert Watson 49995fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 50095fab37eSRobert Watson mpc->mpc_name); 50195fab37eSRobert Watson 50295fab37eSRobert Watson return (0); 50395fab37eSRobert Watson } 50495fab37eSRobert Watson 50595fab37eSRobert Watson /* 50695fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 50795fab37eSRobert Watson * value with the higher precedence. 50895fab37eSRobert Watson */ 5099e7bf51cSRobert Watson int 5109e7bf51cSRobert Watson mac_error_select(int error1, int error2) 51195fab37eSRobert Watson { 51295fab37eSRobert Watson 51395fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 51495fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 51595fab37eSRobert Watson return (EDEADLK); 51695fab37eSRobert Watson 51795fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 51895fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 51995fab37eSRobert Watson return (EINVAL); 52095fab37eSRobert Watson 52195fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 52295fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 52395fab37eSRobert Watson return (ESRCH); 52495fab37eSRobert Watson 52595fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 52695fab37eSRobert Watson return (ENOENT); 52795fab37eSRobert Watson 52895fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 52995fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 53095fab37eSRobert Watson return (EACCES); 53195fab37eSRobert Watson 53295fab37eSRobert Watson /* Precedence goes to privilege. */ 53395fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 53495fab37eSRobert Watson return (EPERM); 53595fab37eSRobert Watson 53695fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 53795fab37eSRobert Watson if (error1 != 0) 53895fab37eSRobert Watson return (error1); 53995fab37eSRobert Watson return (error2); 54095fab37eSRobert Watson } 54195fab37eSRobert Watson 5426fa0475dSRobert Watson void 54308bcdc58SRobert Watson mac_init_label(struct label *label) 54408bcdc58SRobert Watson { 54508bcdc58SRobert Watson 54608bcdc58SRobert Watson bzero(label, sizeof(*label)); 54708bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 54808bcdc58SRobert Watson } 54908bcdc58SRobert Watson 5506fa0475dSRobert Watson void 55108bcdc58SRobert Watson mac_destroy_label(struct label *label) 55208bcdc58SRobert Watson { 55308bcdc58SRobert Watson 55408bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 55508bcdc58SRobert Watson ("destroying uninitialized label")); 55608bcdc58SRobert Watson 55708bcdc58SRobert Watson bzero(label, sizeof(*label)); 55808bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 55908bcdc58SRobert Watson } 56008bcdc58SRobert Watson 5615e7ce478SRobert Watson int 562f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 563f7b951a8SRobert Watson { 564f7b951a8SRobert Watson 565cc7b13bfSRobert Watson if (mac->m_buflen < 0 || 566cc7b13bfSRobert Watson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 567f7b951a8SRobert Watson return (EINVAL); 568f7b951a8SRobert Watson 569f7b951a8SRobert Watson return (0); 570f7b951a8SRobert Watson } 571f7b951a8SRobert Watson 572f0ab0442SRobert Watson /* 573f0ab0442SRobert Watson * MPSAFE 574f0ab0442SRobert Watson */ 575f7b951a8SRobert Watson int 576f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 577f7b951a8SRobert Watson { 578f7b951a8SRobert Watson char *elements, *buffer; 579f7b951a8SRobert Watson struct mac mac; 580f7b951a8SRobert Watson struct proc *tproc; 581f7b951a8SRobert Watson struct ucred *tcred; 582f7b951a8SRobert Watson int error; 583f7b951a8SRobert Watson 584d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 585f7b951a8SRobert Watson if (error) 586f7b951a8SRobert Watson return (error); 587f7b951a8SRobert Watson 588f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 589f7b951a8SRobert Watson if (error) 590f7b951a8SRobert Watson return (error); 591f7b951a8SRobert Watson 592f7b951a8SRobert Watson tproc = pfind(uap->pid); 593f7b951a8SRobert Watson if (tproc == NULL) 594f7b951a8SRobert Watson return (ESRCH); 595f7b951a8SRobert Watson 596f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 597f7b951a8SRobert Watson error = p_cansee(td, tproc); 598f7b951a8SRobert Watson if (error == 0) 599f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 600f7b951a8SRobert Watson PROC_UNLOCK(tproc); 601f7b951a8SRobert Watson if (error) 602f7b951a8SRobert Watson return (error); 603f7b951a8SRobert Watson 604a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 605f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 606f7b951a8SRobert Watson if (error) { 607f7b951a8SRobert Watson free(elements, M_MACTEMP); 608f7b951a8SRobert Watson crfree(tcred); 609f7b951a8SRobert Watson return (error); 610f7b951a8SRobert Watson } 611f7b951a8SRobert Watson 612a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 613eca8a663SRobert Watson error = mac_externalize_cred_label(tcred->cr_label, elements, 61483b7b0edSRobert Watson buffer, mac.m_buflen); 615f7b951a8SRobert Watson if (error == 0) 616f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 617f7b951a8SRobert Watson 618f7b951a8SRobert Watson free(buffer, M_MACTEMP); 619f7b951a8SRobert Watson free(elements, M_MACTEMP); 620f7b951a8SRobert Watson crfree(tcred); 621f7b951a8SRobert Watson return (error); 622f7b951a8SRobert Watson } 623f7b951a8SRobert Watson 62495fab37eSRobert Watson /* 62595fab37eSRobert Watson * MPSAFE 62695fab37eSRobert Watson */ 62795fab37eSRobert Watson int 62895fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 62995fab37eSRobert Watson { 630f7b951a8SRobert Watson char *elements, *buffer; 631f7b951a8SRobert Watson struct mac mac; 63295fab37eSRobert Watson int error; 63395fab37eSRobert Watson 634f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 635f7b951a8SRobert Watson if (error) 636f7b951a8SRobert Watson return (error); 63795fab37eSRobert Watson 638f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 639f7b951a8SRobert Watson if (error) 640f7b951a8SRobert Watson return (error); 641f7b951a8SRobert Watson 642a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 643f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 644f7b951a8SRobert Watson if (error) { 645f7b951a8SRobert Watson free(elements, M_MACTEMP); 646f7b951a8SRobert Watson return (error); 647f7b951a8SRobert Watson } 648f7b951a8SRobert Watson 649a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 650eca8a663SRobert Watson error = mac_externalize_cred_label(td->td_ucred->cr_label, 65183b7b0edSRobert Watson elements, buffer, mac.m_buflen); 652f7b951a8SRobert Watson if (error == 0) 653f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 654f7b951a8SRobert Watson 655f7b951a8SRobert Watson free(buffer, M_MACTEMP); 656f7b951a8SRobert Watson free(elements, M_MACTEMP); 65795fab37eSRobert Watson return (error); 65895fab37eSRobert Watson } 65995fab37eSRobert Watson 66095fab37eSRobert Watson /* 66195fab37eSRobert Watson * MPSAFE 66295fab37eSRobert Watson */ 66395fab37eSRobert Watson int 66495fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 66595fab37eSRobert Watson { 66695fab37eSRobert Watson struct ucred *newcred, *oldcred; 667eca8a663SRobert Watson struct label *intlabel; 668f7b951a8SRobert Watson struct proc *p; 669f7b951a8SRobert Watson struct mac mac; 670f7b951a8SRobert Watson char *buffer; 67195fab37eSRobert Watson int error; 67295fab37eSRobert Watson 673f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 67495fab37eSRobert Watson if (error) 67595fab37eSRobert Watson return (error); 67695fab37eSRobert Watson 677f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 67895fab37eSRobert Watson if (error) 67995fab37eSRobert Watson return (error); 68095fab37eSRobert Watson 681a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 682f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 683f7b951a8SRobert Watson if (error) { 684f7b951a8SRobert Watson free(buffer, M_MACTEMP); 685f7b951a8SRobert Watson return (error); 686f7b951a8SRobert Watson } 687f7b951a8SRobert Watson 688eca8a663SRobert Watson intlabel = mac_cred_label_alloc(); 689eca8a663SRobert Watson error = mac_internalize_cred_label(intlabel, buffer); 690f7b951a8SRobert Watson free(buffer, M_MACTEMP); 691eca8a663SRobert Watson if (error) 692eca8a663SRobert Watson goto out; 693f7b951a8SRobert Watson 69495fab37eSRobert Watson newcred = crget(); 69595fab37eSRobert Watson 69695fab37eSRobert Watson p = td->td_proc; 69795fab37eSRobert Watson PROC_LOCK(p); 69895fab37eSRobert Watson oldcred = p->p_ucred; 69995fab37eSRobert Watson 700eca8a663SRobert Watson error = mac_check_cred_relabel(oldcred, intlabel); 70195fab37eSRobert Watson if (error) { 70295fab37eSRobert Watson PROC_UNLOCK(p); 70395fab37eSRobert Watson crfree(newcred); 704f7b951a8SRobert Watson goto out; 70595fab37eSRobert Watson } 70695fab37eSRobert Watson 70795fab37eSRobert Watson setsugid(p); 70895fab37eSRobert Watson crcopy(newcred, oldcred); 709eca8a663SRobert Watson mac_relabel_cred(newcred, intlabel); 71095fab37eSRobert Watson p->p_ucred = newcred; 711e5cb5e37SRobert Watson 712e5cb5e37SRobert Watson /* 713e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 714e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 715e5cb5e37SRobert Watson */ 716e5cb5e37SRobert Watson crhold(newcred); 71795fab37eSRobert Watson PROC_UNLOCK(p); 718e5cb5e37SRobert Watson 719f7b951a8SRobert Watson if (mac_enforce_vm) { 720e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 721f7b951a8SRobert Watson } 722e5cb5e37SRobert Watson 723e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 72495fab37eSRobert Watson crfree(oldcred); 725f7b951a8SRobert Watson 726f7b951a8SRobert Watson out: 727eca8a663SRobert Watson mac_cred_label_free(intlabel); 728f7b951a8SRobert Watson return (error); 72995fab37eSRobert Watson } 73095fab37eSRobert Watson 73195fab37eSRobert Watson /* 73295fab37eSRobert Watson * MPSAFE 73395fab37eSRobert Watson */ 73495fab37eSRobert Watson int 73595fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 73695fab37eSRobert Watson { 737f7b951a8SRobert Watson char *elements, *buffer; 738eca8a663SRobert Watson struct label *intlabel; 73995fab37eSRobert Watson struct file *fp; 740f7b951a8SRobert Watson struct mac mac; 74195fab37eSRobert Watson struct vnode *vp; 74295fab37eSRobert Watson struct pipe *pipe; 743b0323ea3SRobert Watson struct socket *so; 744f7b951a8SRobert Watson short label_type; 7459eea3d85SChristian S.J. Peron int vfslocked, error; 74695fab37eSRobert Watson 747f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 748f7b951a8SRobert Watson if (error) 749f7b951a8SRobert Watson return (error); 75095fab37eSRobert Watson 751f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 752f7b951a8SRobert Watson if (error) 753f7b951a8SRobert Watson return (error); 754f7b951a8SRobert Watson 755a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 756f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 757f7b951a8SRobert Watson if (error) { 758f7b951a8SRobert Watson free(elements, M_MACTEMP); 759f7b951a8SRobert Watson return (error); 760f7b951a8SRobert Watson } 761f7b951a8SRobert Watson 762a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 763d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 76495fab37eSRobert Watson if (error) 76595fab37eSRobert Watson goto out; 76695fab37eSRobert Watson 767f7b951a8SRobert Watson label_type = fp->f_type; 76895fab37eSRobert Watson switch (fp->f_type) { 76995fab37eSRobert Watson case DTYPE_FIFO: 77095fab37eSRobert Watson case DTYPE_VNODE: 7713b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 772eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 7739eea3d85SChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(vp->v_mount); 77495fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 775eca8a663SRobert Watson mac_copy_vnode_label(vp->v_label, intlabel); 77695fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 7779eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 778f0ab0442SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, 779f0ab0442SRobert Watson buffer, mac.m_buflen); 780f0ab0442SRobert Watson mac_vnode_label_free(intlabel); 78195fab37eSRobert Watson break; 782f0ab0442SRobert Watson 78395fab37eSRobert Watson case DTYPE_PIPE: 78448e3128bSMatthew Dillon pipe = fp->f_data; 785eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 786f7b951a8SRobert Watson PIPE_LOCK(pipe); 7874795b82cSRobert Watson mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 788f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 789eca8a663SRobert Watson error = mac_externalize_pipe_label(intlabel, elements, 79083b7b0edSRobert Watson buffer, mac.m_buflen); 791eca8a663SRobert Watson mac_pipe_label_free(intlabel); 792f7b951a8SRobert Watson break; 79395fab37eSRobert Watson 794b0323ea3SRobert Watson case DTYPE_SOCKET: 795b0323ea3SRobert Watson so = fp->f_data; 796b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 797f0c2044bSRobert Watson NET_LOCK_GIANT(); 798f0c2044bSRobert Watson SOCK_LOCK(so); 799b0323ea3SRobert Watson mac_copy_socket_label(so->so_label, intlabel); 800f0c2044bSRobert Watson SOCK_UNLOCK(so); 801f0c2044bSRobert Watson NET_UNLOCK_GIANT(); 802b0323ea3SRobert Watson error = mac_externalize_socket_label(intlabel, elements, 803b0323ea3SRobert Watson buffer, mac.m_buflen); 804b0323ea3SRobert Watson mac_socket_label_free(intlabel); 805b0323ea3SRobert Watson break; 806b0323ea3SRobert Watson 807f0ab0442SRobert Watson default: 808f0ab0442SRobert Watson error = EINVAL; 809f0ab0442SRobert Watson } 810f0ab0442SRobert Watson fdrop(fp, td); 81195fab37eSRobert Watson if (error == 0) 812f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 81395fab37eSRobert Watson 81495fab37eSRobert Watson out: 815f7b951a8SRobert Watson free(buffer, M_MACTEMP); 816f7b951a8SRobert Watson free(elements, M_MACTEMP); 81795fab37eSRobert Watson return (error); 81895fab37eSRobert Watson } 81995fab37eSRobert Watson 82095fab37eSRobert Watson /* 82195fab37eSRobert Watson * MPSAFE 82295fab37eSRobert Watson */ 82395fab37eSRobert Watson int 82495fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 82595fab37eSRobert Watson { 826f7b951a8SRobert Watson char *elements, *buffer; 82795fab37eSRobert Watson struct nameidata nd; 828eca8a663SRobert Watson struct label *intlabel; 829f7b951a8SRobert Watson struct mac mac; 8309eea3d85SChristian S.J. Peron int vfslocked, error; 83195fab37eSRobert Watson 832f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 833f7b951a8SRobert Watson if (error) 834f7b951a8SRobert Watson return (error); 835f7b951a8SRobert Watson 836f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 837f7b951a8SRobert Watson if (error) 838f7b951a8SRobert Watson return (error); 839f7b951a8SRobert Watson 840a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 841f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 842f7b951a8SRobert Watson if (error) { 843f7b951a8SRobert Watson free(elements, M_MACTEMP); 844f7b951a8SRobert Watson return (error); 845f7b951a8SRobert Watson } 846f7b951a8SRobert Watson 847a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 8489eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 8499eea3d85SChristian S.J. Peron uap->path_p, td); 85095fab37eSRobert Watson error = namei(&nd); 85195fab37eSRobert Watson if (error) 85295fab37eSRobert Watson goto out; 85395fab37eSRobert Watson 854eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 8559eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 856eca8a663SRobert Watson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 857eca8a663SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, buffer, 85883b7b0edSRobert Watson mac.m_buflen); 859f7b951a8SRobert Watson 86095fab37eSRobert Watson NDFREE(&nd, 0); 8619eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 862eca8a663SRobert Watson mac_vnode_label_free(intlabel); 863f7b951a8SRobert Watson if (error == 0) 864f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 865f7b951a8SRobert Watson 866f7b951a8SRobert Watson out: 867f7b951a8SRobert Watson free(buffer, M_MACTEMP); 868f7b951a8SRobert Watson free(elements, M_MACTEMP); 869f7b951a8SRobert Watson 870f7b951a8SRobert Watson return (error); 871f7b951a8SRobert Watson } 872f7b951a8SRobert Watson 873f7b951a8SRobert Watson /* 874f7b951a8SRobert Watson * MPSAFE 875f7b951a8SRobert Watson */ 876f7b951a8SRobert Watson int 877f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 878f7b951a8SRobert Watson { 879f7b951a8SRobert Watson char *elements, *buffer; 880f7b951a8SRobert Watson struct nameidata nd; 881eca8a663SRobert Watson struct label *intlabel; 882f7b951a8SRobert Watson struct mac mac; 8839eea3d85SChristian S.J. Peron int vfslocked, error; 884f7b951a8SRobert Watson 885f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 886f7b951a8SRobert Watson if (error) 887f7b951a8SRobert Watson return (error); 888f7b951a8SRobert Watson 889f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 890f7b951a8SRobert Watson if (error) 891f7b951a8SRobert Watson return (error); 892f7b951a8SRobert Watson 893a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 894f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 895f7b951a8SRobert Watson if (error) { 896f7b951a8SRobert Watson free(elements, M_MACTEMP); 897f7b951a8SRobert Watson return (error); 898f7b951a8SRobert Watson } 899f7b951a8SRobert Watson 900a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 9019eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 9029eea3d85SChristian S.J. Peron uap->path_p, td); 903f7b951a8SRobert Watson error = namei(&nd); 90495fab37eSRobert Watson if (error) 90595fab37eSRobert Watson goto out; 90695fab37eSRobert Watson 907eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 9089eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 909eca8a663SRobert Watson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 910eca8a663SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, buffer, 91183b7b0edSRobert Watson mac.m_buflen); 912f7b951a8SRobert Watson NDFREE(&nd, 0); 9139eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 914eca8a663SRobert Watson mac_vnode_label_free(intlabel); 915f7b951a8SRobert Watson 916f7b951a8SRobert Watson if (error == 0) 917f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 91895fab37eSRobert Watson 91995fab37eSRobert Watson out: 920f7b951a8SRobert Watson free(buffer, M_MACTEMP); 921f7b951a8SRobert Watson free(elements, M_MACTEMP); 922f7b951a8SRobert Watson 92395fab37eSRobert Watson return (error); 92495fab37eSRobert Watson } 92595fab37eSRobert Watson 92695fab37eSRobert Watson /* 92795fab37eSRobert Watson * MPSAFE 92895fab37eSRobert Watson */ 92995fab37eSRobert Watson int 93095fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 93195fab37eSRobert Watson { 932eca8a663SRobert Watson struct label *intlabel; 933f7b951a8SRobert Watson struct pipe *pipe; 934b0323ea3SRobert Watson struct socket *so; 935f7b951a8SRobert Watson struct file *fp; 93695fab37eSRobert Watson struct mount *mp; 93795fab37eSRobert Watson struct vnode *vp; 938f7b951a8SRobert Watson struct mac mac; 939f7b951a8SRobert Watson char *buffer; 9409eea3d85SChristian S.J. Peron int error, vfslocked; 94195fab37eSRobert Watson 942f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 943f7b951a8SRobert Watson if (error) 944f7b951a8SRobert Watson return (error); 945f7b951a8SRobert Watson 946f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 947f7b951a8SRobert Watson if (error) 948f7b951a8SRobert Watson return (error); 949f7b951a8SRobert Watson 950a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 951f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 952f7b951a8SRobert Watson if (error) { 953f7b951a8SRobert Watson free(buffer, M_MACTEMP); 954f7b951a8SRobert Watson return (error); 955f7b951a8SRobert Watson } 956f7b951a8SRobert Watson 957d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 95895fab37eSRobert Watson if (error) 959f7b951a8SRobert Watson goto out; 96095fab37eSRobert Watson 96195fab37eSRobert Watson switch (fp->f_type) { 96295fab37eSRobert Watson case DTYPE_FIFO: 96395fab37eSRobert Watson case DTYPE_VNODE: 964eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 965eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 966f7b951a8SRobert Watson if (error) { 967eca8a663SRobert Watson mac_vnode_label_free(intlabel); 968f7b951a8SRobert Watson break; 969f7b951a8SRobert Watson } 9703b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 9719eea3d85SChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(vp->v_mount); 97295fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 973f7b951a8SRobert Watson if (error != 0) { 9749eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 975eca8a663SRobert Watson mac_vnode_label_free(intlabel); 97695fab37eSRobert Watson break; 977f7b951a8SRobert Watson } 97895fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 979eca8a663SRobert Watson error = vn_setlabel(vp, intlabel, td->td_ucred); 98095fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 98195fab37eSRobert Watson vn_finished_write(mp); 9829eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 983eca8a663SRobert Watson mac_vnode_label_free(intlabel); 98495fab37eSRobert Watson break; 985f7b951a8SRobert Watson 98695fab37eSRobert Watson case DTYPE_PIPE: 987eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 988eca8a663SRobert Watson error = mac_internalize_pipe_label(intlabel, buffer); 989f7b951a8SRobert Watson if (error == 0) { 99048e3128bSMatthew Dillon pipe = fp->f_data; 9911aa37f53SRobert Watson PIPE_LOCK(pipe); 9924795b82cSRobert Watson error = mac_pipe_label_set(td->td_ucred, 9934795b82cSRobert Watson pipe->pipe_pair, intlabel); 9941aa37f53SRobert Watson PIPE_UNLOCK(pipe); 995f7b951a8SRobert Watson } 996eca8a663SRobert Watson mac_pipe_label_free(intlabel); 99795fab37eSRobert Watson break; 998f7b951a8SRobert Watson 999b0323ea3SRobert Watson case DTYPE_SOCKET: 1000b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 1001b0323ea3SRobert Watson error = mac_internalize_socket_label(intlabel, buffer); 1002b0323ea3SRobert Watson if (error == 0) { 1003b0323ea3SRobert Watson so = fp->f_data; 1004f0c2044bSRobert Watson NET_LOCK_GIANT(); 1005b0323ea3SRobert Watson error = mac_socket_label_set(td->td_ucred, so, 1006b0323ea3SRobert Watson intlabel); 1007f0c2044bSRobert Watson NET_UNLOCK_GIANT(); 1008b0323ea3SRobert Watson } 1009b0323ea3SRobert Watson mac_socket_label_free(intlabel); 1010b0323ea3SRobert Watson break; 1011b0323ea3SRobert Watson 101295fab37eSRobert Watson default: 101395fab37eSRobert Watson error = EINVAL; 101495fab37eSRobert Watson } 101595fab37eSRobert Watson fdrop(fp, td); 1016f7b951a8SRobert Watson out: 1017f7b951a8SRobert Watson free(buffer, M_MACTEMP); 101895fab37eSRobert Watson return (error); 101995fab37eSRobert Watson } 102095fab37eSRobert Watson 102195fab37eSRobert Watson /* 102295fab37eSRobert Watson * MPSAFE 102395fab37eSRobert Watson */ 102495fab37eSRobert Watson int 102595fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 102695fab37eSRobert Watson { 1027eca8a663SRobert Watson struct label *intlabel; 1028f7b951a8SRobert Watson struct nameidata nd; 102995fab37eSRobert Watson struct mount *mp; 1030f7b951a8SRobert Watson struct mac mac; 1031f7b951a8SRobert Watson char *buffer; 10329eea3d85SChristian S.J. Peron int vfslocked, error; 103395fab37eSRobert Watson 1034f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 103595fab37eSRobert Watson if (error) 1036f7b951a8SRobert Watson return (error); 103795fab37eSRobert Watson 1038f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 103995fab37eSRobert Watson if (error) 1040f7b951a8SRobert Watson return (error); 104195fab37eSRobert Watson 1042a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1043f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1044f7b951a8SRobert Watson if (error) { 1045f7b951a8SRobert Watson free(buffer, M_MACTEMP); 104695fab37eSRobert Watson return (error); 104795fab37eSRobert Watson } 104895fab37eSRobert Watson 1049eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 1050eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 1051f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1052eca8a663SRobert Watson if (error) 1053eca8a663SRobert Watson goto out; 1054f7b951a8SRobert Watson 10559eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 10569eea3d85SChristian S.J. Peron uap->path_p, td); 1057f7b951a8SRobert Watson error = namei(&nd); 10589eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 1059f7b951a8SRobert Watson if (error == 0) { 1060f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1061d50ef66dSTor Egge if (error == 0) { 1062eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 1063f7b951a8SRobert Watson td->td_ucred); 1064f7b951a8SRobert Watson vn_finished_write(mp); 1065f7b951a8SRobert Watson } 1066d50ef66dSTor Egge } 1067f7b951a8SRobert Watson 1068f7b951a8SRobert Watson NDFREE(&nd, 0); 10699eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 1070eca8a663SRobert Watson out: 1071eca8a663SRobert Watson mac_vnode_label_free(intlabel); 1072f7b951a8SRobert Watson return (error); 1073f7b951a8SRobert Watson } 1074f7b951a8SRobert Watson 1075f7b951a8SRobert Watson /* 1076f7b951a8SRobert Watson * MPSAFE 1077f7b951a8SRobert Watson */ 1078f7b951a8SRobert Watson int 1079f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1080f7b951a8SRobert Watson { 1081eca8a663SRobert Watson struct label *intlabel; 1082f7b951a8SRobert Watson struct nameidata nd; 1083f7b951a8SRobert Watson struct mount *mp; 1084f7b951a8SRobert Watson struct mac mac; 1085f7b951a8SRobert Watson char *buffer; 10869eea3d85SChristian S.J. Peron int vfslocked, error; 1087f7b951a8SRobert Watson 1088f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1089f7b951a8SRobert Watson if (error) 1090f7b951a8SRobert Watson return (error); 1091f7b951a8SRobert Watson 1092f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 1093f7b951a8SRobert Watson if (error) 1094f7b951a8SRobert Watson return (error); 1095f7b951a8SRobert Watson 1096a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1097f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1098f7b951a8SRobert Watson if (error) { 1099f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1100f7b951a8SRobert Watson return (error); 1101f7b951a8SRobert Watson } 1102f7b951a8SRobert Watson 1103eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 1104eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 1105f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1106eca8a663SRobert Watson if (error) 1107eca8a663SRobert Watson goto out; 1108f7b951a8SRobert Watson 11099eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 11109eea3d85SChristian S.J. Peron uap->path_p, td); 1111f7b951a8SRobert Watson error = namei(&nd); 11129eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 1113f7b951a8SRobert Watson if (error == 0) { 1114f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1115d50ef66dSTor Egge if (error == 0) { 1116eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 1117f7b951a8SRobert Watson td->td_ucred); 1118f7b951a8SRobert Watson vn_finished_write(mp); 1119f7b951a8SRobert Watson } 1120d50ef66dSTor Egge } 1121f7b951a8SRobert Watson 1122f7b951a8SRobert Watson NDFREE(&nd, 0); 11239eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 1124eca8a663SRobert Watson out: 1125eca8a663SRobert Watson mac_vnode_label_free(intlabel); 1126f7b951a8SRobert Watson return (error); 1127f7b951a8SRobert Watson } 1128f7b951a8SRobert Watson 1129f7b951a8SRobert Watson /* 1130f7b951a8SRobert Watson * MPSAFE 1131f7b951a8SRobert Watson */ 113227f2eac7SRobert Watson int 113327f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 113427f2eac7SRobert Watson { 113527f2eac7SRobert Watson struct mac_policy_conf *mpc; 113627f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 113741a17fe3SRobert Watson int entrycount, error; 113827f2eac7SRobert Watson 1139d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 114027f2eac7SRobert Watson if (error) 114127f2eac7SRobert Watson return (error); 114227f2eac7SRobert Watson 114327f2eac7SRobert Watson error = ENOSYS; 1144a6a65b05SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 114527f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 114627f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 114727f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 1148d1e405c5SAlfred Perlstein uap->call, uap->arg); 114927f2eac7SRobert Watson goto out; 115027f2eac7SRobert Watson } 115127f2eac7SRobert Watson } 115227f2eac7SRobert Watson 115341a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 115441a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 115541a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 115641a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 115741a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 115841a17fe3SRobert Watson uap->call, uap->arg); 115941a17fe3SRobert Watson break; 116041a17fe3SRobert Watson } 116141a17fe3SRobert Watson } 116241a17fe3SRobert Watson mac_policy_list_unbusy(); 116341a17fe3SRobert Watson } 116427f2eac7SRobert Watson out: 116527f2eac7SRobert Watson return (error); 116627f2eac7SRobert Watson } 116727f2eac7SRobert Watson 116895fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 116995fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 117095fab37eSRobert Watson 117195fab37eSRobert Watson #else /* !MAC */ 11727bc82500SRobert Watson 11737bc82500SRobert Watson int 1174f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1175f7b951a8SRobert Watson { 1176f7b951a8SRobert Watson 1177f7b951a8SRobert Watson return (ENOSYS); 1178f7b951a8SRobert Watson } 1179f7b951a8SRobert Watson 1180f7b951a8SRobert Watson int 11817bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 11827bc82500SRobert Watson { 11837bc82500SRobert Watson 11847bc82500SRobert Watson return (ENOSYS); 11857bc82500SRobert Watson } 11867bc82500SRobert Watson 11877bc82500SRobert Watson int 11887bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 11897bc82500SRobert Watson { 11907bc82500SRobert Watson 11917bc82500SRobert Watson return (ENOSYS); 11927bc82500SRobert Watson } 11937bc82500SRobert Watson 11947bc82500SRobert Watson int 11957bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 11967bc82500SRobert Watson { 11977bc82500SRobert Watson 11987bc82500SRobert Watson return (ENOSYS); 11997bc82500SRobert Watson } 12007bc82500SRobert Watson 12017bc82500SRobert Watson int 12027bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 12037bc82500SRobert Watson { 12047bc82500SRobert Watson 12057bc82500SRobert Watson return (ENOSYS); 12067bc82500SRobert Watson } 12077bc82500SRobert Watson 12087bc82500SRobert Watson int 1209f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1210f7b951a8SRobert Watson { 1211f7b951a8SRobert Watson 1212f7b951a8SRobert Watson return (ENOSYS); 1213f7b951a8SRobert Watson } 1214f7b951a8SRobert Watson 1215f7b951a8SRobert Watson int 12167bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 12177bc82500SRobert Watson { 12187bc82500SRobert Watson 12197bc82500SRobert Watson return (ENOSYS); 12207bc82500SRobert Watson } 12217bc82500SRobert Watson 12227bc82500SRobert Watson int 12237bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 12247bc82500SRobert Watson { 12257bc82500SRobert Watson 12267bc82500SRobert Watson return (ENOSYS); 12277bc82500SRobert Watson } 122895fab37eSRobert Watson 122927f2eac7SRobert Watson int 1230f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1231f7b951a8SRobert Watson { 1232f7b951a8SRobert Watson 1233f7b951a8SRobert Watson return (ENOSYS); 1234f7b951a8SRobert Watson } 1235f7b951a8SRobert Watson 1236f7b951a8SRobert Watson int 123727f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 123827f2eac7SRobert Watson { 123927f2eac7SRobert Watson 124027f2eac7SRobert Watson return (ENOSYS); 124127f2eac7SRobert Watson } 124227f2eac7SRobert Watson 124319b78822SRobert Watson #endif /* !MAC */ 1244