mac_syscalls.c revision 121372
1/*- 2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 3 * Copyright (c) 2001 Ilmar S. Habibulin 4 * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc. 5 * All rights reserved. 6 * 7 * This software was developed by Robert Watson and Ilmar Habibulin for the 8 * TrustedBSD Project. 9 * 10 * This software was developed for the FreeBSD Project in part by Network 11 * Associates Laboratories, the Security Research Division of Network 12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 13 * as part of the DARPA CHATS research program. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37/* 38 * Framework for extensible kernel access control. Kernel and userland 39 * interface to the framework, policy registration and composition. 40 */ 41 42#include <sys/cdefs.h> 43__FBSDID("$FreeBSD: head/sys/security/mac/mac_syscalls.c 121372 2003-10-22 20:47:41Z rwatson $"); 44 45#include "opt_mac.h" 46#include "opt_devfs.h" 47 48#include <sys/param.h> 49#include <sys/condvar.h> 50#include <sys/extattr.h> 51#include <sys/imgact.h> 52#include <sys/kernel.h> 53#include <sys/lock.h> 54#include <sys/malloc.h> 55#include <sys/mutex.h> 56#include <sys/mac.h> 57#include <sys/module.h> 58#include <sys/proc.h> 59#include <sys/sbuf.h> 60#include <sys/systm.h> 61#include <sys/sysproto.h> 62#include <sys/sysent.h> 63#include <sys/vnode.h> 64#include <sys/mount.h> 65#include <sys/file.h> 66#include <sys/namei.h> 67#include <sys/socket.h> 68#include <sys/pipe.h> 69#include <sys/socketvar.h> 70#include <sys/sysctl.h> 71 72#include <vm/vm.h> 73#include <vm/pmap.h> 74#include <vm/vm_map.h> 75#include <vm/vm_object.h> 76 77#include <sys/mac_policy.h> 78 79#include <fs/devfs/devfs.h> 80 81#include <net/bpfdesc.h> 82#include <net/if.h> 83#include <net/if_var.h> 84 85#include <netinet/in.h> 86#include <netinet/ip_var.h> 87 88#ifdef MAC 89 90/* 91 * Declare that the kernel provides MAC support, version 1. This permits 92 * modules to refuse to be loaded if the necessary support isn't present, 93 * even if it's pre-boot. 94 */ 95MODULE_VERSION(kernel_mac_support, 1); 96 97SYSCTL_DECL(_security); 98 99SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 100 "TrustedBSD MAC policy controls"); 101 102#if MAC_MAX_SLOTS > 32 103#error "MAC_MAX_SLOTS too large" 104#endif 105 106static unsigned int mac_max_slots = MAC_MAX_SLOTS; 107static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 108SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 109 &mac_max_slots, 0, ""); 110 111/* 112 * Has the kernel started generating labeled objects yet? All read/write 113 * access to this variable is serialized during the boot process. Following 114 * the end of serialization, we don't update this flag; no locking. 115 */ 116int mac_late = 0; 117 118/* 119 * Flag to indicate whether or not we should allocate label storage for 120 * new mbufs. Since most dynamic policies we currently work with don't 121 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 122 * unless specifically notified of interest. One result of this is 123 * that if a dynamically loaded policy requests mbuf labels, it must 124 * be able to deal with a NULL label being returned on any mbufs that 125 * were already in flight when the policy was loaded. Since the policy 126 * already has to deal with uninitialized labels, this probably won't 127 * be a problem. Note: currently no locking. Will this be a problem? 128 */ 129#ifndef MAC_ALWAYS_LABEL_MBUF 130int mac_labelmbufs = 0; 131#endif 132 133static int mac_enforce_fs = 1; 134SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 135 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 136TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 137 138static int mac_enforce_kld = 1; 139SYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW, 140 &mac_enforce_kld, 0, "Enforce MAC policy on kld operations"); 141TUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld); 142 143static int mac_enforce_network = 1; 144SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 145 &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 146TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 147 148static int mac_enforce_pipe = 1; 149SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 150 &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 151TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 152 153static int mac_enforce_process = 1; 154SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 155 &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 156TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 157 158static int mac_enforce_socket = 1; 159SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 160 &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 161TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 162 163static int mac_enforce_system = 1; 164SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW, 165 &mac_enforce_system, 0, "Enforce MAC policy on system operations"); 166TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system); 167 168static int mac_enforce_vm = 1; 169SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 170 &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 171TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 172 173static int mac_mmap_revocation = 1; 174SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 175 &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 176 "relabel"); 177static int mac_mmap_revocation_via_cow = 0; 178SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 179 &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 180 "copy-on-write semantics, or by removing all write access"); 181 182#ifdef MAC_DEBUG 183SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 184 "TrustedBSD MAC debug info"); 185 186static int mac_debug_label_fallback = 0; 187SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 188 &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 189 "when label is corrupted."); 190TUNABLE_INT("security.mac.debug_label_fallback", 191 &mac_debug_label_fallback); 192 193SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 194 "TrustedBSD MAC object counters"); 195 196static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 197 nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 198 nmacipqs, nmacpipes, nmacprocs; 199 200#define MAC_DEBUG_COUNTER_INC(x) atomic_add_int(x, 1); 201#define MAC_DEBUG_COUNTER_DEC(x) atomic_subtract_int(x, 1); 202 203SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 204 &nmacmbufs, 0, "number of mbufs in use"); 205SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 206 &nmaccreds, 0, "number of ucreds in use"); 207SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 208 &nmacifnets, 0, "number of ifnets in use"); 209SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 210 &nmacipqs, 0, "number of ipqs in use"); 211SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 212 &nmacbpfdescs, 0, "number of bpfdescs in use"); 213SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 214 &nmacsockets, 0, "number of sockets in use"); 215SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 216 &nmacpipes, 0, "number of pipes in use"); 217SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD, 218 &nmacprocs, 0, "number of procs in use"); 219SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 220 &nmacmounts, 0, "number of mounts in use"); 221SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 222 &nmactemp, 0, "number of temporary labels in use"); 223SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 224 &nmacvnodes, 0, "number of vnodes in use"); 225SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 226 &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 227#else 228#define MAC_DEBUG_COUNTER_INC(x) 229#define MAC_DEBUG_COUNTER_DEC(x) 230#endif 231 232static int mac_policy_register(struct mac_policy_conf *mpc); 233static int mac_policy_unregister(struct mac_policy_conf *mpc); 234 235static void mac_check_vnode_mmap_downgrade(struct ucred *cred, 236 struct vnode *vp, int *prot); 237static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 238 struct ucred *cred, struct vm_map *map); 239 240static void mac_destroy_socket_label(struct label *label); 241 242static int mac_setlabel_vnode_extattr(struct ucred *cred, 243 struct vnode *vp, struct label *intlabel); 244 245MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 246MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 247 248/* 249 * mac_static_policy_list holds a list of policy modules that are not 250 * loaded while the system is "live", and cannot be unloaded. These 251 * policies can be invoked without holding the busy count. 252 * 253 * mac_policy_list stores the list of dynamic policies. A busy count is 254 * maintained for the list, stored in mac_policy_busy. The busy count 255 * is protected by mac_policy_mtx; the list may be modified only 256 * while the busy count is 0, requiring that the lock be held to 257 * prevent new references to the list from being acquired. For almost 258 * all operations, incrementing the busy count is sufficient to 259 * guarantee consistency, as the list cannot be modified while the 260 * busy count is elevated. For a few special operations involving a 261 * change to the list of active policies, the mtx itself must be held. 262 * A condition variable, mac_policy_cv, is used to signal potential 263 * exclusive consumers that they should try to acquire the lock if a 264 * first attempt at exclusive access fails. 265 */ 266static struct mtx mac_policy_mtx; 267static struct cv mac_policy_cv; 268static int mac_policy_count; 269struct mac_policy_list_head mac_policy_list; 270struct mac_policy_list_head mac_static_policy_list; 271 272/* 273 * We manually invoke WITNESS_WARN() to allow Witness to generate 274 * warnings even if we don't end up ever triggering the wait at 275 * run-time. The consumer of the exclusive interface must not hold 276 * any locks (other than potentially Giant) since we may sleep for 277 * long (potentially indefinite) periods of time waiting for the 278 * framework to become quiescent so that a policy list change may 279 * be made. 280 */ 281void 282mac_policy_grab_exclusive(void) 283{ 284 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 285 "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 286 mtx_lock(&mac_policy_mtx); 287 while (mac_policy_count != 0) 288 cv_wait(&mac_policy_cv, &mac_policy_mtx); 289} 290 291void 292mac_policy_assert_exclusive(void) 293{ 294 mtx_assert(&mac_policy_mtx, MA_OWNED); 295 KASSERT(mac_policy_count == 0, 296 ("mac_policy_assert_exclusive(): not exclusive")); 297} 298 299void 300mac_policy_release_exclusive(void) 301{ 302 303 KASSERT(mac_policy_count == 0, 304 ("mac_policy_release_exclusive(): not exclusive")); 305 mtx_unlock(&mac_policy_mtx); 306 cv_signal(&mac_policy_cv); 307} 308 309void 310mac_policy_list_busy(void) 311{ 312 mtx_lock(&mac_policy_mtx); 313 mac_policy_count++; 314 mtx_unlock(&mac_policy_mtx); 315} 316 317int 318mac_policy_list_conditional_busy(void) 319{ 320 int ret; 321 322 mtx_lock(&mac_policy_mtx); 323 if (!LIST_EMPTY(&mac_policy_list)) { 324 mac_policy_count++; 325 ret = 1; 326 } else 327 ret = 0; 328 mtx_unlock(&mac_policy_mtx); 329 return (ret); 330} 331 332void 333mac_policy_list_unbusy(void) 334{ 335 mtx_lock(&mac_policy_mtx); 336 mac_policy_count--; 337 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 338 if (mac_policy_count == 0) 339 cv_signal(&mac_policy_cv); 340 mtx_unlock(&mac_policy_mtx); 341} 342 343/* 344 * MAC_CHECK performs the designated check by walking the policy 345 * module list and checking with each as to how it feels about the 346 * request. Note that it returns its value via 'error' in the scope 347 * of the caller. 348 */ 349#define MAC_CHECK(check, args...) do { \ 350 struct mac_policy_conf *mpc; \ 351 int entrycount; \ 352 \ 353 error = 0; \ 354 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 355 if (mpc->mpc_ops->mpo_ ## check != NULL) \ 356 error = mac_error_select( \ 357 mpc->mpc_ops->mpo_ ## check (args), \ 358 error); \ 359 } \ 360 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 361 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 362 if (mpc->mpc_ops->mpo_ ## check != NULL) \ 363 error = mac_error_select( \ 364 mpc->mpc_ops->mpo_ ## check (args), \ 365 error); \ 366 } \ 367 mac_policy_list_unbusy(); \ 368 } \ 369} while (0) 370 371/* 372 * MAC_BOOLEAN performs the designated boolean composition by walking 373 * the module list, invoking each instance of the operation, and 374 * combining the results using the passed C operator. Note that it 375 * returns its value via 'result' in the scope of the caller, which 376 * should be initialized by the caller in a meaningful way to get 377 * a meaningful result. 378 */ 379#define MAC_BOOLEAN(operation, composition, args...) do { \ 380 struct mac_policy_conf *mpc; \ 381 int entrycount; \ 382 \ 383 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 384 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 385 result = result composition \ 386 mpc->mpc_ops->mpo_ ## operation (args); \ 387 } \ 388 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 389 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 390 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 391 result = result composition \ 392 mpc->mpc_ops->mpo_ ## operation \ 393 (args); \ 394 } \ 395 mac_policy_list_unbusy(); \ 396 } \ 397} while (0) 398 399#define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \ 400 outbuflen) do { \ 401 int claimed, first, ignorenotfound, savedlen; \ 402 char *element_name, *element_temp; \ 403 struct sbuf sb; \ 404 \ 405 error = 0; \ 406 first = 1; \ 407 sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN); \ 408 element_temp = elementlist; \ 409 while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 410 if (element_name[0] == '?') { \ 411 element_name++; \ 412 ignorenotfound = 1; \ 413 } else \ 414 ignorenotfound = 0; \ 415 savedlen = sbuf_len(&sb); \ 416 if (first) { \ 417 error = sbuf_printf(&sb, "%s/", element_name); \ 418 first = 0; \ 419 } else \ 420 error = sbuf_printf(&sb, ",%s/", element_name); \ 421 if (error == -1) { \ 422 error = EINVAL; /* XXX: E2BIG? */ \ 423 break; \ 424 } \ 425 claimed = 0; \ 426 MAC_CHECK(externalize_ ## type, label, element_name, \ 427 &sb, &claimed); \ 428 if (error) \ 429 break; \ 430 if (claimed == 0 && ignorenotfound) { \ 431 /* Revert last label name. */ \ 432 sbuf_setpos(&sb, savedlen); \ 433 } else if (claimed != 1) { \ 434 error = EINVAL; /* XXX: ENOLABEL? */ \ 435 break; \ 436 } \ 437 } \ 438 sbuf_finish(&sb); \ 439} while (0) 440 441#define MAC_INTERNALIZE(type, label, instring) do { \ 442 char *element, *element_name, *element_data; \ 443 int claimed; \ 444 \ 445 error = 0; \ 446 element = instring; \ 447 while ((element_name = strsep(&element, ",")) != NULL) { \ 448 element_data = element_name; \ 449 element_name = strsep(&element_data, "/"); \ 450 if (element_data == NULL) { \ 451 error = EINVAL; \ 452 break; \ 453 } \ 454 claimed = 0; \ 455 MAC_CHECK(internalize_ ## type, label, element_name, \ 456 element_data, &claimed); \ 457 if (error) \ 458 break; \ 459 if (claimed != 1) { \ 460 /* XXXMAC: Another error here? */ \ 461 error = EINVAL; \ 462 break; \ 463 } \ 464 } \ 465} while (0) 466 467/* 468 * MAC_PERFORM performs the designated operation by walking the policy 469 * module list and invoking that operation for each policy. 470 */ 471#define MAC_PERFORM(operation, args...) do { \ 472 struct mac_policy_conf *mpc; \ 473 int entrycount; \ 474 \ 475 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 476 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 477 mpc->mpc_ops->mpo_ ## operation (args); \ 478 } \ 479 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 480 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 481 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 482 mpc->mpc_ops->mpo_ ## operation (args); \ 483 } \ 484 mac_policy_list_unbusy(); \ 485 } \ 486} while (0) 487 488/* 489 * Initialize the MAC subsystem, including appropriate SMP locks. 490 */ 491static void 492mac_init(void) 493{ 494 495 LIST_INIT(&mac_static_policy_list); 496 LIST_INIT(&mac_policy_list); 497 498 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 499 cv_init(&mac_policy_cv, "mac_policy_cv"); 500} 501 502/* 503 * For the purposes of modules that want to know if they were loaded 504 * "early", set the mac_late flag once we've processed modules either 505 * linked into the kernel, or loaded before the kernel startup. 506 */ 507static void 508mac_late_init(void) 509{ 510 511 mac_late = 1; 512} 513 514/* 515 * After the policy list has changed, walk the list to update any global 516 * flags. Currently, we support only one flag, and it's conditionally 517 * defined; as a result, the entire function is conditional. Eventually, 518 * the #else case might also iterate across the policies. 519 */ 520static void 521mac_policy_updateflags(void) 522{ 523#ifndef MAC_ALWAYS_LABEL_MBUF 524 struct mac_policy_conf *tmpc; 525 int labelmbufs; 526 527 mac_policy_assert_exclusive(); 528 529 labelmbufs = 0; 530 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 531 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 532 labelmbufs++; 533 } 534 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 535 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 536 labelmbufs++; 537 } 538 mac_labelmbufs = (labelmbufs != 0); 539#endif 540} 541 542/* 543 * Allow MAC policy modules to register during boot, etc. 544 */ 545int 546mac_policy_modevent(module_t mod, int type, void *data) 547{ 548 struct mac_policy_conf *mpc; 549 int error; 550 551 error = 0; 552 mpc = (struct mac_policy_conf *) data; 553 554 switch (type) { 555 case MOD_LOAD: 556 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 557 mac_late) { 558 printf("mac_policy_modevent: can't load %s policy " 559 "after booting\n", mpc->mpc_name); 560 error = EBUSY; 561 break; 562 } 563 error = mac_policy_register(mpc); 564 break; 565 case MOD_UNLOAD: 566 /* Don't unregister the module if it was never registered. */ 567 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 568 != 0) 569 error = mac_policy_unregister(mpc); 570 else 571 error = 0; 572 break; 573 default: 574 break; 575 } 576 577 return (error); 578} 579 580static int 581mac_policy_register(struct mac_policy_conf *mpc) 582{ 583 struct mac_policy_conf *tmpc; 584 int error, slot, static_entry; 585 586 error = 0; 587 588 /* 589 * We don't technically need exclusive access while !mac_late, 590 * but hold it for assertion consistency. 591 */ 592 mac_policy_grab_exclusive(); 593 594 /* 595 * If the module can potentially be unloaded, or we're loading 596 * late, we have to stick it in the non-static list and pay 597 * an extra performance overhead. Otherwise, we can pay a 598 * light locking cost and stick it in the static list. 599 */ 600 static_entry = (!mac_late && 601 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 602 603 if (static_entry) { 604 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 605 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 606 error = EEXIST; 607 goto out; 608 } 609 } 610 } else { 611 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 612 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 613 error = EEXIST; 614 goto out; 615 } 616 } 617 } 618 if (mpc->mpc_field_off != NULL) { 619 slot = ffs(mac_slot_offsets_free); 620 if (slot == 0) { 621 error = ENOMEM; 622 goto out; 623 } 624 slot--; 625 mac_slot_offsets_free &= ~(1 << slot); 626 *mpc->mpc_field_off = slot; 627 } 628 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 629 630 /* 631 * If we're loading a MAC module after the framework has 632 * initialized, it has to go into the dynamic list. If 633 * we're loading it before we've finished initializing, 634 * it can go into the static list with weaker locker 635 * requirements. 636 */ 637 if (static_entry) 638 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 639 else 640 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 641 642 /* Per-policy initialization. */ 643 if (mpc->mpc_ops->mpo_init != NULL) 644 (*(mpc->mpc_ops->mpo_init))(mpc); 645 mac_policy_updateflags(); 646 647 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 648 mpc->mpc_name); 649 650out: 651 mac_policy_release_exclusive(); 652 return (error); 653} 654 655static int 656mac_policy_unregister(struct mac_policy_conf *mpc) 657{ 658 659 /* 660 * If we fail the load, we may get a request to unload. Check 661 * to see if we did the run-time registration, and if not, 662 * silently succeed. 663 */ 664 mac_policy_grab_exclusive(); 665 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 666 mac_policy_release_exclusive(); 667 return (0); 668 } 669#if 0 670 /* 671 * Don't allow unloading modules with private data. 672 */ 673 if (mpc->mpc_field_off != NULL) { 674 MAC_POLICY_LIST_UNLOCK(); 675 return (EBUSY); 676 } 677#endif 678 /* 679 * Only allow the unload to proceed if the module is unloadable 680 * by its own definition. 681 */ 682 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 683 mac_policy_release_exclusive(); 684 return (EBUSY); 685 } 686 if (mpc->mpc_ops->mpo_destroy != NULL) 687 (*(mpc->mpc_ops->mpo_destroy))(mpc); 688 689 LIST_REMOVE(mpc, mpc_list); 690 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 691 mac_policy_updateflags(); 692 693 mac_policy_release_exclusive(); 694 695 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 696 mpc->mpc_name); 697 698 return (0); 699} 700 701/* 702 * Define an error value precedence, and given two arguments, selects the 703 * value with the higher precedence. 704 */ 705int 706mac_error_select(int error1, int error2) 707{ 708 709 /* Certain decision-making errors take top priority. */ 710 if (error1 == EDEADLK || error2 == EDEADLK) 711 return (EDEADLK); 712 713 /* Invalid arguments should be reported where possible. */ 714 if (error1 == EINVAL || error2 == EINVAL) 715 return (EINVAL); 716 717 /* Precedence goes to "visibility", with both process and file. */ 718 if (error1 == ESRCH || error2 == ESRCH) 719 return (ESRCH); 720 721 if (error1 == ENOENT || error2 == ENOENT) 722 return (ENOENT); 723 724 /* Precedence goes to DAC/MAC protections. */ 725 if (error1 == EACCES || error2 == EACCES) 726 return (EACCES); 727 728 /* Precedence goes to privilege. */ 729 if (error1 == EPERM || error2 == EPERM) 730 return (EPERM); 731 732 /* Precedence goes to error over success; otherwise, arbitrary. */ 733 if (error1 != 0) 734 return (error1); 735 return (error2); 736} 737 738static struct label * 739mbuf_to_label(struct mbuf *mbuf) 740{ 741 struct m_tag *tag; 742 struct label *label; 743 744 tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL); 745 label = (struct label *)(tag+1); 746 747 return (label); 748} 749 750static void 751mac_init_label(struct label *label) 752{ 753 754 bzero(label, sizeof(*label)); 755 label->l_flags = MAC_FLAG_INITIALIZED; 756} 757 758static void 759mac_destroy_label(struct label *label) 760{ 761 762 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 763 ("destroying uninitialized label")); 764 765 bzero(label, sizeof(*label)); 766 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 767} 768 769void 770mac_init_bpfdesc(struct bpf_d *bpf_d) 771{ 772 773 mac_init_label(&bpf_d->bd_label); 774 MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 775 MAC_DEBUG_COUNTER_INC(&nmacbpfdescs); 776} 777 778static void 779mac_init_cred_label(struct label *label) 780{ 781 782 mac_init_label(label); 783 MAC_PERFORM(init_cred_label, label); 784 MAC_DEBUG_COUNTER_INC(&nmaccreds); 785} 786 787void 788mac_init_cred(struct ucred *cred) 789{ 790 791 mac_init_cred_label(&cred->cr_label); 792} 793 794void 795mac_init_devfsdirent(struct devfs_dirent *de) 796{ 797 798 mac_init_label(&de->de_label); 799 MAC_PERFORM(init_devfsdirent_label, &de->de_label); 800 MAC_DEBUG_COUNTER_INC(&nmacdevfsdirents); 801} 802 803static void 804mac_init_ifnet_label(struct label *label) 805{ 806 807 mac_init_label(label); 808 MAC_PERFORM(init_ifnet_label, label); 809 MAC_DEBUG_COUNTER_INC(&nmacifnets); 810} 811 812void 813mac_init_ifnet(struct ifnet *ifp) 814{ 815 816 mac_init_ifnet_label(&ifp->if_label); 817} 818 819int 820mac_init_ipq(struct ipq *ipq, int flag) 821{ 822 int error; 823 824 mac_init_label(&ipq->ipq_label); 825 826 MAC_CHECK(init_ipq_label, &ipq->ipq_label, flag); 827 if (error) { 828 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 829 mac_destroy_label(&ipq->ipq_label); 830 } else { 831 MAC_DEBUG_COUNTER_INC(&nmacipqs); 832 } 833 return (error); 834} 835 836int 837mac_init_mbuf_tag(struct m_tag *tag, int flag) 838{ 839 struct label *label; 840 int error; 841 842 label = (struct label *) (tag + 1); 843 mac_init_label(label); 844 845 MAC_CHECK(init_mbuf_label, label, flag); 846 if (error) { 847 MAC_PERFORM(destroy_mbuf_label, label); 848 mac_destroy_label(label); 849 } else { 850 MAC_DEBUG_COUNTER_INC(&nmacmbufs); 851 } 852 return (error); 853} 854 855int 856mac_init_mbuf(struct mbuf *m, int flag) 857{ 858 struct m_tag *tag; 859 int error; 860 861 M_ASSERTPKTHDR(m); 862 863#ifndef MAC_ALWAYS_LABEL_MBUF 864 /* 865 * If conditionally allocating mbuf labels, don't allocate unless 866 * they are required. 867 */ 868 if (!mac_labelmbufs) 869 return (0); 870#endif 871 tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label), 872 flag); 873 if (tag == NULL) 874 return (ENOMEM); 875 error = mac_init_mbuf_tag(tag, flag); 876 if (error) { 877 m_tag_free(tag); 878 return (error); 879 } 880 m_tag_prepend(m, tag); 881 return (0); 882} 883 884void 885mac_init_mount(struct mount *mp) 886{ 887 888 mac_init_label(&mp->mnt_mntlabel); 889 mac_init_label(&mp->mnt_fslabel); 890 MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 891 MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 892 MAC_DEBUG_COUNTER_INC(&nmacmounts); 893} 894 895static void 896mac_init_pipe_label(struct label *label) 897{ 898 899 mac_init_label(label); 900 MAC_PERFORM(init_pipe_label, label); 901 MAC_DEBUG_COUNTER_INC(&nmacpipes); 902} 903 904void 905mac_init_pipe(struct pipe *pipe) 906{ 907 struct label *label; 908 909 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 910 pipe->pipe_label = label; 911 pipe->pipe_peer->pipe_label = label; 912 mac_init_pipe_label(label); 913} 914 915void 916mac_init_proc(struct proc *p) 917{ 918 919 mac_init_label(&p->p_label); 920 MAC_PERFORM(init_proc_label, &p->p_label); 921 MAC_DEBUG_COUNTER_INC(&nmacprocs); 922} 923 924static int 925mac_init_socket_label(struct label *label, int flag) 926{ 927 int error; 928 929 mac_init_label(label); 930 931 MAC_CHECK(init_socket_label, label, flag); 932 if (error) { 933 MAC_PERFORM(destroy_socket_label, label); 934 mac_destroy_label(label); 935 } else { 936 MAC_DEBUG_COUNTER_INC(&nmacsockets); 937 } 938 939 return (error); 940} 941 942static int 943mac_init_socket_peer_label(struct label *label, int flag) 944{ 945 int error; 946 947 mac_init_label(label); 948 949 MAC_CHECK(init_socket_peer_label, label, flag); 950 if (error) { 951 MAC_PERFORM(destroy_socket_label, label); 952 mac_destroy_label(label); 953 } 954 955 return (error); 956} 957 958int 959mac_init_socket(struct socket *socket, int flag) 960{ 961 int error; 962 963 error = mac_init_socket_label(&socket->so_label, flag); 964 if (error) 965 return (error); 966 967 error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 968 if (error) 969 mac_destroy_socket_label(&socket->so_label); 970 971 return (error); 972} 973 974void 975mac_init_vnode_label(struct label *label) 976{ 977 978 mac_init_label(label); 979 MAC_PERFORM(init_vnode_label, label); 980 MAC_DEBUG_COUNTER_INC(&nmacvnodes); 981} 982 983void 984mac_init_vnode(struct vnode *vp) 985{ 986 987 mac_init_vnode_label(&vp->v_label); 988} 989 990void 991mac_destroy_bpfdesc(struct bpf_d *bpf_d) 992{ 993 994 MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 995 mac_destroy_label(&bpf_d->bd_label); 996 MAC_DEBUG_COUNTER_DEC(&nmacbpfdescs); 997} 998 999static void 1000mac_destroy_cred_label(struct label *label) 1001{ 1002 1003 MAC_PERFORM(destroy_cred_label, label); 1004 mac_destroy_label(label); 1005 MAC_DEBUG_COUNTER_DEC(&nmaccreds); 1006} 1007 1008void 1009mac_destroy_cred(struct ucred *cred) 1010{ 1011 1012 mac_destroy_cred_label(&cred->cr_label); 1013} 1014 1015void 1016mac_destroy_devfsdirent(struct devfs_dirent *de) 1017{ 1018 1019 MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 1020 mac_destroy_label(&de->de_label); 1021 MAC_DEBUG_COUNTER_DEC(&nmacdevfsdirents); 1022} 1023 1024static void 1025mac_destroy_ifnet_label(struct label *label) 1026{ 1027 1028 MAC_PERFORM(destroy_ifnet_label, label); 1029 mac_destroy_label(label); 1030 MAC_DEBUG_COUNTER_DEC(&nmacifnets); 1031} 1032 1033void 1034mac_destroy_ifnet(struct ifnet *ifp) 1035{ 1036 1037 mac_destroy_ifnet_label(&ifp->if_label); 1038} 1039 1040void 1041mac_destroy_ipq(struct ipq *ipq) 1042{ 1043 1044 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 1045 mac_destroy_label(&ipq->ipq_label); 1046 MAC_DEBUG_COUNTER_DEC(&nmacipqs); 1047} 1048 1049void 1050mac_destroy_mbuf_tag(struct m_tag *tag) 1051{ 1052 struct label *label; 1053 1054 label = (struct label *)(tag+1); 1055 1056 MAC_PERFORM(destroy_mbuf_label, label); 1057 mac_destroy_label(label); 1058 MAC_DEBUG_COUNTER_DEC(&nmacmbufs); 1059} 1060 1061void 1062mac_destroy_mount(struct mount *mp) 1063{ 1064 1065 MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 1066 MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 1067 mac_destroy_label(&mp->mnt_fslabel); 1068 mac_destroy_label(&mp->mnt_mntlabel); 1069 MAC_DEBUG_COUNTER_DEC(&nmacmounts); 1070} 1071 1072static void 1073mac_destroy_pipe_label(struct label *label) 1074{ 1075 1076 MAC_PERFORM(destroy_pipe_label, label); 1077 mac_destroy_label(label); 1078 MAC_DEBUG_COUNTER_DEC(&nmacpipes); 1079} 1080 1081void 1082mac_destroy_pipe(struct pipe *pipe) 1083{ 1084 1085 mac_destroy_pipe_label(pipe->pipe_label); 1086 free(pipe->pipe_label, M_MACPIPELABEL); 1087} 1088 1089void 1090mac_destroy_proc(struct proc *p) 1091{ 1092 1093 MAC_PERFORM(destroy_proc_label, &p->p_label); 1094 mac_destroy_label(&p->p_label); 1095 MAC_DEBUG_COUNTER_DEC(&nmacprocs); 1096} 1097 1098static void 1099mac_destroy_socket_label(struct label *label) 1100{ 1101 1102 MAC_PERFORM(destroy_socket_label, label); 1103 mac_destroy_label(label); 1104 MAC_DEBUG_COUNTER_DEC(&nmacsockets); 1105} 1106 1107static void 1108mac_destroy_socket_peer_label(struct label *label) 1109{ 1110 1111 MAC_PERFORM(destroy_socket_peer_label, label); 1112 mac_destroy_label(label); 1113} 1114 1115void 1116mac_destroy_socket(struct socket *socket) 1117{ 1118 1119 mac_destroy_socket_label(&socket->so_label); 1120 mac_destroy_socket_peer_label(&socket->so_peerlabel); 1121} 1122 1123void 1124mac_destroy_vnode_label(struct label *label) 1125{ 1126 1127 MAC_PERFORM(destroy_vnode_label, label); 1128 mac_destroy_label(label); 1129 MAC_DEBUG_COUNTER_DEC(&nmacvnodes); 1130} 1131 1132void 1133mac_destroy_vnode(struct vnode *vp) 1134{ 1135 1136 mac_destroy_vnode_label(&vp->v_label); 1137} 1138 1139void 1140mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest) 1141{ 1142 struct label *src_label, *dest_label; 1143 1144 src_label = (struct label *)(src+1); 1145 dest_label = (struct label *)(dest+1); 1146 1147 /* 1148 * mac_init_mbuf_tag() is called on the target tag in 1149 * m_tag_copy(), so we don't need to call it here. 1150 */ 1151 MAC_PERFORM(copy_mbuf_label, src_label, dest_label); 1152} 1153 1154static void 1155mac_copy_pipe_label(struct label *src, struct label *dest) 1156{ 1157 1158 MAC_PERFORM(copy_pipe_label, src, dest); 1159} 1160 1161void 1162mac_copy_vnode_label(struct label *src, struct label *dest) 1163{ 1164 1165 MAC_PERFORM(copy_vnode_label, src, dest); 1166} 1167 1168static int 1169mac_check_structmac_consistent(struct mac *mac) 1170{ 1171 1172 if (mac->m_buflen < 0 || 1173 mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 1174 return (EINVAL); 1175 1176 return (0); 1177} 1178 1179static int 1180mac_externalize_cred_label(struct label *label, char *elements, 1181 char *outbuf, size_t outbuflen, int flags) 1182{ 1183 int error; 1184 1185 MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen); 1186 1187 return (error); 1188} 1189 1190static int 1191mac_externalize_ifnet_label(struct label *label, char *elements, 1192 char *outbuf, size_t outbuflen, int flags) 1193{ 1194 int error; 1195 1196 MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen); 1197 1198 return (error); 1199} 1200 1201static int 1202mac_externalize_pipe_label(struct label *label, char *elements, 1203 char *outbuf, size_t outbuflen, int flags) 1204{ 1205 int error; 1206 1207 MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen); 1208 1209 return (error); 1210} 1211 1212static int 1213mac_externalize_socket_label(struct label *label, char *elements, 1214 char *outbuf, size_t outbuflen, int flags) 1215{ 1216 int error; 1217 1218 MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen); 1219 1220 return (error); 1221} 1222 1223static int 1224mac_externalize_socket_peer_label(struct label *label, char *elements, 1225 char *outbuf, size_t outbuflen, int flags) 1226{ 1227 int error; 1228 1229 MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen); 1230 1231 return (error); 1232} 1233 1234static int 1235mac_externalize_vnode_label(struct label *label, char *elements, 1236 char *outbuf, size_t outbuflen, int flags) 1237{ 1238 int error; 1239 1240 MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen); 1241 1242 return (error); 1243} 1244 1245static int 1246mac_internalize_cred_label(struct label *label, char *string) 1247{ 1248 int error; 1249 1250 MAC_INTERNALIZE(cred_label, label, string); 1251 1252 return (error); 1253} 1254 1255static int 1256mac_internalize_ifnet_label(struct label *label, char *string) 1257{ 1258 int error; 1259 1260 MAC_INTERNALIZE(ifnet_label, label, string); 1261 1262 return (error); 1263} 1264 1265static int 1266mac_internalize_pipe_label(struct label *label, char *string) 1267{ 1268 int error; 1269 1270 MAC_INTERNALIZE(pipe_label, label, string); 1271 1272 return (error); 1273} 1274 1275static int 1276mac_internalize_socket_label(struct label *label, char *string) 1277{ 1278 int error; 1279 1280 MAC_INTERNALIZE(socket_label, label, string); 1281 1282 return (error); 1283} 1284 1285static int 1286mac_internalize_vnode_label(struct label *label, char *string) 1287{ 1288 int error; 1289 1290 MAC_INTERNALIZE(vnode_label, label, string); 1291 1292 return (error); 1293} 1294 1295/* 1296 * Initialize MAC label for the first kernel process, from which other 1297 * kernel processes and threads are spawned. 1298 */ 1299void 1300mac_create_proc0(struct ucred *cred) 1301{ 1302 1303 MAC_PERFORM(create_proc0, cred); 1304} 1305 1306/* 1307 * Initialize MAC label for the first userland process, from which other 1308 * userland processes and threads are spawned. 1309 */ 1310void 1311mac_create_proc1(struct ucred *cred) 1312{ 1313 1314 MAC_PERFORM(create_proc1, cred); 1315} 1316 1317void 1318mac_thread_userret(struct thread *td) 1319{ 1320 1321 MAC_PERFORM(thread_userret, td); 1322} 1323 1324/* 1325 * When a new process is created, its label must be initialized. Generally, 1326 * this involves inheritence from the parent process, modulo possible 1327 * deltas. This function allows that processing to take place. 1328 */ 1329void 1330mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 1331{ 1332 1333 MAC_PERFORM(create_cred, parent_cred, child_cred); 1334} 1335 1336void 1337mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de, 1338 struct vnode *vp) 1339{ 1340 1341 MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp, 1342 &vp->v_label); 1343} 1344 1345void 1346mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 1347 struct vnode *vp) 1348{ 1349 1350 MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, 1351 &de->de_label, vp, &vp->v_label); 1352} 1353 1354int 1355mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 1356{ 1357 int error; 1358 1359 ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 1360 1361 MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, 1362 &vp->v_label); 1363 1364 return (error); 1365} 1366 1367void 1368mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 1369{ 1370 1371 MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, 1372 &vp->v_label); 1373} 1374 1375int 1376mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 1377 struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 1378{ 1379 int error; 1380 1381 ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 1382 ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 1383 1384 error = VOP_OPENEXTATTR(vp, cred, curthread); 1385 if (error == EOPNOTSUPP) { 1386 /* XXX: Optionally abort if transactions not supported. */ 1387 if (ea_warn_once == 0) { 1388 printf("Warning: transactions not supported " 1389 "in EA write.\n"); 1390 ea_warn_once = 1; 1391 } 1392 } else if (error) 1393 return (error); 1394 1395 MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, 1396 dvp, &dvp->v_label, vp, &vp->v_label, cnp); 1397 1398 if (error) { 1399 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 1400 return (error); 1401 } 1402 1403 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 1404 1405 if (error == EOPNOTSUPP) 1406 error = 0; /* XXX */ 1407 1408 return (error); 1409} 1410 1411static int 1412mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 1413 struct label *intlabel) 1414{ 1415 int error; 1416 1417 ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 1418 1419 error = VOP_OPENEXTATTR(vp, cred, curthread); 1420 if (error == EOPNOTSUPP) { 1421 /* XXX: Optionally abort if transactions not supported. */ 1422 if (ea_warn_once == 0) { 1423 printf("Warning: transactions not supported " 1424 "in EA write.\n"); 1425 ea_warn_once = 1; 1426 } 1427 } else if (error) 1428 return (error); 1429 1430 MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); 1431 1432 if (error) { 1433 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 1434 return (error); 1435 } 1436 1437 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 1438 1439 if (error == EOPNOTSUPP) 1440 error = 0; /* XXX */ 1441 1442 return (error); 1443} 1444 1445int 1446mac_execve_enter(struct image_params *imgp, struct mac *mac_p, 1447 struct label *execlabelstorage) 1448{ 1449 struct mac mac; 1450 char *buffer; 1451 int error; 1452 1453 if (mac_p == NULL) 1454 return (0); 1455 1456 error = copyin(mac_p, &mac, sizeof(mac)); 1457 if (error) 1458 return (error); 1459 1460 error = mac_check_structmac_consistent(&mac); 1461 if (error) 1462 return (error); 1463 1464 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1465 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1466 if (error) { 1467 free(buffer, M_MACTEMP); 1468 return (error); 1469 } 1470 1471 mac_init_cred_label(execlabelstorage); 1472 error = mac_internalize_cred_label(execlabelstorage, buffer); 1473 free(buffer, M_MACTEMP); 1474 if (error) { 1475 mac_destroy_cred_label(execlabelstorage); 1476 return (error); 1477 } 1478 imgp->execlabel = execlabelstorage; 1479 return (0); 1480} 1481 1482void 1483mac_execve_exit(struct image_params *imgp) 1484{ 1485 if (imgp->execlabel != NULL) 1486 mac_destroy_cred_label(imgp->execlabel); 1487} 1488 1489void 1490mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, 1491 struct label *interpvnodelabel, struct image_params *imgp) 1492{ 1493 1494 ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 1495 1496 if (!mac_enforce_process && !mac_enforce_fs) 1497 return; 1498 1499 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, 1500 interpvnodelabel, imgp, imgp->execlabel); 1501} 1502 1503int 1504mac_execve_will_transition(struct ucred *old, struct vnode *vp, 1505 struct label *interpvnodelabel, struct image_params *imgp) 1506{ 1507 int result; 1508 1509 ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 1510 1511 if (!mac_enforce_process && !mac_enforce_fs) 1512 return (0); 1513 1514 result = 0; 1515 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, 1516 interpvnodelabel, imgp, imgp->execlabel); 1517 1518 return (result); 1519} 1520 1521int 1522mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 1523{ 1524 int error; 1525 1526 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 1527 1528 if (!mac_enforce_fs) 1529 return (0); 1530 1531 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode); 1532 return (error); 1533} 1534 1535int 1536mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 1537{ 1538 int error; 1539 1540 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 1541 1542 if (!mac_enforce_fs) 1543 return (0); 1544 1545 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 1546 return (error); 1547} 1548 1549int 1550mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 1551{ 1552 int error; 1553 1554 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 1555 1556 if (!mac_enforce_fs) 1557 return (0); 1558 1559 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 1560 return (error); 1561} 1562 1563int 1564mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 1565 struct componentname *cnp, struct vattr *vap) 1566{ 1567 int error; 1568 1569 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 1570 1571 if (!mac_enforce_fs) 1572 return (0); 1573 1574 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 1575 return (error); 1576} 1577 1578int 1579mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 1580 struct componentname *cnp) 1581{ 1582 int error; 1583 1584 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 1585 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 1586 1587 if (!mac_enforce_fs) 1588 return (0); 1589 1590 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 1591 &vp->v_label, cnp); 1592 return (error); 1593} 1594 1595int 1596mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 1597 acl_type_t type) 1598{ 1599 int error; 1600 1601 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 1602 1603 if (!mac_enforce_fs) 1604 return (0); 1605 1606 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 1607 return (error); 1608} 1609 1610int 1611mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, 1612 int attrnamespace, const char *name) 1613{ 1614 int error; 1615 1616 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr"); 1617 1618 if (!mac_enforce_fs) 1619 return (0); 1620 1621 MAC_CHECK(check_vnode_deleteextattr, cred, vp, &vp->v_label, 1622 attrnamespace, name); 1623 return (error); 1624} 1625 1626int 1627mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, 1628 struct image_params *imgp) 1629{ 1630 int error; 1631 1632 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1633 1634 if (!mac_enforce_process && !mac_enforce_fs) 1635 return (0); 1636 1637 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp, 1638 imgp->execlabel); 1639 1640 return (error); 1641} 1642 1643int 1644mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 1645{ 1646 int error; 1647 1648 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 1649 1650 if (!mac_enforce_fs) 1651 return (0); 1652 1653 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 1654 return (error); 1655} 1656 1657int 1658mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 1659 int attrnamespace, const char *name, struct uio *uio) 1660{ 1661 int error; 1662 1663 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 1664 1665 if (!mac_enforce_fs) 1666 return (0); 1667 1668 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 1669 attrnamespace, name, uio); 1670 return (error); 1671} 1672 1673int 1674mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 1675 struct vnode *vp, struct componentname *cnp) 1676{ 1677 int error; 1678 1679 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 1680 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 1681 1682 if (!mac_enforce_fs) 1683 return (0); 1684 1685 MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 1686 &vp->v_label, cnp); 1687 return (error); 1688} 1689 1690int 1691mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, 1692 int attrnamespace) 1693{ 1694 int error; 1695 1696 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr"); 1697 1698 if (!mac_enforce_fs) 1699 return (0); 1700 1701 MAC_CHECK(check_vnode_listextattr, cred, vp, &vp->v_label, 1702 attrnamespace); 1703 return (error); 1704} 1705 1706int 1707mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 1708 struct componentname *cnp) 1709{ 1710 int error; 1711 1712 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 1713 1714 if (!mac_enforce_fs) 1715 return (0); 1716 1717 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 1718 return (error); 1719} 1720 1721int 1722mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 1723{ 1724 int error; 1725 1726 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1727 1728 if (!mac_enforce_fs || !mac_enforce_vm) 1729 return (0); 1730 1731 MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1732 return (error); 1733} 1734 1735void 1736mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1737{ 1738 int result = *prot; 1739 1740 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1741 1742 if (!mac_enforce_fs || !mac_enforce_vm) 1743 return; 1744 1745 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1746 &result); 1747 1748 *prot = result; 1749} 1750 1751int 1752mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1753{ 1754 int error; 1755 1756 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1757 1758 if (!mac_enforce_fs || !mac_enforce_vm) 1759 return (0); 1760 1761 MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 1762 return (error); 1763} 1764 1765int 1766mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 1767{ 1768 int error; 1769 1770 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 1771 1772 if (!mac_enforce_fs) 1773 return (0); 1774 1775 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 1776 return (error); 1777} 1778 1779int 1780mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 1781 struct vnode *vp) 1782{ 1783 int error; 1784 1785 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 1786 1787 if (!mac_enforce_fs) 1788 return (0); 1789 1790 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 1791 &vp->v_label); 1792 1793 return (error); 1794} 1795 1796int 1797mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 1798 struct vnode *vp) 1799{ 1800 int error; 1801 1802 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 1803 1804 if (!mac_enforce_fs) 1805 return (0); 1806 1807 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 1808 &vp->v_label); 1809 1810 return (error); 1811} 1812 1813int 1814mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 1815{ 1816 int error; 1817 1818 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 1819 1820 if (!mac_enforce_fs) 1821 return (0); 1822 1823 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 1824 return (error); 1825} 1826 1827int 1828mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 1829{ 1830 int error; 1831 1832 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 1833 1834 if (!mac_enforce_fs) 1835 return (0); 1836 1837 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 1838 return (error); 1839} 1840 1841static int 1842mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 1843 struct label *newlabel) 1844{ 1845 int error; 1846 1847 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 1848 1849 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 1850 1851 return (error); 1852} 1853 1854int 1855mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 1856 struct vnode *vp, struct componentname *cnp) 1857{ 1858 int error; 1859 1860 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 1861 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 1862 1863 if (!mac_enforce_fs) 1864 return (0); 1865 1866 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 1867 &vp->v_label, cnp); 1868 return (error); 1869} 1870 1871int 1872mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 1873 struct vnode *vp, int samedir, struct componentname *cnp) 1874{ 1875 int error; 1876 1877 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 1878 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 1879 1880 if (!mac_enforce_fs) 1881 return (0); 1882 1883 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 1884 vp != NULL ? &vp->v_label : NULL, samedir, cnp); 1885 return (error); 1886} 1887 1888int 1889mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 1890{ 1891 int error; 1892 1893 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 1894 1895 if (!mac_enforce_fs) 1896 return (0); 1897 1898 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 1899 return (error); 1900} 1901 1902int 1903mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 1904 struct acl *acl) 1905{ 1906 int error; 1907 1908 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 1909 1910 if (!mac_enforce_fs) 1911 return (0); 1912 1913 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 1914 return (error); 1915} 1916 1917int 1918mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 1919 int attrnamespace, const char *name, struct uio *uio) 1920{ 1921 int error; 1922 1923 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 1924 1925 if (!mac_enforce_fs) 1926 return (0); 1927 1928 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 1929 attrnamespace, name, uio); 1930 return (error); 1931} 1932 1933int 1934mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 1935{ 1936 int error; 1937 1938 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 1939 1940 if (!mac_enforce_fs) 1941 return (0); 1942 1943 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 1944 return (error); 1945} 1946 1947int 1948mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 1949{ 1950 int error; 1951 1952 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 1953 1954 if (!mac_enforce_fs) 1955 return (0); 1956 1957 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 1958 return (error); 1959} 1960 1961int 1962mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 1963 gid_t gid) 1964{ 1965 int error; 1966 1967 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 1968 1969 if (!mac_enforce_fs) 1970 return (0); 1971 1972 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 1973 return (error); 1974} 1975 1976int 1977mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 1978 struct timespec atime, struct timespec mtime) 1979{ 1980 int error; 1981 1982 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 1983 1984 if (!mac_enforce_fs) 1985 return (0); 1986 1987 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 1988 mtime); 1989 return (error); 1990} 1991 1992int 1993mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 1994 struct vnode *vp) 1995{ 1996 int error; 1997 1998 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 1999 2000 if (!mac_enforce_fs) 2001 return (0); 2002 2003 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 2004 &vp->v_label); 2005 return (error); 2006} 2007 2008int 2009mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 2010 struct vnode *vp) 2011{ 2012 int error; 2013 2014 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 2015 2016 if (!mac_enforce_fs) 2017 return (0); 2018 2019 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 2020 &vp->v_label); 2021 2022 return (error); 2023} 2024 2025/* 2026 * When relabeling a process, call out to the policies for the maximum 2027 * permission allowed for each object type we know about in its 2028 * memory space, and revoke access (in the least surprising ways we 2029 * know) when necessary. The process lock is not held here. 2030 */ 2031void 2032mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 2033{ 2034 2035 /* XXX freeze all other threads */ 2036 mac_cred_mmapped_drop_perms_recurse(td, cred, 2037 &td->td_proc->p_vmspace->vm_map); 2038 /* XXX allow other threads to continue */ 2039} 2040 2041static __inline const char * 2042prot2str(vm_prot_t prot) 2043{ 2044 2045 switch (prot & VM_PROT_ALL) { 2046 case VM_PROT_READ: 2047 return ("r--"); 2048 case VM_PROT_READ | VM_PROT_WRITE: 2049 return ("rw-"); 2050 case VM_PROT_READ | VM_PROT_EXECUTE: 2051 return ("r-x"); 2052 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 2053 return ("rwx"); 2054 case VM_PROT_WRITE: 2055 return ("-w-"); 2056 case VM_PROT_EXECUTE: 2057 return ("--x"); 2058 case VM_PROT_WRITE | VM_PROT_EXECUTE: 2059 return ("-wx"); 2060 default: 2061 return ("---"); 2062 } 2063} 2064 2065static void 2066mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 2067 struct vm_map *map) 2068{ 2069 struct vm_map_entry *vme; 2070 int result; 2071 vm_prot_t revokeperms; 2072 vm_object_t object; 2073 vm_ooffset_t offset; 2074 struct vnode *vp; 2075 2076 if (!mac_mmap_revocation) 2077 return; 2078 2079 vm_map_lock_read(map); 2080 for (vme = map->header.next; vme != &map->header; vme = vme->next) { 2081 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 2082 mac_cred_mmapped_drop_perms_recurse(td, cred, 2083 vme->object.sub_map); 2084 continue; 2085 } 2086 /* 2087 * Skip over entries that obviously are not shared. 2088 */ 2089 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 2090 !vme->max_protection) 2091 continue; 2092 /* 2093 * Drill down to the deepest backing object. 2094 */ 2095 offset = vme->offset; 2096 object = vme->object.vm_object; 2097 if (object == NULL) 2098 continue; 2099 while (object->backing_object != NULL) { 2100 object = object->backing_object; 2101 offset += object->backing_object_offset; 2102 } 2103 /* 2104 * At the moment, vm_maps and objects aren't considered 2105 * by the MAC system, so only things with backing by a 2106 * normal object (read: vnodes) are checked. 2107 */ 2108 if (object->type != OBJT_VNODE) 2109 continue; 2110 vp = (struct vnode *)object->handle; 2111 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2112 result = vme->max_protection; 2113 mac_check_vnode_mmap_downgrade(cred, vp, &result); 2114 VOP_UNLOCK(vp, 0, td); 2115 /* 2116 * Find out what maximum protection we may be allowing 2117 * now but a policy needs to get removed. 2118 */ 2119 revokeperms = vme->max_protection & ~result; 2120 if (!revokeperms) 2121 continue; 2122 printf("pid %ld: revoking %s perms from %#lx:%ld " 2123 "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 2124 prot2str(revokeperms), (u_long)vme->start, 2125 (long)(vme->end - vme->start), 2126 prot2str(vme->max_protection), prot2str(vme->protection)); 2127 vm_map_lock_upgrade(map); 2128 /* 2129 * This is the really simple case: if a map has more 2130 * max_protection than is allowed, but it's not being 2131 * actually used (that is, the current protection is 2132 * still allowed), we can just wipe it out and do 2133 * nothing more. 2134 */ 2135 if ((vme->protection & revokeperms) == 0) { 2136 vme->max_protection -= revokeperms; 2137 } else { 2138 if (revokeperms & VM_PROT_WRITE) { 2139 /* 2140 * In the more complicated case, flush out all 2141 * pending changes to the object then turn it 2142 * copy-on-write. 2143 */ 2144 vm_object_reference(object); 2145 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2146 VM_OBJECT_LOCK(object); 2147 vm_object_page_clean(object, 2148 OFF_TO_IDX(offset), 2149 OFF_TO_IDX(offset + vme->end - vme->start + 2150 PAGE_MASK), 2151 OBJPC_SYNC); 2152 VM_OBJECT_UNLOCK(object); 2153 VOP_UNLOCK(vp, 0, td); 2154 vm_object_deallocate(object); 2155 /* 2156 * Why bother if there's no read permissions 2157 * anymore? For the rest, we need to leave 2158 * the write permissions on for COW, or 2159 * remove them entirely if configured to. 2160 */ 2161 if (!mac_mmap_revocation_via_cow) { 2162 vme->max_protection &= ~VM_PROT_WRITE; 2163 vme->protection &= ~VM_PROT_WRITE; 2164 } if ((revokeperms & VM_PROT_READ) == 0) 2165 vme->eflags |= MAP_ENTRY_COW | 2166 MAP_ENTRY_NEEDS_COPY; 2167 } 2168 if (revokeperms & VM_PROT_EXECUTE) { 2169 vme->max_protection &= ~VM_PROT_EXECUTE; 2170 vme->protection &= ~VM_PROT_EXECUTE; 2171 } 2172 if (revokeperms & VM_PROT_READ) { 2173 vme->max_protection = 0; 2174 vme->protection = 0; 2175 } 2176 pmap_protect(map->pmap, vme->start, vme->end, 2177 vme->protection & ~revokeperms); 2178 vm_map_simplify_entry(map, vme); 2179 } 2180 vm_map_lock_downgrade(map); 2181 } 2182 vm_map_unlock_read(map); 2183} 2184 2185/* 2186 * When the subject's label changes, it may require revocation of privilege 2187 * to mapped objects. This can't be done on-the-fly later with a unified 2188 * buffer cache. 2189 */ 2190static void 2191mac_relabel_cred(struct ucred *cred, struct label *newlabel) 2192{ 2193 2194 MAC_PERFORM(relabel_cred, cred, newlabel); 2195} 2196 2197void 2198mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 2199{ 2200 2201 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 2202} 2203 2204void 2205mac_create_ifnet(struct ifnet *ifnet) 2206{ 2207 2208 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 2209} 2210 2211void 2212mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 2213{ 2214 2215 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 2216} 2217 2218void 2219mac_create_socket(struct ucred *cred, struct socket *socket) 2220{ 2221 2222 MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 2223} 2224 2225void 2226mac_create_pipe(struct ucred *cred, struct pipe *pipe) 2227{ 2228 2229 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 2230} 2231 2232void 2233mac_create_socket_from_socket(struct socket *oldsocket, 2234 struct socket *newsocket) 2235{ 2236 2237 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 2238 newsocket, &newsocket->so_label); 2239} 2240 2241static void 2242mac_relabel_socket(struct ucred *cred, struct socket *socket, 2243 struct label *newlabel) 2244{ 2245 2246 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 2247} 2248 2249static void 2250mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 2251{ 2252 2253 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 2254} 2255 2256void 2257mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 2258{ 2259 struct label *label; 2260 2261 label = mbuf_to_label(mbuf); 2262 2263 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket, 2264 &socket->so_peerlabel); 2265} 2266 2267void 2268mac_set_socket_peer_from_socket(struct socket *oldsocket, 2269 struct socket *newsocket) 2270{ 2271 2272 MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 2273 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 2274} 2275 2276void 2277mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 2278{ 2279 struct label *label; 2280 2281 label = mbuf_to_label(datagram); 2282 2283 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 2284 datagram, label); 2285} 2286 2287void 2288mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 2289{ 2290 struct label *datagramlabel, *fragmentlabel; 2291 2292 datagramlabel = mbuf_to_label(datagram); 2293 fragmentlabel = mbuf_to_label(fragment); 2294 2295 MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment, 2296 fragmentlabel); 2297} 2298 2299void 2300mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 2301{ 2302 struct label *label; 2303 2304 label = mbuf_to_label(fragment); 2305 2306 MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label); 2307} 2308 2309void 2310mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2311{ 2312 struct label *oldmbuflabel, *newmbuflabel; 2313 2314 oldmbuflabel = mbuf_to_label(oldmbuf); 2315 newmbuflabel = mbuf_to_label(newmbuf); 2316 2317 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf, 2318 newmbuflabel); 2319} 2320 2321void 2322mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 2323{ 2324 struct label *label; 2325 2326 label = mbuf_to_label(mbuf); 2327 2328 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 2329 label); 2330} 2331 2332void 2333mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 2334{ 2335 struct label *label; 2336 2337 label = mbuf_to_label(mbuf); 2338 2339 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 2340 label); 2341} 2342 2343void 2344mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 2345{ 2346 struct label *label; 2347 2348 label = mbuf_to_label(mbuf); 2349 2350 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 2351 label); 2352} 2353 2354void 2355mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 2356 struct mbuf *newmbuf) 2357{ 2358 struct label *oldmbuflabel, *newmbuflabel; 2359 2360 oldmbuflabel = mbuf_to_label(oldmbuf); 2361 newmbuflabel = mbuf_to_label(newmbuf); 2362 2363 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel, 2364 ifnet, &ifnet->if_label, newmbuf, newmbuflabel); 2365} 2366 2367void 2368mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2369{ 2370 struct label *oldmbuflabel, *newmbuflabel; 2371 2372 oldmbuflabel = mbuf_to_label(oldmbuf); 2373 newmbuflabel = mbuf_to_label(newmbuf); 2374 2375 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf, 2376 newmbuflabel); 2377} 2378 2379int 2380mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 2381{ 2382 struct label *label; 2383 int result; 2384 2385 label = mbuf_to_label(fragment); 2386 2387 result = 1; 2388 MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq, 2389 &ipq->ipq_label); 2390 2391 return (result); 2392} 2393 2394void 2395mac_reflect_mbuf_icmp(struct mbuf *m) 2396{ 2397 struct label *label; 2398 2399 label = mbuf_to_label(m); 2400 2401 MAC_PERFORM(reflect_mbuf_icmp, m, label); 2402} 2403void 2404mac_reflect_mbuf_tcp(struct mbuf *m) 2405{ 2406 struct label *label; 2407 2408 label = mbuf_to_label(m); 2409 2410 MAC_PERFORM(reflect_mbuf_tcp, m, label); 2411} 2412 2413void 2414mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 2415{ 2416 struct label *label; 2417 2418 label = mbuf_to_label(fragment); 2419 2420 MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label); 2421} 2422 2423void 2424mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 2425{ 2426 struct label *label; 2427 2428 label = mbuf_to_label(mbuf); 2429 2430 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 2431 label); 2432} 2433 2434void 2435mac_create_mount(struct ucred *cred, struct mount *mp) 2436{ 2437 2438 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 2439 &mp->mnt_fslabel); 2440} 2441 2442void 2443mac_create_root_mount(struct ucred *cred, struct mount *mp) 2444{ 2445 2446 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 2447 &mp->mnt_fslabel); 2448} 2449 2450int 2451mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 2452{ 2453 int error; 2454 2455 if (!mac_enforce_network) 2456 return (0); 2457 2458 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 2459 &ifnet->if_label); 2460 2461 return (error); 2462} 2463 2464static int 2465mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 2466{ 2467 int error; 2468 2469 MAC_CHECK(check_cred_relabel, cred, newlabel); 2470 2471 return (error); 2472} 2473 2474int 2475mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 2476{ 2477 int error; 2478 2479 if (!mac_enforce_process) 2480 return (0); 2481 2482 MAC_CHECK(check_cred_visible, u1, u2); 2483 2484 return (error); 2485} 2486 2487int 2488mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 2489{ 2490 struct label *label; 2491 int error; 2492 2493 M_ASSERTPKTHDR(mbuf); 2494 2495 if (!mac_enforce_network) 2496 return (0); 2497 2498 label = mbuf_to_label(mbuf); 2499 2500 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 2501 label); 2502 2503 return (error); 2504} 2505 2506int 2507mac_check_kenv_dump(struct ucred *cred) 2508{ 2509 int error; 2510 2511 if (!mac_enforce_system) 2512 return (0); 2513 2514 MAC_CHECK(check_kenv_dump, cred); 2515 2516 return (error); 2517} 2518 2519int 2520mac_check_kenv_get(struct ucred *cred, char *name) 2521{ 2522 int error; 2523 2524 if (!mac_enforce_system) 2525 return (0); 2526 2527 MAC_CHECK(check_kenv_get, cred, name); 2528 2529 return (error); 2530} 2531 2532int 2533mac_check_kenv_set(struct ucred *cred, char *name, char *value) 2534{ 2535 int error; 2536 2537 if (!mac_enforce_system) 2538 return (0); 2539 2540 MAC_CHECK(check_kenv_set, cred, name, value); 2541 2542 return (error); 2543} 2544 2545int 2546mac_check_kenv_unset(struct ucred *cred, char *name) 2547{ 2548 int error; 2549 2550 if (!mac_enforce_system) 2551 return (0); 2552 2553 MAC_CHECK(check_kenv_unset, cred, name); 2554 2555 return (error); 2556} 2557 2558int 2559mac_check_kld_load(struct ucred *cred, struct vnode *vp) 2560{ 2561 int error; 2562 2563 ASSERT_VOP_LOCKED(vp, "mac_check_kld_load"); 2564 2565 if (!mac_enforce_kld) 2566 return (0); 2567 2568 MAC_CHECK(check_kld_load, cred, vp, &vp->v_label); 2569 2570 return (error); 2571} 2572 2573int 2574mac_check_kld_stat(struct ucred *cred) 2575{ 2576 int error; 2577 2578 if (!mac_enforce_kld) 2579 return (0); 2580 2581 MAC_CHECK(check_kld_stat, cred); 2582 2583 return (error); 2584} 2585 2586int 2587mac_check_kld_unload(struct ucred *cred) 2588{ 2589 int error; 2590 2591 if (!mac_enforce_kld) 2592 return (0); 2593 2594 MAC_CHECK(check_kld_unload, cred); 2595 2596 return (error); 2597} 2598 2599int 2600mac_check_mount_stat(struct ucred *cred, struct mount *mount) 2601{ 2602 int error; 2603 2604 if (!mac_enforce_fs) 2605 return (0); 2606 2607 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 2608 2609 return (error); 2610} 2611 2612int 2613mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 2614 void *data) 2615{ 2616 int error; 2617 2618 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2619 2620 if (!mac_enforce_pipe) 2621 return (0); 2622 2623 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 2624 2625 return (error); 2626} 2627 2628int 2629mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 2630{ 2631 int error; 2632 2633 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2634 2635 if (!mac_enforce_pipe) 2636 return (0); 2637 2638 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2639 2640 return (error); 2641} 2642 2643int 2644mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2645{ 2646 int error; 2647 2648 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2649 2650 if (!mac_enforce_pipe) 2651 return (0); 2652 2653 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 2654 2655 return (error); 2656} 2657 2658static int 2659mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 2660 struct label *newlabel) 2661{ 2662 int error; 2663 2664 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2665 2666 if (!mac_enforce_pipe) 2667 return (0); 2668 2669 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 2670 2671 return (error); 2672} 2673 2674int 2675mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2676{ 2677 int error; 2678 2679 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2680 2681 if (!mac_enforce_pipe) 2682 return (0); 2683 2684 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2685 2686 return (error); 2687} 2688 2689int 2690mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2691{ 2692 int error; 2693 2694 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2695 2696 if (!mac_enforce_pipe) 2697 return (0); 2698 2699 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2700 2701 return (error); 2702} 2703 2704int 2705mac_check_proc_debug(struct ucred *cred, struct proc *proc) 2706{ 2707 int error; 2708 2709 PROC_LOCK_ASSERT(proc, MA_OWNED); 2710 2711 if (!mac_enforce_process) 2712 return (0); 2713 2714 MAC_CHECK(check_proc_debug, cred, proc); 2715 2716 return (error); 2717} 2718 2719int 2720mac_check_proc_sched(struct ucred *cred, struct proc *proc) 2721{ 2722 int error; 2723 2724 PROC_LOCK_ASSERT(proc, MA_OWNED); 2725 2726 if (!mac_enforce_process) 2727 return (0); 2728 2729 MAC_CHECK(check_proc_sched, cred, proc); 2730 2731 return (error); 2732} 2733 2734int 2735mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 2736{ 2737 int error; 2738 2739 PROC_LOCK_ASSERT(proc, MA_OWNED); 2740 2741 if (!mac_enforce_process) 2742 return (0); 2743 2744 MAC_CHECK(check_proc_signal, cred, proc, signum); 2745 2746 return (error); 2747} 2748 2749int 2750mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 2751 struct sockaddr *sockaddr) 2752{ 2753 int error; 2754 2755 if (!mac_enforce_socket) 2756 return (0); 2757 2758 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 2759 sockaddr); 2760 2761 return (error); 2762} 2763 2764int 2765mac_check_socket_connect(struct ucred *cred, struct socket *socket, 2766 struct sockaddr *sockaddr) 2767{ 2768 int error; 2769 2770 if (!mac_enforce_socket) 2771 return (0); 2772 2773 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 2774 sockaddr); 2775 2776 return (error); 2777} 2778 2779int 2780mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2781{ 2782 struct label *label; 2783 int error; 2784 2785 if (!mac_enforce_socket) 2786 return (0); 2787 2788 label = mbuf_to_label(mbuf); 2789 2790 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2791 label); 2792 2793 return (error); 2794} 2795 2796int 2797mac_check_socket_listen(struct ucred *cred, struct socket *socket) 2798{ 2799 int error; 2800 2801 if (!mac_enforce_socket) 2802 return (0); 2803 2804 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 2805 return (error); 2806} 2807 2808int 2809mac_check_socket_receive(struct ucred *cred, struct socket *so) 2810{ 2811 int error; 2812 2813 if (!mac_enforce_socket) 2814 return (0); 2815 2816 MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2817 2818 return (error); 2819} 2820 2821static int 2822mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 2823 struct label *newlabel) 2824{ 2825 int error; 2826 2827 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 2828 newlabel); 2829 2830 return (error); 2831} 2832 2833int 2834mac_check_socket_send(struct ucred *cred, struct socket *so) 2835{ 2836 int error; 2837 2838 if (!mac_enforce_socket) 2839 return (0); 2840 2841 MAC_CHECK(check_socket_send, cred, so, &so->so_label); 2842 2843 return (error); 2844} 2845 2846int 2847mac_check_socket_visible(struct ucred *cred, struct socket *socket) 2848{ 2849 int error; 2850 2851 if (!mac_enforce_socket) 2852 return (0); 2853 2854 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 2855 2856 return (error); 2857} 2858 2859int 2860mac_check_sysarch_ioperm(struct ucred *cred) 2861{ 2862 int error; 2863 2864 if (!mac_enforce_system) 2865 return (0); 2866 2867 MAC_CHECK(check_sysarch_ioperm, cred); 2868 return (error); 2869} 2870 2871int 2872mac_check_system_acct(struct ucred *cred, struct vnode *vp) 2873{ 2874 int error; 2875 2876 if (vp != NULL) { 2877 ASSERT_VOP_LOCKED(vp, "mac_check_system_acct"); 2878 } 2879 2880 if (!mac_enforce_system) 2881 return (0); 2882 2883 MAC_CHECK(check_system_acct, cred, vp, 2884 vp != NULL ? &vp->v_label : NULL); 2885 2886 return (error); 2887} 2888 2889int 2890mac_check_system_nfsd(struct ucred *cred) 2891{ 2892 int error; 2893 2894 if (!mac_enforce_system) 2895 return (0); 2896 2897 MAC_CHECK(check_system_nfsd, cred); 2898 2899 return (error); 2900} 2901 2902int 2903mac_check_system_reboot(struct ucred *cred, int howto) 2904{ 2905 int error; 2906 2907 if (!mac_enforce_system) 2908 return (0); 2909 2910 MAC_CHECK(check_system_reboot, cred, howto); 2911 2912 return (error); 2913} 2914 2915int 2916mac_check_system_settime(struct ucred *cred) 2917{ 2918 int error; 2919 2920 if (!mac_enforce_system) 2921 return (0); 2922 2923 MAC_CHECK(check_system_settime, cred); 2924 2925 return (error); 2926} 2927 2928int 2929mac_check_system_swapon(struct ucred *cred, struct vnode *vp) 2930{ 2931 int error; 2932 2933 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 2934 2935 if (!mac_enforce_system) 2936 return (0); 2937 2938 MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 2939 return (error); 2940} 2941 2942int 2943mac_check_system_swapoff(struct ucred *cred, struct vnode *vp) 2944{ 2945 int error; 2946 2947 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff"); 2948 2949 if (!mac_enforce_system) 2950 return (0); 2951 2952 MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label); 2953 return (error); 2954} 2955 2956int 2957mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 2958 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 2959{ 2960 int error; 2961 2962 /* 2963 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here, 2964 * but since it's not exported from kern_sysctl.c, we can't. 2965 */ 2966 if (!mac_enforce_system) 2967 return (0); 2968 2969 MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp, 2970 inkernel, new, newlen); 2971 2972 return (error); 2973} 2974 2975int 2976mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 2977 struct ifnet *ifnet) 2978{ 2979 char *elements, *buffer; 2980 struct mac mac; 2981 int error; 2982 2983 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 2984 if (error) 2985 return (error); 2986 2987 error = mac_check_structmac_consistent(&mac); 2988 if (error) 2989 return (error); 2990 2991 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2992 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2993 if (error) { 2994 free(elements, M_MACTEMP); 2995 return (error); 2996 } 2997 2998 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2999 error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 3000 buffer, mac.m_buflen, M_WAITOK); 3001 if (error == 0) 3002 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3003 3004 free(buffer, M_MACTEMP); 3005 free(elements, M_MACTEMP); 3006 3007 return (error); 3008} 3009 3010int 3011mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 3012 struct ifnet *ifnet) 3013{ 3014 struct label intlabel; 3015 struct mac mac; 3016 char *buffer; 3017 int error; 3018 3019 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 3020 if (error) 3021 return (error); 3022 3023 error = mac_check_structmac_consistent(&mac); 3024 if (error) 3025 return (error); 3026 3027 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3028 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3029 if (error) { 3030 free(buffer, M_MACTEMP); 3031 return (error); 3032 } 3033 3034 mac_init_ifnet_label(&intlabel); 3035 error = mac_internalize_ifnet_label(&intlabel, buffer); 3036 free(buffer, M_MACTEMP); 3037 if (error) { 3038 mac_destroy_ifnet_label(&intlabel); 3039 return (error); 3040 } 3041 3042 /* 3043 * XXX: Note that this is a redundant privilege check, since 3044 * policies impose this check themselves if required by the 3045 * policy. Eventually, this should go away. 3046 */ 3047 error = suser_cred(cred, 0); 3048 if (error) { 3049 mac_destroy_ifnet_label(&intlabel); 3050 return (error); 3051 } 3052 3053 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 3054 &intlabel); 3055 if (error) { 3056 mac_destroy_ifnet_label(&intlabel); 3057 return (error); 3058 } 3059 3060 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 3061 3062 mac_destroy_ifnet_label(&intlabel); 3063 return (0); 3064} 3065 3066void 3067mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de) 3068{ 3069 3070 MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label); 3071} 3072 3073void 3074mac_create_devfs_symlink(struct ucred *cred, struct mount *mp, 3075 struct devfs_dirent *dd, struct devfs_dirent *de) 3076{ 3077 3078 MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de, 3079 &de->de_label); 3080} 3081 3082void 3083mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, 3084 struct devfs_dirent *de) 3085{ 3086 3087 MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de, 3088 &de->de_label); 3089} 3090 3091int 3092mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 3093 struct mac *mac) 3094{ 3095 struct label intlabel; 3096 char *buffer; 3097 int error; 3098 3099 error = mac_check_structmac_consistent(mac); 3100 if (error) 3101 return (error); 3102 3103 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3104 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 3105 if (error) { 3106 free(buffer, M_MACTEMP); 3107 return (error); 3108 } 3109 3110 mac_init_socket_label(&intlabel, M_WAITOK); 3111 error = mac_internalize_socket_label(&intlabel, buffer); 3112 free(buffer, M_MACTEMP); 3113 if (error) { 3114 mac_destroy_socket_label(&intlabel); 3115 return (error); 3116 } 3117 3118 mac_check_socket_relabel(cred, so, &intlabel); 3119 if (error) { 3120 mac_destroy_socket_label(&intlabel); 3121 return (error); 3122 } 3123 3124 mac_relabel_socket(cred, so, &intlabel); 3125 3126 mac_destroy_socket_label(&intlabel); 3127 return (0); 3128} 3129 3130int 3131mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 3132{ 3133 int error; 3134 3135 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 3136 3137 error = mac_check_pipe_relabel(cred, pipe, label); 3138 if (error) 3139 return (error); 3140 3141 mac_relabel_pipe(cred, pipe, label); 3142 3143 return (0); 3144} 3145 3146int 3147mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 3148 struct mac *mac) 3149{ 3150 char *buffer, *elements; 3151 int error; 3152 3153 error = mac_check_structmac_consistent(mac); 3154 if (error) 3155 return (error); 3156 3157 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3158 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3159 if (error) { 3160 free(elements, M_MACTEMP); 3161 return (error); 3162 } 3163 3164 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3165 error = mac_externalize_socket_label(&so->so_label, elements, 3166 buffer, mac->m_buflen, M_WAITOK); 3167 if (error == 0) 3168 error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3169 3170 free(buffer, M_MACTEMP); 3171 free(elements, M_MACTEMP); 3172 3173 return (error); 3174} 3175 3176int 3177mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 3178 struct mac *mac) 3179{ 3180 char *elements, *buffer; 3181 int error; 3182 3183 error = mac_check_structmac_consistent(mac); 3184 if (error) 3185 return (error); 3186 3187 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3188 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3189 if (error) { 3190 free(elements, M_MACTEMP); 3191 return (error); 3192 } 3193 3194 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3195 error = mac_externalize_socket_peer_label(&so->so_peerlabel, 3196 elements, buffer, mac->m_buflen, M_WAITOK); 3197 if (error == 0) 3198 error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3199 3200 free(buffer, M_MACTEMP); 3201 free(elements, M_MACTEMP); 3202 3203 return (error); 3204} 3205 3206/* 3207 * Implementation of VOP_SETLABEL() that relies on extended attributes 3208 * to store label data. Can be referenced by filesystems supporting 3209 * extended attributes. 3210 */ 3211int 3212vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 3213{ 3214 struct vnode *vp = ap->a_vp; 3215 struct label *intlabel = ap->a_label; 3216 int error; 3217 3218 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 3219 3220 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 3221 return (EOPNOTSUPP); 3222 3223 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 3224 if (error) 3225 return (error); 3226 3227 mac_relabel_vnode(ap->a_cred, vp, intlabel); 3228 3229 return (0); 3230} 3231 3232static int 3233vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 3234{ 3235 int error; 3236 3237 if (vp->v_mount == NULL) { 3238 /* printf("vn_setlabel: null v_mount\n"); */ 3239 if (vp->v_type != VNON) 3240 printf("vn_setlabel: null v_mount with non-VNON\n"); 3241 return (EBADF); 3242 } 3243 3244 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 3245 return (EOPNOTSUPP); 3246 3247 /* 3248 * Multi-phase commit. First check the policies to confirm the 3249 * change is OK. Then commit via the filesystem. Finally, 3250 * update the actual vnode label. Question: maybe the filesystem 3251 * should update the vnode at the end as part of VOP_SETLABEL()? 3252 */ 3253 error = mac_check_vnode_relabel(cred, vp, intlabel); 3254 if (error) 3255 return (error); 3256 3257 /* 3258 * VADMIN provides the opportunity for the filesystem to make 3259 * decisions about who is and is not able to modify labels 3260 * and protections on files. This might not be right. We can't 3261 * assume VOP_SETLABEL() will do it, because we might implement 3262 * that as part of vop_stdsetlabel_ea(). 3263 */ 3264 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 3265 if (error) 3266 return (error); 3267 3268 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 3269 if (error) 3270 return (error); 3271 3272 return (0); 3273} 3274 3275int 3276__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3277{ 3278 char *elements, *buffer; 3279 struct mac mac; 3280 struct proc *tproc; 3281 struct ucred *tcred; 3282 int error; 3283 3284 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3285 if (error) 3286 return (error); 3287 3288 error = mac_check_structmac_consistent(&mac); 3289 if (error) 3290 return (error); 3291 3292 tproc = pfind(uap->pid); 3293 if (tproc == NULL) 3294 return (ESRCH); 3295 3296 tcred = NULL; /* Satisfy gcc. */ 3297 error = p_cansee(td, tproc); 3298 if (error == 0) 3299 tcred = crhold(tproc->p_ucred); 3300 PROC_UNLOCK(tproc); 3301 if (error) 3302 return (error); 3303 3304 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3305 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3306 if (error) { 3307 free(elements, M_MACTEMP); 3308 crfree(tcred); 3309 return (error); 3310 } 3311 3312 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3313 error = mac_externalize_cred_label(&tcred->cr_label, elements, 3314 buffer, mac.m_buflen, M_WAITOK); 3315 if (error == 0) 3316 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3317 3318 free(buffer, M_MACTEMP); 3319 free(elements, M_MACTEMP); 3320 crfree(tcred); 3321 return (error); 3322} 3323 3324/* 3325 * MPSAFE 3326 */ 3327int 3328__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3329{ 3330 char *elements, *buffer; 3331 struct mac mac; 3332 int error; 3333 3334 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3335 if (error) 3336 return (error); 3337 3338 error = mac_check_structmac_consistent(&mac); 3339 if (error) 3340 return (error); 3341 3342 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3343 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3344 if (error) { 3345 free(elements, M_MACTEMP); 3346 return (error); 3347 } 3348 3349 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3350 error = mac_externalize_cred_label(&td->td_ucred->cr_label, 3351 elements, buffer, mac.m_buflen, M_WAITOK); 3352 if (error == 0) 3353 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3354 3355 free(buffer, M_MACTEMP); 3356 free(elements, M_MACTEMP); 3357 return (error); 3358} 3359 3360/* 3361 * MPSAFE 3362 */ 3363int 3364__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3365{ 3366 struct ucred *newcred, *oldcred; 3367 struct label intlabel; 3368 struct proc *p; 3369 struct mac mac; 3370 char *buffer; 3371 int error; 3372 3373 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3374 if (error) 3375 return (error); 3376 3377 error = mac_check_structmac_consistent(&mac); 3378 if (error) 3379 return (error); 3380 3381 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3382 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3383 if (error) { 3384 free(buffer, M_MACTEMP); 3385 return (error); 3386 } 3387 3388 mac_init_cred_label(&intlabel); 3389 error = mac_internalize_cred_label(&intlabel, buffer); 3390 free(buffer, M_MACTEMP); 3391 if (error) { 3392 mac_destroy_cred_label(&intlabel); 3393 return (error); 3394 } 3395 3396 newcred = crget(); 3397 3398 p = td->td_proc; 3399 PROC_LOCK(p); 3400 oldcred = p->p_ucred; 3401 3402 error = mac_check_cred_relabel(oldcred, &intlabel); 3403 if (error) { 3404 PROC_UNLOCK(p); 3405 crfree(newcred); 3406 goto out; 3407 } 3408 3409 setsugid(p); 3410 crcopy(newcred, oldcred); 3411 mac_relabel_cred(newcred, &intlabel); 3412 p->p_ucred = newcred; 3413 3414 /* 3415 * Grab additional reference for use while revoking mmaps, prior 3416 * to releasing the proc lock and sharing the cred. 3417 */ 3418 crhold(newcred); 3419 PROC_UNLOCK(p); 3420 3421 if (mac_enforce_vm) { 3422 mtx_lock(&Giant); 3423 mac_cred_mmapped_drop_perms(td, newcred); 3424 mtx_unlock(&Giant); 3425 } 3426 3427 crfree(newcred); /* Free revocation reference. */ 3428 crfree(oldcred); 3429 3430out: 3431 mac_destroy_cred_label(&intlabel); 3432 return (error); 3433} 3434 3435/* 3436 * MPSAFE 3437 */ 3438int 3439__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3440{ 3441 char *elements, *buffer; 3442 struct label intlabel; 3443 struct file *fp; 3444 struct mac mac; 3445 struct vnode *vp; 3446 struct pipe *pipe; 3447 short label_type; 3448 int error; 3449 3450 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3451 if (error) 3452 return (error); 3453 3454 error = mac_check_structmac_consistent(&mac); 3455 if (error) 3456 return (error); 3457 3458 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3459 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3460 if (error) { 3461 free(elements, M_MACTEMP); 3462 return (error); 3463 } 3464 3465 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3466 mtx_lock(&Giant); /* VFS */ 3467 error = fget(td, uap->fd, &fp); 3468 if (error) 3469 goto out; 3470 3471 label_type = fp->f_type; 3472 switch (fp->f_type) { 3473 case DTYPE_FIFO: 3474 case DTYPE_VNODE: 3475 vp = fp->f_vnode; 3476 3477 mac_init_vnode_label(&intlabel); 3478 3479 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3480 mac_copy_vnode_label(&vp->v_label, &intlabel); 3481 VOP_UNLOCK(vp, 0, td); 3482 3483 break; 3484 case DTYPE_PIPE: 3485 pipe = fp->f_data; 3486 3487 mac_init_pipe_label(&intlabel); 3488 3489 PIPE_LOCK(pipe); 3490 mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3491 PIPE_UNLOCK(pipe); 3492 break; 3493 default: 3494 error = EINVAL; 3495 fdrop(fp, td); 3496 goto out; 3497 } 3498 fdrop(fp, td); 3499 3500 switch (label_type) { 3501 case DTYPE_FIFO: 3502 case DTYPE_VNODE: 3503 if (error == 0) 3504 error = mac_externalize_vnode_label(&intlabel, 3505 elements, buffer, mac.m_buflen, M_WAITOK); 3506 mac_destroy_vnode_label(&intlabel); 3507 break; 3508 case DTYPE_PIPE: 3509 error = mac_externalize_pipe_label(&intlabel, elements, 3510 buffer, mac.m_buflen, M_WAITOK); 3511 mac_destroy_pipe_label(&intlabel); 3512 break; 3513 default: 3514 panic("__mac_get_fd: corrupted label_type"); 3515 } 3516 3517 if (error == 0) 3518 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3519 3520out: 3521 mtx_unlock(&Giant); /* VFS */ 3522 free(buffer, M_MACTEMP); 3523 free(elements, M_MACTEMP); 3524 3525 return (error); 3526} 3527 3528/* 3529 * MPSAFE 3530 */ 3531int 3532__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3533{ 3534 char *elements, *buffer; 3535 struct nameidata nd; 3536 struct label intlabel; 3537 struct mac mac; 3538 int error; 3539 3540 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3541 if (error) 3542 return (error); 3543 3544 error = mac_check_structmac_consistent(&mac); 3545 if (error) 3546 return (error); 3547 3548 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3549 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3550 if (error) { 3551 free(elements, M_MACTEMP); 3552 return (error); 3553 } 3554 3555 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3556 mtx_lock(&Giant); /* VFS */ 3557 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3558 td); 3559 error = namei(&nd); 3560 if (error) 3561 goto out; 3562 3563 mac_init_vnode_label(&intlabel); 3564 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3565 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3566 mac.m_buflen, M_WAITOK); 3567 3568 NDFREE(&nd, 0); 3569 mac_destroy_vnode_label(&intlabel); 3570 3571 if (error == 0) 3572 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3573 3574out: 3575 mtx_unlock(&Giant); /* VFS */ 3576 3577 free(buffer, M_MACTEMP); 3578 free(elements, M_MACTEMP); 3579 3580 return (error); 3581} 3582 3583/* 3584 * MPSAFE 3585 */ 3586int 3587__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3588{ 3589 char *elements, *buffer; 3590 struct nameidata nd; 3591 struct label intlabel; 3592 struct mac mac; 3593 int error; 3594 3595 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3596 if (error) 3597 return (error); 3598 3599 error = mac_check_structmac_consistent(&mac); 3600 if (error) 3601 return (error); 3602 3603 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3604 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3605 if (error) { 3606 free(elements, M_MACTEMP); 3607 return (error); 3608 } 3609 3610 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3611 mtx_lock(&Giant); /* VFS */ 3612 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3613 td); 3614 error = namei(&nd); 3615 if (error) 3616 goto out; 3617 3618 mac_init_vnode_label(&intlabel); 3619 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3620 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3621 mac.m_buflen, M_WAITOK); 3622 NDFREE(&nd, 0); 3623 mac_destroy_vnode_label(&intlabel); 3624 3625 if (error == 0) 3626 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3627 3628out: 3629 mtx_unlock(&Giant); /* VFS */ 3630 3631 free(buffer, M_MACTEMP); 3632 free(elements, M_MACTEMP); 3633 3634 return (error); 3635} 3636 3637/* 3638 * MPSAFE 3639 */ 3640int 3641__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3642{ 3643 struct label intlabel; 3644 struct pipe *pipe; 3645 struct file *fp; 3646 struct mount *mp; 3647 struct vnode *vp; 3648 struct mac mac; 3649 char *buffer; 3650 int error; 3651 3652 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3653 if (error) 3654 return (error); 3655 3656 error = mac_check_structmac_consistent(&mac); 3657 if (error) 3658 return (error); 3659 3660 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3661 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3662 if (error) { 3663 free(buffer, M_MACTEMP); 3664 return (error); 3665 } 3666 3667 mtx_lock(&Giant); /* VFS */ 3668 3669 error = fget(td, uap->fd, &fp); 3670 if (error) 3671 goto out; 3672 3673 switch (fp->f_type) { 3674 case DTYPE_FIFO: 3675 case DTYPE_VNODE: 3676 mac_init_vnode_label(&intlabel); 3677 error = mac_internalize_vnode_label(&intlabel, buffer); 3678 if (error) { 3679 mac_destroy_vnode_label(&intlabel); 3680 break; 3681 } 3682 3683 vp = fp->f_vnode; 3684 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3685 if (error != 0) { 3686 mac_destroy_vnode_label(&intlabel); 3687 break; 3688 } 3689 3690 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3691 error = vn_setlabel(vp, &intlabel, td->td_ucred); 3692 VOP_UNLOCK(vp, 0, td); 3693 vn_finished_write(mp); 3694 3695 mac_destroy_vnode_label(&intlabel); 3696 break; 3697 3698 case DTYPE_PIPE: 3699 mac_init_pipe_label(&intlabel); 3700 error = mac_internalize_pipe_label(&intlabel, buffer); 3701 if (error == 0) { 3702 pipe = fp->f_data; 3703 PIPE_LOCK(pipe); 3704 error = mac_pipe_label_set(td->td_ucred, pipe, 3705 &intlabel); 3706 PIPE_UNLOCK(pipe); 3707 } 3708 3709 mac_destroy_pipe_label(&intlabel); 3710 break; 3711 3712 default: 3713 error = EINVAL; 3714 } 3715 3716 fdrop(fp, td); 3717out: 3718 mtx_unlock(&Giant); /* VFS */ 3719 3720 free(buffer, M_MACTEMP); 3721 3722 return (error); 3723} 3724 3725/* 3726 * MPSAFE 3727 */ 3728int 3729__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3730{ 3731 struct label intlabel; 3732 struct nameidata nd; 3733 struct mount *mp; 3734 struct mac mac; 3735 char *buffer; 3736 int error; 3737 3738 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3739 if (error) 3740 return (error); 3741 3742 error = mac_check_structmac_consistent(&mac); 3743 if (error) 3744 return (error); 3745 3746 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3747 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3748 if (error) { 3749 free(buffer, M_MACTEMP); 3750 return (error); 3751 } 3752 3753 mac_init_vnode_label(&intlabel); 3754 error = mac_internalize_vnode_label(&intlabel, buffer); 3755 free(buffer, M_MACTEMP); 3756 if (error) { 3757 mac_destroy_vnode_label(&intlabel); 3758 return (error); 3759 } 3760 3761 mtx_lock(&Giant); /* VFS */ 3762 3763 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3764 td); 3765 error = namei(&nd); 3766 if (error == 0) { 3767 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3768 if (error == 0) 3769 error = vn_setlabel(nd.ni_vp, &intlabel, 3770 td->td_ucred); 3771 vn_finished_write(mp); 3772 } 3773 3774 NDFREE(&nd, 0); 3775 mtx_unlock(&Giant); /* VFS */ 3776 mac_destroy_vnode_label(&intlabel); 3777 3778 return (error); 3779} 3780 3781/* 3782 * MPSAFE 3783 */ 3784int 3785__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3786{ 3787 struct label intlabel; 3788 struct nameidata nd; 3789 struct mount *mp; 3790 struct mac mac; 3791 char *buffer; 3792 int error; 3793 3794 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3795 if (error) 3796 return (error); 3797 3798 error = mac_check_structmac_consistent(&mac); 3799 if (error) 3800 return (error); 3801 3802 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3803 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3804 if (error) { 3805 free(buffer, M_MACTEMP); 3806 return (error); 3807 } 3808 3809 mac_init_vnode_label(&intlabel); 3810 error = mac_internalize_vnode_label(&intlabel, buffer); 3811 free(buffer, M_MACTEMP); 3812 if (error) { 3813 mac_destroy_vnode_label(&intlabel); 3814 return (error); 3815 } 3816 3817 mtx_lock(&Giant); /* VFS */ 3818 3819 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3820 td); 3821 error = namei(&nd); 3822 if (error == 0) { 3823 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3824 if (error == 0) 3825 error = vn_setlabel(nd.ni_vp, &intlabel, 3826 td->td_ucred); 3827 vn_finished_write(mp); 3828 } 3829 3830 NDFREE(&nd, 0); 3831 mtx_unlock(&Giant); /* VFS */ 3832 mac_destroy_vnode_label(&intlabel); 3833 3834 return (error); 3835} 3836 3837/* 3838 * MPSAFE 3839 */ 3840int 3841mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3842{ 3843 struct mac_policy_conf *mpc; 3844 char target[MAC_MAX_POLICY_NAME]; 3845 int entrycount, error; 3846 3847 error = copyinstr(uap->policy, target, sizeof(target), NULL); 3848 if (error) 3849 return (error); 3850 3851 error = ENOSYS; 3852 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 3853 if (strcmp(mpc->mpc_name, target) == 0 && 3854 mpc->mpc_ops->mpo_syscall != NULL) { 3855 error = mpc->mpc_ops->mpo_syscall(td, 3856 uap->call, uap->arg); 3857 goto out; 3858 } 3859 } 3860 3861 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 3862 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 3863 if (strcmp(mpc->mpc_name, target) == 0 && 3864 mpc->mpc_ops->mpo_syscall != NULL) { 3865 error = mpc->mpc_ops->mpo_syscall(td, 3866 uap->call, uap->arg); 3867 break; 3868 } 3869 } 3870 mac_policy_list_unbusy(); 3871 } 3872out: 3873 return (error); 3874} 3875 3876SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 3877SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 3878 3879#else /* !MAC */ 3880 3881int 3882__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3883{ 3884 3885 return (ENOSYS); 3886} 3887 3888int 3889__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3890{ 3891 3892 return (ENOSYS); 3893} 3894 3895int 3896__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3897{ 3898 3899 return (ENOSYS); 3900} 3901 3902int 3903__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3904{ 3905 3906 return (ENOSYS); 3907} 3908 3909int 3910__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3911{ 3912 3913 return (ENOSYS); 3914} 3915 3916int 3917__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3918{ 3919 3920 return (ENOSYS); 3921} 3922 3923int 3924__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3925{ 3926 3927 return (ENOSYS); 3928} 3929 3930int 3931__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3932{ 3933 3934 return (ENOSYS); 3935} 3936 3937int 3938__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3939{ 3940 3941 return (ENOSYS); 3942} 3943 3944int 3945mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3946{ 3947 3948 return (ENOSYS); 3949} 3950 3951#endif 3952