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