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