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. 549bb6870SRobert Watson * Copyright (c) 2005 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" 53328048bcSPoul-Henning Kamp #include "opt_devfs.h" 54f9d0d524SRobert Watson 557bc82500SRobert Watson #include <sys/param.h> 56a96acd1aSRobert Watson #include <sys/condvar.h> 5795fab37eSRobert Watson #include <sys/extattr.h> 58670cb89bSRobert Watson #include <sys/imgact.h> 5995fab37eSRobert Watson #include <sys/kernel.h> 6095fab37eSRobert Watson #include <sys/lock.h> 61b656366bSBruce Evans #include <sys/malloc.h> 6295fab37eSRobert Watson #include <sys/mutex.h> 6395fab37eSRobert Watson #include <sys/mac.h> 647ba28492SRobert Watson #include <sys/module.h> 6595fab37eSRobert Watson #include <sys/proc.h> 66f51e5803SRobert Watson #include <sys/sbuf.h> 6795fab37eSRobert Watson #include <sys/systm.h> 687bc82500SRobert Watson #include <sys/sysproto.h> 697bc82500SRobert Watson #include <sys/sysent.h> 7095fab37eSRobert Watson #include <sys/vnode.h> 7195fab37eSRobert Watson #include <sys/mount.h> 7295fab37eSRobert Watson #include <sys/file.h> 7395fab37eSRobert Watson #include <sys/namei.h> 7495fab37eSRobert Watson #include <sys/socket.h> 7595fab37eSRobert Watson #include <sys/pipe.h> 7695fab37eSRobert Watson #include <sys/socketvar.h> 7795fab37eSRobert Watson #include <sys/sysctl.h> 7895fab37eSRobert Watson 7995fab37eSRobert Watson #include <vm/vm.h> 8095fab37eSRobert Watson #include <vm/pmap.h> 8195fab37eSRobert Watson #include <vm/vm_map.h> 8295fab37eSRobert Watson #include <vm/vm_object.h> 8395fab37eSRobert Watson 8495fab37eSRobert Watson #include <sys/mac_policy.h> 8595fab37eSRobert Watson 8695fab37eSRobert Watson #include <fs/devfs/devfs.h> 8795fab37eSRobert Watson 8895fab37eSRobert Watson #include <net/bpfdesc.h> 8995fab37eSRobert Watson #include <net/if.h> 9095fab37eSRobert Watson #include <net/if_var.h> 9195fab37eSRobert Watson 9295fab37eSRobert Watson #include <netinet/in.h> 9395fab37eSRobert Watson #include <netinet/ip_var.h> 9495fab37eSRobert Watson 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 140f050add5SRobert Watson #ifdef MAC_DEBUG 1416be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1426be0c25eSRobert Watson "TrustedBSD MAC debug info"); 143b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 144b2f0927aSRobert Watson "TrustedBSD MAC object counters"); 145b2f0927aSRobert Watson 1466fa0475dSRobert Watson static unsigned int nmactemp; 147b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 14895fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 149f050add5SRobert Watson #endif 15095fab37eSRobert Watson 15195fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 15295fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 15395fab37eSRobert Watson 154f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 15595fab37eSRobert Watson 15695fab37eSRobert Watson /* 15741a17fe3SRobert Watson * mac_static_policy_list holds a list of policy modules that are not 15841a17fe3SRobert Watson * loaded while the system is "live", and cannot be unloaded. These 15941a17fe3SRobert Watson * policies can be invoked without holding the busy count. 16041a17fe3SRobert Watson * 16141a17fe3SRobert Watson * mac_policy_list stores the list of dynamic policies. A busy count is 162a96acd1aSRobert Watson * maintained for the list, stored in mac_policy_busy. The busy count 16341a17fe3SRobert Watson * is protected by mac_policy_mtx; the list may be modified only 164a96acd1aSRobert Watson * while the busy count is 0, requiring that the lock be held to 165a96acd1aSRobert Watson * prevent new references to the list from being acquired. For almost 166a96acd1aSRobert Watson * all operations, incrementing the busy count is sufficient to 167a96acd1aSRobert Watson * guarantee consistency, as the list cannot be modified while the 168a96acd1aSRobert Watson * busy count is elevated. For a few special operations involving a 16941a17fe3SRobert Watson * change to the list of active policies, the mtx itself must be held. 17041a17fe3SRobert Watson * A condition variable, mac_policy_cv, is used to signal potential 17141a17fe3SRobert Watson * exclusive consumers that they should try to acquire the lock if a 17241a17fe3SRobert Watson * first attempt at exclusive access fails. 17395fab37eSRobert Watson */ 1740a05006dSRobert Watson #ifndef MAC_STATIC 17541a17fe3SRobert Watson static struct mtx mac_policy_mtx; 17641a17fe3SRobert Watson static struct cv mac_policy_cv; 17741a17fe3SRobert Watson static int mac_policy_count; 1780a05006dSRobert Watson #endif 179089c1bdaSRobert Watson struct mac_policy_list_head mac_policy_list; 180089c1bdaSRobert Watson struct mac_policy_list_head mac_static_policy_list; 181a96acd1aSRobert Watson 182a96acd1aSRobert Watson /* 18326306795SJohn Baldwin * We manually invoke WITNESS_WARN() to allow Witness to generate 184a96acd1aSRobert Watson * warnings even if we don't end up ever triggering the wait at 185a96acd1aSRobert Watson * run-time. The consumer of the exclusive interface must not hold 186a96acd1aSRobert Watson * any locks (other than potentially Giant) since we may sleep for 187a96acd1aSRobert Watson * long (potentially indefinite) periods of time waiting for the 188a96acd1aSRobert Watson * framework to become quiescent so that a policy list change may 189a96acd1aSRobert Watson * be made. 190a96acd1aSRobert Watson */ 191089c1bdaSRobert Watson void 19241a17fe3SRobert Watson mac_policy_grab_exclusive(void) 19341a17fe3SRobert Watson { 194c8e7bf92SRobert Watson 1950a05006dSRobert Watson #ifndef MAC_STATIC 1961e4cadcbSRobert Watson if (!mac_late) 1971e4cadcbSRobert Watson return; 1981e4cadcbSRobert Watson 19941a17fe3SRobert Watson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 20041a17fe3SRobert Watson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 20141a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 20241a17fe3SRobert Watson while (mac_policy_count != 0) 20341a17fe3SRobert Watson cv_wait(&mac_policy_cv, &mac_policy_mtx); 2040a05006dSRobert Watson #endif 20541a17fe3SRobert Watson } 20695fab37eSRobert Watson 207089c1bdaSRobert Watson void 20841a17fe3SRobert Watson mac_policy_assert_exclusive(void) 20941a17fe3SRobert Watson { 210c8e7bf92SRobert Watson 2110a05006dSRobert Watson #ifndef MAC_STATIC 2121e4cadcbSRobert Watson if (!mac_late) 2131e4cadcbSRobert Watson return; 2141e4cadcbSRobert Watson 21541a17fe3SRobert Watson mtx_assert(&mac_policy_mtx, MA_OWNED); 21641a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 21741a17fe3SRobert Watson ("mac_policy_assert_exclusive(): not exclusive")); 2180a05006dSRobert Watson #endif 21941a17fe3SRobert Watson } 220225bff6fSRobert Watson 221089c1bdaSRobert Watson void 22241a17fe3SRobert Watson mac_policy_release_exclusive(void) 22341a17fe3SRobert Watson { 22495fab37eSRobert Watson 2250a05006dSRobert Watson #ifndef MAC_STATIC 2261e4cadcbSRobert Watson if (!mac_late) 2271e4cadcbSRobert Watson return; 2281e4cadcbSRobert Watson 22941a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 23041a17fe3SRobert Watson ("mac_policy_release_exclusive(): not exclusive")); 23141a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 23241a17fe3SRobert Watson cv_signal(&mac_policy_cv); 2330a05006dSRobert Watson #endif 23441a17fe3SRobert Watson } 23541a17fe3SRobert Watson 236089c1bdaSRobert Watson void 23741a17fe3SRobert Watson mac_policy_list_busy(void) 23841a17fe3SRobert Watson { 239c8e7bf92SRobert Watson 2400a05006dSRobert Watson #ifndef MAC_STATIC 2411e4cadcbSRobert Watson if (!mac_late) 2421e4cadcbSRobert Watson return; 2431e4cadcbSRobert Watson 24441a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 24541a17fe3SRobert Watson mac_policy_count++; 24641a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 2470a05006dSRobert Watson #endif 24841a17fe3SRobert Watson } 24941a17fe3SRobert Watson 250089c1bdaSRobert Watson int 25141a17fe3SRobert Watson mac_policy_list_conditional_busy(void) 25241a17fe3SRobert Watson { 2530a05006dSRobert Watson #ifndef MAC_STATIC 25441a17fe3SRobert Watson int ret; 25541a17fe3SRobert Watson 2561e4cadcbSRobert Watson if (!mac_late) 2571e4cadcbSRobert Watson return (1); 2581e4cadcbSRobert Watson 25941a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 26041a17fe3SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { 26141a17fe3SRobert Watson mac_policy_count++; 26241a17fe3SRobert Watson ret = 1; 26341a17fe3SRobert Watson } else 26441a17fe3SRobert Watson ret = 0; 26541a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 26641a17fe3SRobert Watson return (ret); 2670a05006dSRobert Watson #else 2681e4cadcbSRobert Watson if (!mac_late) 2691e4cadcbSRobert Watson return (1); 2701e4cadcbSRobert Watson 2710a05006dSRobert Watson return (1); 2720a05006dSRobert Watson #endif 27341a17fe3SRobert Watson } 27441a17fe3SRobert Watson 275089c1bdaSRobert Watson void 27641a17fe3SRobert Watson mac_policy_list_unbusy(void) 27741a17fe3SRobert Watson { 278c8e7bf92SRobert Watson 2790a05006dSRobert Watson #ifndef MAC_STATIC 2801e4cadcbSRobert Watson if (!mac_late) 2811e4cadcbSRobert Watson return; 2821e4cadcbSRobert Watson 28341a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 28441a17fe3SRobert Watson mac_policy_count--; 28541a17fe3SRobert Watson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 28641a17fe3SRobert Watson if (mac_policy_count == 0) 28741a17fe3SRobert Watson cv_signal(&mac_policy_cv); 28841a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 2890a05006dSRobert Watson #endif 29041a17fe3SRobert Watson } 29195fab37eSRobert Watson 29295fab37eSRobert Watson /* 29395fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 29495fab37eSRobert Watson */ 29595fab37eSRobert Watson static void 29695fab37eSRobert Watson mac_init(void) 29795fab37eSRobert Watson { 29895fab37eSRobert Watson 29941a17fe3SRobert Watson LIST_INIT(&mac_static_policy_list); 30095fab37eSRobert Watson LIST_INIT(&mac_policy_list); 301eca8a663SRobert Watson mac_labelzone_init(); 30241a17fe3SRobert Watson 3030a05006dSRobert Watson #ifndef MAC_STATIC 30441a17fe3SRobert Watson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 30541a17fe3SRobert Watson cv_init(&mac_policy_cv, "mac_policy_cv"); 3060a05006dSRobert Watson #endif 30795fab37eSRobert Watson } 30895fab37eSRobert Watson 30995fab37eSRobert Watson /* 31095fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 31195fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 31295fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 31395fab37eSRobert Watson */ 31495fab37eSRobert Watson static void 31595fab37eSRobert Watson mac_late_init(void) 31695fab37eSRobert Watson { 31795fab37eSRobert Watson 31895fab37eSRobert Watson mac_late = 1; 31995fab37eSRobert Watson } 32095fab37eSRobert Watson 32195fab37eSRobert Watson /* 322225bff6fSRobert Watson * After the policy list has changed, walk the list to update any global 32319c3e120SRobert Watson * flags. Currently, we support only one flag, and it's conditionally 32419c3e120SRobert Watson * defined; as a result, the entire function is conditional. Eventually, 32519c3e120SRobert Watson * the #else case might also iterate across the policies. 326225bff6fSRobert Watson */ 327225bff6fSRobert Watson static void 328225bff6fSRobert Watson mac_policy_updateflags(void) 329225bff6fSRobert Watson { 330225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 33119c3e120SRobert Watson struct mac_policy_conf *tmpc; 332225bff6fSRobert Watson int labelmbufs; 333225bff6fSRobert Watson 33441a17fe3SRobert Watson mac_policy_assert_exclusive(); 335225bff6fSRobert Watson 336225bff6fSRobert Watson labelmbufs = 0; 33741a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 33841a17fe3SRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 33941a17fe3SRobert Watson labelmbufs++; 34041a17fe3SRobert Watson } 341225bff6fSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 342225bff6fSRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 343225bff6fSRobert Watson labelmbufs++; 344225bff6fSRobert Watson } 345225bff6fSRobert Watson mac_labelmbufs = (labelmbufs != 0); 346225bff6fSRobert Watson #endif 347225bff6fSRobert Watson } 348225bff6fSRobert Watson 349225bff6fSRobert Watson /* 35095fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 35195fab37eSRobert Watson */ 35295fab37eSRobert Watson int 35395fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 35495fab37eSRobert Watson { 35595fab37eSRobert Watson struct mac_policy_conf *mpc; 35695fab37eSRobert Watson int error; 35795fab37eSRobert Watson 35895fab37eSRobert Watson error = 0; 35995fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 36095fab37eSRobert Watson 3610a05006dSRobert Watson #ifdef MAC_STATIC 3620a05006dSRobert Watson if (mac_late) { 3630a05006dSRobert Watson printf("mac_policy_modevent: MAC_STATIC and late\n"); 3640a05006dSRobert Watson return (EBUSY); 3650a05006dSRobert Watson } 3660a05006dSRobert Watson #endif 3670a05006dSRobert Watson 36895fab37eSRobert Watson switch (type) { 36995fab37eSRobert Watson case MOD_LOAD: 37095fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 37195fab37eSRobert Watson mac_late) { 37295fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 37395fab37eSRobert Watson "after booting\n", mpc->mpc_name); 37495fab37eSRobert Watson error = EBUSY; 37595fab37eSRobert Watson break; 37695fab37eSRobert Watson } 37795fab37eSRobert Watson error = mac_policy_register(mpc); 37895fab37eSRobert Watson break; 37995fab37eSRobert Watson case MOD_UNLOAD: 38095fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 38195fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 38295fab37eSRobert Watson != 0) 38395fab37eSRobert Watson error = mac_policy_unregister(mpc); 38495fab37eSRobert Watson else 38595fab37eSRobert Watson error = 0; 38695fab37eSRobert Watson break; 38795fab37eSRobert Watson default: 3883e019deaSPoul-Henning Kamp error = EOPNOTSUPP; 38995fab37eSRobert Watson break; 39095fab37eSRobert Watson } 39195fab37eSRobert Watson 39295fab37eSRobert Watson return (error); 39395fab37eSRobert Watson } 39495fab37eSRobert Watson 39595fab37eSRobert Watson static int 39695fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 39795fab37eSRobert Watson { 39895fab37eSRobert Watson struct mac_policy_conf *tmpc; 39941a17fe3SRobert Watson int error, slot, static_entry; 40095fab37eSRobert Watson 40141a17fe3SRobert Watson error = 0; 40241a17fe3SRobert Watson 40341a17fe3SRobert Watson /* 40441a17fe3SRobert Watson * We don't technically need exclusive access while !mac_late, 40541a17fe3SRobert Watson * but hold it for assertion consistency. 40641a17fe3SRobert Watson */ 40741a17fe3SRobert Watson mac_policy_grab_exclusive(); 40841a17fe3SRobert Watson 40941a17fe3SRobert Watson /* 41041a17fe3SRobert Watson * If the module can potentially be unloaded, or we're loading 41141a17fe3SRobert Watson * late, we have to stick it in the non-static list and pay 41241a17fe3SRobert Watson * an extra performance overhead. Otherwise, we can pay a 41341a17fe3SRobert Watson * light locking cost and stick it in the static list. 41441a17fe3SRobert Watson */ 41541a17fe3SRobert Watson static_entry = (!mac_late && 41641a17fe3SRobert Watson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 41741a17fe3SRobert Watson 41841a17fe3SRobert Watson if (static_entry) { 41941a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 42041a17fe3SRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 42141a17fe3SRobert Watson error = EEXIST; 42241a17fe3SRobert Watson goto out; 42341a17fe3SRobert Watson } 42441a17fe3SRobert Watson } 42541a17fe3SRobert Watson } else { 42695fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 42795fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 42841a17fe3SRobert Watson error = EEXIST; 42941a17fe3SRobert Watson goto out; 43041a17fe3SRobert Watson } 43195fab37eSRobert Watson } 43295fab37eSRobert Watson } 43395fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 434b2aef571SRobert Watson slot = ffs(mac_slot_offsets_free); 43595fab37eSRobert Watson if (slot == 0) { 43641a17fe3SRobert Watson error = ENOMEM; 43741a17fe3SRobert Watson goto out; 43895fab37eSRobert Watson } 43995fab37eSRobert Watson slot--; 440b2aef571SRobert Watson mac_slot_offsets_free &= ~(1 << slot); 44195fab37eSRobert Watson *mpc->mpc_field_off = slot; 44295fab37eSRobert Watson } 44395fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 44441a17fe3SRobert Watson 44541a17fe3SRobert Watson /* 44641a17fe3SRobert Watson * If we're loading a MAC module after the framework has 44741a17fe3SRobert Watson * initialized, it has to go into the dynamic list. If 44841a17fe3SRobert Watson * we're loading it before we've finished initializing, 44941a17fe3SRobert Watson * it can go into the static list with weaker locker 45041a17fe3SRobert Watson * requirements. 45141a17fe3SRobert Watson */ 45241a17fe3SRobert Watson if (static_entry) 45341a17fe3SRobert Watson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 45441a17fe3SRobert Watson else 45595fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 45695fab37eSRobert Watson 45795fab37eSRobert Watson /* Per-policy initialization. */ 45895fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 45995fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 460225bff6fSRobert Watson mac_policy_updateflags(); 46195fab37eSRobert Watson 46295fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 46395fab37eSRobert Watson mpc->mpc_name); 46495fab37eSRobert Watson 46541a17fe3SRobert Watson out: 46641a17fe3SRobert Watson mac_policy_release_exclusive(); 46741a17fe3SRobert Watson return (error); 46895fab37eSRobert Watson } 46995fab37eSRobert Watson 47095fab37eSRobert Watson static int 47195fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 47295fab37eSRobert Watson { 47395fab37eSRobert Watson 474ea599aa0SRobert Watson /* 475ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 476ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 477ea599aa0SRobert Watson * silently succeed. 478ea599aa0SRobert Watson */ 47941a17fe3SRobert Watson mac_policy_grab_exclusive(); 480ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 48141a17fe3SRobert Watson mac_policy_release_exclusive(); 482ea599aa0SRobert Watson return (0); 483ea599aa0SRobert Watson } 48495fab37eSRobert Watson #if 0 48595fab37eSRobert Watson /* 48695fab37eSRobert Watson * Don't allow unloading modules with private data. 48795fab37eSRobert Watson */ 488ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 489ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 49095fab37eSRobert Watson return (EBUSY); 491ea599aa0SRobert Watson } 49295fab37eSRobert Watson #endif 493ea599aa0SRobert Watson /* 494ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 495ea599aa0SRobert Watson * by its own definition. 496ea599aa0SRobert Watson */ 497ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 49841a17fe3SRobert Watson mac_policy_release_exclusive(); 49995fab37eSRobert Watson return (EBUSY); 500ea599aa0SRobert Watson } 50195fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 50295fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 50395fab37eSRobert Watson 50495fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 5059aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 506225bff6fSRobert Watson mac_policy_updateflags(); 50741a17fe3SRobert Watson 50841a17fe3SRobert Watson mac_policy_release_exclusive(); 509a96acd1aSRobert Watson 51095fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 51195fab37eSRobert Watson mpc->mpc_name); 51295fab37eSRobert Watson 51395fab37eSRobert Watson return (0); 51495fab37eSRobert Watson } 51595fab37eSRobert Watson 51695fab37eSRobert Watson /* 51795fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 51895fab37eSRobert Watson * value with the higher precedence. 51995fab37eSRobert Watson */ 5209e7bf51cSRobert Watson int 5219e7bf51cSRobert Watson mac_error_select(int error1, int error2) 52295fab37eSRobert Watson { 52395fab37eSRobert Watson 52495fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 52595fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 52695fab37eSRobert Watson return (EDEADLK); 52795fab37eSRobert Watson 52895fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 52995fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 53095fab37eSRobert Watson return (EINVAL); 53195fab37eSRobert Watson 53295fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 53395fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 53495fab37eSRobert Watson return (ESRCH); 53595fab37eSRobert Watson 53695fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 53795fab37eSRobert Watson return (ENOENT); 53895fab37eSRobert Watson 53995fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 54095fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 54195fab37eSRobert Watson return (EACCES); 54295fab37eSRobert Watson 54395fab37eSRobert Watson /* Precedence goes to privilege. */ 54495fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 54595fab37eSRobert Watson return (EPERM); 54695fab37eSRobert Watson 54795fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 54895fab37eSRobert Watson if (error1 != 0) 54995fab37eSRobert Watson return (error1); 55095fab37eSRobert Watson return (error2); 55195fab37eSRobert Watson } 55295fab37eSRobert Watson 5536fa0475dSRobert Watson void 55408bcdc58SRobert Watson mac_init_label(struct label *label) 55508bcdc58SRobert Watson { 55608bcdc58SRobert Watson 55708bcdc58SRobert Watson bzero(label, sizeof(*label)); 55808bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 55908bcdc58SRobert Watson } 56008bcdc58SRobert Watson 5616fa0475dSRobert Watson void 56208bcdc58SRobert Watson mac_destroy_label(struct label *label) 56308bcdc58SRobert Watson { 56408bcdc58SRobert Watson 56508bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 56608bcdc58SRobert Watson ("destroying uninitialized label")); 56708bcdc58SRobert Watson 56808bcdc58SRobert Watson bzero(label, sizeof(*label)); 56908bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 57008bcdc58SRobert Watson } 57108bcdc58SRobert Watson 5725e7ce478SRobert Watson int 573f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 574f7b951a8SRobert Watson { 575f7b951a8SRobert Watson 576cc7b13bfSRobert Watson if (mac->m_buflen < 0 || 577cc7b13bfSRobert Watson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 578f7b951a8SRobert Watson return (EINVAL); 579f7b951a8SRobert Watson 580f7b951a8SRobert Watson return (0); 581f7b951a8SRobert Watson } 582f7b951a8SRobert Watson 583f0ab0442SRobert Watson /* 584f0ab0442SRobert Watson * MPSAFE 585f0ab0442SRobert Watson */ 586f7b951a8SRobert Watson int 587f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 588f7b951a8SRobert Watson { 589f7b951a8SRobert Watson char *elements, *buffer; 590f7b951a8SRobert Watson struct mac mac; 591f7b951a8SRobert Watson struct proc *tproc; 592f7b951a8SRobert Watson struct ucred *tcred; 593f7b951a8SRobert Watson int error; 594f7b951a8SRobert Watson 595d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 596f7b951a8SRobert Watson if (error) 597f7b951a8SRobert Watson return (error); 598f7b951a8SRobert Watson 599f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 600f7b951a8SRobert Watson if (error) 601f7b951a8SRobert Watson return (error); 602f7b951a8SRobert Watson 603f7b951a8SRobert Watson tproc = pfind(uap->pid); 604f7b951a8SRobert Watson if (tproc == NULL) 605f7b951a8SRobert Watson return (ESRCH); 606f7b951a8SRobert Watson 607f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 608f7b951a8SRobert Watson error = p_cansee(td, tproc); 609f7b951a8SRobert Watson if (error == 0) 610f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 611f7b951a8SRobert Watson PROC_UNLOCK(tproc); 612f7b951a8SRobert Watson if (error) 613f7b951a8SRobert Watson return (error); 614f7b951a8SRobert Watson 615a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 616f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 617f7b951a8SRobert Watson if (error) { 618f7b951a8SRobert Watson free(elements, M_MACTEMP); 619f7b951a8SRobert Watson crfree(tcred); 620f7b951a8SRobert Watson return (error); 621f7b951a8SRobert Watson } 622f7b951a8SRobert Watson 623a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 624eca8a663SRobert Watson error = mac_externalize_cred_label(tcred->cr_label, elements, 62583b7b0edSRobert Watson buffer, mac.m_buflen); 626f7b951a8SRobert Watson if (error == 0) 627f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 628f7b951a8SRobert Watson 629f7b951a8SRobert Watson free(buffer, M_MACTEMP); 630f7b951a8SRobert Watson free(elements, M_MACTEMP); 631f7b951a8SRobert Watson crfree(tcred); 632f7b951a8SRobert Watson return (error); 633f7b951a8SRobert Watson } 634f7b951a8SRobert Watson 63595fab37eSRobert Watson /* 63695fab37eSRobert Watson * MPSAFE 63795fab37eSRobert Watson */ 63895fab37eSRobert Watson int 63995fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 64095fab37eSRobert Watson { 641f7b951a8SRobert Watson char *elements, *buffer; 642f7b951a8SRobert Watson struct mac mac; 64395fab37eSRobert Watson int error; 64495fab37eSRobert Watson 645f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 646f7b951a8SRobert Watson if (error) 647f7b951a8SRobert Watson return (error); 64895fab37eSRobert Watson 649f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 650f7b951a8SRobert Watson if (error) 651f7b951a8SRobert Watson return (error); 652f7b951a8SRobert Watson 653a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 654f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 655f7b951a8SRobert Watson if (error) { 656f7b951a8SRobert Watson free(elements, M_MACTEMP); 657f7b951a8SRobert Watson return (error); 658f7b951a8SRobert Watson } 659f7b951a8SRobert Watson 660a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 661eca8a663SRobert Watson error = mac_externalize_cred_label(td->td_ucred->cr_label, 66283b7b0edSRobert Watson elements, buffer, mac.m_buflen); 663f7b951a8SRobert Watson if (error == 0) 664f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 665f7b951a8SRobert Watson 666f7b951a8SRobert Watson free(buffer, M_MACTEMP); 667f7b951a8SRobert Watson free(elements, M_MACTEMP); 66895fab37eSRobert Watson return (error); 66995fab37eSRobert Watson } 67095fab37eSRobert Watson 67195fab37eSRobert Watson /* 67295fab37eSRobert Watson * MPSAFE 67395fab37eSRobert Watson */ 67495fab37eSRobert Watson int 67595fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 67695fab37eSRobert Watson { 67795fab37eSRobert Watson struct ucred *newcred, *oldcred; 678eca8a663SRobert Watson struct label *intlabel; 679f7b951a8SRobert Watson struct proc *p; 680f7b951a8SRobert Watson struct mac mac; 681f7b951a8SRobert Watson char *buffer; 68295fab37eSRobert Watson int error; 68395fab37eSRobert Watson 684f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 68595fab37eSRobert Watson if (error) 68695fab37eSRobert Watson return (error); 68795fab37eSRobert Watson 688f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 68995fab37eSRobert Watson if (error) 69095fab37eSRobert Watson return (error); 69195fab37eSRobert Watson 692a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 693f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 694f7b951a8SRobert Watson if (error) { 695f7b951a8SRobert Watson free(buffer, M_MACTEMP); 696f7b951a8SRobert Watson return (error); 697f7b951a8SRobert Watson } 698f7b951a8SRobert Watson 699eca8a663SRobert Watson intlabel = mac_cred_label_alloc(); 700eca8a663SRobert Watson error = mac_internalize_cred_label(intlabel, buffer); 701f7b951a8SRobert Watson free(buffer, M_MACTEMP); 702eca8a663SRobert Watson if (error) 703eca8a663SRobert Watson goto out; 704f7b951a8SRobert Watson 70595fab37eSRobert Watson newcred = crget(); 70695fab37eSRobert Watson 70795fab37eSRobert Watson p = td->td_proc; 70895fab37eSRobert Watson PROC_LOCK(p); 70995fab37eSRobert Watson oldcred = p->p_ucred; 71095fab37eSRobert Watson 711eca8a663SRobert Watson error = mac_check_cred_relabel(oldcred, intlabel); 71295fab37eSRobert Watson if (error) { 71395fab37eSRobert Watson PROC_UNLOCK(p); 71495fab37eSRobert Watson crfree(newcred); 715f7b951a8SRobert Watson goto out; 71695fab37eSRobert Watson } 71795fab37eSRobert Watson 71895fab37eSRobert Watson setsugid(p); 71995fab37eSRobert Watson crcopy(newcred, oldcred); 720eca8a663SRobert Watson mac_relabel_cred(newcred, intlabel); 72195fab37eSRobert Watson p->p_ucred = newcred; 722e5cb5e37SRobert Watson 723e5cb5e37SRobert Watson /* 724e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 725e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 726e5cb5e37SRobert Watson */ 727e5cb5e37SRobert Watson crhold(newcred); 72895fab37eSRobert Watson PROC_UNLOCK(p); 729e5cb5e37SRobert Watson 730f7b951a8SRobert Watson if (mac_enforce_vm) { 73116140035SRobert Watson mtx_lock(&Giant); 732e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 73316140035SRobert Watson mtx_unlock(&Giant); 734f7b951a8SRobert Watson } 735e5cb5e37SRobert Watson 736e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 73795fab37eSRobert Watson crfree(oldcred); 738f7b951a8SRobert Watson 739f7b951a8SRobert Watson out: 740eca8a663SRobert Watson mac_cred_label_free(intlabel); 741f7b951a8SRobert Watson return (error); 74295fab37eSRobert Watson } 74395fab37eSRobert Watson 74495fab37eSRobert Watson /* 74595fab37eSRobert Watson * MPSAFE 74695fab37eSRobert Watson */ 74795fab37eSRobert Watson int 74895fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 74995fab37eSRobert Watson { 750f7b951a8SRobert Watson char *elements, *buffer; 751eca8a663SRobert Watson struct label *intlabel; 75295fab37eSRobert Watson struct file *fp; 753f7b951a8SRobert Watson struct mac mac; 75495fab37eSRobert Watson struct vnode *vp; 75595fab37eSRobert Watson struct pipe *pipe; 756b0323ea3SRobert Watson struct socket *so; 757f7b951a8SRobert Watson short label_type; 75895fab37eSRobert Watson int error; 75995fab37eSRobert Watson 760f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 761f7b951a8SRobert Watson if (error) 762f7b951a8SRobert Watson return (error); 76395fab37eSRobert Watson 764f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 765f7b951a8SRobert Watson if (error) 766f7b951a8SRobert Watson return (error); 767f7b951a8SRobert Watson 768a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 769f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 770f7b951a8SRobert Watson if (error) { 771f7b951a8SRobert Watson free(elements, M_MACTEMP); 772f7b951a8SRobert Watson return (error); 773f7b951a8SRobert Watson } 774f7b951a8SRobert Watson 775a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 776d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 77795fab37eSRobert Watson if (error) 77895fab37eSRobert Watson goto out; 77995fab37eSRobert Watson 780f7b951a8SRobert Watson label_type = fp->f_type; 78195fab37eSRobert Watson switch (fp->f_type) { 78295fab37eSRobert Watson case DTYPE_FIFO: 78395fab37eSRobert Watson case DTYPE_VNODE: 7843b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 785eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 786f0ab0442SRobert Watson mtx_lock(&Giant); /* VFS */ 78795fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 788eca8a663SRobert Watson mac_copy_vnode_label(vp->v_label, intlabel); 78995fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 790f0ab0442SRobert Watson mtx_unlock(&Giant); /* VFS */ 791f0ab0442SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, 792f0ab0442SRobert Watson buffer, mac.m_buflen); 793f0ab0442SRobert Watson mac_vnode_label_free(intlabel); 79495fab37eSRobert Watson break; 795f0ab0442SRobert Watson 79695fab37eSRobert Watson case DTYPE_PIPE: 79748e3128bSMatthew Dillon pipe = fp->f_data; 798eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 799f7b951a8SRobert Watson PIPE_LOCK(pipe); 8004795b82cSRobert Watson mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 801f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 802eca8a663SRobert Watson error = mac_externalize_pipe_label(intlabel, elements, 80383b7b0edSRobert Watson buffer, mac.m_buflen); 804eca8a663SRobert Watson mac_pipe_label_free(intlabel); 805f7b951a8SRobert Watson break; 80695fab37eSRobert Watson 807b0323ea3SRobert Watson case DTYPE_SOCKET: 808b0323ea3SRobert Watson so = fp->f_data; 809b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 810f0c2044bSRobert Watson NET_LOCK_GIANT(); 811f0c2044bSRobert Watson SOCK_LOCK(so); 812b0323ea3SRobert Watson mac_copy_socket_label(so->so_label, intlabel); 813f0c2044bSRobert Watson SOCK_UNLOCK(so); 814f0c2044bSRobert Watson NET_UNLOCK_GIANT(); 815b0323ea3SRobert Watson error = mac_externalize_socket_label(intlabel, elements, 816b0323ea3SRobert Watson buffer, mac.m_buflen); 817b0323ea3SRobert Watson mac_socket_label_free(intlabel); 818b0323ea3SRobert Watson break; 819b0323ea3SRobert Watson 820f0ab0442SRobert Watson default: 821f0ab0442SRobert Watson error = EINVAL; 822f0ab0442SRobert Watson } 823f0ab0442SRobert Watson fdrop(fp, td); 82495fab37eSRobert Watson if (error == 0) 825f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 82695fab37eSRobert Watson 82795fab37eSRobert Watson out: 828f7b951a8SRobert Watson free(buffer, M_MACTEMP); 829f7b951a8SRobert Watson free(elements, M_MACTEMP); 83095fab37eSRobert Watson return (error); 83195fab37eSRobert Watson } 83295fab37eSRobert Watson 83395fab37eSRobert Watson /* 83495fab37eSRobert Watson * MPSAFE 83595fab37eSRobert Watson */ 83695fab37eSRobert Watson int 83795fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 83895fab37eSRobert Watson { 839f7b951a8SRobert Watson char *elements, *buffer; 84095fab37eSRobert Watson struct nameidata nd; 841eca8a663SRobert Watson struct label *intlabel; 842f7b951a8SRobert Watson struct mac mac; 84395fab37eSRobert Watson int error; 84495fab37eSRobert Watson 845f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 846f7b951a8SRobert Watson if (error) 847f7b951a8SRobert Watson return (error); 848f7b951a8SRobert Watson 849f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 850f7b951a8SRobert Watson if (error) 851f7b951a8SRobert Watson return (error); 852f7b951a8SRobert Watson 853a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 854f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 855f7b951a8SRobert Watson if (error) { 856f7b951a8SRobert Watson free(elements, M_MACTEMP); 857f7b951a8SRobert Watson return (error); 858f7b951a8SRobert Watson } 859f7b951a8SRobert Watson 860a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 861f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 862f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 863f7b951a8SRobert Watson td); 86495fab37eSRobert Watson error = namei(&nd); 86595fab37eSRobert Watson if (error) 86695fab37eSRobert Watson goto out; 86795fab37eSRobert Watson 868eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 869eca8a663SRobert Watson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 870eca8a663SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, buffer, 87183b7b0edSRobert Watson mac.m_buflen); 872f7b951a8SRobert Watson 87395fab37eSRobert Watson NDFREE(&nd, 0); 874eca8a663SRobert Watson mac_vnode_label_free(intlabel); 875f7b951a8SRobert Watson 876f7b951a8SRobert Watson if (error == 0) 877f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 878f7b951a8SRobert Watson 879f7b951a8SRobert Watson out: 880f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 881f7b951a8SRobert Watson 882f7b951a8SRobert Watson free(buffer, M_MACTEMP); 883f7b951a8SRobert Watson free(elements, M_MACTEMP); 884f7b951a8SRobert Watson 885f7b951a8SRobert Watson return (error); 886f7b951a8SRobert Watson } 887f7b951a8SRobert Watson 888f7b951a8SRobert Watson /* 889f7b951a8SRobert Watson * MPSAFE 890f7b951a8SRobert Watson */ 891f7b951a8SRobert Watson int 892f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 893f7b951a8SRobert Watson { 894f7b951a8SRobert Watson char *elements, *buffer; 895f7b951a8SRobert Watson struct nameidata nd; 896eca8a663SRobert Watson struct label *intlabel; 897f7b951a8SRobert Watson struct mac mac; 898f7b951a8SRobert Watson int error; 899f7b951a8SRobert Watson 900f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 901f7b951a8SRobert Watson if (error) 902f7b951a8SRobert Watson return (error); 903f7b951a8SRobert Watson 904f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 905f7b951a8SRobert Watson if (error) 906f7b951a8SRobert Watson return (error); 907f7b951a8SRobert Watson 908a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 909f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 910f7b951a8SRobert Watson if (error) { 911f7b951a8SRobert Watson free(elements, M_MACTEMP); 912f7b951a8SRobert Watson return (error); 913f7b951a8SRobert Watson } 914f7b951a8SRobert Watson 915a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 916f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 917f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 918f7b951a8SRobert Watson td); 919f7b951a8SRobert Watson error = namei(&nd); 92095fab37eSRobert Watson if (error) 92195fab37eSRobert Watson goto out; 92295fab37eSRobert Watson 923eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 924eca8a663SRobert Watson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 925eca8a663SRobert Watson error = mac_externalize_vnode_label(intlabel, elements, buffer, 92683b7b0edSRobert Watson mac.m_buflen); 927f7b951a8SRobert Watson NDFREE(&nd, 0); 928eca8a663SRobert Watson mac_vnode_label_free(intlabel); 929f7b951a8SRobert Watson 930f7b951a8SRobert Watson if (error == 0) 931f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 93295fab37eSRobert Watson 93395fab37eSRobert Watson out: 934f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 935f7b951a8SRobert Watson 936f7b951a8SRobert Watson free(buffer, M_MACTEMP); 937f7b951a8SRobert Watson free(elements, M_MACTEMP); 938f7b951a8SRobert Watson 93995fab37eSRobert Watson return (error); 94095fab37eSRobert Watson } 94195fab37eSRobert Watson 94295fab37eSRobert Watson /* 94395fab37eSRobert Watson * MPSAFE 94495fab37eSRobert Watson */ 94595fab37eSRobert Watson int 94695fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 94795fab37eSRobert Watson { 948eca8a663SRobert Watson struct label *intlabel; 949f7b951a8SRobert Watson struct pipe *pipe; 950b0323ea3SRobert Watson struct socket *so; 951f7b951a8SRobert Watson struct file *fp; 95295fab37eSRobert Watson struct mount *mp; 95395fab37eSRobert Watson struct vnode *vp; 954f7b951a8SRobert Watson struct mac mac; 955f7b951a8SRobert Watson char *buffer; 95695fab37eSRobert Watson int error; 95795fab37eSRobert Watson 958f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 959f7b951a8SRobert Watson if (error) 960f7b951a8SRobert Watson return (error); 961f7b951a8SRobert Watson 962f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 963f7b951a8SRobert Watson if (error) 964f7b951a8SRobert Watson return (error); 965f7b951a8SRobert Watson 966a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 967f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 968f7b951a8SRobert Watson if (error) { 969f7b951a8SRobert Watson free(buffer, M_MACTEMP); 970f7b951a8SRobert Watson return (error); 971f7b951a8SRobert Watson } 972f7b951a8SRobert Watson 973d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 97495fab37eSRobert Watson if (error) 975f7b951a8SRobert Watson goto out; 97695fab37eSRobert Watson 97795fab37eSRobert Watson switch (fp->f_type) { 97895fab37eSRobert Watson case DTYPE_FIFO: 97995fab37eSRobert Watson case DTYPE_VNODE: 980eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 981eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 982f7b951a8SRobert Watson if (error) { 983eca8a663SRobert Watson mac_vnode_label_free(intlabel); 984f7b951a8SRobert Watson break; 985f7b951a8SRobert Watson } 9863b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 987f0ab0442SRobert Watson mtx_lock(&Giant); /* VFS */ 98895fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 989f7b951a8SRobert Watson if (error != 0) { 990f0ab0442SRobert Watson mtx_unlock(&Giant); /* VFS */ 991eca8a663SRobert Watson mac_vnode_label_free(intlabel); 99295fab37eSRobert Watson break; 993f7b951a8SRobert Watson } 99495fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 995eca8a663SRobert Watson error = vn_setlabel(vp, intlabel, td->td_ucred); 99695fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 99795fab37eSRobert Watson vn_finished_write(mp); 998f0ab0442SRobert Watson mtx_unlock(&Giant); /* VFS */ 999eca8a663SRobert Watson mac_vnode_label_free(intlabel); 100095fab37eSRobert Watson break; 1001f7b951a8SRobert Watson 100295fab37eSRobert Watson case DTYPE_PIPE: 1003eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 1004eca8a663SRobert Watson error = mac_internalize_pipe_label(intlabel, buffer); 1005f7b951a8SRobert Watson if (error == 0) { 100648e3128bSMatthew Dillon pipe = fp->f_data; 10071aa37f53SRobert Watson PIPE_LOCK(pipe); 10084795b82cSRobert Watson error = mac_pipe_label_set(td->td_ucred, 10094795b82cSRobert Watson pipe->pipe_pair, intlabel); 10101aa37f53SRobert Watson PIPE_UNLOCK(pipe); 1011f7b951a8SRobert Watson } 1012eca8a663SRobert Watson mac_pipe_label_free(intlabel); 101395fab37eSRobert Watson break; 1014f7b951a8SRobert Watson 1015b0323ea3SRobert Watson case DTYPE_SOCKET: 1016b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 1017b0323ea3SRobert Watson error = mac_internalize_socket_label(intlabel, buffer); 1018b0323ea3SRobert Watson if (error == 0) { 1019b0323ea3SRobert Watson so = fp->f_data; 1020f0c2044bSRobert Watson NET_LOCK_GIANT(); 1021b0323ea3SRobert Watson error = mac_socket_label_set(td->td_ucred, so, 1022b0323ea3SRobert Watson intlabel); 1023f0c2044bSRobert Watson NET_UNLOCK_GIANT(); 1024b0323ea3SRobert Watson } 1025b0323ea3SRobert Watson mac_socket_label_free(intlabel); 1026b0323ea3SRobert Watson break; 1027b0323ea3SRobert Watson 102895fab37eSRobert Watson default: 102995fab37eSRobert Watson error = EINVAL; 103095fab37eSRobert Watson } 103195fab37eSRobert Watson fdrop(fp, td); 1032f7b951a8SRobert Watson out: 1033f7b951a8SRobert Watson free(buffer, M_MACTEMP); 103495fab37eSRobert Watson return (error); 103595fab37eSRobert Watson } 103695fab37eSRobert Watson 103795fab37eSRobert Watson /* 103895fab37eSRobert Watson * MPSAFE 103995fab37eSRobert Watson */ 104095fab37eSRobert Watson int 104195fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 104295fab37eSRobert Watson { 1043eca8a663SRobert Watson struct label *intlabel; 1044f7b951a8SRobert Watson struct nameidata nd; 104595fab37eSRobert Watson struct mount *mp; 1046f7b951a8SRobert Watson struct mac mac; 1047f7b951a8SRobert Watson char *buffer; 104895fab37eSRobert Watson int error; 104995fab37eSRobert Watson 1050f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 105195fab37eSRobert Watson if (error) 1052f7b951a8SRobert Watson return (error); 105395fab37eSRobert Watson 1054f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 105595fab37eSRobert Watson if (error) 1056f7b951a8SRobert Watson return (error); 105795fab37eSRobert Watson 1058a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1059f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1060f7b951a8SRobert Watson if (error) { 1061f7b951a8SRobert Watson free(buffer, M_MACTEMP); 106295fab37eSRobert Watson return (error); 106395fab37eSRobert Watson } 106495fab37eSRobert Watson 1065eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 1066eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 1067f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1068eca8a663SRobert Watson if (error) 1069eca8a663SRobert Watson goto out; 1070f7b951a8SRobert Watson 1071f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 1072f7b951a8SRobert Watson 1073f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 1074f7b951a8SRobert Watson td); 1075f7b951a8SRobert Watson error = namei(&nd); 1076f7b951a8SRobert Watson if (error == 0) { 1077f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1078f7b951a8SRobert Watson if (error == 0) 1079eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 1080f7b951a8SRobert Watson td->td_ucred); 1081f7b951a8SRobert Watson vn_finished_write(mp); 1082f7b951a8SRobert Watson } 1083f7b951a8SRobert Watson 1084f7b951a8SRobert Watson NDFREE(&nd, 0); 1085f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 1086eca8a663SRobert Watson out: 1087eca8a663SRobert Watson mac_vnode_label_free(intlabel); 1088f7b951a8SRobert Watson return (error); 1089f7b951a8SRobert Watson } 1090f7b951a8SRobert Watson 1091f7b951a8SRobert Watson /* 1092f7b951a8SRobert Watson * MPSAFE 1093f7b951a8SRobert Watson */ 1094f7b951a8SRobert Watson int 1095f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1096f7b951a8SRobert Watson { 1097eca8a663SRobert Watson struct label *intlabel; 1098f7b951a8SRobert Watson struct nameidata nd; 1099f7b951a8SRobert Watson struct mount *mp; 1100f7b951a8SRobert Watson struct mac mac; 1101f7b951a8SRobert Watson char *buffer; 1102f7b951a8SRobert Watson int error; 1103f7b951a8SRobert Watson 1104f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1105f7b951a8SRobert Watson if (error) 1106f7b951a8SRobert Watson return (error); 1107f7b951a8SRobert Watson 1108f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 1109f7b951a8SRobert Watson if (error) 1110f7b951a8SRobert Watson return (error); 1111f7b951a8SRobert Watson 1112a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1113f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1114f7b951a8SRobert Watson if (error) { 1115f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1116f7b951a8SRobert Watson return (error); 1117f7b951a8SRobert Watson } 1118f7b951a8SRobert Watson 1119eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 1120eca8a663SRobert Watson error = mac_internalize_vnode_label(intlabel, buffer); 1121f7b951a8SRobert Watson free(buffer, M_MACTEMP); 1122eca8a663SRobert Watson if (error) 1123eca8a663SRobert Watson goto out; 1124f7b951a8SRobert Watson 1125f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 1126f7b951a8SRobert Watson 1127f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 1128f7b951a8SRobert Watson td); 1129f7b951a8SRobert Watson error = namei(&nd); 1130f7b951a8SRobert Watson if (error == 0) { 1131f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1132f7b951a8SRobert Watson if (error == 0) 1133eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 1134f7b951a8SRobert Watson td->td_ucred); 1135f7b951a8SRobert Watson vn_finished_write(mp); 1136f7b951a8SRobert Watson } 1137f7b951a8SRobert Watson 1138f7b951a8SRobert Watson NDFREE(&nd, 0); 1139f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 1140eca8a663SRobert Watson out: 1141eca8a663SRobert Watson mac_vnode_label_free(intlabel); 1142f7b951a8SRobert Watson return (error); 1143f7b951a8SRobert Watson } 1144f7b951a8SRobert Watson 1145f7b951a8SRobert Watson /* 1146f7b951a8SRobert Watson * MPSAFE 1147f7b951a8SRobert Watson */ 114827f2eac7SRobert Watson int 114927f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 115027f2eac7SRobert Watson { 115127f2eac7SRobert Watson struct mac_policy_conf *mpc; 115227f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 115341a17fe3SRobert Watson int entrycount, error; 115427f2eac7SRobert Watson 1155d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 115627f2eac7SRobert Watson if (error) 115727f2eac7SRobert Watson return (error); 115827f2eac7SRobert Watson 115927f2eac7SRobert Watson error = ENOSYS; 1160a6a65b05SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 116127f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 116227f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 116327f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 1164d1e405c5SAlfred Perlstein uap->call, uap->arg); 116527f2eac7SRobert Watson goto out; 116627f2eac7SRobert Watson } 116727f2eac7SRobert Watson } 116827f2eac7SRobert Watson 116941a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 117041a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 117141a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 117241a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 117341a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 117441a17fe3SRobert Watson uap->call, uap->arg); 117541a17fe3SRobert Watson break; 117641a17fe3SRobert Watson } 117741a17fe3SRobert Watson } 117841a17fe3SRobert Watson mac_policy_list_unbusy(); 117941a17fe3SRobert Watson } 118027f2eac7SRobert Watson out: 118127f2eac7SRobert Watson return (error); 118227f2eac7SRobert Watson } 118327f2eac7SRobert Watson 118495fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 118595fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 118695fab37eSRobert Watson 118795fab37eSRobert Watson #else /* !MAC */ 11887bc82500SRobert Watson 11897bc82500SRobert Watson int 1190f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1191f7b951a8SRobert Watson { 1192f7b951a8SRobert Watson 1193f7b951a8SRobert Watson return (ENOSYS); 1194f7b951a8SRobert Watson } 1195f7b951a8SRobert Watson 1196f7b951a8SRobert Watson int 11977bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 11987bc82500SRobert Watson { 11997bc82500SRobert Watson 12007bc82500SRobert Watson return (ENOSYS); 12017bc82500SRobert Watson } 12027bc82500SRobert Watson 12037bc82500SRobert Watson int 12047bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 12057bc82500SRobert Watson { 12067bc82500SRobert Watson 12077bc82500SRobert Watson return (ENOSYS); 12087bc82500SRobert Watson } 12097bc82500SRobert Watson 12107bc82500SRobert Watson int 12117bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 12127bc82500SRobert Watson { 12137bc82500SRobert Watson 12147bc82500SRobert Watson return (ENOSYS); 12157bc82500SRobert Watson } 12167bc82500SRobert Watson 12177bc82500SRobert Watson int 12187bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 12197bc82500SRobert Watson { 12207bc82500SRobert Watson 12217bc82500SRobert Watson return (ENOSYS); 12227bc82500SRobert Watson } 12237bc82500SRobert Watson 12247bc82500SRobert Watson int 1225f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1226f7b951a8SRobert Watson { 1227f7b951a8SRobert Watson 1228f7b951a8SRobert Watson return (ENOSYS); 1229f7b951a8SRobert Watson } 1230f7b951a8SRobert Watson 1231f7b951a8SRobert Watson int 12327bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 12337bc82500SRobert Watson { 12347bc82500SRobert Watson 12357bc82500SRobert Watson return (ENOSYS); 12367bc82500SRobert Watson } 12377bc82500SRobert Watson 12387bc82500SRobert Watson int 12397bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 12407bc82500SRobert Watson { 12417bc82500SRobert Watson 12427bc82500SRobert Watson return (ENOSYS); 12437bc82500SRobert Watson } 124495fab37eSRobert Watson 124527f2eac7SRobert Watson int 1246f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1247f7b951a8SRobert Watson { 1248f7b951a8SRobert Watson 1249f7b951a8SRobert Watson return (ENOSYS); 1250f7b951a8SRobert Watson } 1251f7b951a8SRobert Watson 1252f7b951a8SRobert Watson int 125327f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 125427f2eac7SRobert Watson { 125527f2eac7SRobert Watson 125627f2eac7SRobert Watson return (ENOSYS); 125727f2eac7SRobert Watson } 125827f2eac7SRobert Watson 125919b78822SRobert Watson #endif /* !MAC */ 1260