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