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