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