mac_syscalls.c revision 165411
1100894Srwatson/*- 2126097Srwatson * Copyright (c) 1999-2002 Robert N. M. Watson 3100894Srwatson * Copyright (c) 2001 Ilmar S. Habibulin 4145160Srwatson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 5163606Srwatson * Copyright (c) 2005-2006 SPARTA, Inc. 6100894Srwatson * All rights reserved. 7100894Srwatson * 8100894Srwatson * This software was developed by Robert Watson and Ilmar Habibulin for the 9100894Srwatson * TrustedBSD Project. 10100894Srwatson * 11106392Srwatson * This software was developed for the FreeBSD Project in part by Network 12106392Srwatson * Associates Laboratories, the Security Research Division of Network 13106392Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 14106392Srwatson * as part of the DARPA CHATS research program. 15100894Srwatson * 16147983Srwatson * This software was enhanced by SPARTA ISSO under SPAWAR contract 17147983Srwatson * N66001-04-C-6019 ("SEFOS"). 18147983Srwatson * 19100894Srwatson * Redistribution and use in source and binary forms, with or without 20100894Srwatson * modification, are permitted provided that the following conditions 21100894Srwatson * are met: 22100894Srwatson * 1. Redistributions of source code must retain the above copyright 23100894Srwatson * notice, this list of conditions and the following disclaimer. 24100894Srwatson * 2. Redistributions in binary form must reproduce the above copyright 25100894Srwatson * notice, this list of conditions and the following disclaimer in the 26100894Srwatson * documentation and/or other materials provided with the distribution. 27100894Srwatson * 28100894Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 29100894Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30100894Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31100894Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 32100894Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33100894Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34100894Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35100894Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36100894Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37100894Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38100894Srwatson * SUCH DAMAGE. 39100894Srwatson */ 40116182Sobrien 41122454Srwatson/*- 42122454Srwatson * Framework for extensible kernel access control. This file contains 43122454Srwatson * Kernel and userland interface to the framework, policy registration 44122454Srwatson * and composition. Per-object interfaces, controls, and labeling may be 45145414Strhodes * found in src/sys/security/mac/. Sample policies may be found in 46145414Strhodes * src/sys/security/mac_*. 47100894Srwatson */ 48100894Srwatson 49116182Sobrien#include <sys/cdefs.h> 50116182Sobrien__FBSDID("$FreeBSD: head/sys/security/mac/mac_syscalls.c 165411 2006-12-20 20:38:44Z rwatson $"); 51116182Sobrien 52100894Srwatson#include "opt_mac.h" 53101173Srwatson 54100894Srwatson#include <sys/param.h> 55106856Srwatson#include <sys/condvar.h> 56100979Srwatson#include <sys/extattr.h> 57106468Srwatson#include <sys/imgact.h> 58100979Srwatson#include <sys/kernel.h> 59100979Srwatson#include <sys/lock.h> 60102949Sbde#include <sys/malloc.h> 61100979Srwatson#include <sys/mutex.h> 62100979Srwatson#include <sys/mac.h> 63101712Srwatson#include <sys/module.h> 64100979Srwatson#include <sys/proc.h> 65116701Srwatson#include <sys/sbuf.h> 66100979Srwatson#include <sys/systm.h> 67100894Srwatson#include <sys/sysproto.h> 68100894Srwatson#include <sys/sysent.h> 69100979Srwatson#include <sys/vnode.h> 70100979Srwatson#include <sys/mount.h> 71100979Srwatson#include <sys/file.h> 72100979Srwatson#include <sys/namei.h> 73100979Srwatson#include <sys/socket.h> 74100979Srwatson#include <sys/pipe.h> 75100979Srwatson#include <sys/socketvar.h> 76100979Srwatson#include <sys/sysctl.h> 77100894Srwatson 78100979Srwatson#include <vm/vm.h> 79100979Srwatson#include <vm/pmap.h> 80100979Srwatson#include <vm/vm_map.h> 81100979Srwatson#include <vm/vm_object.h> 82100979Srwatson 83100979Srwatson#include <sys/mac_policy.h> 84100979Srwatson 85100979Srwatson#include <fs/devfs/devfs.h> 86100979Srwatson 87100979Srwatson#include <net/bpfdesc.h> 88100979Srwatson#include <net/if.h> 89100979Srwatson#include <net/if_var.h> 90100979Srwatson 91100979Srwatson#include <netinet/in.h> 92100979Srwatson#include <netinet/ip_var.h> 93100979Srwatson 94163606Srwatson#include <security/mac/mac_framework.h> 95121374Srwatson#include <security/mac/mac_internal.h> 96121374Srwatson 97100979Srwatson#ifdef MAC 98100979Srwatson 99101712Srwatson/* 100101712Srwatson * Declare that the kernel provides MAC support, version 1. This permits 101101712Srwatson * modules to refuse to be loaded if the necessary support isn't present, 102101712Srwatson * even if it's pre-boot. 103101712Srwatson */ 104147983SrwatsonMODULE_VERSION(kernel_mac_support, 3); 105101712Srwatson 106100979SrwatsonSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 107100979Srwatson "TrustedBSD MAC policy controls"); 108104517Srwatson 109165411Srwatson/* 110165411Srwatson * Labels consist of a indexed set of "slots", which are allocated policies 111165411Srwatson * as required. The MAC Framework maintains a bitmask of slots allocated so 112165411Srwatson * far to prevent reuse. Slots cannot be reused, as the MAC Framework 113165411Srwatson * guarantees that newly allocated slots in labels will be NULL unless 114165411Srwatson * otherwise initialized, and because we do not have a mechanism to garbage 115165411Srwatson * collect slots on policy unload. As labeled policies tend to be statically 116165411Srwatson * loaded during boot, and not frequently unloaded and reloaded, this is not 117165411Srwatson * generally an issue. 118165411Srwatson */ 119114846Srwatson#if MAC_MAX_SLOTS > 32 120114846Srwatson#error "MAC_MAX_SLOTS too large" 121100979Srwatson#endif 122105497Srwatson 123114846Srwatsonstatic unsigned int mac_max_slots = MAC_MAX_SLOTS; 124114846Srwatsonstatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 125114846SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 126114846Srwatson &mac_max_slots, 0, ""); 127100979Srwatson 128105959Srwatson/* 129105959Srwatson * Has the kernel started generating labeled objects yet? All read/write 130105959Srwatson * access to this variable is serialized during the boot process. Following 131105959Srwatson * the end of serialization, we don't update this flag; no locking. 132105959Srwatson */ 133121372Srwatsonint mac_late = 0; 134100979Srwatson 135105988Srwatson/* 136165411Srwatson * Flag to indicate whether or not we should allocate label storage for new 137165411Srwatson * mbufs. Since most dynamic policies we currently work with don't rely on 138165411Srwatson * mbuf labeling, try to avoid paying the cost of mtag allocation unless 139165411Srwatson * specifically notified of interest. One result of this is that if a 140165411Srwatson * dynamically loaded policy requests mbuf labels, it must be able to deal 141165411Srwatson * with a NULL label being returned on any mbufs that were already in flight 142165411Srwatson * when the policy was loaded. Since the policy already has to deal with 143165411Srwatson * uninitialized labels, this probably won't be a problem. Note: currently 144165411Srwatson * no locking. Will this be a problem? 145165411Srwatson * 146165411Srwatson * In the future, we may want to allow objects to request labeling on a per- 147165411Srwatson * object type basis, rather than globally for all objects. 148113487Srwatson */ 149118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF 150121372Srwatsonint mac_labelmbufs = 0; 151113487Srwatson#endif 152113487Srwatson 153100979Srwatsonstatic int mac_policy_register(struct mac_policy_conf *mpc); 154100979Srwatsonstatic int mac_policy_unregister(struct mac_policy_conf *mpc); 155100979Srwatson 156105694SrwatsonMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 157100979Srwatson 158100979Srwatson/* 159165411Srwatson * mac_static_policy_list holds a list of policy modules that are not loaded 160165411Srwatson * while the system is "live", and cannot be unloaded. These policies can be 161165411Srwatson * invoked without holding the busy count. 162114806Srwatson * 163114806Srwatson * mac_policy_list stores the list of dynamic policies. A busy count is 164165411Srwatson * maintained for the list, stored in mac_policy_busy. The busy count is 165165411Srwatson * protected by mac_policy_mtx; the list may be modified only while the busy 166165411Srwatson * count is 0, requiring that the lock be held to prevent new references to 167165411Srwatson * the list from being acquired. For almost all operations, incrementing the 168165411Srwatson * busy count is sufficient to guarantee consistency, as the list cannot be 169165411Srwatson * modified while the busy count is elevated. For a few special operations 170165411Srwatson * involving a change to the list of active policies, the mtx itself must be 171165411Srwatson * held. A condition variable, mac_policy_cv, is used to signal potential 172165411Srwatson * exclusive consumers that they should try to acquire the lock if a first 173165411Srwatson * attempt at exclusive access fails. 174165411Srwatson * 175165411Srwatson * This design intentionally avoids fairness, and may starve attempts to 176165411Srwatson * acquire an exclusive lock on a busy system. This is required because we 177165411Srwatson * do not ever want acquiring a read reference to perform an unbounded length 178165411Srwatson * sleep. Read references are acquired in ithreads, network isrs, etc, and 179165411Srwatson * any unbounded blocking could lead quickly to deadlock. 180165411Srwatson * 181165411Srwatson * Another reason for never blocking on read references is that the MAC 182165411Srwatson * Framework may recurse: if a policy calls a VOP, for example, this might 183165411Srwatson * lead to vnode life cycle operations (such as init/destroy). 184100979Srwatson */ 185128885Srwatson#ifndef MAC_STATIC 186114806Srwatsonstatic struct mtx mac_policy_mtx; 187114806Srwatsonstatic struct cv mac_policy_cv; 188114806Srwatsonstatic int mac_policy_count; 189128885Srwatson#endif 190121372Srwatsonstruct mac_policy_list_head mac_policy_list; 191121372Srwatsonstruct mac_policy_list_head mac_static_policy_list; 192100979Srwatson 193106856Srwatson/* 194165411Srwatson * We manually invoke WITNESS_WARN() to allow Witness to generate warnings 195165411Srwatson * even if we don't end up ever triggering the wait at run-time. The 196165411Srwatson * consumer of the exclusive interface must not hold any locks (other than 197165411Srwatson * potentially Giant) since we may sleep for long (potentially indefinite) 198165411Srwatson * periods of time waiting for the framework to become quiescent so that a 199165411Srwatson * policy list change may be made. 200106856Srwatson */ 201121372Srwatsonvoid 202114806Srwatsonmac_policy_grab_exclusive(void) 203114806Srwatson{ 204122454Srwatson 205128885Srwatson#ifndef MAC_STATIC 206137072Srwatson if (!mac_late) 207137072Srwatson return; 208137072Srwatson 209114806Srwatson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 210114806Srwatson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 211114806Srwatson mtx_lock(&mac_policy_mtx); 212114806Srwatson while (mac_policy_count != 0) 213114806Srwatson cv_wait(&mac_policy_cv, &mac_policy_mtx); 214128885Srwatson#endif 215114806Srwatson} 216106856Srwatson 217121372Srwatsonvoid 218114806Srwatsonmac_policy_assert_exclusive(void) 219114806Srwatson{ 220122454Srwatson 221128885Srwatson#ifndef MAC_STATIC 222137072Srwatson if (!mac_late) 223137072Srwatson return; 224137072Srwatson 225114806Srwatson mtx_assert(&mac_policy_mtx, MA_OWNED); 226114806Srwatson KASSERT(mac_policy_count == 0, 227114806Srwatson ("mac_policy_assert_exclusive(): not exclusive")); 228128885Srwatson#endif 229114806Srwatson} 230113487Srwatson 231121372Srwatsonvoid 232114806Srwatsonmac_policy_release_exclusive(void) 233114806Srwatson{ 234100979Srwatson 235128885Srwatson#ifndef MAC_STATIC 236137072Srwatson if (!mac_late) 237137072Srwatson return; 238137072Srwatson 239114806Srwatson KASSERT(mac_policy_count == 0, 240114806Srwatson ("mac_policy_release_exclusive(): not exclusive")); 241114806Srwatson mtx_unlock(&mac_policy_mtx); 242114806Srwatson cv_signal(&mac_policy_cv); 243128885Srwatson#endif 244114806Srwatson} 245100979Srwatson 246121372Srwatsonvoid 247114806Srwatsonmac_policy_list_busy(void) 248114806Srwatson{ 249122454Srwatson 250128885Srwatson#ifndef MAC_STATIC 251137072Srwatson if (!mac_late) 252137072Srwatson return; 253137072Srwatson 254114806Srwatson mtx_lock(&mac_policy_mtx); 255114806Srwatson mac_policy_count++; 256114806Srwatson mtx_unlock(&mac_policy_mtx); 257128885Srwatson#endif 258114806Srwatson} 259114806Srwatson 260121372Srwatsonint 261114806Srwatsonmac_policy_list_conditional_busy(void) 262114806Srwatson{ 263128885Srwatson#ifndef MAC_STATIC 264114806Srwatson int ret; 265114806Srwatson 266137072Srwatson if (!mac_late) 267137072Srwatson return (1); 268137072Srwatson 269114806Srwatson mtx_lock(&mac_policy_mtx); 270114806Srwatson if (!LIST_EMPTY(&mac_policy_list)) { 271114806Srwatson mac_policy_count++; 272114806Srwatson ret = 1; 273114806Srwatson } else 274114806Srwatson ret = 0; 275114806Srwatson mtx_unlock(&mac_policy_mtx); 276114806Srwatson return (ret); 277128885Srwatson#else 278137072Srwatson if (!mac_late) 279137072Srwatson return (1); 280137072Srwatson 281128885Srwatson return (1); 282128885Srwatson#endif 283114806Srwatson} 284114806Srwatson 285121372Srwatsonvoid 286114806Srwatsonmac_policy_list_unbusy(void) 287114806Srwatson{ 288122454Srwatson 289128885Srwatson#ifndef MAC_STATIC 290137072Srwatson if (!mac_late) 291137072Srwatson return; 292137072Srwatson 293114806Srwatson mtx_lock(&mac_policy_mtx); 294114806Srwatson mac_policy_count--; 295114806Srwatson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 296114806Srwatson if (mac_policy_count == 0) 297114806Srwatson cv_signal(&mac_policy_cv); 298114806Srwatson mtx_unlock(&mac_policy_mtx); 299128885Srwatson#endif 300114806Srwatson} 301114806Srwatson 302100979Srwatson/* 303100979Srwatson * Initialize the MAC subsystem, including appropriate SMP locks. 304100979Srwatson */ 305100979Srwatsonstatic void 306100979Srwatsonmac_init(void) 307100979Srwatson{ 308100979Srwatson 309114806Srwatson LIST_INIT(&mac_static_policy_list); 310100979Srwatson LIST_INIT(&mac_policy_list); 311122524Srwatson mac_labelzone_init(); 312114806Srwatson 313128885Srwatson#ifndef MAC_STATIC 314114806Srwatson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 315114806Srwatson cv_init(&mac_policy_cv, "mac_policy_cv"); 316128885Srwatson#endif 317100979Srwatson} 318100979Srwatson 319100979Srwatson/* 320165411Srwatson * For the purposes of modules that want to know if they were loaded "early", 321165411Srwatson * set the mac_late flag once we've processed modules either linked into the 322165411Srwatson * kernel, or loaded before the kernel startup. 323100979Srwatson */ 324100979Srwatsonstatic void 325100979Srwatsonmac_late_init(void) 326100979Srwatson{ 327100979Srwatson 328100979Srwatson mac_late = 1; 329100979Srwatson} 330100979Srwatson 331100979Srwatson/* 332113487Srwatson * After the policy list has changed, walk the list to update any global 333118308Srwatson * flags. Currently, we support only one flag, and it's conditionally 334165411Srwatson * defined; as a result, the entire function is conditional. Eventually, the 335165411Srwatson * #else case might also iterate across the policies. 336113487Srwatson */ 337113487Srwatsonstatic void 338113487Srwatsonmac_policy_updateflags(void) 339113487Srwatson{ 340118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF 341113487Srwatson struct mac_policy_conf *tmpc; 342113487Srwatson int labelmbufs; 343113487Srwatson 344114806Srwatson mac_policy_assert_exclusive(); 345113487Srwatson 346113487Srwatson labelmbufs = 0; 347114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 348114806Srwatson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 349114806Srwatson labelmbufs++; 350114806Srwatson } 351113487Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 352113487Srwatson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 353113487Srwatson labelmbufs++; 354113487Srwatson } 355113487Srwatson mac_labelmbufs = (labelmbufs != 0); 356113487Srwatson#endif 357113487Srwatson} 358113487Srwatson 359113487Srwatson/* 360100979Srwatson * Allow MAC policy modules to register during boot, etc. 361100979Srwatson */ 362100894Srwatsonint 363100979Srwatsonmac_policy_modevent(module_t mod, int type, void *data) 364100979Srwatson{ 365100979Srwatson struct mac_policy_conf *mpc; 366100979Srwatson int error; 367100979Srwatson 368100979Srwatson error = 0; 369100979Srwatson mpc = (struct mac_policy_conf *) data; 370100979Srwatson 371128885Srwatson#ifdef MAC_STATIC 372128885Srwatson if (mac_late) { 373128885Srwatson printf("mac_policy_modevent: MAC_STATIC and late\n"); 374128885Srwatson return (EBUSY); 375128885Srwatson } 376128885Srwatson#endif 377128885Srwatson 378100979Srwatson switch (type) { 379100979Srwatson case MOD_LOAD: 380100979Srwatson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 381100979Srwatson mac_late) { 382100979Srwatson printf("mac_policy_modevent: can't load %s policy " 383100979Srwatson "after booting\n", mpc->mpc_name); 384100979Srwatson error = EBUSY; 385100979Srwatson break; 386100979Srwatson } 387100979Srwatson error = mac_policy_register(mpc); 388100979Srwatson break; 389100979Srwatson case MOD_UNLOAD: 390100979Srwatson /* Don't unregister the module if it was never registered. */ 391100979Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 392100979Srwatson != 0) 393100979Srwatson error = mac_policy_unregister(mpc); 394100979Srwatson else 395100979Srwatson error = 0; 396100979Srwatson break; 397100979Srwatson default: 398132199Sphk error = EOPNOTSUPP; 399100979Srwatson break; 400100979Srwatson } 401100979Srwatson 402100979Srwatson return (error); 403100979Srwatson} 404100979Srwatson 405100979Srwatsonstatic int 406100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc) 407100979Srwatson{ 408100979Srwatson struct mac_policy_conf *tmpc; 409114806Srwatson int error, slot, static_entry; 410100979Srwatson 411114806Srwatson error = 0; 412114806Srwatson 413114806Srwatson /* 414165411Srwatson * We don't technically need exclusive access while !mac_late, but 415165411Srwatson * hold it for assertion consistency. 416114806Srwatson */ 417114806Srwatson mac_policy_grab_exclusive(); 418114806Srwatson 419114806Srwatson /* 420165411Srwatson * If the module can potentially be unloaded, or we're loading late, 421165411Srwatson * we have to stick it in the non-static list and pay an extra 422165411Srwatson * performance overhead. Otherwise, we can pay a light locking cost 423165411Srwatson * and stick it in the static list. 424114806Srwatson */ 425114806Srwatson static_entry = (!mac_late && 426114806Srwatson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 427114806Srwatson 428114806Srwatson if (static_entry) { 429114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 430114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 431114806Srwatson error = EEXIST; 432114806Srwatson goto out; 433114806Srwatson } 434100979Srwatson } 435114806Srwatson } else { 436114806Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 437114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 438114806Srwatson error = EEXIST; 439114806Srwatson goto out; 440114806Srwatson } 441114806Srwatson } 442100979Srwatson } 443100979Srwatson if (mpc->mpc_field_off != NULL) { 444114846Srwatson slot = ffs(mac_slot_offsets_free); 445100979Srwatson if (slot == 0) { 446114806Srwatson error = ENOMEM; 447114806Srwatson goto out; 448100979Srwatson } 449100979Srwatson slot--; 450114846Srwatson mac_slot_offsets_free &= ~(1 << slot); 451100979Srwatson *mpc->mpc_field_off = slot; 452100979Srwatson } 453100979Srwatson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 454100979Srwatson 455114806Srwatson /* 456165411Srwatson * If we're loading a MAC module after the framework has initialized, 457165411Srwatson * it has to go into the dynamic list. If we're loading it before 458165411Srwatson * we've finished initializing, it can go into the static list with 459165411Srwatson * weaker locker requirements. 460114806Srwatson */ 461114806Srwatson if (static_entry) 462114806Srwatson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 463114806Srwatson else 464114806Srwatson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 465114806Srwatson 466165411Srwatson /* 467165411Srwatson * Per-policy initialization. Currently, this takes place under the 468165411Srwatson * exclusive lock, so policies must not sleep in their init method. 469165411Srwatson * In the future, we may want to separate "init" from "start", with 470165411Srwatson * "init" occuring without the lock held. Likewise, on tear-down, 471165411Srwatson * breaking out "stop" from "destroy". 472165411Srwatson */ 473100979Srwatson if (mpc->mpc_ops->mpo_init != NULL) 474100979Srwatson (*(mpc->mpc_ops->mpo_init))(mpc); 475113487Srwatson mac_policy_updateflags(); 476100979Srwatson 477100979Srwatson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 478100979Srwatson mpc->mpc_name); 479100979Srwatson 480114806Srwatsonout: 481114806Srwatson mac_policy_release_exclusive(); 482114806Srwatson return (error); 483100979Srwatson} 484100979Srwatson 485100979Srwatsonstatic int 486100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc) 487100979Srwatson{ 488100979Srwatson 489104520Srwatson /* 490165411Srwatson * If we fail the load, we may get a request to unload. Check to see 491165411Srwatson * if we did the run-time registration, and if not, silently succeed. 492104520Srwatson */ 493114806Srwatson mac_policy_grab_exclusive(); 494104520Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 495114806Srwatson mac_policy_release_exclusive(); 496104520Srwatson return (0); 497104520Srwatson } 498100979Srwatson#if 0 499100979Srwatson /* 500100979Srwatson * Don't allow unloading modules with private data. 501100979Srwatson */ 502104520Srwatson if (mpc->mpc_field_off != NULL) { 503104520Srwatson MAC_POLICY_LIST_UNLOCK(); 504100979Srwatson return (EBUSY); 505104520Srwatson } 506100979Srwatson#endif 507104520Srwatson /* 508165411Srwatson * Only allow the unload to proceed if the module is unloadable by 509165411Srwatson * its own definition. 510104520Srwatson */ 511104520Srwatson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 512114806Srwatson mac_policy_release_exclusive(); 513100979Srwatson return (EBUSY); 514104520Srwatson } 515100979Srwatson if (mpc->mpc_ops->mpo_destroy != NULL) 516100979Srwatson (*(mpc->mpc_ops->mpo_destroy))(mpc); 517100979Srwatson 518100979Srwatson LIST_REMOVE(mpc, mpc_list); 519106856Srwatson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 520113487Srwatson mac_policy_updateflags(); 521100979Srwatson 522114806Srwatson mac_policy_release_exclusive(); 523114806Srwatson 524100979Srwatson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 525100979Srwatson mpc->mpc_name); 526100979Srwatson 527100979Srwatson return (0); 528100979Srwatson} 529100979Srwatson 530100979Srwatson/* 531100979Srwatson * Define an error value precedence, and given two arguments, selects the 532100979Srwatson * value with the higher precedence. 533100979Srwatson */ 534121371Srwatsonint 535121371Srwatsonmac_error_select(int error1, int error2) 536100979Srwatson{ 537100979Srwatson 538100979Srwatson /* Certain decision-making errors take top priority. */ 539100979Srwatson if (error1 == EDEADLK || error2 == EDEADLK) 540100979Srwatson return (EDEADLK); 541100979Srwatson 542100979Srwatson /* Invalid arguments should be reported where possible. */ 543100979Srwatson if (error1 == EINVAL || error2 == EINVAL) 544100979Srwatson return (EINVAL); 545100979Srwatson 546100979Srwatson /* Precedence goes to "visibility", with both process and file. */ 547100979Srwatson if (error1 == ESRCH || error2 == ESRCH) 548100979Srwatson return (ESRCH); 549100979Srwatson 550100979Srwatson if (error1 == ENOENT || error2 == ENOENT) 551100979Srwatson return (ENOENT); 552100979Srwatson 553100979Srwatson /* Precedence goes to DAC/MAC protections. */ 554100979Srwatson if (error1 == EACCES || error2 == EACCES) 555100979Srwatson return (EACCES); 556100979Srwatson 557100979Srwatson /* Precedence goes to privilege. */ 558100979Srwatson if (error1 == EPERM || error2 == EPERM) 559100979Srwatson return (EPERM); 560100979Srwatson 561100979Srwatson /* Precedence goes to error over success; otherwise, arbitrary. */ 562100979Srwatson if (error1 != 0) 563100979Srwatson return (error1); 564100979Srwatson return (error2); 565100979Srwatson} 566100979Srwatson 567121374Srwatsonvoid 568104521Srwatsonmac_init_label(struct label *label) 569104521Srwatson{ 570104521Srwatson 571104521Srwatson bzero(label, sizeof(*label)); 572104521Srwatson label->l_flags = MAC_FLAG_INITIALIZED; 573104521Srwatson} 574104521Srwatson 575121374Srwatsonvoid 576104521Srwatsonmac_destroy_label(struct label *label) 577104521Srwatson{ 578104521Srwatson 579104521Srwatson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 580104521Srwatson ("destroying uninitialized label")); 581104521Srwatson 582104521Srwatson bzero(label, sizeof(*label)); 583104521Srwatson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 584104521Srwatson} 585104521Srwatson 586112675Srwatsonint 587105694Srwatsonmac_check_structmac_consistent(struct mac *mac) 588104522Srwatson{ 589105694Srwatson 590120582Srwatson if (mac->m_buflen < 0 || 591120582Srwatson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 592105694Srwatson return (EINVAL); 593105694Srwatson 594105694Srwatson return (0); 595105694Srwatson} 596105694Srwatson 597122584Srwatson/* 598122584Srwatson * MPSAFE 599122584Srwatson */ 600105988Srwatsonint 601105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 602105694Srwatson{ 603105694Srwatson char *elements, *buffer; 604105694Srwatson struct mac mac; 605105694Srwatson struct proc *tproc; 606105694Srwatson struct ucred *tcred; 607105694Srwatson int error; 608105694Srwatson 609107849Salfred error = copyin(uap->mac_p, &mac, sizeof(mac)); 610105694Srwatson if (error) 611105694Srwatson return (error); 612105694Srwatson 613105694Srwatson error = mac_check_structmac_consistent(&mac); 614105694Srwatson if (error) 615105694Srwatson return (error); 616105694Srwatson 617105694Srwatson tproc = pfind(uap->pid); 618105694Srwatson if (tproc == NULL) 619105694Srwatson return (ESRCH); 620105694Srwatson 621105694Srwatson tcred = NULL; /* Satisfy gcc. */ 622105694Srwatson error = p_cansee(td, tproc); 623105694Srwatson if (error == 0) 624105694Srwatson tcred = crhold(tproc->p_ucred); 625105694Srwatson PROC_UNLOCK(tproc); 626105694Srwatson if (error) 627105694Srwatson return (error); 628105694Srwatson 629111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 630105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 631105694Srwatson if (error) { 632105694Srwatson free(elements, M_MACTEMP); 633105694Srwatson crfree(tcred); 634105694Srwatson return (error); 635105694Srwatson } 636105694Srwatson 637111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 638122524Srwatson error = mac_externalize_cred_label(tcred->cr_label, elements, 639122159Srwatson buffer, mac.m_buflen); 640105694Srwatson if (error == 0) 641105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 642105694Srwatson 643105694Srwatson free(buffer, M_MACTEMP); 644105694Srwatson free(elements, M_MACTEMP); 645105694Srwatson crfree(tcred); 646105694Srwatson return (error); 647105694Srwatson} 648105694Srwatson 649100979Srwatson/* 650100979Srwatson * MPSAFE 651100979Srwatson */ 652100979Srwatsonint 653100894Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 654100894Srwatson{ 655105694Srwatson char *elements, *buffer; 656105694Srwatson struct mac mac; 657100979Srwatson int error; 658100894Srwatson 659105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 660105694Srwatson if (error) 661105694Srwatson return (error); 662105694Srwatson 663105694Srwatson error = mac_check_structmac_consistent(&mac); 664105694Srwatson if (error) 665105694Srwatson return (error); 666105694Srwatson 667111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 668105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 669105694Srwatson if (error) { 670105694Srwatson free(elements, M_MACTEMP); 671105694Srwatson return (error); 672105694Srwatson } 673105694Srwatson 674111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 675122524Srwatson error = mac_externalize_cred_label(td->td_ucred->cr_label, 676122159Srwatson elements, buffer, mac.m_buflen); 677100979Srwatson if (error == 0) 678105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 679100979Srwatson 680105694Srwatson free(buffer, M_MACTEMP); 681105694Srwatson free(elements, M_MACTEMP); 682100979Srwatson return (error); 683100979Srwatson} 684100979Srwatson 685100979Srwatson/* 686100979Srwatson * MPSAFE 687100979Srwatson */ 688100979Srwatsonint 689100979Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 690100979Srwatson{ 691100979Srwatson struct ucred *newcred, *oldcred; 692122524Srwatson struct label *intlabel; 693100979Srwatson struct proc *p; 694105694Srwatson struct mac mac; 695105694Srwatson char *buffer; 696100979Srwatson int error; 697100979Srwatson 698105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 699100979Srwatson if (error) 700100979Srwatson return (error); 701100979Srwatson 702105694Srwatson error = mac_check_structmac_consistent(&mac); 703100979Srwatson if (error) 704100979Srwatson return (error); 705100979Srwatson 706111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 707105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 708105694Srwatson if (error) { 709105694Srwatson free(buffer, M_MACTEMP); 710105694Srwatson return (error); 711105694Srwatson } 712105694Srwatson 713122524Srwatson intlabel = mac_cred_label_alloc(); 714122524Srwatson error = mac_internalize_cred_label(intlabel, buffer); 715105694Srwatson free(buffer, M_MACTEMP); 716122524Srwatson if (error) 717122524Srwatson goto out; 718105694Srwatson 719100979Srwatson newcred = crget(); 720100979Srwatson 721100979Srwatson p = td->td_proc; 722100979Srwatson PROC_LOCK(p); 723100979Srwatson oldcred = p->p_ucred; 724100979Srwatson 725122524Srwatson error = mac_check_cred_relabel(oldcred, intlabel); 726100979Srwatson if (error) { 727100979Srwatson PROC_UNLOCK(p); 728100979Srwatson crfree(newcred); 729105694Srwatson goto out; 730100979Srwatson } 731100979Srwatson 732100979Srwatson setsugid(p); 733100979Srwatson crcopy(newcred, oldcred); 734122524Srwatson mac_relabel_cred(newcred, intlabel); 735102136Srwatson p->p_ucred = newcred; 736100979Srwatson 737102136Srwatson /* 738165411Srwatson * Grab additional reference for use while revoking mmaps, prior to 739165411Srwatson * releasing the proc lock and sharing the cred. 740102136Srwatson */ 741102136Srwatson crhold(newcred); 742100979Srwatson PROC_UNLOCK(p); 743102136Srwatson 744105694Srwatson if (mac_enforce_vm) { 745105694Srwatson mac_cred_mmapped_drop_perms(td, newcred); 746105694Srwatson } 747102136Srwatson 748102136Srwatson crfree(newcred); /* Free revocation reference. */ 749100979Srwatson crfree(oldcred); 750105694Srwatson 751105694Srwatsonout: 752122524Srwatson mac_cred_label_free(intlabel); 753105694Srwatson return (error); 754100979Srwatson} 755100979Srwatson 756100979Srwatson/* 757100979Srwatson * MPSAFE 758100979Srwatson */ 759100979Srwatsonint 760100979Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 761100979Srwatson{ 762105694Srwatson char *elements, *buffer; 763122524Srwatson struct label *intlabel; 764100979Srwatson struct file *fp; 765105694Srwatson struct mac mac; 766100979Srwatson struct vnode *vp; 767100979Srwatson struct pipe *pipe; 768122820Srwatson struct socket *so; 769105694Srwatson short label_type; 770150914Scsjp int vfslocked, error; 771100979Srwatson 772105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 773105694Srwatson if (error) 774105694Srwatson return (error); 775100979Srwatson 776105694Srwatson error = mac_check_structmac_consistent(&mac); 777105694Srwatson if (error) 778105694Srwatson return (error); 779105694Srwatson 780111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 781105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 782105694Srwatson if (error) { 783105694Srwatson free(elements, M_MACTEMP); 784105694Srwatson return (error); 785105694Srwatson } 786105694Srwatson 787111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 788107849Salfred error = fget(td, uap->fd, &fp); 789100979Srwatson if (error) 790100979Srwatson goto out; 791100979Srwatson 792105694Srwatson label_type = fp->f_type; 793100979Srwatson switch (fp->f_type) { 794100979Srwatson case DTYPE_FIFO: 795100979Srwatson case DTYPE_VNODE: 796116678Sphk vp = fp->f_vnode; 797122524Srwatson intlabel = mac_vnode_label_alloc(); 798150914Scsjp vfslocked = VFS_LOCK_GIANT(vp->v_mount); 799100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 800122524Srwatson mac_copy_vnode_label(vp->v_label, intlabel); 801100979Srwatson VOP_UNLOCK(vp, 0, td); 802150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 803122584Srwatson error = mac_externalize_vnode_label(intlabel, elements, 804122584Srwatson buffer, mac.m_buflen); 805122584Srwatson mac_vnode_label_free(intlabel); 806122584Srwatson break; 807105694Srwatson 808100979Srwatson case DTYPE_PIPE: 809109153Sdillon pipe = fp->f_data; 810122524Srwatson intlabel = mac_pipe_label_alloc(); 811105694Srwatson PIPE_LOCK(pipe); 812125293Srwatson mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 813105694Srwatson PIPE_UNLOCK(pipe); 814122524Srwatson error = mac_externalize_pipe_label(intlabel, elements, 815122159Srwatson buffer, mac.m_buflen); 816122524Srwatson mac_pipe_label_free(intlabel); 817105694Srwatson break; 818122584Srwatson 819122820Srwatson case DTYPE_SOCKET: 820122820Srwatson so = fp->f_data; 821122820Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 822145160Srwatson NET_LOCK_GIANT(); 823145160Srwatson SOCK_LOCK(so); 824122820Srwatson mac_copy_socket_label(so->so_label, intlabel); 825145160Srwatson SOCK_UNLOCK(so); 826145160Srwatson NET_UNLOCK_GIANT(); 827122820Srwatson error = mac_externalize_socket_label(intlabel, elements, 828122820Srwatson buffer, mac.m_buflen); 829122820Srwatson mac_socket_label_free(intlabel); 830122820Srwatson break; 831122820Srwatson 832105694Srwatson default: 833122584Srwatson error = EINVAL; 834105694Srwatson } 835122584Srwatson fdrop(fp, td); 836100979Srwatson if (error == 0) 837105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 838100979Srwatson 839105694Srwatsonout: 840105694Srwatson free(buffer, M_MACTEMP); 841105694Srwatson free(elements, M_MACTEMP); 842100979Srwatson return (error); 843100979Srwatson} 844100979Srwatson 845100979Srwatson/* 846100979Srwatson * MPSAFE 847100979Srwatson */ 848100979Srwatsonint 849100979Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 850100979Srwatson{ 851105694Srwatson char *elements, *buffer; 852100979Srwatson struct nameidata nd; 853122524Srwatson struct label *intlabel; 854105694Srwatson struct mac mac; 855150914Scsjp int vfslocked, error; 856100979Srwatson 857105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 858105694Srwatson if (error) 859105694Srwatson return (error); 860105694Srwatson 861105694Srwatson error = mac_check_structmac_consistent(&mac); 862105694Srwatson if (error) 863105694Srwatson return (error); 864105694Srwatson 865111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 866105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 867105694Srwatson if (error) { 868105694Srwatson free(elements, M_MACTEMP); 869105694Srwatson return (error); 870105694Srwatson } 871105694Srwatson 872111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 873150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 874150914Scsjp uap->path_p, td); 875100979Srwatson error = namei(&nd); 876100979Srwatson if (error) 877100979Srwatson goto out; 878100979Srwatson 879122524Srwatson intlabel = mac_vnode_label_alloc(); 880150914Scsjp vfslocked = NDHASGIANT(&nd); 881122524Srwatson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 882122524Srwatson error = mac_externalize_vnode_label(intlabel, elements, buffer, 883122159Srwatson mac.m_buflen); 884105694Srwatson 885100979Srwatson NDFREE(&nd, 0); 886150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 887122524Srwatson mac_vnode_label_free(intlabel); 888105694Srwatson if (error == 0) 889105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 890105694Srwatson 891105694Srwatsonout: 892105694Srwatson free(buffer, M_MACTEMP); 893105694Srwatson free(elements, M_MACTEMP); 894105694Srwatson 895105694Srwatson return (error); 896105694Srwatson} 897105694Srwatson 898105694Srwatson/* 899105694Srwatson * MPSAFE 900105694Srwatson */ 901105694Srwatsonint 902105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 903105694Srwatson{ 904105694Srwatson char *elements, *buffer; 905105694Srwatson struct nameidata nd; 906122524Srwatson struct label *intlabel; 907105694Srwatson struct mac mac; 908150914Scsjp int vfslocked, error; 909105694Srwatson 910105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 911100979Srwatson if (error) 912105694Srwatson return (error); 913105694Srwatson 914105694Srwatson error = mac_check_structmac_consistent(&mac); 915105694Srwatson if (error) 916105694Srwatson return (error); 917105694Srwatson 918111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 919105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 920105694Srwatson if (error) { 921105694Srwatson free(elements, M_MACTEMP); 922105694Srwatson return (error); 923105694Srwatson } 924105694Srwatson 925111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 926150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 927150914Scsjp uap->path_p, td); 928105694Srwatson error = namei(&nd); 929105694Srwatson if (error) 930100979Srwatson goto out; 931100979Srwatson 932122524Srwatson intlabel = mac_vnode_label_alloc(); 933150914Scsjp vfslocked = NDHASGIANT(&nd); 934122524Srwatson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 935122524Srwatson error = mac_externalize_vnode_label(intlabel, elements, buffer, 936122159Srwatson mac.m_buflen); 937105694Srwatson NDFREE(&nd, 0); 938150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 939122524Srwatson mac_vnode_label_free(intlabel); 940100979Srwatson 941105694Srwatson if (error == 0) 942105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 943105694Srwatson 944100979Srwatsonout: 945105694Srwatson free(buffer, M_MACTEMP); 946105694Srwatson free(elements, M_MACTEMP); 947105694Srwatson 948100979Srwatson return (error); 949100979Srwatson} 950100979Srwatson 951100979Srwatson/* 952100979Srwatson * MPSAFE 953100979Srwatson */ 954100979Srwatsonint 955100979Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 956100979Srwatson{ 957122524Srwatson struct label *intlabel; 958105694Srwatson struct pipe *pipe; 959122820Srwatson struct socket *so; 960100979Srwatson struct file *fp; 961100979Srwatson struct mount *mp; 962100979Srwatson struct vnode *vp; 963105694Srwatson struct mac mac; 964105694Srwatson char *buffer; 965150914Scsjp int error, vfslocked; 966100979Srwatson 967105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 968100979Srwatson if (error) 969105694Srwatson return (error); 970100979Srwatson 971105694Srwatson error = mac_check_structmac_consistent(&mac); 972100979Srwatson if (error) 973105694Srwatson return (error); 974100979Srwatson 975111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 976105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 977105694Srwatson if (error) { 978105694Srwatson free(buffer, M_MACTEMP); 979105694Srwatson return (error); 980105694Srwatson } 981105694Srwatson 982107849Salfred error = fget(td, uap->fd, &fp); 983100979Srwatson if (error) 984105694Srwatson goto out; 985100979Srwatson 986100979Srwatson switch (fp->f_type) { 987100979Srwatson case DTYPE_FIFO: 988100979Srwatson case DTYPE_VNODE: 989122524Srwatson intlabel = mac_vnode_label_alloc(); 990122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 991105694Srwatson if (error) { 992122524Srwatson mac_vnode_label_free(intlabel); 993105694Srwatson break; 994105694Srwatson } 995116678Sphk vp = fp->f_vnode; 996150914Scsjp vfslocked = VFS_LOCK_GIANT(vp->v_mount); 997100979Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 998105694Srwatson if (error != 0) { 999150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1000122524Srwatson mac_vnode_label_free(intlabel); 1001100979Srwatson break; 1002105694Srwatson } 1003100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1004122524Srwatson error = vn_setlabel(vp, intlabel, td->td_ucred); 1005100979Srwatson VOP_UNLOCK(vp, 0, td); 1006100979Srwatson vn_finished_write(mp); 1007150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1008122524Srwatson mac_vnode_label_free(intlabel); 1009100979Srwatson break; 1010105694Srwatson 1011100979Srwatson case DTYPE_PIPE: 1012122524Srwatson intlabel = mac_pipe_label_alloc(); 1013122524Srwatson error = mac_internalize_pipe_label(intlabel, buffer); 1014105694Srwatson if (error == 0) { 1015109153Sdillon pipe = fp->f_data; 1016105694Srwatson PIPE_LOCK(pipe); 1017125293Srwatson error = mac_pipe_label_set(td->td_ucred, 1018125293Srwatson pipe->pipe_pair, intlabel); 1019105694Srwatson PIPE_UNLOCK(pipe); 1020105694Srwatson } 1021122524Srwatson mac_pipe_label_free(intlabel); 1022100979Srwatson break; 1023105694Srwatson 1024122820Srwatson case DTYPE_SOCKET: 1025122820Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 1026122820Srwatson error = mac_internalize_socket_label(intlabel, buffer); 1027122820Srwatson if (error == 0) { 1028122820Srwatson so = fp->f_data; 1029145160Srwatson NET_LOCK_GIANT(); 1030122820Srwatson error = mac_socket_label_set(td->td_ucred, so, 1031122820Srwatson intlabel); 1032145160Srwatson NET_UNLOCK_GIANT(); 1033122820Srwatson } 1034122820Srwatson mac_socket_label_free(intlabel); 1035122820Srwatson break; 1036122820Srwatson 1037100979Srwatson default: 1038100979Srwatson error = EINVAL; 1039100979Srwatson } 1040100979Srwatson fdrop(fp, td); 1041105694Srwatsonout: 1042105694Srwatson free(buffer, M_MACTEMP); 1043100979Srwatson return (error); 1044100979Srwatson} 1045100979Srwatson 1046100979Srwatson/* 1047100979Srwatson * MPSAFE 1048100979Srwatson */ 1049100979Srwatsonint 1050100979Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1051100979Srwatson{ 1052122524Srwatson struct label *intlabel; 1053100979Srwatson struct nameidata nd; 1054100979Srwatson struct mount *mp; 1055105694Srwatson struct mac mac; 1056105694Srwatson char *buffer; 1057150914Scsjp int vfslocked, error; 1058100979Srwatson 1059105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1060100979Srwatson if (error) 1061105694Srwatson return (error); 1062100979Srwatson 1063105694Srwatson error = mac_check_structmac_consistent(&mac); 1064100979Srwatson if (error) 1065105694Srwatson return (error); 1066100979Srwatson 1067111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1068105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1069105694Srwatson if (error) { 1070105694Srwatson free(buffer, M_MACTEMP); 1071105694Srwatson return (error); 1072105694Srwatson } 1073105694Srwatson 1074122524Srwatson intlabel = mac_vnode_label_alloc(); 1075122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 1076105694Srwatson free(buffer, M_MACTEMP); 1077122524Srwatson if (error) 1078122524Srwatson goto out; 1079105694Srwatson 1080150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 1081150914Scsjp uap->path_p, td); 1082100979Srwatson error = namei(&nd); 1083150914Scsjp vfslocked = NDHASGIANT(&nd); 1084105694Srwatson if (error == 0) { 1085105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1086156893Stegge if (error == 0) { 1087122524Srwatson error = vn_setlabel(nd.ni_vp, intlabel, 1088105694Srwatson td->td_ucred); 1089156893Stegge vn_finished_write(mp); 1090156893Stegge } 1091105694Srwatson } 1092105694Srwatson 1093105694Srwatson NDFREE(&nd, 0); 1094150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1095122524Srwatsonout: 1096122524Srwatson mac_vnode_label_free(intlabel); 1097105694Srwatson return (error); 1098105694Srwatson} 1099105694Srwatson 1100105694Srwatson/* 1101105694Srwatson * MPSAFE 1102105694Srwatson */ 1103105694Srwatsonint 1104105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1105105694Srwatson{ 1106122524Srwatson struct label *intlabel; 1107105694Srwatson struct nameidata nd; 1108105694Srwatson struct mount *mp; 1109105694Srwatson struct mac mac; 1110105694Srwatson char *buffer; 1111150914Scsjp int vfslocked, error; 1112105694Srwatson 1113105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1114100979Srwatson if (error) 1115105694Srwatson return (error); 1116105694Srwatson 1117105694Srwatson error = mac_check_structmac_consistent(&mac); 1118100979Srwatson if (error) 1119105694Srwatson return (error); 1120100979Srwatson 1121111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1122105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1123105694Srwatson if (error) { 1124105694Srwatson free(buffer, M_MACTEMP); 1125105694Srwatson return (error); 1126105694Srwatson } 1127105694Srwatson 1128122524Srwatson intlabel = mac_vnode_label_alloc(); 1129122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 1130105694Srwatson free(buffer, M_MACTEMP); 1131122524Srwatson if (error) 1132122524Srwatson goto out; 1133105694Srwatson 1134150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 1135150914Scsjp uap->path_p, td); 1136105694Srwatson error = namei(&nd); 1137150914Scsjp vfslocked = NDHASGIANT(&nd); 1138105694Srwatson if (error == 0) { 1139105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1140156893Stegge if (error == 0) { 1141122524Srwatson error = vn_setlabel(nd.ni_vp, intlabel, 1142105694Srwatson td->td_ucred); 1143156893Stegge vn_finished_write(mp); 1144156893Stegge } 1145105694Srwatson } 1146105694Srwatson 1147100979Srwatson NDFREE(&nd, 0); 1148150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1149122524Srwatsonout: 1150122524Srwatson mac_vnode_label_free(intlabel); 1151100979Srwatson return (error); 1152100979Srwatson} 1153100979Srwatson 1154105694Srwatson/* 1155105694Srwatson * MPSAFE 1156105694Srwatson */ 1157102123Srwatsonint 1158102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1159102123Srwatson{ 1160102123Srwatson struct mac_policy_conf *mpc; 1161102123Srwatson char target[MAC_MAX_POLICY_NAME]; 1162114806Srwatson int entrycount, error; 1163102123Srwatson 1164107849Salfred error = copyinstr(uap->policy, target, sizeof(target), NULL); 1165102123Srwatson if (error) 1166102123Srwatson return (error); 1167102123Srwatson 1168102123Srwatson error = ENOSYS; 1169119494Srwatson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1170102123Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1171102123Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1172102123Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1173107849Salfred uap->call, uap->arg); 1174102123Srwatson goto out; 1175102123Srwatson } 1176102123Srwatson } 1177102123Srwatson 1178114806Srwatson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1179114806Srwatson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1180114806Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1181114806Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1182114806Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1183114806Srwatson uap->call, uap->arg); 1184114806Srwatson break; 1185114806Srwatson } 1186114806Srwatson } 1187114806Srwatson mac_policy_list_unbusy(); 1188114806Srwatson } 1189102123Srwatsonout: 1190102123Srwatson return (error); 1191102123Srwatson} 1192102123Srwatson 1193100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1194100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1195100979Srwatson 1196100979Srwatson#else /* !MAC */ 1197100979Srwatson 1198100979Srwatsonint 1199105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1200105694Srwatson{ 1201105694Srwatson 1202105694Srwatson return (ENOSYS); 1203105694Srwatson} 1204105694Srwatson 1205105694Srwatsonint 1206100979Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1207100979Srwatson{ 1208100979Srwatson 1209100894Srwatson return (ENOSYS); 1210100894Srwatson} 1211100894Srwatson 1212100894Srwatsonint 1213100894Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1214100894Srwatson{ 1215100894Srwatson 1216100894Srwatson return (ENOSYS); 1217100894Srwatson} 1218100894Srwatson 1219100894Srwatsonint 1220100894Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1221100894Srwatson{ 1222100894Srwatson 1223100894Srwatson return (ENOSYS); 1224100894Srwatson} 1225100894Srwatson 1226100894Srwatsonint 1227100894Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1228100894Srwatson{ 1229100894Srwatson 1230100894Srwatson return (ENOSYS); 1231100894Srwatson} 1232100894Srwatson 1233100894Srwatsonint 1234105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1235105694Srwatson{ 1236105694Srwatson 1237105694Srwatson return (ENOSYS); 1238105694Srwatson} 1239105694Srwatson 1240105694Srwatsonint 1241100894Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1242100894Srwatson{ 1243100894Srwatson 1244100894Srwatson return (ENOSYS); 1245100894Srwatson} 1246100894Srwatson 1247100894Srwatsonint 1248100894Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1249100894Srwatson{ 1250100894Srwatson 1251100894Srwatson return (ENOSYS); 1252100894Srwatson} 1253100979Srwatson 1254102123Srwatsonint 1255105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1256105694Srwatson{ 1257105694Srwatson 1258105694Srwatson return (ENOSYS); 1259105694Srwatson} 1260105694Srwatson 1261105694Srwatsonint 1262102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1263102123Srwatson{ 1264102123Srwatson 1265102123Srwatson return (ENOSYS); 1266102123Srwatson} 1267102123Srwatson 1268128901Srwatson#endif /* !MAC */ 1269