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 if (!mac_enforce_process && !mac_enforce_fs) 1261 return; 1262 1263 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); 1264 } 1265 1266 int 1267 mac_execve_will_transition(struct ucred *old, struct vnode *vp) 1268 { 1269 int result; 1270 1271 ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 1272 1273 if (!mac_enforce_process && !mac_enforce_fs) 1274 return (0); 1275 1276 result = 0; 1277 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); 1278 1279 return (result); 1280 } 1281 1282 int 1283 mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 1284 { 1285 int error; 1286 1287 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 1288 1289 if (!mac_enforce_fs) 1290 return (0); 1291 1292 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode); 1293 return (error); 1294 } 1295 1296 int 1297 mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 1298 { 1299 int error; 1300 1301 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 1302 1303 if (!mac_enforce_fs) 1304 return (0); 1305 1306 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 1307 return (error); 1308 } 1309 1310 int 1311 mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 1312 { 1313 int error; 1314 1315 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 1316 1317 if (!mac_enforce_fs) 1318 return (0); 1319 1320 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 1321 return (error); 1322 } 1323 1324 int 1325 mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 1326 struct componentname *cnp, struct vattr *vap) 1327 { 1328 int error; 1329 1330 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 1331 1332 if (!mac_enforce_fs) 1333 return (0); 1334 1335 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 1336 return (error); 1337 } 1338 1339 int 1340 mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 1341 struct componentname *cnp) 1342 { 1343 int error; 1344 1345 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 1346 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 1347 1348 if (!mac_enforce_fs) 1349 return (0); 1350 1351 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 1352 &vp->v_label, cnp); 1353 return (error); 1354 } 1355 1356 int 1357 mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 1358 acl_type_t type) 1359 { 1360 int error; 1361 1362 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 1363 1364 if (!mac_enforce_fs) 1365 return (0); 1366 1367 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 1368 return (error); 1369 } 1370 1371 int 1372 mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) 1373 { 1374 int error; 1375 1376 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1377 1378 if (!mac_enforce_process && !mac_enforce_fs) 1379 return (0); 1380 1381 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); 1382 1383 return (error); 1384 } 1385 1386 int 1387 mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 1388 { 1389 int error; 1390 1391 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 1392 1393 if (!mac_enforce_fs) 1394 return (0); 1395 1396 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 1397 return (error); 1398 } 1399 1400 int 1401 mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 1402 int attrnamespace, const char *name, struct uio *uio) 1403 { 1404 int error; 1405 1406 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 1407 1408 if (!mac_enforce_fs) 1409 return (0); 1410 1411 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 1412 attrnamespace, name, uio); 1413 return (error); 1414 } 1415 1416 int 1417 mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 1418 struct vnode *vp, struct componentname *cnp) 1419 { 1420 int error; 1421 1422 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 1423 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 1424 1425 if (!mac_enforce_fs) 1426 return (0); 1427 1428 MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 1429 &vp->v_label, cnp); 1430 return (error); 1431 } 1432 1433 int 1434 mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 1435 struct componentname *cnp) 1436 { 1437 int error; 1438 1439 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 1440 1441 if (!mac_enforce_fs) 1442 return (0); 1443 1444 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 1445 return (error); 1446 } 1447 1448 int 1449 mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 1450 { 1451 int error; 1452 1453 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1454 1455 if (!mac_enforce_fs || !mac_enforce_vm) 1456 return (0); 1457 1458 MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1459 return (error); 1460 } 1461 1462 void 1463 mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1464 { 1465 int result = *prot; 1466 1467 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1468 1469 if (!mac_enforce_fs || !mac_enforce_vm) 1470 return; 1471 1472 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1473 &result); 1474 1475 *prot = result; 1476 } 1477 1478 int 1479 mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1480 { 1481 int error; 1482 1483 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1484 1485 if (!mac_enforce_fs || !mac_enforce_vm) 1486 return (0); 1487 1488 MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 1489 return (error); 1490 } 1491 1492 int 1493 mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 1494 { 1495 int error; 1496 1497 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 1498 1499 if (!mac_enforce_fs) 1500 return (0); 1501 1502 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 1503 return (error); 1504 } 1505 1506 int 1507 mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 1508 struct vnode *vp) 1509 { 1510 int error; 1511 1512 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 1513 1514 if (!mac_enforce_fs) 1515 return (0); 1516 1517 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 1518 &vp->v_label); 1519 1520 return (error); 1521 } 1522 1523 int 1524 mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 1525 struct vnode *vp) 1526 { 1527 int error; 1528 1529 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 1530 1531 if (!mac_enforce_fs) 1532 return (0); 1533 1534 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 1535 &vp->v_label); 1536 1537 return (error); 1538 } 1539 1540 int 1541 mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 1542 { 1543 int error; 1544 1545 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 1546 1547 if (!mac_enforce_fs) 1548 return (0); 1549 1550 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 1551 return (error); 1552 } 1553 1554 int 1555 mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 1556 { 1557 int error; 1558 1559 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 1560 1561 if (!mac_enforce_fs) 1562 return (0); 1563 1564 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 1565 return (error); 1566 } 1567 1568 static int 1569 mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 1570 struct label *newlabel) 1571 { 1572 int error; 1573 1574 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 1575 1576 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 1577 1578 return (error); 1579 } 1580 1581 int 1582 mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 1583 struct vnode *vp, struct componentname *cnp) 1584 { 1585 int error; 1586 1587 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 1588 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 1589 1590 if (!mac_enforce_fs) 1591 return (0); 1592 1593 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 1594 &vp->v_label, cnp); 1595 return (error); 1596 } 1597 1598 int 1599 mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 1600 struct vnode *vp, int samedir, struct componentname *cnp) 1601 { 1602 int error; 1603 1604 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 1605 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 1606 1607 if (!mac_enforce_fs) 1608 return (0); 1609 1610 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 1611 vp != NULL ? &vp->v_label : NULL, samedir, cnp); 1612 return (error); 1613 } 1614 1615 int 1616 mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 1617 { 1618 int error; 1619 1620 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 1621 1622 if (!mac_enforce_fs) 1623 return (0); 1624 1625 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 1626 return (error); 1627 } 1628 1629 int 1630 mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 1631 struct acl *acl) 1632 { 1633 int error; 1634 1635 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 1636 1637 if (!mac_enforce_fs) 1638 return (0); 1639 1640 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 1641 return (error); 1642 } 1643 1644 int 1645 mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 1646 int attrnamespace, const char *name, struct uio *uio) 1647 { 1648 int error; 1649 1650 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 1651 1652 if (!mac_enforce_fs) 1653 return (0); 1654 1655 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 1656 attrnamespace, name, uio); 1657 return (error); 1658 } 1659 1660 int 1661 mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 1662 { 1663 int error; 1664 1665 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 1666 1667 if (!mac_enforce_fs) 1668 return (0); 1669 1670 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 1671 return (error); 1672 } 1673 1674 int 1675 mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 1676 { 1677 int error; 1678 1679 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 1680 1681 if (!mac_enforce_fs) 1682 return (0); 1683 1684 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 1685 return (error); 1686 } 1687 1688 int 1689 mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 1690 gid_t gid) 1691 { 1692 int error; 1693 1694 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 1695 1696 if (!mac_enforce_fs) 1697 return (0); 1698 1699 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 1700 return (error); 1701 } 1702 1703 int 1704 mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 1705 struct timespec atime, struct timespec mtime) 1706 { 1707 int error; 1708 1709 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 1710 1711 if (!mac_enforce_fs) 1712 return (0); 1713 1714 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 1715 mtime); 1716 return (error); 1717 } 1718 1719 int 1720 mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 1721 struct vnode *vp) 1722 { 1723 int error; 1724 1725 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 1726 1727 if (!mac_enforce_fs) 1728 return (0); 1729 1730 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 1731 &vp->v_label); 1732 return (error); 1733 } 1734 1735 int 1736 mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 1737 struct vnode *vp) 1738 { 1739 int error; 1740 1741 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 1742 1743 if (!mac_enforce_fs) 1744 return (0); 1745 1746 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 1747 &vp->v_label); 1748 1749 return (error); 1750 } 1751 1752 /* 1753 * When relabeling a process, call out to the policies for the maximum 1754 * permission allowed for each object type we know about in its 1755 * memory space, and revoke access (in the least surprising ways we 1756 * know) when necessary. The process lock is not held here. 1757 */ 1758 static void 1759 mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 1760 { 1761 1762 /* XXX freeze all other threads */ 1763 mac_cred_mmapped_drop_perms_recurse(td, cred, 1764 &td->td_proc->p_vmspace->vm_map); 1765 /* XXX allow other threads to continue */ 1766 } 1767 1768 static __inline const char * 1769 prot2str(vm_prot_t prot) 1770 { 1771 1772 switch (prot & VM_PROT_ALL) { 1773 case VM_PROT_READ: 1774 return ("r--"); 1775 case VM_PROT_READ | VM_PROT_WRITE: 1776 return ("rw-"); 1777 case VM_PROT_READ | VM_PROT_EXECUTE: 1778 return ("r-x"); 1779 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 1780 return ("rwx"); 1781 case VM_PROT_WRITE: 1782 return ("-w-"); 1783 case VM_PROT_EXECUTE: 1784 return ("--x"); 1785 case VM_PROT_WRITE | VM_PROT_EXECUTE: 1786 return ("-wx"); 1787 default: 1788 return ("---"); 1789 } 1790 } 1791 1792 static void 1793 mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 1794 struct vm_map *map) 1795 { 1796 struct vm_map_entry *vme; 1797 int result; 1798 vm_prot_t revokeperms; 1799 vm_object_t object; 1800 vm_ooffset_t offset; 1801 struct vnode *vp; 1802 1803 if (!mac_mmap_revocation) 1804 return; 1805 1806 vm_map_lock_read(map); 1807 for (vme = map->header.next; vme != &map->header; vme = vme->next) { 1808 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 1809 mac_cred_mmapped_drop_perms_recurse(td, cred, 1810 vme->object.sub_map); 1811 continue; 1812 } 1813 /* 1814 * Skip over entries that obviously are not shared. 1815 */ 1816 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 1817 !vme->max_protection) 1818 continue; 1819 /* 1820 * Drill down to the deepest backing object. 1821 */ 1822 offset = vme->offset; 1823 object = vme->object.vm_object; 1824 if (object == NULL) 1825 continue; 1826 while (object->backing_object != NULL) { 1827 object = object->backing_object; 1828 offset += object->backing_object_offset; 1829 } 1830 /* 1831 * At the moment, vm_maps and objects aren't considered 1832 * by the MAC system, so only things with backing by a 1833 * normal object (read: vnodes) are checked. 1834 */ 1835 if (object->type != OBJT_VNODE) 1836 continue; 1837 vp = (struct vnode *)object->handle; 1838 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1839 result = vme->max_protection; 1840 mac_check_vnode_mmap_downgrade(cred, vp, &result); 1841 VOP_UNLOCK(vp, 0, td); 1842 /* 1843 * Find out what maximum protection we may be allowing 1844 * now but a policy needs to get removed. 1845 */ 1846 revokeperms = vme->max_protection & ~result; 1847 if (!revokeperms) 1848 continue; 1849 printf("pid %ld: revoking %s perms from %#lx:%ld " 1850 "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 1851 prot2str(revokeperms), (u_long)vme->start, 1852 (long)(vme->end - vme->start), 1853 prot2str(vme->max_protection), prot2str(vme->protection)); 1854 vm_map_lock_upgrade(map); 1855 /* 1856 * This is the really simple case: if a map has more 1857 * max_protection than is allowed, but it's not being 1858 * actually used (that is, the current protection is 1859 * still allowed), we can just wipe it out and do 1860 * nothing more. 1861 */ 1862 if ((vme->protection & revokeperms) == 0) { 1863 vme->max_protection -= revokeperms; 1864 } else { 1865 if (revokeperms & VM_PROT_WRITE) { 1866 /* 1867 * In the more complicated case, flush out all 1868 * pending changes to the object then turn it 1869 * copy-on-write. 1870 */ 1871 vm_object_reference(object); 1872 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1873 vm_object_page_clean(object, 1874 OFF_TO_IDX(offset), 1875 OFF_TO_IDX(offset + vme->end - vme->start + 1876 PAGE_MASK), 1877 OBJPC_SYNC); 1878 VOP_UNLOCK(vp, 0, td); 1879 vm_object_deallocate(object); 1880 /* 1881 * Why bother if there's no read permissions 1882 * anymore? For the rest, we need to leave 1883 * the write permissions on for COW, or 1884 * remove them entirely if configured to. 1885 */ 1886 if (!mac_mmap_revocation_via_cow) { 1887 vme->max_protection &= ~VM_PROT_WRITE; 1888 vme->protection &= ~VM_PROT_WRITE; 1889 } if ((revokeperms & VM_PROT_READ) == 0) 1890 vme->eflags |= MAP_ENTRY_COW | 1891 MAP_ENTRY_NEEDS_COPY; 1892 } 1893 if (revokeperms & VM_PROT_EXECUTE) { 1894 vme->max_protection &= ~VM_PROT_EXECUTE; 1895 vme->protection &= ~VM_PROT_EXECUTE; 1896 } 1897 if (revokeperms & VM_PROT_READ) { 1898 vme->max_protection = 0; 1899 vme->protection = 0; 1900 } 1901 pmap_protect(map->pmap, vme->start, vme->end, 1902 vme->protection & ~revokeperms); 1903 vm_map_simplify_entry(map, vme); 1904 } 1905 vm_map_lock_downgrade(map); 1906 } 1907 vm_map_unlock_read(map); 1908 } 1909 1910 /* 1911 * When the subject's label changes, it may require revocation of privilege 1912 * to mapped objects. This can't be done on-the-fly later with a unified 1913 * buffer cache. 1914 */ 1915 static void 1916 mac_relabel_cred(struct ucred *cred, struct label *newlabel) 1917 { 1918 1919 MAC_PERFORM(relabel_cred, cred, newlabel); 1920 } 1921 1922 void 1923 mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 1924 { 1925 1926 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 1927 } 1928 1929 void 1930 mac_create_ifnet(struct ifnet *ifnet) 1931 { 1932 1933 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 1934 } 1935 1936 void 1937 mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 1938 { 1939 1940 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 1941 } 1942 1943 void 1944 mac_create_socket(struct ucred *cred, struct socket *socket) 1945 { 1946 1947 MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 1948 } 1949 1950 void 1951 mac_create_pipe(struct ucred *cred, struct pipe *pipe) 1952 { 1953 1954 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 1955 } 1956 1957 void 1958 mac_create_socket_from_socket(struct socket *oldsocket, 1959 struct socket *newsocket) 1960 { 1961 1962 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 1963 newsocket, &newsocket->so_label); 1964 } 1965 1966 static void 1967 mac_relabel_socket(struct ucred *cred, struct socket *socket, 1968 struct label *newlabel) 1969 { 1970 1971 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 1972 } 1973 1974 static void 1975 mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 1976 { 1977 1978 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 1979 } 1980 1981 void 1982 mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 1983 { 1984 1985 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 1986 socket, &socket->so_peerlabel); 1987 } 1988 1989 void 1990 mac_set_socket_peer_from_socket(struct socket *oldsocket, 1991 struct socket *newsocket) 1992 { 1993 1994 MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 1995 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 1996 } 1997 1998 void 1999 mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 2000 { 2001 2002 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 2003 datagram, &datagram->m_pkthdr.label); 2004 } 2005 2006 void 2007 mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 2008 { 2009 2010 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 2011 fragment, &fragment->m_pkthdr.label); 2012 } 2013 2014 void 2015 mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 2016 { 2017 2018 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2019 &ipq->ipq_label); 2020 } 2021 2022 void 2023 mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2024 { 2025 2026 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 2027 newmbuf, &newmbuf->m_pkthdr.label); 2028 } 2029 2030 void 2031 mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 2032 { 2033 2034 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 2035 &mbuf->m_pkthdr.label); 2036 } 2037 2038 void 2039 mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 2040 { 2041 2042 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 2043 &mbuf->m_pkthdr.label); 2044 } 2045 2046 void 2047 mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 2048 { 2049 2050 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 2051 &mbuf->m_pkthdr.label); 2052 } 2053 2054 void 2055 mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 2056 struct mbuf *newmbuf) 2057 { 2058 2059 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 2060 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 2061 &newmbuf->m_pkthdr.label); 2062 } 2063 2064 void 2065 mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2066 { 2067 2068 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 2069 newmbuf, &newmbuf->m_pkthdr.label); 2070 } 2071 2072 int 2073 mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 2074 { 2075 int result; 2076 2077 result = 1; 2078 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 2079 ipq, &ipq->ipq_label); 2080 2081 return (result); 2082 } 2083 2084 void 2085 mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 2086 { 2087 2088 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2089 &ipq->ipq_label); 2090 } 2091 2092 void 2093 mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 2094 { 2095 2096 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 2097 &mbuf->m_pkthdr.label); 2098 } 2099 2100 void 2101 mac_create_mount(struct ucred *cred, struct mount *mp) 2102 { 2103 2104 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 2105 &mp->mnt_fslabel); 2106 } 2107 2108 void 2109 mac_create_root_mount(struct ucred *cred, struct mount *mp) 2110 { 2111 2112 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 2113 &mp->mnt_fslabel); 2114 } 2115 2116 int 2117 mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 2118 { 2119 int error; 2120 2121 if (!mac_enforce_network) 2122 return (0); 2123 2124 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 2125 &ifnet->if_label); 2126 2127 return (error); 2128 } 2129 2130 static int 2131 mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 2132 { 2133 int error; 2134 2135 MAC_CHECK(check_cred_relabel, cred, newlabel); 2136 2137 return (error); 2138 } 2139 2140 int 2141 mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 2142 { 2143 int error; 2144 2145 if (!mac_enforce_process) 2146 return (0); 2147 2148 MAC_CHECK(check_cred_visible, u1, u2); 2149 2150 return (error); 2151 } 2152 2153 int 2154 mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 2155 { 2156 int error; 2157 2158 if (!mac_enforce_network) 2159 return (0); 2160 2161 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 2162 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 2163 if_printf(ifnet, "not initialized\n"); 2164 2165 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 2166 &mbuf->m_pkthdr.label); 2167 2168 return (error); 2169 } 2170 2171 int 2172 mac_check_kenv_dump(struct ucred *cred) 2173 { 2174 int error; 2175 2176 if (!mac_enforce_system) 2177 return (0); 2178 2179 MAC_CHECK(check_kenv_dump, cred); 2180 2181 return (error); 2182 } 2183 2184 int 2185 mac_check_kenv_get(struct ucred *cred, char *name) 2186 { 2187 int error; 2188 2189 if (!mac_enforce_system) 2190 return (0); 2191 2192 MAC_CHECK(check_kenv_get, cred, name); 2193 2194 return (error); 2195 } 2196 2197 int 2198 mac_check_kenv_set(struct ucred *cred, char *name, char *value) 2199 { 2200 int error; 2201 2202 if (!mac_enforce_system) 2203 return (0); 2204 2205 MAC_CHECK(check_kenv_set, cred, name, value); 2206 2207 return (error); 2208 } 2209 2210 int 2211 mac_check_kenv_unset(struct ucred *cred, char *name) 2212 { 2213 int error; 2214 2215 if (!mac_enforce_system) 2216 return (0); 2217 2218 MAC_CHECK(check_kenv_unset, cred, name); 2219 2220 return (error); 2221 } 2222 2223 int 2224 mac_check_mount_stat(struct ucred *cred, struct mount *mount) 2225 { 2226 int error; 2227 2228 if (!mac_enforce_fs) 2229 return (0); 2230 2231 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 2232 2233 return (error); 2234 } 2235 2236 int 2237 mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 2238 void *data) 2239 { 2240 int error; 2241 2242 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2243 2244 if (!mac_enforce_pipe) 2245 return (0); 2246 2247 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 2248 2249 return (error); 2250 } 2251 2252 int 2253 mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 2254 { 2255 int error; 2256 2257 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2258 2259 if (!mac_enforce_pipe) 2260 return (0); 2261 2262 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2263 2264 return (error); 2265 } 2266 2267 int 2268 mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2269 { 2270 int error; 2271 2272 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2273 2274 if (!mac_enforce_pipe) 2275 return (0); 2276 2277 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 2278 2279 return (error); 2280 } 2281 2282 static int 2283 mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 2284 struct label *newlabel) 2285 { 2286 int error; 2287 2288 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2289 2290 if (!mac_enforce_pipe) 2291 return (0); 2292 2293 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 2294 2295 return (error); 2296 } 2297 2298 int 2299 mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2300 { 2301 int error; 2302 2303 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2304 2305 if (!mac_enforce_pipe) 2306 return (0); 2307 2308 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2309 2310 return (error); 2311 } 2312 2313 int 2314 mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2315 { 2316 int error; 2317 2318 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2319 2320 if (!mac_enforce_pipe) 2321 return (0); 2322 2323 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2324 2325 return (error); 2326 } 2327 2328 int 2329 mac_check_proc_debug(struct ucred *cred, struct proc *proc) 2330 { 2331 int error; 2332 2333 PROC_LOCK_ASSERT(proc, MA_OWNED); 2334 2335 if (!mac_enforce_process) 2336 return (0); 2337 2338 MAC_CHECK(check_proc_debug, cred, proc); 2339 2340 return (error); 2341 } 2342 2343 int 2344 mac_check_proc_sched(struct ucred *cred, struct proc *proc) 2345 { 2346 int error; 2347 2348 PROC_LOCK_ASSERT(proc, MA_OWNED); 2349 2350 if (!mac_enforce_process) 2351 return (0); 2352 2353 MAC_CHECK(check_proc_sched, cred, proc); 2354 2355 return (error); 2356 } 2357 2358 int 2359 mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 2360 { 2361 int error; 2362 2363 PROC_LOCK_ASSERT(proc, MA_OWNED); 2364 2365 if (!mac_enforce_process) 2366 return (0); 2367 2368 MAC_CHECK(check_proc_signal, cred, proc, signum); 2369 2370 return (error); 2371 } 2372 2373 int 2374 mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 2375 struct sockaddr *sockaddr) 2376 { 2377 int error; 2378 2379 if (!mac_enforce_socket) 2380 return (0); 2381 2382 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 2383 sockaddr); 2384 2385 return (error); 2386 } 2387 2388 int 2389 mac_check_socket_connect(struct ucred *cred, struct socket *socket, 2390 struct sockaddr *sockaddr) 2391 { 2392 int error; 2393 2394 if (!mac_enforce_socket) 2395 return (0); 2396 2397 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 2398 sockaddr); 2399 2400 return (error); 2401 } 2402 2403 int 2404 mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2405 { 2406 int error; 2407 2408 if (!mac_enforce_socket) 2409 return (0); 2410 2411 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2412 &mbuf->m_pkthdr.label); 2413 2414 return (error); 2415 } 2416 2417 int 2418 mac_check_socket_listen(struct ucred *cred, struct socket *socket) 2419 { 2420 int error; 2421 2422 if (!mac_enforce_socket) 2423 return (0); 2424 2425 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 2426 return (error); 2427 } 2428 2429 int 2430 mac_check_socket_receive(struct ucred *cred, struct socket *so) 2431 { 2432 int error; 2433 2434 if (!mac_enforce_socket) 2435 return (0); 2436 2437 MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2438 2439 return (error); 2440 } 2441 2442 static int 2443 mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 2444 struct label *newlabel) 2445 { 2446 int error; 2447 2448 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 2449 newlabel); 2450 2451 return (error); 2452 } 2453 2454 int 2455 mac_check_socket_send(struct ucred *cred, struct socket *so) 2456 { 2457 int error; 2458 2459 if (!mac_enforce_socket) 2460 return (0); 2461 2462 MAC_CHECK(check_socket_send, cred, so, &so->so_label); 2463 2464 return (error); 2465 } 2466 2467 int 2468 mac_check_socket_visible(struct ucred *cred, struct socket *socket) 2469 { 2470 int error; 2471 2472 if (!mac_enforce_socket) 2473 return (0); 2474 2475 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 2476 2477 return (error); 2478 } 2479 2480 int 2481 mac_check_system_acct(struct ucred *cred, struct vnode *vp) 2482 { 2483 int error; 2484 2485 if (vp != NULL) { 2486 ASSERT_VOP_LOCKED(vp, "mac_check_system_acct"); 2487 } 2488 2489 if (!mac_enforce_system) 2490 return (0); 2491 2492 MAC_CHECK(check_system_acct, cred, vp, 2493 vp != NULL ? &vp->v_label : NULL); 2494 2495 return (error); 2496 } 2497 2498 int 2499 mac_check_system_nfsd(struct ucred *cred) 2500 { 2501 int error; 2502 2503 if (!mac_enforce_system) 2504 return (0); 2505 2506 MAC_CHECK(check_system_nfsd, cred); 2507 2508 return (error); 2509 } 2510 2511 int 2512 mac_check_system_reboot(struct ucred *cred, int howto) 2513 { 2514 int error; 2515 2516 if (!mac_enforce_system) 2517 return (0); 2518 2519 MAC_CHECK(check_system_reboot, cred, howto); 2520 2521 return (error); 2522 } 2523 2524 int 2525 mac_check_system_settime(struct ucred *cred) 2526 { 2527 int error; 2528 2529 if (!mac_enforce_system) 2530 return (0); 2531 2532 MAC_CHECK(check_system_settime, cred); 2533 2534 return (error); 2535 } 2536 2537 int 2538 mac_check_system_swapon(struct ucred *cred, struct vnode *vp) 2539 { 2540 int error; 2541 2542 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 2543 2544 if (!mac_enforce_system) 2545 return (0); 2546 2547 MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 2548 return (error); 2549 } 2550 2551 int 2552 mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 2553 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 2554 { 2555 int error; 2556 2557 /* 2558 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here, 2559 * but since it's not exported from kern_sysctl.c, we can't. 2560 */ 2561 if (!mac_enforce_system) 2562 return (0); 2563 2564 MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp, 2565 inkernel, new, newlen); 2566 2567 return (error); 2568 } 2569 2570 int 2571 mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 2572 struct ifnet *ifnet) 2573 { 2574 char *elements, *buffer; 2575 struct mac mac; 2576 int error; 2577 2578 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 2579 if (error) 2580 return (error); 2581 2582 error = mac_check_structmac_consistent(&mac); 2583 if (error) 2584 return (error); 2585 2586 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2587 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2588 if (error) { 2589 free(elements, M_MACTEMP); 2590 return (error); 2591 } 2592 2593 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2594 error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 2595 buffer, mac.m_buflen, M_WAITOK); 2596 if (error == 0) 2597 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2598 2599 free(buffer, M_MACTEMP); 2600 free(elements, M_MACTEMP); 2601 2602 return (error); 2603 } 2604 2605 int 2606 mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 2607 struct ifnet *ifnet) 2608 { 2609 struct label intlabel; 2610 struct mac mac; 2611 char *buffer; 2612 int error; 2613 2614 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 2615 if (error) 2616 return (error); 2617 2618 error = mac_check_structmac_consistent(&mac); 2619 if (error) 2620 return (error); 2621 2622 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2623 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 2624 if (error) { 2625 free(buffer, M_MACTEMP); 2626 return (error); 2627 } 2628 2629 mac_init_ifnet_label(&intlabel); 2630 error = mac_internalize_ifnet_label(&intlabel, buffer); 2631 free(buffer, M_MACTEMP); 2632 if (error) { 2633 mac_destroy_ifnet_label(&intlabel); 2634 return (error); 2635 } 2636 2637 /* 2638 * XXX: Note that this is a redundant privilege check, since 2639 * policies impose this check themselves if required by the 2640 * policy. Eventually, this should go away. 2641 */ 2642 error = suser_cred(cred, 0); 2643 if (error) { 2644 mac_destroy_ifnet_label(&intlabel); 2645 return (error); 2646 } 2647 2648 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 2649 &intlabel); 2650 if (error) { 2651 mac_destroy_ifnet_label(&intlabel); 2652 return (error); 2653 } 2654 2655 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 2656 2657 mac_destroy_ifnet_label(&intlabel); 2658 return (0); 2659 } 2660 2661 void 2662 mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp) 2663 { 2664 2665 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 2666 } 2667 2668 void 2669 mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 2670 { 2671 2672 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 2673 } 2674 2675 void 2676 mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 2677 struct devfs_dirent *de) 2678 { 2679 2680 MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de, 2681 &de->de_label); 2682 } 2683 2684 void 2685 mac_create_devfs_directory(char *dirname, int dirnamelen, 2686 struct devfs_dirent *de) 2687 { 2688 2689 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 2690 &de->de_label); 2691 } 2692 2693 int 2694 mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 2695 struct mac *mac) 2696 { 2697 struct label intlabel; 2698 char *buffer; 2699 int error; 2700 2701 error = mac_check_structmac_consistent(mac); 2702 if (error) 2703 return (error); 2704 2705 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2706 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 2707 if (error) { 2708 free(buffer, M_MACTEMP); 2709 return (error); 2710 } 2711 2712 mac_init_socket_label(&intlabel, M_WAITOK); 2713 error = mac_internalize_socket_label(&intlabel, buffer); 2714 free(buffer, M_MACTEMP); 2715 if (error) { 2716 mac_destroy_socket_label(&intlabel); 2717 return (error); 2718 } 2719 2720 mac_check_socket_relabel(cred, so, &intlabel); 2721 if (error) { 2722 mac_destroy_socket_label(&intlabel); 2723 return (error); 2724 } 2725 2726 mac_relabel_socket(cred, so, &intlabel); 2727 2728 mac_destroy_socket_label(&intlabel); 2729 return (0); 2730 } 2731 2732 int 2733 mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 2734 { 2735 int error; 2736 2737 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2738 2739 error = mac_check_pipe_relabel(cred, pipe, label); 2740 if (error) 2741 return (error); 2742 2743 mac_relabel_pipe(cred, pipe, label); 2744 2745 return (0); 2746 } 2747 2748 int 2749 mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 2750 struct mac *mac) 2751 { 2752 char *buffer, *elements; 2753 int error; 2754 2755 error = mac_check_structmac_consistent(mac); 2756 if (error) 2757 return (error); 2758 2759 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2760 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2761 if (error) { 2762 free(elements, M_MACTEMP); 2763 return (error); 2764 } 2765 2766 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2767 error = mac_externalize_socket_label(&so->so_label, elements, 2768 buffer, mac->m_buflen, M_WAITOK); 2769 if (error == 0) 2770 error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2771 2772 free(buffer, M_MACTEMP); 2773 free(elements, M_MACTEMP); 2774 2775 return (error); 2776 } 2777 2778 int 2779 mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 2780 struct mac *mac) 2781 { 2782 char *elements, *buffer; 2783 int error; 2784 2785 error = mac_check_structmac_consistent(mac); 2786 if (error) 2787 return (error); 2788 2789 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2790 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2791 if (error) { 2792 free(elements, M_MACTEMP); 2793 return (error); 2794 } 2795 2796 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2797 error = mac_externalize_socket_peer_label(&so->so_peerlabel, 2798 elements, buffer, mac->m_buflen, M_WAITOK); 2799 if (error == 0) 2800 error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2801 2802 free(buffer, M_MACTEMP); 2803 free(elements, M_MACTEMP); 2804 2805 return (error); 2806 } 2807 2808 /* 2809 * Implementation of VOP_SETLABEL() that relies on extended attributes 2810 * to store label data. Can be referenced by filesystems supporting 2811 * extended attributes. 2812 */ 2813 int 2814 vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 2815 { 2816 struct vnode *vp = ap->a_vp; 2817 struct label *intlabel = ap->a_label; 2818 int error; 2819 2820 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 2821 2822 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2823 return (EOPNOTSUPP); 2824 2825 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 2826 if (error) 2827 return (error); 2828 2829 mac_relabel_vnode(ap->a_cred, vp, intlabel); 2830 2831 return (0); 2832 } 2833 2834 static int 2835 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 2836 { 2837 int error; 2838 2839 if (vp->v_mount == NULL) { 2840 /* printf("vn_setlabel: null v_mount\n"); */ 2841 if (vp->v_type != VNON) 2842 printf("vn_setlabel: null v_mount with non-VNON\n"); 2843 return (EBADF); 2844 } 2845 2846 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2847 return (EOPNOTSUPP); 2848 2849 /* 2850 * Multi-phase commit. First check the policies to confirm the 2851 * change is OK. Then commit via the filesystem. Finally, 2852 * update the actual vnode label. Question: maybe the filesystem 2853 * should update the vnode at the end as part of VOP_SETLABEL()? 2854 */ 2855 error = mac_check_vnode_relabel(cred, vp, intlabel); 2856 if (error) 2857 return (error); 2858 2859 /* 2860 * VADMIN provides the opportunity for the filesystem to make 2861 * decisions about who is and is not able to modify labels 2862 * and protections on files. This might not be right. We can't 2863 * assume VOP_SETLABEL() will do it, because we might implement 2864 * that as part of vop_stdsetlabel_ea(). 2865 */ 2866 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 2867 if (error) 2868 return (error); 2869 2870 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 2871 if (error) 2872 return (error); 2873 2874 return (0); 2875 } 2876 2877 int 2878 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 2879 { 2880 char *elements, *buffer; 2881 struct mac mac; 2882 struct proc *tproc; 2883 struct ucred *tcred; 2884 int error; 2885 2886 error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac)); 2887 if (error) 2888 return (error); 2889 2890 error = mac_check_structmac_consistent(&mac); 2891 if (error) 2892 return (error); 2893 2894 tproc = pfind(uap->pid); 2895 if (tproc == NULL) 2896 return (ESRCH); 2897 2898 tcred = NULL; /* Satisfy gcc. */ 2899 error = p_cansee(td, tproc); 2900 if (error == 0) 2901 tcred = crhold(tproc->p_ucred); 2902 PROC_UNLOCK(tproc); 2903 if (error) 2904 return (error); 2905 2906 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2907 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2908 if (error) { 2909 free(elements, M_MACTEMP); 2910 crfree(tcred); 2911 return (error); 2912 } 2913 2914 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2915 error = mac_externalize_cred_label(&tcred->cr_label, elements, 2916 buffer, mac.m_buflen, M_WAITOK); 2917 if (error == 0) 2918 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2919 2920 free(buffer, M_MACTEMP); 2921 free(elements, M_MACTEMP); 2922 crfree(tcred); 2923 return (error); 2924 } 2925 2926 /* 2927 * MPSAFE 2928 */ 2929 int 2930 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 2931 { 2932 char *elements, *buffer; 2933 struct mac mac; 2934 int error; 2935 2936 error = copyin(uap->mac_p, &mac, sizeof(mac)); 2937 if (error) 2938 return (error); 2939 2940 error = mac_check_structmac_consistent(&mac); 2941 if (error) 2942 return (error); 2943 2944 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2945 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2946 if (error) { 2947 free(elements, M_MACTEMP); 2948 return (error); 2949 } 2950 2951 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2952 error = mac_externalize_cred_label(&td->td_ucred->cr_label, 2953 elements, buffer, mac.m_buflen, M_WAITOK); 2954 if (error == 0) 2955 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2956 2957 free(buffer, M_MACTEMP); 2958 free(elements, M_MACTEMP); 2959 return (error); 2960 } 2961 2962 /* 2963 * MPSAFE 2964 */ 2965 int 2966 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 2967 { 2968 struct ucred *newcred, *oldcred; 2969 struct label intlabel; 2970 struct proc *p; 2971 struct mac mac; 2972 char *buffer; 2973 int error; 2974 2975 error = copyin(uap->mac_p, &mac, sizeof(mac)); 2976 if (error) 2977 return (error); 2978 2979 error = mac_check_structmac_consistent(&mac); 2980 if (error) 2981 return (error); 2982 2983 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2984 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 2985 if (error) { 2986 free(buffer, M_MACTEMP); 2987 return (error); 2988 } 2989 2990 mac_init_cred_label(&intlabel); 2991 error = mac_internalize_cred_label(&intlabel, buffer); 2992 free(buffer, M_MACTEMP); 2993 if (error) { 2994 mac_destroy_cred_label(&intlabel); 2995 return (error); 2996 } 2997 2998 newcred = crget(); 2999 3000 p = td->td_proc; 3001 PROC_LOCK(p); 3002 oldcred = p->p_ucred; 3003 3004 error = mac_check_cred_relabel(oldcred, &intlabel); 3005 if (error) { 3006 PROC_UNLOCK(p); 3007 crfree(newcred); 3008 goto out; 3009 } 3010 3011 setsugid(p); 3012 crcopy(newcred, oldcred); 3013 mac_relabel_cred(newcred, &intlabel); 3014 p->p_ucred = newcred; 3015 3016 /* 3017 * Grab additional reference for use while revoking mmaps, prior 3018 * to releasing the proc lock and sharing the cred. 3019 */ 3020 crhold(newcred); 3021 PROC_UNLOCK(p); 3022 3023 if (mac_enforce_vm) { 3024 mtx_lock(&Giant); 3025 mac_cred_mmapped_drop_perms(td, newcred); 3026 mtx_unlock(&Giant); 3027 } 3028 3029 crfree(newcred); /* Free revocation reference. */ 3030 crfree(oldcred); 3031 3032 out: 3033 mac_destroy_cred_label(&intlabel); 3034 return (error); 3035 } 3036 3037 /* 3038 * MPSAFE 3039 */ 3040 int 3041 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3042 { 3043 char *elements, *buffer; 3044 struct label intlabel; 3045 struct file *fp; 3046 struct mac mac; 3047 struct vnode *vp; 3048 struct pipe *pipe; 3049 short label_type; 3050 int error; 3051 3052 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3053 if (error) 3054 return (error); 3055 3056 error = mac_check_structmac_consistent(&mac); 3057 if (error) 3058 return (error); 3059 3060 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3061 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3062 if (error) { 3063 free(elements, M_MACTEMP); 3064 return (error); 3065 } 3066 3067 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3068 mtx_lock(&Giant); /* VFS */ 3069 error = fget(td, SCARG(uap, fd), &fp); 3070 if (error) 3071 goto out; 3072 3073 label_type = fp->f_type; 3074 switch (fp->f_type) { 3075 case DTYPE_FIFO: 3076 case DTYPE_VNODE: 3077 vp = (struct vnode *)fp->f_data; 3078 3079 mac_init_vnode_label(&intlabel); 3080 3081 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3082 mac_copy_vnode_label(&vp->v_label, &intlabel); 3083 VOP_UNLOCK(vp, 0, td); 3084 3085 break; 3086 case DTYPE_PIPE: 3087 pipe = (struct pipe *)fp->f_data; 3088 3089 mac_init_pipe_label(&intlabel); 3090 3091 PIPE_LOCK(pipe); 3092 mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3093 PIPE_UNLOCK(pipe); 3094 break; 3095 default: 3096 error = EINVAL; 3097 fdrop(fp, td); 3098 goto out; 3099 } 3100 fdrop(fp, td); 3101 3102 switch (label_type) { 3103 case DTYPE_FIFO: 3104 case DTYPE_VNODE: 3105 if (error == 0) 3106 error = mac_externalize_vnode_label(&intlabel, 3107 elements, buffer, mac.m_buflen, M_WAITOK); 3108 mac_destroy_vnode_label(&intlabel); 3109 break; 3110 case DTYPE_PIPE: 3111 error = mac_externalize_pipe_label(&intlabel, elements, 3112 buffer, mac.m_buflen, M_WAITOK); 3113 mac_destroy_pipe_label(&intlabel); 3114 break; 3115 default: 3116 panic("__mac_get_fd: corrupted label_type"); 3117 } 3118 3119 if (error == 0) 3120 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3121 3122 out: 3123 mtx_unlock(&Giant); /* VFS */ 3124 free(buffer, M_MACTEMP); 3125 free(elements, M_MACTEMP); 3126 3127 return (error); 3128 } 3129 3130 /* 3131 * MPSAFE 3132 */ 3133 int 3134 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3135 { 3136 char *elements, *buffer; 3137 struct nameidata nd; 3138 struct label intlabel; 3139 struct mac mac; 3140 int error; 3141 3142 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3143 if (error) 3144 return (error); 3145 3146 error = mac_check_structmac_consistent(&mac); 3147 if (error) 3148 return (error); 3149 3150 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3151 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3152 if (error) { 3153 free(elements, M_MACTEMP); 3154 return (error); 3155 } 3156 3157 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3158 mtx_lock(&Giant); /* VFS */ 3159 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3160 td); 3161 error = namei(&nd); 3162 if (error) 3163 goto out; 3164 3165 mac_init_vnode_label(&intlabel); 3166 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3167 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3168 mac.m_buflen, M_WAITOK); 3169 3170 NDFREE(&nd, 0); 3171 mac_destroy_vnode_label(&intlabel); 3172 3173 if (error == 0) 3174 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3175 3176 out: 3177 mtx_unlock(&Giant); /* VFS */ 3178 3179 free(buffer, M_MACTEMP); 3180 free(elements, M_MACTEMP); 3181 3182 return (error); 3183 } 3184 3185 /* 3186 * MPSAFE 3187 */ 3188 int 3189 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3190 { 3191 char *elements, *buffer; 3192 struct nameidata nd; 3193 struct label intlabel; 3194 struct mac mac; 3195 int error; 3196 3197 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3198 if (error) 3199 return (error); 3200 3201 error = mac_check_structmac_consistent(&mac); 3202 if (error) 3203 return (error); 3204 3205 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3206 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3207 if (error) { 3208 free(elements, M_MACTEMP); 3209 return (error); 3210 } 3211 3212 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3213 mtx_lock(&Giant); /* VFS */ 3214 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3215 td); 3216 error = namei(&nd); 3217 if (error) 3218 goto out; 3219 3220 mac_init_vnode_label(&intlabel); 3221 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3222 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3223 mac.m_buflen, M_WAITOK); 3224 NDFREE(&nd, 0); 3225 mac_destroy_vnode_label(&intlabel); 3226 3227 if (error == 0) 3228 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3229 3230 out: 3231 mtx_unlock(&Giant); /* VFS */ 3232 3233 free(buffer, M_MACTEMP); 3234 free(elements, M_MACTEMP); 3235 3236 return (error); 3237 } 3238 3239 /* 3240 * MPSAFE 3241 */ 3242 int 3243 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3244 { 3245 struct label intlabel; 3246 struct pipe *pipe; 3247 struct file *fp; 3248 struct mount *mp; 3249 struct vnode *vp; 3250 struct mac mac; 3251 char *buffer; 3252 int error; 3253 3254 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3255 if (error) 3256 return (error); 3257 3258 error = mac_check_structmac_consistent(&mac); 3259 if (error) 3260 return (error); 3261 3262 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3263 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3264 if (error) { 3265 free(buffer, M_MACTEMP); 3266 return (error); 3267 } 3268 3269 mtx_lock(&Giant); /* VFS */ 3270 3271 error = fget(td, SCARG(uap, fd), &fp); 3272 if (error) 3273 goto out; 3274 3275 switch (fp->f_type) { 3276 case DTYPE_FIFO: 3277 case DTYPE_VNODE: 3278 mac_init_vnode_label(&intlabel); 3279 error = mac_internalize_vnode_label(&intlabel, buffer); 3280 if (error) { 3281 mac_destroy_vnode_label(&intlabel); 3282 break; 3283 } 3284 3285 vp = (struct vnode *)fp->f_data; 3286 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3287 if (error != 0) { 3288 mac_destroy_vnode_label(&intlabel); 3289 break; 3290 } 3291 3292 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3293 error = vn_setlabel(vp, &intlabel, td->td_ucred); 3294 VOP_UNLOCK(vp, 0, td); 3295 vn_finished_write(mp); 3296 3297 mac_destroy_vnode_label(&intlabel); 3298 break; 3299 3300 case DTYPE_PIPE: 3301 mac_init_pipe_label(&intlabel); 3302 error = mac_internalize_pipe_label(&intlabel, buffer); 3303 if (error == 0) { 3304 pipe = (struct pipe *)fp->f_data; 3305 PIPE_LOCK(pipe); 3306 error = mac_pipe_label_set(td->td_ucred, pipe, 3307 &intlabel); 3308 PIPE_UNLOCK(pipe); 3309 } 3310 3311 mac_destroy_pipe_label(&intlabel); 3312 break; 3313 3314 default: 3315 error = EINVAL; 3316 } 3317 3318 fdrop(fp, td); 3319 out: 3320 mtx_unlock(&Giant); /* VFS */ 3321 3322 free(buffer, M_MACTEMP); 3323 3324 return (error); 3325 } 3326 3327 /* 3328 * MPSAFE 3329 */ 3330 int 3331 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3332 { 3333 struct label intlabel; 3334 struct nameidata nd; 3335 struct mount *mp; 3336 struct mac mac; 3337 char *buffer; 3338 int error; 3339 3340 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3341 if (error) 3342 return (error); 3343 3344 error = mac_check_structmac_consistent(&mac); 3345 if (error) 3346 return (error); 3347 3348 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3349 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3350 if (error) { 3351 free(buffer, M_MACTEMP); 3352 return (error); 3353 } 3354 3355 mac_init_vnode_label(&intlabel); 3356 error = mac_internalize_vnode_label(&intlabel, buffer); 3357 free(buffer, M_MACTEMP); 3358 if (error) { 3359 mac_destroy_vnode_label(&intlabel); 3360 return (error); 3361 } 3362 3363 mtx_lock(&Giant); /* VFS */ 3364 3365 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3366 td); 3367 error = namei(&nd); 3368 if (error == 0) { 3369 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3370 if (error == 0) 3371 error = vn_setlabel(nd.ni_vp, &intlabel, 3372 td->td_ucred); 3373 vn_finished_write(mp); 3374 } 3375 3376 NDFREE(&nd, 0); 3377 mtx_unlock(&Giant); /* VFS */ 3378 mac_destroy_vnode_label(&intlabel); 3379 3380 return (error); 3381 } 3382 3383 /* 3384 * MPSAFE 3385 */ 3386 int 3387 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3388 { 3389 struct label intlabel; 3390 struct nameidata nd; 3391 struct mount *mp; 3392 struct mac mac; 3393 char *buffer; 3394 int error; 3395 3396 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3397 if (error) 3398 return (error); 3399 3400 error = mac_check_structmac_consistent(&mac); 3401 if (error) 3402 return (error); 3403 3404 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3405 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3406 if (error) { 3407 free(buffer, M_MACTEMP); 3408 return (error); 3409 } 3410 3411 mac_init_vnode_label(&intlabel); 3412 error = mac_internalize_vnode_label(&intlabel, buffer); 3413 free(buffer, M_MACTEMP); 3414 if (error) { 3415 mac_destroy_vnode_label(&intlabel); 3416 return (error); 3417 } 3418 3419 mtx_lock(&Giant); /* VFS */ 3420 3421 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3422 td); 3423 error = namei(&nd); 3424 if (error == 0) { 3425 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3426 if (error == 0) 3427 error = vn_setlabel(nd.ni_vp, &intlabel, 3428 td->td_ucred); 3429 vn_finished_write(mp); 3430 } 3431 3432 NDFREE(&nd, 0); 3433 mtx_unlock(&Giant); /* VFS */ 3434 mac_destroy_vnode_label(&intlabel); 3435 3436 return (error); 3437 } 3438 3439 /* 3440 * MPSAFE 3441 */ 3442 int 3443 mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3444 { 3445 struct mac_policy_conf *mpc; 3446 char target[MAC_MAX_POLICY_NAME]; 3447 int error; 3448 3449 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL); 3450 if (error) 3451 return (error); 3452 3453 error = ENOSYS; 3454 MAC_POLICY_LIST_BUSY(); 3455 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 3456 if (strcmp(mpc->mpc_name, target) == 0 && 3457 mpc->mpc_ops->mpo_syscall != NULL) { 3458 error = mpc->mpc_ops->mpo_syscall(td, 3459 SCARG(uap, call), SCARG(uap, arg)); 3460 goto out; 3461 } 3462 } 3463 3464 out: 3465 MAC_POLICY_LIST_UNBUSY(); 3466 return (error); 3467 } 3468 3469 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 3470 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 3471 3472 #else /* !MAC */ 3473 3474 int 3475 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3476 { 3477 3478 return (ENOSYS); 3479 } 3480 3481 int 3482 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3483 { 3484 3485 return (ENOSYS); 3486 } 3487 3488 int 3489 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3490 { 3491 3492 return (ENOSYS); 3493 } 3494 3495 int 3496 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3497 { 3498 3499 return (ENOSYS); 3500 } 3501 3502 int 3503 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3504 { 3505 3506 return (ENOSYS); 3507 } 3508 3509 int 3510 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3511 { 3512 3513 return (ENOSYS); 3514 } 3515 3516 int 3517 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3518 { 3519 3520 return (ENOSYS); 3521 } 3522 3523 int 3524 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3525 { 3526 3527 return (ENOSYS); 3528 } 3529 3530 int 3531 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3532 { 3533 3534 return (ENOSYS); 3535 } 3536 3537 int 3538 mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3539 { 3540 3541 return (ENOSYS); 3542 } 3543 3544 #endif 3545