mac_internal.h revision 106779
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 106779 2002-11-11 14:15:58Z 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_vnode(struct devfs_dirent *de, struct vnode *vp) 2712{ 2713 2714 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 2715} 2716 2717void 2718mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 2719{ 2720 2721 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 2722} 2723 2724void 2725mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 2726 struct devfs_dirent *de) 2727{ 2728 2729 MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de, 2730 &de->de_label); 2731} 2732 2733void 2734mac_create_devfs_directory(char *dirname, int dirnamelen, 2735 struct devfs_dirent *de) 2736{ 2737 2738 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 2739 &de->de_label); 2740} 2741 2742int 2743mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 2744 struct mac *mac) 2745{ 2746 struct label intlabel; 2747 char *buffer; 2748 int error; 2749 2750 error = mac_check_structmac_consistent(mac); 2751 if (error) 2752 return (error); 2753 2754 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2755 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 2756 if (error) { 2757 free(buffer, M_MACTEMP); 2758 return (error); 2759 } 2760 2761 mac_init_socket_label(&intlabel, M_WAITOK); 2762 error = mac_internalize_socket_label(&intlabel, buffer); 2763 free(buffer, M_MACTEMP); 2764 if (error) { 2765 mac_destroy_socket_label(&intlabel); 2766 return (error); 2767 } 2768 2769 mac_check_socket_relabel(cred, so, &intlabel); 2770 if (error) { 2771 mac_destroy_socket_label(&intlabel); 2772 return (error); 2773 } 2774 2775 mac_relabel_socket(cred, so, &intlabel); 2776 2777 mac_destroy_socket_label(&intlabel); 2778 return (0); 2779} 2780 2781int 2782mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 2783{ 2784 int error; 2785 2786 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2787 2788 error = mac_check_pipe_relabel(cred, pipe, label); 2789 if (error) 2790 return (error); 2791 2792 mac_relabel_pipe(cred, pipe, label); 2793 2794 return (0); 2795} 2796 2797int 2798mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 2799 struct mac *mac) 2800{ 2801 char *buffer, *elements; 2802 int error; 2803 2804 error = mac_check_structmac_consistent(mac); 2805 if (error) 2806 return (error); 2807 2808 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2809 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2810 if (error) { 2811 free(elements, M_MACTEMP); 2812 return (error); 2813 } 2814 2815 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2816 error = mac_externalize_socket_label(&so->so_label, elements, 2817 buffer, mac->m_buflen, M_WAITOK); 2818 if (error == 0) 2819 error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2820 2821 free(buffer, M_MACTEMP); 2822 free(elements, M_MACTEMP); 2823 2824 return (error); 2825} 2826 2827int 2828mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 2829 struct mac *mac) 2830{ 2831 char *elements, *buffer; 2832 int error; 2833 2834 error = mac_check_structmac_consistent(mac); 2835 if (error) 2836 return (error); 2837 2838 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2839 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2840 if (error) { 2841 free(elements, M_MACTEMP); 2842 return (error); 2843 } 2844 2845 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2846 error = mac_externalize_socket_peer_label(&so->so_peerlabel, 2847 elements, buffer, mac->m_buflen, M_WAITOK); 2848 if (error == 0) 2849 error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2850 2851 free(buffer, M_MACTEMP); 2852 free(elements, M_MACTEMP); 2853 2854 return (error); 2855} 2856 2857/* 2858 * Implementation of VOP_SETLABEL() that relies on extended attributes 2859 * to store label data. Can be referenced by filesystems supporting 2860 * extended attributes. 2861 */ 2862int 2863vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 2864{ 2865 struct vnode *vp = ap->a_vp; 2866 struct label *intlabel = ap->a_label; 2867 int error; 2868 2869 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 2870 2871 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2872 return (EOPNOTSUPP); 2873 2874 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 2875 if (error) 2876 return (error); 2877 2878 mac_relabel_vnode(ap->a_cred, vp, intlabel); 2879 2880 return (0); 2881} 2882 2883static int 2884vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 2885{ 2886 int error; 2887 2888 if (vp->v_mount == NULL) { 2889 /* printf("vn_setlabel: null v_mount\n"); */ 2890 if (vp->v_type != VNON) 2891 printf("vn_setlabel: null v_mount with non-VNON\n"); 2892 return (EBADF); 2893 } 2894 2895 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2896 return (EOPNOTSUPP); 2897 2898 /* 2899 * Multi-phase commit. First check the policies to confirm the 2900 * change is OK. Then commit via the filesystem. Finally, 2901 * update the actual vnode label. Question: maybe the filesystem 2902 * should update the vnode at the end as part of VOP_SETLABEL()? 2903 */ 2904 error = mac_check_vnode_relabel(cred, vp, intlabel); 2905 if (error) 2906 return (error); 2907 2908 /* 2909 * VADMIN provides the opportunity for the filesystem to make 2910 * decisions about who is and is not able to modify labels 2911 * and protections on files. This might not be right. We can't 2912 * assume VOP_SETLABEL() will do it, because we might implement 2913 * that as part of vop_stdsetlabel_ea(). 2914 */ 2915 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 2916 if (error) 2917 return (error); 2918 2919 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 2920 if (error) 2921 return (error); 2922 2923 return (0); 2924} 2925 2926int 2927__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 2928{ 2929 char *elements, *buffer; 2930 struct mac mac; 2931 struct proc *tproc; 2932 struct ucred *tcred; 2933 int error; 2934 2935 error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac)); 2936 if (error) 2937 return (error); 2938 2939 error = mac_check_structmac_consistent(&mac); 2940 if (error) 2941 return (error); 2942 2943 tproc = pfind(uap->pid); 2944 if (tproc == NULL) 2945 return (ESRCH); 2946 2947 tcred = NULL; /* Satisfy gcc. */ 2948 error = p_cansee(td, tproc); 2949 if (error == 0) 2950 tcred = crhold(tproc->p_ucred); 2951 PROC_UNLOCK(tproc); 2952 if (error) 2953 return (error); 2954 2955 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2956 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2957 if (error) { 2958 free(elements, M_MACTEMP); 2959 crfree(tcred); 2960 return (error); 2961 } 2962 2963 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2964 error = mac_externalize_cred_label(&tcred->cr_label, elements, 2965 buffer, mac.m_buflen, M_WAITOK); 2966 if (error == 0) 2967 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2968 2969 free(buffer, M_MACTEMP); 2970 free(elements, M_MACTEMP); 2971 crfree(tcred); 2972 return (error); 2973} 2974 2975/* 2976 * MPSAFE 2977 */ 2978int 2979__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 2980{ 2981 char *elements, *buffer; 2982 struct mac mac; 2983 int error; 2984 2985 error = copyin(uap->mac_p, &mac, sizeof(mac)); 2986 if (error) 2987 return (error); 2988 2989 error = mac_check_structmac_consistent(&mac); 2990 if (error) 2991 return (error); 2992 2993 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2994 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2995 if (error) { 2996 free(elements, M_MACTEMP); 2997 return (error); 2998 } 2999 3000 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3001 error = mac_externalize_cred_label(&td->td_ucred->cr_label, 3002 elements, buffer, mac.m_buflen, M_WAITOK); 3003 if (error == 0) 3004 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3005 3006 free(buffer, M_MACTEMP); 3007 free(elements, M_MACTEMP); 3008 return (error); 3009} 3010 3011/* 3012 * MPSAFE 3013 */ 3014int 3015__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3016{ 3017 struct ucred *newcred, *oldcred; 3018 struct label intlabel; 3019 struct proc *p; 3020 struct mac mac; 3021 char *buffer; 3022 int error; 3023 3024 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3025 if (error) 3026 return (error); 3027 3028 error = mac_check_structmac_consistent(&mac); 3029 if (error) 3030 return (error); 3031 3032 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3033 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3034 if (error) { 3035 free(buffer, M_MACTEMP); 3036 return (error); 3037 } 3038 3039 mac_init_cred_label(&intlabel); 3040 error = mac_internalize_cred_label(&intlabel, buffer); 3041 free(buffer, M_MACTEMP); 3042 if (error) { 3043 mac_destroy_cred_label(&intlabel); 3044 return (error); 3045 } 3046 3047 newcred = crget(); 3048 3049 p = td->td_proc; 3050 PROC_LOCK(p); 3051 oldcred = p->p_ucred; 3052 3053 error = mac_check_cred_relabel(oldcred, &intlabel); 3054 if (error) { 3055 PROC_UNLOCK(p); 3056 crfree(newcred); 3057 goto out; 3058 } 3059 3060 setsugid(p); 3061 crcopy(newcred, oldcred); 3062 mac_relabel_cred(newcred, &intlabel); 3063 p->p_ucred = newcred; 3064 3065 /* 3066 * Grab additional reference for use while revoking mmaps, prior 3067 * to releasing the proc lock and sharing the cred. 3068 */ 3069 crhold(newcred); 3070 PROC_UNLOCK(p); 3071 3072 if (mac_enforce_vm) { 3073 mtx_lock(&Giant); 3074 mac_cred_mmapped_drop_perms(td, newcred); 3075 mtx_unlock(&Giant); 3076 } 3077 3078 crfree(newcred); /* Free revocation reference. */ 3079 crfree(oldcred); 3080 3081out: 3082 mac_destroy_cred_label(&intlabel); 3083 return (error); 3084} 3085 3086/* 3087 * MPSAFE 3088 */ 3089int 3090__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3091{ 3092 char *elements, *buffer; 3093 struct label intlabel; 3094 struct file *fp; 3095 struct mac mac; 3096 struct vnode *vp; 3097 struct pipe *pipe; 3098 short label_type; 3099 int error; 3100 3101 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3102 if (error) 3103 return (error); 3104 3105 error = mac_check_structmac_consistent(&mac); 3106 if (error) 3107 return (error); 3108 3109 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3110 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3111 if (error) { 3112 free(elements, M_MACTEMP); 3113 return (error); 3114 } 3115 3116 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3117 mtx_lock(&Giant); /* VFS */ 3118 error = fget(td, SCARG(uap, fd), &fp); 3119 if (error) 3120 goto out; 3121 3122 label_type = fp->f_type; 3123 switch (fp->f_type) { 3124 case DTYPE_FIFO: 3125 case DTYPE_VNODE: 3126 vp = (struct vnode *)fp->f_data; 3127 3128 mac_init_vnode_label(&intlabel); 3129 3130 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3131 mac_copy_vnode_label(&vp->v_label, &intlabel); 3132 VOP_UNLOCK(vp, 0, td); 3133 3134 break; 3135 case DTYPE_PIPE: 3136 pipe = (struct pipe *)fp->f_data; 3137 3138 mac_init_pipe_label(&intlabel); 3139 3140 PIPE_LOCK(pipe); 3141 mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3142 PIPE_UNLOCK(pipe); 3143 break; 3144 default: 3145 error = EINVAL; 3146 fdrop(fp, td); 3147 goto out; 3148 } 3149 fdrop(fp, td); 3150 3151 switch (label_type) { 3152 case DTYPE_FIFO: 3153 case DTYPE_VNODE: 3154 if (error == 0) 3155 error = mac_externalize_vnode_label(&intlabel, 3156 elements, buffer, mac.m_buflen, M_WAITOK); 3157 mac_destroy_vnode_label(&intlabel); 3158 break; 3159 case DTYPE_PIPE: 3160 error = mac_externalize_pipe_label(&intlabel, elements, 3161 buffer, mac.m_buflen, M_WAITOK); 3162 mac_destroy_pipe_label(&intlabel); 3163 break; 3164 default: 3165 panic("__mac_get_fd: corrupted label_type"); 3166 } 3167 3168 if (error == 0) 3169 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3170 3171out: 3172 mtx_unlock(&Giant); /* VFS */ 3173 free(buffer, M_MACTEMP); 3174 free(elements, M_MACTEMP); 3175 3176 return (error); 3177} 3178 3179/* 3180 * MPSAFE 3181 */ 3182int 3183__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3184{ 3185 char *elements, *buffer; 3186 struct nameidata nd; 3187 struct label intlabel; 3188 struct mac mac; 3189 int error; 3190 3191 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3192 if (error) 3193 return (error); 3194 3195 error = mac_check_structmac_consistent(&mac); 3196 if (error) 3197 return (error); 3198 3199 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3200 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3201 if (error) { 3202 free(elements, M_MACTEMP); 3203 return (error); 3204 } 3205 3206 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3207 mtx_lock(&Giant); /* VFS */ 3208 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3209 td); 3210 error = namei(&nd); 3211 if (error) 3212 goto out; 3213 3214 mac_init_vnode_label(&intlabel); 3215 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3216 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3217 mac.m_buflen, M_WAITOK); 3218 3219 NDFREE(&nd, 0); 3220 mac_destroy_vnode_label(&intlabel); 3221 3222 if (error == 0) 3223 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3224 3225out: 3226 mtx_unlock(&Giant); /* VFS */ 3227 3228 free(buffer, M_MACTEMP); 3229 free(elements, M_MACTEMP); 3230 3231 return (error); 3232} 3233 3234/* 3235 * MPSAFE 3236 */ 3237int 3238__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3239{ 3240 char *elements, *buffer; 3241 struct nameidata nd; 3242 struct label intlabel; 3243 struct mac mac; 3244 int error; 3245 3246 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3247 if (error) 3248 return (error); 3249 3250 error = mac_check_structmac_consistent(&mac); 3251 if (error) 3252 return (error); 3253 3254 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3255 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3256 if (error) { 3257 free(elements, M_MACTEMP); 3258 return (error); 3259 } 3260 3261 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3262 mtx_lock(&Giant); /* VFS */ 3263 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3264 td); 3265 error = namei(&nd); 3266 if (error) 3267 goto out; 3268 3269 mac_init_vnode_label(&intlabel); 3270 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3271 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3272 mac.m_buflen, M_WAITOK); 3273 NDFREE(&nd, 0); 3274 mac_destroy_vnode_label(&intlabel); 3275 3276 if (error == 0) 3277 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3278 3279out: 3280 mtx_unlock(&Giant); /* VFS */ 3281 3282 free(buffer, M_MACTEMP); 3283 free(elements, M_MACTEMP); 3284 3285 return (error); 3286} 3287 3288/* 3289 * MPSAFE 3290 */ 3291int 3292__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3293{ 3294 struct label intlabel; 3295 struct pipe *pipe; 3296 struct file *fp; 3297 struct mount *mp; 3298 struct vnode *vp; 3299 struct mac mac; 3300 char *buffer; 3301 int error; 3302 3303 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3304 if (error) 3305 return (error); 3306 3307 error = mac_check_structmac_consistent(&mac); 3308 if (error) 3309 return (error); 3310 3311 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3312 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3313 if (error) { 3314 free(buffer, M_MACTEMP); 3315 return (error); 3316 } 3317 3318 mtx_lock(&Giant); /* VFS */ 3319 3320 error = fget(td, SCARG(uap, fd), &fp); 3321 if (error) 3322 goto out; 3323 3324 switch (fp->f_type) { 3325 case DTYPE_FIFO: 3326 case DTYPE_VNODE: 3327 mac_init_vnode_label(&intlabel); 3328 error = mac_internalize_vnode_label(&intlabel, buffer); 3329 if (error) { 3330 mac_destroy_vnode_label(&intlabel); 3331 break; 3332 } 3333 3334 vp = (struct vnode *)fp->f_data; 3335 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3336 if (error != 0) { 3337 mac_destroy_vnode_label(&intlabel); 3338 break; 3339 } 3340 3341 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3342 error = vn_setlabel(vp, &intlabel, td->td_ucred); 3343 VOP_UNLOCK(vp, 0, td); 3344 vn_finished_write(mp); 3345 3346 mac_destroy_vnode_label(&intlabel); 3347 break; 3348 3349 case DTYPE_PIPE: 3350 mac_init_pipe_label(&intlabel); 3351 error = mac_internalize_pipe_label(&intlabel, buffer); 3352 if (error == 0) { 3353 pipe = (struct pipe *)fp->f_data; 3354 PIPE_LOCK(pipe); 3355 error = mac_pipe_label_set(td->td_ucred, pipe, 3356 &intlabel); 3357 PIPE_UNLOCK(pipe); 3358 } 3359 3360 mac_destroy_pipe_label(&intlabel); 3361 break; 3362 3363 default: 3364 error = EINVAL; 3365 } 3366 3367 fdrop(fp, td); 3368out: 3369 mtx_unlock(&Giant); /* VFS */ 3370 3371 free(buffer, M_MACTEMP); 3372 3373 return (error); 3374} 3375 3376/* 3377 * MPSAFE 3378 */ 3379int 3380__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3381{ 3382 struct label intlabel; 3383 struct nameidata nd; 3384 struct mount *mp; 3385 struct mac mac; 3386 char *buffer; 3387 int error; 3388 3389 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3390 if (error) 3391 return (error); 3392 3393 error = mac_check_structmac_consistent(&mac); 3394 if (error) 3395 return (error); 3396 3397 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3398 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3399 if (error) { 3400 free(buffer, M_MACTEMP); 3401 return (error); 3402 } 3403 3404 mac_init_vnode_label(&intlabel); 3405 error = mac_internalize_vnode_label(&intlabel, buffer); 3406 free(buffer, M_MACTEMP); 3407 if (error) { 3408 mac_destroy_vnode_label(&intlabel); 3409 return (error); 3410 } 3411 3412 mtx_lock(&Giant); /* VFS */ 3413 3414 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3415 td); 3416 error = namei(&nd); 3417 if (error == 0) { 3418 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3419 if (error == 0) 3420 error = vn_setlabel(nd.ni_vp, &intlabel, 3421 td->td_ucred); 3422 vn_finished_write(mp); 3423 } 3424 3425 NDFREE(&nd, 0); 3426 mtx_unlock(&Giant); /* VFS */ 3427 mac_destroy_vnode_label(&intlabel); 3428 3429 return (error); 3430} 3431 3432/* 3433 * MPSAFE 3434 */ 3435int 3436__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3437{ 3438 struct label intlabel; 3439 struct nameidata nd; 3440 struct mount *mp; 3441 struct mac mac; 3442 char *buffer; 3443 int error; 3444 3445 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3446 if (error) 3447 return (error); 3448 3449 error = mac_check_structmac_consistent(&mac); 3450 if (error) 3451 return (error); 3452 3453 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3454 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3455 if (error) { 3456 free(buffer, M_MACTEMP); 3457 return (error); 3458 } 3459 3460 mac_init_vnode_label(&intlabel); 3461 error = mac_internalize_vnode_label(&intlabel, buffer); 3462 free(buffer, M_MACTEMP); 3463 if (error) { 3464 mac_destroy_vnode_label(&intlabel); 3465 return (error); 3466 } 3467 3468 mtx_lock(&Giant); /* VFS */ 3469 3470 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3471 td); 3472 error = namei(&nd); 3473 if (error == 0) { 3474 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3475 if (error == 0) 3476 error = vn_setlabel(nd.ni_vp, &intlabel, 3477 td->td_ucred); 3478 vn_finished_write(mp); 3479 } 3480 3481 NDFREE(&nd, 0); 3482 mtx_unlock(&Giant); /* VFS */ 3483 mac_destroy_vnode_label(&intlabel); 3484 3485 return (error); 3486} 3487 3488/* 3489 * MPSAFE 3490 */ 3491int 3492mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3493{ 3494 struct mac_policy_conf *mpc; 3495 char target[MAC_MAX_POLICY_NAME]; 3496 int error; 3497 3498 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL); 3499 if (error) 3500 return (error); 3501 3502 error = ENOSYS; 3503 MAC_POLICY_LIST_BUSY(); 3504 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 3505 if (strcmp(mpc->mpc_name, target) == 0 && 3506 mpc->mpc_ops->mpo_syscall != NULL) { 3507 error = mpc->mpc_ops->mpo_syscall(td, 3508 SCARG(uap, call), SCARG(uap, arg)); 3509 goto out; 3510 } 3511 } 3512 3513out: 3514 MAC_POLICY_LIST_UNBUSY(); 3515 return (error); 3516} 3517 3518SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 3519SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 3520 3521#else /* !MAC */ 3522 3523int 3524__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3525{ 3526 3527 return (ENOSYS); 3528} 3529 3530int 3531__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3532{ 3533 3534 return (ENOSYS); 3535} 3536 3537int 3538__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3539{ 3540 3541 return (ENOSYS); 3542} 3543 3544int 3545__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3546{ 3547 3548 return (ENOSYS); 3549} 3550 3551int 3552__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3553{ 3554 3555 return (ENOSYS); 3556} 3557 3558int 3559__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3560{ 3561 3562 return (ENOSYS); 3563} 3564 3565int 3566__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3567{ 3568 3569 return (ENOSYS); 3570} 3571 3572int 3573__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3574{ 3575 3576 return (ENOSYS); 3577} 3578 3579int 3580__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3581{ 3582 3583 return (ENOSYS); 3584} 3585 3586int 3587mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3588{ 3589 3590 return (ENOSYS); 3591} 3592 3593#endif 3594