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