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