mac_internal.h revision 102103
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_internal.h 102103 2002-08-19 15:30:30Z 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_OP: 759 mpc->mpc_ops->mpo_check_vnode_op = 760 mpe->mpe_function; 761 break; 762 case MAC_CHECK_VNODE_OPEN: 763 mpc->mpc_ops->mpo_check_vnode_open = 764 mpe->mpe_function; 765 break; 766 case MAC_CHECK_VNODE_READDIR: 767 mpc->mpc_ops->mpo_check_vnode_readdir = 768 mpe->mpe_function; 769 break; 770 case MAC_CHECK_VNODE_READLINK: 771 mpc->mpc_ops->mpo_check_vnode_readlink = 772 mpe->mpe_function; 773 break; 774 case MAC_CHECK_VNODE_RELABEL: 775 mpc->mpc_ops->mpo_check_vnode_relabel = 776 mpe->mpe_function; 777 break; 778 case MAC_CHECK_VNODE_RENAME_FROM: 779 mpc->mpc_ops->mpo_check_vnode_rename_from = 780 mpe->mpe_function; 781 break; 782 case MAC_CHECK_VNODE_RENAME_TO: 783 mpc->mpc_ops->mpo_check_vnode_rename_to = 784 mpe->mpe_function; 785 break; 786 case MAC_CHECK_VNODE_REVOKE: 787 mpc->mpc_ops->mpo_check_vnode_revoke = 788 mpe->mpe_function; 789 break; 790 case MAC_CHECK_VNODE_SETACL: 791 mpc->mpc_ops->mpo_check_vnode_setacl = 792 mpe->mpe_function; 793 break; 794 case MAC_CHECK_VNODE_SETEXTATTR: 795 mpc->mpc_ops->mpo_check_vnode_setextattr = 796 mpe->mpe_function; 797 break; 798 case MAC_CHECK_VNODE_SETFLAGS: 799 mpc->mpc_ops->mpo_check_vnode_setflags = 800 mpe->mpe_function; 801 break; 802 case MAC_CHECK_VNODE_SETMODE: 803 mpc->mpc_ops->mpo_check_vnode_setmode = 804 mpe->mpe_function; 805 break; 806 case MAC_CHECK_VNODE_SETOWNER: 807 mpc->mpc_ops->mpo_check_vnode_setowner = 808 mpe->mpe_function; 809 break; 810 case MAC_CHECK_VNODE_SETUTIMES: 811 mpc->mpc_ops->mpo_check_vnode_setutimes = 812 mpe->mpe_function; 813 break; 814 case MAC_CHECK_VNODE_STAT: 815 mpc->mpc_ops->mpo_check_vnode_stat = 816 mpe->mpe_function; 817 break; 818/* 819 default: 820 printf("MAC policy `%s': unknown operation %d\n", 821 mpc->mpc_name, mpe->mpe_constant); 822 return (EINVAL); 823*/ 824 } 825 } 826 MAC_POLICY_LIST_LOCK(); 827 if (mac_policy_list_busy > 0) { 828 MAC_POLICY_LIST_UNLOCK(); 829 FREE(mpc->mpc_ops, M_MACOPVEC); 830 mpc->mpc_ops = NULL; 831 return (EBUSY); 832 } 833 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 834 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 835 MAC_POLICY_LIST_UNLOCK(); 836 FREE(mpc->mpc_ops, M_MACOPVEC); 837 mpc->mpc_ops = NULL; 838 return (EEXIST); 839 } 840 } 841 if (mpc->mpc_field_off != NULL) { 842 slot = ffs(mac_policy_offsets_free); 843 if (slot == 0) { 844 MAC_POLICY_LIST_UNLOCK(); 845 FREE(mpc->mpc_ops, M_MACOPVEC); 846 mpc->mpc_ops = NULL; 847 return (ENOMEM); 848 } 849 slot--; 850 mac_policy_offsets_free &= ~(1 << slot); 851 *mpc->mpc_field_off = slot; 852 } 853 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 854 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 855 856 /* Per-policy initialization. */ 857 if (mpc->mpc_ops->mpo_init != NULL) 858 (*(mpc->mpc_ops->mpo_init))(mpc); 859 MAC_POLICY_LIST_UNLOCK(); 860 861 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 862 mpc->mpc_name); 863 864 return (0); 865} 866 867static int 868mac_policy_unregister(struct mac_policy_conf *mpc) 869{ 870 871#if 0 872 /* 873 * Don't allow unloading modules with private data. 874 */ 875 if (mpc->mpc_field_off != NULL) 876 return (EBUSY); 877#endif 878 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) 879 return (EBUSY); 880 MAC_POLICY_LIST_LOCK(); 881 if (mac_policy_list_busy > 0) { 882 MAC_POLICY_LIST_UNLOCK(); 883 return (EBUSY); 884 } 885 if (mpc->mpc_ops->mpo_destroy != NULL) 886 (*(mpc->mpc_ops->mpo_destroy))(mpc); 887 888 LIST_REMOVE(mpc, mpc_list); 889 MAC_POLICY_LIST_UNLOCK(); 890 891 FREE(mpc->mpc_ops, M_MACOPVEC); 892 mpc->mpc_ops = NULL; 893 894 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 895 mpc->mpc_name); 896 897 return (0); 898} 899 900/* 901 * Define an error value precedence, and given two arguments, selects the 902 * value with the higher precedence. 903 */ 904static int 905error_select(int error1, int error2) 906{ 907 908 /* Certain decision-making errors take top priority. */ 909 if (error1 == EDEADLK || error2 == EDEADLK) 910 return (EDEADLK); 911 912 /* Invalid arguments should be reported where possible. */ 913 if (error1 == EINVAL || error2 == EINVAL) 914 return (EINVAL); 915 916 /* Precedence goes to "visibility", with both process and file. */ 917 if (error1 == ESRCH || error2 == ESRCH) 918 return (ESRCH); 919 920 if (error1 == ENOENT || error2 == ENOENT) 921 return (ENOENT); 922 923 /* Precedence goes to DAC/MAC protections. */ 924 if (error1 == EACCES || error2 == EACCES) 925 return (EACCES); 926 927 /* Precedence goes to privilege. */ 928 if (error1 == EPERM || error2 == EPERM) 929 return (EPERM); 930 931 /* Precedence goes to error over success; otherwise, arbitrary. */ 932 if (error1 != 0) 933 return (error1); 934 return (error2); 935} 936 937void 938mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 939{ 940 941 MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 942} 943 944void 945mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) 946{ 947 948 MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); 949} 950 951/* 952 * Support callout for policies that manage their own externalization 953 * using extended attributes. 954 */ 955static int 956mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) 957{ 958 int error; 959 960 MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, 961 &mp->mnt_fslabel); 962 963 return (error); 964} 965 966/* 967 * Given an externalized mac label, internalize it and stamp it on a 968 * vnode. 969 */ 970static int 971mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac) 972{ 973 int error; 974 975 MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); 976 977 return (error); 978} 979 980/* 981 * Call out to individual policies to update the label in a vnode from 982 * the mountpoint. 983 */ 984void 985mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) 986{ 987 988 MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, 989 &mp->mnt_fslabel); 990 991 ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); 992 if (mac_cache_fslabel_in_vnode) 993 vp->v_vflag |= VV_CACHEDLABEL; 994} 995 996/* 997 * Implementation of VOP_REFRESHLABEL() that relies on extended attributes 998 * to store label data. Can be referenced by filesystems supporting 999 * extended attributes. 1000 */ 1001int 1002vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) 1003{ 1004 struct vnode *vp = ap->a_vp; 1005 struct mac extmac; 1006 int buflen, error; 1007 1008 ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); 1009 1010 /* 1011 * Call out to external policies first. Order doesn't really 1012 * matter, as long as failure of one assures failure of all. 1013 */ 1014 error = mac_update_vnode_from_extattr(vp, vp->v_mount); 1015 if (error) 1016 return (error); 1017 1018 buflen = sizeof(extmac); 1019 error = vn_extattr_get(vp, IO_NODELOCKED, 1020 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, 1021 (char *)&extmac, curthread); 1022 switch (error) { 1023 case 0: 1024 /* Got it */ 1025 break; 1026 1027 case ENOATTR: 1028 /* 1029 * Use the label from the mount point. 1030 */ 1031 mac_update_vnode_from_mount(vp, vp->v_mount); 1032 return (0); 1033 1034 case EOPNOTSUPP: 1035 default: 1036 /* Fail horribly. */ 1037 return (error); 1038 } 1039 1040 if (buflen != sizeof(extmac)) 1041 error = EPERM; /* Fail very closed. */ 1042 if (error == 0) 1043 error = mac_update_vnode_from_externalized(vp, &extmac); 1044 if (error == 0) 1045 vp->v_vflag |= VV_CACHEDLABEL; 1046 else { 1047 struct vattr va; 1048 1049 printf("Corrupted label on %s", 1050 vp->v_mount->mnt_stat.f_mntonname); 1051 if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) 1052 printf(" inum %ld", va.va_fileid); 1053 if (mac_debug_label_fallback) { 1054 printf(", falling back.\n"); 1055 mac_update_vnode_from_mount(vp, vp->v_mount); 1056 error = 0; 1057 } else { 1058 printf(".\n"); 1059 error = EPERM; 1060 } 1061 } 1062 1063 return (error); 1064} 1065 1066/* 1067 * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle 1068 * the labeling activity outselves. Filesystems should be careful not 1069 * to change their minds regarding whether they support vop_refreshlabel() 1070 * for a vnode or not. Don't cache the vnode here, allow the file 1071 * system code to determine if it's safe to cache. If we update from 1072 * the mount, don't cache since a change to the mount label should affect 1073 * all vnodes. 1074 */ 1075static int 1076vn_refreshlabel(struct vnode *vp, struct ucred *cred) 1077{ 1078 int error; 1079 1080 ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); 1081 1082 if (vp->v_mount == NULL) { 1083/* 1084 Eventually, we probably want to special-case refreshing 1085 of deadfs vnodes, and if there's a lock-free race somewhere, 1086 that case might be handled here. 1087 1088 mac_update_vnode_deadfs(vp); 1089 return (0); 1090 */ 1091 /* printf("vn_refreshlabel: null v_mount\n"); */ 1092 if (vp->v_tag != VT_NON) 1093 printf( 1094 "vn_refreshlabel: null v_mount with non-VT_NON\n"); 1095 return (EBADF); 1096 } 1097 1098 if (vp->v_vflag & VV_CACHEDLABEL) { 1099 mac_vnode_label_cache_hits++; 1100 return (0); 1101 } else 1102 mac_vnode_label_cache_misses++; 1103 1104 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 1105 mac_update_vnode_from_mount(vp, vp->v_mount); 1106 return (0); 1107 } 1108 1109 error = VOP_REFRESHLABEL(vp, cred, curthread); 1110 switch (error) { 1111 case EOPNOTSUPP: 1112 /* 1113 * If labels are not supported on this vnode, fall back to 1114 * the label in the mount and propagate it to the vnode. 1115 * There should probably be some sort of policy/flag/decision 1116 * about doing this. 1117 */ 1118 mac_update_vnode_from_mount(vp, vp->v_mount); 1119 error = 0; 1120 default: 1121 return (error); 1122 } 1123} 1124 1125/* 1126 * Helper function for file systems using the vop_std*_ea() calls. This 1127 * function must be called after EA service is available for the vnode, 1128 * but before it's hooked up to the namespace so that the node persists 1129 * if there's a crash, or before it can be accessed. On successful 1130 * commit of the label to disk (etc), do cache the label. 1131 */ 1132int 1133vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) 1134{ 1135 struct mac extmac; 1136 int error; 1137 1138 ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); 1139 if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 1140 mac_update_vnode_from_mount(tvp, tvp->v_mount); 1141 } else { 1142 error = vn_refreshlabel(dvp, cred); 1143 if (error) 1144 return (error); 1145 1146 /* 1147 * Stick the label in the vnode. Then try to write to 1148 * disk. If we fail, return a failure to abort the 1149 * create operation. Really, this failure shouldn't 1150 * happen except in fairly unusual circumstances (out 1151 * of disk, etc). 1152 */ 1153 mac_create_vnode(cred, dvp, tvp); 1154 1155 error = mac_stdcreatevnode_ea(tvp); 1156 if (error) 1157 return (error); 1158 1159 /* 1160 * XXX: Eventually this will go away and all policies will 1161 * directly manage their extended attributes. 1162 */ 1163 error = mac_externalize(&tvp->v_label, &extmac); 1164 if (error) 1165 return (error); 1166 1167 error = vn_extattr_set(tvp, IO_NODELOCKED, 1168 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 1169 sizeof(extmac), (char *)&extmac, curthread); 1170 if (error == 0) 1171 tvp->v_vflag |= VV_CACHEDLABEL; 1172 else { 1173#if 0 1174 /* 1175 * In theory, we could have fall-back behavior here. 1176 * It would probably be incorrect. 1177 */ 1178#endif 1179 return (error); 1180 } 1181 } 1182 1183 return (0); 1184} 1185 1186void 1187mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) 1188{ 1189 int error; 1190 1191 ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 1192 1193 error = vn_refreshlabel(vp, old); 1194 if (error) { 1195 printf("mac_execve_transition: vn_refreshlabel returned %d\n", 1196 error); 1197 printf("mac_execve_transition: using old vnode label\n"); 1198 } 1199 1200 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); 1201} 1202 1203int 1204mac_execve_will_transition(struct ucred *old, struct vnode *vp) 1205{ 1206 int error, result; 1207 1208 error = vn_refreshlabel(vp, old); 1209 if (error) 1210 return (error); 1211 1212 result = 0; 1213 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); 1214 1215 return (result); 1216} 1217 1218static void 1219mac_init_label(struct label *label) 1220{ 1221 1222 bzero(label, sizeof(*label)); 1223 label->l_flags = MAC_FLAG_INITIALIZED; 1224} 1225 1226static void 1227mac_init_structmac(struct mac *mac) 1228{ 1229 1230 bzero(mac, sizeof(*mac)); 1231 mac->m_macflags = MAC_FLAG_INITIALIZED; 1232} 1233 1234static void 1235mac_destroy_label(struct label *label) 1236{ 1237 1238 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 1239 ("destroying uninitialized label")); 1240 1241 bzero(label, sizeof(*label)); 1242 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 1243} 1244 1245int 1246mac_init_mbuf(struct mbuf *m, int how) 1247{ 1248 KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 1249 1250 /* "how" is one of M_(TRY|DONT)WAIT */ 1251 mac_init_label(&m->m_pkthdr.label); 1252 MAC_PERFORM(init_mbuf, m, how, &m->m_pkthdr.label); 1253#ifdef MAC_DEBUG 1254 atomic_add_int(&nmacmbufs, 1); 1255#endif 1256 return (0); 1257} 1258 1259void 1260mac_destroy_mbuf(struct mbuf *m) 1261{ 1262 1263 MAC_PERFORM(destroy_mbuf, m, &m->m_pkthdr.label); 1264 mac_destroy_label(&m->m_pkthdr.label); 1265#ifdef MAC_DEBUG 1266 atomic_subtract_int(&nmacmbufs, 1); 1267#endif 1268} 1269 1270void 1271mac_init_cred(struct ucred *cr) 1272{ 1273 1274 mac_init_label(&cr->cr_label); 1275 MAC_PERFORM(init_cred, cr, &cr->cr_label); 1276#ifdef MAC_DEBUG 1277 atomic_add_int(&nmaccreds, 1); 1278#endif 1279} 1280 1281void 1282mac_destroy_cred(struct ucred *cr) 1283{ 1284 1285 MAC_PERFORM(destroy_cred, cr, &cr->cr_label); 1286 mac_destroy_label(&cr->cr_label); 1287#ifdef MAC_DEBUG 1288 atomic_subtract_int(&nmaccreds, 1); 1289#endif 1290} 1291 1292void 1293mac_init_ifnet(struct ifnet *ifp) 1294{ 1295 1296 mac_init_label(&ifp->if_label); 1297 MAC_PERFORM(init_ifnet, ifp, &ifp->if_label); 1298#ifdef MAC_DEBUG 1299 atomic_add_int(&nmacifnets, 1); 1300#endif 1301} 1302 1303void 1304mac_destroy_ifnet(struct ifnet *ifp) 1305{ 1306 1307 MAC_PERFORM(destroy_ifnet, ifp, &ifp->if_label); 1308 mac_destroy_label(&ifp->if_label); 1309#ifdef MAC_DEBUG 1310 atomic_subtract_int(&nmacifnets, 1); 1311#endif 1312} 1313 1314void 1315mac_init_ipq(struct ipq *ipq) 1316{ 1317 1318 mac_init_label(&ipq->ipq_label); 1319 MAC_PERFORM(init_ipq, ipq, &ipq->ipq_label); 1320#ifdef MAC_DEBUG 1321 atomic_add_int(&nmacipqs, 1); 1322#endif 1323} 1324 1325void 1326mac_destroy_ipq(struct ipq *ipq) 1327{ 1328 1329 MAC_PERFORM(destroy_ipq, ipq, &ipq->ipq_label); 1330 mac_destroy_label(&ipq->ipq_label); 1331#ifdef MAC_DEBUG 1332 atomic_subtract_int(&nmacipqs, 1); 1333#endif 1334} 1335 1336void 1337mac_init_socket(struct socket *socket) 1338{ 1339 1340 mac_init_label(&socket->so_label); 1341 mac_init_label(&socket->so_peerlabel); 1342 MAC_PERFORM(init_socket, socket, &socket->so_label, 1343 &socket->so_peerlabel); 1344#ifdef MAC_DEBUG 1345 atomic_add_int(&nmacsockets, 1); 1346#endif 1347} 1348 1349void 1350mac_destroy_socket(struct socket *socket) 1351{ 1352 1353 MAC_PERFORM(destroy_socket, socket, &socket->so_label, 1354 &socket->so_peerlabel); 1355 mac_destroy_label(&socket->so_label); 1356 mac_destroy_label(&socket->so_peerlabel); 1357#ifdef MAC_DEBUG 1358 atomic_subtract_int(&nmacsockets, 1); 1359#endif 1360} 1361 1362void 1363mac_init_pipe(struct pipe *pipe) 1364{ 1365 struct label *label; 1366 1367 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 1368 mac_init_label(label); 1369 pipe->pipe_label = label; 1370 pipe->pipe_peer->pipe_label = label; 1371 MAC_PERFORM(init_pipe, pipe, pipe->pipe_label); 1372#ifdef MAC_DEBUG 1373 atomic_add_int(&nmacpipes, 1); 1374#endif 1375} 1376 1377void 1378mac_destroy_pipe(struct pipe *pipe) 1379{ 1380 1381 MAC_PERFORM(destroy_pipe, pipe, pipe->pipe_label); 1382 mac_destroy_label(pipe->pipe_label); 1383 free(pipe->pipe_label, M_MACPIPELABEL); 1384#ifdef MAC_DEBUG 1385 atomic_subtract_int(&nmacpipes, 1); 1386#endif 1387} 1388 1389void 1390mac_init_bpfdesc(struct bpf_d *bpf_d) 1391{ 1392 1393 mac_init_label(&bpf_d->bd_label); 1394 MAC_PERFORM(init_bpfdesc, bpf_d, &bpf_d->bd_label); 1395#ifdef MAC_DEBUG 1396 atomic_add_int(&nmacbpfdescs, 1); 1397#endif 1398} 1399 1400void 1401mac_destroy_bpfdesc(struct bpf_d *bpf_d) 1402{ 1403 1404 MAC_PERFORM(destroy_bpfdesc, bpf_d, &bpf_d->bd_label); 1405 mac_destroy_label(&bpf_d->bd_label); 1406#ifdef MAC_DEBUG 1407 atomic_subtract_int(&nmacbpfdescs, 1); 1408#endif 1409} 1410 1411void 1412mac_init_mount(struct mount *mp) 1413{ 1414 1415 mac_init_label(&mp->mnt_mntlabel); 1416 mac_init_label(&mp->mnt_fslabel); 1417 MAC_PERFORM(init_mount, mp, &mp->mnt_mntlabel, &mp->mnt_fslabel); 1418#ifdef MAC_DEBUG 1419 atomic_add_int(&nmacmounts, 1); 1420#endif 1421} 1422 1423void 1424mac_destroy_mount(struct mount *mp) 1425{ 1426 1427 MAC_PERFORM(destroy_mount, mp, &mp->mnt_mntlabel, &mp->mnt_fslabel); 1428 mac_destroy_label(&mp->mnt_fslabel); 1429 mac_destroy_label(&mp->mnt_mntlabel); 1430#ifdef MAC_DEBUG 1431 atomic_subtract_int(&nmacmounts, 1); 1432#endif 1433} 1434 1435static void 1436mac_init_temp(struct label *label) 1437{ 1438 1439 mac_init_label(label); 1440 MAC_PERFORM(init_temp, label); 1441#ifdef MAC_DEBUG 1442 atomic_add_int(&nmactemp, 1); 1443#endif 1444} 1445 1446static void 1447mac_destroy_temp(struct label *label) 1448{ 1449 1450 MAC_PERFORM(destroy_temp, label); 1451 mac_destroy_label(label); 1452#ifdef MAC_DEBUG 1453 atomic_subtract_int(&nmactemp, 1); 1454#endif 1455} 1456 1457void 1458mac_init_vnode(struct vnode *vp) 1459{ 1460 1461 mac_init_label(&vp->v_label); 1462 MAC_PERFORM(init_vnode, vp, &vp->v_label); 1463#ifdef MAC_DEBUG 1464 atomic_add_int(&nmacvnodes, 1); 1465#endif 1466} 1467 1468void 1469mac_destroy_vnode(struct vnode *vp) 1470{ 1471 1472 MAC_PERFORM(destroy_vnode, vp, &vp->v_label); 1473 mac_destroy_label(&vp->v_label); 1474#ifdef MAC_DEBUG 1475 atomic_subtract_int(&nmacvnodes, 1); 1476#endif 1477} 1478 1479void 1480mac_init_devfsdirent(struct devfs_dirent *de) 1481{ 1482 1483 mac_init_label(&de->de_label); 1484 MAC_PERFORM(init_devfsdirent, de, &de->de_label); 1485#ifdef MAC_DEBUG 1486 atomic_add_int(&nmacdevfsdirents, 1); 1487#endif 1488} 1489 1490void 1491mac_destroy_devfsdirent(struct devfs_dirent *de) 1492{ 1493 1494 MAC_PERFORM(destroy_devfsdirent, de, &de->de_label); 1495 mac_destroy_label(&de->de_label); 1496#ifdef MAC_DEBUG 1497 atomic_subtract_int(&nmacdevfsdirents, 1); 1498#endif 1499} 1500 1501static int 1502mac_externalize(struct label *label, struct mac *mac) 1503{ 1504 int error; 1505 1506 mac_init_structmac(mac); 1507 MAC_CHECK(externalize, label, mac); 1508 1509 return (error); 1510} 1511 1512static int 1513mac_internalize(struct label *label, struct mac *mac) 1514{ 1515 int error; 1516 1517 mac_init_temp(label); 1518 MAC_CHECK(internalize, label, mac); 1519 if (error) 1520 mac_destroy_temp(label); 1521 1522 return (error); 1523} 1524 1525/* 1526 * Initialize MAC label for the first kernel process, from which other 1527 * kernel processes and threads are spawned. 1528 */ 1529void 1530mac_create_proc0(struct ucred *cred) 1531{ 1532 1533 MAC_PERFORM(create_proc0, cred); 1534} 1535 1536/* 1537 * Initialize MAC label for the first userland process, from which other 1538 * userland processes and threads are spawned. 1539 */ 1540void 1541mac_create_proc1(struct ucred *cred) 1542{ 1543 1544 MAC_PERFORM(create_proc1, cred); 1545} 1546 1547/* 1548 * When a new process is created, its label must be initialized. Generally, 1549 * this involves inheritence from the parent process, modulo possible 1550 * deltas. This function allows that processing to take place. 1551 */ 1552void 1553mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 1554{ 1555 1556 MAC_PERFORM(create_cred, parent_cred, child_cred); 1557} 1558 1559int 1560mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) 1561{ 1562 int error; 1563 1564 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 1565 1566 if (!mac_enforce_fs) 1567 return (0); 1568 1569 error = vn_refreshlabel(vp, cred); 1570 if (error) 1571 return (error); 1572 1573 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); 1574 return (error); 1575} 1576 1577int 1578mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 1579{ 1580 int error; 1581 1582 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 1583 1584 if (!mac_enforce_fs) 1585 return (0); 1586 1587 error = vn_refreshlabel(dvp, cred); 1588 if (error) 1589 return (error); 1590 1591 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 1592 return (error); 1593} 1594 1595int 1596mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 1597{ 1598 int error; 1599 1600 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 1601 1602 if (!mac_enforce_fs) 1603 return (0); 1604 1605 error = vn_refreshlabel(dvp, cred); 1606 if (error) 1607 return (error); 1608 1609 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 1610 return (error); 1611} 1612 1613int 1614mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 1615 struct componentname *cnp, struct vattr *vap) 1616{ 1617 int error; 1618 1619 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 1620 1621 if (!mac_enforce_fs) 1622 return (0); 1623 1624 error = vn_refreshlabel(dvp, cred); 1625 if (error) 1626 return (error); 1627 1628 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 1629 return (error); 1630} 1631 1632int 1633mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 1634 struct componentname *cnp) 1635{ 1636 int error; 1637 1638 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 1639 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 1640 1641 if (!mac_enforce_fs) 1642 return (0); 1643 1644 error = vn_refreshlabel(dvp, cred); 1645 if (error) 1646 return (error); 1647 error = vn_refreshlabel(vp, cred); 1648 if (error) 1649 return (error); 1650 1651 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 1652 &vp->v_label, cnp); 1653 return (error); 1654} 1655 1656int 1657mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 1658 acl_type_t type) 1659{ 1660 int error; 1661 1662 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 1663 1664 if (!mac_enforce_fs) 1665 return (0); 1666 1667 error = vn_refreshlabel(vp, cred); 1668 if (error) 1669 return (error); 1670 1671 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 1672 return (error); 1673} 1674 1675int 1676mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) 1677{ 1678 int error; 1679 1680 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1681 1682 if (!mac_enforce_process && !mac_enforce_fs) 1683 return (0); 1684 1685 error = vn_refreshlabel(vp, cred); 1686 if (error) 1687 return (error); 1688 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); 1689 1690 return (error); 1691} 1692 1693int 1694mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 1695{ 1696 int error; 1697 1698 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 1699 1700 if (!mac_enforce_fs) 1701 return (0); 1702 1703 error = vn_refreshlabel(vp, cred); 1704 if (error) 1705 return (error); 1706 1707 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 1708 return (error); 1709} 1710 1711int 1712mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 1713 int attrnamespace, const char *name, struct uio *uio) 1714{ 1715 int error; 1716 1717 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 1718 1719 if (!mac_enforce_fs) 1720 return (0); 1721 1722 error = vn_refreshlabel(vp, cred); 1723 if (error) 1724 return (error); 1725 1726 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 1727 attrnamespace, name, uio); 1728 return (error); 1729} 1730 1731int 1732mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 1733 struct componentname *cnp) 1734{ 1735 int error; 1736 1737 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 1738 1739 if (!mac_enforce_fs) 1740 return (0); 1741 1742 error = vn_refreshlabel(dvp, cred); 1743 if (error) 1744 return (error); 1745 1746 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 1747 return (error); 1748} 1749 1750vm_prot_t 1751mac_check_vnode_mmap_prot(struct ucred *cred, struct vnode *vp, int newmapping) 1752{ 1753 vm_prot_t result = VM_PROT_ALL; 1754 1755 /* 1756 * This should be some sort of MAC_BITWISE, maybe :) 1757 */ 1758 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_perms"); 1759 MAC_BOOLEAN(check_vnode_mmap_perms, &, cred, vp, &vp->v_label, 1760 newmapping); 1761 return (result); 1762} 1763 1764int 1765mac_check_vnode_op(struct ucred *cred, struct vnode *vp, int op) 1766{ 1767 int error; 1768 1769 if (!mac_enforce_fs) 1770 return (0); 1771 1772 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_op"); 1773 1774 error = vn_refreshlabel(vp, cred); 1775 if (error) 1776 return (error); 1777 1778 MAC_CHECK(check_vnode_op, cred, vp, &vp->v_label, op); 1779 1780 return (error); 1781} 1782 1783int 1784mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) 1785{ 1786 int error; 1787 1788 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 1789 1790 if (!mac_enforce_fs) 1791 return (0); 1792 1793 error = vn_refreshlabel(vp, cred); 1794 if (error) 1795 return (error); 1796 1797 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 1798 return (error); 1799} 1800 1801int 1802mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 1803{ 1804 int error; 1805 1806 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 1807 1808 if (!mac_enforce_fs) 1809 return (0); 1810 1811 error = vn_refreshlabel(dvp, cred); 1812 if (error) 1813 return (error); 1814 1815 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 1816 return (error); 1817} 1818 1819int 1820mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 1821{ 1822 int error; 1823 1824 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 1825 1826 if (!mac_enforce_fs) 1827 return (0); 1828 1829 error = vn_refreshlabel(vp, cred); 1830 if (error) 1831 return (error); 1832 1833 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 1834 return (error); 1835} 1836 1837static int 1838mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 1839 struct label *newlabel) 1840{ 1841 int error; 1842 1843 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 1844 1845 error = vn_refreshlabel(vp, cred); 1846 if (error) 1847 return (error); 1848 1849 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 1850 1851 return (error); 1852} 1853 1854int 1855mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 1856 struct vnode *vp, struct componentname *cnp) 1857{ 1858 int error; 1859 1860 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 1861 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 1862 1863 if (!mac_enforce_fs) 1864 return (0); 1865 1866 error = vn_refreshlabel(dvp, cred); 1867 if (error) 1868 return (error); 1869 error = vn_refreshlabel(vp, cred); 1870 if (error) 1871 return (error); 1872 1873 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 1874 &vp->v_label, cnp); 1875 return (error); 1876} 1877 1878int 1879mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 1880 struct vnode *vp, int samedir, struct componentname *cnp) 1881{ 1882 int error; 1883 1884 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 1885 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 1886 1887 if (!mac_enforce_fs) 1888 return (0); 1889 1890 error = vn_refreshlabel(dvp, cred); 1891 if (error) 1892 return (error); 1893 if (vp != NULL) { 1894 error = vn_refreshlabel(vp, cred); 1895 if (error) 1896 return (error); 1897 } 1898 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 1899 vp != NULL ? &vp->v_label : NULL, samedir, cnp); 1900 return (error); 1901} 1902 1903int 1904mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 1905{ 1906 int error; 1907 1908 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 1909 1910 if (!mac_enforce_fs) 1911 return (0); 1912 1913 error = vn_refreshlabel(vp, cred); 1914 if (error) 1915 return (error); 1916 1917 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 1918 return (error); 1919} 1920 1921int 1922mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 1923 struct acl *acl) 1924{ 1925 int error; 1926 1927 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 1928 1929 if (!mac_enforce_fs) 1930 return (0); 1931 1932 error = vn_refreshlabel(vp, cred); 1933 if (error) 1934 return (error); 1935 1936 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 1937 return (error); 1938} 1939 1940int 1941mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 1942 int attrnamespace, const char *name, struct uio *uio) 1943{ 1944 int error; 1945 1946 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 1947 1948 if (!mac_enforce_fs) 1949 return (0); 1950 1951 error = vn_refreshlabel(vp, cred); 1952 if (error) 1953 return (error); 1954 1955 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 1956 attrnamespace, name, uio); 1957 return (error); 1958} 1959 1960int 1961mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 1962{ 1963 int error; 1964 1965 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 1966 1967 if (!mac_enforce_fs) 1968 return (0); 1969 1970 error = vn_refreshlabel(vp, cred); 1971 if (error) 1972 return (error); 1973 1974 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 1975 return (error); 1976} 1977 1978int 1979mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 1980{ 1981 int error; 1982 1983 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 1984 1985 if (!mac_enforce_fs) 1986 return (0); 1987 1988 error = vn_refreshlabel(vp, cred); 1989 if (error) 1990 return (error); 1991 1992 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 1993 return (error); 1994} 1995 1996int 1997mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 1998 gid_t gid) 1999{ 2000 int error; 2001 2002 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 2003 2004 if (!mac_enforce_fs) 2005 return (0); 2006 2007 error = vn_refreshlabel(vp, cred); 2008 if (error) 2009 return (error); 2010 2011 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 2012 return (error); 2013} 2014 2015int 2016mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 2017 struct timespec atime, struct timespec mtime) 2018{ 2019 int error; 2020 2021 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 2022 2023 if (!mac_enforce_fs) 2024 return (0); 2025 2026 error = vn_refreshlabel(vp, cred); 2027 if (error) 2028 return (error); 2029 2030 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 2031 mtime); 2032 return (error); 2033} 2034 2035int 2036mac_check_vnode_stat(struct ucred *cred, struct vnode *vp) 2037{ 2038 int error; 2039 2040 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 2041 2042 if (!mac_enforce_fs) 2043 return (0); 2044 2045 error = vn_refreshlabel(vp, cred); 2046 if (error) 2047 return (error); 2048 2049 MAC_CHECK(check_vnode_stat, cred, vp, &vp->v_label); 2050 return (error); 2051} 2052 2053/* 2054 * When relabeling a process, call out to the policies for the maximum 2055 * permission allowed for each object type we know about in its 2056 * memory space, and revoke access (in the least surprising ways we 2057 * know) when necessary. The process lock is not held here. 2058 */ 2059static void 2060mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 2061{ 2062 2063 /* XXX freeze all other threads */ 2064 mtx_lock(&Giant); 2065 mac_cred_mmapped_drop_perms_recurse(td, cred, 2066 &td->td_proc->p_vmspace->vm_map); 2067 mtx_unlock(&Giant); 2068 /* XXX allow other threads to continue */ 2069} 2070 2071static __inline const char * 2072prot2str(vm_prot_t prot) 2073{ 2074 2075 switch (prot & VM_PROT_ALL) { 2076 case VM_PROT_READ: 2077 return ("r--"); 2078 case VM_PROT_READ | VM_PROT_WRITE: 2079 return ("rw-"); 2080 case VM_PROT_READ | VM_PROT_EXECUTE: 2081 return ("r-x"); 2082 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 2083 return ("rwx"); 2084 case VM_PROT_WRITE: 2085 return ("-w-"); 2086 case VM_PROT_EXECUTE: 2087 return ("--x"); 2088 case VM_PROT_WRITE | VM_PROT_EXECUTE: 2089 return ("-wx"); 2090 default: 2091 return ("---"); 2092 } 2093} 2094 2095static void 2096mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 2097 struct vm_map *map) 2098{ 2099 struct vm_map_entry *vme; 2100 vm_prot_t result, revokeperms; 2101 vm_object_t object; 2102 vm_ooffset_t offset; 2103 struct vnode *vp; 2104 2105 vm_map_lock_read(map); 2106 for (vme = map->header.next; vme != &map->header; vme = vme->next) { 2107 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 2108 mac_cred_mmapped_drop_perms_recurse(td, cred, 2109 vme->object.sub_map); 2110 continue; 2111 } 2112 /* 2113 * Skip over entries that obviously are not shared. 2114 */ 2115 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 2116 !vme->max_protection) 2117 continue; 2118 /* 2119 * Drill down to the deepest backing object. 2120 */ 2121 offset = vme->offset; 2122 object = vme->object.vm_object; 2123 if (object == NULL) 2124 continue; 2125 while (object->backing_object != NULL) { 2126 object = object->backing_object; 2127 offset += object->backing_object_offset; 2128 } 2129 /* 2130 * At the moment, vm_maps and objects aren't considered 2131 * by the MAC system, so only things with backing by a 2132 * normal object (read: vnodes) are checked. 2133 */ 2134 if (object->type != OBJT_VNODE) 2135 continue; 2136 vp = (struct vnode *)object->handle; 2137 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2138 result = mac_check_vnode_mmap_prot(cred, vp, 0); 2139 VOP_UNLOCK(vp, 0, td); 2140 /* 2141 * Find out what maximum protection we may be allowing 2142 * now but a policy needs to get removed. 2143 */ 2144 revokeperms = vme->max_protection & ~result; 2145 if (!revokeperms) 2146 continue; 2147 printf("pid %d: revoking %s perms from %#lx:%d " 2148 "(max %s/cur %s)\n", td->td_proc->p_pid, 2149 prot2str(revokeperms), vme->start, vme->end - vme->start, 2150 prot2str(vme->max_protection), prot2str(vme->protection)); 2151 vm_map_lock_upgrade(map); 2152 /* 2153 * This is the really simple case: if a map has more 2154 * max_protection than is allowed, but it's not being 2155 * actually used (that is, the current protection is 2156 * still allowed), we can just wipe it out and do 2157 * nothing more. 2158 */ 2159 if ((vme->protection & revokeperms) == 0) { 2160 vme->max_protection -= revokeperms; 2161 } else { 2162 if (revokeperms & VM_PROT_WRITE) { 2163 /* 2164 * In the more complicated case, flush out all 2165 * pending changes to the object then turn it 2166 * copy-on-write. 2167 */ 2168 vm_object_reference(object); 2169 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2170 vm_object_page_clean(object, 2171 OFF_TO_IDX(offset), 2172 OFF_TO_IDX(offset + vme->end - vme->start + 2173 PAGE_MASK), 2174 OBJPC_SYNC); 2175 VOP_UNLOCK(vp, 0, td); 2176 vm_object_deallocate(object); 2177 /* 2178 * Why bother if there's no read permissions 2179 * anymore? For the rest, we need to leave 2180 * the write permissions on for COW, or 2181 * remove them entirely if configured to. 2182 */ 2183 if (!mac_mmap_revocation_via_cow) { 2184 vme->max_protection &= ~VM_PROT_WRITE; 2185 vme->protection &= ~VM_PROT_WRITE; 2186 } if ((revokeperms & VM_PROT_READ) == 0) 2187 vme->eflags |= MAP_ENTRY_COW | 2188 MAP_ENTRY_NEEDS_COPY; 2189 } 2190 if (revokeperms & VM_PROT_EXECUTE) { 2191 vme->max_protection &= ~VM_PROT_EXECUTE; 2192 vme->protection &= ~VM_PROT_EXECUTE; 2193 } 2194 if (revokeperms & VM_PROT_READ) { 2195 vme->max_protection = 0; 2196 vme->protection = 0; 2197 } 2198 pmap_protect(map->pmap, vme->start, vme->end, 2199 vme->protection & ~revokeperms); 2200 vm_map_simplify_entry(map, vme); 2201 } 2202 vm_map_lock_downgrade(map); 2203 } 2204 vm_map_unlock_read(map); 2205} 2206 2207/* 2208 * When the subject's label changes, it may require revocation of privilege 2209 * to mapped objects. This can't be done on-the-fly later with a unified 2210 * buffer cache. 2211 */ 2212static void 2213mac_relabel_cred(struct ucred *cred, struct label *newlabel) 2214{ 2215 2216 MAC_PERFORM(relabel_cred, cred, newlabel); 2217 mac_cred_mmapped_drop_perms(curthread, cred); 2218} 2219 2220void 2221mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 2222{ 2223 2224 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 2225} 2226 2227void 2228mac_create_ifnet(struct ifnet *ifnet) 2229{ 2230 2231 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 2232} 2233 2234void 2235mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 2236{ 2237 2238 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 2239} 2240 2241void 2242mac_create_socket(struct ucred *cred, struct socket *socket) 2243{ 2244 2245 MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 2246} 2247 2248void 2249mac_create_pipe(struct ucred *cred, struct pipe *pipe) 2250{ 2251 2252 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 2253} 2254 2255void 2256mac_create_socket_from_socket(struct socket *oldsocket, 2257 struct socket *newsocket) 2258{ 2259 2260 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 2261 newsocket, &newsocket->so_label); 2262} 2263 2264static void 2265mac_relabel_socket(struct ucred *cred, struct socket *socket, 2266 struct label *newlabel) 2267{ 2268 2269 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 2270} 2271 2272static void 2273mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 2274{ 2275 2276 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 2277} 2278 2279void 2280mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 2281{ 2282 2283 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 2284 socket, &socket->so_peerlabel); 2285} 2286 2287void 2288mac_set_socket_peer_from_socket(struct socket *oldsocket, 2289 struct socket *newsocket) 2290{ 2291 2292 MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 2293 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 2294} 2295 2296void 2297mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 2298{ 2299 2300 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 2301 datagram, &datagram->m_pkthdr.label); 2302} 2303 2304void 2305mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 2306{ 2307 2308 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 2309 fragment, &fragment->m_pkthdr.label); 2310} 2311 2312void 2313mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 2314{ 2315 2316 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2317 &ipq->ipq_label); 2318} 2319 2320void 2321mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2322{ 2323 2324 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 2325 newmbuf, &newmbuf->m_pkthdr.label); 2326} 2327 2328void 2329mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 2330{ 2331 2332 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 2333 &mbuf->m_pkthdr.label); 2334} 2335 2336void 2337mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 2338{ 2339 2340 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 2341 &mbuf->m_pkthdr.label); 2342} 2343 2344void 2345mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 2346{ 2347 2348 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 2349 &mbuf->m_pkthdr.label); 2350} 2351 2352void 2353mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 2354 struct mbuf *newmbuf) 2355{ 2356 2357 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 2358 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 2359 &newmbuf->m_pkthdr.label); 2360} 2361 2362void 2363mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2364{ 2365 2366 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 2367 newmbuf, &newmbuf->m_pkthdr.label); 2368} 2369 2370int 2371mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 2372{ 2373 int result; 2374 2375 result = 1; 2376 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 2377 ipq, &ipq->ipq_label); 2378 2379 return (result); 2380} 2381 2382void 2383mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 2384{ 2385 2386 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2387 &ipq->ipq_label); 2388} 2389 2390void 2391mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 2392{ 2393 2394 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 2395 &mbuf->m_pkthdr.label); 2396} 2397 2398void 2399mac_create_mount(struct ucred *cred, struct mount *mp) 2400{ 2401 2402 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 2403 &mp->mnt_fslabel); 2404} 2405 2406void 2407mac_create_root_mount(struct ucred *cred, struct mount *mp) 2408{ 2409 2410 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 2411 &mp->mnt_fslabel); 2412} 2413 2414int 2415mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 2416{ 2417 int error; 2418 2419 if (!mac_enforce_network) 2420 return (0); 2421 2422 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 2423 &ifnet->if_label); 2424 2425 return (error); 2426} 2427 2428static int 2429mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 2430{ 2431 int error; 2432 2433 MAC_CHECK(check_cred_relabel, cred, newlabel); 2434 2435 return (error); 2436} 2437 2438int 2439mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 2440{ 2441 int error; 2442 2443 if (!mac_enforce_process) 2444 return (0); 2445 2446 MAC_CHECK(check_cred_visible, u1, u2); 2447 2448 return (error); 2449} 2450 2451int 2452mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 2453{ 2454 int error; 2455 2456 if (!mac_enforce_network) 2457 return (0); 2458 2459 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 2460 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 2461 printf("%s%d: not initialized\n", ifnet->if_name, 2462 ifnet->if_unit); 2463 2464 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 2465 &mbuf->m_pkthdr.label); 2466 2467 return (error); 2468} 2469 2470int 2471mac_check_mount_stat(struct ucred *cred, struct mount *mount) 2472{ 2473 int error; 2474 2475 if (!mac_enforce_fs) 2476 return (0); 2477 2478 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 2479 2480 return (error); 2481} 2482 2483int 2484mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 2485 void *data) 2486{ 2487 int error; 2488 2489 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 2490 2491 return (error); 2492} 2493 2494int 2495mac_check_pipe_op(struct ucred *cred, struct pipe *pipe, int op) 2496{ 2497 int error; 2498 2499 MAC_CHECK(check_pipe_op, cred, pipe, pipe->pipe_label, op); 2500 2501 return (error); 2502} 2503 2504static int 2505mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 2506 struct label *newlabel) 2507{ 2508 int error; 2509 2510 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 2511 2512 return (error); 2513} 2514 2515int 2516mac_check_proc_debug(struct ucred *cred, struct proc *proc) 2517{ 2518 int error; 2519 2520 PROC_LOCK_ASSERT(proc, MA_OWNED); 2521 2522 if (!mac_enforce_process) 2523 return (0); 2524 2525 MAC_CHECK(check_proc_debug, cred, proc); 2526 2527 return (error); 2528} 2529 2530int 2531mac_check_proc_sched(struct ucred *cred, struct proc *proc) 2532{ 2533 int error; 2534 2535 PROC_LOCK_ASSERT(proc, MA_OWNED); 2536 2537 if (!mac_enforce_process) 2538 return (0); 2539 2540 MAC_CHECK(check_proc_sched, cred, proc); 2541 2542 return (error); 2543} 2544 2545int 2546mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 2547{ 2548 int error; 2549 2550 PROC_LOCK_ASSERT(proc, MA_OWNED); 2551 2552 if (!mac_enforce_process) 2553 return (0); 2554 2555 MAC_CHECK(check_proc_signal, cred, proc, signum); 2556 2557 return (error); 2558} 2559 2560int 2561mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 2562 struct sockaddr *sockaddr) 2563{ 2564 int error; 2565 2566 if (!mac_enforce_socket) 2567 return (0); 2568 2569 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 2570 sockaddr); 2571 2572 return (error); 2573} 2574 2575int 2576mac_check_socket_connect(struct ucred *cred, struct socket *socket, 2577 struct sockaddr *sockaddr) 2578{ 2579 int error; 2580 2581 if (!mac_enforce_socket) 2582 return (0); 2583 2584 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 2585 sockaddr); 2586 2587 return (error); 2588} 2589 2590int 2591mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2592{ 2593 int error; 2594 2595 if (!mac_enforce_socket) 2596 return (0); 2597 2598 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2599 &mbuf->m_pkthdr.label); 2600 2601 return (error); 2602} 2603 2604int 2605mac_check_socket_listen(struct ucred *cred, struct socket *socket) 2606{ 2607 int error; 2608 2609 if (!mac_enforce_socket) 2610 return (0); 2611 2612 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 2613 return (error); 2614} 2615 2616static int 2617mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 2618 struct label *newlabel) 2619{ 2620 int error; 2621 2622 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 2623 newlabel); 2624 2625 return (error); 2626} 2627 2628int 2629mac_check_socket_visible(struct ucred *cred, struct socket *socket) 2630{ 2631 int error; 2632 2633 if (!mac_enforce_socket) 2634 return (0); 2635 2636 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 2637 2638 return (error); 2639} 2640 2641int 2642mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 2643 struct ifnet *ifnet) 2644{ 2645 struct mac label; 2646 int error; 2647 2648 error = mac_externalize(&ifnet->if_label, &label); 2649 if (error) 2650 return (error); 2651 2652 return (copyout(&label, ifr->ifr_ifru.ifru_data, sizeof(label))); 2653} 2654 2655int 2656mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 2657 struct ifnet *ifnet) 2658{ 2659 struct mac newlabel; 2660 struct label intlabel; 2661 int error; 2662 2663 error = copyin(ifr->ifr_ifru.ifru_data, &newlabel, sizeof(newlabel)); 2664 if (error) 2665 return (error); 2666 2667 error = mac_internalize(&intlabel, &newlabel); 2668 if (error) 2669 return (error); 2670 2671 /* 2672 * XXX: Note that this is a redundant privilege check, since 2673 * policies impose this check themselves if required by the 2674 * policy. Eventually, this should go away. 2675 */ 2676 error = suser_cred(cred, 0); 2677 if (error) 2678 goto out; 2679 2680 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 2681 &intlabel); 2682 if (error) 2683 goto out; 2684 2685 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 2686 2687out: 2688 mac_destroy_temp(&intlabel); 2689 return (error); 2690} 2691 2692void 2693mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp) 2694{ 2695 2696 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 2697} 2698 2699void 2700mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 2701{ 2702 2703 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 2704} 2705 2706static int 2707mac_stdcreatevnode_ea(struct vnode *vp) 2708{ 2709 int error; 2710 2711 MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); 2712 2713 return (error); 2714} 2715 2716void 2717mac_create_devfs_directory(char *dirname, int dirnamelen, 2718 struct devfs_dirent *de) 2719{ 2720 2721 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 2722 &de->de_label); 2723} 2724 2725/* 2726 * When a new vnode is created, this call will initialize its label. 2727 */ 2728void 2729mac_create_vnode(struct ucred *cred, struct vnode *parent, 2730 struct vnode *child) 2731{ 2732 int error; 2733 2734 ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); 2735 ASSERT_VOP_LOCKED(child, "mac_create_vnode"); 2736 2737 error = vn_refreshlabel(parent, cred); 2738 if (error) { 2739 printf("mac_create_vnode: vn_refreshlabel returned %d\n", 2740 error); 2741 printf("mac_create_vnode: using old vnode label\n"); 2742 } 2743 2744 MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, 2745 &child->v_label); 2746} 2747 2748int 2749mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 2750 struct mac *extmac) 2751{ 2752 struct label intlabel; 2753 int error; 2754 2755 error = mac_internalize(&intlabel, extmac); 2756 if (error) 2757 return (error); 2758 2759 mac_check_socket_relabel(cred, so, &intlabel); 2760 if (error) { 2761 mac_destroy_temp(&intlabel); 2762 return (error); 2763 } 2764 2765 mac_relabel_socket(cred, so, &intlabel); 2766 2767 mac_destroy_temp(&intlabel); 2768 return (0); 2769} 2770 2771int 2772mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 2773{ 2774 int error; 2775 2776 error = mac_check_pipe_relabel(cred, pipe, label); 2777 if (error) 2778 return (error); 2779 2780 mac_relabel_pipe(cred, pipe, label); 2781 2782 return (0); 2783} 2784 2785int 2786mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 2787 struct mac *extmac) 2788{ 2789 2790 return (mac_externalize(&so->so_label, extmac)); 2791} 2792 2793int 2794mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 2795 struct mac *extmac) 2796{ 2797 2798 return (mac_externalize(&so->so_peerlabel, extmac)); 2799} 2800 2801/* 2802 * Implementation of VOP_SETLABEL() that relies on extended attributes 2803 * to store label data. Can be referenced by filesystems supporting 2804 * extended attributes. 2805 */ 2806int 2807vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 2808{ 2809 struct vnode *vp = ap->a_vp; 2810 struct label *intlabel = ap->a_label; 2811 struct mac extmac; 2812 int error; 2813 2814 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 2815 2816 /* 2817 * XXX: Eventually call out to EA check/set calls here. 2818 * Be particularly careful to avoid race conditions, 2819 * consistency problems, and stability problems when 2820 * dealing with multiple EAs. In particular, we require 2821 * the ability to write multiple EAs on the same file in 2822 * a single transaction, which the current EA interface 2823 * does not provide. 2824 */ 2825 2826 error = mac_externalize(intlabel, &extmac); 2827 if (error) 2828 return (error); 2829 2830 error = vn_extattr_set(vp, IO_NODELOCKED, 2831 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 2832 sizeof(extmac), (char *)&extmac, curthread); 2833 if (error) 2834 return (error); 2835 2836 mac_relabel_vnode(ap->a_cred, vp, intlabel); 2837 2838 vp->v_vflag |= VV_CACHEDLABEL; 2839 2840 return (0); 2841} 2842 2843static int 2844vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 2845{ 2846 int error; 2847 2848 if (vp->v_mount == NULL) { 2849 /* printf("vn_setlabel: null v_mount\n"); */ 2850 if (vp->v_tag != VT_NON) 2851 printf("vn_setlabel: null v_mount with non-VT_NON\n"); 2852 return (EBADF); 2853 } 2854 2855 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2856 return (EOPNOTSUPP); 2857 2858 /* 2859 * Multi-phase commit. First check the policies to confirm the 2860 * change is OK. Then commit via the filesystem. Finally, 2861 * update the actual vnode label. Question: maybe the filesystem 2862 * should update the vnode at the end as part of VOP_SETLABEL()? 2863 */ 2864 error = mac_check_vnode_relabel(cred, vp, intlabel); 2865 if (error) 2866 return (error); 2867 2868 /* 2869 * VADMIN provides the opportunity for the filesystem to make 2870 * decisions about who is and is not able to modify labels 2871 * and protections on files. This might not be right. We can't 2872 * assume VOP_SETLABEL() will do it, because we might implement 2873 * that as part of vop_stdsetlabel_ea(). 2874 */ 2875 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 2876 if (error) 2877 return (error); 2878 2879 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 2880 if (error) 2881 return (error); 2882 2883 return (0); 2884} 2885 2886/* 2887 * MPSAFE 2888 */ 2889int 2890__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 2891{ 2892 struct mac extmac; 2893 int error; 2894 2895 error = mac_externalize(&td->td_ucred->cr_label, &extmac); 2896 if (error == 0) 2897 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 2898 2899 return (error); 2900} 2901 2902/* 2903 * MPSAFE 2904 * 2905 * XXX: Needs to be re-written for proc locking. 2906 */ 2907int 2908__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 2909{ 2910 struct ucred *newcred, *oldcred; 2911 struct proc *p; 2912 struct mac extmac; 2913 struct label intlabel; 2914 int error; 2915 2916 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 2917 if (error) 2918 return (error); 2919 2920 error = mac_internalize(&intlabel, &extmac); 2921 if (error) 2922 return (error); 2923 2924 newcred = crget(); 2925 2926 p = td->td_proc; 2927 PROC_LOCK(p); 2928 oldcred = p->p_ucred; 2929 2930 error = mac_check_cred_relabel(oldcred, &intlabel); 2931 if (error) { 2932 PROC_UNLOCK(p); 2933 mac_destroy_temp(&intlabel); 2934 crfree(newcred); 2935 return (error); 2936 } 2937 2938 setsugid(p); 2939 crcopy(newcred, oldcred); 2940 PROC_UNLOCK(p); 2941 mac_relabel_cred(newcred, &intlabel); 2942 2943 PROC_LOCK(p); 2944 p->p_ucred = newcred; 2945 PROC_UNLOCK(p); 2946 crfree(oldcred); 2947 mac_destroy_temp(&intlabel); 2948 return (0); 2949} 2950 2951/* 2952 * MPSAFE 2953 */ 2954int 2955__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 2956{ 2957 struct file *fp; 2958 struct mac extmac; 2959 struct vnode *vp; 2960 struct pipe *pipe; 2961 int error; 2962 2963 mtx_lock(&Giant); 2964 2965 error = fget(td, SCARG(uap, fd), &fp); 2966 if (error) 2967 goto out; 2968 2969 switch (fp->f_type) { 2970 case DTYPE_FIFO: 2971 case DTYPE_VNODE: 2972 vp = (struct vnode *)fp->f_data; 2973 2974 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2975 error = vn_refreshlabel(vp, td->td_ucred); 2976 if (error == 0) 2977 error = mac_externalize(&vp->v_label, &extmac); 2978 VOP_UNLOCK(vp, 0, td); 2979 break; 2980 case DTYPE_PIPE: 2981 pipe = (struct pipe *)fp->f_data; 2982 error = mac_externalize(pipe->pipe_label, &extmac); 2983 break; 2984 default: 2985 error = EINVAL; 2986 } 2987 2988 if (error == 0) 2989 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 2990 2991 fdrop(fp, td); 2992 2993out: 2994 mtx_unlock(&Giant); 2995 return (error); 2996} 2997 2998/* 2999 * MPSAFE 3000 */ 3001int 3002__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3003{ 3004 struct nameidata nd; 3005 struct mac extmac; 3006 int error; 3007 3008 mtx_lock(&Giant); 3009 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 3010 SCARG(uap, path_p), td); 3011 error = namei(&nd); 3012 if (error) 3013 goto out; 3014 3015 error = vn_refreshlabel(nd.ni_vp, td->td_ucred); 3016 if (error == 0) 3017 error = mac_externalize(&nd.ni_vp->v_label, &extmac); 3018 NDFREE(&nd, 0); 3019 if (error) 3020 goto out; 3021 3022 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 3023 3024out: 3025 mtx_unlock(&Giant); 3026 return (error); 3027} 3028 3029/* 3030 * MPSAFE 3031 */ 3032int 3033__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3034{ 3035 struct file *fp; 3036 struct mac extmac; 3037 struct label intlabel; 3038 struct mount *mp; 3039 struct vnode *vp; 3040 struct pipe *pipe; 3041 int error; 3042 3043 mtx_lock(&Giant); 3044 error = fget(td, SCARG(uap, fd), &fp); 3045 if (error) 3046 goto out1; 3047 3048 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 3049 if (error) 3050 goto out2; 3051 3052 error = mac_internalize(&intlabel, &extmac); 3053 if (error) 3054 goto out2; 3055 3056 switch (fp->f_type) { 3057 case DTYPE_FIFO: 3058 case DTYPE_VNODE: 3059 vp = (struct vnode *)fp->f_data; 3060 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3061 if (error != 0) 3062 break; 3063 3064 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3065 error = vn_setlabel(vp, &intlabel, td->td_ucred); 3066 VOP_UNLOCK(vp, 0, td); 3067 vn_finished_write(mp); 3068 mac_destroy_temp(&intlabel); 3069 break; 3070 case DTYPE_PIPE: 3071 pipe = (struct pipe *)fp->f_data; 3072 error = mac_pipe_label_set(td->td_ucred, pipe, &intlabel); 3073 break; 3074 default: 3075 error = EINVAL; 3076 } 3077 3078out2: 3079 fdrop(fp, td); 3080out1: 3081 mtx_unlock(&Giant); 3082 return (error); 3083} 3084 3085/* 3086 * MPSAFE 3087 */ 3088int 3089__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3090{ 3091 struct nameidata nd; 3092 struct mac extmac; 3093 struct label intlabel; 3094 struct mount *mp; 3095 int error; 3096 3097 mtx_lock(&Giant); 3098 3099 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 3100 if (error) 3101 goto out; 3102 3103 error = mac_internalize(&intlabel, &extmac); 3104 if (error) 3105 goto out; 3106 3107 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 3108 SCARG(uap, path_p), td); 3109 error = namei(&nd); 3110 if (error) 3111 goto out2; 3112 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3113 if (error) 3114 goto out2; 3115 3116 error = vn_setlabel(nd.ni_vp, &intlabel, td->td_ucred); 3117 3118 vn_finished_write(mp); 3119out2: 3120 mac_destroy_temp(&intlabel); 3121 NDFREE(&nd, 0); 3122out: 3123 mtx_unlock(&Giant); 3124 return (error); 3125} 3126 3127SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 3128SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 3129 3130#else /* !MAC */ 3131 3132int 3133__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3134{ 3135 3136 return (ENOSYS); 3137} 3138 3139int 3140__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3141{ 3142 3143 return (ENOSYS); 3144} 3145 3146int 3147__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3148{ 3149 3150 return (ENOSYS); 3151} 3152 3153int 3154__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3155{ 3156 3157 return (ENOSYS); 3158} 3159 3160int 3161__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3162{ 3163 3164 return (ENOSYS); 3165} 3166 3167int 3168__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3169{ 3170 3171 return (ENOSYS); 3172} 3173 3174#endif /* !MAC */ 3175