mac_framework.c revision 122454
1100894Srwatson/*- 2100894Srwatson * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 3100894Srwatson * Copyright (c) 2001 Ilmar S. Habibulin 4113681Srwatson * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc. 5100894Srwatson * All rights reserved. 6100894Srwatson * 7100894Srwatson * This software was developed by Robert Watson and Ilmar Habibulin for the 8100894Srwatson * TrustedBSD Project. 9100894Srwatson * 10106392Srwatson * This software was developed for the FreeBSD Project in part by Network 11106392Srwatson * Associates Laboratories, the Security Research Division of Network 12106392Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 13106392Srwatson * as part of the DARPA CHATS research program. 14100894Srwatson * 15100894Srwatson * Redistribution and use in source and binary forms, with or without 16100894Srwatson * modification, are permitted provided that the following conditions 17100894Srwatson * are met: 18100894Srwatson * 1. Redistributions of source code must retain the above copyright 19100894Srwatson * notice, this list of conditions and the following disclaimer. 20100894Srwatson * 2. Redistributions in binary form must reproduce the above copyright 21100894Srwatson * notice, this list of conditions and the following disclaimer in the 22100894Srwatson * documentation and/or other materials provided with the distribution. 23100894Srwatson * 24100894Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25100894Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26100894Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27100894Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28100894Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29100894Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30100894Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31100894Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32100894Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33100894Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34100894Srwatson * SUCH DAMAGE. 35100894Srwatson */ 36116182Sobrien 37122454Srwatson/*- 38122454Srwatson * Framework for extensible kernel access control. This file contains 39122454Srwatson * Kernel and userland interface to the framework, policy registration 40122454Srwatson * and composition. Per-object interfaces, controls, and labeling may be 41122454Srwatson * found in src/sys/mac/. Sample policies may be found in src/sys/mac*. 42100894Srwatson */ 43100894Srwatson 44116182Sobrien#include <sys/cdefs.h> 45116182Sobrien__FBSDID("$FreeBSD: head/sys/security/mac/mac_framework.c 122454 2003-11-11 03:40:04Z rwatson $"); 46116182Sobrien 47100894Srwatson#include "opt_mac.h" 48104300Sphk#include "opt_devfs.h" 49101173Srwatson 50100894Srwatson#include <sys/param.h> 51106856Srwatson#include <sys/condvar.h> 52100979Srwatson#include <sys/extattr.h> 53106468Srwatson#include <sys/imgact.h> 54100979Srwatson#include <sys/kernel.h> 55100979Srwatson#include <sys/lock.h> 56102949Sbde#include <sys/malloc.h> 57100979Srwatson#include <sys/mutex.h> 58100979Srwatson#include <sys/mac.h> 59101712Srwatson#include <sys/module.h> 60100979Srwatson#include <sys/proc.h> 61116701Srwatson#include <sys/sbuf.h> 62100979Srwatson#include <sys/systm.h> 63100894Srwatson#include <sys/sysproto.h> 64100894Srwatson#include <sys/sysent.h> 65100979Srwatson#include <sys/vnode.h> 66100979Srwatson#include <sys/mount.h> 67100979Srwatson#include <sys/file.h> 68100979Srwatson#include <sys/namei.h> 69100979Srwatson#include <sys/socket.h> 70100979Srwatson#include <sys/pipe.h> 71100979Srwatson#include <sys/socketvar.h> 72100979Srwatson#include <sys/sysctl.h> 73100894Srwatson 74100979Srwatson#include <vm/vm.h> 75100979Srwatson#include <vm/pmap.h> 76100979Srwatson#include <vm/vm_map.h> 77100979Srwatson#include <vm/vm_object.h> 78100979Srwatson 79100979Srwatson#include <sys/mac_policy.h> 80100979Srwatson 81100979Srwatson#include <fs/devfs/devfs.h> 82100979Srwatson 83100979Srwatson#include <net/bpfdesc.h> 84100979Srwatson#include <net/if.h> 85100979Srwatson#include <net/if_var.h> 86100979Srwatson 87100979Srwatson#include <netinet/in.h> 88100979Srwatson#include <netinet/ip_var.h> 89100979Srwatson 90121374Srwatson#include <security/mac/mac_internal.h> 91121374Srwatson 92100979Srwatson#ifdef MAC 93100979Srwatson 94101712Srwatson/* 95101712Srwatson * Declare that the kernel provides MAC support, version 1. This permits 96101712Srwatson * modules to refuse to be loaded if the necessary support isn't present, 97101712Srwatson * even if it's pre-boot. 98101712Srwatson */ 99101712SrwatsonMODULE_VERSION(kernel_mac_support, 1); 100101712Srwatson 101100979SrwatsonSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 102100979Srwatson "TrustedBSD MAC policy controls"); 103104517Srwatson 104114846Srwatson#if MAC_MAX_SLOTS > 32 105114846Srwatson#error "MAC_MAX_SLOTS too large" 106100979Srwatson#endif 107105497Srwatson 108114846Srwatsonstatic unsigned int mac_max_slots = MAC_MAX_SLOTS; 109114846Srwatsonstatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 110114846SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 111114846Srwatson &mac_max_slots, 0, ""); 112100979Srwatson 113105959Srwatson/* 114105959Srwatson * Has the kernel started generating labeled objects yet? All read/write 115105959Srwatson * access to this variable is serialized during the boot process. Following 116105959Srwatson * the end of serialization, we don't update this flag; no locking. 117105959Srwatson */ 118121372Srwatsonint mac_late = 0; 119100979Srwatson 120105988Srwatson/* 121113487Srwatson * Flag to indicate whether or not we should allocate label storage for 122113487Srwatson * new mbufs. Since most dynamic policies we currently work with don't 123113487Srwatson * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 124113487Srwatson * unless specifically notified of interest. One result of this is 125113487Srwatson * that if a dynamically loaded policy requests mbuf labels, it must 126113487Srwatson * be able to deal with a NULL label being returned on any mbufs that 127113487Srwatson * were already in flight when the policy was loaded. Since the policy 128113487Srwatson * already has to deal with uninitialized labels, this probably won't 129113487Srwatson * be a problem. Note: currently no locking. Will this be a problem? 130113487Srwatson */ 131118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF 132121372Srwatsonint mac_labelmbufs = 0; 133113487Srwatson#endif 134113487Srwatson 135101988Srwatson#ifdef MAC_DEBUG 136104268SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 137104268Srwatson "TrustedBSD MAC debug info"); 138104517SrwatsonSYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 139104517Srwatson "TrustedBSD MAC object counters"); 140104517Srwatson 141121374Srwatsonstatic unsigned int nmactemp; 142104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 143100979Srwatson &nmactemp, 0, "number of temporary labels in use"); 144101988Srwatson#endif 145100979Srwatson 146100979Srwatsonstatic int mac_policy_register(struct mac_policy_conf *mpc); 147100979Srwatsonstatic int mac_policy_unregister(struct mac_policy_conf *mpc); 148100979Srwatson 149105694SrwatsonMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 150100979Srwatson 151100979Srwatson/* 152114806Srwatson * mac_static_policy_list holds a list of policy modules that are not 153114806Srwatson * loaded while the system is "live", and cannot be unloaded. These 154114806Srwatson * policies can be invoked without holding the busy count. 155114806Srwatson * 156114806Srwatson * mac_policy_list stores the list of dynamic policies. A busy count is 157106856Srwatson * maintained for the list, stored in mac_policy_busy. The busy count 158114806Srwatson * is protected by mac_policy_mtx; the list may be modified only 159106856Srwatson * while the busy count is 0, requiring that the lock be held to 160106856Srwatson * prevent new references to the list from being acquired. For almost 161106856Srwatson * all operations, incrementing the busy count is sufficient to 162106856Srwatson * guarantee consistency, as the list cannot be modified while the 163106856Srwatson * busy count is elevated. For a few special operations involving a 164114806Srwatson * change to the list of active policies, the mtx itself must be held. 165114806Srwatson * A condition variable, mac_policy_cv, is used to signal potential 166114806Srwatson * exclusive consumers that they should try to acquire the lock if a 167114806Srwatson * first attempt at exclusive access fails. 168100979Srwatson */ 169114806Srwatsonstatic struct mtx mac_policy_mtx; 170114806Srwatsonstatic struct cv mac_policy_cv; 171114806Srwatsonstatic int mac_policy_count; 172121372Srwatsonstruct mac_policy_list_head mac_policy_list; 173121372Srwatsonstruct mac_policy_list_head mac_static_policy_list; 174100979Srwatson 175106856Srwatson/* 176111883Sjhb * We manually invoke WITNESS_WARN() to allow Witness to generate 177106856Srwatson * warnings even if we don't end up ever triggering the wait at 178106856Srwatson * run-time. The consumer of the exclusive interface must not hold 179106856Srwatson * any locks (other than potentially Giant) since we may sleep for 180106856Srwatson * long (potentially indefinite) periods of time waiting for the 181106856Srwatson * framework to become quiescent so that a policy list change may 182106856Srwatson * be made. 183106856Srwatson */ 184121372Srwatsonvoid 185114806Srwatsonmac_policy_grab_exclusive(void) 186114806Srwatson{ 187122454Srwatson 188114806Srwatson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 189114806Srwatson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 190114806Srwatson mtx_lock(&mac_policy_mtx); 191114806Srwatson while (mac_policy_count != 0) 192114806Srwatson cv_wait(&mac_policy_cv, &mac_policy_mtx); 193114806Srwatson} 194106856Srwatson 195121372Srwatsonvoid 196114806Srwatsonmac_policy_assert_exclusive(void) 197114806Srwatson{ 198122454Srwatson 199114806Srwatson mtx_assert(&mac_policy_mtx, MA_OWNED); 200114806Srwatson KASSERT(mac_policy_count == 0, 201114806Srwatson ("mac_policy_assert_exclusive(): not exclusive")); 202114806Srwatson} 203113487Srwatson 204121372Srwatsonvoid 205114806Srwatsonmac_policy_release_exclusive(void) 206114806Srwatson{ 207100979Srwatson 208114806Srwatson KASSERT(mac_policy_count == 0, 209114806Srwatson ("mac_policy_release_exclusive(): not exclusive")); 210114806Srwatson mtx_unlock(&mac_policy_mtx); 211114806Srwatson cv_signal(&mac_policy_cv); 212114806Srwatson} 213100979Srwatson 214121372Srwatsonvoid 215114806Srwatsonmac_policy_list_busy(void) 216114806Srwatson{ 217122454Srwatson 218114806Srwatson mtx_lock(&mac_policy_mtx); 219114806Srwatson mac_policy_count++; 220114806Srwatson mtx_unlock(&mac_policy_mtx); 221114806Srwatson} 222114806Srwatson 223121372Srwatsonint 224114806Srwatsonmac_policy_list_conditional_busy(void) 225114806Srwatson{ 226114806Srwatson int ret; 227114806Srwatson 228114806Srwatson mtx_lock(&mac_policy_mtx); 229114806Srwatson if (!LIST_EMPTY(&mac_policy_list)) { 230114806Srwatson mac_policy_count++; 231114806Srwatson ret = 1; 232114806Srwatson } else 233114806Srwatson ret = 0; 234114806Srwatson mtx_unlock(&mac_policy_mtx); 235114806Srwatson return (ret); 236114806Srwatson} 237114806Srwatson 238121372Srwatsonvoid 239114806Srwatsonmac_policy_list_unbusy(void) 240114806Srwatson{ 241122454Srwatson 242114806Srwatson mtx_lock(&mac_policy_mtx); 243114806Srwatson mac_policy_count--; 244114806Srwatson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 245114806Srwatson if (mac_policy_count == 0) 246114806Srwatson cv_signal(&mac_policy_cv); 247114806Srwatson mtx_unlock(&mac_policy_mtx); 248114806Srwatson} 249114806Srwatson 250100979Srwatson/* 251100979Srwatson * Initialize the MAC subsystem, including appropriate SMP locks. 252100979Srwatson */ 253100979Srwatsonstatic void 254100979Srwatsonmac_init(void) 255100979Srwatson{ 256100979Srwatson 257114806Srwatson LIST_INIT(&mac_static_policy_list); 258100979Srwatson LIST_INIT(&mac_policy_list); 259114806Srwatson 260114806Srwatson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 261114806Srwatson cv_init(&mac_policy_cv, "mac_policy_cv"); 262100979Srwatson} 263100979Srwatson 264100979Srwatson/* 265100979Srwatson * For the purposes of modules that want to know if they were loaded 266100979Srwatson * "early", set the mac_late flag once we've processed modules either 267100979Srwatson * linked into the kernel, or loaded before the kernel startup. 268100979Srwatson */ 269100979Srwatsonstatic void 270100979Srwatsonmac_late_init(void) 271100979Srwatson{ 272100979Srwatson 273100979Srwatson mac_late = 1; 274100979Srwatson} 275100979Srwatson 276100979Srwatson/* 277113487Srwatson * After the policy list has changed, walk the list to update any global 278118308Srwatson * flags. Currently, we support only one flag, and it's conditionally 279118308Srwatson * defined; as a result, the entire function is conditional. Eventually, 280118308Srwatson * the #else case might also iterate across the policies. 281113487Srwatson */ 282113487Srwatsonstatic void 283113487Srwatsonmac_policy_updateflags(void) 284113487Srwatson{ 285118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF 286113487Srwatson struct mac_policy_conf *tmpc; 287113487Srwatson int labelmbufs; 288113487Srwatson 289114806Srwatson mac_policy_assert_exclusive(); 290113487Srwatson 291113487Srwatson labelmbufs = 0; 292114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 293114806Srwatson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 294114806Srwatson labelmbufs++; 295114806Srwatson } 296113487Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 297113487Srwatson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 298113487Srwatson labelmbufs++; 299113487Srwatson } 300113487Srwatson mac_labelmbufs = (labelmbufs != 0); 301113487Srwatson#endif 302113487Srwatson} 303113487Srwatson 304113487Srwatson/* 305100979Srwatson * Allow MAC policy modules to register during boot, etc. 306100979Srwatson */ 307100894Srwatsonint 308100979Srwatsonmac_policy_modevent(module_t mod, int type, void *data) 309100979Srwatson{ 310100979Srwatson struct mac_policy_conf *mpc; 311100979Srwatson int error; 312100979Srwatson 313100979Srwatson error = 0; 314100979Srwatson mpc = (struct mac_policy_conf *) data; 315100979Srwatson 316100979Srwatson switch (type) { 317100979Srwatson case MOD_LOAD: 318100979Srwatson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 319100979Srwatson mac_late) { 320100979Srwatson printf("mac_policy_modevent: can't load %s policy " 321100979Srwatson "after booting\n", mpc->mpc_name); 322100979Srwatson error = EBUSY; 323100979Srwatson break; 324100979Srwatson } 325100979Srwatson error = mac_policy_register(mpc); 326100979Srwatson break; 327100979Srwatson case MOD_UNLOAD: 328100979Srwatson /* Don't unregister the module if it was never registered. */ 329100979Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 330100979Srwatson != 0) 331100979Srwatson error = mac_policy_unregister(mpc); 332100979Srwatson else 333100979Srwatson error = 0; 334100979Srwatson break; 335100979Srwatson default: 336100979Srwatson break; 337100979Srwatson } 338100979Srwatson 339100979Srwatson return (error); 340100979Srwatson} 341100979Srwatson 342100979Srwatsonstatic int 343100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc) 344100979Srwatson{ 345100979Srwatson struct mac_policy_conf *tmpc; 346114806Srwatson int error, slot, static_entry; 347100979Srwatson 348114806Srwatson error = 0; 349114806Srwatson 350114806Srwatson /* 351114806Srwatson * We don't technically need exclusive access while !mac_late, 352114806Srwatson * but hold it for assertion consistency. 353114806Srwatson */ 354114806Srwatson mac_policy_grab_exclusive(); 355114806Srwatson 356114806Srwatson /* 357114806Srwatson * If the module can potentially be unloaded, or we're loading 358114806Srwatson * late, we have to stick it in the non-static list and pay 359114806Srwatson * an extra performance overhead. Otherwise, we can pay a 360114806Srwatson * light locking cost and stick it in the static list. 361114806Srwatson */ 362114806Srwatson static_entry = (!mac_late && 363114806Srwatson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 364114806Srwatson 365114806Srwatson if (static_entry) { 366114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 367114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 368114806Srwatson error = EEXIST; 369114806Srwatson goto out; 370114806Srwatson } 371100979Srwatson } 372114806Srwatson } else { 373114806Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 374114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 375114806Srwatson error = EEXIST; 376114806Srwatson goto out; 377114806Srwatson } 378114806Srwatson } 379100979Srwatson } 380100979Srwatson if (mpc->mpc_field_off != NULL) { 381114846Srwatson slot = ffs(mac_slot_offsets_free); 382100979Srwatson if (slot == 0) { 383114806Srwatson error = ENOMEM; 384114806Srwatson goto out; 385100979Srwatson } 386100979Srwatson slot--; 387114846Srwatson mac_slot_offsets_free &= ~(1 << slot); 388100979Srwatson *mpc->mpc_field_off = slot; 389100979Srwatson } 390100979Srwatson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 391100979Srwatson 392114806Srwatson /* 393114806Srwatson * If we're loading a MAC module after the framework has 394114806Srwatson * initialized, it has to go into the dynamic list. If 395114806Srwatson * we're loading it before we've finished initializing, 396114806Srwatson * it can go into the static list with weaker locker 397114806Srwatson * requirements. 398114806Srwatson */ 399114806Srwatson if (static_entry) 400114806Srwatson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 401114806Srwatson else 402114806Srwatson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 403114806Srwatson 404100979Srwatson /* Per-policy initialization. */ 405100979Srwatson if (mpc->mpc_ops->mpo_init != NULL) 406100979Srwatson (*(mpc->mpc_ops->mpo_init))(mpc); 407113487Srwatson mac_policy_updateflags(); 408100979Srwatson 409100979Srwatson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 410100979Srwatson mpc->mpc_name); 411100979Srwatson 412114806Srwatsonout: 413114806Srwatson mac_policy_release_exclusive(); 414114806Srwatson return (error); 415100979Srwatson} 416100979Srwatson 417100979Srwatsonstatic int 418100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc) 419100979Srwatson{ 420100979Srwatson 421104520Srwatson /* 422104520Srwatson * If we fail the load, we may get a request to unload. Check 423104520Srwatson * to see if we did the run-time registration, and if not, 424104520Srwatson * silently succeed. 425104520Srwatson */ 426114806Srwatson mac_policy_grab_exclusive(); 427104520Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 428114806Srwatson mac_policy_release_exclusive(); 429104520Srwatson return (0); 430104520Srwatson } 431100979Srwatson#if 0 432100979Srwatson /* 433100979Srwatson * Don't allow unloading modules with private data. 434100979Srwatson */ 435104520Srwatson if (mpc->mpc_field_off != NULL) { 436104520Srwatson MAC_POLICY_LIST_UNLOCK(); 437100979Srwatson return (EBUSY); 438104520Srwatson } 439100979Srwatson#endif 440104520Srwatson /* 441104520Srwatson * Only allow the unload to proceed if the module is unloadable 442104520Srwatson * by its own definition. 443104520Srwatson */ 444104520Srwatson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 445114806Srwatson mac_policy_release_exclusive(); 446100979Srwatson return (EBUSY); 447104520Srwatson } 448100979Srwatson if (mpc->mpc_ops->mpo_destroy != NULL) 449100979Srwatson (*(mpc->mpc_ops->mpo_destroy))(mpc); 450100979Srwatson 451100979Srwatson LIST_REMOVE(mpc, mpc_list); 452106856Srwatson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 453113487Srwatson mac_policy_updateflags(); 454100979Srwatson 455114806Srwatson mac_policy_release_exclusive(); 456114806Srwatson 457100979Srwatson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 458100979Srwatson mpc->mpc_name); 459100979Srwatson 460100979Srwatson return (0); 461100979Srwatson} 462100979Srwatson 463100979Srwatson/* 464100979Srwatson * Define an error value precedence, and given two arguments, selects the 465100979Srwatson * value with the higher precedence. 466100979Srwatson */ 467121371Srwatsonint 468121371Srwatsonmac_error_select(int error1, int error2) 469100979Srwatson{ 470100979Srwatson 471100979Srwatson /* Certain decision-making errors take top priority. */ 472100979Srwatson if (error1 == EDEADLK || error2 == EDEADLK) 473100979Srwatson return (EDEADLK); 474100979Srwatson 475100979Srwatson /* Invalid arguments should be reported where possible. */ 476100979Srwatson if (error1 == EINVAL || error2 == EINVAL) 477100979Srwatson return (EINVAL); 478100979Srwatson 479100979Srwatson /* Precedence goes to "visibility", with both process and file. */ 480100979Srwatson if (error1 == ESRCH || error2 == ESRCH) 481100979Srwatson return (ESRCH); 482100979Srwatson 483100979Srwatson if (error1 == ENOENT || error2 == ENOENT) 484100979Srwatson return (ENOENT); 485100979Srwatson 486100979Srwatson /* Precedence goes to DAC/MAC protections. */ 487100979Srwatson if (error1 == EACCES || error2 == EACCES) 488100979Srwatson return (EACCES); 489100979Srwatson 490100979Srwatson /* Precedence goes to privilege. */ 491100979Srwatson if (error1 == EPERM || error2 == EPERM) 492100979Srwatson return (EPERM); 493100979Srwatson 494100979Srwatson /* Precedence goes to error over success; otherwise, arbitrary. */ 495100979Srwatson if (error1 != 0) 496100979Srwatson return (error1); 497100979Srwatson return (error2); 498100979Srwatson} 499100979Srwatson 500121374Srwatsonvoid 501104521Srwatsonmac_init_label(struct label *label) 502104521Srwatson{ 503104521Srwatson 504104521Srwatson bzero(label, sizeof(*label)); 505104521Srwatson label->l_flags = MAC_FLAG_INITIALIZED; 506104521Srwatson} 507104521Srwatson 508121374Srwatsonvoid 509104521Srwatsonmac_destroy_label(struct label *label) 510104521Srwatson{ 511104521Srwatson 512104521Srwatson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 513104521Srwatson ("destroying uninitialized label")); 514104521Srwatson 515104521Srwatson bzero(label, sizeof(*label)); 516104521Srwatson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 517104521Srwatson} 518104521Srwatson 519112675Srwatsonint 520105694Srwatsonmac_check_structmac_consistent(struct mac *mac) 521104522Srwatson{ 522105694Srwatson 523120582Srwatson if (mac->m_buflen < 0 || 524120582Srwatson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 525105694Srwatson return (EINVAL); 526105694Srwatson 527105694Srwatson return (0); 528105694Srwatson} 529105694Srwatson 530105988Srwatsonint 531105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 532105694Srwatson{ 533105694Srwatson char *elements, *buffer; 534105694Srwatson struct mac mac; 535105694Srwatson struct proc *tproc; 536105694Srwatson struct ucred *tcred; 537105694Srwatson int error; 538105694Srwatson 539107849Salfred error = copyin(uap->mac_p, &mac, sizeof(mac)); 540105694Srwatson if (error) 541105694Srwatson return (error); 542105694Srwatson 543105694Srwatson error = mac_check_structmac_consistent(&mac); 544105694Srwatson if (error) 545105694Srwatson return (error); 546105694Srwatson 547105694Srwatson tproc = pfind(uap->pid); 548105694Srwatson if (tproc == NULL) 549105694Srwatson return (ESRCH); 550105694Srwatson 551105694Srwatson tcred = NULL; /* Satisfy gcc. */ 552105694Srwatson error = p_cansee(td, tproc); 553105694Srwatson if (error == 0) 554105694Srwatson tcred = crhold(tproc->p_ucred); 555105694Srwatson PROC_UNLOCK(tproc); 556105694Srwatson if (error) 557105694Srwatson return (error); 558105694Srwatson 559111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 560105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 561105694Srwatson if (error) { 562105694Srwatson free(elements, M_MACTEMP); 563105694Srwatson crfree(tcred); 564105694Srwatson return (error); 565105694Srwatson } 566105694Srwatson 567111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 568105694Srwatson error = mac_externalize_cred_label(&tcred->cr_label, elements, 569122159Srwatson buffer, mac.m_buflen); 570105694Srwatson if (error == 0) 571105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 572105694Srwatson 573105694Srwatson free(buffer, M_MACTEMP); 574105694Srwatson free(elements, M_MACTEMP); 575105694Srwatson crfree(tcred); 576105694Srwatson return (error); 577105694Srwatson} 578105694Srwatson 579100979Srwatson/* 580100979Srwatson * MPSAFE 581100979Srwatson */ 582100979Srwatsonint 583100894Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 584100894Srwatson{ 585105694Srwatson char *elements, *buffer; 586105694Srwatson struct mac mac; 587100979Srwatson int error; 588100894Srwatson 589105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 590105694Srwatson if (error) 591105694Srwatson return (error); 592105694Srwatson 593105694Srwatson error = mac_check_structmac_consistent(&mac); 594105694Srwatson if (error) 595105694Srwatson return (error); 596105694Srwatson 597111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 598105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 599105694Srwatson if (error) { 600105694Srwatson free(elements, M_MACTEMP); 601105694Srwatson return (error); 602105694Srwatson } 603105694Srwatson 604111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 605105694Srwatson error = mac_externalize_cred_label(&td->td_ucred->cr_label, 606122159Srwatson elements, buffer, mac.m_buflen); 607100979Srwatson if (error == 0) 608105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 609100979Srwatson 610105694Srwatson free(buffer, M_MACTEMP); 611105694Srwatson free(elements, M_MACTEMP); 612100979Srwatson return (error); 613100979Srwatson} 614100979Srwatson 615100979Srwatson/* 616100979Srwatson * MPSAFE 617100979Srwatson */ 618100979Srwatsonint 619100979Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 620100979Srwatson{ 621100979Srwatson struct ucred *newcred, *oldcred; 622105694Srwatson struct label intlabel; 623100979Srwatson struct proc *p; 624105694Srwatson struct mac mac; 625105694Srwatson char *buffer; 626100979Srwatson int error; 627100979Srwatson 628105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 629100979Srwatson if (error) 630100979Srwatson return (error); 631100979Srwatson 632105694Srwatson error = mac_check_structmac_consistent(&mac); 633100979Srwatson if (error) 634100979Srwatson return (error); 635100979Srwatson 636111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 637105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 638105694Srwatson if (error) { 639105694Srwatson free(buffer, M_MACTEMP); 640105694Srwatson return (error); 641105694Srwatson } 642105694Srwatson 643105694Srwatson mac_init_cred_label(&intlabel); 644105694Srwatson error = mac_internalize_cred_label(&intlabel, buffer); 645105694Srwatson free(buffer, M_MACTEMP); 646105694Srwatson if (error) { 647105694Srwatson mac_destroy_cred_label(&intlabel); 648105694Srwatson return (error); 649105694Srwatson } 650105694Srwatson 651100979Srwatson newcred = crget(); 652100979Srwatson 653100979Srwatson p = td->td_proc; 654100979Srwatson PROC_LOCK(p); 655100979Srwatson oldcred = p->p_ucred; 656100979Srwatson 657100979Srwatson error = mac_check_cred_relabel(oldcred, &intlabel); 658100979Srwatson if (error) { 659100979Srwatson PROC_UNLOCK(p); 660100979Srwatson crfree(newcred); 661105694Srwatson goto out; 662100979Srwatson } 663100979Srwatson 664100979Srwatson setsugid(p); 665100979Srwatson crcopy(newcred, oldcred); 666100979Srwatson mac_relabel_cred(newcred, &intlabel); 667102136Srwatson p->p_ucred = newcred; 668100979Srwatson 669102136Srwatson /* 670102136Srwatson * Grab additional reference for use while revoking mmaps, prior 671102136Srwatson * to releasing the proc lock and sharing the cred. 672102136Srwatson */ 673102136Srwatson crhold(newcred); 674100979Srwatson PROC_UNLOCK(p); 675102136Srwatson 676105694Srwatson if (mac_enforce_vm) { 677105694Srwatson mtx_lock(&Giant); 678105694Srwatson mac_cred_mmapped_drop_perms(td, newcred); 679105694Srwatson mtx_unlock(&Giant); 680105694Srwatson } 681102136Srwatson 682102136Srwatson crfree(newcred); /* Free revocation reference. */ 683100979Srwatson crfree(oldcred); 684105694Srwatson 685105694Srwatsonout: 686105694Srwatson mac_destroy_cred_label(&intlabel); 687105694Srwatson return (error); 688100979Srwatson} 689100979Srwatson 690100979Srwatson/* 691100979Srwatson * MPSAFE 692100979Srwatson */ 693100979Srwatsonint 694100979Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 695100979Srwatson{ 696105694Srwatson char *elements, *buffer; 697105694Srwatson struct label intlabel; 698100979Srwatson struct file *fp; 699105694Srwatson struct mac mac; 700100979Srwatson struct vnode *vp; 701100979Srwatson struct pipe *pipe; 702105694Srwatson short label_type; 703100979Srwatson int error; 704100979Srwatson 705105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 706105694Srwatson if (error) 707105694Srwatson return (error); 708100979Srwatson 709105694Srwatson error = mac_check_structmac_consistent(&mac); 710105694Srwatson if (error) 711105694Srwatson return (error); 712105694Srwatson 713111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 714105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 715105694Srwatson if (error) { 716105694Srwatson free(elements, M_MACTEMP); 717105694Srwatson return (error); 718105694Srwatson } 719105694Srwatson 720111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 721105694Srwatson mtx_lock(&Giant); /* VFS */ 722107849Salfred error = fget(td, uap->fd, &fp); 723100979Srwatson if (error) 724100979Srwatson goto out; 725100979Srwatson 726105694Srwatson label_type = fp->f_type; 727100979Srwatson switch (fp->f_type) { 728100979Srwatson case DTYPE_FIFO: 729100979Srwatson case DTYPE_VNODE: 730116678Sphk vp = fp->f_vnode; 731100979Srwatson 732105694Srwatson mac_init_vnode_label(&intlabel); 733105694Srwatson 734100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 735105988Srwatson mac_copy_vnode_label(&vp->v_label, &intlabel); 736100979Srwatson VOP_UNLOCK(vp, 0, td); 737105694Srwatson 738100979Srwatson break; 739100979Srwatson case DTYPE_PIPE: 740109153Sdillon pipe = fp->f_data; 741105694Srwatson 742105694Srwatson mac_init_pipe_label(&intlabel); 743105694Srwatson 744105694Srwatson PIPE_LOCK(pipe); 745105694Srwatson mac_copy_pipe_label(pipe->pipe_label, &intlabel); 746105694Srwatson PIPE_UNLOCK(pipe); 747100979Srwatson break; 748100979Srwatson default: 749100979Srwatson error = EINVAL; 750105694Srwatson fdrop(fp, td); 751105694Srwatson goto out; 752100979Srwatson } 753105694Srwatson fdrop(fp, td); 754100979Srwatson 755105694Srwatson switch (label_type) { 756105694Srwatson case DTYPE_FIFO: 757105694Srwatson case DTYPE_VNODE: 758105694Srwatson if (error == 0) 759105694Srwatson error = mac_externalize_vnode_label(&intlabel, 760122159Srwatson elements, buffer, mac.m_buflen); 761105694Srwatson mac_destroy_vnode_label(&intlabel); 762105694Srwatson break; 763105694Srwatson case DTYPE_PIPE: 764105694Srwatson error = mac_externalize_pipe_label(&intlabel, elements, 765122159Srwatson buffer, mac.m_buflen); 766105694Srwatson mac_destroy_pipe_label(&intlabel); 767105694Srwatson break; 768105694Srwatson default: 769105694Srwatson panic("__mac_get_fd: corrupted label_type"); 770105694Srwatson } 771105694Srwatson 772100979Srwatson if (error == 0) 773105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 774100979Srwatson 775105694Srwatsonout: 776105694Srwatson mtx_unlock(&Giant); /* VFS */ 777105694Srwatson free(buffer, M_MACTEMP); 778105694Srwatson free(elements, M_MACTEMP); 779100979Srwatson 780100979Srwatson return (error); 781100979Srwatson} 782100979Srwatson 783100979Srwatson/* 784100979Srwatson * MPSAFE 785100979Srwatson */ 786100979Srwatsonint 787100979Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 788100979Srwatson{ 789105694Srwatson char *elements, *buffer; 790100979Srwatson struct nameidata nd; 791105694Srwatson struct label intlabel; 792105694Srwatson struct mac mac; 793100979Srwatson int error; 794100979Srwatson 795105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 796105694Srwatson if (error) 797105694Srwatson return (error); 798105694Srwatson 799105694Srwatson error = mac_check_structmac_consistent(&mac); 800105694Srwatson if (error) 801105694Srwatson return (error); 802105694Srwatson 803111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 804105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 805105694Srwatson if (error) { 806105694Srwatson free(elements, M_MACTEMP); 807105694Srwatson return (error); 808105694Srwatson } 809105694Srwatson 810111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 811105694Srwatson mtx_lock(&Giant); /* VFS */ 812105694Srwatson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 813105694Srwatson td); 814100979Srwatson error = namei(&nd); 815100979Srwatson if (error) 816100979Srwatson goto out; 817100979Srwatson 818105694Srwatson mac_init_vnode_label(&intlabel); 819105988Srwatson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 820105988Srwatson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 821122159Srwatson mac.m_buflen); 822105694Srwatson 823100979Srwatson NDFREE(&nd, 0); 824105694Srwatson mac_destroy_vnode_label(&intlabel); 825105694Srwatson 826105694Srwatson if (error == 0) 827105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 828105694Srwatson 829105694Srwatsonout: 830105694Srwatson mtx_unlock(&Giant); /* VFS */ 831105694Srwatson 832105694Srwatson free(buffer, M_MACTEMP); 833105694Srwatson free(elements, M_MACTEMP); 834105694Srwatson 835105694Srwatson return (error); 836105694Srwatson} 837105694Srwatson 838105694Srwatson/* 839105694Srwatson * MPSAFE 840105694Srwatson */ 841105694Srwatsonint 842105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 843105694Srwatson{ 844105694Srwatson char *elements, *buffer; 845105694Srwatson struct nameidata nd; 846105694Srwatson struct label intlabel; 847105694Srwatson struct mac mac; 848105694Srwatson int error; 849105694Srwatson 850105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 851100979Srwatson if (error) 852105694Srwatson return (error); 853105694Srwatson 854105694Srwatson error = mac_check_structmac_consistent(&mac); 855105694Srwatson if (error) 856105694Srwatson return (error); 857105694Srwatson 858111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 859105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 860105694Srwatson if (error) { 861105694Srwatson free(elements, M_MACTEMP); 862105694Srwatson return (error); 863105694Srwatson } 864105694Srwatson 865111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 866105694Srwatson mtx_lock(&Giant); /* VFS */ 867105694Srwatson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 868105694Srwatson td); 869105694Srwatson error = namei(&nd); 870105694Srwatson if (error) 871100979Srwatson goto out; 872100979Srwatson 873105694Srwatson mac_init_vnode_label(&intlabel); 874105988Srwatson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 875105988Srwatson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 876122159Srwatson mac.m_buflen); 877105694Srwatson NDFREE(&nd, 0); 878105694Srwatson mac_destroy_vnode_label(&intlabel); 879100979Srwatson 880105694Srwatson if (error == 0) 881105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 882105694Srwatson 883100979Srwatsonout: 884105694Srwatson mtx_unlock(&Giant); /* VFS */ 885105694Srwatson 886105694Srwatson free(buffer, M_MACTEMP); 887105694Srwatson free(elements, M_MACTEMP); 888105694Srwatson 889100979Srwatson return (error); 890100979Srwatson} 891100979Srwatson 892100979Srwatson/* 893100979Srwatson * MPSAFE 894100979Srwatson */ 895100979Srwatsonint 896100979Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 897100979Srwatson{ 898105694Srwatson struct label intlabel; 899105694Srwatson struct pipe *pipe; 900100979Srwatson struct file *fp; 901100979Srwatson struct mount *mp; 902100979Srwatson struct vnode *vp; 903105694Srwatson struct mac mac; 904105694Srwatson char *buffer; 905100979Srwatson int error; 906100979Srwatson 907105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 908100979Srwatson if (error) 909105694Srwatson return (error); 910100979Srwatson 911105694Srwatson error = mac_check_structmac_consistent(&mac); 912100979Srwatson if (error) 913105694Srwatson return (error); 914100979Srwatson 915111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 916105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 917105694Srwatson if (error) { 918105694Srwatson free(buffer, M_MACTEMP); 919105694Srwatson return (error); 920105694Srwatson } 921105694Srwatson 922105694Srwatson mtx_lock(&Giant); /* VFS */ 923105694Srwatson 924107849Salfred error = fget(td, uap->fd, &fp); 925100979Srwatson if (error) 926105694Srwatson goto out; 927100979Srwatson 928100979Srwatson switch (fp->f_type) { 929100979Srwatson case DTYPE_FIFO: 930100979Srwatson case DTYPE_VNODE: 931105694Srwatson mac_init_vnode_label(&intlabel); 932105694Srwatson error = mac_internalize_vnode_label(&intlabel, buffer); 933105694Srwatson if (error) { 934105694Srwatson mac_destroy_vnode_label(&intlabel); 935105694Srwatson break; 936105694Srwatson } 937105694Srwatson 938116678Sphk vp = fp->f_vnode; 939100979Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 940105694Srwatson if (error != 0) { 941105694Srwatson mac_destroy_vnode_label(&intlabel); 942100979Srwatson break; 943105694Srwatson } 944100979Srwatson 945100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 946100979Srwatson error = vn_setlabel(vp, &intlabel, td->td_ucred); 947100979Srwatson VOP_UNLOCK(vp, 0, td); 948100979Srwatson vn_finished_write(mp); 949105694Srwatson 950105694Srwatson mac_destroy_vnode_label(&intlabel); 951100979Srwatson break; 952105694Srwatson 953100979Srwatson case DTYPE_PIPE: 954105694Srwatson mac_init_pipe_label(&intlabel); 955105694Srwatson error = mac_internalize_pipe_label(&intlabel, buffer); 956105694Srwatson if (error == 0) { 957109153Sdillon pipe = fp->f_data; 958105694Srwatson PIPE_LOCK(pipe); 959105694Srwatson error = mac_pipe_label_set(td->td_ucred, pipe, 960105694Srwatson &intlabel); 961105694Srwatson PIPE_UNLOCK(pipe); 962105694Srwatson } 963105694Srwatson 964105694Srwatson mac_destroy_pipe_label(&intlabel); 965100979Srwatson break; 966105694Srwatson 967100979Srwatson default: 968100979Srwatson error = EINVAL; 969100979Srwatson } 970100979Srwatson 971100979Srwatson fdrop(fp, td); 972105694Srwatsonout: 973105694Srwatson mtx_unlock(&Giant); /* VFS */ 974105694Srwatson 975105694Srwatson free(buffer, M_MACTEMP); 976105694Srwatson 977100979Srwatson return (error); 978100979Srwatson} 979100979Srwatson 980100979Srwatson/* 981100979Srwatson * MPSAFE 982100979Srwatson */ 983100979Srwatsonint 984100979Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 985100979Srwatson{ 986105694Srwatson struct label intlabel; 987100979Srwatson struct nameidata nd; 988100979Srwatson struct mount *mp; 989105694Srwatson struct mac mac; 990105694Srwatson char *buffer; 991100979Srwatson int error; 992100979Srwatson 993105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 994100979Srwatson if (error) 995105694Srwatson return (error); 996100979Srwatson 997105694Srwatson error = mac_check_structmac_consistent(&mac); 998100979Srwatson if (error) 999105694Srwatson return (error); 1000100979Srwatson 1001111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1002105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1003105694Srwatson if (error) { 1004105694Srwatson free(buffer, M_MACTEMP); 1005105694Srwatson return (error); 1006105694Srwatson } 1007105694Srwatson 1008105694Srwatson mac_init_vnode_label(&intlabel); 1009105694Srwatson error = mac_internalize_vnode_label(&intlabel, buffer); 1010105694Srwatson free(buffer, M_MACTEMP); 1011105694Srwatson if (error) { 1012105694Srwatson mac_destroy_vnode_label(&intlabel); 1013105694Srwatson return (error); 1014105694Srwatson } 1015105694Srwatson 1016105694Srwatson mtx_lock(&Giant); /* VFS */ 1017105694Srwatson 1018105694Srwatson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 1019105694Srwatson td); 1020100979Srwatson error = namei(&nd); 1021105694Srwatson if (error == 0) { 1022105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1023105694Srwatson if (error == 0) 1024105694Srwatson error = vn_setlabel(nd.ni_vp, &intlabel, 1025105694Srwatson td->td_ucred); 1026105694Srwatson vn_finished_write(mp); 1027105694Srwatson } 1028105694Srwatson 1029105694Srwatson NDFREE(&nd, 0); 1030105694Srwatson mtx_unlock(&Giant); /* VFS */ 1031105694Srwatson mac_destroy_vnode_label(&intlabel); 1032105694Srwatson 1033105694Srwatson return (error); 1034105694Srwatson} 1035105694Srwatson 1036105694Srwatson/* 1037105694Srwatson * MPSAFE 1038105694Srwatson */ 1039105694Srwatsonint 1040105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1041105694Srwatson{ 1042105694Srwatson struct label intlabel; 1043105694Srwatson struct nameidata nd; 1044105694Srwatson struct mount *mp; 1045105694Srwatson struct mac mac; 1046105694Srwatson char *buffer; 1047105694Srwatson int error; 1048105694Srwatson 1049105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1050100979Srwatson if (error) 1051105694Srwatson return (error); 1052105694Srwatson 1053105694Srwatson error = mac_check_structmac_consistent(&mac); 1054100979Srwatson if (error) 1055105694Srwatson return (error); 1056100979Srwatson 1057111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1058105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1059105694Srwatson if (error) { 1060105694Srwatson free(buffer, M_MACTEMP); 1061105694Srwatson return (error); 1062105694Srwatson } 1063105694Srwatson 1064105694Srwatson mac_init_vnode_label(&intlabel); 1065105694Srwatson error = mac_internalize_vnode_label(&intlabel, buffer); 1066105694Srwatson free(buffer, M_MACTEMP); 1067105694Srwatson if (error) { 1068105694Srwatson mac_destroy_vnode_label(&intlabel); 1069105694Srwatson return (error); 1070105694Srwatson } 1071105694Srwatson 1072105694Srwatson mtx_lock(&Giant); /* VFS */ 1073105694Srwatson 1074105694Srwatson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 1075105694Srwatson td); 1076105694Srwatson error = namei(&nd); 1077105694Srwatson if (error == 0) { 1078105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1079105694Srwatson if (error == 0) 1080105694Srwatson error = vn_setlabel(nd.ni_vp, &intlabel, 1081105694Srwatson td->td_ucred); 1082105694Srwatson vn_finished_write(mp); 1083105694Srwatson } 1084105694Srwatson 1085100979Srwatson NDFREE(&nd, 0); 1086105694Srwatson mtx_unlock(&Giant); /* VFS */ 1087105694Srwatson mac_destroy_vnode_label(&intlabel); 1088105694Srwatson 1089100979Srwatson return (error); 1090100979Srwatson} 1091100979Srwatson 1092105694Srwatson/* 1093105694Srwatson * MPSAFE 1094105694Srwatson */ 1095102123Srwatsonint 1096102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1097102123Srwatson{ 1098102123Srwatson struct mac_policy_conf *mpc; 1099102123Srwatson char target[MAC_MAX_POLICY_NAME]; 1100114806Srwatson int entrycount, error; 1101102123Srwatson 1102107849Salfred error = copyinstr(uap->policy, target, sizeof(target), NULL); 1103102123Srwatson if (error) 1104102123Srwatson return (error); 1105102123Srwatson 1106102123Srwatson error = ENOSYS; 1107119494Srwatson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1108102123Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1109102123Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1110102123Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1111107849Salfred uap->call, uap->arg); 1112102123Srwatson goto out; 1113102123Srwatson } 1114102123Srwatson } 1115102123Srwatson 1116114806Srwatson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1117114806Srwatson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1118114806Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1119114806Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1120114806Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1121114806Srwatson uap->call, uap->arg); 1122114806Srwatson break; 1123114806Srwatson } 1124114806Srwatson } 1125114806Srwatson mac_policy_list_unbusy(); 1126114806Srwatson } 1127102123Srwatsonout: 1128102123Srwatson return (error); 1129102123Srwatson} 1130102123Srwatson 1131100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1132100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1133100979Srwatson 1134100979Srwatson#else /* !MAC */ 1135100979Srwatson 1136100979Srwatsonint 1137105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1138105694Srwatson{ 1139105694Srwatson 1140105694Srwatson return (ENOSYS); 1141105694Srwatson} 1142105694Srwatson 1143105694Srwatsonint 1144100979Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1145100979Srwatson{ 1146100979Srwatson 1147100894Srwatson return (ENOSYS); 1148100894Srwatson} 1149100894Srwatson 1150100894Srwatsonint 1151100894Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1152100894Srwatson{ 1153100894Srwatson 1154100894Srwatson return (ENOSYS); 1155100894Srwatson} 1156100894Srwatson 1157100894Srwatsonint 1158100894Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1159100894Srwatson{ 1160100894Srwatson 1161100894Srwatson return (ENOSYS); 1162100894Srwatson} 1163100894Srwatson 1164100894Srwatsonint 1165100894Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1166100894Srwatson{ 1167100894Srwatson 1168100894Srwatson return (ENOSYS); 1169100894Srwatson} 1170100894Srwatson 1171100894Srwatsonint 1172105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1173105694Srwatson{ 1174105694Srwatson 1175105694Srwatson return (ENOSYS); 1176105694Srwatson} 1177105694Srwatson 1178105694Srwatsonint 1179100894Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1180100894Srwatson{ 1181100894Srwatson 1182100894Srwatson return (ENOSYS); 1183100894Srwatson} 1184100894Srwatson 1185100894Srwatsonint 1186100894Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1187100894Srwatson{ 1188100894Srwatson 1189100894Srwatson return (ENOSYS); 1190100894Srwatson} 1191100979Srwatson 1192102123Srwatsonint 1193105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1194105694Srwatson{ 1195105694Srwatson 1196105694Srwatson return (ENOSYS); 1197105694Srwatson} 1198105694Srwatson 1199105694Srwatsonint 1200102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1201102123Srwatson{ 1202102123Srwatson 1203102123Srwatson return (ENOSYS); 1204102123Srwatson} 1205102123Srwatson 1206105694Srwatson#endif 1207