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