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