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 464int 465mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp, 466 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl, 467 void *macextensions) 468{ 469 kauth_cred_t cred; 470 int disjoint = 0; 471 posix_cred_t pcred = posix_cred_get(new); 472 473 if (!mac_proc_enforce && !mac_vnode_enforce) 474 return disjoint; 475 476 /* mark the new cred to indicate "matching" includes the label */ 477 pcred->cr_flags |= CRF_MAC_ENFORCE; 478 479 cred = vfs_context_ucred(ctx); 480 481 /* 482 * NB: Cannot use MAC_PERFORM macro because we need a sequence point after 483 * calling exec_spawnattr_getmacpolicyinfo() and before passing the 484 * spawnattrlen as an argument to the hook. 485 */ 486 { 487 struct mac_policy_conf *mpc; 488 u_int i; 489 490 for (i = 0; i< mac_policy_list.staticmax; i++) { 491 mpc = mac_policy_list.entries[i].mpc; 492 if (mpc == NULL) 493 continue; 494 495 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve; 496 if (hook == NULL) 497 continue; 498 499 size_t spawnattrlen = 0; 500 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); 501 502 hook(cred, new, vfs_context_proc(ctx), vp, scriptvp, vp->v_label, 503 scriptvnodelabel, execl, spawnattr, spawnattrlen, &disjoint); 504 } 505 if (mac_policy_list_conditional_busy() != 0) { 506 for (; i <= mac_policy_list.maxindex; i++) { 507 mpc = mac_policy_list.entries[i].mpc; 508 if (mpc == NULL) 509 continue; 510 511 mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve; 512 if (hook == NULL) 513 continue; 514 515 size_t spawnattrlen = 0; 516 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); 517 518 hook(cred, new, vfs_context_proc(ctx), vp, scriptvp, vp->v_label, 519 scriptvnodelabel, execl, spawnattr, spawnattrlen, &disjoint); 520 } 521 mac_policy_list_unbusy(); 522 } 523 } 524 525 return (disjoint); 526} 527 528int 529mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp, 530 struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel, 531 struct proc *p, void *macextensions) 532{ 533 kauth_cred_t cred; 534 int result = 0; 535 536 if (!mac_proc_enforce && !mac_vnode_enforce) 537 return result; 538 539 cred = vfs_context_ucred(ctx); 540 541 /* 542 * NB: Cannot use MAC_BOOLEAN macro because we need a sequence point after 543 * calling exec_spawnattr_getmacpolicyinfo() and before passing the 544 * spawnattrlen as an argument to the hook. 545 */ 546 { 547 struct mac_policy_conf *mpc; 548 u_int i; 549 550 for (i = 0; i< mac_policy_list.staticmax; i++) { 551 mpc = mac_policy_list.entries[i].mpc; 552 if (mpc == NULL) 553 continue; 554 555 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve; 556 if (hook == NULL) 557 continue; 558 559 size_t spawnattrlen = 0; 560 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); 561 562 result = result || hook(cred, vp, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen); 563 } 564 if (mac_policy_list_conditional_busy() != 0) { 565 for (; i <= mac_policy_list.maxindex; i++) { 566 mpc = mac_policy_list.entries[i].mpc; 567 if (mpc == NULL) 568 continue; 569 570 mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve; 571 if (hook == NULL) 572 continue; 573 574 size_t spawnattrlen = 0; 575 void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); 576 577 result = result || hook(cred, vp, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen); 578 } 579 mac_policy_list_unbusy(); 580 } 581 } 582 583 return (result); 584} 585 586int 587mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp, 588 int acc_mode) 589{ 590 kauth_cred_t cred; 591 int error; 592 int mask; 593 594 if (!mac_vnode_enforce || 595 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 596 return 0; 597 598 cred = vfs_context_ucred(ctx); 599 /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */ 600 mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode); 601 MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask); 602 return (error); 603 } 604 605int 606mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp) 607{ 608 kauth_cred_t cred; 609 int error; 610 611 if (!mac_vnode_enforce || 612 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 613 return (0); 614 615 cred = vfs_context_ucred(ctx); 616 MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label); 617 return (error); 618} 619 620int 621mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp, 622 struct componentname *cnp) 623{ 624 kauth_cred_t cred; 625 int error; 626 627 if (!mac_vnode_enforce || 628 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 629 return (0); 630 631 cred = vfs_context_ucred(ctx); 632 MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp); 633 return (error); 634} 635 636int 637mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp, 638 struct componentname *cnp, struct vnode_attr *vap) 639{ 640 kauth_cred_t cred; 641 int error; 642 643 if (!mac_vnode_enforce || 644 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 645 return (0); 646 647 cred = vfs_context_ucred(ctx); 648 MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap); 649 return (error); 650} 651 652int 653mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp, 654 struct componentname *cnp) 655{ 656 kauth_cred_t cred; 657 int error; 658 659 if (!mac_vnode_enforce || 660 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 661 return (0); 662 663 cred = vfs_context_ucred(ctx); 664 MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp, 665 vp->v_label, cnp); 666 return (error); 667} 668#if 0 669int 670mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp, 671 acl_type_t type) 672{ 673 kauth_cred_t cred; 674 int error; 675 676 if (!mac_vnode_enforce || 677 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 678 return (0); 679 680 cred = vfs_context_ucred(ctx); 681 MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type); 682 return (error); 683} 684#endif 685 686int 687mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp, 688 const char *name) 689{ 690 kauth_cred_t cred; 691 int error; 692 693 if (!mac_vnode_enforce || 694 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 695 return (0); 696 697 cred = vfs_context_ucred(ctx); 698 MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name); 699 return (error); 700} 701int 702mac_vnode_check_exchangedata(vfs_context_t ctx, 703 struct vnode *v1, struct vnode *v2) 704{ 705 kauth_cred_t cred; 706 int error; 707 708 if (!mac_vnode_enforce || 709 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 710 return (0); 711 712 cred = vfs_context_ucred(ctx); 713 MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label, 714 v2, v2->v_label); 715 716 return (error); 717} 718 719#if 0 720int 721mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type) 722{ 723 kauth_cred_t cred; 724 int error; 725 726 if (!mac_vnode_enforce || 727 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 728 return (0); 729 730 cred = vfs_context_ucred(ctx); 731 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type); 732 return (error); 733} 734#endif 735 736int 737mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp, 738 struct attrlist *alist) 739{ 740 kauth_cred_t cred; 741 int error; 742 743 if (!mac_vnode_enforce || 744 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 745 return (0); 746 747 cred = vfs_context_ucred(ctx); 748 MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist); 749 750 /* Falsify results instead of returning error? */ 751 return (error); 752} 753 754int 755mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp, 756 struct image_params *imgp) 757{ 758 kauth_cred_t cred; 759 int error = 0; 760 761 if (!mac_vnode_enforce || !mac_proc_enforce) 762 return (0); 763 764 cred = vfs_context_ucred(ctx); 765 766 /* 767 * NB: Cannot use MAC_CHECK macro because we need a sequence point after 768 * calling exec_spawnattr_getmacpolicyinfo() and before passing the 769 * spawnattrlen as an argument to the hook. 770 */ 771 { 772 struct mac_policy_conf *mpc; 773 u_int i; 774 775 for (i = 0; i< mac_policy_list.staticmax; i++) { 776 mpc = mac_policy_list.entries[i].mpc; 777 if (mpc == NULL) 778 continue; 779 780 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec; 781 if (hook == NULL) 782 continue; 783 784 size_t spawnattrlen = 0; 785 void *spawnattr = (imgp != NULL) ? exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen) : NULL; 786 787 error = mac_error_select( 788 hook(cred, vp, vp->v_label, 789 (imgp != NULL) ? imgp->ip_execlabelp : NULL, 790 (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL, 791 (imgp != NULL) ? &imgp->ip_csflags : NULL, 792 spawnattr, spawnattrlen), error); 793 } 794 if (mac_policy_list_conditional_busy() != 0) { 795 for (; i <= mac_policy_list.maxindex; i++) { 796 mpc = mac_policy_list.entries[i].mpc; 797 if (mpc == NULL) 798 continue; 799 800 mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec; 801 if (hook == NULL) 802 continue; 803 804 size_t spawnattrlen = 0; 805 void *spawnattr = (imgp != NULL) ? exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen) : NULL; 806 807 error = mac_error_select( 808 hook(cred, vp, vp->v_label, 809 (imgp != NULL) ? imgp->ip_execlabelp : NULL, 810 (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL, 811 (imgp != NULL) ? &imgp->ip_csflags : NULL, 812 spawnattr, spawnattrlen), error); 813 } 814 mac_policy_list_unbusy(); 815 } 816 } 817 818 return (error); 819} 820 821int 822mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp) 823{ 824 kauth_cred_t cred; 825 int error; 826 827 if (!mac_vnode_enforce || 828 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 829 return (0); 830 831 cred = vfs_context_ucred(ctx); 832 MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label); 833 return (error); 834} 835 836int 837mac_vnode_check_signature(struct vnode *vp, off_t macho_offset, 838 unsigned char *sha1, 839 void * signature, size_t size) 840{ 841 int error; 842 843 if (!mac_vnode_enforce || !mac_proc_enforce) 844 return (0); 845 846 MAC_CHECK(vnode_check_signature, vp, vp->v_label, macho_offset, sha1, signature, size); 847 return (error); 848} 849 850#if 0 851int 852mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type) 853{ 854 kauth_cred_t cred; 855 int error; 856 857 if (!mac_vnode_enforce || 858 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 859 return (0); 860 861 cred = vfs_context_ucred(ctx); 862 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type); 863 return (error); 864} 865#endif 866 867int 868mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp, 869 const char *name, struct uio *uio) 870{ 871 kauth_cred_t cred; 872 int error; 873 874 if (!mac_vnode_enforce || 875 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 876 return (0); 877 878 cred = vfs_context_ucred(ctx); 879 MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label, 880 name, uio); 881 return (error); 882} 883 884int 885mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd) 886{ 887 kauth_cred_t cred; 888 int error; 889 890 if (!mac_vnode_enforce || 891 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 892 return (0); 893 894 cred = vfs_context_ucred(ctx); 895 MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd); 896 return (error); 897} 898 899int 900mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred, 901 struct knote *kn, struct vnode *vp) 902{ 903 kauth_cred_t cred; 904 int error; 905 906 if (!mac_vnode_enforce || 907 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 908 return (0); 909 910 cred = vfs_context_ucred(ctx); 911 MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp, 912 vp->v_label); 913 914 return (error); 915} 916 917int 918mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp, 919 struct vnode *vp, struct componentname *cnp) 920{ 921 kauth_cred_t cred; 922 int error; 923 924 if (!mac_vnode_enforce || 925 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 926 return (0); 927 928 cred = vfs_context_ucred(ctx); 929 MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp, 930 vp->v_label, cnp); 931 return (error); 932} 933 934int 935mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp) 936{ 937 kauth_cred_t cred; 938 int error; 939 940 if (!mac_vnode_enforce || 941 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 942 return (0); 943 944 cred = vfs_context_ucred(ctx); 945 MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label); 946 return (error); 947} 948 949int 950mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp, 951 struct componentname *cnp) 952{ 953 kauth_cred_t cred; 954 int error; 955 956 if (!mac_vnode_enforce || 957 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 958 return (0); 959 960 cred = vfs_context_ucred(ctx); 961 MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp); 962 return (error); 963} 964 965int 966mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode) 967{ 968 kauth_cred_t cred; 969 int error; 970 971 if (!mac_vnode_enforce || 972 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 973 return (0); 974 975 cred = vfs_context_ucred(ctx); 976 MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode); 977 return (error); 978} 979 980int 981mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred, 982 struct vnode *vp) 983{ 984 kauth_cred_t cred; 985 int error; 986 987 if (!mac_vnode_enforce || 988 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 989 return (0); 990 991 cred = vfs_context_ucred(ctx); 992 MAC_CHECK(vnode_check_read, cred, file_cred, vp, 993 vp->v_label); 994 995 return (error); 996} 997 998int 999mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp) 1000{ 1001 kauth_cred_t cred; 1002 int error; 1003 1004 if (!mac_vnode_enforce || 1005 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1006 return (0); 1007 1008 cred = vfs_context_ucred(ctx); 1009 MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label); 1010 return (error); 1011} 1012 1013int 1014mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp) 1015{ 1016 kauth_cred_t cred; 1017 int error; 1018 1019 if (!mac_vnode_enforce || 1020 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1021 return (0); 1022 1023 cred = vfs_context_ucred(ctx); 1024 MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label); 1025 return (error); 1026} 1027 1028int 1029mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp, 1030 struct label *newlabel) 1031{ 1032 kauth_cred_t cred; 1033 int error; 1034 1035 if (!mac_vnode_enforce || 1036 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1037 return (0); 1038 1039 cred = vfs_context_ucred(ctx); 1040 MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel); 1041 1042 return (error); 1043} 1044 1045int 1046mac_vnode_check_rename_from(vfs_context_t ctx, struct vnode *dvp, 1047 struct vnode *vp, struct componentname *cnp) 1048{ 1049 kauth_cred_t cred; 1050 int error; 1051 1052 if (!mac_vnode_enforce || 1053 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1054 return (0); 1055 1056 cred = vfs_context_ucred(ctx); 1057 MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp, 1058 vp->v_label, cnp); 1059 return (error); 1060} 1061 1062int 1063mac_vnode_check_rename_to(vfs_context_t ctx, struct vnode *dvp, 1064 struct vnode *vp, int samedir, struct componentname *cnp) 1065{ 1066 kauth_cred_t cred; 1067 int error; 1068 1069 if (!mac_vnode_enforce || 1070 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1071 return (0); 1072 1073 cred = vfs_context_ucred(ctx); 1074 MAC_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp, 1075 vp != NULL ? vp->v_label : NULL, samedir, cnp); 1076 return (error); 1077} 1078 1079int 1080mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp) 1081{ 1082 kauth_cred_t cred; 1083 int error; 1084 1085 if (!mac_vnode_enforce || 1086 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1087 return (0); 1088 1089 cred = vfs_context_ucred(ctx); 1090 MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label); 1091 return (error); 1092} 1093 1094int 1095mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist) 1096{ 1097 kauth_cred_t cred; 1098 int error; 1099 1100 if (!mac_vnode_enforce || 1101 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1102 return (0); 1103 1104 cred = vfs_context_ucred(ctx); 1105 MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist); 1106 return (error); 1107} 1108 1109int 1110mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which) 1111{ 1112 kauth_cred_t cred; 1113 int error; 1114 1115 if (!mac_vnode_enforce || 1116 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1117 return (0); 1118 1119 cred = vfs_context_ucred(ctx); 1120 MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which); 1121 return (error); 1122} 1123 1124#if 0 1125int 1126mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type, 1127 struct acl *acl) 1128{ 1129 kauth_cred_t cred; 1130 int error; 1131 1132 if (!mac_vnode_enforce || 1133 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1134 return (0); 1135 1136 cred = vfs_context_ucred(ctx); 1137 MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl); 1138 return (error); 1139} 1140#endif 1141 1142int 1143mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp, 1144 struct attrlist *alist) 1145{ 1146 kauth_cred_t cred; 1147 int error; 1148 1149 if (!mac_vnode_enforce || 1150 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1151 return (0); 1152 1153 cred = vfs_context_ucred(ctx); 1154 MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist); 1155 return (error); 1156} 1157 1158int 1159mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp, 1160 const char *name, struct uio *uio) 1161{ 1162 kauth_cred_t cred; 1163 int error; 1164 1165 if (!mac_vnode_enforce || 1166 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1167 return (0); 1168 1169 cred = vfs_context_ucred(ctx); 1170 MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label, 1171 name, uio); 1172 return (error); 1173} 1174 1175int 1176mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags) 1177{ 1178 kauth_cred_t cred; 1179 int error; 1180 1181 if (!mac_vnode_enforce || 1182 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1183 return (0); 1184 1185 cred = vfs_context_ucred(ctx); 1186 MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags); 1187 return (error); 1188} 1189 1190int 1191mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode) 1192{ 1193 kauth_cred_t cred; 1194 int error; 1195 1196 if (!mac_vnode_enforce || 1197 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1198 return (0); 1199 1200 cred = vfs_context_ucred(ctx); 1201 MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode); 1202 return (error); 1203} 1204 1205int 1206mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid, 1207 gid_t gid) 1208{ 1209 kauth_cred_t cred; 1210 int error; 1211 1212 if (!mac_vnode_enforce || 1213 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1214 return (0); 1215 1216 cred = vfs_context_ucred(ctx); 1217 MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid); 1218 return (error); 1219} 1220 1221int 1222mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp, 1223 struct timespec atime, struct timespec mtime) 1224{ 1225 kauth_cred_t cred; 1226 int error; 1227 1228 if (!mac_vnode_enforce || 1229 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1230 return (0); 1231 1232 cred = vfs_context_ucred(ctx); 1233 MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime, 1234 mtime); 1235 return (error); 1236} 1237 1238int 1239mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred, 1240 struct vnode *vp) 1241{ 1242 kauth_cred_t cred; 1243 int error; 1244 1245 if (!mac_vnode_enforce || 1246 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1247 return (0); 1248 1249 cred = vfs_context_ucred(ctx); 1250 MAC_CHECK(vnode_check_stat, cred, file_cred, vp, 1251 vp->v_label); 1252 return (error); 1253} 1254 1255int 1256mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred, 1257 struct vnode *vp) 1258{ 1259 kauth_cred_t cred; 1260 int error; 1261 1262 if (!mac_vnode_enforce || 1263 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1264 return (0); 1265 1266 cred = vfs_context_ucred(ctx); 1267 MAC_CHECK(vnode_check_truncate, cred, file_cred, vp, 1268 vp->v_label); 1269 1270 return (error); 1271} 1272 1273int 1274mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred, 1275 struct vnode *vp) 1276{ 1277 kauth_cred_t cred; 1278 int error; 1279 1280 if (!mac_vnode_enforce || 1281 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1282 return (0); 1283 1284 cred = vfs_context_ucred(ctx); 1285 MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label); 1286 1287 return (error); 1288} 1289 1290int 1291mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp, 1292 struct componentname *cnp, struct vnode_attr *vap) 1293{ 1294 kauth_cred_t cred; 1295 int error; 1296 1297 if (!mac_vnode_enforce || 1298 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1299 return (0); 1300 1301 cred = vfs_context_ucred(ctx); 1302 MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap); 1303 return (error); 1304} 1305 1306int 1307mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp) 1308{ 1309 kauth_cred_t cred; 1310 int error; 1311 1312 if (!mac_vnode_enforce || 1313 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1314 return (0); 1315 1316 cred = vfs_context_ucred(ctx); 1317 MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label); 1318 return (error); 1319} 1320 1321void 1322mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel) 1323{ 1324 kauth_cred_t cred = vfs_context_ucred(ctx); 1325 struct label *tmpl = NULL; 1326 1327 if (vp->v_label == NULL) 1328 tmpl = mac_vnode_label_alloc(); 1329 1330 vnode_lock(vp); 1331 1332 /* recheck after lock */ 1333 if (vp->v_label == NULL) { 1334 vp->v_label = tmpl; 1335 tmpl = NULL; 1336 } 1337 1338 MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel); 1339 vnode_unlock(vp); 1340 1341 if (tmpl != NULL) 1342 mac_vnode_label_free(tmpl); 1343} 1344 1345int 1346mac_vnode_find_sigs(struct proc *p, struct vnode *vp, off_t offset) 1347{ 1348 int error; 1349 1350 if (!mac_vnode_enforce || !mac_proc_enforce) 1351 return (0); 1352 1353 MAC_CHECK(vnode_find_sigs, p, vp, offset, vp->v_label); 1354 1355 return (error); 1356} 1357 1358void 1359mac_mount_label_associate(vfs_context_t ctx, struct mount *mp) 1360{ 1361 kauth_cred_t cred = vfs_context_ucred(ctx); 1362 1363 /* XXX: eventually this logic may be handled by the policy? */ 1364 1365 /* We desire MULTILABEL for the root filesystem. */ 1366 if ((mp->mnt_flag & MNT_ROOTFS) && 1367 (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0)) 1368 mp->mnt_flag |= MNT_MULTILABEL; 1369 1370 /* MULTILABEL on DEVFS. */ 1371 if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0) 1372 mp->mnt_flag |= MNT_MULTILABEL; 1373 1374 /* MULTILABEL on FDESC pseudo-filesystem. */ 1375 if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0) 1376 mp->mnt_flag |= MNT_MULTILABEL; 1377 1378 /* MULTILABEL on all NFS filesystems. */ 1379 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0) 1380 mp->mnt_flag |= MNT_MULTILABEL; 1381 1382 /* MULTILABEL on all AFP filesystems. */ 1383 if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0) 1384 mp->mnt_flag |= MNT_MULTILABEL; 1385 1386 if (mp->mnt_vtable != NULL) { 1387 /* Any filesystem that supports native XATTRs. */ 1388 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR)) 1389 mp->mnt_flag |= MNT_MULTILABEL; 1390 1391 /* Filesystem does not support multilabel. */ 1392 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) && 1393 (mp->mnt_flag & MNT_MULTILABEL)) 1394 mp->mnt_flag &= ~MNT_MULTILABEL; 1395 } 1396 1397 MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel); 1398#if DEBUG 1399 printf("MAC Framework enabling %s support: %s -> %s (%s)\n", 1400 mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel", 1401 mp->mnt_vfsstat.f_mntfromname, 1402 mp->mnt_vfsstat.f_mntonname, 1403 mp->mnt_vfsstat.f_fstypename); 1404#endif 1405} 1406 1407int 1408mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp, 1409 struct componentname *cnp, const char *vfc_name) 1410{ 1411 kauth_cred_t cred; 1412 int error; 1413 1414 if (!mac_vnode_enforce || 1415 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1416 return (0); 1417 1418 cred = vfs_context_ucred(ctx); 1419 MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name); 1420 1421 return (error); 1422} 1423 1424int 1425mac_mount_check_remount(vfs_context_t ctx, struct mount *mp) 1426{ 1427 kauth_cred_t cred; 1428 int error; 1429 1430 if (!mac_vnode_enforce || 1431 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1432 return (0); 1433 1434 cred = vfs_context_ucred(ctx); 1435 MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel); 1436 1437 return (error); 1438} 1439 1440int 1441mac_mount_check_umount(vfs_context_t ctx, struct mount *mp) 1442{ 1443 kauth_cred_t cred; 1444 int error; 1445 1446 if (!mac_vnode_enforce || 1447 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1448 return (0); 1449 1450 cred = vfs_context_ucred(ctx); 1451 MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel); 1452 1453 return (error); 1454} 1455 1456int 1457mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp, 1458 struct vfs_attr *vfa) 1459{ 1460 kauth_cred_t cred; 1461 int error; 1462 1463 if (!mac_vnode_enforce || 1464 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1465 return (0); 1466 1467 cred = vfs_context_ucred(ctx); 1468 MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa); 1469 return (error); 1470} 1471 1472int 1473mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp, 1474 struct vfs_attr *vfa) 1475{ 1476 kauth_cred_t cred; 1477 int error; 1478 1479 if (!mac_vnode_enforce || 1480 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1481 return (0); 1482 1483 cred = vfs_context_ucred(ctx); 1484 MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa); 1485 return (error); 1486} 1487 1488int 1489mac_mount_check_stat(vfs_context_t ctx, struct mount *mount) 1490{ 1491 kauth_cred_t cred; 1492 int error; 1493 1494 if (!mac_vnode_enforce || 1495 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1496 return (0); 1497 1498 cred = vfs_context_ucred(ctx); 1499 MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel); 1500 1501 return (error); 1502} 1503 1504int 1505mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount) 1506{ 1507 kauth_cred_t cred; 1508 int error; 1509 1510 if (!mac_vnode_enforce || 1511 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1512 return (0); 1513 1514 cred = vfs_context_ucred(ctx); 1515 MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel); 1516 1517 return (error); 1518} 1519 1520int 1521mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd) 1522{ 1523 kauth_cred_t cred; 1524 int error; 1525 1526 if (!mac_vnode_enforce || 1527 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1528 return (0); 1529 1530 cred = vfs_context_ucred(ctx); 1531 MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd); 1532 1533 return (error); 1534} 1535 1536void 1537mac_devfs_label_associate_device(dev_t dev, struct devnode *de, 1538 const char *fullpath) 1539{ 1540 if (!mac_device_enforce) 1541 return; 1542 1543 MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label, 1544 fullpath); 1545} 1546 1547void 1548mac_devfs_label_associate_directory(const char *dirname, int dirnamelen, 1549 struct devnode *de, const char *fullpath) 1550{ 1551 if (!mac_device_enforce) 1552 return; 1553 1554 MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de, 1555 de->dn_label, fullpath); 1556} 1557 1558int 1559vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context) 1560{ 1561 int error; 1562 1563 if (!mac_vnode_enforce || !mac_label_vnodes) 1564 return (0); 1565 1566 if (vp->v_mount == NULL) { 1567 printf("vn_setlabel: null v_mount\n"); 1568 if (vp->v_type != VNON) 1569 printf("vn_setlabel: null v_mount with non-VNON\n"); 1570 return (EBADF); 1571 } 1572 1573 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 1574 return (ENOTSUP); 1575 1576 /* 1577 * Multi-phase commit. First check the policies to confirm the 1578 * change is OK. Then commit via the filesystem. Finally, 1579 * update the actual vnode label. Question: maybe the filesystem 1580 * should update the vnode at the end as part of VNOP_SETLABEL()? 1581 */ 1582 error = mac_vnode_check_label_update(context, vp, intlabel); 1583 if (error) 1584 return (error); 1585 1586 error = VNOP_SETLABEL(vp, intlabel, context); 1587 if (error == ENOTSUP) { 1588 error = mac_vnode_label_store(context, vp, 1589 intlabel); 1590 if (error) { 1591 printf("%s: mac_vnode_label_store failed %d\n", 1592 __func__, error); 1593 return (error); 1594 } 1595 mac_vnode_label_update(context, vp, intlabel); 1596 } else 1597 if (error) { 1598 printf("vn_setlabel: vop setlabel failed %d\n", error); 1599 return (error); 1600 } 1601 1602 return (0); 1603} 1604 1605int 1606mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp, 1607 struct vnode *vp, vfs_context_t ctx) 1608{ 1609 struct fileproc *fp; 1610#if CONFIG_MACF_SOCKET_SUBSET 1611 struct socket *so; 1612#endif 1613 struct pipe *cpipe; 1614 struct vnode *fvp; 1615 struct proc *p; 1616 int error; 1617 1618 error = 0; 1619 1620 /* 1621 * If no backing file, let the policy choose which label to use. 1622 */ 1623 if (fnp->fd_fd == -1) { 1624 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx), 1625 mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label); 1626 return (0); 1627 } 1628 1629 p = vfs_context_proc(ctx); 1630 error = fp_lookup(p, fnp->fd_fd, &fp, 0); 1631 if (error) 1632 return (error); 1633 1634 if (fp->f_fglob == NULL) { 1635 error = EBADF; 1636 goto out; 1637 } 1638 1639 switch (FILEGLOB_DTYPE(fp->f_fglob)) { 1640 case DTYPE_VNODE: 1641 fvp = (struct vnode *)fp->f_fglob->fg_data; 1642 if ((error = vnode_getwithref(fvp))) 1643 goto out; 1644 MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label); 1645 (void)vnode_put(fvp); 1646 break; 1647#if CONFIG_MACF_SOCKET_SUBSET 1648 case DTYPE_SOCKET: 1649 so = (struct socket *)fp->f_fglob->fg_data; 1650 socket_lock(so, 1); 1651 MAC_PERFORM(vnode_label_associate_socket, 1652 vfs_context_ucred(ctx), (socket_t)so, so->so_label, 1653 vp, vp->v_label); 1654 socket_unlock(so, 1); 1655 break; 1656#endif 1657 case DTYPE_PSXSHM: 1658 pshm_label_associate(fp, vp, ctx); 1659 break; 1660 case DTYPE_PSXSEM: 1661 psem_label_associate(fp, vp, ctx); 1662 break; 1663 case DTYPE_PIPE: 1664 cpipe = (struct pipe *)fp->f_fglob->fg_data; 1665 /* kern/sys_pipe.c:pipe_select() suggests this test. */ 1666 if (cpipe == (struct pipe *)-1) { 1667 error = EINVAL; 1668 goto out; 1669 } 1670 PIPE_LOCK(cpipe); 1671 MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx), 1672 cpipe, cpipe->pipe_label, vp, vp->v_label); 1673 PIPE_UNLOCK(cpipe); 1674 break; 1675 case DTYPE_KQUEUE: 1676 case DTYPE_FSEVENTS: 1677 default: 1678 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx), 1679 mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label, 1680 vp, vp->v_label); 1681 break; 1682 } 1683out: 1684 fp_drop(p, fnp->fd_fd, fp, 0); 1685 return (error); 1686} 1687