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