mac_pipe.c revision 106460
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_pipe.c 106460 2002-11-05 15:11:33Z 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 if (!mac_enforce_process && !mac_enforce_fs) 1261 return; 1262 1263 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); 1264} 1265 1266int 1267mac_execve_will_transition(struct ucred *old, struct vnode *vp) 1268{ 1269 int result; 1270 1271 ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 1272 1273 if (!mac_enforce_process && !mac_enforce_fs) 1274 return (0); 1275 1276 result = 0; 1277 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); 1278 1279 return (result); 1280} 1281 1282int 1283mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 1284{ 1285 int error; 1286 1287 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 1288 1289 if (!mac_enforce_fs) 1290 return (0); 1291 1292 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode); 1293 return (error); 1294} 1295 1296int 1297mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 1298{ 1299 int error; 1300 1301 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 1302 1303 if (!mac_enforce_fs) 1304 return (0); 1305 1306 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 1307 return (error); 1308} 1309 1310int 1311mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 1312{ 1313 int error; 1314 1315 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 1316 1317 if (!mac_enforce_fs) 1318 return (0); 1319 1320 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 1321 return (error); 1322} 1323 1324int 1325mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 1326 struct componentname *cnp, struct vattr *vap) 1327{ 1328 int error; 1329 1330 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 1331 1332 if (!mac_enforce_fs) 1333 return (0); 1334 1335 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 1336 return (error); 1337} 1338 1339int 1340mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 1341 struct componentname *cnp) 1342{ 1343 int error; 1344 1345 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 1346 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 1347 1348 if (!mac_enforce_fs) 1349 return (0); 1350 1351 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 1352 &vp->v_label, cnp); 1353 return (error); 1354} 1355 1356int 1357mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 1358 acl_type_t type) 1359{ 1360 int error; 1361 1362 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 1363 1364 if (!mac_enforce_fs) 1365 return (0); 1366 1367 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 1368 return (error); 1369} 1370 1371int 1372mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) 1373{ 1374 int error; 1375 1376 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1377 1378 if (!mac_enforce_process && !mac_enforce_fs) 1379 return (0); 1380 1381 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); 1382 1383 return (error); 1384} 1385 1386int 1387mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 1388{ 1389 int error; 1390 1391 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 1392 1393 if (!mac_enforce_fs) 1394 return (0); 1395 1396 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 1397 return (error); 1398} 1399 1400int 1401mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 1402 int attrnamespace, const char *name, struct uio *uio) 1403{ 1404 int error; 1405 1406 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 1407 1408 if (!mac_enforce_fs) 1409 return (0); 1410 1411 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 1412 attrnamespace, name, uio); 1413 return (error); 1414} 1415 1416int 1417mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 1418 struct vnode *vp, struct componentname *cnp) 1419{ 1420 int error; 1421 1422 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 1423 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 1424 1425 if (!mac_enforce_fs) 1426 return (0); 1427 1428 MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 1429 &vp->v_label, cnp); 1430 return (error); 1431} 1432 1433int 1434mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 1435 struct componentname *cnp) 1436{ 1437 int error; 1438 1439 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 1440 1441 if (!mac_enforce_fs) 1442 return (0); 1443 1444 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 1445 return (error); 1446} 1447 1448int 1449mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 1450{ 1451 int error; 1452 1453 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1454 1455 if (!mac_enforce_fs || !mac_enforce_vm) 1456 return (0); 1457 1458 MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1459 return (error); 1460} 1461 1462void 1463mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1464{ 1465 int result = *prot; 1466 1467 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1468 1469 if (!mac_enforce_fs || !mac_enforce_vm) 1470 return; 1471 1472 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1473 &result); 1474 1475 *prot = result; 1476} 1477 1478int 1479mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1480{ 1481 int error; 1482 1483 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1484 1485 if (!mac_enforce_fs || !mac_enforce_vm) 1486 return (0); 1487 1488 MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 1489 return (error); 1490} 1491 1492int 1493mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 1494{ 1495 int error; 1496 1497 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 1498 1499 if (!mac_enforce_fs) 1500 return (0); 1501 1502 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 1503 return (error); 1504} 1505 1506int 1507mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 1508 struct vnode *vp) 1509{ 1510 int error; 1511 1512 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 1513 1514 if (!mac_enforce_fs) 1515 return (0); 1516 1517 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 1518 &vp->v_label); 1519 1520 return (error); 1521} 1522 1523int 1524mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 1525 struct vnode *vp) 1526{ 1527 int error; 1528 1529 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 1530 1531 if (!mac_enforce_fs) 1532 return (0); 1533 1534 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 1535 &vp->v_label); 1536 1537 return (error); 1538} 1539 1540int 1541mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 1542{ 1543 int error; 1544 1545 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 1546 1547 if (!mac_enforce_fs) 1548 return (0); 1549 1550 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 1551 return (error); 1552} 1553 1554int 1555mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 1556{ 1557 int error; 1558 1559 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 1560 1561 if (!mac_enforce_fs) 1562 return (0); 1563 1564 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 1565 return (error); 1566} 1567 1568static int 1569mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 1570 struct label *newlabel) 1571{ 1572 int error; 1573 1574 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 1575 1576 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 1577 1578 return (error); 1579} 1580 1581int 1582mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 1583 struct vnode *vp, struct componentname *cnp) 1584{ 1585 int error; 1586 1587 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 1588 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 1589 1590 if (!mac_enforce_fs) 1591 return (0); 1592 1593 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 1594 &vp->v_label, cnp); 1595 return (error); 1596} 1597 1598int 1599mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 1600 struct vnode *vp, int samedir, struct componentname *cnp) 1601{ 1602 int error; 1603 1604 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 1605 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 1606 1607 if (!mac_enforce_fs) 1608 return (0); 1609 1610 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 1611 vp != NULL ? &vp->v_label : NULL, samedir, cnp); 1612 return (error); 1613} 1614 1615int 1616mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 1617{ 1618 int error; 1619 1620 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 1621 1622 if (!mac_enforce_fs) 1623 return (0); 1624 1625 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 1626 return (error); 1627} 1628 1629int 1630mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 1631 struct acl *acl) 1632{ 1633 int error; 1634 1635 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 1636 1637 if (!mac_enforce_fs) 1638 return (0); 1639 1640 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 1641 return (error); 1642} 1643 1644int 1645mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 1646 int attrnamespace, const char *name, struct uio *uio) 1647{ 1648 int error; 1649 1650 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 1651 1652 if (!mac_enforce_fs) 1653 return (0); 1654 1655 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 1656 attrnamespace, name, uio); 1657 return (error); 1658} 1659 1660int 1661mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 1662{ 1663 int error; 1664 1665 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 1666 1667 if (!mac_enforce_fs) 1668 return (0); 1669 1670 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 1671 return (error); 1672} 1673 1674int 1675mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 1676{ 1677 int error; 1678 1679 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 1680 1681 if (!mac_enforce_fs) 1682 return (0); 1683 1684 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 1685 return (error); 1686} 1687 1688int 1689mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 1690 gid_t gid) 1691{ 1692 int error; 1693 1694 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 1695 1696 if (!mac_enforce_fs) 1697 return (0); 1698 1699 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 1700 return (error); 1701} 1702 1703int 1704mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 1705 struct timespec atime, struct timespec mtime) 1706{ 1707 int error; 1708 1709 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 1710 1711 if (!mac_enforce_fs) 1712 return (0); 1713 1714 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 1715 mtime); 1716 return (error); 1717} 1718 1719int 1720mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 1721 struct vnode *vp) 1722{ 1723 int error; 1724 1725 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 1726 1727 if (!mac_enforce_fs) 1728 return (0); 1729 1730 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 1731 &vp->v_label); 1732 return (error); 1733} 1734 1735int 1736mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 1737 struct vnode *vp) 1738{ 1739 int error; 1740 1741 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 1742 1743 if (!mac_enforce_fs) 1744 return (0); 1745 1746 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 1747 &vp->v_label); 1748 1749 return (error); 1750} 1751 1752/* 1753 * When relabeling a process, call out to the policies for the maximum 1754 * permission allowed for each object type we know about in its 1755 * memory space, and revoke access (in the least surprising ways we 1756 * know) when necessary. The process lock is not held here. 1757 */ 1758static void 1759mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 1760{ 1761 1762 /* XXX freeze all other threads */ 1763 mac_cred_mmapped_drop_perms_recurse(td, cred, 1764 &td->td_proc->p_vmspace->vm_map); 1765 /* XXX allow other threads to continue */ 1766} 1767 1768static __inline const char * 1769prot2str(vm_prot_t prot) 1770{ 1771 1772 switch (prot & VM_PROT_ALL) { 1773 case VM_PROT_READ: 1774 return ("r--"); 1775 case VM_PROT_READ | VM_PROT_WRITE: 1776 return ("rw-"); 1777 case VM_PROT_READ | VM_PROT_EXECUTE: 1778 return ("r-x"); 1779 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 1780 return ("rwx"); 1781 case VM_PROT_WRITE: 1782 return ("-w-"); 1783 case VM_PROT_EXECUTE: 1784 return ("--x"); 1785 case VM_PROT_WRITE | VM_PROT_EXECUTE: 1786 return ("-wx"); 1787 default: 1788 return ("---"); 1789 } 1790} 1791 1792static void 1793mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 1794 struct vm_map *map) 1795{ 1796 struct vm_map_entry *vme; 1797 int result; 1798 vm_prot_t revokeperms; 1799 vm_object_t object; 1800 vm_ooffset_t offset; 1801 struct vnode *vp; 1802 1803 if (!mac_mmap_revocation) 1804 return; 1805 1806 vm_map_lock_read(map); 1807 for (vme = map->header.next; vme != &map->header; vme = vme->next) { 1808 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 1809 mac_cred_mmapped_drop_perms_recurse(td, cred, 1810 vme->object.sub_map); 1811 continue; 1812 } 1813 /* 1814 * Skip over entries that obviously are not shared. 1815 */ 1816 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 1817 !vme->max_protection) 1818 continue; 1819 /* 1820 * Drill down to the deepest backing object. 1821 */ 1822 offset = vme->offset; 1823 object = vme->object.vm_object; 1824 if (object == NULL) 1825 continue; 1826 while (object->backing_object != NULL) { 1827 object = object->backing_object; 1828 offset += object->backing_object_offset; 1829 } 1830 /* 1831 * At the moment, vm_maps and objects aren't considered 1832 * by the MAC system, so only things with backing by a 1833 * normal object (read: vnodes) are checked. 1834 */ 1835 if (object->type != OBJT_VNODE) 1836 continue; 1837 vp = (struct vnode *)object->handle; 1838 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1839 result = vme->max_protection; 1840 mac_check_vnode_mmap_downgrade(cred, vp, &result); 1841 VOP_UNLOCK(vp, 0, td); 1842 /* 1843 * Find out what maximum protection we may be allowing 1844 * now but a policy needs to get removed. 1845 */ 1846 revokeperms = vme->max_protection & ~result; 1847 if (!revokeperms) 1848 continue; 1849 printf("pid %ld: revoking %s perms from %#lx:%ld " 1850 "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 1851 prot2str(revokeperms), (u_long)vme->start, 1852 (long)(vme->end - vme->start), 1853 prot2str(vme->max_protection), prot2str(vme->protection)); 1854 vm_map_lock_upgrade(map); 1855 /* 1856 * This is the really simple case: if a map has more 1857 * max_protection than is allowed, but it's not being 1858 * actually used (that is, the current protection is 1859 * still allowed), we can just wipe it out and do 1860 * nothing more. 1861 */ 1862 if ((vme->protection & revokeperms) == 0) { 1863 vme->max_protection -= revokeperms; 1864 } else { 1865 if (revokeperms & VM_PROT_WRITE) { 1866 /* 1867 * In the more complicated case, flush out all 1868 * pending changes to the object then turn it 1869 * copy-on-write. 1870 */ 1871 vm_object_reference(object); 1872 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1873 vm_object_page_clean(object, 1874 OFF_TO_IDX(offset), 1875 OFF_TO_IDX(offset + vme->end - vme->start + 1876 PAGE_MASK), 1877 OBJPC_SYNC); 1878 VOP_UNLOCK(vp, 0, td); 1879 vm_object_deallocate(object); 1880 /* 1881 * Why bother if there's no read permissions 1882 * anymore? For the rest, we need to leave 1883 * the write permissions on for COW, or 1884 * remove them entirely if configured to. 1885 */ 1886 if (!mac_mmap_revocation_via_cow) { 1887 vme->max_protection &= ~VM_PROT_WRITE; 1888 vme->protection &= ~VM_PROT_WRITE; 1889 } if ((revokeperms & VM_PROT_READ) == 0) 1890 vme->eflags |= MAP_ENTRY_COW | 1891 MAP_ENTRY_NEEDS_COPY; 1892 } 1893 if (revokeperms & VM_PROT_EXECUTE) { 1894 vme->max_protection &= ~VM_PROT_EXECUTE; 1895 vme->protection &= ~VM_PROT_EXECUTE; 1896 } 1897 if (revokeperms & VM_PROT_READ) { 1898 vme->max_protection = 0; 1899 vme->protection = 0; 1900 } 1901 pmap_protect(map->pmap, vme->start, vme->end, 1902 vme->protection & ~revokeperms); 1903 vm_map_simplify_entry(map, vme); 1904 } 1905 vm_map_lock_downgrade(map); 1906 } 1907 vm_map_unlock_read(map); 1908} 1909 1910/* 1911 * When the subject's label changes, it may require revocation of privilege 1912 * to mapped objects. This can't be done on-the-fly later with a unified 1913 * buffer cache. 1914 */ 1915static void 1916mac_relabel_cred(struct ucred *cred, struct label *newlabel) 1917{ 1918 1919 MAC_PERFORM(relabel_cred, cred, newlabel); 1920} 1921 1922void 1923mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 1924{ 1925 1926 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 1927} 1928 1929void 1930mac_create_ifnet(struct ifnet *ifnet) 1931{ 1932 1933 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 1934} 1935 1936void 1937mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 1938{ 1939 1940 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 1941} 1942 1943void 1944mac_create_socket(struct ucred *cred, struct socket *socket) 1945{ 1946 1947 MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 1948} 1949 1950void 1951mac_create_pipe(struct ucred *cred, struct pipe *pipe) 1952{ 1953 1954 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 1955} 1956 1957void 1958mac_create_socket_from_socket(struct socket *oldsocket, 1959 struct socket *newsocket) 1960{ 1961 1962 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 1963 newsocket, &newsocket->so_label); 1964} 1965 1966static void 1967mac_relabel_socket(struct ucred *cred, struct socket *socket, 1968 struct label *newlabel) 1969{ 1970 1971 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 1972} 1973 1974static void 1975mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 1976{ 1977 1978 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 1979} 1980 1981void 1982mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 1983{ 1984 1985 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 1986 socket, &socket->so_peerlabel); 1987} 1988 1989void 1990mac_set_socket_peer_from_socket(struct socket *oldsocket, 1991 struct socket *newsocket) 1992{ 1993 1994 MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 1995 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 1996} 1997 1998void 1999mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 2000{ 2001 2002 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 2003 datagram, &datagram->m_pkthdr.label); 2004} 2005 2006void 2007mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 2008{ 2009 2010 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 2011 fragment, &fragment->m_pkthdr.label); 2012} 2013 2014void 2015mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 2016{ 2017 2018 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2019 &ipq->ipq_label); 2020} 2021 2022void 2023mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2024{ 2025 2026 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 2027 newmbuf, &newmbuf->m_pkthdr.label); 2028} 2029 2030void 2031mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 2032{ 2033 2034 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 2035 &mbuf->m_pkthdr.label); 2036} 2037 2038void 2039mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 2040{ 2041 2042 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 2043 &mbuf->m_pkthdr.label); 2044} 2045 2046void 2047mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 2048{ 2049 2050 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 2051 &mbuf->m_pkthdr.label); 2052} 2053 2054void 2055mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 2056 struct mbuf *newmbuf) 2057{ 2058 2059 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 2060 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 2061 &newmbuf->m_pkthdr.label); 2062} 2063 2064void 2065mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2066{ 2067 2068 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 2069 newmbuf, &newmbuf->m_pkthdr.label); 2070} 2071 2072int 2073mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 2074{ 2075 int result; 2076 2077 result = 1; 2078 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 2079 ipq, &ipq->ipq_label); 2080 2081 return (result); 2082} 2083 2084void 2085mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 2086{ 2087 2088 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2089 &ipq->ipq_label); 2090} 2091 2092void 2093mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 2094{ 2095 2096 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 2097 &mbuf->m_pkthdr.label); 2098} 2099 2100void 2101mac_create_mount(struct ucred *cred, struct mount *mp) 2102{ 2103 2104 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 2105 &mp->mnt_fslabel); 2106} 2107 2108void 2109mac_create_root_mount(struct ucred *cred, struct mount *mp) 2110{ 2111 2112 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 2113 &mp->mnt_fslabel); 2114} 2115 2116int 2117mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 2118{ 2119 int error; 2120 2121 if (!mac_enforce_network) 2122 return (0); 2123 2124 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 2125 &ifnet->if_label); 2126 2127 return (error); 2128} 2129 2130static int 2131mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 2132{ 2133 int error; 2134 2135 MAC_CHECK(check_cred_relabel, cred, newlabel); 2136 2137 return (error); 2138} 2139 2140int 2141mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 2142{ 2143 int error; 2144 2145 if (!mac_enforce_process) 2146 return (0); 2147 2148 MAC_CHECK(check_cred_visible, u1, u2); 2149 2150 return (error); 2151} 2152 2153int 2154mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 2155{ 2156 int error; 2157 2158 if (!mac_enforce_network) 2159 return (0); 2160 2161 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 2162 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 2163 if_printf(ifnet, "not initialized\n"); 2164 2165 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 2166 &mbuf->m_pkthdr.label); 2167 2168 return (error); 2169} 2170 2171int 2172mac_check_kenv_dump(struct ucred *cred) 2173{ 2174 int error; 2175 2176 if (!mac_enforce_system) 2177 return (0); 2178 2179 MAC_CHECK(check_kenv_dump, cred); 2180 2181 return (error); 2182} 2183 2184int 2185mac_check_kenv_get(struct ucred *cred, char *name) 2186{ 2187 int error; 2188 2189 if (!mac_enforce_system) 2190 return (0); 2191 2192 MAC_CHECK(check_kenv_get, cred, name); 2193 2194 return (error); 2195} 2196 2197int 2198mac_check_kenv_set(struct ucred *cred, char *name, char *value) 2199{ 2200 int error; 2201 2202 if (!mac_enforce_system) 2203 return (0); 2204 2205 MAC_CHECK(check_kenv_set, cred, name, value); 2206 2207 return (error); 2208} 2209 2210int 2211mac_check_kenv_unset(struct ucred *cred, char *name) 2212{ 2213 int error; 2214 2215 if (!mac_enforce_system) 2216 return (0); 2217 2218 MAC_CHECK(check_kenv_unset, cred, name); 2219 2220 return (error); 2221} 2222 2223int 2224mac_check_mount_stat(struct ucred *cred, struct mount *mount) 2225{ 2226 int error; 2227 2228 if (!mac_enforce_fs) 2229 return (0); 2230 2231 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 2232 2233 return (error); 2234} 2235 2236int 2237mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 2238 void *data) 2239{ 2240 int error; 2241 2242 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2243 2244 if (!mac_enforce_pipe) 2245 return (0); 2246 2247 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 2248 2249 return (error); 2250} 2251 2252int 2253mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 2254{ 2255 int error; 2256 2257 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2258 2259 if (!mac_enforce_pipe) 2260 return (0); 2261 2262 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2263 2264 return (error); 2265} 2266 2267int 2268mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2269{ 2270 int error; 2271 2272 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2273 2274 if (!mac_enforce_pipe) 2275 return (0); 2276 2277 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 2278 2279 return (error); 2280} 2281 2282static int 2283mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 2284 struct label *newlabel) 2285{ 2286 int error; 2287 2288 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2289 2290 if (!mac_enforce_pipe) 2291 return (0); 2292 2293 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 2294 2295 return (error); 2296} 2297 2298int 2299mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2300{ 2301 int error; 2302 2303 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2304 2305 if (!mac_enforce_pipe) 2306 return (0); 2307 2308 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2309 2310 return (error); 2311} 2312 2313int 2314mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2315{ 2316 int error; 2317 2318 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2319 2320 if (!mac_enforce_pipe) 2321 return (0); 2322 2323 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2324 2325 return (error); 2326} 2327 2328int 2329mac_check_proc_debug(struct ucred *cred, struct proc *proc) 2330{ 2331 int error; 2332 2333 PROC_LOCK_ASSERT(proc, MA_OWNED); 2334 2335 if (!mac_enforce_process) 2336 return (0); 2337 2338 MAC_CHECK(check_proc_debug, cred, proc); 2339 2340 return (error); 2341} 2342 2343int 2344mac_check_proc_sched(struct ucred *cred, struct proc *proc) 2345{ 2346 int error; 2347 2348 PROC_LOCK_ASSERT(proc, MA_OWNED); 2349 2350 if (!mac_enforce_process) 2351 return (0); 2352 2353 MAC_CHECK(check_proc_sched, cred, proc); 2354 2355 return (error); 2356} 2357 2358int 2359mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 2360{ 2361 int error; 2362 2363 PROC_LOCK_ASSERT(proc, MA_OWNED); 2364 2365 if (!mac_enforce_process) 2366 return (0); 2367 2368 MAC_CHECK(check_proc_signal, cred, proc, signum); 2369 2370 return (error); 2371} 2372 2373int 2374mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 2375 struct sockaddr *sockaddr) 2376{ 2377 int error; 2378 2379 if (!mac_enforce_socket) 2380 return (0); 2381 2382 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 2383 sockaddr); 2384 2385 return (error); 2386} 2387 2388int 2389mac_check_socket_connect(struct ucred *cred, struct socket *socket, 2390 struct sockaddr *sockaddr) 2391{ 2392 int error; 2393 2394 if (!mac_enforce_socket) 2395 return (0); 2396 2397 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 2398 sockaddr); 2399 2400 return (error); 2401} 2402 2403int 2404mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2405{ 2406 int error; 2407 2408 if (!mac_enforce_socket) 2409 return (0); 2410 2411 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2412 &mbuf->m_pkthdr.label); 2413 2414 return (error); 2415} 2416 2417int 2418mac_check_socket_listen(struct ucred *cred, struct socket *socket) 2419{ 2420 int error; 2421 2422 if (!mac_enforce_socket) 2423 return (0); 2424 2425 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 2426 return (error); 2427} 2428 2429int 2430mac_check_socket_receive(struct ucred *cred, struct socket *so) 2431{ 2432 int error; 2433 2434 if (!mac_enforce_socket) 2435 return (0); 2436 2437 MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2438 2439 return (error); 2440} 2441 2442static int 2443mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 2444 struct label *newlabel) 2445{ 2446 int error; 2447 2448 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 2449 newlabel); 2450 2451 return (error); 2452} 2453 2454int 2455mac_check_socket_send(struct ucred *cred, struct socket *so) 2456{ 2457 int error; 2458 2459 if (!mac_enforce_socket) 2460 return (0); 2461 2462 MAC_CHECK(check_socket_send, cred, so, &so->so_label); 2463 2464 return (error); 2465} 2466 2467int 2468mac_check_socket_visible(struct ucred *cred, struct socket *socket) 2469{ 2470 int error; 2471 2472 if (!mac_enforce_socket) 2473 return (0); 2474 2475 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 2476 2477 return (error); 2478} 2479 2480int 2481mac_check_system_acct(struct ucred *cred, struct vnode *vp) 2482{ 2483 int error; 2484 2485 if (vp != NULL) { 2486 ASSERT_VOP_LOCKED(vp, "mac_check_system_acct"); 2487 } 2488 2489 if (!mac_enforce_system) 2490 return (0); 2491 2492 MAC_CHECK(check_system_acct, cred, vp, 2493 vp != NULL ? &vp->v_label : NULL); 2494 2495 return (error); 2496} 2497 2498int 2499mac_check_system_nfsd(struct ucred *cred) 2500{ 2501 int error; 2502 2503 if (!mac_enforce_system) 2504 return (0); 2505 2506 MAC_CHECK(check_system_nfsd, cred); 2507 2508 return (error); 2509} 2510 2511int 2512mac_check_system_reboot(struct ucred *cred, int howto) 2513{ 2514 int error; 2515 2516 if (!mac_enforce_system) 2517 return (0); 2518 2519 MAC_CHECK(check_system_reboot, cred, howto); 2520 2521 return (error); 2522} 2523 2524int 2525mac_check_system_settime(struct ucred *cred) 2526{ 2527 int error; 2528 2529 if (!mac_enforce_system) 2530 return (0); 2531 2532 MAC_CHECK(check_system_settime, cred); 2533 2534 return (error); 2535} 2536 2537int 2538mac_check_system_swapon(struct ucred *cred, struct vnode *vp) 2539{ 2540 int error; 2541 2542 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 2543 2544 if (!mac_enforce_system) 2545 return (0); 2546 2547 MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 2548 return (error); 2549} 2550 2551int 2552mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 2553 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 2554{ 2555 int error; 2556 2557 /* 2558 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here, 2559 * but since it's not exported from kern_sysctl.c, we can't. 2560 */ 2561 if (!mac_enforce_system) 2562 return (0); 2563 2564 MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp, 2565 inkernel, new, newlen); 2566 2567 return (error); 2568} 2569 2570int 2571mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 2572 struct ifnet *ifnet) 2573{ 2574 char *elements, *buffer; 2575 struct mac mac; 2576 int error; 2577 2578 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 2579 if (error) 2580 return (error); 2581 2582 error = mac_check_structmac_consistent(&mac); 2583 if (error) 2584 return (error); 2585 2586 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2587 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2588 if (error) { 2589 free(elements, M_MACTEMP); 2590 return (error); 2591 } 2592 2593 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2594 error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 2595 buffer, mac.m_buflen, M_WAITOK); 2596 if (error == 0) 2597 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2598 2599 free(buffer, M_MACTEMP); 2600 free(elements, M_MACTEMP); 2601 2602 return (error); 2603} 2604 2605int 2606mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 2607 struct ifnet *ifnet) 2608{ 2609 struct label intlabel; 2610 struct mac mac; 2611 char *buffer; 2612 int error; 2613 2614 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 2615 if (error) 2616 return (error); 2617 2618 error = mac_check_structmac_consistent(&mac); 2619 if (error) 2620 return (error); 2621 2622 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2623 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 2624 if (error) { 2625 free(buffer, M_MACTEMP); 2626 return (error); 2627 } 2628 2629 mac_init_ifnet_label(&intlabel); 2630 error = mac_internalize_ifnet_label(&intlabel, buffer); 2631 free(buffer, M_MACTEMP); 2632 if (error) { 2633 mac_destroy_ifnet_label(&intlabel); 2634 return (error); 2635 } 2636 2637 /* 2638 * XXX: Note that this is a redundant privilege check, since 2639 * policies impose this check themselves if required by the 2640 * policy. Eventually, this should go away. 2641 */ 2642 error = suser_cred(cred, 0); 2643 if (error) { 2644 mac_destroy_ifnet_label(&intlabel); 2645 return (error); 2646 } 2647 2648 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 2649 &intlabel); 2650 if (error) { 2651 mac_destroy_ifnet_label(&intlabel); 2652 return (error); 2653 } 2654 2655 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 2656 2657 mac_destroy_ifnet_label(&intlabel); 2658 return (0); 2659} 2660 2661void 2662mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp) 2663{ 2664 2665 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 2666} 2667 2668void 2669mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 2670{ 2671 2672 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 2673} 2674 2675void 2676mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 2677 struct devfs_dirent *de) 2678{ 2679 2680 MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de, 2681 &de->de_label); 2682} 2683 2684void 2685mac_create_devfs_directory(char *dirname, int dirnamelen, 2686 struct devfs_dirent *de) 2687{ 2688 2689 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 2690 &de->de_label); 2691} 2692 2693int 2694mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 2695 struct mac *mac) 2696{ 2697 struct label intlabel; 2698 char *buffer; 2699 int error; 2700 2701 error = mac_check_structmac_consistent(mac); 2702 if (error) 2703 return (error); 2704 2705 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2706 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 2707 if (error) { 2708 free(buffer, M_MACTEMP); 2709 return (error); 2710 } 2711 2712 mac_init_socket_label(&intlabel, M_WAITOK); 2713 error = mac_internalize_socket_label(&intlabel, buffer); 2714 free(buffer, M_MACTEMP); 2715 if (error) { 2716 mac_destroy_socket_label(&intlabel); 2717 return (error); 2718 } 2719 2720 mac_check_socket_relabel(cred, so, &intlabel); 2721 if (error) { 2722 mac_destroy_socket_label(&intlabel); 2723 return (error); 2724 } 2725 2726 mac_relabel_socket(cred, so, &intlabel); 2727 2728 mac_destroy_socket_label(&intlabel); 2729 return (0); 2730} 2731 2732int 2733mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 2734{ 2735 int error; 2736 2737 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2738 2739 error = mac_check_pipe_relabel(cred, pipe, label); 2740 if (error) 2741 return (error); 2742 2743 mac_relabel_pipe(cred, pipe, label); 2744 2745 return (0); 2746} 2747 2748int 2749mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 2750 struct mac *mac) 2751{ 2752 char *buffer, *elements; 2753 int error; 2754 2755 error = mac_check_structmac_consistent(mac); 2756 if (error) 2757 return (error); 2758 2759 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2760 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2761 if (error) { 2762 free(elements, M_MACTEMP); 2763 return (error); 2764 } 2765 2766 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2767 error = mac_externalize_socket_label(&so->so_label, elements, 2768 buffer, mac->m_buflen, M_WAITOK); 2769 if (error == 0) 2770 error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2771 2772 free(buffer, M_MACTEMP); 2773 free(elements, M_MACTEMP); 2774 2775 return (error); 2776} 2777 2778int 2779mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 2780 struct mac *mac) 2781{ 2782 char *elements, *buffer; 2783 int error; 2784 2785 error = mac_check_structmac_consistent(mac); 2786 if (error) 2787 return (error); 2788 2789 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2790 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2791 if (error) { 2792 free(elements, M_MACTEMP); 2793 return (error); 2794 } 2795 2796 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2797 error = mac_externalize_socket_peer_label(&so->so_peerlabel, 2798 elements, buffer, mac->m_buflen, M_WAITOK); 2799 if (error == 0) 2800 error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2801 2802 free(buffer, M_MACTEMP); 2803 free(elements, M_MACTEMP); 2804 2805 return (error); 2806} 2807 2808/* 2809 * Implementation of VOP_SETLABEL() that relies on extended attributes 2810 * to store label data. Can be referenced by filesystems supporting 2811 * extended attributes. 2812 */ 2813int 2814vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 2815{ 2816 struct vnode *vp = ap->a_vp; 2817 struct label *intlabel = ap->a_label; 2818 int error; 2819 2820 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 2821 2822 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2823 return (EOPNOTSUPP); 2824 2825 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 2826 if (error) 2827 return (error); 2828 2829 mac_relabel_vnode(ap->a_cred, vp, intlabel); 2830 2831 return (0); 2832} 2833 2834static int 2835vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 2836{ 2837 int error; 2838 2839 if (vp->v_mount == NULL) { 2840 /* printf("vn_setlabel: null v_mount\n"); */ 2841 if (vp->v_type != VNON) 2842 printf("vn_setlabel: null v_mount with non-VNON\n"); 2843 return (EBADF); 2844 } 2845 2846 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2847 return (EOPNOTSUPP); 2848 2849 /* 2850 * Multi-phase commit. First check the policies to confirm the 2851 * change is OK. Then commit via the filesystem. Finally, 2852 * update the actual vnode label. Question: maybe the filesystem 2853 * should update the vnode at the end as part of VOP_SETLABEL()? 2854 */ 2855 error = mac_check_vnode_relabel(cred, vp, intlabel); 2856 if (error) 2857 return (error); 2858 2859 /* 2860 * VADMIN provides the opportunity for the filesystem to make 2861 * decisions about who is and is not able to modify labels 2862 * and protections on files. This might not be right. We can't 2863 * assume VOP_SETLABEL() will do it, because we might implement 2864 * that as part of vop_stdsetlabel_ea(). 2865 */ 2866 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 2867 if (error) 2868 return (error); 2869 2870 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 2871 if (error) 2872 return (error); 2873 2874 return (0); 2875} 2876 2877int 2878__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 2879{ 2880 char *elements, *buffer; 2881 struct mac mac; 2882 struct proc *tproc; 2883 struct ucred *tcred; 2884 int error; 2885 2886 error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac)); 2887 if (error) 2888 return (error); 2889 2890 error = mac_check_structmac_consistent(&mac); 2891 if (error) 2892 return (error); 2893 2894 tproc = pfind(uap->pid); 2895 if (tproc == NULL) 2896 return (ESRCH); 2897 2898 tcred = NULL; /* Satisfy gcc. */ 2899 error = p_cansee(td, tproc); 2900 if (error == 0) 2901 tcred = crhold(tproc->p_ucred); 2902 PROC_UNLOCK(tproc); 2903 if (error) 2904 return (error); 2905 2906 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2907 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2908 if (error) { 2909 free(elements, M_MACTEMP); 2910 crfree(tcred); 2911 return (error); 2912 } 2913 2914 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2915 error = mac_externalize_cred_label(&tcred->cr_label, elements, 2916 buffer, mac.m_buflen, M_WAITOK); 2917 if (error == 0) 2918 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2919 2920 free(buffer, M_MACTEMP); 2921 free(elements, M_MACTEMP); 2922 crfree(tcred); 2923 return (error); 2924} 2925 2926/* 2927 * MPSAFE 2928 */ 2929int 2930__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 2931{ 2932 char *elements, *buffer; 2933 struct mac mac; 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 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2945 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2946 if (error) { 2947 free(elements, M_MACTEMP); 2948 return (error); 2949 } 2950 2951 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2952 error = mac_externalize_cred_label(&td->td_ucred->cr_label, 2953 elements, buffer, mac.m_buflen, M_WAITOK); 2954 if (error == 0) 2955 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2956 2957 free(buffer, M_MACTEMP); 2958 free(elements, M_MACTEMP); 2959 return (error); 2960} 2961 2962/* 2963 * MPSAFE 2964 */ 2965int 2966__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 2967{ 2968 struct ucred *newcred, *oldcred; 2969 struct label intlabel; 2970 struct proc *p; 2971 struct mac mac; 2972 char *buffer; 2973 int error; 2974 2975 error = copyin(uap->mac_p, &mac, sizeof(mac)); 2976 if (error) 2977 return (error); 2978 2979 error = mac_check_structmac_consistent(&mac); 2980 if (error) 2981 return (error); 2982 2983 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2984 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 2985 if (error) { 2986 free(buffer, M_MACTEMP); 2987 return (error); 2988 } 2989 2990 mac_init_cred_label(&intlabel); 2991 error = mac_internalize_cred_label(&intlabel, buffer); 2992 free(buffer, M_MACTEMP); 2993 if (error) { 2994 mac_destroy_cred_label(&intlabel); 2995 return (error); 2996 } 2997 2998 newcred = crget(); 2999 3000 p = td->td_proc; 3001 PROC_LOCK(p); 3002 oldcred = p->p_ucred; 3003 3004 error = mac_check_cred_relabel(oldcred, &intlabel); 3005 if (error) { 3006 PROC_UNLOCK(p); 3007 crfree(newcred); 3008 goto out; 3009 } 3010 3011 setsugid(p); 3012 crcopy(newcred, oldcred); 3013 mac_relabel_cred(newcred, &intlabel); 3014 p->p_ucred = newcred; 3015 3016 /* 3017 * Grab additional reference for use while revoking mmaps, prior 3018 * to releasing the proc lock and sharing the cred. 3019 */ 3020 crhold(newcred); 3021 PROC_UNLOCK(p); 3022 3023 if (mac_enforce_vm) { 3024 mtx_lock(&Giant); 3025 mac_cred_mmapped_drop_perms(td, newcred); 3026 mtx_unlock(&Giant); 3027 } 3028 3029 crfree(newcred); /* Free revocation reference. */ 3030 crfree(oldcred); 3031 3032out: 3033 mac_destroy_cred_label(&intlabel); 3034 return (error); 3035} 3036 3037/* 3038 * MPSAFE 3039 */ 3040int 3041__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3042{ 3043 char *elements, *buffer; 3044 struct label intlabel; 3045 struct file *fp; 3046 struct mac mac; 3047 struct vnode *vp; 3048 struct pipe *pipe; 3049 short label_type; 3050 int error; 3051 3052 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3053 if (error) 3054 return (error); 3055 3056 error = mac_check_structmac_consistent(&mac); 3057 if (error) 3058 return (error); 3059 3060 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3061 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3062 if (error) { 3063 free(elements, M_MACTEMP); 3064 return (error); 3065 } 3066 3067 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3068 mtx_lock(&Giant); /* VFS */ 3069 error = fget(td, SCARG(uap, fd), &fp); 3070 if (error) 3071 goto out; 3072 3073 label_type = fp->f_type; 3074 switch (fp->f_type) { 3075 case DTYPE_FIFO: 3076 case DTYPE_VNODE: 3077 vp = (struct vnode *)fp->f_data; 3078 3079 mac_init_vnode_label(&intlabel); 3080 3081 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3082 mac_copy_vnode_label(&vp->v_label, &intlabel); 3083 VOP_UNLOCK(vp, 0, td); 3084 3085 break; 3086 case DTYPE_PIPE: 3087 pipe = (struct pipe *)fp->f_data; 3088 3089 mac_init_pipe_label(&intlabel); 3090 3091 PIPE_LOCK(pipe); 3092 mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3093 PIPE_UNLOCK(pipe); 3094 break; 3095 default: 3096 error = EINVAL; 3097 fdrop(fp, td); 3098 goto out; 3099 } 3100 fdrop(fp, td); 3101 3102 switch (label_type) { 3103 case DTYPE_FIFO: 3104 case DTYPE_VNODE: 3105 if (error == 0) 3106 error = mac_externalize_vnode_label(&intlabel, 3107 elements, buffer, mac.m_buflen, M_WAITOK); 3108 mac_destroy_vnode_label(&intlabel); 3109 break; 3110 case DTYPE_PIPE: 3111 error = mac_externalize_pipe_label(&intlabel, elements, 3112 buffer, mac.m_buflen, M_WAITOK); 3113 mac_destroy_pipe_label(&intlabel); 3114 break; 3115 default: 3116 panic("__mac_get_fd: corrupted label_type"); 3117 } 3118 3119 if (error == 0) 3120 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3121 3122out: 3123 mtx_unlock(&Giant); /* VFS */ 3124 free(buffer, M_MACTEMP); 3125 free(elements, M_MACTEMP); 3126 3127 return (error); 3128} 3129 3130/* 3131 * MPSAFE 3132 */ 3133int 3134__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3135{ 3136 char *elements, *buffer; 3137 struct nameidata nd; 3138 struct label intlabel; 3139 struct mac mac; 3140 int error; 3141 3142 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3143 if (error) 3144 return (error); 3145 3146 error = mac_check_structmac_consistent(&mac); 3147 if (error) 3148 return (error); 3149 3150 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3151 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3152 if (error) { 3153 free(elements, M_MACTEMP); 3154 return (error); 3155 } 3156 3157 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3158 mtx_lock(&Giant); /* VFS */ 3159 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3160 td); 3161 error = namei(&nd); 3162 if (error) 3163 goto out; 3164 3165 mac_init_vnode_label(&intlabel); 3166 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3167 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3168 mac.m_buflen, M_WAITOK); 3169 3170 NDFREE(&nd, 0); 3171 mac_destroy_vnode_label(&intlabel); 3172 3173 if (error == 0) 3174 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3175 3176out: 3177 mtx_unlock(&Giant); /* VFS */ 3178 3179 free(buffer, M_MACTEMP); 3180 free(elements, M_MACTEMP); 3181 3182 return (error); 3183} 3184 3185/* 3186 * MPSAFE 3187 */ 3188int 3189__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3190{ 3191 char *elements, *buffer; 3192 struct nameidata nd; 3193 struct label intlabel; 3194 struct mac mac; 3195 int error; 3196 3197 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3198 if (error) 3199 return (error); 3200 3201 error = mac_check_structmac_consistent(&mac); 3202 if (error) 3203 return (error); 3204 3205 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3206 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3207 if (error) { 3208 free(elements, M_MACTEMP); 3209 return (error); 3210 } 3211 3212 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3213 mtx_lock(&Giant); /* VFS */ 3214 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3215 td); 3216 error = namei(&nd); 3217 if (error) 3218 goto out; 3219 3220 mac_init_vnode_label(&intlabel); 3221 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3222 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3223 mac.m_buflen, M_WAITOK); 3224 NDFREE(&nd, 0); 3225 mac_destroy_vnode_label(&intlabel); 3226 3227 if (error == 0) 3228 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3229 3230out: 3231 mtx_unlock(&Giant); /* VFS */ 3232 3233 free(buffer, M_MACTEMP); 3234 free(elements, M_MACTEMP); 3235 3236 return (error); 3237} 3238 3239/* 3240 * MPSAFE 3241 */ 3242int 3243__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3244{ 3245 struct label intlabel; 3246 struct pipe *pipe; 3247 struct file *fp; 3248 struct mount *mp; 3249 struct vnode *vp; 3250 struct mac mac; 3251 char *buffer; 3252 int error; 3253 3254 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3255 if (error) 3256 return (error); 3257 3258 error = mac_check_structmac_consistent(&mac); 3259 if (error) 3260 return (error); 3261 3262 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3263 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3264 if (error) { 3265 free(buffer, M_MACTEMP); 3266 return (error); 3267 } 3268 3269 mtx_lock(&Giant); /* VFS */ 3270 3271 error = fget(td, SCARG(uap, fd), &fp); 3272 if (error) 3273 goto out; 3274 3275 switch (fp->f_type) { 3276 case DTYPE_FIFO: 3277 case DTYPE_VNODE: 3278 mac_init_vnode_label(&intlabel); 3279 error = mac_internalize_vnode_label(&intlabel, buffer); 3280 if (error) { 3281 mac_destroy_vnode_label(&intlabel); 3282 break; 3283 } 3284 3285 vp = (struct vnode *)fp->f_data; 3286 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3287 if (error != 0) { 3288 mac_destroy_vnode_label(&intlabel); 3289 break; 3290 } 3291 3292 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3293 error = vn_setlabel(vp, &intlabel, td->td_ucred); 3294 VOP_UNLOCK(vp, 0, td); 3295 vn_finished_write(mp); 3296 3297 mac_destroy_vnode_label(&intlabel); 3298 break; 3299 3300 case DTYPE_PIPE: 3301 mac_init_pipe_label(&intlabel); 3302 error = mac_internalize_pipe_label(&intlabel, buffer); 3303 if (error == 0) { 3304 pipe = (struct pipe *)fp->f_data; 3305 PIPE_LOCK(pipe); 3306 error = mac_pipe_label_set(td->td_ucred, pipe, 3307 &intlabel); 3308 PIPE_UNLOCK(pipe); 3309 } 3310 3311 mac_destroy_pipe_label(&intlabel); 3312 break; 3313 3314 default: 3315 error = EINVAL; 3316 } 3317 3318 fdrop(fp, td); 3319out: 3320 mtx_unlock(&Giant); /* VFS */ 3321 3322 free(buffer, M_MACTEMP); 3323 3324 return (error); 3325} 3326 3327/* 3328 * MPSAFE 3329 */ 3330int 3331__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3332{ 3333 struct label intlabel; 3334 struct nameidata nd; 3335 struct mount *mp; 3336 struct mac mac; 3337 char *buffer; 3338 int error; 3339 3340 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3341 if (error) 3342 return (error); 3343 3344 error = mac_check_structmac_consistent(&mac); 3345 if (error) 3346 return (error); 3347 3348 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3349 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3350 if (error) { 3351 free(buffer, M_MACTEMP); 3352 return (error); 3353 } 3354 3355 mac_init_vnode_label(&intlabel); 3356 error = mac_internalize_vnode_label(&intlabel, buffer); 3357 free(buffer, M_MACTEMP); 3358 if (error) { 3359 mac_destroy_vnode_label(&intlabel); 3360 return (error); 3361 } 3362 3363 mtx_lock(&Giant); /* VFS */ 3364 3365 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3366 td); 3367 error = namei(&nd); 3368 if (error == 0) { 3369 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3370 if (error == 0) 3371 error = vn_setlabel(nd.ni_vp, &intlabel, 3372 td->td_ucred); 3373 vn_finished_write(mp); 3374 } 3375 3376 NDFREE(&nd, 0); 3377 mtx_unlock(&Giant); /* VFS */ 3378 mac_destroy_vnode_label(&intlabel); 3379 3380 return (error); 3381} 3382 3383/* 3384 * MPSAFE 3385 */ 3386int 3387__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3388{ 3389 struct label intlabel; 3390 struct nameidata nd; 3391 struct mount *mp; 3392 struct mac mac; 3393 char *buffer; 3394 int error; 3395 3396 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3397 if (error) 3398 return (error); 3399 3400 error = mac_check_structmac_consistent(&mac); 3401 if (error) 3402 return (error); 3403 3404 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3405 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3406 if (error) { 3407 free(buffer, M_MACTEMP); 3408 return (error); 3409 } 3410 3411 mac_init_vnode_label(&intlabel); 3412 error = mac_internalize_vnode_label(&intlabel, buffer); 3413 free(buffer, M_MACTEMP); 3414 if (error) { 3415 mac_destroy_vnode_label(&intlabel); 3416 return (error); 3417 } 3418 3419 mtx_lock(&Giant); /* VFS */ 3420 3421 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3422 td); 3423 error = namei(&nd); 3424 if (error == 0) { 3425 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3426 if (error == 0) 3427 error = vn_setlabel(nd.ni_vp, &intlabel, 3428 td->td_ucred); 3429 vn_finished_write(mp); 3430 } 3431 3432 NDFREE(&nd, 0); 3433 mtx_unlock(&Giant); /* VFS */ 3434 mac_destroy_vnode_label(&intlabel); 3435 3436 return (error); 3437} 3438 3439/* 3440 * MPSAFE 3441 */ 3442int 3443mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3444{ 3445 struct mac_policy_conf *mpc; 3446 char target[MAC_MAX_POLICY_NAME]; 3447 int error; 3448 3449 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL); 3450 if (error) 3451 return (error); 3452 3453 error = ENOSYS; 3454 MAC_POLICY_LIST_BUSY(); 3455 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 3456 if (strcmp(mpc->mpc_name, target) == 0 && 3457 mpc->mpc_ops->mpo_syscall != NULL) { 3458 error = mpc->mpc_ops->mpo_syscall(td, 3459 SCARG(uap, call), SCARG(uap, arg)); 3460 goto out; 3461 } 3462 } 3463 3464out: 3465 MAC_POLICY_LIST_UNBUSY(); 3466 return (error); 3467} 3468 3469SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 3470SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 3471 3472#else /* !MAC */ 3473 3474int 3475__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3476{ 3477 3478 return (ENOSYS); 3479} 3480 3481int 3482__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3483{ 3484 3485 return (ENOSYS); 3486} 3487 3488int 3489__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3490{ 3491 3492 return (ENOSYS); 3493} 3494 3495int 3496__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3497{ 3498 3499 return (ENOSYS); 3500} 3501 3502int 3503__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3504{ 3505 3506 return (ENOSYS); 3507} 3508 3509int 3510__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3511{ 3512 3513 return (ENOSYS); 3514} 3515 3516int 3517__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3518{ 3519 3520 return (ENOSYS); 3521} 3522 3523int 3524__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3525{ 3526 3527 return (ENOSYS); 3528} 3529 3530int 3531__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3532{ 3533 3534 return (ENOSYS); 3535} 3536 3537int 3538mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3539{ 3540 3541 return (ENOSYS); 3542} 3543 3544#endif 3545