mac_syscalls.c revision 150914
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. 5147983Srwatson * Copyright (c) 2005 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 150914 2005-10-04 14:32:58Z csjp $"); 51116182Sobrien 52100894Srwatson#include "opt_mac.h" 53104300Sphk#include "opt_devfs.h" 54101173Srwatson 55100894Srwatson#include <sys/param.h> 56106856Srwatson#include <sys/condvar.h> 57100979Srwatson#include <sys/extattr.h> 58106468Srwatson#include <sys/imgact.h> 59100979Srwatson#include <sys/kernel.h> 60100979Srwatson#include <sys/lock.h> 61102949Sbde#include <sys/malloc.h> 62100979Srwatson#include <sys/mutex.h> 63100979Srwatson#include <sys/mac.h> 64101712Srwatson#include <sys/module.h> 65100979Srwatson#include <sys/proc.h> 66116701Srwatson#include <sys/sbuf.h> 67100979Srwatson#include <sys/systm.h> 68100894Srwatson#include <sys/sysproto.h> 69100894Srwatson#include <sys/sysent.h> 70100979Srwatson#include <sys/vnode.h> 71100979Srwatson#include <sys/mount.h> 72100979Srwatson#include <sys/file.h> 73100979Srwatson#include <sys/namei.h> 74100979Srwatson#include <sys/socket.h> 75100979Srwatson#include <sys/pipe.h> 76100979Srwatson#include <sys/socketvar.h> 77100979Srwatson#include <sys/sysctl.h> 78100894Srwatson 79100979Srwatson#include <vm/vm.h> 80100979Srwatson#include <vm/pmap.h> 81100979Srwatson#include <vm/vm_map.h> 82100979Srwatson#include <vm/vm_object.h> 83100979Srwatson 84100979Srwatson#include <sys/mac_policy.h> 85100979Srwatson 86100979Srwatson#include <fs/devfs/devfs.h> 87100979Srwatson 88100979Srwatson#include <net/bpfdesc.h> 89100979Srwatson#include <net/if.h> 90100979Srwatson#include <net/if_var.h> 91100979Srwatson 92100979Srwatson#include <netinet/in.h> 93100979Srwatson#include <netinet/ip_var.h> 94100979Srwatson 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 109114846Srwatson#if MAC_MAX_SLOTS > 32 110114846Srwatson#error "MAC_MAX_SLOTS too large" 111100979Srwatson#endif 112105497Srwatson 113114846Srwatsonstatic unsigned int mac_max_slots = MAC_MAX_SLOTS; 114114846Srwatsonstatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 115114846SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 116114846Srwatson &mac_max_slots, 0, ""); 117100979Srwatson 118105959Srwatson/* 119105959Srwatson * Has the kernel started generating labeled objects yet? All read/write 120105959Srwatson * access to this variable is serialized during the boot process. Following 121105959Srwatson * the end of serialization, we don't update this flag; no locking. 122105959Srwatson */ 123121372Srwatsonint mac_late = 0; 124100979Srwatson 125105988Srwatson/* 126113487Srwatson * Flag to indicate whether or not we should allocate label storage for 127113487Srwatson * new mbufs. Since most dynamic policies we currently work with don't 128113487Srwatson * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 129113487Srwatson * unless specifically notified of interest. One result of this is 130113487Srwatson * that if a dynamically loaded policy requests mbuf labels, it must 131113487Srwatson * be able to deal with a NULL label being returned on any mbufs that 132113487Srwatson * were already in flight when the policy was loaded. Since the policy 133113487Srwatson * already has to deal with uninitialized labels, this probably won't 134113487Srwatson * be a problem. Note: currently no locking. Will this be a problem? 135113487Srwatson */ 136118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF 137121372Srwatsonint mac_labelmbufs = 0; 138113487Srwatson#endif 139113487Srwatson 140101988Srwatson#ifdef MAC_DEBUG 141104268SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 142104268Srwatson "TrustedBSD MAC debug info"); 143104517SrwatsonSYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 144104517Srwatson "TrustedBSD MAC object counters"); 145104517Srwatson 146121374Srwatsonstatic unsigned int nmactemp; 147104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 148100979Srwatson &nmactemp, 0, "number of temporary labels in use"); 149101988Srwatson#endif 150100979Srwatson 151100979Srwatsonstatic int mac_policy_register(struct mac_policy_conf *mpc); 152100979Srwatsonstatic int mac_policy_unregister(struct mac_policy_conf *mpc); 153100979Srwatson 154105694SrwatsonMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 155100979Srwatson 156100979Srwatson/* 157114806Srwatson * mac_static_policy_list holds a list of policy modules that are not 158114806Srwatson * loaded while the system is "live", and cannot be unloaded. These 159114806Srwatson * policies can be invoked without holding the busy count. 160114806Srwatson * 161114806Srwatson * mac_policy_list stores the list of dynamic policies. A busy count is 162106856Srwatson * maintained for the list, stored in mac_policy_busy. The busy count 163114806Srwatson * is protected by mac_policy_mtx; the list may be modified only 164106856Srwatson * while the busy count is 0, requiring that the lock be held to 165106856Srwatson * prevent new references to the list from being acquired. For almost 166106856Srwatson * all operations, incrementing the busy count is sufficient to 167106856Srwatson * guarantee consistency, as the list cannot be modified while the 168106856Srwatson * busy count is elevated. For a few special operations involving a 169114806Srwatson * change to the list of active policies, the mtx itself must be held. 170114806Srwatson * A condition variable, mac_policy_cv, is used to signal potential 171114806Srwatson * exclusive consumers that they should try to acquire the lock if a 172114806Srwatson * first attempt at exclusive access fails. 173100979Srwatson */ 174128885Srwatson#ifndef MAC_STATIC 175114806Srwatsonstatic struct mtx mac_policy_mtx; 176114806Srwatsonstatic struct cv mac_policy_cv; 177114806Srwatsonstatic int mac_policy_count; 178128885Srwatson#endif 179121372Srwatsonstruct mac_policy_list_head mac_policy_list; 180121372Srwatsonstruct mac_policy_list_head mac_static_policy_list; 181100979Srwatson 182106856Srwatson/* 183111883Sjhb * We manually invoke WITNESS_WARN() to allow Witness to generate 184106856Srwatson * warnings even if we don't end up ever triggering the wait at 185106856Srwatson * run-time. The consumer of the exclusive interface must not hold 186106856Srwatson * any locks (other than potentially Giant) since we may sleep for 187106856Srwatson * long (potentially indefinite) periods of time waiting for the 188106856Srwatson * framework to become quiescent so that a policy list change may 189106856Srwatson * be made. 190106856Srwatson */ 191121372Srwatsonvoid 192114806Srwatsonmac_policy_grab_exclusive(void) 193114806Srwatson{ 194122454Srwatson 195128885Srwatson#ifndef MAC_STATIC 196137072Srwatson if (!mac_late) 197137072Srwatson return; 198137072Srwatson 199114806Srwatson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 200114806Srwatson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 201114806Srwatson mtx_lock(&mac_policy_mtx); 202114806Srwatson while (mac_policy_count != 0) 203114806Srwatson cv_wait(&mac_policy_cv, &mac_policy_mtx); 204128885Srwatson#endif 205114806Srwatson} 206106856Srwatson 207121372Srwatsonvoid 208114806Srwatsonmac_policy_assert_exclusive(void) 209114806Srwatson{ 210122454Srwatson 211128885Srwatson#ifndef MAC_STATIC 212137072Srwatson if (!mac_late) 213137072Srwatson return; 214137072Srwatson 215114806Srwatson mtx_assert(&mac_policy_mtx, MA_OWNED); 216114806Srwatson KASSERT(mac_policy_count == 0, 217114806Srwatson ("mac_policy_assert_exclusive(): not exclusive")); 218128885Srwatson#endif 219114806Srwatson} 220113487Srwatson 221121372Srwatsonvoid 222114806Srwatsonmac_policy_release_exclusive(void) 223114806Srwatson{ 224100979Srwatson 225128885Srwatson#ifndef MAC_STATIC 226137072Srwatson if (!mac_late) 227137072Srwatson return; 228137072Srwatson 229114806Srwatson KASSERT(mac_policy_count == 0, 230114806Srwatson ("mac_policy_release_exclusive(): not exclusive")); 231114806Srwatson mtx_unlock(&mac_policy_mtx); 232114806Srwatson cv_signal(&mac_policy_cv); 233128885Srwatson#endif 234114806Srwatson} 235100979Srwatson 236121372Srwatsonvoid 237114806Srwatsonmac_policy_list_busy(void) 238114806Srwatson{ 239122454Srwatson 240128885Srwatson#ifndef MAC_STATIC 241137072Srwatson if (!mac_late) 242137072Srwatson return; 243137072Srwatson 244114806Srwatson mtx_lock(&mac_policy_mtx); 245114806Srwatson mac_policy_count++; 246114806Srwatson mtx_unlock(&mac_policy_mtx); 247128885Srwatson#endif 248114806Srwatson} 249114806Srwatson 250121372Srwatsonint 251114806Srwatsonmac_policy_list_conditional_busy(void) 252114806Srwatson{ 253128885Srwatson#ifndef MAC_STATIC 254114806Srwatson int ret; 255114806Srwatson 256137072Srwatson if (!mac_late) 257137072Srwatson return (1); 258137072Srwatson 259114806Srwatson mtx_lock(&mac_policy_mtx); 260114806Srwatson if (!LIST_EMPTY(&mac_policy_list)) { 261114806Srwatson mac_policy_count++; 262114806Srwatson ret = 1; 263114806Srwatson } else 264114806Srwatson ret = 0; 265114806Srwatson mtx_unlock(&mac_policy_mtx); 266114806Srwatson return (ret); 267128885Srwatson#else 268137072Srwatson if (!mac_late) 269137072Srwatson return (1); 270137072Srwatson 271128885Srwatson return (1); 272128885Srwatson#endif 273114806Srwatson} 274114806Srwatson 275121372Srwatsonvoid 276114806Srwatsonmac_policy_list_unbusy(void) 277114806Srwatson{ 278122454Srwatson 279128885Srwatson#ifndef MAC_STATIC 280137072Srwatson if (!mac_late) 281137072Srwatson return; 282137072Srwatson 283114806Srwatson mtx_lock(&mac_policy_mtx); 284114806Srwatson mac_policy_count--; 285114806Srwatson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 286114806Srwatson if (mac_policy_count == 0) 287114806Srwatson cv_signal(&mac_policy_cv); 288114806Srwatson mtx_unlock(&mac_policy_mtx); 289128885Srwatson#endif 290114806Srwatson} 291114806Srwatson 292100979Srwatson/* 293100979Srwatson * Initialize the MAC subsystem, including appropriate SMP locks. 294100979Srwatson */ 295100979Srwatsonstatic void 296100979Srwatsonmac_init(void) 297100979Srwatson{ 298100979Srwatson 299114806Srwatson LIST_INIT(&mac_static_policy_list); 300100979Srwatson LIST_INIT(&mac_policy_list); 301122524Srwatson mac_labelzone_init(); 302114806Srwatson 303128885Srwatson#ifndef MAC_STATIC 304114806Srwatson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 305114806Srwatson cv_init(&mac_policy_cv, "mac_policy_cv"); 306128885Srwatson#endif 307100979Srwatson} 308100979Srwatson 309100979Srwatson/* 310100979Srwatson * For the purposes of modules that want to know if they were loaded 311100979Srwatson * "early", set the mac_late flag once we've processed modules either 312100979Srwatson * linked into the kernel, or loaded before the kernel startup. 313100979Srwatson */ 314100979Srwatsonstatic void 315100979Srwatsonmac_late_init(void) 316100979Srwatson{ 317100979Srwatson 318100979Srwatson mac_late = 1; 319100979Srwatson} 320100979Srwatson 321100979Srwatson/* 322113487Srwatson * After the policy list has changed, walk the list to update any global 323118308Srwatson * flags. Currently, we support only one flag, and it's conditionally 324118308Srwatson * defined; as a result, the entire function is conditional. Eventually, 325118308Srwatson * the #else case might also iterate across the policies. 326113487Srwatson */ 327113487Srwatsonstatic void 328113487Srwatsonmac_policy_updateflags(void) 329113487Srwatson{ 330118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF 331113487Srwatson struct mac_policy_conf *tmpc; 332113487Srwatson int labelmbufs; 333113487Srwatson 334114806Srwatson mac_policy_assert_exclusive(); 335113487Srwatson 336113487Srwatson labelmbufs = 0; 337114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 338114806Srwatson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 339114806Srwatson labelmbufs++; 340114806Srwatson } 341113487Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 342113487Srwatson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 343113487Srwatson labelmbufs++; 344113487Srwatson } 345113487Srwatson mac_labelmbufs = (labelmbufs != 0); 346113487Srwatson#endif 347113487Srwatson} 348113487Srwatson 349113487Srwatson/* 350100979Srwatson * Allow MAC policy modules to register during boot, etc. 351100979Srwatson */ 352100894Srwatsonint 353100979Srwatsonmac_policy_modevent(module_t mod, int type, void *data) 354100979Srwatson{ 355100979Srwatson struct mac_policy_conf *mpc; 356100979Srwatson int error; 357100979Srwatson 358100979Srwatson error = 0; 359100979Srwatson mpc = (struct mac_policy_conf *) data; 360100979Srwatson 361128885Srwatson#ifdef MAC_STATIC 362128885Srwatson if (mac_late) { 363128885Srwatson printf("mac_policy_modevent: MAC_STATIC and late\n"); 364128885Srwatson return (EBUSY); 365128885Srwatson } 366128885Srwatson#endif 367128885Srwatson 368100979Srwatson switch (type) { 369100979Srwatson case MOD_LOAD: 370100979Srwatson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 371100979Srwatson mac_late) { 372100979Srwatson printf("mac_policy_modevent: can't load %s policy " 373100979Srwatson "after booting\n", mpc->mpc_name); 374100979Srwatson error = EBUSY; 375100979Srwatson break; 376100979Srwatson } 377100979Srwatson error = mac_policy_register(mpc); 378100979Srwatson break; 379100979Srwatson case MOD_UNLOAD: 380100979Srwatson /* Don't unregister the module if it was never registered. */ 381100979Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 382100979Srwatson != 0) 383100979Srwatson error = mac_policy_unregister(mpc); 384100979Srwatson else 385100979Srwatson error = 0; 386100979Srwatson break; 387100979Srwatson default: 388132199Sphk error = EOPNOTSUPP; 389100979Srwatson break; 390100979Srwatson } 391100979Srwatson 392100979Srwatson return (error); 393100979Srwatson} 394100979Srwatson 395100979Srwatsonstatic int 396100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc) 397100979Srwatson{ 398100979Srwatson struct mac_policy_conf *tmpc; 399114806Srwatson int error, slot, static_entry; 400100979Srwatson 401114806Srwatson error = 0; 402114806Srwatson 403114806Srwatson /* 404114806Srwatson * We don't technically need exclusive access while !mac_late, 405114806Srwatson * but hold it for assertion consistency. 406114806Srwatson */ 407114806Srwatson mac_policy_grab_exclusive(); 408114806Srwatson 409114806Srwatson /* 410114806Srwatson * If the module can potentially be unloaded, or we're loading 411114806Srwatson * late, we have to stick it in the non-static list and pay 412114806Srwatson * an extra performance overhead. Otherwise, we can pay a 413114806Srwatson * light locking cost and stick it in the static list. 414114806Srwatson */ 415114806Srwatson static_entry = (!mac_late && 416114806Srwatson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 417114806Srwatson 418114806Srwatson if (static_entry) { 419114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 420114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 421114806Srwatson error = EEXIST; 422114806Srwatson goto out; 423114806Srwatson } 424100979Srwatson } 425114806Srwatson } else { 426114806Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 427114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 428114806Srwatson error = EEXIST; 429114806Srwatson goto out; 430114806Srwatson } 431114806Srwatson } 432100979Srwatson } 433100979Srwatson if (mpc->mpc_field_off != NULL) { 434114846Srwatson slot = ffs(mac_slot_offsets_free); 435100979Srwatson if (slot == 0) { 436114806Srwatson error = ENOMEM; 437114806Srwatson goto out; 438100979Srwatson } 439100979Srwatson slot--; 440114846Srwatson mac_slot_offsets_free &= ~(1 << slot); 441100979Srwatson *mpc->mpc_field_off = slot; 442100979Srwatson } 443100979Srwatson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 444100979Srwatson 445114806Srwatson /* 446114806Srwatson * If we're loading a MAC module after the framework has 447114806Srwatson * initialized, it has to go into the dynamic list. If 448114806Srwatson * we're loading it before we've finished initializing, 449114806Srwatson * it can go into the static list with weaker locker 450114806Srwatson * requirements. 451114806Srwatson */ 452114806Srwatson if (static_entry) 453114806Srwatson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 454114806Srwatson else 455114806Srwatson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 456114806Srwatson 457100979Srwatson /* Per-policy initialization. */ 458100979Srwatson if (mpc->mpc_ops->mpo_init != NULL) 459100979Srwatson (*(mpc->mpc_ops->mpo_init))(mpc); 460113487Srwatson mac_policy_updateflags(); 461100979Srwatson 462100979Srwatson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 463100979Srwatson mpc->mpc_name); 464100979Srwatson 465114806Srwatsonout: 466114806Srwatson mac_policy_release_exclusive(); 467114806Srwatson return (error); 468100979Srwatson} 469100979Srwatson 470100979Srwatsonstatic int 471100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc) 472100979Srwatson{ 473100979Srwatson 474104520Srwatson /* 475104520Srwatson * If we fail the load, we may get a request to unload. Check 476104520Srwatson * to see if we did the run-time registration, and if not, 477104520Srwatson * silently succeed. 478104520Srwatson */ 479114806Srwatson mac_policy_grab_exclusive(); 480104520Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 481114806Srwatson mac_policy_release_exclusive(); 482104520Srwatson return (0); 483104520Srwatson } 484100979Srwatson#if 0 485100979Srwatson /* 486100979Srwatson * Don't allow unloading modules with private data. 487100979Srwatson */ 488104520Srwatson if (mpc->mpc_field_off != NULL) { 489104520Srwatson MAC_POLICY_LIST_UNLOCK(); 490100979Srwatson return (EBUSY); 491104520Srwatson } 492100979Srwatson#endif 493104520Srwatson /* 494104520Srwatson * Only allow the unload to proceed if the module is unloadable 495104520Srwatson * by its own definition. 496104520Srwatson */ 497104520Srwatson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 498114806Srwatson mac_policy_release_exclusive(); 499100979Srwatson return (EBUSY); 500104520Srwatson } 501100979Srwatson if (mpc->mpc_ops->mpo_destroy != NULL) 502100979Srwatson (*(mpc->mpc_ops->mpo_destroy))(mpc); 503100979Srwatson 504100979Srwatson LIST_REMOVE(mpc, mpc_list); 505106856Srwatson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 506113487Srwatson mac_policy_updateflags(); 507100979Srwatson 508114806Srwatson mac_policy_release_exclusive(); 509114806Srwatson 510100979Srwatson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 511100979Srwatson mpc->mpc_name); 512100979Srwatson 513100979Srwatson return (0); 514100979Srwatson} 515100979Srwatson 516100979Srwatson/* 517100979Srwatson * Define an error value precedence, and given two arguments, selects the 518100979Srwatson * value with the higher precedence. 519100979Srwatson */ 520121371Srwatsonint 521121371Srwatsonmac_error_select(int error1, int error2) 522100979Srwatson{ 523100979Srwatson 524100979Srwatson /* Certain decision-making errors take top priority. */ 525100979Srwatson if (error1 == EDEADLK || error2 == EDEADLK) 526100979Srwatson return (EDEADLK); 527100979Srwatson 528100979Srwatson /* Invalid arguments should be reported where possible. */ 529100979Srwatson if (error1 == EINVAL || error2 == EINVAL) 530100979Srwatson return (EINVAL); 531100979Srwatson 532100979Srwatson /* Precedence goes to "visibility", with both process and file. */ 533100979Srwatson if (error1 == ESRCH || error2 == ESRCH) 534100979Srwatson return (ESRCH); 535100979Srwatson 536100979Srwatson if (error1 == ENOENT || error2 == ENOENT) 537100979Srwatson return (ENOENT); 538100979Srwatson 539100979Srwatson /* Precedence goes to DAC/MAC protections. */ 540100979Srwatson if (error1 == EACCES || error2 == EACCES) 541100979Srwatson return (EACCES); 542100979Srwatson 543100979Srwatson /* Precedence goes to privilege. */ 544100979Srwatson if (error1 == EPERM || error2 == EPERM) 545100979Srwatson return (EPERM); 546100979Srwatson 547100979Srwatson /* Precedence goes to error over success; otherwise, arbitrary. */ 548100979Srwatson if (error1 != 0) 549100979Srwatson return (error1); 550100979Srwatson return (error2); 551100979Srwatson} 552100979Srwatson 553121374Srwatsonvoid 554104521Srwatsonmac_init_label(struct label *label) 555104521Srwatson{ 556104521Srwatson 557104521Srwatson bzero(label, sizeof(*label)); 558104521Srwatson label->l_flags = MAC_FLAG_INITIALIZED; 559104521Srwatson} 560104521Srwatson 561121374Srwatsonvoid 562104521Srwatsonmac_destroy_label(struct label *label) 563104521Srwatson{ 564104521Srwatson 565104521Srwatson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 566104521Srwatson ("destroying uninitialized label")); 567104521Srwatson 568104521Srwatson bzero(label, sizeof(*label)); 569104521Srwatson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 570104521Srwatson} 571104521Srwatson 572112675Srwatsonint 573105694Srwatsonmac_check_structmac_consistent(struct mac *mac) 574104522Srwatson{ 575105694Srwatson 576120582Srwatson if (mac->m_buflen < 0 || 577120582Srwatson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 578105694Srwatson return (EINVAL); 579105694Srwatson 580105694Srwatson return (0); 581105694Srwatson} 582105694Srwatson 583122584Srwatson/* 584122584Srwatson * MPSAFE 585122584Srwatson */ 586105988Srwatsonint 587105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 588105694Srwatson{ 589105694Srwatson char *elements, *buffer; 590105694Srwatson struct mac mac; 591105694Srwatson struct proc *tproc; 592105694Srwatson struct ucred *tcred; 593105694Srwatson int error; 594105694Srwatson 595107849Salfred error = copyin(uap->mac_p, &mac, sizeof(mac)); 596105694Srwatson if (error) 597105694Srwatson return (error); 598105694Srwatson 599105694Srwatson error = mac_check_structmac_consistent(&mac); 600105694Srwatson if (error) 601105694Srwatson return (error); 602105694Srwatson 603105694Srwatson tproc = pfind(uap->pid); 604105694Srwatson if (tproc == NULL) 605105694Srwatson return (ESRCH); 606105694Srwatson 607105694Srwatson tcred = NULL; /* Satisfy gcc. */ 608105694Srwatson error = p_cansee(td, tproc); 609105694Srwatson if (error == 0) 610105694Srwatson tcred = crhold(tproc->p_ucred); 611105694Srwatson PROC_UNLOCK(tproc); 612105694Srwatson if (error) 613105694Srwatson return (error); 614105694Srwatson 615111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 616105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 617105694Srwatson if (error) { 618105694Srwatson free(elements, M_MACTEMP); 619105694Srwatson crfree(tcred); 620105694Srwatson return (error); 621105694Srwatson } 622105694Srwatson 623111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 624122524Srwatson error = mac_externalize_cred_label(tcred->cr_label, elements, 625122159Srwatson buffer, mac.m_buflen); 626105694Srwatson if (error == 0) 627105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 628105694Srwatson 629105694Srwatson free(buffer, M_MACTEMP); 630105694Srwatson free(elements, M_MACTEMP); 631105694Srwatson crfree(tcred); 632105694Srwatson return (error); 633105694Srwatson} 634105694Srwatson 635100979Srwatson/* 636100979Srwatson * MPSAFE 637100979Srwatson */ 638100979Srwatsonint 639100894Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 640100894Srwatson{ 641105694Srwatson char *elements, *buffer; 642105694Srwatson struct mac mac; 643100979Srwatson int error; 644100894Srwatson 645105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 646105694Srwatson if (error) 647105694Srwatson return (error); 648105694Srwatson 649105694Srwatson error = mac_check_structmac_consistent(&mac); 650105694Srwatson if (error) 651105694Srwatson return (error); 652105694Srwatson 653111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 654105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 655105694Srwatson if (error) { 656105694Srwatson free(elements, M_MACTEMP); 657105694Srwatson return (error); 658105694Srwatson } 659105694Srwatson 660111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 661122524Srwatson error = mac_externalize_cred_label(td->td_ucred->cr_label, 662122159Srwatson elements, buffer, mac.m_buflen); 663100979Srwatson if (error == 0) 664105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 665100979Srwatson 666105694Srwatson free(buffer, M_MACTEMP); 667105694Srwatson free(elements, M_MACTEMP); 668100979Srwatson return (error); 669100979Srwatson} 670100979Srwatson 671100979Srwatson/* 672100979Srwatson * MPSAFE 673100979Srwatson */ 674100979Srwatsonint 675100979Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 676100979Srwatson{ 677100979Srwatson struct ucred *newcred, *oldcred; 678122524Srwatson struct label *intlabel; 679100979Srwatson struct proc *p; 680105694Srwatson struct mac mac; 681105694Srwatson char *buffer; 682100979Srwatson int error; 683100979Srwatson 684105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 685100979Srwatson if (error) 686100979Srwatson return (error); 687100979Srwatson 688105694Srwatson error = mac_check_structmac_consistent(&mac); 689100979Srwatson if (error) 690100979Srwatson return (error); 691100979Srwatson 692111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 693105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 694105694Srwatson if (error) { 695105694Srwatson free(buffer, M_MACTEMP); 696105694Srwatson return (error); 697105694Srwatson } 698105694Srwatson 699122524Srwatson intlabel = mac_cred_label_alloc(); 700122524Srwatson error = mac_internalize_cred_label(intlabel, buffer); 701105694Srwatson free(buffer, M_MACTEMP); 702122524Srwatson if (error) 703122524Srwatson goto out; 704105694Srwatson 705100979Srwatson newcred = crget(); 706100979Srwatson 707100979Srwatson p = td->td_proc; 708100979Srwatson PROC_LOCK(p); 709100979Srwatson oldcred = p->p_ucred; 710100979Srwatson 711122524Srwatson error = mac_check_cred_relabel(oldcred, intlabel); 712100979Srwatson if (error) { 713100979Srwatson PROC_UNLOCK(p); 714100979Srwatson crfree(newcred); 715105694Srwatson goto out; 716100979Srwatson } 717100979Srwatson 718100979Srwatson setsugid(p); 719100979Srwatson crcopy(newcred, oldcred); 720122524Srwatson mac_relabel_cred(newcred, intlabel); 721102136Srwatson p->p_ucred = newcred; 722100979Srwatson 723102136Srwatson /* 724102136Srwatson * Grab additional reference for use while revoking mmaps, prior 725102136Srwatson * to releasing the proc lock and sharing the cred. 726102136Srwatson */ 727102136Srwatson crhold(newcred); 728100979Srwatson PROC_UNLOCK(p); 729102136Srwatson 730105694Srwatson if (mac_enforce_vm) { 731105694Srwatson mac_cred_mmapped_drop_perms(td, newcred); 732105694Srwatson } 733102136Srwatson 734102136Srwatson crfree(newcred); /* Free revocation reference. */ 735100979Srwatson crfree(oldcred); 736105694Srwatson 737105694Srwatsonout: 738122524Srwatson mac_cred_label_free(intlabel); 739105694Srwatson return (error); 740100979Srwatson} 741100979Srwatson 742100979Srwatson/* 743100979Srwatson * MPSAFE 744100979Srwatson */ 745100979Srwatsonint 746100979Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 747100979Srwatson{ 748105694Srwatson char *elements, *buffer; 749122524Srwatson struct label *intlabel; 750100979Srwatson struct file *fp; 751105694Srwatson struct mac mac; 752100979Srwatson struct vnode *vp; 753100979Srwatson struct pipe *pipe; 754122820Srwatson struct socket *so; 755105694Srwatson short label_type; 756150914Scsjp int vfslocked, error; 757100979Srwatson 758105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 759105694Srwatson if (error) 760105694Srwatson return (error); 761100979Srwatson 762105694Srwatson error = mac_check_structmac_consistent(&mac); 763105694Srwatson if (error) 764105694Srwatson return (error); 765105694Srwatson 766111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 767105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 768105694Srwatson if (error) { 769105694Srwatson free(elements, M_MACTEMP); 770105694Srwatson return (error); 771105694Srwatson } 772105694Srwatson 773111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 774107849Salfred error = fget(td, uap->fd, &fp); 775100979Srwatson if (error) 776100979Srwatson goto out; 777100979Srwatson 778105694Srwatson label_type = fp->f_type; 779100979Srwatson switch (fp->f_type) { 780100979Srwatson case DTYPE_FIFO: 781100979Srwatson case DTYPE_VNODE: 782116678Sphk vp = fp->f_vnode; 783122524Srwatson intlabel = mac_vnode_label_alloc(); 784150914Scsjp vfslocked = VFS_LOCK_GIANT(vp->v_mount); 785100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 786122524Srwatson mac_copy_vnode_label(vp->v_label, intlabel); 787100979Srwatson VOP_UNLOCK(vp, 0, td); 788150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 789122584Srwatson error = mac_externalize_vnode_label(intlabel, elements, 790122584Srwatson buffer, mac.m_buflen); 791122584Srwatson mac_vnode_label_free(intlabel); 792122584Srwatson break; 793105694Srwatson 794100979Srwatson case DTYPE_PIPE: 795109153Sdillon pipe = fp->f_data; 796122524Srwatson intlabel = mac_pipe_label_alloc(); 797105694Srwatson PIPE_LOCK(pipe); 798125293Srwatson mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 799105694Srwatson PIPE_UNLOCK(pipe); 800122524Srwatson error = mac_externalize_pipe_label(intlabel, elements, 801122159Srwatson buffer, mac.m_buflen); 802122524Srwatson mac_pipe_label_free(intlabel); 803105694Srwatson break; 804122584Srwatson 805122820Srwatson case DTYPE_SOCKET: 806122820Srwatson so = fp->f_data; 807122820Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 808145160Srwatson NET_LOCK_GIANT(); 809145160Srwatson SOCK_LOCK(so); 810122820Srwatson mac_copy_socket_label(so->so_label, intlabel); 811145160Srwatson SOCK_UNLOCK(so); 812145160Srwatson NET_UNLOCK_GIANT(); 813122820Srwatson error = mac_externalize_socket_label(intlabel, elements, 814122820Srwatson buffer, mac.m_buflen); 815122820Srwatson mac_socket_label_free(intlabel); 816122820Srwatson break; 817122820Srwatson 818105694Srwatson default: 819122584Srwatson error = EINVAL; 820105694Srwatson } 821122584Srwatson fdrop(fp, td); 822100979Srwatson if (error == 0) 823105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 824100979Srwatson 825105694Srwatsonout: 826105694Srwatson free(buffer, M_MACTEMP); 827105694Srwatson free(elements, M_MACTEMP); 828100979Srwatson return (error); 829100979Srwatson} 830100979Srwatson 831100979Srwatson/* 832100979Srwatson * MPSAFE 833100979Srwatson */ 834100979Srwatsonint 835100979Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 836100979Srwatson{ 837105694Srwatson char *elements, *buffer; 838100979Srwatson struct nameidata nd; 839122524Srwatson struct label *intlabel; 840105694Srwatson struct mac mac; 841150914Scsjp int vfslocked, error; 842100979Srwatson 843105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 844105694Srwatson if (error) 845105694Srwatson return (error); 846105694Srwatson 847105694Srwatson error = mac_check_structmac_consistent(&mac); 848105694Srwatson if (error) 849105694Srwatson return (error); 850105694Srwatson 851111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 852105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 853105694Srwatson if (error) { 854105694Srwatson free(elements, M_MACTEMP); 855105694Srwatson return (error); 856105694Srwatson } 857105694Srwatson 858111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 859150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 860150914Scsjp uap->path_p, td); 861100979Srwatson error = namei(&nd); 862100979Srwatson if (error) 863100979Srwatson goto out; 864100979Srwatson 865122524Srwatson intlabel = mac_vnode_label_alloc(); 866150914Scsjp vfslocked = NDHASGIANT(&nd); 867122524Srwatson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 868122524Srwatson error = mac_externalize_vnode_label(intlabel, elements, buffer, 869122159Srwatson mac.m_buflen); 870105694Srwatson 871100979Srwatson NDFREE(&nd, 0); 872150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 873122524Srwatson mac_vnode_label_free(intlabel); 874105694Srwatson if (error == 0) 875105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 876105694Srwatson 877105694Srwatsonout: 878105694Srwatson free(buffer, M_MACTEMP); 879105694Srwatson free(elements, M_MACTEMP); 880105694Srwatson 881105694Srwatson return (error); 882105694Srwatson} 883105694Srwatson 884105694Srwatson/* 885105694Srwatson * MPSAFE 886105694Srwatson */ 887105694Srwatsonint 888105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 889105694Srwatson{ 890105694Srwatson char *elements, *buffer; 891105694Srwatson struct nameidata nd; 892122524Srwatson struct label *intlabel; 893105694Srwatson struct mac mac; 894150914Scsjp int vfslocked, error; 895105694Srwatson 896105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 897100979Srwatson if (error) 898105694Srwatson return (error); 899105694Srwatson 900105694Srwatson error = mac_check_structmac_consistent(&mac); 901105694Srwatson if (error) 902105694Srwatson return (error); 903105694Srwatson 904111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 905105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 906105694Srwatson if (error) { 907105694Srwatson free(elements, M_MACTEMP); 908105694Srwatson return (error); 909105694Srwatson } 910105694Srwatson 911111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 912150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 913150914Scsjp uap->path_p, td); 914105694Srwatson error = namei(&nd); 915105694Srwatson if (error) 916100979Srwatson goto out; 917100979Srwatson 918122524Srwatson intlabel = mac_vnode_label_alloc(); 919150914Scsjp vfslocked = NDHASGIANT(&nd); 920122524Srwatson mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 921122524Srwatson error = mac_externalize_vnode_label(intlabel, elements, buffer, 922122159Srwatson mac.m_buflen); 923105694Srwatson NDFREE(&nd, 0); 924150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 925122524Srwatson mac_vnode_label_free(intlabel); 926100979Srwatson 927105694Srwatson if (error == 0) 928105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 929105694Srwatson 930100979Srwatsonout: 931105694Srwatson free(buffer, M_MACTEMP); 932105694Srwatson free(elements, M_MACTEMP); 933105694Srwatson 934100979Srwatson return (error); 935100979Srwatson} 936100979Srwatson 937100979Srwatson/* 938100979Srwatson * MPSAFE 939100979Srwatson */ 940100979Srwatsonint 941100979Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 942100979Srwatson{ 943122524Srwatson struct label *intlabel; 944105694Srwatson struct pipe *pipe; 945122820Srwatson struct socket *so; 946100979Srwatson struct file *fp; 947100979Srwatson struct mount *mp; 948100979Srwatson struct vnode *vp; 949105694Srwatson struct mac mac; 950105694Srwatson char *buffer; 951150914Scsjp int error, vfslocked; 952100979Srwatson 953105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 954100979Srwatson if (error) 955105694Srwatson return (error); 956100979Srwatson 957105694Srwatson error = mac_check_structmac_consistent(&mac); 958100979Srwatson if (error) 959105694Srwatson return (error); 960100979Srwatson 961111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 962105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 963105694Srwatson if (error) { 964105694Srwatson free(buffer, M_MACTEMP); 965105694Srwatson return (error); 966105694Srwatson } 967105694Srwatson 968107849Salfred error = fget(td, uap->fd, &fp); 969100979Srwatson if (error) 970105694Srwatson goto out; 971100979Srwatson 972100979Srwatson switch (fp->f_type) { 973100979Srwatson case DTYPE_FIFO: 974100979Srwatson case DTYPE_VNODE: 975122524Srwatson intlabel = mac_vnode_label_alloc(); 976122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 977105694Srwatson if (error) { 978122524Srwatson mac_vnode_label_free(intlabel); 979105694Srwatson break; 980105694Srwatson } 981116678Sphk vp = fp->f_vnode; 982150914Scsjp vfslocked = VFS_LOCK_GIANT(vp->v_mount); 983100979Srwatson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 984105694Srwatson if (error != 0) { 985150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 986122524Srwatson mac_vnode_label_free(intlabel); 987100979Srwatson break; 988105694Srwatson } 989100979Srwatson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 990122524Srwatson error = vn_setlabel(vp, intlabel, td->td_ucred); 991100979Srwatson VOP_UNLOCK(vp, 0, td); 992100979Srwatson vn_finished_write(mp); 993150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 994122524Srwatson mac_vnode_label_free(intlabel); 995100979Srwatson break; 996105694Srwatson 997100979Srwatson case DTYPE_PIPE: 998122524Srwatson intlabel = mac_pipe_label_alloc(); 999122524Srwatson error = mac_internalize_pipe_label(intlabel, buffer); 1000105694Srwatson if (error == 0) { 1001109153Sdillon pipe = fp->f_data; 1002105694Srwatson PIPE_LOCK(pipe); 1003125293Srwatson error = mac_pipe_label_set(td->td_ucred, 1004125293Srwatson pipe->pipe_pair, intlabel); 1005105694Srwatson PIPE_UNLOCK(pipe); 1006105694Srwatson } 1007122524Srwatson mac_pipe_label_free(intlabel); 1008100979Srwatson break; 1009105694Srwatson 1010122820Srwatson case DTYPE_SOCKET: 1011122820Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 1012122820Srwatson error = mac_internalize_socket_label(intlabel, buffer); 1013122820Srwatson if (error == 0) { 1014122820Srwatson so = fp->f_data; 1015145160Srwatson NET_LOCK_GIANT(); 1016122820Srwatson error = mac_socket_label_set(td->td_ucred, so, 1017122820Srwatson intlabel); 1018145160Srwatson NET_UNLOCK_GIANT(); 1019122820Srwatson } 1020122820Srwatson mac_socket_label_free(intlabel); 1021122820Srwatson break; 1022122820Srwatson 1023100979Srwatson default: 1024100979Srwatson error = EINVAL; 1025100979Srwatson } 1026100979Srwatson fdrop(fp, td); 1027105694Srwatsonout: 1028105694Srwatson free(buffer, M_MACTEMP); 1029100979Srwatson return (error); 1030100979Srwatson} 1031100979Srwatson 1032100979Srwatson/* 1033100979Srwatson * MPSAFE 1034100979Srwatson */ 1035100979Srwatsonint 1036100979Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1037100979Srwatson{ 1038122524Srwatson struct label *intlabel; 1039100979Srwatson struct nameidata nd; 1040100979Srwatson struct mount *mp; 1041105694Srwatson struct mac mac; 1042105694Srwatson char *buffer; 1043150914Scsjp int vfslocked, error; 1044100979Srwatson 1045105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1046100979Srwatson if (error) 1047105694Srwatson return (error); 1048100979Srwatson 1049105694Srwatson error = mac_check_structmac_consistent(&mac); 1050100979Srwatson if (error) 1051105694Srwatson return (error); 1052100979Srwatson 1053111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1054105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1055105694Srwatson if (error) { 1056105694Srwatson free(buffer, M_MACTEMP); 1057105694Srwatson return (error); 1058105694Srwatson } 1059105694Srwatson 1060122524Srwatson intlabel = mac_vnode_label_alloc(); 1061122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 1062105694Srwatson free(buffer, M_MACTEMP); 1063122524Srwatson if (error) 1064122524Srwatson goto out; 1065105694Srwatson 1066150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 1067150914Scsjp uap->path_p, td); 1068100979Srwatson error = namei(&nd); 1069150914Scsjp vfslocked = NDHASGIANT(&nd); 1070105694Srwatson if (error == 0) { 1071105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1072105694Srwatson if (error == 0) 1073122524Srwatson error = vn_setlabel(nd.ni_vp, intlabel, 1074105694Srwatson td->td_ucred); 1075105694Srwatson vn_finished_write(mp); 1076105694Srwatson } 1077105694Srwatson 1078105694Srwatson NDFREE(&nd, 0); 1079150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1080122524Srwatsonout: 1081122524Srwatson mac_vnode_label_free(intlabel); 1082105694Srwatson return (error); 1083105694Srwatson} 1084105694Srwatson 1085105694Srwatson/* 1086105694Srwatson * MPSAFE 1087105694Srwatson */ 1088105694Srwatsonint 1089105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1090105694Srwatson{ 1091122524Srwatson struct label *intlabel; 1092105694Srwatson struct nameidata nd; 1093105694Srwatson struct mount *mp; 1094105694Srwatson struct mac mac; 1095105694Srwatson char *buffer; 1096150914Scsjp int vfslocked, error; 1097105694Srwatson 1098105694Srwatson error = copyin(uap->mac_p, &mac, sizeof(mac)); 1099100979Srwatson if (error) 1100105694Srwatson return (error); 1101105694Srwatson 1102105694Srwatson error = mac_check_structmac_consistent(&mac); 1103100979Srwatson if (error) 1104105694Srwatson return (error); 1105100979Srwatson 1106111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1107105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1108105694Srwatson if (error) { 1109105694Srwatson free(buffer, M_MACTEMP); 1110105694Srwatson return (error); 1111105694Srwatson } 1112105694Srwatson 1113122524Srwatson intlabel = mac_vnode_label_alloc(); 1114122524Srwatson error = mac_internalize_vnode_label(intlabel, buffer); 1115105694Srwatson free(buffer, M_MACTEMP); 1116122524Srwatson if (error) 1117122524Srwatson goto out; 1118105694Srwatson 1119150914Scsjp NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 1120150914Scsjp uap->path_p, td); 1121105694Srwatson error = namei(&nd); 1122150914Scsjp vfslocked = NDHASGIANT(&nd); 1123105694Srwatson if (error == 0) { 1124105694Srwatson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1125105694Srwatson if (error == 0) 1126122524Srwatson error = vn_setlabel(nd.ni_vp, intlabel, 1127105694Srwatson td->td_ucred); 1128105694Srwatson vn_finished_write(mp); 1129105694Srwatson } 1130105694Srwatson 1131100979Srwatson NDFREE(&nd, 0); 1132150914Scsjp VFS_UNLOCK_GIANT(vfslocked); 1133122524Srwatsonout: 1134122524Srwatson mac_vnode_label_free(intlabel); 1135100979Srwatson return (error); 1136100979Srwatson} 1137100979Srwatson 1138105694Srwatson/* 1139105694Srwatson * MPSAFE 1140105694Srwatson */ 1141102123Srwatsonint 1142102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1143102123Srwatson{ 1144102123Srwatson struct mac_policy_conf *mpc; 1145102123Srwatson char target[MAC_MAX_POLICY_NAME]; 1146114806Srwatson int entrycount, error; 1147102123Srwatson 1148107849Salfred error = copyinstr(uap->policy, target, sizeof(target), NULL); 1149102123Srwatson if (error) 1150102123Srwatson return (error); 1151102123Srwatson 1152102123Srwatson error = ENOSYS; 1153119494Srwatson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1154102123Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1155102123Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1156102123Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1157107849Salfred uap->call, uap->arg); 1158102123Srwatson goto out; 1159102123Srwatson } 1160102123Srwatson } 1161102123Srwatson 1162114806Srwatson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1163114806Srwatson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1164114806Srwatson if (strcmp(mpc->mpc_name, target) == 0 && 1165114806Srwatson mpc->mpc_ops->mpo_syscall != NULL) { 1166114806Srwatson error = mpc->mpc_ops->mpo_syscall(td, 1167114806Srwatson uap->call, uap->arg); 1168114806Srwatson break; 1169114806Srwatson } 1170114806Srwatson } 1171114806Srwatson mac_policy_list_unbusy(); 1172114806Srwatson } 1173102123Srwatsonout: 1174102123Srwatson return (error); 1175102123Srwatson} 1176102123Srwatson 1177100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1178100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1179100979Srwatson 1180100979Srwatson#else /* !MAC */ 1181100979Srwatson 1182100979Srwatsonint 1183105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1184105694Srwatson{ 1185105694Srwatson 1186105694Srwatson return (ENOSYS); 1187105694Srwatson} 1188105694Srwatson 1189105694Srwatsonint 1190100979Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1191100979Srwatson{ 1192100979Srwatson 1193100894Srwatson return (ENOSYS); 1194100894Srwatson} 1195100894Srwatson 1196100894Srwatsonint 1197100894Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1198100894Srwatson{ 1199100894Srwatson 1200100894Srwatson return (ENOSYS); 1201100894Srwatson} 1202100894Srwatson 1203100894Srwatsonint 1204100894Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1205100894Srwatson{ 1206100894Srwatson 1207100894Srwatson return (ENOSYS); 1208100894Srwatson} 1209100894Srwatson 1210100894Srwatsonint 1211100894Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1212100894Srwatson{ 1213100894Srwatson 1214100894Srwatson return (ENOSYS); 1215100894Srwatson} 1216100894Srwatson 1217100894Srwatsonint 1218105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1219105694Srwatson{ 1220105694Srwatson 1221105694Srwatson return (ENOSYS); 1222105694Srwatson} 1223105694Srwatson 1224105694Srwatsonint 1225100894Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1226100894Srwatson{ 1227100894Srwatson 1228100894Srwatson return (ENOSYS); 1229100894Srwatson} 1230100894Srwatson 1231100894Srwatsonint 1232100894Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1233100894Srwatson{ 1234100894Srwatson 1235100894Srwatson return (ENOSYS); 1236100894Srwatson} 1237100979Srwatson 1238102123Srwatsonint 1239105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1240105694Srwatson{ 1241105694Srwatson 1242105694Srwatson return (ENOSYS); 1243105694Srwatson} 1244105694Srwatson 1245105694Srwatsonint 1246102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap) 1247102123Srwatson{ 1248102123Srwatson 1249102123Srwatson return (ENOSYS); 1250102123Srwatson} 1251102123Srwatson 1252128901Srwatson#endif /* !MAC */ 1253