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