17bc82500SRobert Watson /*- 2f6a41092SRobert Watson * Copyright (c) 1999-2002 Robert N. M. Watson 37bc82500SRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 4f6a41092SRobert Watson * Copyright (c) 2001-2003 Networks Associates Technology, Inc. 57bc82500SRobert Watson * All rights reserved. 67bc82500SRobert Watson * 77bc82500SRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the 87bc82500SRobert Watson * TrustedBSD Project. 97bc82500SRobert Watson * 106201265bSRobert Watson * This software was developed for the FreeBSD Project in part by Network 116201265bSRobert Watson * Associates Laboratories, the Security Research Division of Network 126201265bSRobert Watson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 136201265bSRobert Watson * as part of the DARPA CHATS research program. 147bc82500SRobert Watson * 157bc82500SRobert Watson * Redistribution and use in source and binary forms, with or without 167bc82500SRobert Watson * modification, are permitted provided that the following conditions 177bc82500SRobert Watson * are met: 187bc82500SRobert Watson * 1. Redistributions of source code must retain the above copyright 197bc82500SRobert Watson * notice, this list of conditions and the following disclaimer. 207bc82500SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 217bc82500SRobert Watson * notice, this list of conditions and the following disclaimer in the 227bc82500SRobert Watson * documentation and/or other materials provided with the distribution. 237bc82500SRobert Watson * 247bc82500SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 257bc82500SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 267bc82500SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 277bc82500SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 287bc82500SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 297bc82500SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 307bc82500SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 317bc82500SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 327bc82500SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 337bc82500SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 347bc82500SRobert Watson * SUCH DAMAGE. 357bc82500SRobert Watson */ 36677b542eSDavid E. O'Brien 37c8e7bf92SRobert Watson /*- 38c8e7bf92SRobert Watson * Framework for extensible kernel access control. This file contains 39c8e7bf92SRobert Watson * Kernel and userland interface to the framework, policy registration 40c8e7bf92SRobert Watson * and composition. Per-object interfaces, controls, and labeling may be 41c8e7bf92SRobert Watson * found in src/sys/mac/. Sample policies may be found in src/sys/mac*. 427bc82500SRobert Watson */ 437bc82500SRobert Watson 44677b542eSDavid E. O'Brien #include <sys/cdefs.h> 45677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 46677b542eSDavid E. O'Brien 477bc82500SRobert Watson #include "opt_mac.h" 48328048bcSPoul-Henning Kamp #include "opt_devfs.h" 49f9d0d524SRobert Watson 507bc82500SRobert Watson #include <sys/param.h> 51a96acd1aSRobert Watson #include <sys/condvar.h> 5295fab37eSRobert Watson #include <sys/extattr.h> 53670cb89bSRobert Watson #include <sys/imgact.h> 5495fab37eSRobert Watson #include <sys/kernel.h> 5595fab37eSRobert Watson #include <sys/lock.h> 56b656366bSBruce Evans #include <sys/malloc.h> 5795fab37eSRobert Watson #include <sys/mutex.h> 5895fab37eSRobert Watson #include <sys/mac.h> 597ba28492SRobert Watson #include <sys/module.h> 6095fab37eSRobert Watson #include <sys/proc.h> 61f51e5803SRobert Watson #include <sys/sbuf.h> 6295fab37eSRobert Watson #include <sys/systm.h> 637bc82500SRobert Watson #include <sys/sysproto.h> 647bc82500SRobert Watson #include <sys/sysent.h> 6595fab37eSRobert Watson #include <sys/vnode.h> 6695fab37eSRobert Watson #include <sys/mount.h> 6795fab37eSRobert Watson #include <sys/file.h> 6895fab37eSRobert Watson #include <sys/namei.h> 6995fab37eSRobert Watson #include <sys/socket.h> 7095fab37eSRobert Watson #include <sys/pipe.h> 7195fab37eSRobert Watson #include <sys/socketvar.h> 7295fab37eSRobert Watson #include <sys/sysctl.h> 7395fab37eSRobert Watson 7495fab37eSRobert Watson #include <vm/vm.h> 7595fab37eSRobert Watson #include <vm/pmap.h> 7695fab37eSRobert Watson #include <vm/vm_map.h> 7795fab37eSRobert Watson #include <vm/vm_object.h> 7895fab37eSRobert Watson 7995fab37eSRobert Watson #include <sys/mac_policy.h> 8095fab37eSRobert Watson 8195fab37eSRobert Watson #include <fs/devfs/devfs.h> 8295fab37eSRobert Watson 8395fab37eSRobert Watson #include <net/bpfdesc.h> 8495fab37eSRobert Watson #include <net/if.h> 8595fab37eSRobert Watson #include <net/if_var.h> 8695fab37eSRobert Watson 8795fab37eSRobert Watson #include <netinet/in.h> 8895fab37eSRobert Watson #include <netinet/ip_var.h> 8995fab37eSRobert Watson 906fa0475dSRobert Watson #include <security/mac/mac_internal.h> 916fa0475dSRobert Watson 9295fab37eSRobert Watson #ifdef MAC 9395fab37eSRobert Watson 947ba28492SRobert Watson /* 957ba28492SRobert Watson * Declare that the kernel provides MAC support, version 1. This permits 967ba28492SRobert Watson * modules to refuse to be loaded if the necessary support isn't present, 977ba28492SRobert Watson * even if it's pre-boot. 987ba28492SRobert Watson */ 997ba28492SRobert Watson MODULE_VERSION(kernel_mac_support, 1); 1007ba28492SRobert Watson 10195fab37eSRobert Watson SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 10295fab37eSRobert Watson "TrustedBSD MAC policy controls"); 103b2f0927aSRobert Watson 104b2aef571SRobert Watson #if MAC_MAX_SLOTS > 32 105b2aef571SRobert Watson #error "MAC_MAX_SLOTS too large" 10695fab37eSRobert Watson #endif 107a13c67daSRobert Watson 108b2aef571SRobert Watson static unsigned int mac_max_slots = MAC_MAX_SLOTS; 109b2aef571SRobert Watson static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 110b2aef571SRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 111b2aef571SRobert Watson &mac_max_slots, 0, ""); 11295fab37eSRobert Watson 113a67fe518SRobert Watson /* 114a67fe518SRobert Watson * Has the kernel started generating labeled objects yet? All read/write 115a67fe518SRobert Watson * access to this variable is serialized during the boot process. Following 116a67fe518SRobert Watson * the end of serialization, we don't update this flag; no locking. 117a67fe518SRobert Watson */ 118089c1bdaSRobert Watson int mac_late = 0; 119763bbd2fSRobert Watson 120225bff6fSRobert Watson /* 121225bff6fSRobert Watson * Flag to indicate whether or not we should allocate label storage for 122225bff6fSRobert Watson * new mbufs. Since most dynamic policies we currently work with don't 123225bff6fSRobert Watson * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 124225bff6fSRobert Watson * unless specifically notified of interest. One result of this is 125225bff6fSRobert Watson * that if a dynamically loaded policy requests mbuf labels, it must 126225bff6fSRobert Watson * be able to deal with a NULL label being returned on any mbufs that 127225bff6fSRobert Watson * were already in flight when the policy was loaded. Since the policy 128225bff6fSRobert Watson * already has to deal with uninitialized labels, this probably won't 129225bff6fSRobert Watson * be a problem. Note: currently no locking. Will this be a problem? 130225bff6fSRobert Watson */ 13119c3e120SRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 132089c1bdaSRobert Watson int mac_labelmbufs = 0; 133225bff6fSRobert Watson #endif 134225bff6fSRobert Watson 135f050add5SRobert Watson #ifdef MAC_DEBUG 1366be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1376be0c25eSRobert Watson "TrustedBSD MAC debug info"); 138b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 139b2f0927aSRobert Watson "TrustedBSD MAC object counters"); 140b2f0927aSRobert Watson 1416fa0475dSRobert Watson static unsigned int nmactemp; 142b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 14395fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 144f050add5SRobert Watson #endif 14595fab37eSRobert Watson 14695fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 14795fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 14895fab37eSRobert Watson 149f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 15095fab37eSRobert Watson 15195fab37eSRobert Watson /* 15241a17fe3SRobert Watson * mac_static_policy_list holds a list of policy modules that are not 15341a17fe3SRobert Watson * loaded while the system is "live", and cannot be unloaded. These 15441a17fe3SRobert Watson * policies can be invoked without holding the busy count. 15541a17fe3SRobert Watson * 15641a17fe3SRobert Watson * mac_policy_list stores the list of dynamic policies. A busy count is 157a96acd1aSRobert Watson * maintained for the list, stored in mac_policy_busy. The busy count 15841a17fe3SRobert Watson * is protected by mac_policy_mtx; the list may be modified only 159a96acd1aSRobert Watson * while the busy count is 0, requiring that the lock be held to 160a96acd1aSRobert Watson * prevent new references to the list from being acquired. For almost 161a96acd1aSRobert Watson * all operations, incrementing the busy count is sufficient to 162a96acd1aSRobert Watson * guarantee consistency, as the list cannot be modified while the 163a96acd1aSRobert Watson * busy count is elevated. For a few special operations involving a 16441a17fe3SRobert Watson * change to the list of active policies, the mtx itself must be held. 16541a17fe3SRobert Watson * A condition variable, mac_policy_cv, is used to signal potential 16641a17fe3SRobert Watson * exclusive consumers that they should try to acquire the lock if a 16741a17fe3SRobert Watson * first attempt at exclusive access fails. 16895fab37eSRobert Watson */ 1690a05006dSRobert Watson #ifndef MAC_STATIC 17041a17fe3SRobert Watson static struct mtx mac_policy_mtx; 17141a17fe3SRobert Watson static struct cv mac_policy_cv; 17241a17fe3SRobert Watson static int mac_policy_count; 1730a05006dSRobert Watson #endif 174089c1bdaSRobert Watson struct mac_policy_list_head mac_policy_list; 175089c1bdaSRobert Watson struct mac_policy_list_head mac_static_policy_list; 176a96acd1aSRobert Watson 177a96acd1aSRobert Watson /* 17826306795SJohn Baldwin * We manually invoke WITNESS_WARN() to allow Witness to generate 179a96acd1aSRobert Watson * warnings even if we don't end up ever triggering the wait at 180a96acd1aSRobert Watson * run-time. The consumer of the exclusive interface must not hold 181a96acd1aSRobert Watson * any locks (other than potentially Giant) since we may sleep for 182a96acd1aSRobert Watson * long (potentially indefinite) periods of time waiting for the 183a96acd1aSRobert Watson * framework to become quiescent so that a policy list change may 184a96acd1aSRobert Watson * be made. 185a96acd1aSRobert Watson */ 186089c1bdaSRobert Watson void 18741a17fe3SRobert Watson mac_policy_grab_exclusive(void) 18841a17fe3SRobert Watson { 189c8e7bf92SRobert Watson 1900a05006dSRobert Watson #ifndef MAC_STATIC 19141a17fe3SRobert Watson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 19241a17fe3SRobert Watson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 19341a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 19441a17fe3SRobert Watson while (mac_policy_count != 0) 19541a17fe3SRobert Watson cv_wait(&mac_policy_cv, &mac_policy_mtx); 1960a05006dSRobert Watson #endif 19741a17fe3SRobert Watson } 19895fab37eSRobert Watson 199089c1bdaSRobert Watson void 20041a17fe3SRobert Watson mac_policy_assert_exclusive(void) 20141a17fe3SRobert Watson { 202c8e7bf92SRobert Watson 2030a05006dSRobert Watson #ifndef MAC_STATIC 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 21541a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 21641a17fe3SRobert Watson ("mac_policy_release_exclusive(): not exclusive")); 21741a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 21841a17fe3SRobert Watson cv_signal(&mac_policy_cv); 2190a05006dSRobert Watson #endif 22041a17fe3SRobert Watson } 22141a17fe3SRobert Watson 222089c1bdaSRobert Watson void 22341a17fe3SRobert Watson mac_policy_list_busy(void) 22441a17fe3SRobert Watson { 225c8e7bf92SRobert Watson 2260a05006dSRobert Watson #ifndef MAC_STATIC 22741a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 22841a17fe3SRobert Watson mac_policy_count++; 22941a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 2300a05006dSRobert Watson #endif 23141a17fe3SRobert Watson } 23241a17fe3SRobert Watson 233089c1bdaSRobert Watson int 23441a17fe3SRobert Watson mac_policy_list_conditional_busy(void) 23541a17fe3SRobert Watson { 2360a05006dSRobert Watson #ifndef MAC_STATIC 23741a17fe3SRobert Watson int ret; 23841a17fe3SRobert Watson 23941a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 24041a17fe3SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { 24141a17fe3SRobert Watson mac_policy_count++; 24241a17fe3SRobert Watson ret = 1; 24341a17fe3SRobert Watson } else 24441a17fe3SRobert Watson ret = 0; 24541a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 24641a17fe3SRobert Watson return (ret); 2470a05006dSRobert Watson #else 2480a05006dSRobert Watson return (1); 2490a05006dSRobert Watson #endif 25041a17fe3SRobert Watson } 25141a17fe3SRobert Watson 252089c1bdaSRobert Watson void 25341a17fe3SRobert Watson mac_policy_list_unbusy(void) 25441a17fe3SRobert Watson { 255c8e7bf92SRobert Watson 2560a05006dSRobert Watson #ifndef MAC_STATIC 25741a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 25841a17fe3SRobert Watson mac_policy_count--; 25941a17fe3SRobert Watson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 26041a17fe3SRobert Watson if (mac_policy_count == 0) 26141a17fe3SRobert Watson cv_signal(&mac_policy_cv); 26241a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 2630a05006dSRobert Watson #endif 26441a17fe3SRobert Watson } 26595fab37eSRobert Watson 26695fab37eSRobert Watson /* 26795fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 26895fab37eSRobert Watson */ 26995fab37eSRobert Watson static void 27095fab37eSRobert Watson mac_init(void) 27195fab37eSRobert Watson { 27295fab37eSRobert Watson 27341a17fe3SRobert Watson LIST_INIT(&mac_static_policy_list); 27495fab37eSRobert Watson LIST_INIT(&mac_policy_list); 275eca8a663SRobert Watson mac_labelzone_init(); 27641a17fe3SRobert Watson 2770a05006dSRobert Watson #ifndef MAC_STATIC 27841a17fe3SRobert Watson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 27941a17fe3SRobert Watson cv_init(&mac_policy_cv, "mac_policy_cv"); 2800a05006dSRobert Watson #endif 28195fab37eSRobert Watson } 28295fab37eSRobert Watson 28395fab37eSRobert Watson /* 28495fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 28595fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 28695fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 28795fab37eSRobert Watson */ 28895fab37eSRobert Watson static void 28995fab37eSRobert Watson mac_late_init(void) 29095fab37eSRobert Watson { 29195fab37eSRobert Watson 29295fab37eSRobert Watson mac_late = 1; 29395fab37eSRobert Watson } 29495fab37eSRobert Watson 29595fab37eSRobert Watson /* 296225bff6fSRobert Watson * After the policy list has changed, walk the list to update any global 29719c3e120SRobert Watson * flags. Currently, we support only one flag, and it's conditionally 29819c3e120SRobert Watson * defined; as a result, the entire function is conditional. Eventually, 29919c3e120SRobert Watson * the #else case might also iterate across the policies. 300225bff6fSRobert Watson */ 301225bff6fSRobert Watson static void 302225bff6fSRobert Watson mac_policy_updateflags(void) 303225bff6fSRobert Watson { 304225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 30519c3e120SRobert Watson struct mac_policy_conf *tmpc; 306225bff6fSRobert Watson int labelmbufs; 307225bff6fSRobert Watson 30841a17fe3SRobert Watson mac_policy_assert_exclusive(); 309225bff6fSRobert Watson 310225bff6fSRobert Watson labelmbufs = 0; 31141a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 31241a17fe3SRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 31341a17fe3SRobert Watson labelmbufs++; 31441a17fe3SRobert Watson } 315225bff6fSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 316225bff6fSRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 317225bff6fSRobert Watson labelmbufs++; 318225bff6fSRobert Watson } 319225bff6fSRobert Watson mac_labelmbufs = (labelmbufs != 0); 320225bff6fSRobert Watson #endif 321225bff6fSRobert Watson } 322225bff6fSRobert Watson 323225bff6fSRobert Watson /* 32495fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 32595fab37eSRobert Watson */ 32695fab37eSRobert Watson int 32795fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 32895fab37eSRobert Watson { 32995fab37eSRobert Watson struct mac_policy_conf *mpc; 33095fab37eSRobert Watson int error; 33195fab37eSRobert Watson 33295fab37eSRobert Watson error = 0; 33395fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 33495fab37eSRobert Watson 3350a05006dSRobert Watson #ifdef MAC_STATIC 3360a05006dSRobert Watson if (mac_late) { 3370a05006dSRobert Watson printf("mac_policy_modevent: MAC_STATIC and late\n"); 3380a05006dSRobert Watson return (EBUSY); 3390a05006dSRobert Watson } 3400a05006dSRobert Watson #endif 3410a05006dSRobert Watson 34295fab37eSRobert Watson switch (type) { 34395fab37eSRobert Watson case MOD_LOAD: 34495fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 34595fab37eSRobert Watson mac_late) { 34695fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 34795fab37eSRobert Watson "after booting\n", mpc->mpc_name); 34895fab37eSRobert Watson error = EBUSY; 34995fab37eSRobert Watson break; 35095fab37eSRobert Watson } 35195fab37eSRobert Watson error = mac_policy_register(mpc); 35295fab37eSRobert Watson break; 35395fab37eSRobert Watson case MOD_UNLOAD: 35495fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 35595fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 35695fab37eSRobert Watson != 0) 35795fab37eSRobert Watson error = mac_policy_unregister(mpc); 35895fab37eSRobert Watson else 35995fab37eSRobert Watson error = 0; 36095fab37eSRobert Watson break; 36195fab37eSRobert Watson default: 36295fab37eSRobert Watson break; 36395fab37eSRobert Watson } 36495fab37eSRobert Watson 36595fab37eSRobert Watson return (error); 36695fab37eSRobert Watson } 36795fab37eSRobert Watson 36895fab37eSRobert Watson static int 36995fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 37095fab37eSRobert Watson { 37195fab37eSRobert Watson struct mac_policy_conf *tmpc; 37241a17fe3SRobert Watson int error, slot, static_entry; 37395fab37eSRobert Watson 37441a17fe3SRobert Watson error = 0; 37541a17fe3SRobert Watson 37641a17fe3SRobert Watson /* 37741a17fe3SRobert Watson * We don't technically need exclusive access while !mac_late, 37841a17fe3SRobert Watson * but hold it for assertion consistency. 37941a17fe3SRobert Watson */ 38041a17fe3SRobert Watson mac_policy_grab_exclusive(); 38141a17fe3SRobert Watson 38241a17fe3SRobert Watson /* 38341a17fe3SRobert Watson * If the module can potentially be unloaded, or we're loading 38441a17fe3SRobert Watson * late, we have to stick it in the non-static list and pay 38541a17fe3SRobert Watson * an extra performance overhead. Otherwise, we can pay a 38641a17fe3SRobert Watson * light locking cost and stick it in the static list. 38741a17fe3SRobert Watson */ 38841a17fe3SRobert Watson static_entry = (!mac_late && 38941a17fe3SRobert Watson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 39041a17fe3SRobert Watson 39141a17fe3SRobert Watson if (static_entry) { 39241a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 39341a17fe3SRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 39441a17fe3SRobert Watson error = EEXIST; 39541a17fe3SRobert Watson goto out; 39641a17fe3SRobert Watson } 39741a17fe3SRobert Watson } 39841a17fe3SRobert Watson } else { 39995fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 40095fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 40141a17fe3SRobert Watson error = EEXIST; 40241a17fe3SRobert Watson goto out; 40341a17fe3SRobert Watson } 40495fab37eSRobert Watson } 40595fab37eSRobert Watson } 40695fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 407b2aef571SRobert Watson slot = ffs(mac_slot_offsets_free); 40895fab37eSRobert Watson if (slot == 0) { 40941a17fe3SRobert Watson error = ENOMEM; 41041a17fe3SRobert Watson goto out; 41195fab37eSRobert Watson } 41295fab37eSRobert Watson slot--; 413b2aef571SRobert Watson mac_slot_offsets_free &= ~(1 << slot); 41495fab37eSRobert Watson *mpc->mpc_field_off = slot; 41595fab37eSRobert Watson } 41695fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 41741a17fe3SRobert Watson 41841a17fe3SRobert Watson /* 41941a17fe3SRobert Watson * If we're loading a MAC module after the framework has 42041a17fe3SRobert Watson * initialized, it has to go into the dynamic list. If 42141a17fe3SRobert Watson * we're loading it before we've finished initializing, 42241a17fe3SRobert Watson * it can go into the static list with weaker locker 42341a17fe3SRobert Watson * requirements. 42441a17fe3SRobert Watson */ 42541a17fe3SRobert Watson if (static_entry) 42641a17fe3SRobert Watson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 42741a17fe3SRobert Watson else 42895fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 42995fab37eSRobert Watson 43095fab37eSRobert Watson /* Per-policy initialization. */ 43195fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 43295fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 433225bff6fSRobert Watson mac_policy_updateflags(); 43495fab37eSRobert Watson 43595fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 43695fab37eSRobert Watson mpc->mpc_name); 43795fab37eSRobert Watson 43841a17fe3SRobert Watson out: 43941a17fe3SRobert Watson mac_policy_release_exclusive(); 44041a17fe3SRobert Watson return (error); 44195fab37eSRobert Watson } 44295fab37eSRobert Watson 44395fab37eSRobert Watson static int 44495fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 44595fab37eSRobert Watson { 44695fab37eSRobert Watson 447ea599aa0SRobert Watson /* 448ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 449ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 450ea599aa0SRobert Watson * silently succeed. 451ea599aa0SRobert Watson */ 45241a17fe3SRobert Watson mac_policy_grab_exclusive(); 453ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 45441a17fe3SRobert Watson mac_policy_release_exclusive(); 455ea599aa0SRobert Watson return (0); 456ea599aa0SRobert Watson } 45795fab37eSRobert Watson #if 0 45895fab37eSRobert Watson /* 45995fab37eSRobert Watson * Don't allow unloading modules with private data. 46095fab37eSRobert Watson */ 461ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 462ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 46395fab37eSRobert Watson return (EBUSY); 464ea599aa0SRobert Watson } 46595fab37eSRobert Watson #endif 466ea599aa0SRobert Watson /* 467ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 468ea599aa0SRobert Watson * by its own definition. 469ea599aa0SRobert Watson */ 470ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 47141a17fe3SRobert Watson mac_policy_release_exclusive(); 47295fab37eSRobert Watson return (EBUSY); 473ea599aa0SRobert Watson } 47495fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 47595fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 47695fab37eSRobert Watson 47795fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 4789aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 479225bff6fSRobert Watson mac_policy_updateflags(); 48041a17fe3SRobert Watson 48141a17fe3SRobert Watson mac_policy_release_exclusive(); 482a96acd1aSRobert Watson 48395fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 48495fab37eSRobert Watson mpc->mpc_name); 48595fab37eSRobert Watson 48695fab37eSRobert Watson return (0); 48795fab37eSRobert Watson } 48895fab37eSRobert Watson 48995fab37eSRobert Watson /* 49095fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 49195fab37eSRobert Watson * value with the higher precedence. 49295fab37eSRobert Watson */ 4939e7bf51cSRobert Watson int 4949e7bf51cSRobert Watson mac_error_select(int error1, int error2) 49595fab37eSRobert Watson { 49695fab37eSRobert Watson 49795fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 49895fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 49995fab37eSRobert Watson return (EDEADLK); 50095fab37eSRobert Watson 50195fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 50295fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 50395fab37eSRobert Watson return (EINVAL); 50495fab37eSRobert Watson 50595fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 50695fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 50795fab37eSRobert Watson return (ESRCH); 50895fab37eSRobert Watson 50995fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 51095fab37eSRobert Watson return (ENOENT); 51195fab37eSRobert Watson 51295fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 51395fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 51495fab37eSRobert Watson return (EACCES); 51595fab37eSRobert Watson 51695fab37eSRobert Watson /* Precedence goes to privilege. */ 51795fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 51895fab37eSRobert Watson return (EPERM); 51995fab37eSRobert Watson 52095fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 52195fab37eSRobert Watson if (error1 != 0) 52295fab37eSRobert Watson return (error1); 52395fab37eSRobert Watson return (error2); 52495fab37eSRobert Watson } 52595fab37eSRobert Watson 5266fa0475dSRobert Watson void 52708bcdc58SRobert Watson mac_init_label(struct label *label) 52808bcdc58SRobert Watson { 52908bcdc58SRobert Watson 53008bcdc58SRobert Watson bzero(label, sizeof(*label)); 53108bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 53208bcdc58SRobert Watson } 53308bcdc58SRobert Watson 5346fa0475dSRobert Watson void 53508bcdc58SRobert Watson mac_destroy_label(struct label *label) 53608bcdc58SRobert Watson { 53708bcdc58SRobert Watson 53808bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 53908bcdc58SRobert Watson ("destroying uninitialized label")); 54008bcdc58SRobert Watson 54108bcdc58SRobert Watson bzero(label, sizeof(*label)); 54208bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 54308bcdc58SRobert Watson } 54408bcdc58SRobert Watson 5455e7ce478SRobert Watson int 546f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 547f7b951a8SRobert Watson { 548f7b951a8SRobert Watson 549cc7b13bfSRobert Watson if (mac->m_buflen < 0 || 550cc7b13bfSRobert Watson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 551f7b951a8SRobert Watson return (EINVAL); 552f7b951a8SRobert Watson 553f7b951a8SRobert Watson return (0); 554f7b951a8SRobert Watson } 555f7b951a8SRobert Watson 556f0ab0442SRobert Watson /* 557f0ab0442SRobert Watson * MPSAFE 558f0ab0442SRobert Watson */ 559f7b951a8SRobert Watson int 560f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 561f7b951a8SRobert Watson { 562f7b951a8SRobert Watson char *elements, *buffer; 563f7b951a8SRobert Watson struct mac mac; 564f7b951a8SRobert Watson struct proc *tproc; 565f7b951a8SRobert Watson struct ucred *tcred; 566f7b951a8SRobert Watson int error; 567f7b951a8SRobert Watson 568d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 569f7b951a8SRobert Watson if (error) 570f7b951a8SRobert Watson return (error); 571f7b951a8SRobert Watson 572f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 573f7b951a8SRobert Watson if (error) 574f7b951a8SRobert Watson return (error); 575f7b951a8SRobert Watson 576f7b951a8SRobert Watson tproc = pfind(uap->pid); 577f7b951a8SRobert Watson if (tproc == NULL) 578f7b951a8SRobert Watson return (ESRCH); 579f7b951a8SRobert Watson 580f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 581f7b951a8SRobert Watson error = p_cansee(td, tproc); 582f7b951a8SRobert Watson if (error == 0) 583f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 584f7b951a8SRobert Watson PROC_UNLOCK(tproc); 585f7b951a8SRobert Watson if (error) 586f7b951a8SRobert Watson return (error); 587f7b951a8SRobert Watson 588a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 589f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 590f7b951a8SRobert Watson if (error) { 591f7b951a8SRobert Watson free(elements, M_MACTEMP); 592f7b951a8SRobert Watson crfree(tcred); 593f7b951a8SRobert Watson return (error); 594f7b951a8SRobert Watson } 595f7b951a8SRobert Watson 596a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 597eca8a663SRobert Watson error = mac_externalize_cred_label(tcred->cr_label, elements, 59883b7b0edSRobert Watson buffer, mac.m_buflen); 599f7b951a8SRobert Watson if (error == 0) 600f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 601f7b951a8SRobert Watson 602f7b951a8SRobert Watson free(buffer, M_MACTEMP); 603f7b951a8SRobert Watson free(elements, M_MACTEMP); 604f7b951a8SRobert Watson crfree(tcred); 605f7b951a8SRobert Watson return (error); 606f7b951a8SRobert Watson } 607f7b951a8SRobert Watson 60895fab37eSRobert Watson /* 60995fab37eSRobert Watson * MPSAFE 61095fab37eSRobert Watson */ 61195fab37eSRobert Watson int 61295fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 61395fab37eSRobert Watson { 614f7b951a8SRobert Watson char *elements, *buffer; 615f7b951a8SRobert Watson struct mac mac; 61695fab37eSRobert Watson int error; 61795fab37eSRobert Watson 618f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 619f7b951a8SRobert Watson if (error) 620f7b951a8SRobert Watson return (error); 62195fab37eSRobert Watson 622f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 623f7b951a8SRobert Watson if (error) 624f7b951a8SRobert Watson return (error); 625f7b951a8SRobert Watson 626a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 627f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 628f7b951a8SRobert Watson if (error) { 629f7b951a8SRobert Watson free(elements, M_MACTEMP); 630f7b951a8SRobert Watson return (error); 631f7b951a8SRobert Watson } 632f7b951a8SRobert Watson 633a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 634eca8a663SRobert Watson error = mac_externalize_cred_label(td->td_ucred->cr_label, 63583b7b0edSRobert Watson elements, buffer, mac.m_buflen); 636f7b951a8SRobert Watson if (error == 0) 637f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 638f7b951a8SRobert Watson 639f7b951a8SRobert Watson free(buffer, M_MACTEMP); 640f7b951a8SRobert Watson free(elements, M_MACTEMP); 64195fab37eSRobert Watson return (error); 64295fab37eSRobert Watson } 64395fab37eSRobert Watson 64495fab37eSRobert Watson /* 64595fab37eSRobert Watson * MPSAFE 64695fab37eSRobert Watson */ 64795fab37eSRobert Watson int 64895fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 64995fab37eSRobert Watson { 65095fab37eSRobert Watson struct ucred *newcred, *oldcred; 651eca8a663SRobert Watson struct label *intlabel; 652f7b951a8SRobert Watson struct proc *p; 653f7b951a8SRobert Watson struct mac mac; 654f7b951a8SRobert Watson char *buffer; 65595fab37eSRobert Watson int error; 65695fab37eSRobert Watson 657f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 65895fab37eSRobert Watson if (error) 65995fab37eSRobert Watson return (error); 66095fab37eSRobert Watson 661f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 66295fab37eSRobert Watson if (error) 66395fab37eSRobert Watson return (error); 66495fab37eSRobert Watson 665a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 666f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 667f7b951a8SRobert Watson if (error) { 668f7b951a8SRobert Watson free(buffer, M_MACTEMP); 669f7b951a8SRobert Watson return (error); 670f7b951a8SRobert Watson } 671f7b951a8SRobert Watson 672eca8a663SRobert Watson intlabel = mac_cred_label_alloc(); 673eca8a663SRobert Watson error = mac_internalize_cred_label(intlabel, buffer); 674f7b951a8SRobert Watson free(buffer, M_MACTEMP); 675eca8a663SRobert Watson if (error) 676eca8a663SRobert Watson goto out; 677f7b951a8SRobert Watson 67895fab37eSRobert Watson newcred = crget(); 67995fab37eSRobert Watson 68095fab37eSRobert Watson p = td->td_proc; 68195fab37eSRobert Watson PROC_LOCK(p); 68295fab37eSRobert Watson oldcred = p->p_ucred; 68395fab37eSRobert Watson 684eca8a663SRobert Watson error = mac_check_cred_relabel(oldcred, intlabel); 68595fab37eSRobert Watson if (error) { 68695fab37eSRobert Watson PROC_UNLOCK(p); 68795fab37eSRobert Watson crfree(newcred); 688f7b951a8SRobert Watson goto out; 68995fab37eSRobert Watson } 69095fab37eSRobert Watson 69195fab37eSRobert Watson setsugid(p); 69295fab37eSRobert Watson crcopy(newcred, oldcred); 693eca8a663SRobert Watson mac_relabel_cred(newcred, intlabel); 69495fab37eSRobert Watson p->p_ucred = newcred; 695e5cb5e37SRobert Watson 696e5cb5e37SRobert Watson /* 697e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 698e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 699e5cb5e37SRobert Watson */ 700e5cb5e37SRobert Watson crhold(newcred); 70195fab37eSRobert Watson PROC_UNLOCK(p); 702e5cb5e37SRobert Watson 703f7b951a8SRobert Watson if (mac_enforce_vm) { 70416140035SRobert Watson mtx_lock(&Giant); 705e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 70616140035SRobert Watson mtx_unlock(&Giant); 707f7b951a8SRobert Watson } 708e5cb5e37SRobert Watson 709e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 71095fab37eSRobert Watson crfree(oldcred); 711f7b951a8SRobert Watson 712f7b951a8SRobert Watson out: 713eca8a663SRobert Watson mac_cred_label_free(intlabel); 714f7b951a8SRobert Watson return (error); 71595fab37eSRobert Watson } 71695fab37eSRobert Watson 71795fab37eSRobert Watson /* 71895fab37eSRobert Watson * MPSAFE 71995fab37eSRobert Watson */ 72095fab37eSRobert Watson int 72195fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 72295fab37eSRobert Watson { 723f7b951a8SRobert Watson char *elements, *buffer; 724eca8a663SRobert Watson struct label *intlabel; 72595fab37eSRobert Watson struct file *fp; 726f7b951a8SRobert Watson struct mac mac; 72795fab37eSRobert Watson struct vnode *vp; 72895fab37eSRobert Watson struct pipe *pipe; 729b0323ea3SRobert Watson struct socket *so; 730f7b951a8SRobert Watson short label_type; 73195fab37eSRobert Watson int error; 73295fab37eSRobert Watson 733f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 734f7b951a8SRobert Watson if (error) 735f7b951a8SRobert Watson return (error); 73695fab37eSRobert Watson 737f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 738f7b951a8SRobert Watson if (error) 739f7b951a8SRobert Watson return (error); 740f7b951a8SRobert Watson 741a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 742f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 743f7b951a8SRobert Watson if (error) { 744f7b951a8SRobert Watson free(elements, M_MACTEMP); 745f7b951a8SRobert Watson return (error); 746f7b951a8SRobert Watson } 747f7b951a8SRobert Watson 748a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 749d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 75095fab37eSRobert Watson if (error) 75195fab37eSRobert Watson goto out; 75295fab37eSRobert Watson 753f7b951a8SRobert Watson label_type = fp->f_type; 75495fab37eSRobert Watson switch (fp->f_type) { 75595fab37eSRobert Watson case DTYPE_FIFO: 75695fab37eSRobert Watson case DTYPE_VNODE: 7573b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 758eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 759f0ab0442SRobert Watson mtx_lock(&Giant); /* VFS */ 76095fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 761eca8a663SRobert Watson mac_copy_vnode_label(vp->v_label, intlabel); 76295fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 763f0ab0442SRobert Watson mtx_unlock(&Giant); /* VFS */ 764f0ab0442SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, 765f0ab0442SRobert Watson buffer, mac.m_buflen); 766f0ab0442SRobert Watson mac_vnode_label_free(intlabel); 76795fab37eSRobert Watson break; 768f0ab0442SRobert Watson 76995fab37eSRobert Watson case DTYPE_PIPE: 77048e3128bSMatthew Dillon pipe = fp->f_data; 771eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 772f7b951a8SRobert Watson PIPE_LOCK(pipe); 7734795b82cSRobert Watson mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 774f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 775eca8a663SRobert Watson error = mac_externalize_pipe_label(intlabel, elements, 77683b7b0edSRobert Watson buffer, mac.m_buflen); 777eca8a663SRobert Watson mac_pipe_label_free(intlabel); 778f7b951a8SRobert Watson break; 77995fab37eSRobert Watson 780b0323ea3SRobert Watson case DTYPE_SOCKET: 781b0323ea3SRobert Watson so = fp->f_data; 782b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 783b0323ea3SRobert Watson mtx_lock(&Giant); /* Sockets */ 784b0323ea3SRobert Watson /* XXX: Socket lock here. */ 785b0323ea3SRobert Watson mac_copy_socket_label(so->so_label, intlabel); 786b0323ea3SRobert Watson /* XXX: Socket unlock here. */ 787b0323ea3SRobert Watson mtx_unlock(&Giant); /* Sockets */ 788b0323ea3SRobert Watson error = mac_externalize_socket_label(intlabel, elements, 789b0323ea3SRobert Watson buffer, mac.m_buflen); 790b0323ea3SRobert Watson mac_socket_label_free(intlabel); 791b0323ea3SRobert Watson break; 792b0323ea3SRobert Watson 793f0ab0442SRobert Watson default: 794f0ab0442SRobert Watson error = EINVAL; 795f0ab0442SRobert Watson } 796f0ab0442SRobert Watson fdrop(fp, td); 79795fab37eSRobert Watson if (error == 0) 798f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 79995fab37eSRobert Watson 80095fab37eSRobert Watson out: 801f7b951a8SRobert Watson free(buffer, M_MACTEMP); 802f7b951a8SRobert Watson free(elements, M_MACTEMP); 80395fab37eSRobert Watson return (error); 80495fab37eSRobert Watson } 80595fab37eSRobert Watson 80695fab37eSRobert Watson /* 80795fab37eSRobert Watson * MPSAFE 80895fab37eSRobert Watson */ 80995fab37eSRobert Watson int 81095fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 81195fab37eSRobert Watson { 812f7b951a8SRobert Watson char *elements, *buffer; 81395fab37eSRobert Watson struct nameidata nd; 814eca8a663SRobert Watson struct label *intlabel; 815f7b951a8SRobert Watson struct mac mac; 81695fab37eSRobert Watson int error; 81795fab37eSRobert Watson 818f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 819f7b951a8SRobert Watson if (error) 820f7b951a8SRobert Watson return (error); 821f7b951a8SRobert Watson 822f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 823f7b951a8SRobert Watson if (error) 824f7b951a8SRobert Watson return (error); 825f7b951a8SRobert Watson 826a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 827f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 828f7b951a8SRobert Watson if (error) { 829f7b951a8SRobert Watson free(elements, M_MACTEMP); 830f7b951a8SRobert Watson return (error); 831f7b951a8SRobert Watson } 832f7b951a8SRobert Watson 833a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 834f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 835f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 836f7b951a8SRobert Watson td); 83795fab37eSRobert Watson error = namei(&nd); 83895fab37eSRobert Watson if (error) 83995fab37eSRobert Watson goto out; 84095fab37eSRobert Watson 841eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 842eca8a663SRobert Watson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 843eca8a663SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, buffer, 84483b7b0edSRobert Watson mac.m_buflen); 845f7b951a8SRobert Watson 84695fab37eSRobert Watson NDFREE(&nd, 0); 847eca8a663SRobert Watson mac_vnode_label_free(intlabel); 848f7b951a8SRobert Watson 849f7b951a8SRobert Watson if (error == 0) 850f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 851f7b951a8SRobert Watson 852f7b951a8SRobert Watson out: 853f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 854f7b951a8SRobert Watson 855f7b951a8SRobert Watson free(buffer, M_MACTEMP); 856f7b951a8SRobert Watson free(elements, M_MACTEMP); 857f7b951a8SRobert Watson 858f7b951a8SRobert Watson return (error); 859f7b951a8SRobert Watson } 860f7b951a8SRobert Watson 861f7b951a8SRobert Watson /* 862f7b951a8SRobert Watson * MPSAFE 863f7b951a8SRobert Watson */ 864f7b951a8SRobert Watson int 865f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 866f7b951a8SRobert Watson { 867f7b951a8SRobert Watson char *elements, *buffer; 868f7b951a8SRobert Watson struct nameidata nd; 869eca8a663SRobert Watson struct label *intlabel; 870f7b951a8SRobert Watson struct mac mac; 871f7b951a8SRobert Watson int error; 872f7b951a8SRobert Watson 873f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 874f7b951a8SRobert Watson if (error) 875f7b951a8SRobert Watson return (error); 876f7b951a8SRobert Watson 877f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 878f7b951a8SRobert Watson if (error) 879f7b951a8SRobert Watson return (error); 880f7b951a8SRobert Watson 881a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 882f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 883f7b951a8SRobert Watson if (error) { 884f7b951a8SRobert Watson free(elements, M_MACTEMP); 885f7b951a8SRobert Watson return (error); 886f7b951a8SRobert Watson } 887f7b951a8SRobert Watson 888a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 889f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 890f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 891f7b951a8SRobert Watson td); 892f7b951a8SRobert Watson error = namei(&nd); 89395fab37eSRobert Watson if (error) 89495fab37eSRobert Watson goto out; 89595fab37eSRobert Watson 896eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 897eca8a663SRobert Watson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 898eca8a663SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, buffer, 89983b7b0edSRobert Watson mac.m_buflen); 900f7b951a8SRobert Watson NDFREE(&nd, 0); 901eca8a663SRobert Watson mac_vnode_label_free(intlabel); 902f7b951a8SRobert Watson 903f7b951a8SRobert Watson if (error == 0) 904f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 90595fab37eSRobert Watson 90695fab37eSRobert Watson out: 907f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 908f7b951a8SRobert Watson 909f7b951a8SRobert Watson free(buffer, M_MACTEMP); 910f7b951a8SRobert Watson free(elements, M_MACTEMP); 911f7b951a8SRobert Watson 91295fab37eSRobert Watson return (error); 91395fab37eSRobert Watson } 91495fab37eSRobert Watson 91595fab37eSRobert Watson /* 91695fab37eSRobert Watson * MPSAFE 91795fab37eSRobert Watson */ 91895fab37eSRobert Watson int 91995fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 92095fab37eSRobert Watson { 921eca8a663SRobert Watson struct label *intlabel; 922f7b951a8SRobert Watson struct pipe *pipe; 923b0323ea3SRobert Watson struct socket *so; 924f7b951a8SRobert Watson struct file *fp; 92595fab37eSRobert Watson struct mount *mp; 92695fab37eSRobert Watson struct vnode *vp; 927f7b951a8SRobert Watson struct mac mac; 928f7b951a8SRobert Watson char *buffer; 92995fab37eSRobert Watson int error; 93095fab37eSRobert Watson 931f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 932f7b951a8SRobert Watson if (error) 933f7b951a8SRobert Watson return (error); 934f7b951a8SRobert Watson 935f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 936f7b951a8SRobert Watson if (error) 937f7b951a8SRobert Watson return (error); 938f7b951a8SRobert Watson 939a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 940f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 941f7b951a8SRobert Watson if (error) { 942f7b951a8SRobert Watson free(buffer, M_MACTEMP); 943f7b951a8SRobert Watson return (error); 944f7b951a8SRobert Watson } 945f7b951a8SRobert Watson 946d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 94795fab37eSRobert Watson if (error) 948f7b951a8SRobert Watson goto out; 94995fab37eSRobert Watson 95095fab37eSRobert Watson switch (fp->f_type) { 95195fab37eSRobert Watson case DTYPE_FIFO: 95295fab37eSRobert Watson case DTYPE_VNODE: 953eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 954eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 955f7b951a8SRobert Watson if (error) { 956eca8a663SRobert Watson mac_vnode_label_free(intlabel); 957f7b951a8SRobert Watson break; 958f7b951a8SRobert Watson } 9593b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 960f0ab0442SRobert Watson mtx_lock(&Giant); /* VFS */ 96195fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 962f7b951a8SRobert Watson if (error != 0) { 963f0ab0442SRobert Watson mtx_unlock(&Giant); /* VFS */ 964eca8a663SRobert Watson mac_vnode_label_free(intlabel); 96595fab37eSRobert Watson break; 966f7b951a8SRobert Watson } 96795fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 968eca8a663SRobert Watson error = vn_setlabel(vp, intlabel, td->td_ucred); 96995fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 97095fab37eSRobert Watson vn_finished_write(mp); 971f0ab0442SRobert Watson mtx_unlock(&Giant); /* VFS */ 972eca8a663SRobert Watson mac_vnode_label_free(intlabel); 97395fab37eSRobert Watson break; 974f7b951a8SRobert Watson 97595fab37eSRobert Watson case DTYPE_PIPE: 976eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 977eca8a663SRobert Watson error = mac_internalize_pipe_label(intlabel, buffer); 978f7b951a8SRobert Watson if (error == 0) { 97948e3128bSMatthew Dillon pipe = fp->f_data; 9801aa37f53SRobert Watson PIPE_LOCK(pipe); 9814795b82cSRobert Watson error = mac_pipe_label_set(td->td_ucred, 9824795b82cSRobert Watson pipe->pipe_pair, intlabel); 9831aa37f53SRobert Watson PIPE_UNLOCK(pipe); 984f7b951a8SRobert Watson } 985eca8a663SRobert Watson mac_pipe_label_free(intlabel); 98695fab37eSRobert Watson break; 987f7b951a8SRobert Watson 988b0323ea3SRobert Watson case DTYPE_SOCKET: 989b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 990b0323ea3SRobert Watson error = mac_internalize_socket_label(intlabel, buffer); 991b0323ea3SRobert Watson if (error == 0) { 992b0323ea3SRobert Watson so = fp->f_data; 993b0323ea3SRobert Watson mtx_lock(&Giant); /* Sockets */ 994b0323ea3SRobert Watson /* XXX: Socket lock here. */ 995b0323ea3SRobert Watson error = mac_socket_label_set(td->td_ucred, so, 996b0323ea3SRobert Watson intlabel); 997b0323ea3SRobert Watson /* XXX: Socket unlock here. */ 998b0323ea3SRobert Watson mtx_unlock(&Giant); /* Sockets */ 999b0323ea3SRobert Watson } 1000b0323ea3SRobert Watson mac_socket_label_free(intlabel); 1001b0323ea3SRobert Watson break; 1002b0323ea3SRobert Watson 100395fab37eSRobert Watson default: 100495fab37eSRobert Watson error = EINVAL; 100595fab37eSRobert Watson } 100695fab37eSRobert Watson fdrop(fp, td); 1007f7b951a8SRobert Watson out: 1008f7b951a8SRobert Watson free(buffer, M_MACTEMP); 100995fab37eSRobert Watson return (error); 101095fab37eSRobert Watson } 101195fab37eSRobert Watson 101295fab37eSRobert Watson /* 101395fab37eSRobert Watson * MPSAFE 101495fab37eSRobert Watson */ 101595fab37eSRobert Watson int 101695fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 101795fab37eSRobert Watson { 1018eca8a663SRobert Watson struct label *intlabel; 1019f7b951a8SRobert Watson struct nameidata nd; 102095fab37eSRobert Watson struct mount *mp; 1021f7b951a8SRobert Watson struct mac mac; 1022f7b951a8SRobert Watson char *buffer; 102395fab37eSRobert Watson int error; 102495fab37eSRobert Watson 1025f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 102695fab37eSRobert Watson if (error) 1027f7b951a8SRobert Watson return (error); 102895fab37eSRobert Watson 1029f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 103095fab37eSRobert Watson if (error) 1031f7b951a8SRobert Watson return (error); 103295fab37eSRobert Watson 1033a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1034f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1035f7b951a8SRobert Watson if (error) { 1036f7b951a8SRobert Watson free(buffer, M_MACTEMP); 103795fab37eSRobert Watson return (error); 103895fab37eSRobert Watson } 103995fab37eSRobert Watson 1040eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 1041eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 1042f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1043eca8a663SRobert Watson if (error) 1044eca8a663SRobert Watson goto out; 1045f7b951a8SRobert Watson 1046f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 1047f7b951a8SRobert Watson 1048f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 1049f7b951a8SRobert Watson td); 1050f7b951a8SRobert Watson error = namei(&nd); 1051f7b951a8SRobert Watson if (error == 0) { 1052f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1053f7b951a8SRobert Watson if (error == 0) 1054eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 1055f7b951a8SRobert Watson td->td_ucred); 1056f7b951a8SRobert Watson vn_finished_write(mp); 1057f7b951a8SRobert Watson } 1058f7b951a8SRobert Watson 1059f7b951a8SRobert Watson NDFREE(&nd, 0); 1060f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 1061eca8a663SRobert Watson out: 1062eca8a663SRobert Watson mac_vnode_label_free(intlabel); 1063f7b951a8SRobert Watson return (error); 1064f7b951a8SRobert Watson } 1065f7b951a8SRobert Watson 1066f7b951a8SRobert Watson /* 1067f7b951a8SRobert Watson * MPSAFE 1068f7b951a8SRobert Watson */ 1069f7b951a8SRobert Watson int 1070f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1071f7b951a8SRobert Watson { 1072eca8a663SRobert Watson struct label *intlabel; 1073f7b951a8SRobert Watson struct nameidata nd; 1074f7b951a8SRobert Watson struct mount *mp; 1075f7b951a8SRobert Watson struct mac mac; 1076f7b951a8SRobert Watson char *buffer; 1077f7b951a8SRobert Watson int error; 1078f7b951a8SRobert Watson 1079f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1080f7b951a8SRobert Watson if (error) 1081f7b951a8SRobert Watson return (error); 1082f7b951a8SRobert Watson 1083f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 1084f7b951a8SRobert Watson if (error) 1085f7b951a8SRobert Watson return (error); 1086f7b951a8SRobert Watson 1087a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1088f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1089f7b951a8SRobert Watson if (error) { 1090f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1091f7b951a8SRobert Watson return (error); 1092f7b951a8SRobert Watson } 1093f7b951a8SRobert Watson 1094eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 1095eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 1096f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1097eca8a663SRobert Watson if (error) 1098eca8a663SRobert Watson goto out; 1099f7b951a8SRobert Watson 1100f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 1101f7b951a8SRobert Watson 1102f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 1103f7b951a8SRobert Watson td); 1104f7b951a8SRobert Watson error = namei(&nd); 1105f7b951a8SRobert Watson if (error == 0) { 1106f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1107f7b951a8SRobert Watson if (error == 0) 1108eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 1109f7b951a8SRobert Watson td->td_ucred); 1110f7b951a8SRobert Watson vn_finished_write(mp); 1111f7b951a8SRobert Watson } 1112f7b951a8SRobert Watson 1113f7b951a8SRobert Watson NDFREE(&nd, 0); 1114f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 1115eca8a663SRobert Watson out: 1116eca8a663SRobert Watson mac_vnode_label_free(intlabel); 1117f7b951a8SRobert Watson return (error); 1118f7b951a8SRobert Watson } 1119f7b951a8SRobert Watson 1120f7b951a8SRobert Watson /* 1121f7b951a8SRobert Watson * MPSAFE 1122f7b951a8SRobert Watson */ 112327f2eac7SRobert Watson int 112427f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 112527f2eac7SRobert Watson { 112627f2eac7SRobert Watson struct mac_policy_conf *mpc; 112727f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 112841a17fe3SRobert Watson int entrycount, error; 112927f2eac7SRobert Watson 1130d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 113127f2eac7SRobert Watson if (error) 113227f2eac7SRobert Watson return (error); 113327f2eac7SRobert Watson 113427f2eac7SRobert Watson error = ENOSYS; 1135a6a65b05SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 113627f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 113727f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 113827f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 1139d1e405c5SAlfred Perlstein uap->call, uap->arg); 114027f2eac7SRobert Watson goto out; 114127f2eac7SRobert Watson } 114227f2eac7SRobert Watson } 114327f2eac7SRobert Watson 114441a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 114541a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 114641a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 114741a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 114841a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 114941a17fe3SRobert Watson uap->call, uap->arg); 115041a17fe3SRobert Watson break; 115141a17fe3SRobert Watson } 115241a17fe3SRobert Watson } 115341a17fe3SRobert Watson mac_policy_list_unbusy(); 115441a17fe3SRobert Watson } 115527f2eac7SRobert Watson out: 115627f2eac7SRobert Watson return (error); 115727f2eac7SRobert Watson } 115827f2eac7SRobert Watson 115995fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 116095fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 116195fab37eSRobert Watson 116295fab37eSRobert Watson #else /* !MAC */ 11637bc82500SRobert Watson 11647bc82500SRobert Watson int 1165f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1166f7b951a8SRobert Watson { 1167f7b951a8SRobert Watson 1168f7b951a8SRobert Watson return (ENOSYS); 1169f7b951a8SRobert Watson } 1170f7b951a8SRobert Watson 1171f7b951a8SRobert Watson int 11727bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 11737bc82500SRobert Watson { 11747bc82500SRobert Watson 11757bc82500SRobert Watson return (ENOSYS); 11767bc82500SRobert Watson } 11777bc82500SRobert Watson 11787bc82500SRobert Watson int 11797bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 11807bc82500SRobert Watson { 11817bc82500SRobert Watson 11827bc82500SRobert Watson return (ENOSYS); 11837bc82500SRobert Watson } 11847bc82500SRobert Watson 11857bc82500SRobert Watson int 11867bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 11877bc82500SRobert Watson { 11887bc82500SRobert Watson 11897bc82500SRobert Watson return (ENOSYS); 11907bc82500SRobert Watson } 11917bc82500SRobert Watson 11927bc82500SRobert Watson int 11937bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 11947bc82500SRobert Watson { 11957bc82500SRobert Watson 11967bc82500SRobert Watson return (ENOSYS); 11977bc82500SRobert Watson } 11987bc82500SRobert Watson 11997bc82500SRobert Watson int 1200f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1201f7b951a8SRobert Watson { 1202f7b951a8SRobert Watson 1203f7b951a8SRobert Watson return (ENOSYS); 1204f7b951a8SRobert Watson } 1205f7b951a8SRobert Watson 1206f7b951a8SRobert Watson int 12077bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 12087bc82500SRobert Watson { 12097bc82500SRobert Watson 12107bc82500SRobert Watson return (ENOSYS); 12117bc82500SRobert Watson } 12127bc82500SRobert Watson 12137bc82500SRobert Watson int 12147bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 12157bc82500SRobert Watson { 12167bc82500SRobert Watson 12177bc82500SRobert Watson return (ENOSYS); 12187bc82500SRobert Watson } 121995fab37eSRobert Watson 122027f2eac7SRobert Watson int 1221f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1222f7b951a8SRobert Watson { 1223f7b951a8SRobert Watson 1224f7b951a8SRobert Watson return (ENOSYS); 1225f7b951a8SRobert Watson } 1226f7b951a8SRobert Watson 1227f7b951a8SRobert Watson int 122827f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 122927f2eac7SRobert Watson { 123027f2eac7SRobert Watson 123127f2eac7SRobert Watson return (ENOSYS); 123227f2eac7SRobert Watson } 123327f2eac7SRobert Watson 1234f7b951a8SRobert Watson #endif 1235