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