mac_syscalls.c revision 165469
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 165469 2006-12-22 23:34:47Z 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 <fs/devfs/devfs.h> 84100979Srwatson 85100979Srwatson#include <net/bpfdesc.h> 86100979Srwatson#include <net/if.h> 87100979Srwatson#include <net/if_var.h> 88100979Srwatson 89100979Srwatson#include <netinet/in.h> 90100979Srwatson#include <netinet/ip_var.h> 91100979Srwatson 92163606Srwatson#include <security/mac/mac_framework.h> 93121374Srwatson#include <security/mac/mac_internal.h> 94165469Srwatson#include <security/mac/mac_policy.h> 95121374Srwatson 96100979Srwatson#ifdef MAC 97100979Srwatson 98101712Srwatson/* 99101712Srwatson * Declare that the kernel provides MAC support, version 1. This permits 100101712Srwatson * modules to refuse to be loaded if the necessary support isn't present, 101101712Srwatson * even if it's pre-boot. 102101712Srwatson */ 103147983SrwatsonMODULE_VERSION(kernel_mac_support, 3); 104101712Srwatson 105100979SrwatsonSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 106100979Srwatson "TrustedBSD MAC policy controls"); 107104517Srwatson 108165411Srwatson/* 109165411Srwatson * Labels consist of a indexed set of "slots", which are allocated policies 110165411Srwatson * as required. The MAC Framework maintains a bitmask of slots allocated so 111165411Srwatson * far to prevent reuse. Slots cannot be reused, as the MAC Framework 112165411Srwatson * guarantees that newly allocated slots in labels will be NULL unless 113165411Srwatson * otherwise initialized, and because we do not have a mechanism to garbage 114165411Srwatson * collect slots on policy unload. As labeled policies tend to be statically 115165411Srwatson * loaded during boot, and not frequently unloaded and reloaded, this is not 116165411Srwatson * generally an issue. 117165411Srwatson */ 118114846Srwatson#if MAC_MAX_SLOTS > 32 119114846Srwatson#error "MAC_MAX_SLOTS too large" 120100979Srwatson#endif 121105497Srwatson 122114846Srwatsonstatic unsigned int mac_max_slots = MAC_MAX_SLOTS; 123114846Srwatsonstatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 124114846SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 125114846Srwatson &mac_max_slots, 0, ""); 126100979Srwatson 127105959Srwatson/* 128105959Srwatson * Has the kernel started generating labeled objects yet? All read/write 129105959Srwatson * access to this variable is serialized during the boot process. Following 130105959Srwatson * the end of serialization, we don't update this flag; no locking. 131105959Srwatson */ 132121372Srwatsonint mac_late = 0; 133100979Srwatson 134105988Srwatson/* 135165411Srwatson * Flag to indicate whether or not we should allocate label storage for new 136165411Srwatson * mbufs. Since most dynamic policies we currently work with don't rely on 137165411Srwatson * mbuf labeling, try to avoid paying the cost of mtag allocation unless 138165411Srwatson * specifically notified of interest. One result of this is that if a 139165411Srwatson * dynamically loaded policy requests mbuf labels, it must be able to deal 140165411Srwatson * with a NULL label being returned on any mbufs that were already in flight 141165411Srwatson * when the policy was loaded. Since the policy already has to deal with 142165411Srwatson * uninitialized labels, this probably won't be a problem. Note: currently 143165411Srwatson * no locking. Will this be a problem? 144165411Srwatson * 145165411Srwatson * In the future, we may want to allow objects to request labeling on a per- 146165411Srwatson * object type basis, rather than globally for all objects. 147113487Srwatson */ 148118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF 149121372Srwatsonint mac_labelmbufs = 0; 150113487Srwatson#endif 151113487Srwatson 152100979Srwatsonstatic int mac_policy_register(struct mac_policy_conf *mpc); 153100979Srwatsonstatic int mac_policy_unregister(struct mac_policy_conf *mpc); 154100979Srwatson 155105694SrwatsonMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 156100979Srwatson 157100979Srwatson/* 158165411Srwatson * mac_static_policy_list holds a list of policy modules that are not loaded 159165411Srwatson * while the system is "live", and cannot be unloaded. These policies can be 160165411Srwatson * invoked without holding the busy count. 161114806Srwatson * 162114806Srwatson * mac_policy_list stores the list of dynamic policies. A busy count is 163165411Srwatson * maintained for the list, stored in mac_policy_busy. The busy count is 164165411Srwatson * protected by mac_policy_mtx; the list may be modified only while the busy 165165411Srwatson * count is 0, requiring that the lock be held to prevent new references to 166165411Srwatson * the list from being acquired. For almost all operations, incrementing the 167165411Srwatson * busy count is sufficient to guarantee consistency, as the list cannot be 168165411Srwatson * modified while the busy count is elevated. For a few special operations 169165411Srwatson * involving a change to the list of active policies, the mtx itself must be 170165411Srwatson * held. A condition variable, mac_policy_cv, is used to signal potential 171165411Srwatson * exclusive consumers that they should try to acquire the lock if a first 172165411Srwatson * attempt at exclusive access fails. 173165411Srwatson * 174165411Srwatson * This design intentionally avoids fairness, and may starve attempts to 175165411Srwatson * acquire an exclusive lock on a busy system. This is required because we 176165411Srwatson * do not ever want acquiring a read reference to perform an unbounded length 177165411Srwatson * sleep. Read references are acquired in ithreads, network isrs, etc, and 178165411Srwatson * any unbounded blocking could lead quickly to deadlock. 179165411Srwatson * 180165411Srwatson * Another reason for never blocking on read references is that the MAC 181165411Srwatson * Framework may recurse: if a policy calls a VOP, for example, this might 182165411Srwatson * lead to vnode life cycle operations (such as init/destroy). 183100979Srwatson */ 184128885Srwatson#ifndef MAC_STATIC 185114806Srwatsonstatic struct mtx mac_policy_mtx; 186114806Srwatsonstatic struct cv mac_policy_cv; 187114806Srwatsonstatic int mac_policy_count; 188128885Srwatson#endif 189121372Srwatsonstruct mac_policy_list_head mac_policy_list; 190121372Srwatsonstruct mac_policy_list_head mac_static_policy_list; 191100979Srwatson 192106856Srwatson/* 193165411Srwatson * We manually invoke WITNESS_WARN() to allow Witness to generate warnings 194165411Srwatson * even if we don't end up ever triggering the wait at run-time. The 195165411Srwatson * consumer of the exclusive interface must not hold any locks (other than 196165411Srwatson * potentially Giant) since we may sleep for long (potentially indefinite) 197165411Srwatson * periods of time waiting for the framework to become quiescent so that a 198165411Srwatson * policy list change may be made. 199106856Srwatson */ 200121372Srwatsonvoid 201114806Srwatsonmac_policy_grab_exclusive(void) 202114806Srwatson{ 203122454Srwatson 204128885Srwatson#ifndef MAC_STATIC 205137072Srwatson if (!mac_late) 206137072Srwatson return; 207137072Srwatson 208114806Srwatson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 209114806Srwatson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 210114806Srwatson mtx_lock(&mac_policy_mtx); 211114806Srwatson while (mac_policy_count != 0) 212114806Srwatson cv_wait(&mac_policy_cv, &mac_policy_mtx); 213128885Srwatson#endif 214114806Srwatson} 215106856Srwatson 216121372Srwatsonvoid 217114806Srwatsonmac_policy_assert_exclusive(void) 218114806Srwatson{ 219122454Srwatson 220128885Srwatson#ifndef MAC_STATIC 221137072Srwatson if (!mac_late) 222137072Srwatson return; 223137072Srwatson 224114806Srwatson mtx_assert(&mac_policy_mtx, MA_OWNED); 225114806Srwatson KASSERT(mac_policy_count == 0, 226114806Srwatson ("mac_policy_assert_exclusive(): not exclusive")); 227128885Srwatson#endif 228114806Srwatson} 229113487Srwatson 230121372Srwatsonvoid 231114806Srwatsonmac_policy_release_exclusive(void) 232114806Srwatson{ 233100979Srwatson 234128885Srwatson#ifndef MAC_STATIC 235137072Srwatson if (!mac_late) 236137072Srwatson return; 237137072Srwatson 238114806Srwatson KASSERT(mac_policy_count == 0, 239114806Srwatson ("mac_policy_release_exclusive(): not exclusive")); 240114806Srwatson mtx_unlock(&mac_policy_mtx); 241114806Srwatson cv_signal(&mac_policy_cv); 242128885Srwatson#endif 243114806Srwatson} 244100979Srwatson 245121372Srwatsonvoid 246114806Srwatsonmac_policy_list_busy(void) 247114806Srwatson{ 248122454Srwatson 249128885Srwatson#ifndef MAC_STATIC 250137072Srwatson if (!mac_late) 251137072Srwatson return; 252137072Srwatson 253114806Srwatson mtx_lock(&mac_policy_mtx); 254114806Srwatson mac_policy_count++; 255114806Srwatson mtx_unlock(&mac_policy_mtx); 256128885Srwatson#endif 257114806Srwatson} 258114806Srwatson 259121372Srwatsonint 260114806Srwatsonmac_policy_list_conditional_busy(void) 261114806Srwatson{ 262128885Srwatson#ifndef MAC_STATIC 263114806Srwatson int ret; 264114806Srwatson 265137072Srwatson if (!mac_late) 266137072Srwatson return (1); 267137072Srwatson 268114806Srwatson mtx_lock(&mac_policy_mtx); 269114806Srwatson if (!LIST_EMPTY(&mac_policy_list)) { 270114806Srwatson mac_policy_count++; 271114806Srwatson ret = 1; 272114806Srwatson } else 273114806Srwatson ret = 0; 274114806Srwatson mtx_unlock(&mac_policy_mtx); 275114806Srwatson return (ret); 276128885Srwatson#else 277137072Srwatson if (!mac_late) 278137072Srwatson return (1); 279137072Srwatson 280128885Srwatson return (1); 281128885Srwatson#endif 282114806Srwatson} 283114806Srwatson 284121372Srwatsonvoid 285114806Srwatsonmac_policy_list_unbusy(void) 286114806Srwatson{ 287122454Srwatson 288128885Srwatson#ifndef MAC_STATIC 289137072Srwatson if (!mac_late) 290137072Srwatson return; 291137072Srwatson 292114806Srwatson mtx_lock(&mac_policy_mtx); 293114806Srwatson mac_policy_count--; 294114806Srwatson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 295114806Srwatson if (mac_policy_count == 0) 296114806Srwatson cv_signal(&mac_policy_cv); 297114806Srwatson mtx_unlock(&mac_policy_mtx); 298128885Srwatson#endif 299114806Srwatson} 300114806Srwatson 301100979Srwatson/* 302100979Srwatson * Initialize the MAC subsystem, including appropriate SMP locks. 303100979Srwatson */ 304100979Srwatsonstatic void 305100979Srwatsonmac_init(void) 306100979Srwatson{ 307100979Srwatson 308114806Srwatson LIST_INIT(&mac_static_policy_list); 309100979Srwatson LIST_INIT(&mac_policy_list); 310122524Srwatson mac_labelzone_init(); 311114806Srwatson 312128885Srwatson#ifndef MAC_STATIC 313114806Srwatson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 314114806Srwatson cv_init(&mac_policy_cv, "mac_policy_cv"); 315128885Srwatson#endif 316100979Srwatson} 317100979Srwatson 318100979Srwatson/* 319165411Srwatson * For the purposes of modules that want to know if they were loaded "early", 320165411Srwatson * set the mac_late flag once we've processed modules either linked into the 321165411Srwatson * kernel, or loaded before the kernel startup. 322100979Srwatson */ 323100979Srwatsonstatic void 324100979Srwatsonmac_late_init(void) 325100979Srwatson{ 326100979Srwatson 327100979Srwatson mac_late = 1; 328100979Srwatson} 329100979Srwatson 330100979Srwatson/* 331113487Srwatson * After the policy list has changed, walk the list to update any global 332118308Srwatson * flags. Currently, we support only one flag, and it's conditionally 333165411Srwatson * defined; as a result, the entire function is conditional. Eventually, the 334165411Srwatson * #else case might also iterate across the policies. 335113487Srwatson */ 336113487Srwatsonstatic void 337113487Srwatsonmac_policy_updateflags(void) 338113487Srwatson{ 339118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF 340113487Srwatson struct mac_policy_conf *tmpc; 341113487Srwatson int labelmbufs; 342113487Srwatson 343114806Srwatson mac_policy_assert_exclusive(); 344113487Srwatson 345113487Srwatson labelmbufs = 0; 346114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 347114806Srwatson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 348114806Srwatson labelmbufs++; 349114806Srwatson } 350113487Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 351113487Srwatson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 352113487Srwatson labelmbufs++; 353113487Srwatson } 354113487Srwatson mac_labelmbufs = (labelmbufs != 0); 355113487Srwatson#endif 356113487Srwatson} 357113487Srwatson 358113487Srwatson/* 359100979Srwatson * Allow MAC policy modules to register during boot, etc. 360100979Srwatson */ 361100894Srwatsonint 362100979Srwatsonmac_policy_modevent(module_t mod, int type, void *data) 363100979Srwatson{ 364100979Srwatson struct mac_policy_conf *mpc; 365100979Srwatson int error; 366100979Srwatson 367100979Srwatson error = 0; 368100979Srwatson mpc = (struct mac_policy_conf *) data; 369100979Srwatson 370128885Srwatson#ifdef MAC_STATIC 371128885Srwatson if (mac_late) { 372128885Srwatson printf("mac_policy_modevent: MAC_STATIC and late\n"); 373128885Srwatson return (EBUSY); 374128885Srwatson } 375128885Srwatson#endif 376128885Srwatson 377100979Srwatson switch (type) { 378100979Srwatson case MOD_LOAD: 379100979Srwatson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 380100979Srwatson mac_late) { 381100979Srwatson printf("mac_policy_modevent: can't load %s policy " 382100979Srwatson "after booting\n", mpc->mpc_name); 383100979Srwatson error = EBUSY; 384100979Srwatson break; 385100979Srwatson } 386100979Srwatson error = mac_policy_register(mpc); 387100979Srwatson break; 388100979Srwatson case MOD_UNLOAD: 389100979Srwatson /* Don't unregister the module if it was never registered. */ 390100979Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 391100979Srwatson != 0) 392100979Srwatson error = mac_policy_unregister(mpc); 393100979Srwatson else 394100979Srwatson error = 0; 395100979Srwatson break; 396100979Srwatson default: 397132199Sphk error = EOPNOTSUPP; 398100979Srwatson break; 399100979Srwatson } 400100979Srwatson 401100979Srwatson return (error); 402100979Srwatson} 403100979Srwatson 404100979Srwatsonstatic int 405100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc) 406100979Srwatson{ 407100979Srwatson struct mac_policy_conf *tmpc; 408114806Srwatson int error, slot, static_entry; 409100979Srwatson 410114806Srwatson error = 0; 411114806Srwatson 412114806Srwatson /* 413165411Srwatson * We don't technically need exclusive access while !mac_late, but 414165411Srwatson * hold it for assertion consistency. 415114806Srwatson */ 416114806Srwatson mac_policy_grab_exclusive(); 417114806Srwatson 418114806Srwatson /* 419165411Srwatson * If the module can potentially be unloaded, or we're loading late, 420165411Srwatson * we have to stick it in the non-static list and pay an extra 421165411Srwatson * performance overhead. Otherwise, we can pay a light locking cost 422165411Srwatson * and stick it in the static list. 423114806Srwatson */ 424114806Srwatson static_entry = (!mac_late && 425114806Srwatson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 426114806Srwatson 427114806Srwatson if (static_entry) { 428114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 429114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 430114806Srwatson error = EEXIST; 431114806Srwatson goto out; 432114806Srwatson } 433100979Srwatson } 434114806Srwatson } else { 435114806Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 436114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 437114806Srwatson error = EEXIST; 438114806Srwatson goto out; 439114806Srwatson } 440114806Srwatson } 441100979Srwatson } 442100979Srwatson if (mpc->mpc_field_off != NULL) { 443114846Srwatson slot = ffs(mac_slot_offsets_free); 444100979Srwatson if (slot == 0) { 445114806Srwatson error = ENOMEM; 446114806Srwatson goto out; 447100979Srwatson } 448100979Srwatson slot--; 449114846Srwatson mac_slot_offsets_free &= ~(1 << slot); 450100979Srwatson *mpc->mpc_field_off = slot; 451100979Srwatson } 452100979Srwatson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 453100979Srwatson 454114806Srwatson /* 455165411Srwatson * If we're loading a MAC module after the framework has initialized, 456165411Srwatson * it has to go into the dynamic list. If we're loading it before 457165411Srwatson * we've finished initializing, it can go into the static list with 458165411Srwatson * weaker locker requirements. 459114806Srwatson */ 460114806Srwatson if (static_entry) 461114806Srwatson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 462114806Srwatson else 463114806Srwatson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 464114806Srwatson 465165411Srwatson /* 466165411Srwatson * Per-policy initialization. Currently, this takes place under the 467165411Srwatson * exclusive lock, so policies must not sleep in their init method. 468165411Srwatson * In the future, we may want to separate "init" from "start", with 469165411Srwatson * "init" occuring without the lock held. Likewise, on tear-down, 470165411Srwatson * breaking out "stop" from "destroy". 471165411Srwatson */ 472100979Srwatson if (mpc->mpc_ops->mpo_init != NULL) 473100979Srwatson (*(mpc->mpc_ops->mpo_init))(mpc); 474113487Srwatson mac_policy_updateflags(); 475100979Srwatson 476100979Srwatson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 477100979Srwatson mpc->mpc_name); 478100979Srwatson 479114806Srwatsonout: 480114806Srwatson mac_policy_release_exclusive(); 481114806Srwatson return (error); 482100979Srwatson} 483100979Srwatson 484100979Srwatsonstatic int 485100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc) 486100979Srwatson{ 487100979Srwatson 488104520Srwatson /* 489165411Srwatson * If we fail the load, we may get a request to unload. Check to see 490165411Srwatson * if we did the run-time registration, and if not, silently succeed. 491104520Srwatson */ 492114806Srwatson mac_policy_grab_exclusive(); 493104520Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 494114806Srwatson mac_policy_release_exclusive(); 495104520Srwatson return (0); 496104520Srwatson } 497100979Srwatson#if 0 498100979Srwatson /* 499100979Srwatson * Don't allow unloading modules with private data. 500100979Srwatson */ 501104520Srwatson if (mpc->mpc_field_off != NULL) { 502104520Srwatson MAC_POLICY_LIST_UNLOCK(); 503100979Srwatson return (EBUSY); 504104520Srwatson } 505100979Srwatson#endif 506104520Srwatson /* 507165411Srwatson * Only allow the unload to proceed if the module is unloadable by 508165411Srwatson * its own definition. 509104520Srwatson */ 510104520Srwatson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 511114806Srwatson mac_policy_release_exclusive(); 512100979Srwatson return (EBUSY); 513104520Srwatson } 514100979Srwatson if (mpc->mpc_ops->mpo_destroy != NULL) 515100979Srwatson (*(mpc->mpc_ops->mpo_destroy))(mpc); 516100979Srwatson 517100979Srwatson LIST_REMOVE(mpc, mpc_list); 518106856Srwatson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 519113487Srwatson mac_policy_updateflags(); 520100979Srwatson 521114806Srwatson mac_policy_release_exclusive(); 522114806Srwatson 523100979Srwatson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 524100979Srwatson mpc->mpc_name); 525100979Srwatson 526100979Srwatson return (0); 527100979Srwatson} 528100979Srwatson 529100979Srwatson/* 530100979Srwatson * Define an error value precedence, and given two arguments, selects the 531100979Srwatson * value with the higher precedence. 532100979Srwatson */ 533121371Srwatsonint 534121371Srwatsonmac_error_select(int error1, int error2) 535100979Srwatson{ 536100979Srwatson 537100979Srwatson /* Certain decision-making errors take top priority. */ 538100979Srwatson if (error1 == EDEADLK || error2 == EDEADLK) 539100979Srwatson return (EDEADLK); 540100979Srwatson 541100979Srwatson /* Invalid arguments should be reported where possible. */ 542100979Srwatson if (error1 == EINVAL || error2 == EINVAL) 543100979Srwatson return (EINVAL); 544100979Srwatson 545100979Srwatson /* Precedence goes to "visibility", with both process and file. */ 546100979Srwatson if (error1 == ESRCH || error2 == ESRCH) 547100979Srwatson return (ESRCH); 548100979Srwatson 549100979Srwatson if (error1 == ENOENT || error2 == ENOENT) 550100979Srwatson return (ENOENT); 551100979Srwatson 552100979Srwatson /* Precedence goes to DAC/MAC protections. */ 553100979Srwatson if (error1 == EACCES || error2 == EACCES) 554100979Srwatson return (EACCES); 555100979Srwatson 556100979Srwatson /* Precedence goes to privilege. */ 557100979Srwatson if (error1 == EPERM || error2 == EPERM) 558100979Srwatson return (EPERM); 559100979Srwatson 560100979Srwatson /* Precedence goes to error over success; otherwise, arbitrary. */ 561100979Srwatson if (error1 != 0) 562100979Srwatson return (error1); 563100979Srwatson return (error2); 564100979Srwatson} 565100979Srwatson 566121374Srwatsonvoid 567104521Srwatsonmac_init_label(struct label *label) 568104521Srwatson{ 569104521Srwatson 570104521Srwatson bzero(label, sizeof(*label)); 571104521Srwatson label->l_flags = MAC_FLAG_INITIALIZED; 572104521Srwatson} 573104521Srwatson 574121374Srwatsonvoid 575104521Srwatsonmac_destroy_label(struct label *label) 576104521Srwatson{ 577104521Srwatson 578104521Srwatson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 579104521Srwatson ("destroying uninitialized label")); 580104521Srwatson 581104521Srwatson bzero(label, sizeof(*label)); 582104521Srwatson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 583104521Srwatson} 584104521Srwatson 585112675Srwatsonint 586105694Srwatsonmac_check_structmac_consistent(struct mac *mac) 587104522Srwatson{ 588105694Srwatson 589120582Srwatson if (mac->m_buflen < 0 || 590120582Srwatson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 591105694Srwatson return (EINVAL); 592105694Srwatson 593105694Srwatson return (0); 594105694Srwatson} 595105694Srwatson 596122584Srwatson/* 597122584Srwatson * MPSAFE 598122584Srwatson */ 599105988Srwatsonint 600105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 601105694Srwatson{ 602105694Srwatson char *elements, *buffer; 603105694Srwatson struct mac mac; 604105694Srwatson struct proc *tproc; 605105694Srwatson struct ucred *tcred; 606105694Srwatson int error; 607105694Srwatson 608107849Salfred error = copyin(uap->mac_p, &mac, sizeof(mac)); 609105694Srwatson if (error) 610105694Srwatson return (error); 611105694Srwatson 612105694Srwatson error = mac_check_structmac_consistent(&mac); 613105694Srwatson if (error) 614105694Srwatson return (error); 615105694Srwatson 616105694Srwatson tproc = pfind(uap->pid); 617105694Srwatson if (tproc == NULL) 618105694Srwatson return (ESRCH); 619105694Srwatson 620105694Srwatson tcred = NULL; /* Satisfy gcc. */ 621105694Srwatson error = p_cansee(td, tproc); 622105694Srwatson if (error == 0) 623105694Srwatson tcred = crhold(tproc->p_ucred); 624105694Srwatson PROC_UNLOCK(tproc); 625105694Srwatson if (error) 626105694Srwatson return (error); 627105694Srwatson 628111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 629105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 630105694Srwatson if (error) { 631105694Srwatson free(elements, M_MACTEMP); 632105694Srwatson crfree(tcred); 633105694Srwatson return (error); 634105694Srwatson } 635105694Srwatson 636111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 637122524Srwatson error = mac_externalize_cred_label(tcred->cr_label, elements, 638122159Srwatson buffer, mac.m_buflen); 639105694Srwatson if (error == 0) 640105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 641105694Srwatson 642105694Srwatson free(buffer, M_MACTEMP); 643105694Srwatson free(elements, M_MACTEMP); 644105694Srwatson crfree(tcred); 645105694Srwatson return (error); 646105694Srwatson} 647105694Srwatson 648100979Srwatson/* 649100979Srwatson * MPSAFE 650100979Srwatson */ 651100979Srwatsonint 652100894Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 653100894Srwatson{ 654105694Srwatson char *elements, *buffer; 655105694Srwatson struct mac mac; 656100979Srwatson int error; 657100894Srwatson 658105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 659105694Srwatson if (error) 660105694Srwatson return (error); 661105694Srwatson 662105694Srwatson error = mac_check_structmac_consistent(&mac); 663105694Srwatson if (error) 664105694Srwatson return (error); 665105694Srwatson 666111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 667105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 668105694Srwatson if (error) { 669105694Srwatson free(elements, M_MACTEMP); 670105694Srwatson return (error); 671105694Srwatson } 672105694Srwatson 673111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 674122524Srwatson error = mac_externalize_cred_label(td->td_ucred->cr_label, 675122159Srwatson elements, buffer, mac.m_buflen); 676100979Srwatson if (error == 0) 677105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 678100979Srwatson 679105694Srwatson free(buffer, M_MACTEMP); 680105694Srwatson free(elements, M_MACTEMP); 681100979Srwatson return (error); 682100979Srwatson} 683100979Srwatson 684100979Srwatson/* 685100979Srwatson * MPSAFE 686100979Srwatson */ 687100979Srwatsonint 688100979Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 689100979Srwatson{ 690100979Srwatson struct ucred *newcred, *oldcred; 691122524Srwatson struct label *intlabel; 692100979Srwatson struct proc *p; 693105694Srwatson struct mac mac; 694105694Srwatson char *buffer; 695100979Srwatson int error; 696100979Srwatson 697105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 698100979Srwatson if (error) 699100979Srwatson return (error); 700100979Srwatson 701105694Srwatson error = mac_check_structmac_consistent(&mac); 702100979Srwatson if (error) 703100979Srwatson return (error); 704100979Srwatson 705111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 706105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 707105694Srwatson if (error) { 708105694Srwatson free(buffer, M_MACTEMP); 709105694Srwatson return (error); 710105694Srwatson } 711105694Srwatson 712122524Srwatson intlabel = mac_cred_label_alloc(); 713122524Srwatson error = mac_internalize_cred_label(intlabel, buffer); 714105694Srwatson free(buffer, M_MACTEMP); 715122524Srwatson if (error) 716122524Srwatson goto out; 717105694Srwatson 718100979Srwatson newcred = crget(); 719100979Srwatson 720100979Srwatson p = td->td_proc; 721100979Srwatson PROC_LOCK(p); 722100979Srwatson oldcred = p->p_ucred; 723100979Srwatson 724122524Srwatson error = mac_check_cred_relabel(oldcred, intlabel); 725100979Srwatson if (error) { 726100979Srwatson PROC_UNLOCK(p); 727100979Srwatson crfree(newcred); 728105694Srwatson goto out; 729100979Srwatson } 730100979Srwatson 731100979Srwatson setsugid(p); 732100979Srwatson crcopy(newcred, oldcred); 733122524Srwatson mac_relabel_cred(newcred, intlabel); 734102136Srwatson p->p_ucred = newcred; 735100979Srwatson 736102136Srwatson /* 737165411Srwatson * Grab additional reference for use while revoking mmaps, prior to 738165411Srwatson * releasing the proc lock and sharing the cred. 739102136Srwatson */ 740102136Srwatson crhold(newcred); 741100979Srwatson PROC_UNLOCK(p); 742102136Srwatson 743165433Srwatson mac_cred_mmapped_drop_perms(td, newcred); 744102136Srwatson 745102136Srwatson crfree(newcred); /* Free revocation reference. */ 746100979Srwatson crfree(oldcred); 747105694Srwatson 748105694Srwatsonout: 749122524Srwatson mac_cred_label_free(intlabel); 750105694Srwatson return (error); 751100979Srwatson} 752100979Srwatson 753100979Srwatson/* 754100979Srwatson * MPSAFE 755100979Srwatson */ 756100979Srwatsonint 757100979Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 758100979Srwatson{ 759105694Srwatson char *elements, *buffer; 760122524Srwatson struct label *intlabel; 761100979Srwatson struct file *fp; 762105694Srwatson struct mac mac; 763100979Srwatson struct vnode *vp; 764100979Srwatson struct pipe *pipe; 765122820Srwatson struct socket *so; 766105694Srwatson short label_type; 767150914Scsjp int vfslocked, error; 768100979Srwatson 769105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 770105694Srwatson if (error) 771105694Srwatson return (error); 772100979Srwatson 773105694Srwatson error = mac_check_structmac_consistent(&mac); 774105694Srwatson if (error) 775105694Srwatson return (error); 776105694Srwatson 777111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 778105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 779105694Srwatson if (error) { 780105694Srwatson free(elements, M_MACTEMP); 781105694Srwatson return (error); 782105694Srwatson } 783105694Srwatson 784111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 785107849Salfred error = fget(td, uap->fd, &fp); 786100979Srwatson if (error) 787100979Srwatson goto out; 788100979Srwatson 789105694Srwatson label_type = fp->f_type; 790100979Srwatson switch (fp->f_type) { 791100979Srwatson case DTYPE_FIFO: 792100979Srwatson case DTYPE_VNODE: 793116678Sphk vp = fp->f_vnode; 794122524Srwatson intlabel = mac_vnode_label_alloc(); 795150914Scsjp vfslocked = VFS_LOCK_GIANT(vp->v_mount); 796100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 797122524Srwatson mac_copy_vnode_label(vp->v_label, intlabel); 798100979Srwatson VOP_UNLOCK(vp, 0, td); 799150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 800122584Srwatson error = mac_externalize_vnode_label(intlabel, elements, 801122584Srwatson buffer, mac.m_buflen); 802122584Srwatson mac_vnode_label_free(intlabel); 803122584Srwatson break; 804105694Srwatson 805100979Srwatson case DTYPE_PIPE: 806109153Sdillon pipe = fp->f_data; 807122524Srwatson intlabel = mac_pipe_label_alloc(); 808105694Srwatson PIPE_LOCK(pipe); 809125293Srwatson mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 810105694Srwatson PIPE_UNLOCK(pipe); 811122524Srwatson error = mac_externalize_pipe_label(intlabel, elements, 812122159Srwatson buffer, mac.m_buflen); 813122524Srwatson mac_pipe_label_free(intlabel); 814105694Srwatson break; 815122584Srwatson 816122820Srwatson case DTYPE_SOCKET: 817122820Srwatson so = fp->f_data; 818122820Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 819145160Srwatson NET_LOCK_GIANT(); 820145160Srwatson SOCK_LOCK(so); 821122820Srwatson mac_copy_socket_label(so->so_label, intlabel); 822145160Srwatson SOCK_UNLOCK(so); 823145160Srwatson NET_UNLOCK_GIANT(); 824122820Srwatson error = mac_externalize_socket_label(intlabel, elements, 825122820Srwatson buffer, mac.m_buflen); 826122820Srwatson mac_socket_label_free(intlabel); 827122820Srwatson break; 828122820Srwatson 829105694Srwatson default: 830122584Srwatson error = EINVAL; 831105694Srwatson } 832122584Srwatson fdrop(fp, td); 833100979Srwatson if (error == 0) 834105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 835100979Srwatson 836105694Srwatsonout: 837105694Srwatson free(buffer, M_MACTEMP); 838105694Srwatson free(elements, M_MACTEMP); 839100979Srwatson return (error); 840100979Srwatson} 841100979Srwatson 842100979Srwatson/* 843100979Srwatson * MPSAFE 844100979Srwatson */ 845100979Srwatsonint 846100979Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 847100979Srwatson{ 848105694Srwatson char *elements, *buffer; 849100979Srwatson struct nameidata nd; 850122524Srwatson struct label *intlabel; 851105694Srwatson struct mac mac; 852150914Scsjp int vfslocked, error; 853100979Srwatson 854105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 855105694Srwatson if (error) 856105694Srwatson return (error); 857105694Srwatson 858105694Srwatson error = mac_check_structmac_consistent(&mac); 859105694Srwatson if (error) 860105694Srwatson return (error); 861105694Srwatson 862111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 863105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 864105694Srwatson if (error) { 865105694Srwatson free(elements, M_MACTEMP); 866105694Srwatson return (error); 867105694Srwatson } 868105694Srwatson 869111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 870150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 871150914Scsjp uap->path_p, td); 872100979Srwatson error = namei(&nd); 873100979Srwatson if (error) 874100979Srwatson goto out; 875100979Srwatson 876122524Srwatson intlabel = mac_vnode_label_alloc(); 877150914Scsjp vfslocked = NDHASGIANT(&nd); 878122524Srwatson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 879122524Srwatson error = mac_externalize_vnode_label(intlabel, elements, buffer, 880122159Srwatson mac.m_buflen); 881105694Srwatson 882100979Srwatson NDFREE(&nd, 0); 883150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 884122524Srwatson mac_vnode_label_free(intlabel); 885105694Srwatson if (error == 0) 886105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 887105694Srwatson 888105694Srwatsonout: 889105694Srwatson free(buffer, M_MACTEMP); 890105694Srwatson free(elements, M_MACTEMP); 891105694Srwatson 892105694Srwatson return (error); 893105694Srwatson} 894105694Srwatson 895105694Srwatson/* 896105694Srwatson * MPSAFE 897105694Srwatson */ 898105694Srwatsonint 899105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 900105694Srwatson{ 901105694Srwatson char *elements, *buffer; 902105694Srwatson struct nameidata nd; 903122524Srwatson struct label *intlabel; 904105694Srwatson struct mac mac; 905150914Scsjp int vfslocked, error; 906105694Srwatson 907105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 908100979Srwatson if (error) 909105694Srwatson return (error); 910105694Srwatson 911105694Srwatson error = mac_check_structmac_consistent(&mac); 912105694Srwatson if (error) 913105694Srwatson return (error); 914105694Srwatson 915111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 916105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 917105694Srwatson if (error) { 918105694Srwatson free(elements, M_MACTEMP); 919105694Srwatson return (error); 920105694Srwatson } 921105694Srwatson 922111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 923150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 924150914Scsjp uap->path_p, td); 925105694Srwatson error = namei(&nd); 926105694Srwatson if (error) 927100979Srwatson goto out; 928100979Srwatson 929122524Srwatson intlabel = mac_vnode_label_alloc(); 930150914Scsjp vfslocked = NDHASGIANT(&nd); 931122524Srwatson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 932122524Srwatson error = mac_externalize_vnode_label(intlabel, elements, buffer, 933122159Srwatson mac.m_buflen); 934105694Srwatson NDFREE(&nd, 0); 935150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 936122524Srwatson mac_vnode_label_free(intlabel); 937100979Srwatson 938105694Srwatson if (error == 0) 939105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 940105694Srwatson 941100979Srwatsonout: 942105694Srwatson free(buffer, M_MACTEMP); 943105694Srwatson free(elements, M_MACTEMP); 944105694Srwatson 945100979Srwatson return (error); 946100979Srwatson} 947100979Srwatson 948100979Srwatson/* 949100979Srwatson * MPSAFE 950100979Srwatson */ 951100979Srwatsonint 952100979Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 953100979Srwatson{ 954122524Srwatson struct label *intlabel; 955105694Srwatson struct pipe *pipe; 956122820Srwatson struct socket *so; 957100979Srwatson struct file *fp; 958100979Srwatson struct mount *mp; 959100979Srwatson struct vnode *vp; 960105694Srwatson struct mac mac; 961105694Srwatson char *buffer; 962150914Scsjp int error, vfslocked; 963100979Srwatson 964105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 965100979Srwatson if (error) 966105694Srwatson return (error); 967100979Srwatson 968105694Srwatson error = mac_check_structmac_consistent(&mac); 969100979Srwatson if (error) 970105694Srwatson return (error); 971100979Srwatson 972111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 973105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 974105694Srwatson if (error) { 975105694Srwatson free(buffer, M_MACTEMP); 976105694Srwatson return (error); 977105694Srwatson } 978105694Srwatson 979107849Salfred error = fget(td, uap->fd, &fp); 980100979Srwatson if (error) 981105694Srwatson goto out; 982100979Srwatson 983100979Srwatson switch (fp->f_type) { 984100979Srwatson case DTYPE_FIFO: 985100979Srwatson case DTYPE_VNODE: 986122524Srwatson intlabel = mac_vnode_label_alloc(); 987122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 988105694Srwatson if (error) { 989122524Srwatson mac_vnode_label_free(intlabel); 990105694Srwatson break; 991105694Srwatson } 992116678Sphk vp = fp->f_vnode; 993150914Scsjp vfslocked = VFS_LOCK_GIANT(vp->v_mount); 994100979Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 995105694Srwatson if (error != 0) { 996150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 997122524Srwatson mac_vnode_label_free(intlabel); 998100979Srwatson break; 999105694Srwatson } 1000100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1001122524Srwatson error = vn_setlabel(vp, intlabel, td->td_ucred); 1002100979Srwatson VOP_UNLOCK(vp, 0, td); 1003100979Srwatson vn_finished_write(mp); 1004150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1005122524Srwatson mac_vnode_label_free(intlabel); 1006100979Srwatson break; 1007105694Srwatson 1008100979Srwatson case DTYPE_PIPE: 1009122524Srwatson intlabel = mac_pipe_label_alloc(); 1010122524Srwatson error = mac_internalize_pipe_label(intlabel, buffer); 1011105694Srwatson if (error == 0) { 1012109153Sdillon pipe = fp->f_data; 1013105694Srwatson PIPE_LOCK(pipe); 1014125293Srwatson error = mac_pipe_label_set(td->td_ucred, 1015125293Srwatson pipe->pipe_pair, intlabel); 1016105694Srwatson PIPE_UNLOCK(pipe); 1017105694Srwatson } 1018122524Srwatson mac_pipe_label_free(intlabel); 1019100979Srwatson break; 1020105694Srwatson 1021122820Srwatson case DTYPE_SOCKET: 1022122820Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 1023122820Srwatson error = mac_internalize_socket_label(intlabel, buffer); 1024122820Srwatson if (error == 0) { 1025122820Srwatson so = fp->f_data; 1026145160Srwatson NET_LOCK_GIANT(); 1027122820Srwatson error = mac_socket_label_set(td->td_ucred, so, 1028122820Srwatson intlabel); 1029145160Srwatson NET_UNLOCK_GIANT(); 1030122820Srwatson } 1031122820Srwatson mac_socket_label_free(intlabel); 1032122820Srwatson break; 1033122820Srwatson 1034100979Srwatson default: 1035100979Srwatson error = EINVAL; 1036100979Srwatson } 1037100979Srwatson fdrop(fp, td); 1038105694Srwatsonout: 1039105694Srwatson free(buffer, M_MACTEMP); 1040100979Srwatson return (error); 1041100979Srwatson} 1042100979Srwatson 1043100979Srwatson/* 1044100979Srwatson * MPSAFE 1045100979Srwatson */ 1046100979Srwatsonint 1047100979Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1048100979Srwatson{ 1049122524Srwatson struct label *intlabel; 1050100979Srwatson struct nameidata nd; 1051100979Srwatson struct mount *mp; 1052105694Srwatson struct mac mac; 1053105694Srwatson char *buffer; 1054150914Scsjp int vfslocked, error; 1055100979Srwatson 1056105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1057100979Srwatson if (error) 1058105694Srwatson return (error); 1059100979Srwatson 1060105694Srwatson error = mac_check_structmac_consistent(&mac); 1061100979Srwatson if (error) 1062105694Srwatson return (error); 1063100979Srwatson 1064111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1065105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1066105694Srwatson if (error) { 1067105694Srwatson free(buffer, M_MACTEMP); 1068105694Srwatson return (error); 1069105694Srwatson } 1070105694Srwatson 1071122524Srwatson intlabel = mac_vnode_label_alloc(); 1072122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 1073105694Srwatson free(buffer, M_MACTEMP); 1074122524Srwatson if (error) 1075122524Srwatson goto out; 1076105694Srwatson 1077150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 1078150914Scsjp uap->path_p, td); 1079100979Srwatson error = namei(&nd); 1080150914Scsjp vfslocked = NDHASGIANT(&nd); 1081105694Srwatson if (error == 0) { 1082105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1083156893Stegge if (error == 0) { 1084122524Srwatson error = vn_setlabel(nd.ni_vp, intlabel, 1085105694Srwatson td->td_ucred); 1086156893Stegge vn_finished_write(mp); 1087156893Stegge } 1088105694Srwatson } 1089105694Srwatson 1090105694Srwatson NDFREE(&nd, 0); 1091150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1092122524Srwatsonout: 1093122524Srwatson mac_vnode_label_free(intlabel); 1094105694Srwatson return (error); 1095105694Srwatson} 1096105694Srwatson 1097105694Srwatson/* 1098105694Srwatson * MPSAFE 1099105694Srwatson */ 1100105694Srwatsonint 1101105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1102105694Srwatson{ 1103122524Srwatson struct label *intlabel; 1104105694Srwatson struct nameidata nd; 1105105694Srwatson struct mount *mp; 1106105694Srwatson struct mac mac; 1107105694Srwatson char *buffer; 1108150914Scsjp int vfslocked, error; 1109105694Srwatson 1110105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1111100979Srwatson if (error) 1112105694Srwatson return (error); 1113105694Srwatson 1114105694Srwatson error = mac_check_structmac_consistent(&mac); 1115100979Srwatson if (error) 1116105694Srwatson return (error); 1117100979Srwatson 1118111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1119105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1120105694Srwatson if (error) { 1121105694Srwatson free(buffer, M_MACTEMP); 1122105694Srwatson return (error); 1123105694Srwatson } 1124105694Srwatson 1125122524Srwatson intlabel = mac_vnode_label_alloc(); 1126122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 1127105694Srwatson free(buffer, M_MACTEMP); 1128122524Srwatson if (error) 1129122524Srwatson goto out; 1130105694Srwatson 1131150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 1132150914Scsjp uap->path_p, td); 1133105694Srwatson error = namei(&nd); 1134150914Scsjp vfslocked = NDHASGIANT(&nd); 1135105694Srwatson if (error == 0) { 1136105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1137156893Stegge if (error == 0) { 1138122524Srwatson error = vn_setlabel(nd.ni_vp, intlabel, 1139105694Srwatson td->td_ucred); 1140156893Stegge vn_finished_write(mp); 1141156893Stegge } 1142105694Srwatson } 1143105694Srwatson 1144100979Srwatson NDFREE(&nd, 0); 1145150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1146122524Srwatsonout: 1147122524Srwatson mac_vnode_label_free(intlabel); 1148100979Srwatson return (error); 1149100979Srwatson} 1150100979Srwatson 1151105694Srwatson/* 1152105694Srwatson * MPSAFE 1153105694Srwatson */ 1154102123Srwatsonint 1155102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1156102123Srwatson{ 1157102123Srwatson struct mac_policy_conf *mpc; 1158102123Srwatson char target[MAC_MAX_POLICY_NAME]; 1159114806Srwatson int entrycount, error; 1160102123Srwatson 1161107849Salfred error = copyinstr(uap->policy, target, sizeof(target), NULL); 1162102123Srwatson if (error) 1163102123Srwatson return (error); 1164102123Srwatson 1165102123Srwatson error = ENOSYS; 1166119494Srwatson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1167102123Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1168102123Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1169102123Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1170107849Salfred uap->call, uap->arg); 1171102123Srwatson goto out; 1172102123Srwatson } 1173102123Srwatson } 1174102123Srwatson 1175114806Srwatson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1176114806Srwatson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1177114806Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1178114806Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1179114806Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1180114806Srwatson uap->call, uap->arg); 1181114806Srwatson break; 1182114806Srwatson } 1183114806Srwatson } 1184114806Srwatson mac_policy_list_unbusy(); 1185114806Srwatson } 1186102123Srwatsonout: 1187102123Srwatson return (error); 1188102123Srwatson} 1189102123Srwatson 1190100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1191100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1192100979Srwatson 1193100979Srwatson#else /* !MAC */ 1194100979Srwatson 1195100979Srwatsonint 1196105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1197105694Srwatson{ 1198105694Srwatson 1199105694Srwatson return (ENOSYS); 1200105694Srwatson} 1201105694Srwatson 1202105694Srwatsonint 1203100979Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1204100979Srwatson{ 1205100979Srwatson 1206100894Srwatson return (ENOSYS); 1207100894Srwatson} 1208100894Srwatson 1209100894Srwatsonint 1210100894Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1211100894Srwatson{ 1212100894Srwatson 1213100894Srwatson return (ENOSYS); 1214100894Srwatson} 1215100894Srwatson 1216100894Srwatsonint 1217100894Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1218100894Srwatson{ 1219100894Srwatson 1220100894Srwatson return (ENOSYS); 1221100894Srwatson} 1222100894Srwatson 1223100894Srwatsonint 1224100894Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1225100894Srwatson{ 1226100894Srwatson 1227100894Srwatson return (ENOSYS); 1228100894Srwatson} 1229100894Srwatson 1230100894Srwatsonint 1231105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1232105694Srwatson{ 1233105694Srwatson 1234105694Srwatson return (ENOSYS); 1235105694Srwatson} 1236105694Srwatson 1237105694Srwatsonint 1238100894Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1239100894Srwatson{ 1240100894Srwatson 1241100894Srwatson return (ENOSYS); 1242100894Srwatson} 1243100894Srwatson 1244100894Srwatsonint 1245100894Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1246100894Srwatson{ 1247100894Srwatson 1248100894Srwatson return (ENOSYS); 1249100894Srwatson} 1250100979Srwatson 1251102123Srwatsonint 1252105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1253105694Srwatson{ 1254105694Srwatson 1255105694Srwatson return (ENOSYS); 1256105694Srwatson} 1257105694Srwatson 1258105694Srwatsonint 1259102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1260102123Srwatson{ 1261102123Srwatson 1262102123Srwatson return (ENOSYS); 1263102123Srwatson} 1264102123Srwatson 1265128901Srwatson#endif /* !MAC */ 1266