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