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