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