mac_system.c revision 102112
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_system.c 102112 2002-08-19 16:43:25Z 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 50#include <sys/param.h> 51#include <sys/extattr.h> 52#include <sys/kernel.h> 53#include <sys/lock.h> 54#include <sys/mutex.h> 55#include <sys/sx.h> 56#include <sys/mac.h> 57#include <sys/module.h> 58#include <sys/proc.h> 59#include <sys/systm.h> 60#include <sys/sysproto.h> 61#include <sys/sysent.h> 62#include <sys/vnode.h> 63#include <sys/mount.h> 64#include <sys/file.h> 65#include <sys/namei.h> 66#include <sys/socket.h> 67#include <sys/pipe.h> 68#include <sys/socketvar.h> 69#include <sys/sx.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/bpf.h> 82#include <net/bpfdesc.h> 83#include <net/if.h> 84#include <net/if_var.h> 85 86#include <netinet/in.h> 87#include <netinet/ip_var.h> 88 89#ifdef MAC 90 91/* 92 * Declare that the kernel provides MAC support, version 1. This permits 93 * modules to refuse to be loaded if the necessary support isn't present, 94 * even if it's pre-boot. 95 */ 96MODULE_VERSION(kernel_mac_support, 1); 97 98SYSCTL_DECL(_security); 99 100SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 101 "TrustedBSD MAC policy controls"); 102SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 103 "TrustedBSD MAC debug info"); 104 105static int mac_debug_label_fallback = 0; 106SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 107 &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 108 "when label is corrupted."); 109TUNABLE_INT("security.mac.debug_label_fallback", 110 &mac_debug_label_fallback); 111 112#ifndef MAC_MAX_POLICIES 113#define MAC_MAX_POLICIES 8 114#endif 115#if MAC_MAX_POLICIES > 32 116#error "MAC_MAX_POLICIES too large" 117#endif 118static unsigned int mac_max_policies = MAC_MAX_POLICIES; 119static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1; 120SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, 121 &mac_max_policies, 0, ""); 122 123static int mac_late = 0; 124 125static int mac_enforce_fs = 1; 126SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 127 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 128TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 129 130static int mac_enforce_network = 1; 131SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 132 &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 133TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 134 135static int mac_enforce_process = 1; 136SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 137 &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 138TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 139 140static int mac_enforce_socket = 1; 141SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 142 &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 143TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 144 145static int mac_enforce_pipe = 1; 146SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 147 &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 148 149static int mac_label_size = sizeof(struct mac); 150SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, 151 &mac_label_size, 0, "Pre-compiled MAC label size"); 152 153static int mac_cache_fslabel_in_vnode = 1; 154SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, 155 &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); 156TUNABLE_INT("security.mac.cache_fslabel_in_vnode", 157 &mac_cache_fslabel_in_vnode); 158 159static int mac_vnode_label_cache_hits = 0; 160SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, 161 &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); 162static int mac_vnode_label_cache_misses = 0; 163SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, 164 &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); 165static int mac_mmap_revocation_via_cow = 0; 166SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 167 &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 168 "copy-on-write semantics, or by removing all write access"); 169 170#ifdef MAC_DEBUG 171static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 172 nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 173 nmacipqs, nmacpipes; 174SYSCTL_UINT(_security_mac_debug, OID_AUTO, mbufs, CTLFLAG_RD, 175 &nmacmbufs, 0, "number of mbufs in use"); 176SYSCTL_UINT(_security_mac_debug, OID_AUTO, creds, CTLFLAG_RD, 177 &nmaccreds, 0, "number of ucreds in use"); 178SYSCTL_UINT(_security_mac_debug, OID_AUTO, ifnets, CTLFLAG_RD, 179 &nmacifnets, 0, "number of ifnets in use"); 180SYSCTL_UINT(_security_mac_debug, OID_AUTO, ipqs, CTLFLAG_RD, 181 &nmacipqs, 0, "number of ipqs in use"); 182SYSCTL_UINT(_security_mac_debug, OID_AUTO, bpfdescs, CTLFLAG_RD, 183 &nmacbpfdescs, 0, "number of bpfdescs in use"); 184SYSCTL_UINT(_security_mac_debug, OID_AUTO, sockets, CTLFLAG_RD, 185 &nmacsockets, 0, "number of sockets in use"); 186SYSCTL_UINT(_security_mac_debug, OID_AUTO, pipes, CTLFLAG_RD, 187 &nmacpipes, 0, "number of pipes in use"); 188SYSCTL_UINT(_security_mac_debug, OID_AUTO, mounts, CTLFLAG_RD, 189 &nmacmounts, 0, "number of mounts in use"); 190SYSCTL_UINT(_security_mac_debug, OID_AUTO, temp, CTLFLAG_RD, 191 &nmactemp, 0, "number of temporary labels in use"); 192SYSCTL_UINT(_security_mac_debug, OID_AUTO, vnodes, CTLFLAG_RD, 193 &nmacvnodes, 0, "number of vnodes in use"); 194SYSCTL_UINT(_security_mac_debug, OID_AUTO, devfsdirents, CTLFLAG_RD, 195 &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 196#endif 197 198static int error_select(int error1, int error2); 199static int mac_externalize(struct label *label, struct mac *mac); 200static int mac_policy_register(struct mac_policy_conf *mpc); 201static int mac_policy_unregister(struct mac_policy_conf *mpc); 202 203static int mac_stdcreatevnode_ea(struct vnode *vp); 204static void mac_cred_mmapped_drop_perms(struct thread *td, 205 struct ucred *cred); 206static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 207 struct ucred *cred, struct vm_map *map); 208 209MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); 210MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 211 212/* 213 * mac_policy_list_lock protects the consistency of 'mac_policy_list', 214 * the linked list of attached policy modules. Read-only consumers of 215 * the list must acquire a shared lock for the duration of their use; 216 * writers must acquire an exclusive lock. Note that for compound 217 * operations, locks should be held for the entire compound operation, 218 * and that this is not yet done for relabel requests. 219 */ 220static struct mtx mac_policy_list_lock; 221static LIST_HEAD(, mac_policy_conf) mac_policy_list; 222static int mac_policy_list_busy; 223#define MAC_POLICY_LIST_LOCKINIT() mtx_init(&mac_policy_list_lock, \ 224 "mac_policy_list_lock", NULL, MTX_DEF); 225#define MAC_POLICY_LIST_LOCK() mtx_lock(&mac_policy_list_lock); 226#define MAC_POLICY_LIST_UNLOCK() mtx_unlock(&mac_policy_list_lock); 227 228#define MAC_POLICY_LIST_BUSY() do { \ 229 MAC_POLICY_LIST_LOCK(); \ 230 mac_policy_list_busy++; \ 231 MAC_POLICY_LIST_UNLOCK(); \ 232} while (0) 233 234#define MAC_POLICY_LIST_UNBUSY() do { \ 235 MAC_POLICY_LIST_LOCK(); \ 236 mac_policy_list_busy--; \ 237 if (mac_policy_list_busy < 0) \ 238 panic("Extra mac_policy_list_busy--"); \ 239 MAC_POLICY_LIST_UNLOCK(); \ 240} while (0) 241 242/* 243 * MAC_CHECK performs the designated check by walking the policy 244 * module list and checking with each as to how it feels about the 245 * request. Note that it returns its value via 'error' in the scope 246 * of the caller. 247 */ 248#define MAC_CHECK(check, args...) do { \ 249 struct mac_policy_conf *mpc; \ 250 \ 251 error = 0; \ 252 MAC_POLICY_LIST_BUSY(); \ 253 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 254 if (mpc->mpc_ops->mpo_ ## check != NULL) \ 255 error = error_select( \ 256 mpc->mpc_ops->mpo_ ## check (args), \ 257 error); \ 258 } \ 259 MAC_POLICY_LIST_UNBUSY(); \ 260} while (0) 261 262/* 263 * MAC_BOOLEAN performs the designated boolean composition by walking 264 * the module list, invoking each instance of the operation, and 265 * combining the results using the passed C operator. Note that it 266 * returns its value via 'result' in the scope of the caller, which 267 * should be initialized by the caller in a meaningful way to get 268 * a meaningful result. 269 */ 270#define MAC_BOOLEAN(operation, composition, args...) do { \ 271 struct mac_policy_conf *mpc; \ 272 \ 273 MAC_POLICY_LIST_BUSY(); \ 274 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 275 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 276 result = result composition \ 277 mpc->mpc_ops->mpo_ ## operation (args); \ 278 } \ 279 MAC_POLICY_LIST_UNBUSY(); \ 280} while (0) 281 282/* 283 * MAC_PERFORM performs the designated operation by walking the policy 284 * module list and invoking that operation for each policy. 285 */ 286#define MAC_PERFORM(operation, args...) do { \ 287 struct mac_policy_conf *mpc; \ 288 \ 289 MAC_POLICY_LIST_BUSY(); \ 290 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 291 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 292 mpc->mpc_ops->mpo_ ## operation (args); \ 293 } \ 294 MAC_POLICY_LIST_UNBUSY(); \ 295} while (0) 296 297/* 298 * Initialize the MAC subsystem, including appropriate SMP locks. 299 */ 300static void 301mac_init(void) 302{ 303 304 LIST_INIT(&mac_policy_list); 305 MAC_POLICY_LIST_LOCKINIT(); 306} 307 308/* 309 * For the purposes of modules that want to know if they were loaded 310 * "early", set the mac_late flag once we've processed modules either 311 * linked into the kernel, or loaded before the kernel startup. 312 */ 313static void 314mac_late_init(void) 315{ 316 317 mac_late = 1; 318} 319 320/* 321 * Allow MAC policy modules to register during boot, etc. 322 */ 323int 324mac_policy_modevent(module_t mod, int type, void *data) 325{ 326 struct mac_policy_conf *mpc; 327 int error; 328 329 error = 0; 330 mpc = (struct mac_policy_conf *) data; 331 332 switch (type) { 333 case MOD_LOAD: 334 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 335 mac_late) { 336 printf("mac_policy_modevent: can't load %s policy " 337 "after booting\n", mpc->mpc_name); 338 error = EBUSY; 339 break; 340 } 341 error = mac_policy_register(mpc); 342 break; 343 case MOD_UNLOAD: 344 /* Don't unregister the module if it was never registered. */ 345 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 346 != 0) 347 error = mac_policy_unregister(mpc); 348 else 349 error = 0; 350 break; 351 default: 352 break; 353 } 354 355 return (error); 356} 357 358static int 359mac_policy_register(struct mac_policy_conf *mpc) 360{ 361 struct mac_policy_conf *tmpc; 362 struct mac_policy_ops *ops; 363 struct mac_policy_op_entry *mpe; 364 int slot; 365 366 MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*ops), M_MACOPVEC, 367 M_WAITOK | M_ZERO); 368 for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) { 369 switch (mpe->mpe_constant) { 370 case MAC_OP_LAST: 371 /* 372 * Doesn't actually happen, but this allows checking 373 * that all enumerated values are handled. 374 */ 375 break; 376 case MAC_DESTROY: 377 mpc->mpc_ops->mpo_destroy = 378 mpe->mpe_function; 379 break; 380 case MAC_INIT: 381 mpc->mpc_ops->mpo_init = 382 mpe->mpe_function; 383 break; 384 case MAC_INIT_BPFDESC: 385 mpc->mpc_ops->mpo_init_bpfdesc = 386 mpe->mpe_function; 387 break; 388 case MAC_INIT_CRED: 389 mpc->mpc_ops->mpo_init_cred = 390 mpe->mpe_function; 391 break; 392 case MAC_INIT_DEVFSDIRENT: 393 mpc->mpc_ops->mpo_init_devfsdirent = 394 mpe->mpe_function; 395 break; 396 case MAC_INIT_IFNET: 397 mpc->mpc_ops->mpo_init_ifnet = 398 mpe->mpe_function; 399 break; 400 case MAC_INIT_IPQ: 401 mpc->mpc_ops->mpo_init_ipq = 402 mpe->mpe_function; 403 break; 404 case MAC_INIT_MBUF: 405 mpc->mpc_ops->mpo_init_mbuf = 406 mpe->mpe_function; 407 break; 408 case MAC_INIT_MOUNT: 409 mpc->mpc_ops->mpo_init_mount = 410 mpe->mpe_function; 411 break; 412 case MAC_INIT_PIPE: 413 mpc->mpc_ops->mpo_init_pipe = 414 mpe->mpe_function; 415 break; 416 case MAC_INIT_SOCKET: 417 mpc->mpc_ops->mpo_init_socket = 418 mpe->mpe_function; 419 break; 420 case MAC_INIT_TEMP: 421 mpc->mpc_ops->mpo_init_temp = 422 mpe->mpe_function; 423 break; 424 case MAC_INIT_VNODE: 425 mpc->mpc_ops->mpo_init_vnode = 426 mpe->mpe_function; 427 break; 428 case MAC_DESTROY_BPFDESC: 429 mpc->mpc_ops->mpo_destroy_bpfdesc = 430 mpe->mpe_function; 431 break; 432 case MAC_DESTROY_CRED: 433 mpc->mpc_ops->mpo_destroy_cred = 434 mpe->mpe_function; 435 break; 436 case MAC_DESTROY_DEVFSDIRENT: 437 mpc->mpc_ops->mpo_destroy_devfsdirent = 438 mpe->mpe_function; 439 break; 440 case MAC_DESTROY_IFNET: 441 mpc->mpc_ops->mpo_destroy_ifnet = 442 mpe->mpe_function; 443 break; 444 case MAC_DESTROY_IPQ: 445 mpc->mpc_ops->mpo_destroy_ipq = 446 mpe->mpe_function; 447 break; 448 case MAC_DESTROY_MBUF: 449 mpc->mpc_ops->mpo_destroy_mbuf = 450 mpe->mpe_function; 451 break; 452 case MAC_DESTROY_MOUNT: 453 mpc->mpc_ops->mpo_destroy_mount = 454 mpe->mpe_function; 455 break; 456 case MAC_DESTROY_PIPE: 457 mpc->mpc_ops->mpo_destroy_pipe = 458 mpe->mpe_function; 459 break; 460 case MAC_DESTROY_SOCKET: 461 mpc->mpc_ops->mpo_destroy_socket = 462 mpe->mpe_function; 463 break; 464 case MAC_DESTROY_TEMP: 465 mpc->mpc_ops->mpo_destroy_temp = 466 mpe->mpe_function; 467 break; 468 case MAC_DESTROY_VNODE: 469 mpc->mpc_ops->mpo_destroy_vnode = 470 mpe->mpe_function; 471 break; 472 case MAC_EXTERNALIZE: 473 mpc->mpc_ops->mpo_externalize = 474 mpe->mpe_function; 475 break; 476 case MAC_INTERNALIZE: 477 mpc->mpc_ops->mpo_internalize = 478 mpe->mpe_function; 479 break; 480 case MAC_CREATE_DEVFS_DEVICE: 481 mpc->mpc_ops->mpo_create_devfs_device = 482 mpe->mpe_function; 483 break; 484 case MAC_CREATE_DEVFS_DIRECTORY: 485 mpc->mpc_ops->mpo_create_devfs_directory = 486 mpe->mpe_function; 487 break; 488 case MAC_CREATE_DEVFS_VNODE: 489 mpc->mpc_ops->mpo_create_devfs_vnode = 490 mpe->mpe_function; 491 break; 492 case MAC_STDCREATEVNODE_EA: 493 mpc->mpc_ops->mpo_stdcreatevnode_ea = 494 mpe->mpe_function; 495 break; 496 case MAC_CREATE_VNODE: 497 mpc->mpc_ops->mpo_create_vnode = 498 mpe->mpe_function; 499 break; 500 case MAC_CREATE_MOUNT: 501 mpc->mpc_ops->mpo_create_mount = 502 mpe->mpe_function; 503 break; 504 case MAC_CREATE_ROOT_MOUNT: 505 mpc->mpc_ops->mpo_create_root_mount = 506 mpe->mpe_function; 507 break; 508 case MAC_RELABEL_VNODE: 509 mpc->mpc_ops->mpo_relabel_vnode = 510 mpe->mpe_function; 511 break; 512 case MAC_UPDATE_DEVFSDIRENT: 513 mpc->mpc_ops->mpo_update_devfsdirent = 514 mpe->mpe_function; 515 break; 516 case MAC_UPDATE_PROCFSVNODE: 517 mpc->mpc_ops->mpo_update_procfsvnode = 518 mpe->mpe_function; 519 break; 520 case MAC_UPDATE_VNODE_FROM_EXTATTR: 521 mpc->mpc_ops->mpo_update_vnode_from_extattr = 522 mpe->mpe_function; 523 break; 524 case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: 525 mpc->mpc_ops->mpo_update_vnode_from_externalized = 526 mpe->mpe_function; 527 break; 528 case MAC_UPDATE_VNODE_FROM_MOUNT: 529 mpc->mpc_ops->mpo_update_vnode_from_mount = 530 mpe->mpe_function; 531 break; 532 case MAC_CREATE_MBUF_FROM_SOCKET: 533 mpc->mpc_ops->mpo_create_mbuf_from_socket = 534 mpe->mpe_function; 535 break; 536 case MAC_CREATE_PIPE: 537 mpc->mpc_ops->mpo_create_pipe = 538 mpe->mpe_function; 539 break; 540 case MAC_CREATE_SOCKET: 541 mpc->mpc_ops->mpo_create_socket = 542 mpe->mpe_function; 543 break; 544 case MAC_CREATE_SOCKET_FROM_SOCKET: 545 mpc->mpc_ops->mpo_create_socket_from_socket = 546 mpe->mpe_function; 547 break; 548 case MAC_RELABEL_PIPE: 549 mpc->mpc_ops->mpo_relabel_pipe = 550 mpe->mpe_function; 551 break; 552 case MAC_RELABEL_SOCKET: 553 mpc->mpc_ops->mpo_relabel_socket = 554 mpe->mpe_function; 555 break; 556 case MAC_SET_SOCKET_PEER_FROM_MBUF: 557 mpc->mpc_ops->mpo_set_socket_peer_from_mbuf = 558 mpe->mpe_function; 559 break; 560 case MAC_SET_SOCKET_PEER_FROM_SOCKET: 561 mpc->mpc_ops->mpo_set_socket_peer_from_socket = 562 mpe->mpe_function; 563 break; 564 case MAC_CREATE_BPFDESC: 565 mpc->mpc_ops->mpo_create_bpfdesc = 566 mpe->mpe_function; 567 break; 568 case MAC_CREATE_DATAGRAM_FROM_IPQ: 569 mpc->mpc_ops->mpo_create_datagram_from_ipq = 570 mpe->mpe_function; 571 break; 572 case MAC_CREATE_FRAGMENT: 573 mpc->mpc_ops->mpo_create_fragment = 574 mpe->mpe_function; 575 break; 576 case MAC_CREATE_IFNET: 577 mpc->mpc_ops->mpo_create_ifnet = 578 mpe->mpe_function; 579 break; 580 case MAC_CREATE_IPQ: 581 mpc->mpc_ops->mpo_create_ipq = 582 mpe->mpe_function; 583 break; 584 case MAC_CREATE_MBUF_FROM_MBUF: 585 mpc->mpc_ops->mpo_create_mbuf_from_mbuf = 586 mpe->mpe_function; 587 break; 588 case MAC_CREATE_MBUF_LINKLAYER: 589 mpc->mpc_ops->mpo_create_mbuf_linklayer = 590 mpe->mpe_function; 591 break; 592 case MAC_CREATE_MBUF_FROM_BPFDESC: 593 mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc = 594 mpe->mpe_function; 595 break; 596 case MAC_CREATE_MBUF_FROM_IFNET: 597 mpc->mpc_ops->mpo_create_mbuf_from_ifnet = 598 mpe->mpe_function; 599 break; 600 case MAC_CREATE_MBUF_MULTICAST_ENCAP: 601 mpc->mpc_ops->mpo_create_mbuf_multicast_encap = 602 mpe->mpe_function; 603 break; 604 case MAC_CREATE_MBUF_NETLAYER: 605 mpc->mpc_ops->mpo_create_mbuf_netlayer = 606 mpe->mpe_function; 607 break; 608 case MAC_FRAGMENT_MATCH: 609 mpc->mpc_ops->mpo_fragment_match = 610 mpe->mpe_function; 611 break; 612 case MAC_RELABEL_IFNET: 613 mpc->mpc_ops->mpo_relabel_ifnet = 614 mpe->mpe_function; 615 break; 616 case MAC_UPDATE_IPQ: 617 mpc->mpc_ops->mpo_update_ipq = 618 mpe->mpe_function; 619 break; 620 case MAC_CREATE_CRED: 621 mpc->mpc_ops->mpo_create_cred = 622 mpe->mpe_function; 623 break; 624 case MAC_EXECVE_TRANSITION: 625 mpc->mpc_ops->mpo_execve_transition = 626 mpe->mpe_function; 627 break; 628 case MAC_EXECVE_WILL_TRANSITION: 629 mpc->mpc_ops->mpo_execve_will_transition = 630 mpe->mpe_function; 631 break; 632 case MAC_CREATE_PROC0: 633 mpc->mpc_ops->mpo_create_proc0 = mpe->mpe_function; 634 break; 635 case MAC_CREATE_PROC1: 636 mpc->mpc_ops->mpo_create_proc1 = mpe->mpe_function; 637 break; 638 case MAC_RELABEL_CRED: 639 mpc->mpc_ops->mpo_relabel_cred = 640 mpe->mpe_function; 641 break; 642 case MAC_CHECK_BPFDESC_RECEIVE: 643 mpc->mpc_ops->mpo_check_bpfdesc_receive = 644 mpe->mpe_function; 645 break; 646 case MAC_CHECK_CRED_RELABEL: 647 mpc->mpc_ops->mpo_check_cred_relabel = 648 mpe->mpe_function; 649 break; 650 case MAC_CHECK_CRED_VISIBLE: 651 mpc->mpc_ops->mpo_check_cred_visible = 652 mpe->mpe_function; 653 break; 654 case MAC_CHECK_IFNET_RELABEL: 655 mpc->mpc_ops->mpo_check_ifnet_relabel = 656 mpe->mpe_function; 657 break; 658 case MAC_CHECK_IFNET_TRANSMIT: 659 mpc->mpc_ops->mpo_check_ifnet_transmit = 660 mpe->mpe_function; 661 break; 662 case MAC_CHECK_MOUNT_STAT: 663 mpc->mpc_ops->mpo_check_mount_stat = 664 mpe->mpe_function; 665 break; 666 case MAC_CHECK_PIPE_IOCTL: 667 mpc->mpc_ops->mpo_check_pipe_ioctl = 668 mpe->mpe_function; 669 break; 670 case MAC_CHECK_PIPE_OP: 671 mpc->mpc_ops->mpo_check_pipe_op = 672 mpe->mpe_function; 673 break; 674 case MAC_CHECK_PIPE_RELABEL: 675 mpc->mpc_ops->mpo_check_pipe_relabel = 676 mpe->mpe_function; 677 break; 678 case MAC_CHECK_PROC_DEBUG: 679 mpc->mpc_ops->mpo_check_proc_debug = 680 mpe->mpe_function; 681 break; 682 case MAC_CHECK_PROC_SCHED: 683 mpc->mpc_ops->mpo_check_proc_sched = 684 mpe->mpe_function; 685 break; 686 case MAC_CHECK_PROC_SIGNAL: 687 mpc->mpc_ops->mpo_check_proc_signal = 688 mpe->mpe_function; 689 break; 690 case MAC_CHECK_SOCKET_BIND: 691 mpc->mpc_ops->mpo_check_socket_bind = 692 mpe->mpe_function; 693 break; 694 case MAC_CHECK_SOCKET_CONNECT: 695 mpc->mpc_ops->mpo_check_socket_connect = 696 mpe->mpe_function; 697 break; 698 case MAC_CHECK_SOCKET_DELIVER: 699 mpc->mpc_ops->mpo_check_socket_deliver = 700 mpe->mpe_function; 701 break; 702 case MAC_CHECK_SOCKET_LISTEN: 703 mpc->mpc_ops->mpo_check_socket_listen = 704 mpe->mpe_function; 705 break; 706 case MAC_CHECK_SOCKET_RELABEL: 707 mpc->mpc_ops->mpo_check_socket_relabel = 708 mpe->mpe_function; 709 break; 710 case MAC_CHECK_SOCKET_VISIBLE: 711 mpc->mpc_ops->mpo_check_socket_visible = 712 mpe->mpe_function; 713 break; 714 case MAC_CHECK_VNODE_ACCESS: 715 mpc->mpc_ops->mpo_check_vnode_access = 716 mpe->mpe_function; 717 break; 718 case MAC_CHECK_VNODE_CHDIR: 719 mpc->mpc_ops->mpo_check_vnode_chdir = 720 mpe->mpe_function; 721 break; 722 case MAC_CHECK_VNODE_CHROOT: 723 mpc->mpc_ops->mpo_check_vnode_chroot = 724 mpe->mpe_function; 725 break; 726 case MAC_CHECK_VNODE_CREATE: 727 mpc->mpc_ops->mpo_check_vnode_create = 728 mpe->mpe_function; 729 break; 730 case MAC_CHECK_VNODE_DELETE: 731 mpc->mpc_ops->mpo_check_vnode_delete = 732 mpe->mpe_function; 733 break; 734 case MAC_CHECK_VNODE_DELETEACL: 735 mpc->mpc_ops->mpo_check_vnode_deleteacl = 736 mpe->mpe_function; 737 break; 738 case MAC_CHECK_VNODE_EXEC: 739 mpc->mpc_ops->mpo_check_vnode_exec = 740 mpe->mpe_function; 741 break; 742 case MAC_CHECK_VNODE_GETACL: 743 mpc->mpc_ops->mpo_check_vnode_getacl = 744 mpe->mpe_function; 745 break; 746 case MAC_CHECK_VNODE_GETEXTATTR: 747 mpc->mpc_ops->mpo_check_vnode_getextattr = 748 mpe->mpe_function; 749 break; 750 case MAC_CHECK_VNODE_LOOKUP: 751 mpc->mpc_ops->mpo_check_vnode_lookup = 752 mpe->mpe_function; 753 break; 754 case MAC_CHECK_VNODE_MMAP_PERMS: 755 mpc->mpc_ops->mpo_check_vnode_mmap_perms = 756 mpe->mpe_function; 757 break; 758 case MAC_CHECK_VNODE_OPEN: 759 mpc->mpc_ops->mpo_check_vnode_open = 760 mpe->mpe_function; 761 break; 762 case MAC_CHECK_VNODE_POLL: 763 mpc->mpc_ops->mpo_check_vnode_poll = 764 mpe->mpe_function; 765 break; 766 case MAC_CHECK_VNODE_READ: 767 mpc->mpc_ops->mpo_check_vnode_read = 768 mpe->mpe_function; 769 break; 770 case MAC_CHECK_VNODE_READDIR: 771 mpc->mpc_ops->mpo_check_vnode_readdir = 772 mpe->mpe_function; 773 break; 774 case MAC_CHECK_VNODE_READLINK: 775 mpc->mpc_ops->mpo_check_vnode_readlink = 776 mpe->mpe_function; 777 break; 778 case MAC_CHECK_VNODE_RELABEL: 779 mpc->mpc_ops->mpo_check_vnode_relabel = 780 mpe->mpe_function; 781 break; 782 case MAC_CHECK_VNODE_RENAME_FROM: 783 mpc->mpc_ops->mpo_check_vnode_rename_from = 784 mpe->mpe_function; 785 break; 786 case MAC_CHECK_VNODE_RENAME_TO: 787 mpc->mpc_ops->mpo_check_vnode_rename_to = 788 mpe->mpe_function; 789 break; 790 case MAC_CHECK_VNODE_REVOKE: 791 mpc->mpc_ops->mpo_check_vnode_revoke = 792 mpe->mpe_function; 793 break; 794 case MAC_CHECK_VNODE_SETACL: 795 mpc->mpc_ops->mpo_check_vnode_setacl = 796 mpe->mpe_function; 797 break; 798 case MAC_CHECK_VNODE_SETEXTATTR: 799 mpc->mpc_ops->mpo_check_vnode_setextattr = 800 mpe->mpe_function; 801 break; 802 case MAC_CHECK_VNODE_SETFLAGS: 803 mpc->mpc_ops->mpo_check_vnode_setflags = 804 mpe->mpe_function; 805 break; 806 case MAC_CHECK_VNODE_SETMODE: 807 mpc->mpc_ops->mpo_check_vnode_setmode = 808 mpe->mpe_function; 809 break; 810 case MAC_CHECK_VNODE_SETOWNER: 811 mpc->mpc_ops->mpo_check_vnode_setowner = 812 mpe->mpe_function; 813 break; 814 case MAC_CHECK_VNODE_SETUTIMES: 815 mpc->mpc_ops->mpo_check_vnode_setutimes = 816 mpe->mpe_function; 817 break; 818 case MAC_CHECK_VNODE_STAT: 819 mpc->mpc_ops->mpo_check_vnode_stat = 820 mpe->mpe_function; 821 break; 822 case MAC_CHECK_VNODE_WRITE: 823 mpc->mpc_ops->mpo_check_vnode_write = 824 mpe->mpe_function; 825 break; 826/* 827 default: 828 printf("MAC policy `%s': unknown operation %d\n", 829 mpc->mpc_name, mpe->mpe_constant); 830 return (EINVAL); 831*/ 832 } 833 } 834 MAC_POLICY_LIST_LOCK(); 835 if (mac_policy_list_busy > 0) { 836 MAC_POLICY_LIST_UNLOCK(); 837 FREE(mpc->mpc_ops, M_MACOPVEC); 838 mpc->mpc_ops = NULL; 839 return (EBUSY); 840 } 841 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 842 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 843 MAC_POLICY_LIST_UNLOCK(); 844 FREE(mpc->mpc_ops, M_MACOPVEC); 845 mpc->mpc_ops = NULL; 846 return (EEXIST); 847 } 848 } 849 if (mpc->mpc_field_off != NULL) { 850 slot = ffs(mac_policy_offsets_free); 851 if (slot == 0) { 852 MAC_POLICY_LIST_UNLOCK(); 853 FREE(mpc->mpc_ops, M_MACOPVEC); 854 mpc->mpc_ops = NULL; 855 return (ENOMEM); 856 } 857 slot--; 858 mac_policy_offsets_free &= ~(1 << slot); 859 *mpc->mpc_field_off = slot; 860 } 861 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 862 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 863 864 /* Per-policy initialization. */ 865 if (mpc->mpc_ops->mpo_init != NULL) 866 (*(mpc->mpc_ops->mpo_init))(mpc); 867 MAC_POLICY_LIST_UNLOCK(); 868 869 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 870 mpc->mpc_name); 871 872 return (0); 873} 874 875static int 876mac_policy_unregister(struct mac_policy_conf *mpc) 877{ 878 879#if 0 880 /* 881 * Don't allow unloading modules with private data. 882 */ 883 if (mpc->mpc_field_off != NULL) 884 return (EBUSY); 885#endif 886 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) 887 return (EBUSY); 888 MAC_POLICY_LIST_LOCK(); 889 if (mac_policy_list_busy > 0) { 890 MAC_POLICY_LIST_UNLOCK(); 891 return (EBUSY); 892 } 893 if (mpc->mpc_ops->mpo_destroy != NULL) 894 (*(mpc->mpc_ops->mpo_destroy))(mpc); 895 896 LIST_REMOVE(mpc, mpc_list); 897 MAC_POLICY_LIST_UNLOCK(); 898 899 FREE(mpc->mpc_ops, M_MACOPVEC); 900 mpc->mpc_ops = NULL; 901 902 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 903 mpc->mpc_name); 904 905 return (0); 906} 907 908/* 909 * Define an error value precedence, and given two arguments, selects the 910 * value with the higher precedence. 911 */ 912static int 913error_select(int error1, int error2) 914{ 915 916 /* Certain decision-making errors take top priority. */ 917 if (error1 == EDEADLK || error2 == EDEADLK) 918 return (EDEADLK); 919 920 /* Invalid arguments should be reported where possible. */ 921 if (error1 == EINVAL || error2 == EINVAL) 922 return (EINVAL); 923 924 /* Precedence goes to "visibility", with both process and file. */ 925 if (error1 == ESRCH || error2 == ESRCH) 926 return (ESRCH); 927 928 if (error1 == ENOENT || error2 == ENOENT) 929 return (ENOENT); 930 931 /* Precedence goes to DAC/MAC protections. */ 932 if (error1 == EACCES || error2 == EACCES) 933 return (EACCES); 934 935 /* Precedence goes to privilege. */ 936 if (error1 == EPERM || error2 == EPERM) 937 return (EPERM); 938 939 /* Precedence goes to error over success; otherwise, arbitrary. */ 940 if (error1 != 0) 941 return (error1); 942 return (error2); 943} 944 945void 946mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 947{ 948 949 MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 950} 951 952void 953mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) 954{ 955 956 MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); 957} 958 959/* 960 * Support callout for policies that manage their own externalization 961 * using extended attributes. 962 */ 963static int 964mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) 965{ 966 int error; 967 968 MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, 969 &mp->mnt_fslabel); 970 971 return (error); 972} 973 974/* 975 * Given an externalized mac label, internalize it and stamp it on a 976 * vnode. 977 */ 978static int 979mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac) 980{ 981 int error; 982 983 MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); 984 985 return (error); 986} 987 988/* 989 * Call out to individual policies to update the label in a vnode from 990 * the mountpoint. 991 */ 992void 993mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) 994{ 995 996 MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, 997 &mp->mnt_fslabel); 998 999 ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); 1000 if (mac_cache_fslabel_in_vnode) 1001 vp->v_vflag |= VV_CACHEDLABEL; 1002} 1003 1004/* 1005 * Implementation of VOP_REFRESHLABEL() that relies on extended attributes 1006 * to store label data. Can be referenced by filesystems supporting 1007 * extended attributes. 1008 */ 1009int 1010vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) 1011{ 1012 struct vnode *vp = ap->a_vp; 1013 struct mac extmac; 1014 int buflen, error; 1015 1016 ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); 1017 1018 /* 1019 * Call out to external policies first. Order doesn't really 1020 * matter, as long as failure of one assures failure of all. 1021 */ 1022 error = mac_update_vnode_from_extattr(vp, vp->v_mount); 1023 if (error) 1024 return (error); 1025 1026 buflen = sizeof(extmac); 1027 error = vn_extattr_get(vp, IO_NODELOCKED, 1028 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, 1029 (char *)&extmac, curthread); 1030 switch (error) { 1031 case 0: 1032 /* Got it */ 1033 break; 1034 1035 case ENOATTR: 1036 /* 1037 * Use the label from the mount point. 1038 */ 1039 mac_update_vnode_from_mount(vp, vp->v_mount); 1040 return (0); 1041 1042 case EOPNOTSUPP: 1043 default: 1044 /* Fail horribly. */ 1045 return (error); 1046 } 1047 1048 if (buflen != sizeof(extmac)) 1049 error = EPERM; /* Fail very closed. */ 1050 if (error == 0) 1051 error = mac_update_vnode_from_externalized(vp, &extmac); 1052 if (error == 0) 1053 vp->v_vflag |= VV_CACHEDLABEL; 1054 else { 1055 struct vattr va; 1056 1057 printf("Corrupted label on %s", 1058 vp->v_mount->mnt_stat.f_mntonname); 1059 if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) 1060 printf(" inum %ld", va.va_fileid); 1061 if (mac_debug_label_fallback) { 1062 printf(", falling back.\n"); 1063 mac_update_vnode_from_mount(vp, vp->v_mount); 1064 error = 0; 1065 } else { 1066 printf(".\n"); 1067 error = EPERM; 1068 } 1069 } 1070 1071 return (error); 1072} 1073 1074/* 1075 * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle 1076 * the labeling activity outselves. Filesystems should be careful not 1077 * to change their minds regarding whether they support vop_refreshlabel() 1078 * for a vnode or not. Don't cache the vnode here, allow the file 1079 * system code to determine if it's safe to cache. If we update from 1080 * the mount, don't cache since a change to the mount label should affect 1081 * all vnodes. 1082 */ 1083static int 1084vn_refreshlabel(struct vnode *vp, struct ucred *cred) 1085{ 1086 int error; 1087 1088 ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); 1089 1090 if (vp->v_mount == NULL) { 1091/* 1092 Eventually, we probably want to special-case refreshing 1093 of deadfs vnodes, and if there's a lock-free race somewhere, 1094 that case might be handled here. 1095 1096 mac_update_vnode_deadfs(vp); 1097 return (0); 1098 */ 1099 /* printf("vn_refreshlabel: null v_mount\n"); */ 1100 if (vp->v_tag != VT_NON) 1101 printf( 1102 "vn_refreshlabel: null v_mount with non-VT_NON\n"); 1103 return (EBADF); 1104 } 1105 1106 if (vp->v_vflag & VV_CACHEDLABEL) { 1107 mac_vnode_label_cache_hits++; 1108 return (0); 1109 } else 1110 mac_vnode_label_cache_misses++; 1111 1112 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 1113 mac_update_vnode_from_mount(vp, vp->v_mount); 1114 return (0); 1115 } 1116 1117 error = VOP_REFRESHLABEL(vp, cred, curthread); 1118 switch (error) { 1119 case EOPNOTSUPP: 1120 /* 1121 * If labels are not supported on this vnode, fall back to 1122 * the label in the mount and propagate it to the vnode. 1123 * There should probably be some sort of policy/flag/decision 1124 * about doing this. 1125 */ 1126 mac_update_vnode_from_mount(vp, vp->v_mount); 1127 error = 0; 1128 default: 1129 return (error); 1130 } 1131} 1132 1133/* 1134 * Helper function for file systems using the vop_std*_ea() calls. This 1135 * function must be called after EA service is available for the vnode, 1136 * but before it's hooked up to the namespace so that the node persists 1137 * if there's a crash, or before it can be accessed. On successful 1138 * commit of the label to disk (etc), do cache the label. 1139 */ 1140int 1141vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) 1142{ 1143 struct mac extmac; 1144 int error; 1145 1146 ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); 1147 if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 1148 mac_update_vnode_from_mount(tvp, tvp->v_mount); 1149 } else { 1150 error = vn_refreshlabel(dvp, cred); 1151 if (error) 1152 return (error); 1153 1154 /* 1155 * Stick the label in the vnode. Then try to write to 1156 * disk. If we fail, return a failure to abort the 1157 * create operation. Really, this failure shouldn't 1158 * happen except in fairly unusual circumstances (out 1159 * of disk, etc). 1160 */ 1161 mac_create_vnode(cred, dvp, tvp); 1162 1163 error = mac_stdcreatevnode_ea(tvp); 1164 if (error) 1165 return (error); 1166 1167 /* 1168 * XXX: Eventually this will go away and all policies will 1169 * directly manage their extended attributes. 1170 */ 1171 error = mac_externalize(&tvp->v_label, &extmac); 1172 if (error) 1173 return (error); 1174 1175 error = vn_extattr_set(tvp, IO_NODELOCKED, 1176 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 1177 sizeof(extmac), (char *)&extmac, curthread); 1178 if (error == 0) 1179 tvp->v_vflag |= VV_CACHEDLABEL; 1180 else { 1181#if 0 1182 /* 1183 * In theory, we could have fall-back behavior here. 1184 * It would probably be incorrect. 1185 */ 1186#endif 1187 return (error); 1188 } 1189 } 1190 1191 return (0); 1192} 1193 1194void 1195mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) 1196{ 1197 int error; 1198 1199 ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 1200 1201 error = vn_refreshlabel(vp, old); 1202 if (error) { 1203 printf("mac_execve_transition: vn_refreshlabel returned %d\n", 1204 error); 1205 printf("mac_execve_transition: using old vnode label\n"); 1206 } 1207 1208 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); 1209} 1210 1211int 1212mac_execve_will_transition(struct ucred *old, struct vnode *vp) 1213{ 1214 int error, result; 1215 1216 error = vn_refreshlabel(vp, old); 1217 if (error) 1218 return (error); 1219 1220 result = 0; 1221 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); 1222 1223 return (result); 1224} 1225 1226static void 1227mac_init_label(struct label *label) 1228{ 1229 1230 bzero(label, sizeof(*label)); 1231 label->l_flags = MAC_FLAG_INITIALIZED; 1232} 1233 1234static void 1235mac_init_structmac(struct mac *mac) 1236{ 1237 1238 bzero(mac, sizeof(*mac)); 1239 mac->m_macflags = MAC_FLAG_INITIALIZED; 1240} 1241 1242static void 1243mac_destroy_label(struct label *label) 1244{ 1245 1246 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 1247 ("destroying uninitialized label")); 1248 1249 bzero(label, sizeof(*label)); 1250 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 1251} 1252 1253int 1254mac_init_mbuf(struct mbuf *m, int how) 1255{ 1256 KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 1257 1258 /* "how" is one of M_(TRY|DONT)WAIT */ 1259 mac_init_label(&m->m_pkthdr.label); 1260 MAC_PERFORM(init_mbuf, m, how, &m->m_pkthdr.label); 1261#ifdef MAC_DEBUG 1262 atomic_add_int(&nmacmbufs, 1); 1263#endif 1264 return (0); 1265} 1266 1267void 1268mac_destroy_mbuf(struct mbuf *m) 1269{ 1270 1271 MAC_PERFORM(destroy_mbuf, m, &m->m_pkthdr.label); 1272 mac_destroy_label(&m->m_pkthdr.label); 1273#ifdef MAC_DEBUG 1274 atomic_subtract_int(&nmacmbufs, 1); 1275#endif 1276} 1277 1278void 1279mac_init_cred(struct ucred *cr) 1280{ 1281 1282 mac_init_label(&cr->cr_label); 1283 MAC_PERFORM(init_cred, cr, &cr->cr_label); 1284#ifdef MAC_DEBUG 1285 atomic_add_int(&nmaccreds, 1); 1286#endif 1287} 1288 1289void 1290mac_destroy_cred(struct ucred *cr) 1291{ 1292 1293 MAC_PERFORM(destroy_cred, cr, &cr->cr_label); 1294 mac_destroy_label(&cr->cr_label); 1295#ifdef MAC_DEBUG 1296 atomic_subtract_int(&nmaccreds, 1); 1297#endif 1298} 1299 1300void 1301mac_init_ifnet(struct ifnet *ifp) 1302{ 1303 1304 mac_init_label(&ifp->if_label); 1305 MAC_PERFORM(init_ifnet, ifp, &ifp->if_label); 1306#ifdef MAC_DEBUG 1307 atomic_add_int(&nmacifnets, 1); 1308#endif 1309} 1310 1311void 1312mac_destroy_ifnet(struct ifnet *ifp) 1313{ 1314 1315 MAC_PERFORM(destroy_ifnet, ifp, &ifp->if_label); 1316 mac_destroy_label(&ifp->if_label); 1317#ifdef MAC_DEBUG 1318 atomic_subtract_int(&nmacifnets, 1); 1319#endif 1320} 1321 1322void 1323mac_init_ipq(struct ipq *ipq) 1324{ 1325 1326 mac_init_label(&ipq->ipq_label); 1327 MAC_PERFORM(init_ipq, ipq, &ipq->ipq_label); 1328#ifdef MAC_DEBUG 1329 atomic_add_int(&nmacipqs, 1); 1330#endif 1331} 1332 1333void 1334mac_destroy_ipq(struct ipq *ipq) 1335{ 1336 1337 MAC_PERFORM(destroy_ipq, ipq, &ipq->ipq_label); 1338 mac_destroy_label(&ipq->ipq_label); 1339#ifdef MAC_DEBUG 1340 atomic_subtract_int(&nmacipqs, 1); 1341#endif 1342} 1343 1344void 1345mac_init_socket(struct socket *socket) 1346{ 1347 1348 mac_init_label(&socket->so_label); 1349 mac_init_label(&socket->so_peerlabel); 1350 MAC_PERFORM(init_socket, socket, &socket->so_label, 1351 &socket->so_peerlabel); 1352#ifdef MAC_DEBUG 1353 atomic_add_int(&nmacsockets, 1); 1354#endif 1355} 1356 1357void 1358mac_destroy_socket(struct socket *socket) 1359{ 1360 1361 MAC_PERFORM(destroy_socket, socket, &socket->so_label, 1362 &socket->so_peerlabel); 1363 mac_destroy_label(&socket->so_label); 1364 mac_destroy_label(&socket->so_peerlabel); 1365#ifdef MAC_DEBUG 1366 atomic_subtract_int(&nmacsockets, 1); 1367#endif 1368} 1369 1370void 1371mac_init_pipe(struct pipe *pipe) 1372{ 1373 struct label *label; 1374 1375 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 1376 mac_init_label(label); 1377 pipe->pipe_label = label; 1378 pipe->pipe_peer->pipe_label = label; 1379 MAC_PERFORM(init_pipe, pipe, pipe->pipe_label); 1380#ifdef MAC_DEBUG 1381 atomic_add_int(&nmacpipes, 1); 1382#endif 1383} 1384 1385void 1386mac_destroy_pipe(struct pipe *pipe) 1387{ 1388 1389 MAC_PERFORM(destroy_pipe, pipe, pipe->pipe_label); 1390 mac_destroy_label(pipe->pipe_label); 1391 free(pipe->pipe_label, M_MACPIPELABEL); 1392#ifdef MAC_DEBUG 1393 atomic_subtract_int(&nmacpipes, 1); 1394#endif 1395} 1396 1397void 1398mac_init_bpfdesc(struct bpf_d *bpf_d) 1399{ 1400 1401 mac_init_label(&bpf_d->bd_label); 1402 MAC_PERFORM(init_bpfdesc, bpf_d, &bpf_d->bd_label); 1403#ifdef MAC_DEBUG 1404 atomic_add_int(&nmacbpfdescs, 1); 1405#endif 1406} 1407 1408void 1409mac_destroy_bpfdesc(struct bpf_d *bpf_d) 1410{ 1411 1412 MAC_PERFORM(destroy_bpfdesc, bpf_d, &bpf_d->bd_label); 1413 mac_destroy_label(&bpf_d->bd_label); 1414#ifdef MAC_DEBUG 1415 atomic_subtract_int(&nmacbpfdescs, 1); 1416#endif 1417} 1418 1419void 1420mac_init_mount(struct mount *mp) 1421{ 1422 1423 mac_init_label(&mp->mnt_mntlabel); 1424 mac_init_label(&mp->mnt_fslabel); 1425 MAC_PERFORM(init_mount, mp, &mp->mnt_mntlabel, &mp->mnt_fslabel); 1426#ifdef MAC_DEBUG 1427 atomic_add_int(&nmacmounts, 1); 1428#endif 1429} 1430 1431void 1432mac_destroy_mount(struct mount *mp) 1433{ 1434 1435 MAC_PERFORM(destroy_mount, mp, &mp->mnt_mntlabel, &mp->mnt_fslabel); 1436 mac_destroy_label(&mp->mnt_fslabel); 1437 mac_destroy_label(&mp->mnt_mntlabel); 1438#ifdef MAC_DEBUG 1439 atomic_subtract_int(&nmacmounts, 1); 1440#endif 1441} 1442 1443static void 1444mac_init_temp(struct label *label) 1445{ 1446 1447 mac_init_label(label); 1448 MAC_PERFORM(init_temp, label); 1449#ifdef MAC_DEBUG 1450 atomic_add_int(&nmactemp, 1); 1451#endif 1452} 1453 1454static void 1455mac_destroy_temp(struct label *label) 1456{ 1457 1458 MAC_PERFORM(destroy_temp, label); 1459 mac_destroy_label(label); 1460#ifdef MAC_DEBUG 1461 atomic_subtract_int(&nmactemp, 1); 1462#endif 1463} 1464 1465void 1466mac_init_vnode(struct vnode *vp) 1467{ 1468 1469 mac_init_label(&vp->v_label); 1470 MAC_PERFORM(init_vnode, vp, &vp->v_label); 1471#ifdef MAC_DEBUG 1472 atomic_add_int(&nmacvnodes, 1); 1473#endif 1474} 1475 1476void 1477mac_destroy_vnode(struct vnode *vp) 1478{ 1479 1480 MAC_PERFORM(destroy_vnode, vp, &vp->v_label); 1481 mac_destroy_label(&vp->v_label); 1482#ifdef MAC_DEBUG 1483 atomic_subtract_int(&nmacvnodes, 1); 1484#endif 1485} 1486 1487void 1488mac_init_devfsdirent(struct devfs_dirent *de) 1489{ 1490 1491 mac_init_label(&de->de_label); 1492 MAC_PERFORM(init_devfsdirent, de, &de->de_label); 1493#ifdef MAC_DEBUG 1494 atomic_add_int(&nmacdevfsdirents, 1); 1495#endif 1496} 1497 1498void 1499mac_destroy_devfsdirent(struct devfs_dirent *de) 1500{ 1501 1502 MAC_PERFORM(destroy_devfsdirent, de, &de->de_label); 1503 mac_destroy_label(&de->de_label); 1504#ifdef MAC_DEBUG 1505 atomic_subtract_int(&nmacdevfsdirents, 1); 1506#endif 1507} 1508 1509static int 1510mac_externalize(struct label *label, struct mac *mac) 1511{ 1512 int error; 1513 1514 mac_init_structmac(mac); 1515 MAC_CHECK(externalize, label, mac); 1516 1517 return (error); 1518} 1519 1520static int 1521mac_internalize(struct label *label, struct mac *mac) 1522{ 1523 int error; 1524 1525 mac_init_temp(label); 1526 MAC_CHECK(internalize, label, mac); 1527 if (error) 1528 mac_destroy_temp(label); 1529 1530 return (error); 1531} 1532 1533/* 1534 * Initialize MAC label for the first kernel process, from which other 1535 * kernel processes and threads are spawned. 1536 */ 1537void 1538mac_create_proc0(struct ucred *cred) 1539{ 1540 1541 MAC_PERFORM(create_proc0, cred); 1542} 1543 1544/* 1545 * Initialize MAC label for the first userland process, from which other 1546 * userland processes and threads are spawned. 1547 */ 1548void 1549mac_create_proc1(struct ucred *cred) 1550{ 1551 1552 MAC_PERFORM(create_proc1, cred); 1553} 1554 1555/* 1556 * When a new process is created, its label must be initialized. Generally, 1557 * this involves inheritence from the parent process, modulo possible 1558 * deltas. This function allows that processing to take place. 1559 */ 1560void 1561mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 1562{ 1563 1564 MAC_PERFORM(create_cred, parent_cred, child_cred); 1565} 1566 1567int 1568mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) 1569{ 1570 int error; 1571 1572 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 1573 1574 if (!mac_enforce_fs) 1575 return (0); 1576 1577 error = vn_refreshlabel(vp, cred); 1578 if (error) 1579 return (error); 1580 1581 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); 1582 return (error); 1583} 1584 1585int 1586mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 1587{ 1588 int error; 1589 1590 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 1591 1592 if (!mac_enforce_fs) 1593 return (0); 1594 1595 error = vn_refreshlabel(dvp, cred); 1596 if (error) 1597 return (error); 1598 1599 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 1600 return (error); 1601} 1602 1603int 1604mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 1605{ 1606 int error; 1607 1608 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 1609 1610 if (!mac_enforce_fs) 1611 return (0); 1612 1613 error = vn_refreshlabel(dvp, cred); 1614 if (error) 1615 return (error); 1616 1617 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 1618 return (error); 1619} 1620 1621int 1622mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 1623 struct componentname *cnp, struct vattr *vap) 1624{ 1625 int error; 1626 1627 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 1628 1629 if (!mac_enforce_fs) 1630 return (0); 1631 1632 error = vn_refreshlabel(dvp, cred); 1633 if (error) 1634 return (error); 1635 1636 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 1637 return (error); 1638} 1639 1640int 1641mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 1642 struct componentname *cnp) 1643{ 1644 int error; 1645 1646 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 1647 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 1648 1649 if (!mac_enforce_fs) 1650 return (0); 1651 1652 error = vn_refreshlabel(dvp, cred); 1653 if (error) 1654 return (error); 1655 error = vn_refreshlabel(vp, cred); 1656 if (error) 1657 return (error); 1658 1659 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 1660 &vp->v_label, cnp); 1661 return (error); 1662} 1663 1664int 1665mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 1666 acl_type_t type) 1667{ 1668 int error; 1669 1670 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 1671 1672 if (!mac_enforce_fs) 1673 return (0); 1674 1675 error = vn_refreshlabel(vp, cred); 1676 if (error) 1677 return (error); 1678 1679 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 1680 return (error); 1681} 1682 1683int 1684mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) 1685{ 1686 int error; 1687 1688 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1689 1690 if (!mac_enforce_process && !mac_enforce_fs) 1691 return (0); 1692 1693 error = vn_refreshlabel(vp, cred); 1694 if (error) 1695 return (error); 1696 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); 1697 1698 return (error); 1699} 1700 1701int 1702mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 1703{ 1704 int error; 1705 1706 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 1707 1708 if (!mac_enforce_fs) 1709 return (0); 1710 1711 error = vn_refreshlabel(vp, cred); 1712 if (error) 1713 return (error); 1714 1715 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 1716 return (error); 1717} 1718 1719int 1720mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 1721 int attrnamespace, const char *name, struct uio *uio) 1722{ 1723 int error; 1724 1725 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 1726 1727 if (!mac_enforce_fs) 1728 return (0); 1729 1730 error = vn_refreshlabel(vp, cred); 1731 if (error) 1732 return (error); 1733 1734 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 1735 attrnamespace, name, uio); 1736 return (error); 1737} 1738 1739int 1740mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 1741 struct componentname *cnp) 1742{ 1743 int error; 1744 1745 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 1746 1747 if (!mac_enforce_fs) 1748 return (0); 1749 1750 error = vn_refreshlabel(dvp, cred); 1751 if (error) 1752 return (error); 1753 1754 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 1755 return (error); 1756} 1757 1758vm_prot_t 1759mac_check_vnode_mmap_prot(struct ucred *cred, struct vnode *vp, int newmapping) 1760{ 1761 vm_prot_t result = VM_PROT_ALL; 1762 1763 /* 1764 * This should be some sort of MAC_BITWISE, maybe :) 1765 */ 1766 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_perms"); 1767 MAC_BOOLEAN(check_vnode_mmap_perms, &, cred, vp, &vp->v_label, 1768 newmapping); 1769 return (result); 1770} 1771 1772int 1773mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) 1774{ 1775 int error; 1776 1777 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 1778 1779 if (!mac_enforce_fs) 1780 return (0); 1781 1782 error = vn_refreshlabel(vp, cred); 1783 if (error) 1784 return (error); 1785 1786 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 1787 return (error); 1788} 1789 1790int 1791mac_check_vnode_poll(struct ucred *cred, struct vnode *vp) 1792{ 1793 int error; 1794 1795 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 1796 1797 if (!mac_enforce_fs) 1798 return (0); 1799 1800 error = vn_refreshlabel(vp, cred); 1801 if (error) 1802 return (error); 1803 1804 MAC_CHECK(check_vnode_poll, cred, vp, &vp->v_label); 1805 1806 return (error); 1807} 1808 1809int 1810mac_check_vnode_read(struct ucred *cred, struct vnode *vp) 1811{ 1812 int error; 1813 1814 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 1815 1816 if (!mac_enforce_fs) 1817 return (0); 1818 1819 error = vn_refreshlabel(vp, cred); 1820 if (error) 1821 return (error); 1822 1823 MAC_CHECK(check_vnode_read, cred, vp, &vp->v_label); 1824 1825 return (error); 1826} 1827 1828int 1829mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 1830{ 1831 int error; 1832 1833 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 1834 1835 if (!mac_enforce_fs) 1836 return (0); 1837 1838 error = vn_refreshlabel(dvp, cred); 1839 if (error) 1840 return (error); 1841 1842 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 1843 return (error); 1844} 1845 1846int 1847mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 1848{ 1849 int error; 1850 1851 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 1852 1853 if (!mac_enforce_fs) 1854 return (0); 1855 1856 error = vn_refreshlabel(vp, cred); 1857 if (error) 1858 return (error); 1859 1860 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 1861 return (error); 1862} 1863 1864static int 1865mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 1866 struct label *newlabel) 1867{ 1868 int error; 1869 1870 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 1871 1872 error = vn_refreshlabel(vp, cred); 1873 if (error) 1874 return (error); 1875 1876 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 1877 1878 return (error); 1879} 1880 1881int 1882mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 1883 struct vnode *vp, struct componentname *cnp) 1884{ 1885 int error; 1886 1887 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 1888 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 1889 1890 if (!mac_enforce_fs) 1891 return (0); 1892 1893 error = vn_refreshlabel(dvp, cred); 1894 if (error) 1895 return (error); 1896 error = vn_refreshlabel(vp, cred); 1897 if (error) 1898 return (error); 1899 1900 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 1901 &vp->v_label, cnp); 1902 return (error); 1903} 1904 1905int 1906mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 1907 struct vnode *vp, int samedir, struct componentname *cnp) 1908{ 1909 int error; 1910 1911 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 1912 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 1913 1914 if (!mac_enforce_fs) 1915 return (0); 1916 1917 error = vn_refreshlabel(dvp, cred); 1918 if (error) 1919 return (error); 1920 if (vp != NULL) { 1921 error = vn_refreshlabel(vp, cred); 1922 if (error) 1923 return (error); 1924 } 1925 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 1926 vp != NULL ? &vp->v_label : NULL, samedir, cnp); 1927 return (error); 1928} 1929 1930int 1931mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 1932{ 1933 int error; 1934 1935 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 1936 1937 if (!mac_enforce_fs) 1938 return (0); 1939 1940 error = vn_refreshlabel(vp, cred); 1941 if (error) 1942 return (error); 1943 1944 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 1945 return (error); 1946} 1947 1948int 1949mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 1950 struct acl *acl) 1951{ 1952 int error; 1953 1954 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 1955 1956 if (!mac_enforce_fs) 1957 return (0); 1958 1959 error = vn_refreshlabel(vp, cred); 1960 if (error) 1961 return (error); 1962 1963 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 1964 return (error); 1965} 1966 1967int 1968mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 1969 int attrnamespace, const char *name, struct uio *uio) 1970{ 1971 int error; 1972 1973 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 1974 1975 if (!mac_enforce_fs) 1976 return (0); 1977 1978 error = vn_refreshlabel(vp, cred); 1979 if (error) 1980 return (error); 1981 1982 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 1983 attrnamespace, name, uio); 1984 return (error); 1985} 1986 1987int 1988mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 1989{ 1990 int error; 1991 1992 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 1993 1994 if (!mac_enforce_fs) 1995 return (0); 1996 1997 error = vn_refreshlabel(vp, cred); 1998 if (error) 1999 return (error); 2000 2001 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 2002 return (error); 2003} 2004 2005int 2006mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 2007{ 2008 int error; 2009 2010 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 2011 2012 if (!mac_enforce_fs) 2013 return (0); 2014 2015 error = vn_refreshlabel(vp, cred); 2016 if (error) 2017 return (error); 2018 2019 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 2020 return (error); 2021} 2022 2023int 2024mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 2025 gid_t gid) 2026{ 2027 int error; 2028 2029 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 2030 2031 if (!mac_enforce_fs) 2032 return (0); 2033 2034 error = vn_refreshlabel(vp, cred); 2035 if (error) 2036 return (error); 2037 2038 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 2039 return (error); 2040} 2041 2042int 2043mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 2044 struct timespec atime, struct timespec mtime) 2045{ 2046 int error; 2047 2048 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 2049 2050 if (!mac_enforce_fs) 2051 return (0); 2052 2053 error = vn_refreshlabel(vp, cred); 2054 if (error) 2055 return (error); 2056 2057 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 2058 mtime); 2059 return (error); 2060} 2061 2062int 2063mac_check_vnode_stat(struct ucred *cred, struct vnode *vp) 2064{ 2065 int error; 2066 2067 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 2068 2069 if (!mac_enforce_fs) 2070 return (0); 2071 2072 error = vn_refreshlabel(vp, cred); 2073 if (error) 2074 return (error); 2075 2076 MAC_CHECK(check_vnode_stat, cred, vp, &vp->v_label); 2077 return (error); 2078} 2079 2080int 2081mac_check_vnode_write(struct ucred *cred, struct vnode *vp) 2082{ 2083 int error; 2084 2085 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 2086 2087 if (!mac_enforce_fs) 2088 return (0); 2089 2090 error = vn_refreshlabel(vp, cred); 2091 if (error) 2092 return (error); 2093 2094 MAC_CHECK(check_vnode_write, cred, vp, &vp->v_label); 2095 2096 return (error); 2097} 2098 2099 2100/* 2101 * When relabeling a process, call out to the policies for the maximum 2102 * permission allowed for each object type we know about in its 2103 * memory space, and revoke access (in the least surprising ways we 2104 * know) when necessary. The process lock is not held here. 2105 */ 2106static void 2107mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 2108{ 2109 2110 /* XXX freeze all other threads */ 2111 mtx_lock(&Giant); 2112 mac_cred_mmapped_drop_perms_recurse(td, cred, 2113 &td->td_proc->p_vmspace->vm_map); 2114 mtx_unlock(&Giant); 2115 /* XXX allow other threads to continue */ 2116} 2117 2118static __inline const char * 2119prot2str(vm_prot_t prot) 2120{ 2121 2122 switch (prot & VM_PROT_ALL) { 2123 case VM_PROT_READ: 2124 return ("r--"); 2125 case VM_PROT_READ | VM_PROT_WRITE: 2126 return ("rw-"); 2127 case VM_PROT_READ | VM_PROT_EXECUTE: 2128 return ("r-x"); 2129 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 2130 return ("rwx"); 2131 case VM_PROT_WRITE: 2132 return ("-w-"); 2133 case VM_PROT_EXECUTE: 2134 return ("--x"); 2135 case VM_PROT_WRITE | VM_PROT_EXECUTE: 2136 return ("-wx"); 2137 default: 2138 return ("---"); 2139 } 2140} 2141 2142static void 2143mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 2144 struct vm_map *map) 2145{ 2146 struct vm_map_entry *vme; 2147 vm_prot_t result, revokeperms; 2148 vm_object_t object; 2149 vm_ooffset_t offset; 2150 struct vnode *vp; 2151 2152 vm_map_lock_read(map); 2153 for (vme = map->header.next; vme != &map->header; vme = vme->next) { 2154 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 2155 mac_cred_mmapped_drop_perms_recurse(td, cred, 2156 vme->object.sub_map); 2157 continue; 2158 } 2159 /* 2160 * Skip over entries that obviously are not shared. 2161 */ 2162 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 2163 !vme->max_protection) 2164 continue; 2165 /* 2166 * Drill down to the deepest backing object. 2167 */ 2168 offset = vme->offset; 2169 object = vme->object.vm_object; 2170 if (object == NULL) 2171 continue; 2172 while (object->backing_object != NULL) { 2173 object = object->backing_object; 2174 offset += object->backing_object_offset; 2175 } 2176 /* 2177 * At the moment, vm_maps and objects aren't considered 2178 * by the MAC system, so only things with backing by a 2179 * normal object (read: vnodes) are checked. 2180 */ 2181 if (object->type != OBJT_VNODE) 2182 continue; 2183 vp = (struct vnode *)object->handle; 2184 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2185 result = mac_check_vnode_mmap_prot(cred, vp, 0); 2186 VOP_UNLOCK(vp, 0, td); 2187 /* 2188 * Find out what maximum protection we may be allowing 2189 * now but a policy needs to get removed. 2190 */ 2191 revokeperms = vme->max_protection & ~result; 2192 if (!revokeperms) 2193 continue; 2194 printf("pid %d: revoking %s perms from %#lx:%d " 2195 "(max %s/cur %s)\n", td->td_proc->p_pid, 2196 prot2str(revokeperms), vme->start, vme->end - vme->start, 2197 prot2str(vme->max_protection), prot2str(vme->protection)); 2198 vm_map_lock_upgrade(map); 2199 /* 2200 * This is the really simple case: if a map has more 2201 * max_protection than is allowed, but it's not being 2202 * actually used (that is, the current protection is 2203 * still allowed), we can just wipe it out and do 2204 * nothing more. 2205 */ 2206 if ((vme->protection & revokeperms) == 0) { 2207 vme->max_protection -= revokeperms; 2208 } else { 2209 if (revokeperms & VM_PROT_WRITE) { 2210 /* 2211 * In the more complicated case, flush out all 2212 * pending changes to the object then turn it 2213 * copy-on-write. 2214 */ 2215 vm_object_reference(object); 2216 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2217 vm_object_page_clean(object, 2218 OFF_TO_IDX(offset), 2219 OFF_TO_IDX(offset + vme->end - vme->start + 2220 PAGE_MASK), 2221 OBJPC_SYNC); 2222 VOP_UNLOCK(vp, 0, td); 2223 vm_object_deallocate(object); 2224 /* 2225 * Why bother if there's no read permissions 2226 * anymore? For the rest, we need to leave 2227 * the write permissions on for COW, or 2228 * remove them entirely if configured to. 2229 */ 2230 if (!mac_mmap_revocation_via_cow) { 2231 vme->max_protection &= ~VM_PROT_WRITE; 2232 vme->protection &= ~VM_PROT_WRITE; 2233 } if ((revokeperms & VM_PROT_READ) == 0) 2234 vme->eflags |= MAP_ENTRY_COW | 2235 MAP_ENTRY_NEEDS_COPY; 2236 } 2237 if (revokeperms & VM_PROT_EXECUTE) { 2238 vme->max_protection &= ~VM_PROT_EXECUTE; 2239 vme->protection &= ~VM_PROT_EXECUTE; 2240 } 2241 if (revokeperms & VM_PROT_READ) { 2242 vme->max_protection = 0; 2243 vme->protection = 0; 2244 } 2245 pmap_protect(map->pmap, vme->start, vme->end, 2246 vme->protection & ~revokeperms); 2247 vm_map_simplify_entry(map, vme); 2248 } 2249 vm_map_lock_downgrade(map); 2250 } 2251 vm_map_unlock_read(map); 2252} 2253 2254/* 2255 * When the subject's label changes, it may require revocation of privilege 2256 * to mapped objects. This can't be done on-the-fly later with a unified 2257 * buffer cache. 2258 */ 2259static void 2260mac_relabel_cred(struct ucred *cred, struct label *newlabel) 2261{ 2262 2263 MAC_PERFORM(relabel_cred, cred, newlabel); 2264 mac_cred_mmapped_drop_perms(curthread, cred); 2265} 2266 2267void 2268mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 2269{ 2270 2271 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 2272} 2273 2274void 2275mac_create_ifnet(struct ifnet *ifnet) 2276{ 2277 2278 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 2279} 2280 2281void 2282mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 2283{ 2284 2285 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 2286} 2287 2288void 2289mac_create_socket(struct ucred *cred, struct socket *socket) 2290{ 2291 2292 MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 2293} 2294 2295void 2296mac_create_pipe(struct ucred *cred, struct pipe *pipe) 2297{ 2298 2299 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 2300} 2301 2302void 2303mac_create_socket_from_socket(struct socket *oldsocket, 2304 struct socket *newsocket) 2305{ 2306 2307 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 2308 newsocket, &newsocket->so_label); 2309} 2310 2311static void 2312mac_relabel_socket(struct ucred *cred, struct socket *socket, 2313 struct label *newlabel) 2314{ 2315 2316 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 2317} 2318 2319static void 2320mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 2321{ 2322 2323 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 2324} 2325 2326void 2327mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 2328{ 2329 2330 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 2331 socket, &socket->so_peerlabel); 2332} 2333 2334void 2335mac_set_socket_peer_from_socket(struct socket *oldsocket, 2336 struct socket *newsocket) 2337{ 2338 2339 MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 2340 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 2341} 2342 2343void 2344mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 2345{ 2346 2347 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 2348 datagram, &datagram->m_pkthdr.label); 2349} 2350 2351void 2352mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 2353{ 2354 2355 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 2356 fragment, &fragment->m_pkthdr.label); 2357} 2358 2359void 2360mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 2361{ 2362 2363 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2364 &ipq->ipq_label); 2365} 2366 2367void 2368mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2369{ 2370 2371 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 2372 newmbuf, &newmbuf->m_pkthdr.label); 2373} 2374 2375void 2376mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 2377{ 2378 2379 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 2380 &mbuf->m_pkthdr.label); 2381} 2382 2383void 2384mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 2385{ 2386 2387 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 2388 &mbuf->m_pkthdr.label); 2389} 2390 2391void 2392mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 2393{ 2394 2395 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 2396 &mbuf->m_pkthdr.label); 2397} 2398 2399void 2400mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 2401 struct mbuf *newmbuf) 2402{ 2403 2404 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 2405 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 2406 &newmbuf->m_pkthdr.label); 2407} 2408 2409void 2410mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2411{ 2412 2413 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 2414 newmbuf, &newmbuf->m_pkthdr.label); 2415} 2416 2417int 2418mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 2419{ 2420 int result; 2421 2422 result = 1; 2423 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 2424 ipq, &ipq->ipq_label); 2425 2426 return (result); 2427} 2428 2429void 2430mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 2431{ 2432 2433 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2434 &ipq->ipq_label); 2435} 2436 2437void 2438mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 2439{ 2440 2441 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 2442 &mbuf->m_pkthdr.label); 2443} 2444 2445void 2446mac_create_mount(struct ucred *cred, struct mount *mp) 2447{ 2448 2449 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 2450 &mp->mnt_fslabel); 2451} 2452 2453void 2454mac_create_root_mount(struct ucred *cred, struct mount *mp) 2455{ 2456 2457 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 2458 &mp->mnt_fslabel); 2459} 2460 2461int 2462mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 2463{ 2464 int error; 2465 2466 if (!mac_enforce_network) 2467 return (0); 2468 2469 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 2470 &ifnet->if_label); 2471 2472 return (error); 2473} 2474 2475static int 2476mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 2477{ 2478 int error; 2479 2480 MAC_CHECK(check_cred_relabel, cred, newlabel); 2481 2482 return (error); 2483} 2484 2485int 2486mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 2487{ 2488 int error; 2489 2490 if (!mac_enforce_process) 2491 return (0); 2492 2493 MAC_CHECK(check_cred_visible, u1, u2); 2494 2495 return (error); 2496} 2497 2498int 2499mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 2500{ 2501 int error; 2502 2503 if (!mac_enforce_network) 2504 return (0); 2505 2506 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 2507 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 2508 printf("%s%d: not initialized\n", ifnet->if_name, 2509 ifnet->if_unit); 2510 2511 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 2512 &mbuf->m_pkthdr.label); 2513 2514 return (error); 2515} 2516 2517int 2518mac_check_mount_stat(struct ucred *cred, struct mount *mount) 2519{ 2520 int error; 2521 2522 if (!mac_enforce_fs) 2523 return (0); 2524 2525 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 2526 2527 return (error); 2528} 2529 2530int 2531mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 2532 void *data) 2533{ 2534 int error; 2535 2536 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 2537 2538 return (error); 2539} 2540 2541int 2542mac_check_pipe_op(struct ucred *cred, struct pipe *pipe, int op) 2543{ 2544 int error; 2545 2546 MAC_CHECK(check_pipe_op, cred, pipe, pipe->pipe_label, op); 2547 2548 return (error); 2549} 2550 2551static int 2552mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 2553 struct label *newlabel) 2554{ 2555 int error; 2556 2557 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 2558 2559 return (error); 2560} 2561 2562int 2563mac_check_proc_debug(struct ucred *cred, struct proc *proc) 2564{ 2565 int error; 2566 2567 PROC_LOCK_ASSERT(proc, MA_OWNED); 2568 2569 if (!mac_enforce_process) 2570 return (0); 2571 2572 MAC_CHECK(check_proc_debug, cred, proc); 2573 2574 return (error); 2575} 2576 2577int 2578mac_check_proc_sched(struct ucred *cred, struct proc *proc) 2579{ 2580 int error; 2581 2582 PROC_LOCK_ASSERT(proc, MA_OWNED); 2583 2584 if (!mac_enforce_process) 2585 return (0); 2586 2587 MAC_CHECK(check_proc_sched, cred, proc); 2588 2589 return (error); 2590} 2591 2592int 2593mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 2594{ 2595 int error; 2596 2597 PROC_LOCK_ASSERT(proc, MA_OWNED); 2598 2599 if (!mac_enforce_process) 2600 return (0); 2601 2602 MAC_CHECK(check_proc_signal, cred, proc, signum); 2603 2604 return (error); 2605} 2606 2607int 2608mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 2609 struct sockaddr *sockaddr) 2610{ 2611 int error; 2612 2613 if (!mac_enforce_socket) 2614 return (0); 2615 2616 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 2617 sockaddr); 2618 2619 return (error); 2620} 2621 2622int 2623mac_check_socket_connect(struct ucred *cred, struct socket *socket, 2624 struct sockaddr *sockaddr) 2625{ 2626 int error; 2627 2628 if (!mac_enforce_socket) 2629 return (0); 2630 2631 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 2632 sockaddr); 2633 2634 return (error); 2635} 2636 2637int 2638mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2639{ 2640 int error; 2641 2642 if (!mac_enforce_socket) 2643 return (0); 2644 2645 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2646 &mbuf->m_pkthdr.label); 2647 2648 return (error); 2649} 2650 2651int 2652mac_check_socket_listen(struct ucred *cred, struct socket *socket) 2653{ 2654 int error; 2655 2656 if (!mac_enforce_socket) 2657 return (0); 2658 2659 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 2660 return (error); 2661} 2662 2663static int 2664mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 2665 struct label *newlabel) 2666{ 2667 int error; 2668 2669 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 2670 newlabel); 2671 2672 return (error); 2673} 2674 2675int 2676mac_check_socket_visible(struct ucred *cred, struct socket *socket) 2677{ 2678 int error; 2679 2680 if (!mac_enforce_socket) 2681 return (0); 2682 2683 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 2684 2685 return (error); 2686} 2687 2688int 2689mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 2690 struct ifnet *ifnet) 2691{ 2692 struct mac label; 2693 int error; 2694 2695 error = mac_externalize(&ifnet->if_label, &label); 2696 if (error) 2697 return (error); 2698 2699 return (copyout(&label, ifr->ifr_ifru.ifru_data, sizeof(label))); 2700} 2701 2702int 2703mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 2704 struct ifnet *ifnet) 2705{ 2706 struct mac newlabel; 2707 struct label intlabel; 2708 int error; 2709 2710 error = copyin(ifr->ifr_ifru.ifru_data, &newlabel, sizeof(newlabel)); 2711 if (error) 2712 return (error); 2713 2714 error = mac_internalize(&intlabel, &newlabel); 2715 if (error) 2716 return (error); 2717 2718 /* 2719 * XXX: Note that this is a redundant privilege check, since 2720 * policies impose this check themselves if required by the 2721 * policy. Eventually, this should go away. 2722 */ 2723 error = suser_cred(cred, 0); 2724 if (error) 2725 goto out; 2726 2727 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 2728 &intlabel); 2729 if (error) 2730 goto out; 2731 2732 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 2733 2734out: 2735 mac_destroy_temp(&intlabel); 2736 return (error); 2737} 2738 2739void 2740mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp) 2741{ 2742 2743 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 2744} 2745 2746void 2747mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 2748{ 2749 2750 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 2751} 2752 2753static int 2754mac_stdcreatevnode_ea(struct vnode *vp) 2755{ 2756 int error; 2757 2758 MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); 2759 2760 return (error); 2761} 2762 2763void 2764mac_create_devfs_directory(char *dirname, int dirnamelen, 2765 struct devfs_dirent *de) 2766{ 2767 2768 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 2769 &de->de_label); 2770} 2771 2772/* 2773 * When a new vnode is created, this call will initialize its label. 2774 */ 2775void 2776mac_create_vnode(struct ucred *cred, struct vnode *parent, 2777 struct vnode *child) 2778{ 2779 int error; 2780 2781 ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); 2782 ASSERT_VOP_LOCKED(child, "mac_create_vnode"); 2783 2784 error = vn_refreshlabel(parent, cred); 2785 if (error) { 2786 printf("mac_create_vnode: vn_refreshlabel returned %d\n", 2787 error); 2788 printf("mac_create_vnode: using old vnode label\n"); 2789 } 2790 2791 MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, 2792 &child->v_label); 2793} 2794 2795int 2796mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 2797 struct mac *extmac) 2798{ 2799 struct label intlabel; 2800 int error; 2801 2802 error = mac_internalize(&intlabel, extmac); 2803 if (error) 2804 return (error); 2805 2806 mac_check_socket_relabel(cred, so, &intlabel); 2807 if (error) { 2808 mac_destroy_temp(&intlabel); 2809 return (error); 2810 } 2811 2812 mac_relabel_socket(cred, so, &intlabel); 2813 2814 mac_destroy_temp(&intlabel); 2815 return (0); 2816} 2817 2818int 2819mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 2820{ 2821 int error; 2822 2823 error = mac_check_pipe_relabel(cred, pipe, label); 2824 if (error) 2825 return (error); 2826 2827 mac_relabel_pipe(cred, pipe, label); 2828 2829 return (0); 2830} 2831 2832int 2833mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 2834 struct mac *extmac) 2835{ 2836 2837 return (mac_externalize(&so->so_label, extmac)); 2838} 2839 2840int 2841mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 2842 struct mac *extmac) 2843{ 2844 2845 return (mac_externalize(&so->so_peerlabel, extmac)); 2846} 2847 2848/* 2849 * Implementation of VOP_SETLABEL() that relies on extended attributes 2850 * to store label data. Can be referenced by filesystems supporting 2851 * extended attributes. 2852 */ 2853int 2854vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 2855{ 2856 struct vnode *vp = ap->a_vp; 2857 struct label *intlabel = ap->a_label; 2858 struct mac extmac; 2859 int error; 2860 2861 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 2862 2863 /* 2864 * XXX: Eventually call out to EA check/set calls here. 2865 * Be particularly careful to avoid race conditions, 2866 * consistency problems, and stability problems when 2867 * dealing with multiple EAs. In particular, we require 2868 * the ability to write multiple EAs on the same file in 2869 * a single transaction, which the current EA interface 2870 * does not provide. 2871 */ 2872 2873 error = mac_externalize(intlabel, &extmac); 2874 if (error) 2875 return (error); 2876 2877 error = vn_extattr_set(vp, IO_NODELOCKED, 2878 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 2879 sizeof(extmac), (char *)&extmac, curthread); 2880 if (error) 2881 return (error); 2882 2883 mac_relabel_vnode(ap->a_cred, vp, intlabel); 2884 2885 vp->v_vflag |= VV_CACHEDLABEL; 2886 2887 return (0); 2888} 2889 2890static int 2891vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 2892{ 2893 int error; 2894 2895 if (vp->v_mount == NULL) { 2896 /* printf("vn_setlabel: null v_mount\n"); */ 2897 if (vp->v_tag != VT_NON) 2898 printf("vn_setlabel: null v_mount with non-VT_NON\n"); 2899 return (EBADF); 2900 } 2901 2902 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2903 return (EOPNOTSUPP); 2904 2905 /* 2906 * Multi-phase commit. First check the policies to confirm the 2907 * change is OK. Then commit via the filesystem. Finally, 2908 * update the actual vnode label. Question: maybe the filesystem 2909 * should update the vnode at the end as part of VOP_SETLABEL()? 2910 */ 2911 error = mac_check_vnode_relabel(cred, vp, intlabel); 2912 if (error) 2913 return (error); 2914 2915 /* 2916 * VADMIN provides the opportunity for the filesystem to make 2917 * decisions about who is and is not able to modify labels 2918 * and protections on files. This might not be right. We can't 2919 * assume VOP_SETLABEL() will do it, because we might implement 2920 * that as part of vop_stdsetlabel_ea(). 2921 */ 2922 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 2923 if (error) 2924 return (error); 2925 2926 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 2927 if (error) 2928 return (error); 2929 2930 return (0); 2931} 2932 2933/* 2934 * MPSAFE 2935 */ 2936int 2937__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 2938{ 2939 struct mac extmac; 2940 int error; 2941 2942 error = mac_externalize(&td->td_ucred->cr_label, &extmac); 2943 if (error == 0) 2944 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 2945 2946 return (error); 2947} 2948 2949/* 2950 * MPSAFE 2951 * 2952 * XXX: Needs to be re-written for proc locking. 2953 */ 2954int 2955__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 2956{ 2957 struct ucred *newcred, *oldcred; 2958 struct proc *p; 2959 struct mac extmac; 2960 struct label intlabel; 2961 int error; 2962 2963 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 2964 if (error) 2965 return (error); 2966 2967 error = mac_internalize(&intlabel, &extmac); 2968 if (error) 2969 return (error); 2970 2971 newcred = crget(); 2972 2973 p = td->td_proc; 2974 PROC_LOCK(p); 2975 oldcred = p->p_ucred; 2976 2977 error = mac_check_cred_relabel(oldcred, &intlabel); 2978 if (error) { 2979 PROC_UNLOCK(p); 2980 mac_destroy_temp(&intlabel); 2981 crfree(newcred); 2982 return (error); 2983 } 2984 2985 setsugid(p); 2986 crcopy(newcred, oldcred); 2987 PROC_UNLOCK(p); 2988 mac_relabel_cred(newcred, &intlabel); 2989 2990 PROC_LOCK(p); 2991 p->p_ucred = newcred; 2992 PROC_UNLOCK(p); 2993 crfree(oldcred); 2994 mac_destroy_temp(&intlabel); 2995 return (0); 2996} 2997 2998/* 2999 * MPSAFE 3000 */ 3001int 3002__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3003{ 3004 struct file *fp; 3005 struct mac extmac; 3006 struct vnode *vp; 3007 struct pipe *pipe; 3008 int error; 3009 3010 mtx_lock(&Giant); 3011 3012 error = fget(td, SCARG(uap, fd), &fp); 3013 if (error) 3014 goto out; 3015 3016 switch (fp->f_type) { 3017 case DTYPE_FIFO: 3018 case DTYPE_VNODE: 3019 vp = (struct vnode *)fp->f_data; 3020 3021 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3022 error = vn_refreshlabel(vp, td->td_ucred); 3023 if (error == 0) 3024 error = mac_externalize(&vp->v_label, &extmac); 3025 VOP_UNLOCK(vp, 0, td); 3026 break; 3027 case DTYPE_PIPE: 3028 pipe = (struct pipe *)fp->f_data; 3029 error = mac_externalize(pipe->pipe_label, &extmac); 3030 break; 3031 default: 3032 error = EINVAL; 3033 } 3034 3035 if (error == 0) 3036 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 3037 3038 fdrop(fp, td); 3039 3040out: 3041 mtx_unlock(&Giant); 3042 return (error); 3043} 3044 3045/* 3046 * MPSAFE 3047 */ 3048int 3049__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3050{ 3051 struct nameidata nd; 3052 struct mac extmac; 3053 int error; 3054 3055 mtx_lock(&Giant); 3056 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 3057 SCARG(uap, path_p), td); 3058 error = namei(&nd); 3059 if (error) 3060 goto out; 3061 3062 error = vn_refreshlabel(nd.ni_vp, td->td_ucred); 3063 if (error == 0) 3064 error = mac_externalize(&nd.ni_vp->v_label, &extmac); 3065 NDFREE(&nd, 0); 3066 if (error) 3067 goto out; 3068 3069 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 3070 3071out: 3072 mtx_unlock(&Giant); 3073 return (error); 3074} 3075 3076/* 3077 * MPSAFE 3078 */ 3079int 3080__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3081{ 3082 struct file *fp; 3083 struct mac extmac; 3084 struct label intlabel; 3085 struct mount *mp; 3086 struct vnode *vp; 3087 struct pipe *pipe; 3088 int error; 3089 3090 mtx_lock(&Giant); 3091 error = fget(td, SCARG(uap, fd), &fp); 3092 if (error) 3093 goto out1; 3094 3095 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 3096 if (error) 3097 goto out2; 3098 3099 error = mac_internalize(&intlabel, &extmac); 3100 if (error) 3101 goto out2; 3102 3103 switch (fp->f_type) { 3104 case DTYPE_FIFO: 3105 case DTYPE_VNODE: 3106 vp = (struct vnode *)fp->f_data; 3107 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3108 if (error != 0) 3109 break; 3110 3111 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3112 error = vn_setlabel(vp, &intlabel, td->td_ucred); 3113 VOP_UNLOCK(vp, 0, td); 3114 vn_finished_write(mp); 3115 mac_destroy_temp(&intlabel); 3116 break; 3117 case DTYPE_PIPE: 3118 pipe = (struct pipe *)fp->f_data; 3119 error = mac_pipe_label_set(td->td_ucred, pipe, &intlabel); 3120 break; 3121 default: 3122 error = EINVAL; 3123 } 3124 3125out2: 3126 fdrop(fp, td); 3127out1: 3128 mtx_unlock(&Giant); 3129 return (error); 3130} 3131 3132/* 3133 * MPSAFE 3134 */ 3135int 3136__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3137{ 3138 struct nameidata nd; 3139 struct mac extmac; 3140 struct label intlabel; 3141 struct mount *mp; 3142 int error; 3143 3144 mtx_lock(&Giant); 3145 3146 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 3147 if (error) 3148 goto out; 3149 3150 error = mac_internalize(&intlabel, &extmac); 3151 if (error) 3152 goto out; 3153 3154 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 3155 SCARG(uap, path_p), td); 3156 error = namei(&nd); 3157 if (error) 3158 goto out2; 3159 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3160 if (error) 3161 goto out2; 3162 3163 error = vn_setlabel(nd.ni_vp, &intlabel, td->td_ucred); 3164 3165 vn_finished_write(mp); 3166out2: 3167 mac_destroy_temp(&intlabel); 3168 NDFREE(&nd, 0); 3169out: 3170 mtx_unlock(&Giant); 3171 return (error); 3172} 3173 3174SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 3175SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 3176 3177#else /* !MAC */ 3178 3179int 3180__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3181{ 3182 3183 return (ENOSYS); 3184} 3185 3186int 3187__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3188{ 3189 3190 return (ENOSYS); 3191} 3192 3193int 3194__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3195{ 3196 3197 return (ENOSYS); 3198} 3199 3200int 3201__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3202{ 3203 3204 return (ENOSYS); 3205} 3206 3207int 3208__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3209{ 3210 3211 return (ENOSYS); 3212} 3213 3214int 3215__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3216{ 3217 3218 return (ENOSYS); 3219} 3220 3221#endif /* !MAC */ 3222