1/* 2 * Copyright (c) 2007 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/*- 29 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 30 * Copyright (c) 2001 Ilmar S. Habibulin 31 * Copyright (c) 2001, 2002, 2003, 2004 Networks Associates Technology, Inc. 32 * Copyright (c) 2005 SPARTA, Inc. 33 * 34 * This software was developed by Robert Watson and Ilmar Habibulin for the 35 * TrustedBSD Project. 36 * 37 * This software was developed for the FreeBSD Project in part by Network 38 * Associates Laboratories, the Security Research Division of Network 39 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 40 * as part of the DARPA CHATS research program. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 * 63 */ 64 65#include <sys/param.h> 66#include <sys/systm.h> 67#include <sys/kernel.h> 68#include <sys/proc.h> 69#include <sys/kauth.h> 70 71#include <sys/file_internal.h> 72#include <sys/imgact.h> 73#include <sys/namei.h> 74#include <sys/mount_internal.h> 75#include <sys/pipe.h> 76#include <sys/posix_sem.h> 77#include <sys/posix_shm.h> 78#include <sys/uio_internal.h> 79#include <sys/vnode_internal.h> 80 81#include <miscfs/devfs/devfsdefs.h> 82#include <miscfs/devfs/fdesc.h> 83 84#include <security/mac_internal.h> 85 86/* convert {R,W,X}_OK values to V{READ,WRITE,EXEC} */ 87#define ACCESS_MODE_TO_VNODE_MASK(m) (m << 6) 88 89static struct label * 90mac_devfsdirent_label_alloc(void) 91{ 92 struct label *label; 93 94 label = mac_labelzone_alloc(MAC_WAITOK); 95 if (label == NULL) 96 return (NULL); 97 MAC_PERFORM(devfs_label_init, label); 98 return (label); 99} 100 101void 102mac_devfs_label_init(struct devnode *de) 103{ 104 105 de->dn_label = mac_devfsdirent_label_alloc(); 106} 107 108static struct label * 109mac_mount_label_alloc(void) 110{ 111 struct label *label; 112 113 label = mac_labelzone_alloc(MAC_WAITOK); 114 if (label == NULL) 115 return (NULL); 116 MAC_PERFORM(mount_label_init, label); 117 return (label); 118} 119 120void 121mac_mount_label_init(struct mount *mp) 122{ 123 124 mp->mnt_mntlabel = mac_mount_label_alloc(); 125} 126 127struct label * 128mac_vnode_label_alloc(void) 129{ 130 struct label *label; 131 132 label = mac_labelzone_alloc(MAC_WAITOK); 133 if (label == NULL) 134 return (NULL); 135 MAC_PERFORM(vnode_label_init, label); 136 return (label); 137} 138 139void 140mac_vnode_label_init(vnode_t vp) 141{ 142 vp->v_label = mac_vnode_label_alloc(); 143} 144 145int 146mac_vnode_label_init_needed(vnode_t vp) 147{ 148 return (mac_label_vnodes != 0 && vp->v_label == NULL); 149} 150 151/* 152 * vnode labels are allocated at the same time as vnodes, but vnodes are never 153 * freed. Instead, we want to remove any sensitive information before putting 154 * them on the free list for reuse. 155*/ 156void 157mac_vnode_label_recycle(vnode_t vp) 158{ 159 160 MAC_PERFORM(vnode_label_recycle, vp->v_label); 161} 162 163static void 164mac_devfs_label_free(struct label *label) 165{ 166 MAC_PERFORM(devfs_label_destroy, label); 167 mac_labelzone_free(label); 168} 169 170void 171mac_devfs_label_destroy(struct devnode *de) 172{ 173 if (de->dn_label != NULL) { 174 mac_devfs_label_free(de->dn_label); 175 de->dn_label = NULL; 176 } 177} 178 179static void 180mac_mount_label_free(struct label *label) 181{ 182 183 MAC_PERFORM(mount_label_destroy, label); 184 mac_labelzone_free(label); 185} 186 187void 188mac_mount_label_destroy(struct mount *mp) 189{ 190 if (mp->mnt_mntlabel != NULL) { 191 mac_mount_label_free(mp->mnt_mntlabel); 192 mp->mnt_mntlabel = NULL; 193 } 194} 195 196void 197mac_vnode_label_free(struct label *label) 198{ 199 MAC_PERFORM(vnode_label_destroy, label); 200 mac_labelzone_free(label); 201} 202 203#ifndef __APPLE__ 204void 205mac_vnode_label_destroy(struct vnode *vp) 206{ 207 if (vp->v_label != NULL) { 208 mac_vnode_label_free(vp->v_label); 209 vp->v_label = NULL; 210 } 211} 212#endif 213 214void 215mac_vnode_label_copy(struct label *src, struct label *dest) 216{ 217 if (src == NULL) { 218 MAC_PERFORM(vnode_label_init, dest); 219 } else { 220 MAC_PERFORM(vnode_label_copy, src, dest); 221 } 222} 223 224int 225mac_vnode_label_externalize_audit(struct vnode *vp, struct mac *mac) 226{ 227 int error; 228 229 /* It is assumed that any necessary vnode locking is done on entry */ 230 error = MAC_EXTERNALIZE_AUDIT(vnode, vp->v_label, 231 mac->m_string, mac->m_buflen); 232 233 return (error); 234} 235 236int 237mac_vnode_label_externalize(struct label *label, char *elements, 238 char *outbuf, size_t outbuflen, int flags __unused) 239{ 240 int error; 241 242 error = MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen); 243 244 return (error); 245} 246 247int 248mac_vnode_label_internalize(struct label *label, char *string) 249{ 250 int error; 251 252 error = MAC_INTERNALIZE(vnode, label, string); 253 254 return (error); 255} 256 257int 258mac_mount_label_internalize(struct label *label, char *string) 259{ 260 int error; 261 262 error = MAC_INTERNALIZE(mount, label, string); 263 264 return (error); 265} 266 267int 268mac_mount_label_externalize(struct label *label, char *elements, 269 char *outbuf, size_t outbuflen) 270{ 271 int error; 272 273 error = MAC_EXTERNALIZE(mount, label, elements, outbuf, outbuflen); 274 275 return (error); 276} 277 278void 279mac_devfs_label_copy(struct label *src, struct label *dest) 280{ 281 if (!mac_device_enforce) 282 return; 283 284 MAC_PERFORM(devfs_label_copy, src, dest); 285} 286 287void 288mac_devfs_label_update(struct mount *mp, struct devnode *de, 289 struct vnode *vp) 290{ 291 292 if (!mac_device_enforce) 293 return; 294 295 MAC_PERFORM(devfs_label_update, mp, de, de->dn_label, vp, 296 vp->v_label); 297} 298 299int 300mac_vnode_label_associate(struct mount *mp, struct vnode *vp, vfs_context_t ctx) 301{ 302 struct devnode *dnp; 303 struct fdescnode *fnp; 304 int error = 0; 305 306 if (!mac_vnode_enforce) 307 return (error); 308 309 /* XXX: should not inspect v_tag in kernel! */ 310 switch (vp->v_tag) { 311 case VT_DEVFS: 312 dnp = VTODN(vp); 313 mac_vnode_label_associate_devfs(mp, dnp, vp); 314 break; 315 case VT_FDESC: 316 fnp = VTOFDESC(vp); 317 error = mac_vnode_label_associate_fdesc(mp, fnp, vp, ctx); 318 break; 319 default: 320 error = mac_vnode_label_associate_extattr(mp, vp); 321 break; 322 } 323 324 return (error); 325} 326 327void 328mac_vnode_label_associate_devfs(struct mount *mp, struct devnode *de, 329 struct vnode *vp) 330{ 331 if (!mac_device_enforce) 332 return; 333 334 MAC_PERFORM(vnode_label_associate_devfs, 335 mp, mp ? mp->mnt_mntlabel : NULL, 336 de, de->dn_label, 337 vp, vp->v_label); 338} 339 340int 341mac_vnode_label_associate_extattr(struct mount *mp, struct vnode *vp) 342{ 343 int error; 344 345 MAC_CHECK(vnode_label_associate_extattr, mp, mp->mnt_mntlabel, vp, 346 vp->v_label); 347 348 return (error); 349} 350 351void 352mac_vnode_label_associate_singlelabel(struct mount *mp, struct vnode *vp) 353{ 354 355 if (!mac_vnode_enforce || !mac_label_vnodes) 356 return; 357 358 MAC_PERFORM(vnode_label_associate_singlelabel, mp, 359 mp ? mp->mnt_mntlabel : NULL, vp, vp->v_label); 360} 361 362int 363mac_vnode_notify_create(vfs_context_t ctx, struct mount *mp, 364 struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 365{ 366 kauth_cred_t cred; 367 int error; 368 369 if (!mac_vnode_enforce || 370 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 371 return (0); 372 373 cred = vfs_context_ucred(ctx); 374 MAC_CHECK(vnode_notify_create, cred, mp, mp->mnt_mntlabel, 375 dvp, dvp->v_label, vp, vp->v_label, cnp); 376 377 return (error); 378} 379 380void 381mac_vnode_notify_rename(vfs_context_t ctx, struct vnode *vp, 382 struct vnode *dvp, struct componentname *cnp) 383{ 384 kauth_cred_t cred; 385 386 if (!mac_vnode_enforce || 387 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 388 return; 389 390 cred = vfs_context_ucred(ctx); 391 MAC_PERFORM(vnode_notify_rename, cred, vp, vp->v_label, 392 dvp, dvp->v_label, cnp); 393} 394 395void 396mac_vnode_notify_open(vfs_context_t ctx, struct vnode *vp, int acc_flags) 397{ 398 kauth_cred_t cred; 399 400 if (!mac_vnode_enforce || 401 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 402 return; 403 404 cred = vfs_context_ucred(ctx); 405 MAC_PERFORM(vnode_notify_open, cred, vp, vp->v_label, acc_flags); 406} 407 408void 409mac_vnode_notify_link(vfs_context_t ctx, struct vnode *vp, 410 struct vnode *dvp, struct componentname *cnp) 411{ 412 kauth_cred_t cred; 413 414 if (!mac_vnode_enforce || 415 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 416 return; 417 418 cred = vfs_context_ucred(ctx); 419 MAC_PERFORM(vnode_notify_link, cred, dvp, dvp->v_label, vp, vp->v_label, cnp); 420} 421 422/* 423 * Extended attribute 'name' was updated via 424 * vn_setxattr() or vn_removexattr(). Allow the 425 * policy to update the vnode label. 426 */ 427void 428mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp, 429 const char *name) 430{ 431 int error = 0; 432 433 if (!mac_vnode_enforce || !mac_label_vnodes) 434 return; 435 436 MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp, 437 vp->v_label, name); 438 if (error == 0) 439 return; 440 441 vnode_lock(vp); 442 vnode_relabel(vp); 443 vnode_unlock(vp); 444 return; 445} 446 447static int 448mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp, 449 struct label *intlabel) 450{ 451 kauth_cred_t cred; 452 int error; 453 454 if (!mac_vnode_enforce || !mac_label_vnodes || 455 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 456 return 0; 457 458 cred = vfs_context_ucred(ctx); 459 MAC_CHECK(vnode_label_store, cred, vp, vp->v_label, intlabel); 460 461 return (error); 462} 463 464void 465mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp, off_t offset, 466 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl, u_int *csflags, 467 void *macextensions, int *disjoint, int *labelupdateerror) 468{ 469 kauth_cred_t cred; 470 *disjoint = 0; 471 int error; 472 posix_cred_t pcred = posix_cred_get(new); 473 474 if (!mac_proc_enforce && !mac_vnode_enforce) 475 return; 476 477 /* mark the new cred to indicate "matching" includes the label */ 478 pcred->cr_flags |= CRF_MAC_ENFORCE; 479 480 cred = vfs_context_ucred(ctx); 481 482 /* 483 * NB: Cannot use MAC_CHECK macro because we need a sequence point after 484 * calling exec_spawnattr_getmacpolicyinfo() and before passing the 485 * spawnattrlen as an argument to the hook. 486 */ 487 { 488 struct mac_policy_conf *mpc; 489 u_int i; 490 491 error = 0; 492 for (i = 0; i< mac_policy_list.staticmax; i++) { 493 mpc = mac_policy_list.entries[i].mpc; 494 if (mpc == NULL) 495 continue; 496 497 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve; 498 if (hook == NULL) 499 continue; 500 501 size_t spawnattrlen = 0; 502 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); 503 504 error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp, 505 vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint), 506 error); 507 } 508 if (mac_policy_list_conditional_busy() != 0) { 509 for (; i <= mac_policy_list.maxindex; i++) { 510 mpc = mac_policy_list.entries[i].mpc; 511 if (mpc == NULL) 512 continue; 513 514 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve; 515 if (hook == NULL) 516 continue; 517 518 size_t spawnattrlen = 0; 519 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); 520 521 error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp, 522 vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint), 523 error); 524 } 525 mac_policy_list_unbusy(); 526 } 527 } 528 *labelupdateerror = error; 529} 530 531int 532mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp, off_t offset, 533 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel, 534 struct proc *p, void *macextensions) 535{ 536 kauth_cred_t cred; 537 int result = 0; 538 539 if (!mac_proc_enforce && !mac_vnode_enforce) 540 return result; 541 542 cred = vfs_context_ucred(ctx); 543 544 /* 545 * NB: Cannot use MAC_BOOLEAN macro because we need a sequence point after 546 * calling exec_spawnattr_getmacpolicyinfo() and before passing the 547 * spawnattrlen as an argument to the hook. 548 */ 549 { 550 struct mac_policy_conf *mpc; 551 u_int i; 552 553 for (i = 0; i< mac_policy_list.staticmax; i++) { 554 mpc = mac_policy_list.entries[i].mpc; 555 if (mpc == NULL) 556 continue; 557 558 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve; 559 if (hook == NULL) 560 continue; 561 562 size_t spawnattrlen = 0; 563 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); 564 565 result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen); 566 } 567 if (mac_policy_list_conditional_busy() != 0) { 568 for (; i <= mac_policy_list.maxindex; i++) { 569 mpc = mac_policy_list.entries[i].mpc; 570 if (mpc == NULL) 571 continue; 572 573 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve; 574 if (hook == NULL) 575 continue; 576 577 size_t spawnattrlen = 0; 578 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); 579 580 result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen); 581 } 582 mac_policy_list_unbusy(); 583 } 584 } 585 586 return (result); 587} 588 589int 590mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp, 591 int acc_mode) 592{ 593 kauth_cred_t cred; 594 int error; 595 int mask; 596 597 if (!mac_vnode_enforce || 598 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 599 return 0; 600 601 cred = vfs_context_ucred(ctx); 602 /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */ 603 mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode); 604 MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask); 605 return (error); 606 } 607 608int 609mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp) 610{ 611 kauth_cred_t cred; 612 int error; 613 614 if (!mac_vnode_enforce || 615 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 616 return (0); 617 618 cred = vfs_context_ucred(ctx); 619 MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label); 620 return (error); 621} 622 623int 624mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp, 625 struct componentname *cnp) 626{ 627 kauth_cred_t cred; 628 int error; 629 630 if (!mac_vnode_enforce || 631 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 632 return (0); 633 634 cred = vfs_context_ucred(ctx); 635 MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp); 636 return (error); 637} 638 639int 640mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp, 641 struct componentname *cnp, struct vnode_attr *vap) 642{ 643 kauth_cred_t cred; 644 int error; 645 646 if (!mac_vnode_enforce || 647 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 648 return (0); 649 650 cred = vfs_context_ucred(ctx); 651 MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap); 652 return (error); 653} 654 655int 656mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp, 657 struct componentname *cnp) 658{ 659 kauth_cred_t cred; 660 int error; 661 662 if (!mac_vnode_enforce || 663 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 664 return (0); 665 666 cred = vfs_context_ucred(ctx); 667 MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp, 668 vp->v_label, cnp); 669 return (error); 670} 671#if 0 672int 673mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp, 674 acl_type_t type) 675{ 676 kauth_cred_t cred; 677 int error; 678 679 if (!mac_vnode_enforce || 680 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 681 return (0); 682 683 cred = vfs_context_ucred(ctx); 684 MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type); 685 return (error); 686} 687#endif 688 689int 690mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp, 691 const char *name) 692{ 693 kauth_cred_t cred; 694 int error; 695 696 if (!mac_vnode_enforce || 697 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 698 return (0); 699 700 cred = vfs_context_ucred(ctx); 701 MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name); 702 return (error); 703} 704int 705mac_vnode_check_exchangedata(vfs_context_t ctx, 706 struct vnode *v1, struct vnode *v2) 707{ 708 kauth_cred_t cred; 709 int error; 710 711 if (!mac_vnode_enforce || 712 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 713 return (0); 714 715 cred = vfs_context_ucred(ctx); 716 MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label, 717 v2, v2->v_label); 718 719 return (error); 720} 721 722#if 0 723int 724mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type) 725{ 726 kauth_cred_t cred; 727 int error; 728 729 if (!mac_vnode_enforce || 730 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 731 return (0); 732 733 cred = vfs_context_ucred(ctx); 734 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type); 735 return (error); 736} 737#endif 738 739int 740mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp, 741 struct attrlist *alist) 742{ 743 kauth_cred_t cred; 744 int error; 745 746 if (!mac_vnode_enforce || 747 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 748 return (0); 749 750 cred = vfs_context_ucred(ctx); 751 MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist); 752 753 /* Falsify results instead of returning error? */ 754 return (error); 755} 756 757int 758mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp, 759 struct image_params *imgp) 760{ 761 kauth_cred_t cred; 762 int error = 0; 763 764 if (!mac_vnode_enforce || !mac_proc_enforce) 765 return (0); 766 767 cred = vfs_context_ucred(ctx); 768 769 /* 770 * NB: Cannot use MAC_CHECK macro because we need a sequence point after 771 * calling exec_spawnattr_getmacpolicyinfo() and before passing the 772 * spawnattrlen as an argument to the hook. 773 */ 774 { 775 struct mac_policy_conf *mpc; 776 u_int i; 777 778 for (i = 0; i< mac_policy_list.staticmax; i++) { 779 mpc = mac_policy_list.entries[i].mpc; 780 if (mpc == NULL) 781 continue; 782 783 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec; 784 if (hook == NULL) 785 continue; 786 787 size_t spawnattrlen = 0; 788 void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen); 789 790 error = mac_error_select( 791 hook(cred, 792 vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp, 793 imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags, 794 spawnattr, spawnattrlen), error); 795 } 796 if (mac_policy_list_conditional_busy() != 0) { 797 for (; i <= mac_policy_list.maxindex; i++) { 798 mpc = mac_policy_list.entries[i].mpc; 799 if (mpc == NULL) 800 continue; 801 802 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec; 803 if (hook == NULL) 804 continue; 805 806 size_t spawnattrlen = 0; 807 void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen); 808 809 error = mac_error_select( 810 hook(cred, 811 vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp, 812 imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags, 813 spawnattr, spawnattrlen), error); 814 } 815 mac_policy_list_unbusy(); 816 } 817 } 818 819 return (error); 820} 821 822int 823mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp) 824{ 825 kauth_cred_t cred; 826 int error; 827 828 if (!mac_vnode_enforce || 829 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 830 return (0); 831 832 cred = vfs_context_ucred(ctx); 833 MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label); 834 return (error); 835} 836 837int 838mac_vnode_check_signature(struct vnode *vp, off_t macho_offset, 839 unsigned char *sha1, 840 const void *signature, size_t size, 841 int *is_platform_binary) 842{ 843 int error; 844 845 if (!mac_vnode_enforce || !mac_proc_enforce) 846 return (0); 847 848 MAC_CHECK(vnode_check_signature, vp, vp->v_label, macho_offset, sha1, 849 signature, size, is_platform_binary); 850 return (error); 851} 852 853#if 0 854int 855mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type) 856{ 857 kauth_cred_t cred; 858 int error; 859 860 if (!mac_vnode_enforce || 861 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 862 return (0); 863 864 cred = vfs_context_ucred(ctx); 865 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type); 866 return (error); 867} 868#endif 869 870int 871mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp, 872 const char *name, struct uio *uio) 873{ 874 kauth_cred_t cred; 875 int error; 876 877 if (!mac_vnode_enforce || 878 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 879 return (0); 880 881 cred = vfs_context_ucred(ctx); 882 MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label, 883 name, uio); 884 return (error); 885} 886 887int 888mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd) 889{ 890 kauth_cred_t cred; 891 int error; 892 893 if (!mac_vnode_enforce || 894 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 895 return (0); 896 897 cred = vfs_context_ucred(ctx); 898 MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd); 899 return (error); 900} 901 902int 903mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred, 904 struct knote *kn, struct vnode *vp) 905{ 906 kauth_cred_t cred; 907 int error; 908 909 if (!mac_vnode_enforce || 910 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 911 return (0); 912 913 cred = vfs_context_ucred(ctx); 914 MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp, 915 vp->v_label); 916 917 return (error); 918} 919 920int 921mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp, 922 struct vnode *vp, struct componentname *cnp) 923{ 924 kauth_cred_t cred; 925 int error; 926 927 if (!mac_vnode_enforce || 928 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 929 return (0); 930 931 cred = vfs_context_ucred(ctx); 932 MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp, 933 vp->v_label, cnp); 934 return (error); 935} 936 937int 938mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp) 939{ 940 kauth_cred_t cred; 941 int error; 942 943 if (!mac_vnode_enforce || 944 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 945 return (0); 946 947 cred = vfs_context_ucred(ctx); 948 MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label); 949 return (error); 950} 951 952int 953mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp, 954 struct componentname *cnp) 955{ 956 kauth_cred_t cred; 957 int error; 958 959 if (!mac_vnode_enforce || 960 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 961 return (0); 962 963 cred = vfs_context_ucred(ctx); 964 MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp); 965 return (error); 966} 967 968int 969mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode) 970{ 971 kauth_cred_t cred; 972 int error; 973 974 if (!mac_vnode_enforce || 975 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 976 return (0); 977 978 cred = vfs_context_ucred(ctx); 979 MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode); 980 return (error); 981} 982 983int 984mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred, 985 struct vnode *vp) 986{ 987 kauth_cred_t cred; 988 int error; 989 990 if (!mac_vnode_enforce || 991 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 992 return (0); 993 994 cred = vfs_context_ucred(ctx); 995 MAC_CHECK(vnode_check_read, cred, file_cred, vp, 996 vp->v_label); 997 998 return (error); 999} 1000 1001int 1002mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp) 1003{ 1004 kauth_cred_t cred; 1005 int error; 1006 1007 if (!mac_vnode_enforce || 1008 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1009 return (0); 1010 1011 cred = vfs_context_ucred(ctx); 1012 MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label); 1013 return (error); 1014} 1015 1016int 1017mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp) 1018{ 1019 kauth_cred_t cred; 1020 int error; 1021 1022 if (!mac_vnode_enforce || 1023 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1024 return (0); 1025 1026 cred = vfs_context_ucred(ctx); 1027 MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label); 1028 return (error); 1029} 1030 1031int 1032mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp, 1033 struct label *newlabel) 1034{ 1035 kauth_cred_t cred; 1036 int error; 1037 1038 if (!mac_vnode_enforce || 1039 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1040 return (0); 1041 1042 cred = vfs_context_ucred(ctx); 1043 MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel); 1044 1045 return (error); 1046} 1047 1048int 1049mac_vnode_check_rename(vfs_context_t ctx, struct vnode *dvp, 1050 struct vnode *vp, struct componentname *cnp, struct vnode *tdvp, 1051 struct vnode *tvp, struct componentname *tcnp) 1052{ 1053 kauth_cred_t cred; 1054 int error; 1055 1056 if (!mac_vnode_enforce || 1057 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1058 return (0); 1059 1060 cred = vfs_context_ucred(ctx); 1061 1062 MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp, 1063 vp->v_label, cnp); 1064 if (error) 1065 return (error); 1066 1067 MAC_CHECK(vnode_check_rename_to, cred, tdvp, tdvp->v_label, tvp, 1068 tvp != NULL ? tvp->v_label : NULL, dvp == tdvp, tcnp); 1069 if (error) 1070 return (error); 1071 1072 MAC_CHECK(vnode_check_rename, cred, dvp, dvp->v_label, vp, 1073 vp->v_label, cnp, tdvp, tdvp->v_label, tvp, 1074 tvp != NULL ? tvp->v_label : NULL, tcnp); 1075 return (error); 1076} 1077 1078int 1079mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp) 1080{ 1081 kauth_cred_t cred; 1082 int error; 1083 1084 if (!mac_vnode_enforce || 1085 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1086 return (0); 1087 1088 cred = vfs_context_ucred(ctx); 1089 MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label); 1090 return (error); 1091} 1092 1093int 1094mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist) 1095{ 1096 kauth_cred_t cred; 1097 int error; 1098 1099 if (!mac_vnode_enforce || 1100 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1101 return (0); 1102 1103 cred = vfs_context_ucred(ctx); 1104 MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist); 1105 return (error); 1106} 1107 1108int 1109mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which) 1110{ 1111 kauth_cred_t cred; 1112 int error; 1113 1114 if (!mac_vnode_enforce || 1115 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1116 return (0); 1117 1118 cred = vfs_context_ucred(ctx); 1119 MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which); 1120 return (error); 1121} 1122 1123#if 0 1124int 1125mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type, 1126 struct acl *acl) 1127{ 1128 kauth_cred_t cred; 1129 int error; 1130 1131 if (!mac_vnode_enforce || 1132 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1133 return (0); 1134 1135 cred = vfs_context_ucred(ctx); 1136 MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl); 1137 return (error); 1138} 1139#endif 1140 1141int 1142mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp, 1143 struct attrlist *alist) 1144{ 1145 kauth_cred_t cred; 1146 int error; 1147 1148 if (!mac_vnode_enforce || 1149 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1150 return (0); 1151 1152 cred = vfs_context_ucred(ctx); 1153 MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist); 1154 return (error); 1155} 1156 1157int 1158mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp, 1159 const char *name, struct uio *uio) 1160{ 1161 kauth_cred_t cred; 1162 int error; 1163 1164 if (!mac_vnode_enforce || 1165 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1166 return (0); 1167 1168 cred = vfs_context_ucred(ctx); 1169 MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label, 1170 name, uio); 1171 return (error); 1172} 1173 1174int 1175mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags) 1176{ 1177 kauth_cred_t cred; 1178 int error; 1179 1180 if (!mac_vnode_enforce || 1181 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1182 return (0); 1183 1184 cred = vfs_context_ucred(ctx); 1185 MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags); 1186 return (error); 1187} 1188 1189int 1190mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode) 1191{ 1192 kauth_cred_t cred; 1193 int error; 1194 1195 if (!mac_vnode_enforce || 1196 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1197 return (0); 1198 1199 cred = vfs_context_ucred(ctx); 1200 MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode); 1201 return (error); 1202} 1203 1204int 1205mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid, 1206 gid_t gid) 1207{ 1208 kauth_cred_t cred; 1209 int error; 1210 1211 if (!mac_vnode_enforce || 1212 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1213 return (0); 1214 1215 cred = vfs_context_ucred(ctx); 1216 MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid); 1217 return (error); 1218} 1219 1220int 1221mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp, 1222 struct timespec atime, struct timespec mtime) 1223{ 1224 kauth_cred_t cred; 1225 int error; 1226 1227 if (!mac_vnode_enforce || 1228 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1229 return (0); 1230 1231 cred = vfs_context_ucred(ctx); 1232 MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime, 1233 mtime); 1234 return (error); 1235} 1236 1237int 1238mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred, 1239 struct vnode *vp) 1240{ 1241 kauth_cred_t cred; 1242 int error; 1243 1244 if (!mac_vnode_enforce || 1245 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1246 return (0); 1247 1248 cred = vfs_context_ucred(ctx); 1249 MAC_CHECK(vnode_check_stat, cred, file_cred, vp, 1250 vp->v_label); 1251 return (error); 1252} 1253 1254int 1255mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred, 1256 struct vnode *vp) 1257{ 1258 kauth_cred_t cred; 1259 int error; 1260 1261 if (!mac_vnode_enforce || 1262 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1263 return (0); 1264 1265 cred = vfs_context_ucred(ctx); 1266 MAC_CHECK(vnode_check_truncate, cred, file_cred, vp, 1267 vp->v_label); 1268 1269 return (error); 1270} 1271 1272int 1273mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred, 1274 struct vnode *vp) 1275{ 1276 kauth_cred_t cred; 1277 int error; 1278 1279 if (!mac_vnode_enforce || 1280 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1281 return (0); 1282 1283 cred = vfs_context_ucred(ctx); 1284 MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label); 1285 1286 return (error); 1287} 1288 1289int 1290mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp, 1291 struct componentname *cnp, struct vnode_attr *vap) 1292{ 1293 kauth_cred_t cred; 1294 int error; 1295 1296 if (!mac_vnode_enforce || 1297 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1298 return (0); 1299 1300 cred = vfs_context_ucred(ctx); 1301 MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap); 1302 return (error); 1303} 1304 1305int 1306mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp) 1307{ 1308 kauth_cred_t cred; 1309 int error; 1310 1311 if (!mac_vnode_enforce || 1312 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1313 return (0); 1314 1315 cred = vfs_context_ucred(ctx); 1316 MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label); 1317 return (error); 1318} 1319 1320void 1321mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel) 1322{ 1323 kauth_cred_t cred = vfs_context_ucred(ctx); 1324 struct label *tmpl = NULL; 1325 1326 if (vp->v_label == NULL) 1327 tmpl = mac_vnode_label_alloc(); 1328 1329 vnode_lock(vp); 1330 1331 /* recheck after lock */ 1332 if (vp->v_label == NULL) { 1333 vp->v_label = tmpl; 1334 tmpl = NULL; 1335 } 1336 1337 MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel); 1338 vnode_unlock(vp); 1339 1340 if (tmpl != NULL) 1341 mac_vnode_label_free(tmpl); 1342} 1343 1344int 1345mac_vnode_find_sigs(struct proc *p, struct vnode *vp, off_t offset) 1346{ 1347 int error; 1348 1349 if (!mac_vnode_enforce || !mac_proc_enforce) 1350 return (0); 1351 1352 MAC_CHECK(vnode_find_sigs, p, vp, offset, vp->v_label); 1353 1354 return (error); 1355} 1356 1357void 1358mac_mount_label_associate(vfs_context_t ctx, struct mount *mp) 1359{ 1360 kauth_cred_t cred = vfs_context_ucred(ctx); 1361 1362 /* XXX: eventually this logic may be handled by the policy? */ 1363 1364 /* We desire MULTILABEL for the root filesystem. */ 1365 if ((mp->mnt_flag & MNT_ROOTFS) && 1366 (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0)) 1367 mp->mnt_flag |= MNT_MULTILABEL; 1368 1369 /* MULTILABEL on DEVFS. */ 1370 if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0) 1371 mp->mnt_flag |= MNT_MULTILABEL; 1372 1373 /* MULTILABEL on FDESC pseudo-filesystem. */ 1374 if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0) 1375 mp->mnt_flag |= MNT_MULTILABEL; 1376 1377 /* MULTILABEL on all NFS filesystems. */ 1378 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0) 1379 mp->mnt_flag |= MNT_MULTILABEL; 1380 1381 /* MULTILABEL on all AFP filesystems. */ 1382 if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0) 1383 mp->mnt_flag |= MNT_MULTILABEL; 1384 1385 if (mp->mnt_vtable != NULL) { 1386 /* Any filesystem that supports native XATTRs. */ 1387 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR)) 1388 mp->mnt_flag |= MNT_MULTILABEL; 1389 1390 /* Filesystem does not support multilabel. */ 1391 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) && 1392 (mp->mnt_flag & MNT_MULTILABEL)) 1393 mp->mnt_flag &= ~MNT_MULTILABEL; 1394 } 1395 1396 MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel); 1397#if DEBUG 1398 printf("MAC Framework enabling %s support: %s -> %s (%s)\n", 1399 mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel", 1400 mp->mnt_vfsstat.f_mntfromname, 1401 mp->mnt_vfsstat.f_mntonname, 1402 mp->mnt_vfsstat.f_fstypename); 1403#endif 1404} 1405 1406int 1407mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp, 1408 struct componentname *cnp, const char *vfc_name) 1409{ 1410 kauth_cred_t cred; 1411 int error; 1412 1413 if (!mac_vnode_enforce || 1414 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1415 return (0); 1416 1417 cred = vfs_context_ucred(ctx); 1418 MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name); 1419 1420 return (error); 1421} 1422 1423int 1424mac_mount_check_remount(vfs_context_t ctx, struct mount *mp) 1425{ 1426 kauth_cred_t cred; 1427 int error; 1428 1429 if (!mac_vnode_enforce || 1430 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1431 return (0); 1432 1433 cred = vfs_context_ucred(ctx); 1434 MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel); 1435 1436 return (error); 1437} 1438 1439int 1440mac_mount_check_umount(vfs_context_t ctx, struct mount *mp) 1441{ 1442 kauth_cred_t cred; 1443 int error; 1444 1445 if (!mac_vnode_enforce || 1446 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1447 return (0); 1448 1449 cred = vfs_context_ucred(ctx); 1450 MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel); 1451 1452 return (error); 1453} 1454 1455int 1456mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp, 1457 struct vfs_attr *vfa) 1458{ 1459 kauth_cred_t cred; 1460 int error; 1461 1462 if (!mac_vnode_enforce || 1463 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1464 return (0); 1465 1466 cred = vfs_context_ucred(ctx); 1467 MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa); 1468 return (error); 1469} 1470 1471int 1472mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp, 1473 struct vfs_attr *vfa) 1474{ 1475 kauth_cred_t cred; 1476 int error; 1477 1478 if (!mac_vnode_enforce || 1479 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1480 return (0); 1481 1482 cred = vfs_context_ucred(ctx); 1483 MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa); 1484 return (error); 1485} 1486 1487int 1488mac_mount_check_stat(vfs_context_t ctx, struct mount *mount) 1489{ 1490 kauth_cred_t cred; 1491 int error; 1492 1493 if (!mac_vnode_enforce || 1494 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1495 return (0); 1496 1497 cred = vfs_context_ucred(ctx); 1498 MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel); 1499 1500 return (error); 1501} 1502 1503int 1504mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount) 1505{ 1506 kauth_cred_t cred; 1507 int error; 1508 1509 if (!mac_vnode_enforce || 1510 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1511 return (0); 1512 1513 cred = vfs_context_ucred(ctx); 1514 MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel); 1515 1516 return (error); 1517} 1518 1519int 1520mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd) 1521{ 1522 kauth_cred_t cred; 1523 int error; 1524 1525 if (!mac_vnode_enforce || 1526 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1527 return (0); 1528 1529 cred = vfs_context_ucred(ctx); 1530 MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd); 1531 1532 return (error); 1533} 1534 1535void 1536mac_devfs_label_associate_device(dev_t dev, struct devnode *de, 1537 const char *fullpath) 1538{ 1539 if (!mac_device_enforce) 1540 return; 1541 1542 MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label, 1543 fullpath); 1544} 1545 1546void 1547mac_devfs_label_associate_directory(const char *dirname, int dirnamelen, 1548 struct devnode *de, const char *fullpath) 1549{ 1550 if (!mac_device_enforce) 1551 return; 1552 1553 MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de, 1554 de->dn_label, fullpath); 1555} 1556 1557int 1558vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context) 1559{ 1560 int error; 1561 1562 if (!mac_vnode_enforce || !mac_label_vnodes) 1563 return (0); 1564 1565 if (vp->v_mount == NULL) { 1566 printf("vn_setlabel: null v_mount\n"); 1567 if (vp->v_type != VNON) 1568 printf("vn_setlabel: null v_mount with non-VNON\n"); 1569 return (EBADF); 1570 } 1571 1572 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 1573 return (ENOTSUP); 1574 1575 /* 1576 * Multi-phase commit. First check the policies to confirm the 1577 * change is OK. Then commit via the filesystem. Finally, 1578 * update the actual vnode label. Question: maybe the filesystem 1579 * should update the vnode at the end as part of VNOP_SETLABEL()? 1580 */ 1581 error = mac_vnode_check_label_update(context, vp, intlabel); 1582 if (error) 1583 return (error); 1584 1585 error = VNOP_SETLABEL(vp, intlabel, context); 1586 if (error == ENOTSUP) { 1587 error = mac_vnode_label_store(context, vp, 1588 intlabel); 1589 if (error) { 1590 printf("%s: mac_vnode_label_store failed %d\n", 1591 __func__, error); 1592 return (error); 1593 } 1594 mac_vnode_label_update(context, vp, intlabel); 1595 } else 1596 if (error) { 1597 printf("vn_setlabel: vop setlabel failed %d\n", error); 1598 return (error); 1599 } 1600 1601 return (0); 1602} 1603 1604int 1605mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp, 1606 struct vnode *vp, vfs_context_t ctx) 1607{ 1608 struct fileproc *fp; 1609#if CONFIG_MACF_SOCKET_SUBSET 1610 struct socket *so; 1611#endif 1612 struct pipe *cpipe; 1613 struct vnode *fvp; 1614 struct proc *p; 1615 int error; 1616 1617 error = 0; 1618 1619 /* 1620 * If no backing file, let the policy choose which label to use. 1621 */ 1622 if (fnp->fd_fd == -1) { 1623 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx), 1624 mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label); 1625 return (0); 1626 } 1627 1628 p = vfs_context_proc(ctx); 1629 error = fp_lookup(p, fnp->fd_fd, &fp, 0); 1630 if (error) 1631 return (error); 1632 1633 if (fp->f_fglob == NULL) { 1634 error = EBADF; 1635 goto out; 1636 } 1637 1638 switch (FILEGLOB_DTYPE(fp->f_fglob)) { 1639 case DTYPE_VNODE: 1640 fvp = (struct vnode *)fp->f_fglob->fg_data; 1641 if ((error = vnode_getwithref(fvp))) 1642 goto out; 1643 MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label); 1644 (void)vnode_put(fvp); 1645 break; 1646#if CONFIG_MACF_SOCKET_SUBSET 1647 case DTYPE_SOCKET: 1648 so = (struct socket *)fp->f_fglob->fg_data; 1649 socket_lock(so, 1); 1650 MAC_PERFORM(vnode_label_associate_socket, 1651 vfs_context_ucred(ctx), (socket_t)so, so->so_label, 1652 vp, vp->v_label); 1653 socket_unlock(so, 1); 1654 break; 1655#endif 1656 case DTYPE_PSXSHM: 1657 pshm_label_associate(fp, vp, ctx); 1658 break; 1659 case DTYPE_PSXSEM: 1660 psem_label_associate(fp, vp, ctx); 1661 break; 1662 case DTYPE_PIPE: 1663 cpipe = (struct pipe *)fp->f_fglob->fg_data; 1664 /* kern/sys_pipe.c:pipe_select() suggests this test. */ 1665 if (cpipe == (struct pipe *)-1) { 1666 error = EINVAL; 1667 goto out; 1668 } 1669 PIPE_LOCK(cpipe); 1670 MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx), 1671 cpipe, cpipe->pipe_label, vp, vp->v_label); 1672 PIPE_UNLOCK(cpipe); 1673 break; 1674 case DTYPE_KQUEUE: 1675 case DTYPE_FSEVENTS: 1676 default: 1677 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx), 1678 mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label, 1679 vp, vp->v_label); 1680 break; 1681 } 1682out: 1683 fp_drop(p, fnp->fd_fd, fp, 0); 1684 return (error); 1685} 1686