mac_syscalls.c revision 137454
10SN/A/*- 215690SN/A * Copyright (c) 1999-2002 Robert N. M. Watson 30SN/A * Copyright (c) 2001 Ilmar S. Habibulin 40SN/A * Copyright (c) 2001-2004 Networks Associates Technology, Inc. 50SN/A * All rights reserved. 60SN/A * 72362SN/A * This software was developed by Robert Watson and Ilmar Habibulin for the 80SN/A * TrustedBSD Project. 92362SN/A * 100SN/A * This software was developed for the FreeBSD Project in part by Network 110SN/A * Associates Laboratories, the Security Research Division of Network 120SN/A * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 130SN/A * as part of the DARPA CHATS research program. 140SN/A * 150SN/A * Redistribution and use in source and binary forms, with or without 160SN/A * modification, are permitted provided that the following conditions 170SN/A * are met: 180SN/A * 1. Redistributions of source code must retain the above copyright 190SN/A * notice, this list of conditions and the following disclaimer. 200SN/A * 2. Redistributions in binary form must reproduce the above copyright 212362SN/A * notice, this list of conditions and the following disclaimer in the 222362SN/A * documentation and/or other materials provided with the distribution. 232362SN/A * 240SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 250SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 260SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 270SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 280SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 290SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 300SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 310SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 320SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 330SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 340SN/A * SUCH DAMAGE. 350SN/A */ 360SN/A 370SN/A/*- 380SN/A * Framework for extensible kernel access control. This file contains 390SN/A * Kernel and userland interface to the framework, policy registration 400SN/A * and composition. Per-object interfaces, controls, and labeling may be 410SN/A * found in src/sys/mac/. Sample policies may be found in src/sys/mac*. 420SN/A */ 430SN/A 440SN/A#include <sys/cdefs.h> 450SN/A__FBSDID("$FreeBSD: head/sys/security/mac/mac_syscalls.c 137454 2004-11-09 11:28:40Z rwatson $"); 460SN/A 470SN/A#include "opt_mac.h" 480SN/A#include "opt_devfs.h" 490SN/A 500SN/A#include <sys/param.h> 510SN/A#include <sys/condvar.h> 520SN/A#include <sys/extattr.h> 530SN/A#include <sys/imgact.h> 540SN/A#include <sys/kernel.h> 550SN/A#include <sys/lock.h> 560SN/A#include <sys/malloc.h> 570SN/A#include <sys/mutex.h> 580SN/A#include <sys/mac.h> 590SN/A#include <sys/module.h> 6011067SN/A#include <sys/proc.h> 610SN/A#include <sys/sbuf.h> 620SN/A#include <sys/systm.h> 6315690SN/A#include <sys/sysproto.h> 6415690SN/A#include <sys/sysent.h> 6515690SN/A#include <sys/vnode.h> 660SN/A#include <sys/mount.h> 670SN/A#include <sys/file.h> 680SN/A#include <sys/namei.h> 690SN/A#include <sys/socket.h> 700SN/A#include <sys/pipe.h> 710SN/A#include <sys/socketvar.h> 7215690SN/A#include <sys/sysctl.h> 7315690SN/A 7415690SN/A#include <vm/vm.h> 7515690SN/A#include <vm/pmap.h> 7615690SN/A#include <vm/vm_map.h> 770SN/A#include <vm/vm_object.h> 780SN/A 790SN/A#include <sys/mac_policy.h> 800SN/A 810SN/A#include <fs/devfs/devfs.h> 820SN/A 8311067SN/A#include <net/bpfdesc.h> 840SN/A#include <net/if.h> 850SN/A#include <net/if_var.h> 869696SN/A 870SN/A#include <netinet/in.h> 880SN/A#include <netinet/ip_var.h> 8915690SN/A 9015690SN/A#include <security/mac/mac_internal.h> 9115690SN/A 9215690SN/A#ifdef MAC 9315690SN/A 9415690SN/A/* 9515690SN/A * Declare that the kernel provides MAC support, version 1. This permits 9615690SN/A * modules to refuse to be loaded if the necessary support isn't present, 9715690SN/A * even if it's pre-boot. 9815690SN/A */ 9915690SN/AMODULE_VERSION(kernel_mac_support, 2); 10015690SN/A 10115690SN/ASYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 10215690SN/A "TrustedBSD MAC policy controls"); 1030SN/A 1040SN/A#if MAC_MAX_SLOTS > 32 1050SN/A#error "MAC_MAX_SLOTS too large" 1060SN/A#endif 1070SN/A 1080SN/Astatic unsigned int mac_max_slots = MAC_MAX_SLOTS; 1099696SN/Astatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 1100SN/ASYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 1110SN/A &mac_max_slots, 0, ""); 1120SN/A 1130SN/A/* 1140SN/A * Has the kernel started generating labeled objects yet? All read/write 1159103SN/A * access to this variable is serialized during the boot process. Following 1169696SN/A * the end of serialization, we don't update this flag; no locking. 1179103SN/A */ 1189696SN/Aint mac_late = 0; 1199696SN/A 1209696SN/A/* 1219696SN/A * Flag to indicate whether or not we should allocate label storage for 1229696SN/A * new mbufs. Since most dynamic policies we currently work with don't 1239696SN/A * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 1249696SN/A * unless specifically notified of interest. One result of this is 1259696SN/A * that if a dynamically loaded policy requests mbuf labels, it must 1269696SN/A * be able to deal with a NULL label being returned on any mbufs that 1279696SN/A * were already in flight when the policy was loaded. Since the policy 1289696SN/A * already has to deal with uninitialized labels, this probably won't 1299696SN/A * be a problem. Note: currently no locking. Will this be a problem? 1309696SN/A */ 1319696SN/A#ifndef MAC_ALWAYS_LABEL_MBUF 1329696SN/Aint mac_labelmbufs = 0; 1339696SN/A#endif 1340SN/A 1350SN/A#ifdef MAC_DEBUG 1360SN/ASYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1370SN/A "TrustedBSD MAC debug info"); 138SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 139 "TrustedBSD MAC object counters"); 140 141static unsigned int nmactemp; 142SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 143 &nmactemp, 0, "number of temporary labels in use"); 144#endif 145 146static int mac_policy_register(struct mac_policy_conf *mpc); 147static int mac_policy_unregister(struct mac_policy_conf *mpc); 148 149MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 150 151/* 152 * mac_static_policy_list holds a list of policy modules that are not 153 * loaded while the system is "live", and cannot be unloaded. These 154 * policies can be invoked without holding the busy count. 155 * 156 * mac_policy_list stores the list of dynamic policies. A busy count is 157 * maintained for the list, stored in mac_policy_busy. The busy count 158 * is protected by mac_policy_mtx; the list may be modified only 159 * while the busy count is 0, requiring that the lock be held to 160 * prevent new references to the list from being acquired. For almost 161 * all operations, incrementing the busy count is sufficient to 162 * guarantee consistency, as the list cannot be modified while the 163 * busy count is elevated. For a few special operations involving a 164 * change to the list of active policies, the mtx itself must be held. 165 * A condition variable, mac_policy_cv, is used to signal potential 166 * exclusive consumers that they should try to acquire the lock if a 167 * first attempt at exclusive access fails. 168 */ 169#ifndef MAC_STATIC 170static struct mtx mac_policy_mtx; 171static struct cv mac_policy_cv; 172static int mac_policy_count; 173#endif 174struct mac_policy_list_head mac_policy_list; 175struct mac_policy_list_head mac_static_policy_list; 176 177/* 178 * We manually invoke WITNESS_WARN() to allow Witness to generate 179 * warnings even if we don't end up ever triggering the wait at 180 * run-time. The consumer of the exclusive interface must not hold 181 * any locks (other than potentially Giant) since we may sleep for 182 * long (potentially indefinite) periods of time waiting for the 183 * framework to become quiescent so that a policy list change may 184 * be made. 185 */ 186void 187mac_policy_grab_exclusive(void) 188{ 189 190#ifndef MAC_STATIC 191 if (!mac_late) 192 return; 193 194 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 195 "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 196 mtx_lock(&mac_policy_mtx); 197 while (mac_policy_count != 0) 198 cv_wait(&mac_policy_cv, &mac_policy_mtx); 199#endif 200} 201 202void 203mac_policy_assert_exclusive(void) 204{ 205 206#ifndef MAC_STATIC 207 if (!mac_late) 208 return; 209 210 mtx_assert(&mac_policy_mtx, MA_OWNED); 211 KASSERT(mac_policy_count == 0, 212 ("mac_policy_assert_exclusive(): not exclusive")); 213#endif 214} 215 216void 217mac_policy_release_exclusive(void) 218{ 219 220#ifndef MAC_STATIC 221 if (!mac_late) 222 return; 223 224 KASSERT(mac_policy_count == 0, 225 ("mac_policy_release_exclusive(): not exclusive")); 226 mtx_unlock(&mac_policy_mtx); 227 cv_signal(&mac_policy_cv); 228#endif 229} 230 231void 232mac_policy_list_busy(void) 233{ 234 235#ifndef MAC_STATIC 236 if (!mac_late) 237 return; 238 239 mtx_lock(&mac_policy_mtx); 240 mac_policy_count++; 241 mtx_unlock(&mac_policy_mtx); 242#endif 243} 244 245int 246mac_policy_list_conditional_busy(void) 247{ 248#ifndef MAC_STATIC 249 int ret; 250 251 if (!mac_late) 252 return (1); 253 254 mtx_lock(&mac_policy_mtx); 255 if (!LIST_EMPTY(&mac_policy_list)) { 256 mac_policy_count++; 257 ret = 1; 258 } else 259 ret = 0; 260 mtx_unlock(&mac_policy_mtx); 261 return (ret); 262#else 263 if (!mac_late) 264 return (1); 265 266 return (1); 267#endif 268} 269 270void 271mac_policy_list_unbusy(void) 272{ 273 274#ifndef MAC_STATIC 275 if (!mac_late) 276 return; 277 278 mtx_lock(&mac_policy_mtx); 279 mac_policy_count--; 280 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 281 if (mac_policy_count == 0) 282 cv_signal(&mac_policy_cv); 283 mtx_unlock(&mac_policy_mtx); 284#endif 285} 286 287/* 288 * Initialize the MAC subsystem, including appropriate SMP locks. 289 */ 290static void 291mac_init(void) 292{ 293 294 LIST_INIT(&mac_static_policy_list); 295 LIST_INIT(&mac_policy_list); 296 mac_labelzone_init(); 297 298#ifndef MAC_STATIC 299 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 300 cv_init(&mac_policy_cv, "mac_policy_cv"); 301#endif 302} 303 304/* 305 * For the purposes of modules that want to know if they were loaded 306 * "early", set the mac_late flag once we've processed modules either 307 * linked into the kernel, or loaded before the kernel startup. 308 */ 309static void 310mac_late_init(void) 311{ 312 313 mac_late = 1; 314} 315 316/* 317 * After the policy list has changed, walk the list to update any global 318 * flags. Currently, we support only one flag, and it's conditionally 319 * defined; as a result, the entire function is conditional. Eventually, 320 * the #else case might also iterate across the policies. 321 */ 322static void 323mac_policy_updateflags(void) 324{ 325#ifndef MAC_ALWAYS_LABEL_MBUF 326 struct mac_policy_conf *tmpc; 327 int labelmbufs; 328 329 mac_policy_assert_exclusive(); 330 331 labelmbufs = 0; 332 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 333 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 334 labelmbufs++; 335 } 336 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 337 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 338 labelmbufs++; 339 } 340 mac_labelmbufs = (labelmbufs != 0); 341#endif 342} 343 344/* 345 * Allow MAC policy modules to register during boot, etc. 346 */ 347int 348mac_policy_modevent(module_t mod, int type, void *data) 349{ 350 struct mac_policy_conf *mpc; 351 int error; 352 353 error = 0; 354 mpc = (struct mac_policy_conf *) data; 355 356#ifdef MAC_STATIC 357 if (mac_late) { 358 printf("mac_policy_modevent: MAC_STATIC and late\n"); 359 return (EBUSY); 360 } 361#endif 362 363 switch (type) { 364 case MOD_LOAD: 365 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 366 mac_late) { 367 printf("mac_policy_modevent: can't load %s policy " 368 "after booting\n", mpc->mpc_name); 369 error = EBUSY; 370 break; 371 } 372 error = mac_policy_register(mpc); 373 break; 374 case MOD_UNLOAD: 375 /* Don't unregister the module if it was never registered. */ 376 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 377 != 0) 378 error = mac_policy_unregister(mpc); 379 else 380 error = 0; 381 break; 382 default: 383 error = EOPNOTSUPP; 384 break; 385 } 386 387 return (error); 388} 389 390static int 391mac_policy_register(struct mac_policy_conf *mpc) 392{ 393 struct mac_policy_conf *tmpc; 394 int error, slot, static_entry; 395 396 error = 0; 397 398 /* 399 * We don't technically need exclusive access while !mac_late, 400 * but hold it for assertion consistency. 401 */ 402 mac_policy_grab_exclusive(); 403 404 /* 405 * If the module can potentially be unloaded, or we're loading 406 * late, we have to stick it in the non-static list and pay 407 * an extra performance overhead. Otherwise, we can pay a 408 * light locking cost and stick it in the static list. 409 */ 410 static_entry = (!mac_late && 411 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 412 413 if (static_entry) { 414 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 415 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 416 error = EEXIST; 417 goto out; 418 } 419 } 420 } else { 421 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 422 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 423 error = EEXIST; 424 goto out; 425 } 426 } 427 } 428 if (mpc->mpc_field_off != NULL) { 429 slot = ffs(mac_slot_offsets_free); 430 if (slot == 0) { 431 error = ENOMEM; 432 goto out; 433 } 434 slot--; 435 mac_slot_offsets_free &= ~(1 << slot); 436 *mpc->mpc_field_off = slot; 437 } 438 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 439 440 /* 441 * If we're loading a MAC module after the framework has 442 * initialized, it has to go into the dynamic list. If 443 * we're loading it before we've finished initializing, 444 * it can go into the static list with weaker locker 445 * requirements. 446 */ 447 if (static_entry) 448 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 449 else 450 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 451 452 /* Per-policy initialization. */ 453 if (mpc->mpc_ops->mpo_init != NULL) 454 (*(mpc->mpc_ops->mpo_init))(mpc); 455 mac_policy_updateflags(); 456 457 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 458 mpc->mpc_name); 459 460out: 461 mac_policy_release_exclusive(); 462 return (error); 463} 464 465static int 466mac_policy_unregister(struct mac_policy_conf *mpc) 467{ 468 469 /* 470 * If we fail the load, we may get a request to unload. Check 471 * to see if we did the run-time registration, and if not, 472 * silently succeed. 473 */ 474 mac_policy_grab_exclusive(); 475 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 476 mac_policy_release_exclusive(); 477 return (0); 478 } 479#if 0 480 /* 481 * Don't allow unloading modules with private data. 482 */ 483 if (mpc->mpc_field_off != NULL) { 484 MAC_POLICY_LIST_UNLOCK(); 485 return (EBUSY); 486 } 487#endif 488 /* 489 * Only allow the unload to proceed if the module is unloadable 490 * by its own definition. 491 */ 492 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 493 mac_policy_release_exclusive(); 494 return (EBUSY); 495 } 496 if (mpc->mpc_ops->mpo_destroy != NULL) 497 (*(mpc->mpc_ops->mpo_destroy))(mpc); 498 499 LIST_REMOVE(mpc, mpc_list); 500 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 501 mac_policy_updateflags(); 502 503 mac_policy_release_exclusive(); 504 505 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 506 mpc->mpc_name); 507 508 return (0); 509} 510 511/* 512 * Define an error value precedence, and given two arguments, selects the 513 * value with the higher precedence. 514 */ 515int 516mac_error_select(int error1, int error2) 517{ 518 519 /* Certain decision-making errors take top priority. */ 520 if (error1 == EDEADLK || error2 == EDEADLK) 521 return (EDEADLK); 522 523 /* Invalid arguments should be reported where possible. */ 524 if (error1 == EINVAL || error2 == EINVAL) 525 return (EINVAL); 526 527 /* Precedence goes to "visibility", with both process and file. */ 528 if (error1 == ESRCH || error2 == ESRCH) 529 return (ESRCH); 530 531 if (error1 == ENOENT || error2 == ENOENT) 532 return (ENOENT); 533 534 /* Precedence goes to DAC/MAC protections. */ 535 if (error1 == EACCES || error2 == EACCES) 536 return (EACCES); 537 538 /* Precedence goes to privilege. */ 539 if (error1 == EPERM || error2 == EPERM) 540 return (EPERM); 541 542 /* Precedence goes to error over success; otherwise, arbitrary. */ 543 if (error1 != 0) 544 return (error1); 545 return (error2); 546} 547 548void 549mac_init_label(struct label *label) 550{ 551 552 bzero(label, sizeof(*label)); 553 label->l_flags = MAC_FLAG_INITIALIZED; 554} 555 556void 557mac_destroy_label(struct label *label) 558{ 559 560 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 561 ("destroying uninitialized label")); 562 563 bzero(label, sizeof(*label)); 564 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 565} 566 567int 568mac_check_structmac_consistent(struct mac *mac) 569{ 570 571 if (mac->m_buflen < 0 || 572 mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 573 return (EINVAL); 574 575 return (0); 576} 577 578/* 579 * MPSAFE 580 */ 581int 582__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 583{ 584 char *elements, *buffer; 585 struct mac mac; 586 struct proc *tproc; 587 struct ucred *tcred; 588 int error; 589 590 error = copyin(uap->mac_p, &mac, sizeof(mac)); 591 if (error) 592 return (error); 593 594 error = mac_check_structmac_consistent(&mac); 595 if (error) 596 return (error); 597 598 tproc = pfind(uap->pid); 599 if (tproc == NULL) 600 return (ESRCH); 601 602 tcred = NULL; /* Satisfy gcc. */ 603 error = p_cansee(td, tproc); 604 if (error == 0) 605 tcred = crhold(tproc->p_ucred); 606 PROC_UNLOCK(tproc); 607 if (error) 608 return (error); 609 610 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 611 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 612 if (error) { 613 free(elements, M_MACTEMP); 614 crfree(tcred); 615 return (error); 616 } 617 618 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 619 error = mac_externalize_cred_label(tcred->cr_label, elements, 620 buffer, mac.m_buflen); 621 if (error == 0) 622 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 623 624 free(buffer, M_MACTEMP); 625 free(elements, M_MACTEMP); 626 crfree(tcred); 627 return (error); 628} 629 630/* 631 * MPSAFE 632 */ 633int 634__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 635{ 636 char *elements, *buffer; 637 struct mac mac; 638 int error; 639 640 error = copyin(uap->mac_p, &mac, sizeof(mac)); 641 if (error) 642 return (error); 643 644 error = mac_check_structmac_consistent(&mac); 645 if (error) 646 return (error); 647 648 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 649 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 650 if (error) { 651 free(elements, M_MACTEMP); 652 return (error); 653 } 654 655 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 656 error = mac_externalize_cred_label(td->td_ucred->cr_label, 657 elements, buffer, mac.m_buflen); 658 if (error == 0) 659 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 660 661 free(buffer, M_MACTEMP); 662 free(elements, M_MACTEMP); 663 return (error); 664} 665 666/* 667 * MPSAFE 668 */ 669int 670__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 671{ 672 struct ucred *newcred, *oldcred; 673 struct label *intlabel; 674 struct proc *p; 675 struct mac mac; 676 char *buffer; 677 int error; 678 679 error = copyin(uap->mac_p, &mac, sizeof(mac)); 680 if (error) 681 return (error); 682 683 error = mac_check_structmac_consistent(&mac); 684 if (error) 685 return (error); 686 687 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 688 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 689 if (error) { 690 free(buffer, M_MACTEMP); 691 return (error); 692 } 693 694 intlabel = mac_cred_label_alloc(); 695 error = mac_internalize_cred_label(intlabel, buffer); 696 free(buffer, M_MACTEMP); 697 if (error) 698 goto out; 699 700 newcred = crget(); 701 702 p = td->td_proc; 703 PROC_LOCK(p); 704 oldcred = p->p_ucred; 705 706 error = mac_check_cred_relabel(oldcred, intlabel); 707 if (error) { 708 PROC_UNLOCK(p); 709 crfree(newcred); 710 goto out; 711 } 712 713 setsugid(p); 714 crcopy(newcred, oldcred); 715 mac_relabel_cred(newcred, intlabel); 716 p->p_ucred = newcred; 717 718 /* 719 * Grab additional reference for use while revoking mmaps, prior 720 * to releasing the proc lock and sharing the cred. 721 */ 722 crhold(newcred); 723 PROC_UNLOCK(p); 724 725 if (mac_enforce_vm) { 726 mtx_lock(&Giant); 727 mac_cred_mmapped_drop_perms(td, newcred); 728 mtx_unlock(&Giant); 729 } 730 731 crfree(newcred); /* Free revocation reference. */ 732 crfree(oldcred); 733 734out: 735 mac_cred_label_free(intlabel); 736 return (error); 737} 738 739/* 740 * MPSAFE 741 */ 742int 743__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 744{ 745 char *elements, *buffer; 746 struct label *intlabel; 747 struct file *fp; 748 struct mac mac; 749 struct vnode *vp; 750 struct pipe *pipe; 751 struct socket *so; 752 short label_type; 753 int error; 754 755 error = copyin(uap->mac_p, &mac, sizeof(mac)); 756 if (error) 757 return (error); 758 759 error = mac_check_structmac_consistent(&mac); 760 if (error) 761 return (error); 762 763 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 764 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 765 if (error) { 766 free(elements, M_MACTEMP); 767 return (error); 768 } 769 770 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 771 error = fget(td, uap->fd, &fp); 772 if (error) 773 goto out; 774 775 label_type = fp->f_type; 776 switch (fp->f_type) { 777 case DTYPE_FIFO: 778 case DTYPE_VNODE: 779 vp = fp->f_vnode; 780 intlabel = mac_vnode_label_alloc(); 781 mtx_lock(&Giant); /* VFS */ 782 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 783 mac_copy_vnode_label(vp->v_label, intlabel); 784 VOP_UNLOCK(vp, 0, td); 785 mtx_unlock(&Giant); /* VFS */ 786 error = mac_externalize_vnode_label(intlabel, elements, 787 buffer, mac.m_buflen); 788 mac_vnode_label_free(intlabel); 789 break; 790 791 case DTYPE_PIPE: 792 pipe = fp->f_data; 793 intlabel = mac_pipe_label_alloc(); 794 PIPE_LOCK(pipe); 795 mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 796 PIPE_UNLOCK(pipe); 797 error = mac_externalize_pipe_label(intlabel, elements, 798 buffer, mac.m_buflen); 799 mac_pipe_label_free(intlabel); 800 break; 801 802 case DTYPE_SOCKET: 803 so = fp->f_data; 804 intlabel = mac_socket_label_alloc(M_WAITOK); 805 mtx_lock(&Giant); /* Sockets */ 806 /* XXX: Socket lock here. */ 807 mac_copy_socket_label(so->so_label, intlabel); 808 /* XXX: Socket unlock here. */ 809 mtx_unlock(&Giant); /* Sockets */ 810 error = mac_externalize_socket_label(intlabel, elements, 811 buffer, mac.m_buflen); 812 mac_socket_label_free(intlabel); 813 break; 814 815 default: 816 error = EINVAL; 817 } 818 fdrop(fp, td); 819 if (error == 0) 820 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 821 822out: 823 free(buffer, M_MACTEMP); 824 free(elements, M_MACTEMP); 825 return (error); 826} 827 828/* 829 * MPSAFE 830 */ 831int 832__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 833{ 834 char *elements, *buffer; 835 struct nameidata nd; 836 struct label *intlabel; 837 struct mac mac; 838 int error; 839 840 error = copyin(uap->mac_p, &mac, sizeof(mac)); 841 if (error) 842 return (error); 843 844 error = mac_check_structmac_consistent(&mac); 845 if (error) 846 return (error); 847 848 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 849 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 850 if (error) { 851 free(elements, M_MACTEMP); 852 return (error); 853 } 854 855 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 856 mtx_lock(&Giant); /* VFS */ 857 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 858 td); 859 error = namei(&nd); 860 if (error) 861 goto out; 862 863 intlabel = mac_vnode_label_alloc(); 864 mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 865 error = mac_externalize_vnode_label(intlabel, elements, buffer, 866 mac.m_buflen); 867 868 NDFREE(&nd, 0); 869 mac_vnode_label_free(intlabel); 870 871 if (error == 0) 872 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 873 874out: 875 mtx_unlock(&Giant); /* VFS */ 876 877 free(buffer, M_MACTEMP); 878 free(elements, M_MACTEMP); 879 880 return (error); 881} 882 883/* 884 * MPSAFE 885 */ 886int 887__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 888{ 889 char *elements, *buffer; 890 struct nameidata nd; 891 struct label *intlabel; 892 struct mac mac; 893 int error; 894 895 error = copyin(uap->mac_p, &mac, sizeof(mac)); 896 if (error) 897 return (error); 898 899 error = mac_check_structmac_consistent(&mac); 900 if (error) 901 return (error); 902 903 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 904 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 905 if (error) { 906 free(elements, M_MACTEMP); 907 return (error); 908 } 909 910 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 911 mtx_lock(&Giant); /* VFS */ 912 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 913 td); 914 error = namei(&nd); 915 if (error) 916 goto out; 917 918 intlabel = mac_vnode_label_alloc(); 919 mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 920 error = mac_externalize_vnode_label(intlabel, elements, buffer, 921 mac.m_buflen); 922 NDFREE(&nd, 0); 923 mac_vnode_label_free(intlabel); 924 925 if (error == 0) 926 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 927 928out: 929 mtx_unlock(&Giant); /* VFS */ 930 931 free(buffer, M_MACTEMP); 932 free(elements, M_MACTEMP); 933 934 return (error); 935} 936 937/* 938 * MPSAFE 939 */ 940int 941__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 942{ 943 struct label *intlabel; 944 struct pipe *pipe; 945 struct socket *so; 946 struct file *fp; 947 struct mount *mp; 948 struct vnode *vp; 949 struct mac mac; 950 char *buffer; 951 int error; 952 953 error = copyin(uap->mac_p, &mac, sizeof(mac)); 954 if (error) 955 return (error); 956 957 error = mac_check_structmac_consistent(&mac); 958 if (error) 959 return (error); 960 961 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 962 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 963 if (error) { 964 free(buffer, M_MACTEMP); 965 return (error); 966 } 967 968 error = fget(td, uap->fd, &fp); 969 if (error) 970 goto out; 971 972 switch (fp->f_type) { 973 case DTYPE_FIFO: 974 case DTYPE_VNODE: 975 intlabel = mac_vnode_label_alloc(); 976 error = mac_internalize_vnode_label(intlabel, buffer); 977 if (error) { 978 mac_vnode_label_free(intlabel); 979 break; 980 } 981 vp = fp->f_vnode; 982 mtx_lock(&Giant); /* VFS */ 983 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 984 if (error != 0) { 985 mtx_unlock(&Giant); /* VFS */ 986 mac_vnode_label_free(intlabel); 987 break; 988 } 989 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 990 error = vn_setlabel(vp, intlabel, td->td_ucred); 991 VOP_UNLOCK(vp, 0, td); 992 vn_finished_write(mp); 993 mtx_unlock(&Giant); /* VFS */ 994 mac_vnode_label_free(intlabel); 995 break; 996 997 case DTYPE_PIPE: 998 intlabel = mac_pipe_label_alloc(); 999 error = mac_internalize_pipe_label(intlabel, buffer); 1000 if (error == 0) { 1001 pipe = fp->f_data; 1002 PIPE_LOCK(pipe); 1003 error = mac_pipe_label_set(td->td_ucred, 1004 pipe->pipe_pair, intlabel); 1005 PIPE_UNLOCK(pipe); 1006 } 1007 mac_pipe_label_free(intlabel); 1008 break; 1009 1010 case DTYPE_SOCKET: 1011 intlabel = mac_socket_label_alloc(M_WAITOK); 1012 error = mac_internalize_socket_label(intlabel, buffer); 1013 if (error == 0) { 1014 so = fp->f_data; 1015 mtx_lock(&Giant); /* Sockets */ 1016 /* XXX: Socket lock here. */ 1017 error = mac_socket_label_set(td->td_ucred, so, 1018 intlabel); 1019 /* XXX: Socket unlock here. */ 1020 mtx_unlock(&Giant); /* Sockets */ 1021 } 1022 mac_socket_label_free(intlabel); 1023 break; 1024 1025 default: 1026 error = EINVAL; 1027 } 1028 fdrop(fp, td); 1029out: 1030 free(buffer, M_MACTEMP); 1031 return (error); 1032} 1033 1034/* 1035 * MPSAFE 1036 */ 1037int 1038__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1039{ 1040 struct label *intlabel; 1041 struct nameidata nd; 1042 struct mount *mp; 1043 struct mac mac; 1044 char *buffer; 1045 int error; 1046 1047 error = copyin(uap->mac_p, &mac, sizeof(mac)); 1048 if (error) 1049 return (error); 1050 1051 error = mac_check_structmac_consistent(&mac); 1052 if (error) 1053 return (error); 1054 1055 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1056 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1057 if (error) { 1058 free(buffer, M_MACTEMP); 1059 return (error); 1060 } 1061 1062 intlabel = mac_vnode_label_alloc(); 1063 error = mac_internalize_vnode_label(intlabel, buffer); 1064 free(buffer, M_MACTEMP); 1065 if (error) 1066 goto out; 1067 1068 mtx_lock(&Giant); /* VFS */ 1069 1070 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 1071 td); 1072 error = namei(&nd); 1073 if (error == 0) { 1074 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1075 if (error == 0) 1076 error = vn_setlabel(nd.ni_vp, intlabel, 1077 td->td_ucred); 1078 vn_finished_write(mp); 1079 } 1080 1081 NDFREE(&nd, 0); 1082 mtx_unlock(&Giant); /* VFS */ 1083out: 1084 mac_vnode_label_free(intlabel); 1085 return (error); 1086} 1087 1088/* 1089 * MPSAFE 1090 */ 1091int 1092__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1093{ 1094 struct label *intlabel; 1095 struct nameidata nd; 1096 struct mount *mp; 1097 struct mac mac; 1098 char *buffer; 1099 int error; 1100 1101 error = copyin(uap->mac_p, &mac, sizeof(mac)); 1102 if (error) 1103 return (error); 1104 1105 error = mac_check_structmac_consistent(&mac); 1106 if (error) 1107 return (error); 1108 1109 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1110 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1111 if (error) { 1112 free(buffer, M_MACTEMP); 1113 return (error); 1114 } 1115 1116 intlabel = mac_vnode_label_alloc(); 1117 error = mac_internalize_vnode_label(intlabel, buffer); 1118 free(buffer, M_MACTEMP); 1119 if (error) 1120 goto out; 1121 1122 mtx_lock(&Giant); /* VFS */ 1123 1124 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 1125 td); 1126 error = namei(&nd); 1127 if (error == 0) { 1128 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1129 if (error == 0) 1130 error = vn_setlabel(nd.ni_vp, intlabel, 1131 td->td_ucred); 1132 vn_finished_write(mp); 1133 } 1134 1135 NDFREE(&nd, 0); 1136 mtx_unlock(&Giant); /* VFS */ 1137out: 1138 mac_vnode_label_free(intlabel); 1139 return (error); 1140} 1141 1142/* 1143 * MPSAFE 1144 */ 1145int 1146mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1147{ 1148 struct mac_policy_conf *mpc; 1149 char target[MAC_MAX_POLICY_NAME]; 1150 int entrycount, error; 1151 1152 error = copyinstr(uap->policy, target, sizeof(target), NULL); 1153 if (error) 1154 return (error); 1155 1156 error = ENOSYS; 1157 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1158 if (strcmp(mpc->mpc_name, target) == 0 && 1159 mpc->mpc_ops->mpo_syscall != NULL) { 1160 error = mpc->mpc_ops->mpo_syscall(td, 1161 uap->call, uap->arg); 1162 goto out; 1163 } 1164 } 1165 1166 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1167 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1168 if (strcmp(mpc->mpc_name, target) == 0 && 1169 mpc->mpc_ops->mpo_syscall != NULL) { 1170 error = mpc->mpc_ops->mpo_syscall(td, 1171 uap->call, uap->arg); 1172 break; 1173 } 1174 } 1175 mac_policy_list_unbusy(); 1176 } 1177out: 1178 return (error); 1179} 1180 1181SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1182SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1183 1184#else /* !MAC */ 1185 1186int 1187__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1188{ 1189 1190 return (ENOSYS); 1191} 1192 1193int 1194__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1195{ 1196 1197 return (ENOSYS); 1198} 1199 1200int 1201__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1202{ 1203 1204 return (ENOSYS); 1205} 1206 1207int 1208__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1209{ 1210 1211 return (ENOSYS); 1212} 1213 1214int 1215__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1216{ 1217 1218 return (ENOSYS); 1219} 1220 1221int 1222__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1223{ 1224 1225 return (ENOSYS); 1226} 1227 1228int 1229__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1230{ 1231 1232 return (ENOSYS); 1233} 1234 1235int 1236__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1237{ 1238 1239 return (ENOSYS); 1240} 1241 1242int 1243__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1244{ 1245 1246 return (ENOSYS); 1247} 1248 1249int 1250mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1251{ 1252 1253 return (ENOSYS); 1254} 1255 1256#endif /* !MAC */ 1257