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