mac_syscalls.c revision 126097
1100894Srwatson/*- 2126097Srwatson * Copyright (c) 1999-2002 Robert N. M. Watson 3100894Srwatson * Copyright (c) 2001 Ilmar S. Habibulin 4126097Srwatson * Copyright (c) 2001-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_syscalls.c 126097 2004-02-22 00:33:12Z 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); 259122524Srwatson mac_labelzone_init(); 260114806Srwatson 261114806Srwatson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 262114806Srwatson cv_init(&mac_policy_cv, "mac_policy_cv"); 263100979Srwatson} 264100979Srwatson 265100979Srwatson/* 266100979Srwatson * For the purposes of modules that want to know if they were loaded 267100979Srwatson * "early", set the mac_late flag once we've processed modules either 268100979Srwatson * linked into the kernel, or loaded before the kernel startup. 269100979Srwatson */ 270100979Srwatsonstatic void 271100979Srwatsonmac_late_init(void) 272100979Srwatson{ 273100979Srwatson 274100979Srwatson mac_late = 1; 275100979Srwatson} 276100979Srwatson 277100979Srwatson/* 278113487Srwatson * After the policy list has changed, walk the list to update any global 279118308Srwatson * flags. Currently, we support only one flag, and it's conditionally 280118308Srwatson * defined; as a result, the entire function is conditional. Eventually, 281118308Srwatson * the #else case might also iterate across the policies. 282113487Srwatson */ 283113487Srwatsonstatic void 284113487Srwatsonmac_policy_updateflags(void) 285113487Srwatson{ 286118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF 287113487Srwatson struct mac_policy_conf *tmpc; 288113487Srwatson int labelmbufs; 289113487Srwatson 290114806Srwatson mac_policy_assert_exclusive(); 291113487Srwatson 292113487Srwatson labelmbufs = 0; 293114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 294114806Srwatson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 295114806Srwatson labelmbufs++; 296114806Srwatson } 297113487Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 298113487Srwatson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 299113487Srwatson labelmbufs++; 300113487Srwatson } 301113487Srwatson mac_labelmbufs = (labelmbufs != 0); 302113487Srwatson#endif 303113487Srwatson} 304113487Srwatson 305113487Srwatson/* 306100979Srwatson * Allow MAC policy modules to register during boot, etc. 307100979Srwatson */ 308100894Srwatsonint 309100979Srwatsonmac_policy_modevent(module_t mod, int type, void *data) 310100979Srwatson{ 311100979Srwatson struct mac_policy_conf *mpc; 312100979Srwatson int error; 313100979Srwatson 314100979Srwatson error = 0; 315100979Srwatson mpc = (struct mac_policy_conf *) data; 316100979Srwatson 317100979Srwatson switch (type) { 318100979Srwatson case MOD_LOAD: 319100979Srwatson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 320100979Srwatson mac_late) { 321100979Srwatson printf("mac_policy_modevent: can't load %s policy " 322100979Srwatson "after booting\n", mpc->mpc_name); 323100979Srwatson error = EBUSY; 324100979Srwatson break; 325100979Srwatson } 326100979Srwatson error = mac_policy_register(mpc); 327100979Srwatson break; 328100979Srwatson case MOD_UNLOAD: 329100979Srwatson /* Don't unregister the module if it was never registered. */ 330100979Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 331100979Srwatson != 0) 332100979Srwatson error = mac_policy_unregister(mpc); 333100979Srwatson else 334100979Srwatson error = 0; 335100979Srwatson break; 336100979Srwatson default: 337100979Srwatson break; 338100979Srwatson } 339100979Srwatson 340100979Srwatson return (error); 341100979Srwatson} 342100979Srwatson 343100979Srwatsonstatic int 344100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc) 345100979Srwatson{ 346100979Srwatson struct mac_policy_conf *tmpc; 347114806Srwatson int error, slot, static_entry; 348100979Srwatson 349114806Srwatson error = 0; 350114806Srwatson 351114806Srwatson /* 352114806Srwatson * We don't technically need exclusive access while !mac_late, 353114806Srwatson * but hold it for assertion consistency. 354114806Srwatson */ 355114806Srwatson mac_policy_grab_exclusive(); 356114806Srwatson 357114806Srwatson /* 358114806Srwatson * If the module can potentially be unloaded, or we're loading 359114806Srwatson * late, we have to stick it in the non-static list and pay 360114806Srwatson * an extra performance overhead. Otherwise, we can pay a 361114806Srwatson * light locking cost and stick it in the static list. 362114806Srwatson */ 363114806Srwatson static_entry = (!mac_late && 364114806Srwatson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 365114806Srwatson 366114806Srwatson if (static_entry) { 367114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 368114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 369114806Srwatson error = EEXIST; 370114806Srwatson goto out; 371114806Srwatson } 372100979Srwatson } 373114806Srwatson } else { 374114806Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 375114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 376114806Srwatson error = EEXIST; 377114806Srwatson goto out; 378114806Srwatson } 379114806Srwatson } 380100979Srwatson } 381100979Srwatson if (mpc->mpc_field_off != NULL) { 382114846Srwatson slot = ffs(mac_slot_offsets_free); 383100979Srwatson if (slot == 0) { 384114806Srwatson error = ENOMEM; 385114806Srwatson goto out; 386100979Srwatson } 387100979Srwatson slot--; 388114846Srwatson mac_slot_offsets_free &= ~(1 << slot); 389100979Srwatson *mpc->mpc_field_off = slot; 390100979Srwatson } 391100979Srwatson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 392100979Srwatson 393114806Srwatson /* 394114806Srwatson * If we're loading a MAC module after the framework has 395114806Srwatson * initialized, it has to go into the dynamic list. If 396114806Srwatson * we're loading it before we've finished initializing, 397114806Srwatson * it can go into the static list with weaker locker 398114806Srwatson * requirements. 399114806Srwatson */ 400114806Srwatson if (static_entry) 401114806Srwatson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 402114806Srwatson else 403114806Srwatson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 404114806Srwatson 405100979Srwatson /* Per-policy initialization. */ 406100979Srwatson if (mpc->mpc_ops->mpo_init != NULL) 407100979Srwatson (*(mpc->mpc_ops->mpo_init))(mpc); 408113487Srwatson mac_policy_updateflags(); 409100979Srwatson 410100979Srwatson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 411100979Srwatson mpc->mpc_name); 412100979Srwatson 413114806Srwatsonout: 414114806Srwatson mac_policy_release_exclusive(); 415114806Srwatson return (error); 416100979Srwatson} 417100979Srwatson 418100979Srwatsonstatic int 419100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc) 420100979Srwatson{ 421100979Srwatson 422104520Srwatson /* 423104520Srwatson * If we fail the load, we may get a request to unload. Check 424104520Srwatson * to see if we did the run-time registration, and if not, 425104520Srwatson * silently succeed. 426104520Srwatson */ 427114806Srwatson mac_policy_grab_exclusive(); 428104520Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 429114806Srwatson mac_policy_release_exclusive(); 430104520Srwatson return (0); 431104520Srwatson } 432100979Srwatson#if 0 433100979Srwatson /* 434100979Srwatson * Don't allow unloading modules with private data. 435100979Srwatson */ 436104520Srwatson if (mpc->mpc_field_off != NULL) { 437104520Srwatson MAC_POLICY_LIST_UNLOCK(); 438100979Srwatson return (EBUSY); 439104520Srwatson } 440100979Srwatson#endif 441104520Srwatson /* 442104520Srwatson * Only allow the unload to proceed if the module is unloadable 443104520Srwatson * by its own definition. 444104520Srwatson */ 445104520Srwatson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 446114806Srwatson mac_policy_release_exclusive(); 447100979Srwatson return (EBUSY); 448104520Srwatson } 449100979Srwatson if (mpc->mpc_ops->mpo_destroy != NULL) 450100979Srwatson (*(mpc->mpc_ops->mpo_destroy))(mpc); 451100979Srwatson 452100979Srwatson LIST_REMOVE(mpc, mpc_list); 453106856Srwatson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 454113487Srwatson mac_policy_updateflags(); 455100979Srwatson 456114806Srwatson mac_policy_release_exclusive(); 457114806Srwatson 458100979Srwatson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 459100979Srwatson mpc->mpc_name); 460100979Srwatson 461100979Srwatson return (0); 462100979Srwatson} 463100979Srwatson 464100979Srwatson/* 465100979Srwatson * Define an error value precedence, and given two arguments, selects the 466100979Srwatson * value with the higher precedence. 467100979Srwatson */ 468121371Srwatsonint 469121371Srwatsonmac_error_select(int error1, int error2) 470100979Srwatson{ 471100979Srwatson 472100979Srwatson /* Certain decision-making errors take top priority. */ 473100979Srwatson if (error1 == EDEADLK || error2 == EDEADLK) 474100979Srwatson return (EDEADLK); 475100979Srwatson 476100979Srwatson /* Invalid arguments should be reported where possible. */ 477100979Srwatson if (error1 == EINVAL || error2 == EINVAL) 478100979Srwatson return (EINVAL); 479100979Srwatson 480100979Srwatson /* Precedence goes to "visibility", with both process and file. */ 481100979Srwatson if (error1 == ESRCH || error2 == ESRCH) 482100979Srwatson return (ESRCH); 483100979Srwatson 484100979Srwatson if (error1 == ENOENT || error2 == ENOENT) 485100979Srwatson return (ENOENT); 486100979Srwatson 487100979Srwatson /* Precedence goes to DAC/MAC protections. */ 488100979Srwatson if (error1 == EACCES || error2 == EACCES) 489100979Srwatson return (EACCES); 490100979Srwatson 491100979Srwatson /* Precedence goes to privilege. */ 492100979Srwatson if (error1 == EPERM || error2 == EPERM) 493100979Srwatson return (EPERM); 494100979Srwatson 495100979Srwatson /* Precedence goes to error over success; otherwise, arbitrary. */ 496100979Srwatson if (error1 != 0) 497100979Srwatson return (error1); 498100979Srwatson return (error2); 499100979Srwatson} 500100979Srwatson 501121374Srwatsonvoid 502104521Srwatsonmac_init_label(struct label *label) 503104521Srwatson{ 504104521Srwatson 505104521Srwatson bzero(label, sizeof(*label)); 506104521Srwatson label->l_flags = MAC_FLAG_INITIALIZED; 507104521Srwatson} 508104521Srwatson 509121374Srwatsonvoid 510104521Srwatsonmac_destroy_label(struct label *label) 511104521Srwatson{ 512104521Srwatson 513104521Srwatson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 514104521Srwatson ("destroying uninitialized label")); 515104521Srwatson 516104521Srwatson bzero(label, sizeof(*label)); 517104521Srwatson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 518104521Srwatson} 519104521Srwatson 520112675Srwatsonint 521105694Srwatsonmac_check_structmac_consistent(struct mac *mac) 522104522Srwatson{ 523105694Srwatson 524120582Srwatson if (mac->m_buflen < 0 || 525120582Srwatson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 526105694Srwatson return (EINVAL); 527105694Srwatson 528105694Srwatson return (0); 529105694Srwatson} 530105694Srwatson 531122584Srwatson/* 532122584Srwatson * MPSAFE 533122584Srwatson */ 534105988Srwatsonint 535105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 536105694Srwatson{ 537105694Srwatson char *elements, *buffer; 538105694Srwatson struct mac mac; 539105694Srwatson struct proc *tproc; 540105694Srwatson struct ucred *tcred; 541105694Srwatson int error; 542105694Srwatson 543107849Salfred error = copyin(uap->mac_p, &mac, sizeof(mac)); 544105694Srwatson if (error) 545105694Srwatson return (error); 546105694Srwatson 547105694Srwatson error = mac_check_structmac_consistent(&mac); 548105694Srwatson if (error) 549105694Srwatson return (error); 550105694Srwatson 551105694Srwatson tproc = pfind(uap->pid); 552105694Srwatson if (tproc == NULL) 553105694Srwatson return (ESRCH); 554105694Srwatson 555105694Srwatson tcred = NULL; /* Satisfy gcc. */ 556105694Srwatson error = p_cansee(td, tproc); 557105694Srwatson if (error == 0) 558105694Srwatson tcred = crhold(tproc->p_ucred); 559105694Srwatson PROC_UNLOCK(tproc); 560105694Srwatson if (error) 561105694Srwatson return (error); 562105694Srwatson 563111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 564105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 565105694Srwatson if (error) { 566105694Srwatson free(elements, M_MACTEMP); 567105694Srwatson crfree(tcred); 568105694Srwatson return (error); 569105694Srwatson } 570105694Srwatson 571111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 572122524Srwatson error = mac_externalize_cred_label(tcred->cr_label, elements, 573122159Srwatson buffer, mac.m_buflen); 574105694Srwatson if (error == 0) 575105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 576105694Srwatson 577105694Srwatson free(buffer, M_MACTEMP); 578105694Srwatson free(elements, M_MACTEMP); 579105694Srwatson crfree(tcred); 580105694Srwatson return (error); 581105694Srwatson} 582105694Srwatson 583100979Srwatson/* 584100979Srwatson * MPSAFE 585100979Srwatson */ 586100979Srwatsonint 587100894Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 588100894Srwatson{ 589105694Srwatson char *elements, *buffer; 590105694Srwatson struct mac mac; 591100979Srwatson int error; 592100894Srwatson 593105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 594105694Srwatson if (error) 595105694Srwatson return (error); 596105694Srwatson 597105694Srwatson error = mac_check_structmac_consistent(&mac); 598105694Srwatson if (error) 599105694Srwatson return (error); 600105694Srwatson 601111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 602105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 603105694Srwatson if (error) { 604105694Srwatson free(elements, M_MACTEMP); 605105694Srwatson return (error); 606105694Srwatson } 607105694Srwatson 608111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 609122524Srwatson error = mac_externalize_cred_label(td->td_ucred->cr_label, 610122159Srwatson elements, buffer, mac.m_buflen); 611100979Srwatson if (error == 0) 612105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 613100979Srwatson 614105694Srwatson free(buffer, M_MACTEMP); 615105694Srwatson free(elements, M_MACTEMP); 616100979Srwatson return (error); 617100979Srwatson} 618100979Srwatson 619100979Srwatson/* 620100979Srwatson * MPSAFE 621100979Srwatson */ 622100979Srwatsonint 623100979Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 624100979Srwatson{ 625100979Srwatson struct ucred *newcred, *oldcred; 626122524Srwatson struct label *intlabel; 627100979Srwatson struct proc *p; 628105694Srwatson struct mac mac; 629105694Srwatson char *buffer; 630100979Srwatson int error; 631100979Srwatson 632105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 633100979Srwatson if (error) 634100979Srwatson return (error); 635100979Srwatson 636105694Srwatson error = mac_check_structmac_consistent(&mac); 637100979Srwatson if (error) 638100979Srwatson return (error); 639100979Srwatson 640111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 641105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 642105694Srwatson if (error) { 643105694Srwatson free(buffer, M_MACTEMP); 644105694Srwatson return (error); 645105694Srwatson } 646105694Srwatson 647122524Srwatson intlabel = mac_cred_label_alloc(); 648122524Srwatson error = mac_internalize_cred_label(intlabel, buffer); 649105694Srwatson free(buffer, M_MACTEMP); 650122524Srwatson if (error) 651122524Srwatson goto out; 652105694Srwatson 653100979Srwatson newcred = crget(); 654100979Srwatson 655100979Srwatson p = td->td_proc; 656100979Srwatson PROC_LOCK(p); 657100979Srwatson oldcred = p->p_ucred; 658100979Srwatson 659122524Srwatson error = mac_check_cred_relabel(oldcred, intlabel); 660100979Srwatson if (error) { 661100979Srwatson PROC_UNLOCK(p); 662100979Srwatson crfree(newcred); 663105694Srwatson goto out; 664100979Srwatson } 665100979Srwatson 666100979Srwatson setsugid(p); 667100979Srwatson crcopy(newcred, oldcred); 668122524Srwatson mac_relabel_cred(newcred, intlabel); 669102136Srwatson p->p_ucred = newcred; 670100979Srwatson 671102136Srwatson /* 672102136Srwatson * Grab additional reference for use while revoking mmaps, prior 673102136Srwatson * to releasing the proc lock and sharing the cred. 674102136Srwatson */ 675102136Srwatson crhold(newcred); 676100979Srwatson PROC_UNLOCK(p); 677102136Srwatson 678105694Srwatson if (mac_enforce_vm) { 679105694Srwatson mtx_lock(&Giant); 680105694Srwatson mac_cred_mmapped_drop_perms(td, newcred); 681105694Srwatson mtx_unlock(&Giant); 682105694Srwatson } 683102136Srwatson 684102136Srwatson crfree(newcred); /* Free revocation reference. */ 685100979Srwatson crfree(oldcred); 686105694Srwatson 687105694Srwatsonout: 688122524Srwatson mac_cred_label_free(intlabel); 689105694Srwatson return (error); 690100979Srwatson} 691100979Srwatson 692100979Srwatson/* 693100979Srwatson * MPSAFE 694100979Srwatson */ 695100979Srwatsonint 696100979Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 697100979Srwatson{ 698105694Srwatson char *elements, *buffer; 699122524Srwatson struct label *intlabel; 700100979Srwatson struct file *fp; 701105694Srwatson struct mac mac; 702100979Srwatson struct vnode *vp; 703100979Srwatson struct pipe *pipe; 704122820Srwatson struct socket *so; 705105694Srwatson short label_type; 706100979Srwatson int error; 707100979Srwatson 708105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 709105694Srwatson if (error) 710105694Srwatson return (error); 711100979Srwatson 712105694Srwatson error = mac_check_structmac_consistent(&mac); 713105694Srwatson if (error) 714105694Srwatson return (error); 715105694Srwatson 716111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 717105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 718105694Srwatson if (error) { 719105694Srwatson free(elements, M_MACTEMP); 720105694Srwatson return (error); 721105694Srwatson } 722105694Srwatson 723111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 724107849Salfred error = fget(td, uap->fd, &fp); 725100979Srwatson if (error) 726100979Srwatson goto out; 727100979Srwatson 728105694Srwatson label_type = fp->f_type; 729100979Srwatson switch (fp->f_type) { 730100979Srwatson case DTYPE_FIFO: 731100979Srwatson case DTYPE_VNODE: 732116678Sphk vp = fp->f_vnode; 733122524Srwatson intlabel = mac_vnode_label_alloc(); 734122584Srwatson mtx_lock(&Giant); /* VFS */ 735100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 736122524Srwatson mac_copy_vnode_label(vp->v_label, intlabel); 737100979Srwatson VOP_UNLOCK(vp, 0, td); 738122584Srwatson mtx_unlock(&Giant); /* VFS */ 739122584Srwatson error = mac_externalize_vnode_label(intlabel, elements, 740122584Srwatson buffer, mac.m_buflen); 741122584Srwatson mac_vnode_label_free(intlabel); 742122584Srwatson break; 743105694Srwatson 744100979Srwatson case DTYPE_PIPE: 745109153Sdillon pipe = fp->f_data; 746122524Srwatson intlabel = mac_pipe_label_alloc(); 747105694Srwatson PIPE_LOCK(pipe); 748125293Srwatson mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 749105694Srwatson PIPE_UNLOCK(pipe); 750122524Srwatson error = mac_externalize_pipe_label(intlabel, elements, 751122159Srwatson buffer, mac.m_buflen); 752122524Srwatson mac_pipe_label_free(intlabel); 753105694Srwatson break; 754122584Srwatson 755122820Srwatson case DTYPE_SOCKET: 756122820Srwatson so = fp->f_data; 757122820Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 758122820Srwatson mtx_lock(&Giant); /* Sockets */ 759122820Srwatson /* XXX: Socket lock here. */ 760122820Srwatson mac_copy_socket_label(so->so_label, intlabel); 761122820Srwatson /* XXX: Socket unlock here. */ 762122820Srwatson mtx_unlock(&Giant); /* Sockets */ 763122820Srwatson error = mac_externalize_socket_label(intlabel, elements, 764122820Srwatson buffer, mac.m_buflen); 765122820Srwatson mac_socket_label_free(intlabel); 766122820Srwatson break; 767122820Srwatson 768105694Srwatson default: 769122584Srwatson error = EINVAL; 770105694Srwatson } 771122584Srwatson fdrop(fp, td); 772100979Srwatson if (error == 0) 773105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 774100979Srwatson 775105694Srwatsonout: 776105694Srwatson free(buffer, M_MACTEMP); 777105694Srwatson free(elements, M_MACTEMP); 778100979Srwatson return (error); 779100979Srwatson} 780100979Srwatson 781100979Srwatson/* 782100979Srwatson * MPSAFE 783100979Srwatson */ 784100979Srwatsonint 785100979Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 786100979Srwatson{ 787105694Srwatson char *elements, *buffer; 788100979Srwatson struct nameidata nd; 789122524Srwatson struct label *intlabel; 790105694Srwatson struct mac mac; 791100979Srwatson int error; 792100979Srwatson 793105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 794105694Srwatson if (error) 795105694Srwatson return (error); 796105694Srwatson 797105694Srwatson error = mac_check_structmac_consistent(&mac); 798105694Srwatson if (error) 799105694Srwatson return (error); 800105694Srwatson 801111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 802105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 803105694Srwatson if (error) { 804105694Srwatson free(elements, M_MACTEMP); 805105694Srwatson return (error); 806105694Srwatson } 807105694Srwatson 808111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 809105694Srwatson mtx_lock(&Giant); /* VFS */ 810105694Srwatson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 811105694Srwatson td); 812100979Srwatson error = namei(&nd); 813100979Srwatson if (error) 814100979Srwatson goto out; 815100979Srwatson 816122524Srwatson intlabel = mac_vnode_label_alloc(); 817122524Srwatson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 818122524Srwatson error = mac_externalize_vnode_label(intlabel, elements, buffer, 819122159Srwatson mac.m_buflen); 820105694Srwatson 821100979Srwatson NDFREE(&nd, 0); 822122524Srwatson mac_vnode_label_free(intlabel); 823105694Srwatson 824105694Srwatson if (error == 0) 825105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 826105694Srwatson 827105694Srwatsonout: 828105694Srwatson mtx_unlock(&Giant); /* VFS */ 829105694Srwatson 830105694Srwatson free(buffer, M_MACTEMP); 831105694Srwatson free(elements, M_MACTEMP); 832105694Srwatson 833105694Srwatson return (error); 834105694Srwatson} 835105694Srwatson 836105694Srwatson/* 837105694Srwatson * MPSAFE 838105694Srwatson */ 839105694Srwatsonint 840105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 841105694Srwatson{ 842105694Srwatson char *elements, *buffer; 843105694Srwatson struct nameidata nd; 844122524Srwatson struct label *intlabel; 845105694Srwatson struct mac mac; 846105694Srwatson int error; 847105694Srwatson 848105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 849100979Srwatson if (error) 850105694Srwatson return (error); 851105694Srwatson 852105694Srwatson error = mac_check_structmac_consistent(&mac); 853105694Srwatson if (error) 854105694Srwatson return (error); 855105694Srwatson 856111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 857105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 858105694Srwatson if (error) { 859105694Srwatson free(elements, M_MACTEMP); 860105694Srwatson return (error); 861105694Srwatson } 862105694Srwatson 863111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 864105694Srwatson mtx_lock(&Giant); /* VFS */ 865105694Srwatson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 866105694Srwatson td); 867105694Srwatson error = namei(&nd); 868105694Srwatson if (error) 869100979Srwatson goto out; 870100979Srwatson 871122524Srwatson intlabel = mac_vnode_label_alloc(); 872122524Srwatson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 873122524Srwatson error = mac_externalize_vnode_label(intlabel, elements, buffer, 874122159Srwatson mac.m_buflen); 875105694Srwatson NDFREE(&nd, 0); 876122524Srwatson mac_vnode_label_free(intlabel); 877100979Srwatson 878105694Srwatson if (error == 0) 879105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 880105694Srwatson 881100979Srwatsonout: 882105694Srwatson mtx_unlock(&Giant); /* VFS */ 883105694Srwatson 884105694Srwatson free(buffer, M_MACTEMP); 885105694Srwatson free(elements, M_MACTEMP); 886105694Srwatson 887100979Srwatson return (error); 888100979Srwatson} 889100979Srwatson 890100979Srwatson/* 891100979Srwatson * MPSAFE 892100979Srwatson */ 893100979Srwatsonint 894100979Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 895100979Srwatson{ 896122524Srwatson struct label *intlabel; 897105694Srwatson struct pipe *pipe; 898122820Srwatson struct socket *so; 899100979Srwatson struct file *fp; 900100979Srwatson struct mount *mp; 901100979Srwatson struct vnode *vp; 902105694Srwatson struct mac mac; 903105694Srwatson char *buffer; 904100979Srwatson int error; 905100979Srwatson 906105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 907100979Srwatson if (error) 908105694Srwatson return (error); 909100979Srwatson 910105694Srwatson error = mac_check_structmac_consistent(&mac); 911100979Srwatson if (error) 912105694Srwatson return (error); 913100979Srwatson 914111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 915105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 916105694Srwatson if (error) { 917105694Srwatson free(buffer, M_MACTEMP); 918105694Srwatson return (error); 919105694Srwatson } 920105694Srwatson 921107849Salfred error = fget(td, uap->fd, &fp); 922100979Srwatson if (error) 923105694Srwatson goto out; 924100979Srwatson 925100979Srwatson switch (fp->f_type) { 926100979Srwatson case DTYPE_FIFO: 927100979Srwatson case DTYPE_VNODE: 928122524Srwatson intlabel = mac_vnode_label_alloc(); 929122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 930105694Srwatson if (error) { 931122524Srwatson mac_vnode_label_free(intlabel); 932105694Srwatson break; 933105694Srwatson } 934116678Sphk vp = fp->f_vnode; 935122584Srwatson mtx_lock(&Giant); /* VFS */ 936100979Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 937105694Srwatson if (error != 0) { 938122584Srwatson mtx_unlock(&Giant); /* VFS */ 939122524Srwatson mac_vnode_label_free(intlabel); 940100979Srwatson break; 941105694Srwatson } 942100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 943122524Srwatson error = vn_setlabel(vp, intlabel, td->td_ucred); 944100979Srwatson VOP_UNLOCK(vp, 0, td); 945100979Srwatson vn_finished_write(mp); 946122584Srwatson mtx_unlock(&Giant); /* VFS */ 947122524Srwatson mac_vnode_label_free(intlabel); 948100979Srwatson break; 949105694Srwatson 950100979Srwatson case DTYPE_PIPE: 951122524Srwatson intlabel = mac_pipe_label_alloc(); 952122524Srwatson error = mac_internalize_pipe_label(intlabel, buffer); 953105694Srwatson if (error == 0) { 954109153Sdillon pipe = fp->f_data; 955105694Srwatson PIPE_LOCK(pipe); 956125293Srwatson error = mac_pipe_label_set(td->td_ucred, 957125293Srwatson pipe->pipe_pair, intlabel); 958105694Srwatson PIPE_UNLOCK(pipe); 959105694Srwatson } 960122524Srwatson mac_pipe_label_free(intlabel); 961100979Srwatson break; 962105694Srwatson 963122820Srwatson case DTYPE_SOCKET: 964122820Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 965122820Srwatson error = mac_internalize_socket_label(intlabel, buffer); 966122820Srwatson if (error == 0) { 967122820Srwatson so = fp->f_data; 968122820Srwatson mtx_lock(&Giant); /* Sockets */ 969122820Srwatson /* XXX: Socket lock here. */ 970122820Srwatson error = mac_socket_label_set(td->td_ucred, so, 971122820Srwatson intlabel); 972122820Srwatson /* XXX: Socket unlock here. */ 973122820Srwatson mtx_unlock(&Giant); /* Sockets */ 974122820Srwatson } 975122820Srwatson mac_socket_label_free(intlabel); 976122820Srwatson break; 977122820Srwatson 978100979Srwatson default: 979100979Srwatson error = EINVAL; 980100979Srwatson } 981100979Srwatson fdrop(fp, td); 982105694Srwatsonout: 983105694Srwatson free(buffer, M_MACTEMP); 984100979Srwatson return (error); 985100979Srwatson} 986100979Srwatson 987100979Srwatson/* 988100979Srwatson * MPSAFE 989100979Srwatson */ 990100979Srwatsonint 991100979Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 992100979Srwatson{ 993122524Srwatson struct label *intlabel; 994100979Srwatson struct nameidata nd; 995100979Srwatson struct mount *mp; 996105694Srwatson struct mac mac; 997105694Srwatson char *buffer; 998100979Srwatson int error; 999100979Srwatson 1000105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1001100979Srwatson if (error) 1002105694Srwatson return (error); 1003100979Srwatson 1004105694Srwatson error = mac_check_structmac_consistent(&mac); 1005100979Srwatson if (error) 1006105694Srwatson return (error); 1007100979Srwatson 1008111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1009105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1010105694Srwatson if (error) { 1011105694Srwatson free(buffer, M_MACTEMP); 1012105694Srwatson return (error); 1013105694Srwatson } 1014105694Srwatson 1015122524Srwatson intlabel = mac_vnode_label_alloc(); 1016122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 1017105694Srwatson free(buffer, M_MACTEMP); 1018122524Srwatson if (error) 1019122524Srwatson goto out; 1020105694Srwatson 1021105694Srwatson mtx_lock(&Giant); /* VFS */ 1022105694Srwatson 1023105694Srwatson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 1024105694Srwatson td); 1025100979Srwatson error = namei(&nd); 1026105694Srwatson if (error == 0) { 1027105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1028105694Srwatson if (error == 0) 1029122524Srwatson error = vn_setlabel(nd.ni_vp, intlabel, 1030105694Srwatson td->td_ucred); 1031105694Srwatson vn_finished_write(mp); 1032105694Srwatson } 1033105694Srwatson 1034105694Srwatson NDFREE(&nd, 0); 1035105694Srwatson mtx_unlock(&Giant); /* VFS */ 1036122524Srwatsonout: 1037122524Srwatson mac_vnode_label_free(intlabel); 1038105694Srwatson return (error); 1039105694Srwatson} 1040105694Srwatson 1041105694Srwatson/* 1042105694Srwatson * MPSAFE 1043105694Srwatson */ 1044105694Srwatsonint 1045105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1046105694Srwatson{ 1047122524Srwatson struct label *intlabel; 1048105694Srwatson struct nameidata nd; 1049105694Srwatson struct mount *mp; 1050105694Srwatson struct mac mac; 1051105694Srwatson char *buffer; 1052105694Srwatson int error; 1053105694Srwatson 1054105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1055100979Srwatson if (error) 1056105694Srwatson return (error); 1057105694Srwatson 1058105694Srwatson error = mac_check_structmac_consistent(&mac); 1059100979Srwatson if (error) 1060105694Srwatson return (error); 1061100979Srwatson 1062111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1063105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1064105694Srwatson if (error) { 1065105694Srwatson free(buffer, M_MACTEMP); 1066105694Srwatson return (error); 1067105694Srwatson } 1068105694Srwatson 1069122524Srwatson intlabel = mac_vnode_label_alloc(); 1070122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 1071105694Srwatson free(buffer, M_MACTEMP); 1072122524Srwatson if (error) 1073122524Srwatson goto out; 1074105694Srwatson 1075105694Srwatson mtx_lock(&Giant); /* VFS */ 1076105694Srwatson 1077105694Srwatson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 1078105694Srwatson td); 1079105694Srwatson error = namei(&nd); 1080105694Srwatson if (error == 0) { 1081105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1082105694Srwatson if (error == 0) 1083122524Srwatson error = vn_setlabel(nd.ni_vp, intlabel, 1084105694Srwatson td->td_ucred); 1085105694Srwatson vn_finished_write(mp); 1086105694Srwatson } 1087105694Srwatson 1088100979Srwatson NDFREE(&nd, 0); 1089105694Srwatson mtx_unlock(&Giant); /* VFS */ 1090122524Srwatsonout: 1091122524Srwatson mac_vnode_label_free(intlabel); 1092100979Srwatson return (error); 1093100979Srwatson} 1094100979Srwatson 1095105694Srwatson/* 1096105694Srwatson * MPSAFE 1097105694Srwatson */ 1098102123Srwatsonint 1099102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1100102123Srwatson{ 1101102123Srwatson struct mac_policy_conf *mpc; 1102102123Srwatson char target[MAC_MAX_POLICY_NAME]; 1103114806Srwatson int entrycount, error; 1104102123Srwatson 1105107849Salfred error = copyinstr(uap->policy, target, sizeof(target), NULL); 1106102123Srwatson if (error) 1107102123Srwatson return (error); 1108102123Srwatson 1109102123Srwatson error = ENOSYS; 1110119494Srwatson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1111102123Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1112102123Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1113102123Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1114107849Salfred uap->call, uap->arg); 1115102123Srwatson goto out; 1116102123Srwatson } 1117102123Srwatson } 1118102123Srwatson 1119114806Srwatson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1120114806Srwatson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1121114806Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1122114806Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1123114806Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1124114806Srwatson uap->call, uap->arg); 1125114806Srwatson break; 1126114806Srwatson } 1127114806Srwatson } 1128114806Srwatson mac_policy_list_unbusy(); 1129114806Srwatson } 1130102123Srwatsonout: 1131102123Srwatson return (error); 1132102123Srwatson} 1133102123Srwatson 1134100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1135100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1136100979Srwatson 1137100979Srwatson#else /* !MAC */ 1138100979Srwatson 1139100979Srwatsonint 1140105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1141105694Srwatson{ 1142105694Srwatson 1143105694Srwatson return (ENOSYS); 1144105694Srwatson} 1145105694Srwatson 1146105694Srwatsonint 1147100979Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1148100979Srwatson{ 1149100979Srwatson 1150100894Srwatson return (ENOSYS); 1151100894Srwatson} 1152100894Srwatson 1153100894Srwatsonint 1154100894Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1155100894Srwatson{ 1156100894Srwatson 1157100894Srwatson return (ENOSYS); 1158100894Srwatson} 1159100894Srwatson 1160100894Srwatsonint 1161100894Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1162100894Srwatson{ 1163100894Srwatson 1164100894Srwatson return (ENOSYS); 1165100894Srwatson} 1166100894Srwatson 1167100894Srwatsonint 1168100894Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1169100894Srwatson{ 1170100894Srwatson 1171100894Srwatson return (ENOSYS); 1172100894Srwatson} 1173100894Srwatson 1174100894Srwatsonint 1175105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1176105694Srwatson{ 1177105694Srwatson 1178105694Srwatson return (ENOSYS); 1179105694Srwatson} 1180105694Srwatson 1181105694Srwatsonint 1182100894Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1183100894Srwatson{ 1184100894Srwatson 1185100894Srwatson return (ENOSYS); 1186100894Srwatson} 1187100894Srwatson 1188100894Srwatsonint 1189100894Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1190100894Srwatson{ 1191100894Srwatson 1192100894Srwatson return (ENOSYS); 1193100894Srwatson} 1194100979Srwatson 1195102123Srwatsonint 1196105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1197105694Srwatson{ 1198105694Srwatson 1199105694Srwatson return (ENOSYS); 1200105694Srwatson} 1201105694Srwatson 1202105694Srwatsonint 1203102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1204102123Srwatson{ 1205102123Srwatson 1206102123Srwatson return (ENOSYS); 1207102123Srwatson} 1208102123Srwatson 1209105694Srwatson#endif 1210