mac_syscalls.c revision 165433
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 165433 2006-12-21 09:51:34Z 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 744165433Srwatson mac_cred_mmapped_drop_perms(td, newcred); 745102136Srwatson 746102136Srwatson crfree(newcred); /* Free revocation reference. */ 747100979Srwatson crfree(oldcred); 748105694Srwatson 749105694Srwatsonout: 750122524Srwatson mac_cred_label_free(intlabel); 751105694Srwatson return (error); 752100979Srwatson} 753100979Srwatson 754100979Srwatson/* 755100979Srwatson * MPSAFE 756100979Srwatson */ 757100979Srwatsonint 758100979Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 759100979Srwatson{ 760105694Srwatson char *elements, *buffer; 761122524Srwatson struct label *intlabel; 762100979Srwatson struct file *fp; 763105694Srwatson struct mac mac; 764100979Srwatson struct vnode *vp; 765100979Srwatson struct pipe *pipe; 766122820Srwatson struct socket *so; 767105694Srwatson short label_type; 768150914Scsjp int vfslocked, error; 769100979Srwatson 770105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 771105694Srwatson if (error) 772105694Srwatson return (error); 773100979Srwatson 774105694Srwatson error = mac_check_structmac_consistent(&mac); 775105694Srwatson if (error) 776105694Srwatson return (error); 777105694Srwatson 778111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 779105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 780105694Srwatson if (error) { 781105694Srwatson free(elements, M_MACTEMP); 782105694Srwatson return (error); 783105694Srwatson } 784105694Srwatson 785111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 786107849Salfred error = fget(td, uap->fd, &fp); 787100979Srwatson if (error) 788100979Srwatson goto out; 789100979Srwatson 790105694Srwatson label_type = fp->f_type; 791100979Srwatson switch (fp->f_type) { 792100979Srwatson case DTYPE_FIFO: 793100979Srwatson case DTYPE_VNODE: 794116678Sphk vp = fp->f_vnode; 795122524Srwatson intlabel = mac_vnode_label_alloc(); 796150914Scsjp vfslocked = VFS_LOCK_GIANT(vp->v_mount); 797100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 798122524Srwatson mac_copy_vnode_label(vp->v_label, intlabel); 799100979Srwatson VOP_UNLOCK(vp, 0, td); 800150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 801122584Srwatson error = mac_externalize_vnode_label(intlabel, elements, 802122584Srwatson buffer, mac.m_buflen); 803122584Srwatson mac_vnode_label_free(intlabel); 804122584Srwatson break; 805105694Srwatson 806100979Srwatson case DTYPE_PIPE: 807109153Sdillon pipe = fp->f_data; 808122524Srwatson intlabel = mac_pipe_label_alloc(); 809105694Srwatson PIPE_LOCK(pipe); 810125293Srwatson mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 811105694Srwatson PIPE_UNLOCK(pipe); 812122524Srwatson error = mac_externalize_pipe_label(intlabel, elements, 813122159Srwatson buffer, mac.m_buflen); 814122524Srwatson mac_pipe_label_free(intlabel); 815105694Srwatson break; 816122584Srwatson 817122820Srwatson case DTYPE_SOCKET: 818122820Srwatson so = fp->f_data; 819122820Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 820145160Srwatson NET_LOCK_GIANT(); 821145160Srwatson SOCK_LOCK(so); 822122820Srwatson mac_copy_socket_label(so->so_label, intlabel); 823145160Srwatson SOCK_UNLOCK(so); 824145160Srwatson NET_UNLOCK_GIANT(); 825122820Srwatson error = mac_externalize_socket_label(intlabel, elements, 826122820Srwatson buffer, mac.m_buflen); 827122820Srwatson mac_socket_label_free(intlabel); 828122820Srwatson break; 829122820Srwatson 830105694Srwatson default: 831122584Srwatson error = EINVAL; 832105694Srwatson } 833122584Srwatson fdrop(fp, td); 834100979Srwatson if (error == 0) 835105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 836100979Srwatson 837105694Srwatsonout: 838105694Srwatson free(buffer, M_MACTEMP); 839105694Srwatson free(elements, M_MACTEMP); 840100979Srwatson return (error); 841100979Srwatson} 842100979Srwatson 843100979Srwatson/* 844100979Srwatson * MPSAFE 845100979Srwatson */ 846100979Srwatsonint 847100979Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 848100979Srwatson{ 849105694Srwatson char *elements, *buffer; 850100979Srwatson struct nameidata nd; 851122524Srwatson struct label *intlabel; 852105694Srwatson struct mac mac; 853150914Scsjp int vfslocked, error; 854100979Srwatson 855105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 856105694Srwatson if (error) 857105694Srwatson return (error); 858105694Srwatson 859105694Srwatson error = mac_check_structmac_consistent(&mac); 860105694Srwatson if (error) 861105694Srwatson return (error); 862105694Srwatson 863111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 864105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 865105694Srwatson if (error) { 866105694Srwatson free(elements, M_MACTEMP); 867105694Srwatson return (error); 868105694Srwatson } 869105694Srwatson 870111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 871150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 872150914Scsjp uap->path_p, td); 873100979Srwatson error = namei(&nd); 874100979Srwatson if (error) 875100979Srwatson goto out; 876100979Srwatson 877122524Srwatson intlabel = mac_vnode_label_alloc(); 878150914Scsjp vfslocked = NDHASGIANT(&nd); 879122524Srwatson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 880122524Srwatson error = mac_externalize_vnode_label(intlabel, elements, buffer, 881122159Srwatson mac.m_buflen); 882105694Srwatson 883100979Srwatson NDFREE(&nd, 0); 884150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 885122524Srwatson mac_vnode_label_free(intlabel); 886105694Srwatson if (error == 0) 887105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 888105694Srwatson 889105694Srwatsonout: 890105694Srwatson free(buffer, M_MACTEMP); 891105694Srwatson free(elements, M_MACTEMP); 892105694Srwatson 893105694Srwatson return (error); 894105694Srwatson} 895105694Srwatson 896105694Srwatson/* 897105694Srwatson * MPSAFE 898105694Srwatson */ 899105694Srwatsonint 900105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 901105694Srwatson{ 902105694Srwatson char *elements, *buffer; 903105694Srwatson struct nameidata nd; 904122524Srwatson struct label *intlabel; 905105694Srwatson struct mac mac; 906150914Scsjp int vfslocked, error; 907105694Srwatson 908105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 909100979Srwatson if (error) 910105694Srwatson return (error); 911105694Srwatson 912105694Srwatson error = mac_check_structmac_consistent(&mac); 913105694Srwatson if (error) 914105694Srwatson return (error); 915105694Srwatson 916111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 917105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 918105694Srwatson if (error) { 919105694Srwatson free(elements, M_MACTEMP); 920105694Srwatson return (error); 921105694Srwatson } 922105694Srwatson 923111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 924150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 925150914Scsjp uap->path_p, td); 926105694Srwatson error = namei(&nd); 927105694Srwatson if (error) 928100979Srwatson goto out; 929100979Srwatson 930122524Srwatson intlabel = mac_vnode_label_alloc(); 931150914Scsjp vfslocked = NDHASGIANT(&nd); 932122524Srwatson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 933122524Srwatson error = mac_externalize_vnode_label(intlabel, elements, buffer, 934122159Srwatson mac.m_buflen); 935105694Srwatson NDFREE(&nd, 0); 936150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 937122524Srwatson mac_vnode_label_free(intlabel); 938100979Srwatson 939105694Srwatson if (error == 0) 940105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 941105694Srwatson 942100979Srwatsonout: 943105694Srwatson free(buffer, M_MACTEMP); 944105694Srwatson free(elements, M_MACTEMP); 945105694Srwatson 946100979Srwatson return (error); 947100979Srwatson} 948100979Srwatson 949100979Srwatson/* 950100979Srwatson * MPSAFE 951100979Srwatson */ 952100979Srwatsonint 953100979Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 954100979Srwatson{ 955122524Srwatson struct label *intlabel; 956105694Srwatson struct pipe *pipe; 957122820Srwatson struct socket *so; 958100979Srwatson struct file *fp; 959100979Srwatson struct mount *mp; 960100979Srwatson struct vnode *vp; 961105694Srwatson struct mac mac; 962105694Srwatson char *buffer; 963150914Scsjp int error, vfslocked; 964100979Srwatson 965105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 966100979Srwatson if (error) 967105694Srwatson return (error); 968100979Srwatson 969105694Srwatson error = mac_check_structmac_consistent(&mac); 970100979Srwatson if (error) 971105694Srwatson return (error); 972100979Srwatson 973111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 974105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 975105694Srwatson if (error) { 976105694Srwatson free(buffer, M_MACTEMP); 977105694Srwatson return (error); 978105694Srwatson } 979105694Srwatson 980107849Salfred error = fget(td, uap->fd, &fp); 981100979Srwatson if (error) 982105694Srwatson goto out; 983100979Srwatson 984100979Srwatson switch (fp->f_type) { 985100979Srwatson case DTYPE_FIFO: 986100979Srwatson case DTYPE_VNODE: 987122524Srwatson intlabel = mac_vnode_label_alloc(); 988122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 989105694Srwatson if (error) { 990122524Srwatson mac_vnode_label_free(intlabel); 991105694Srwatson break; 992105694Srwatson } 993116678Sphk vp = fp->f_vnode; 994150914Scsjp vfslocked = VFS_LOCK_GIANT(vp->v_mount); 995100979Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 996105694Srwatson if (error != 0) { 997150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 998122524Srwatson mac_vnode_label_free(intlabel); 999100979Srwatson break; 1000105694Srwatson } 1001100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1002122524Srwatson error = vn_setlabel(vp, intlabel, td->td_ucred); 1003100979Srwatson VOP_UNLOCK(vp, 0, td); 1004100979Srwatson vn_finished_write(mp); 1005150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1006122524Srwatson mac_vnode_label_free(intlabel); 1007100979Srwatson break; 1008105694Srwatson 1009100979Srwatson case DTYPE_PIPE: 1010122524Srwatson intlabel = mac_pipe_label_alloc(); 1011122524Srwatson error = mac_internalize_pipe_label(intlabel, buffer); 1012105694Srwatson if (error == 0) { 1013109153Sdillon pipe = fp->f_data; 1014105694Srwatson PIPE_LOCK(pipe); 1015125293Srwatson error = mac_pipe_label_set(td->td_ucred, 1016125293Srwatson pipe->pipe_pair, intlabel); 1017105694Srwatson PIPE_UNLOCK(pipe); 1018105694Srwatson } 1019122524Srwatson mac_pipe_label_free(intlabel); 1020100979Srwatson break; 1021105694Srwatson 1022122820Srwatson case DTYPE_SOCKET: 1023122820Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 1024122820Srwatson error = mac_internalize_socket_label(intlabel, buffer); 1025122820Srwatson if (error == 0) { 1026122820Srwatson so = fp->f_data; 1027145160Srwatson NET_LOCK_GIANT(); 1028122820Srwatson error = mac_socket_label_set(td->td_ucred, so, 1029122820Srwatson intlabel); 1030145160Srwatson NET_UNLOCK_GIANT(); 1031122820Srwatson } 1032122820Srwatson mac_socket_label_free(intlabel); 1033122820Srwatson break; 1034122820Srwatson 1035100979Srwatson default: 1036100979Srwatson error = EINVAL; 1037100979Srwatson } 1038100979Srwatson fdrop(fp, td); 1039105694Srwatsonout: 1040105694Srwatson free(buffer, M_MACTEMP); 1041100979Srwatson return (error); 1042100979Srwatson} 1043100979Srwatson 1044100979Srwatson/* 1045100979Srwatson * MPSAFE 1046100979Srwatson */ 1047100979Srwatsonint 1048100979Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1049100979Srwatson{ 1050122524Srwatson struct label *intlabel; 1051100979Srwatson struct nameidata nd; 1052100979Srwatson struct mount *mp; 1053105694Srwatson struct mac mac; 1054105694Srwatson char *buffer; 1055150914Scsjp int vfslocked, error; 1056100979Srwatson 1057105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1058100979Srwatson if (error) 1059105694Srwatson return (error); 1060100979Srwatson 1061105694Srwatson error = mac_check_structmac_consistent(&mac); 1062100979Srwatson if (error) 1063105694Srwatson return (error); 1064100979Srwatson 1065111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1066105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1067105694Srwatson if (error) { 1068105694Srwatson free(buffer, M_MACTEMP); 1069105694Srwatson return (error); 1070105694Srwatson } 1071105694Srwatson 1072122524Srwatson intlabel = mac_vnode_label_alloc(); 1073122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 1074105694Srwatson free(buffer, M_MACTEMP); 1075122524Srwatson if (error) 1076122524Srwatson goto out; 1077105694Srwatson 1078150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 1079150914Scsjp uap->path_p, td); 1080100979Srwatson error = namei(&nd); 1081150914Scsjp vfslocked = NDHASGIANT(&nd); 1082105694Srwatson if (error == 0) { 1083105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1084156893Stegge if (error == 0) { 1085122524Srwatson error = vn_setlabel(nd.ni_vp, intlabel, 1086105694Srwatson td->td_ucred); 1087156893Stegge vn_finished_write(mp); 1088156893Stegge } 1089105694Srwatson } 1090105694Srwatson 1091105694Srwatson NDFREE(&nd, 0); 1092150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1093122524Srwatsonout: 1094122524Srwatson mac_vnode_label_free(intlabel); 1095105694Srwatson return (error); 1096105694Srwatson} 1097105694Srwatson 1098105694Srwatson/* 1099105694Srwatson * MPSAFE 1100105694Srwatson */ 1101105694Srwatsonint 1102105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1103105694Srwatson{ 1104122524Srwatson struct label *intlabel; 1105105694Srwatson struct nameidata nd; 1106105694Srwatson struct mount *mp; 1107105694Srwatson struct mac mac; 1108105694Srwatson char *buffer; 1109150914Scsjp int vfslocked, error; 1110105694Srwatson 1111105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1112100979Srwatson if (error) 1113105694Srwatson return (error); 1114105694Srwatson 1115105694Srwatson error = mac_check_structmac_consistent(&mac); 1116100979Srwatson if (error) 1117105694Srwatson return (error); 1118100979Srwatson 1119111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1120105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1121105694Srwatson if (error) { 1122105694Srwatson free(buffer, M_MACTEMP); 1123105694Srwatson return (error); 1124105694Srwatson } 1125105694Srwatson 1126122524Srwatson intlabel = mac_vnode_label_alloc(); 1127122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 1128105694Srwatson free(buffer, M_MACTEMP); 1129122524Srwatson if (error) 1130122524Srwatson goto out; 1131105694Srwatson 1132150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 1133150914Scsjp uap->path_p, td); 1134105694Srwatson error = namei(&nd); 1135150914Scsjp vfslocked = NDHASGIANT(&nd); 1136105694Srwatson if (error == 0) { 1137105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1138156893Stegge if (error == 0) { 1139122524Srwatson error = vn_setlabel(nd.ni_vp, intlabel, 1140105694Srwatson td->td_ucred); 1141156893Stegge vn_finished_write(mp); 1142156893Stegge } 1143105694Srwatson } 1144105694Srwatson 1145100979Srwatson NDFREE(&nd, 0); 1146150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1147122524Srwatsonout: 1148122524Srwatson mac_vnode_label_free(intlabel); 1149100979Srwatson return (error); 1150100979Srwatson} 1151100979Srwatson 1152105694Srwatson/* 1153105694Srwatson * MPSAFE 1154105694Srwatson */ 1155102123Srwatsonint 1156102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1157102123Srwatson{ 1158102123Srwatson struct mac_policy_conf *mpc; 1159102123Srwatson char target[MAC_MAX_POLICY_NAME]; 1160114806Srwatson int entrycount, error; 1161102123Srwatson 1162107849Salfred error = copyinstr(uap->policy, target, sizeof(target), NULL); 1163102123Srwatson if (error) 1164102123Srwatson return (error); 1165102123Srwatson 1166102123Srwatson error = ENOSYS; 1167119494Srwatson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1168102123Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1169102123Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1170102123Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1171107849Salfred uap->call, uap->arg); 1172102123Srwatson goto out; 1173102123Srwatson } 1174102123Srwatson } 1175102123Srwatson 1176114806Srwatson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1177114806Srwatson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1178114806Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1179114806Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1180114806Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1181114806Srwatson uap->call, uap->arg); 1182114806Srwatson break; 1183114806Srwatson } 1184114806Srwatson } 1185114806Srwatson mac_policy_list_unbusy(); 1186114806Srwatson } 1187102123Srwatsonout: 1188102123Srwatson return (error); 1189102123Srwatson} 1190102123Srwatson 1191100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1192100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1193100979Srwatson 1194100979Srwatson#else /* !MAC */ 1195100979Srwatson 1196100979Srwatsonint 1197105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1198105694Srwatson{ 1199105694Srwatson 1200105694Srwatson return (ENOSYS); 1201105694Srwatson} 1202105694Srwatson 1203105694Srwatsonint 1204100979Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1205100979Srwatson{ 1206100979Srwatson 1207100894Srwatson return (ENOSYS); 1208100894Srwatson} 1209100894Srwatson 1210100894Srwatsonint 1211100894Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1212100894Srwatson{ 1213100894Srwatson 1214100894Srwatson return (ENOSYS); 1215100894Srwatson} 1216100894Srwatson 1217100894Srwatsonint 1218100894Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1219100894Srwatson{ 1220100894Srwatson 1221100894Srwatson return (ENOSYS); 1222100894Srwatson} 1223100894Srwatson 1224100894Srwatsonint 1225100894Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1226100894Srwatson{ 1227100894Srwatson 1228100894Srwatson return (ENOSYS); 1229100894Srwatson} 1230100894Srwatson 1231100894Srwatsonint 1232105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1233105694Srwatson{ 1234105694Srwatson 1235105694Srwatson return (ENOSYS); 1236105694Srwatson} 1237105694Srwatson 1238105694Srwatsonint 1239100894Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1240100894Srwatson{ 1241100894Srwatson 1242100894Srwatson return (ENOSYS); 1243100894Srwatson} 1244100894Srwatson 1245100894Srwatsonint 1246100894Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1247100894Srwatson{ 1248100894Srwatson 1249100894Srwatson return (ENOSYS); 1250100894Srwatson} 1251100979Srwatson 1252102123Srwatsonint 1253105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1254105694Srwatson{ 1255105694Srwatson 1256105694Srwatson return (ENOSYS); 1257105694Srwatson} 1258105694Srwatson 1259105694Srwatsonint 1260102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1261102123Srwatson{ 1262102123Srwatson 1263102123Srwatson return (ENOSYS); 1264102123Srwatson} 1265102123Srwatson 1266128901Srwatson#endif /* !MAC */ 1267