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/fdesc/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 143 vp->v_label = mac_vnode_label_alloc(); 144} 145 146/* 147 * vnode labels are allocated at the same time as vnodes, but vnodes are never 148 * freed. Instead, we want to remove any sensitive information before putting 149 * them on the free list for reuse. 150*/ 151void 152mac_vnode_label_recycle(vnode_t vp) 153{ 154 155 MAC_PERFORM(vnode_label_recycle, vp->v_label); 156} 157 158static void 159mac_devfs_label_free(struct label *label) 160{ 161 MAC_PERFORM(devfs_label_destroy, label); 162 mac_labelzone_free(label); 163} 164 165void 166mac_devfs_label_destroy(struct devnode *de) 167{ 168 if (de->dn_label != NULL) { 169 mac_devfs_label_free(de->dn_label); 170 de->dn_label = NULL; 171 } 172} 173 174static void 175mac_mount_label_free(struct label *label) 176{ 177 178 MAC_PERFORM(mount_label_destroy, label); 179 mac_labelzone_free(label); 180} 181 182void 183mac_mount_label_destroy(struct mount *mp) 184{ 185 186 187 if (mp->mnt_mntlabel != NULL) { 188 mac_mount_label_free(mp->mnt_mntlabel); 189 mp->mnt_mntlabel = NULL; 190 } 191} 192 193void 194mac_vnode_label_free(struct label *label) 195{ 196 197 MAC_PERFORM(vnode_label_destroy, label); 198 mac_labelzone_free(label); 199} 200 201#ifndef __APPLE__ 202void 203mac_vnode_label_destroy(struct vnode *vp) 204{ 205 206 mac_vnode_label_free(vp->v_label); 207 vp->v_label = NULL; 208} 209#endif 210 211void 212mac_vnode_label_copy(struct label *src, struct label *dest) 213{ 214 215 MAC_PERFORM(vnode_label_copy, src, dest); 216} 217 218int 219mac_vnode_label_externalize_audit(struct vnode *vp, struct mac *mac) 220{ 221 int error; 222 223 /* It is assumed that any necessary vnode locking is done on entry */ 224 error = MAC_EXTERNALIZE_AUDIT(vnode, vp->v_label, 225 mac->m_string, mac->m_buflen); 226 227 return (error); 228} 229 230int 231mac_vnode_label_externalize(struct label *label, char *elements, 232 char *outbuf, size_t outbuflen, int flags __unused) 233{ 234 int error; 235 236 error = MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen); 237 238 return (error); 239} 240 241int 242mac_vnode_label_internalize(struct label *label, char *string) 243{ 244 int error; 245 246 error = MAC_INTERNALIZE(vnode, label, string); 247 248 return (error); 249} 250 251int 252mac_mount_label_internalize(struct label *label, char *string) 253{ 254 int error; 255 256 error = MAC_INTERNALIZE(mount, label, string); 257 258 return (error); 259} 260 261int 262mac_mount_label_externalize(struct label *label, char *elements, 263 char *outbuf, size_t outbuflen) 264{ 265 int error; 266 267 error = MAC_EXTERNALIZE(mount, label, elements, outbuf, outbuflen); 268 269 return (error); 270} 271 272void 273mac_devfs_label_copy(struct label *src, struct label *dest) 274{ 275 if (!mac_device_enforce) 276 return; 277 278 MAC_PERFORM(devfs_label_copy, src, dest); 279} 280 281void 282mac_devfs_label_update(struct mount *mp, struct devnode *de, 283 struct vnode *vp) 284{ 285 286 if (!mac_device_enforce) 287 return; 288 289 MAC_PERFORM(devfs_label_update, mp, de, de->dn_label, vp, 290 vp->v_label); 291} 292 293int 294mac_vnode_label_associate(struct mount *mp, struct vnode *vp, vfs_context_t ctx) 295{ 296 struct devnode *dnp; 297 struct fdescnode *fnp; 298 int error = 0; 299 300 if (!mac_vnode_enforce) 301 return (error); 302 303 /* XXX: should not inspect v_tag in kernel! */ 304 switch (vp->v_tag) { 305 case VT_DEVFS: 306 dnp = VTODN(vp); 307 mac_vnode_label_associate_devfs(mp, dnp, vp); 308 break; 309 case VT_FDESC: 310 fnp = VTOFDESC(vp); 311 error = mac_vnode_label_associate_fdesc(mp, fnp, vp, ctx); 312 break; 313 default: 314 error = mac_vnode_label_associate_extattr(mp, vp); 315 break; 316 } 317 318 return (error); 319} 320 321void 322mac_vnode_label_associate_devfs(struct mount *mp, struct devnode *de, 323 struct vnode *vp) 324{ 325 if (!mac_device_enforce) 326 return; 327 328 MAC_PERFORM(vnode_label_associate_devfs, 329 mp, mp ? mp->mnt_mntlabel : NULL, 330 de, de->dn_label, 331 vp, vp->v_label); 332} 333 334int 335mac_vnode_label_associate_extattr(struct mount *mp, struct vnode *vp) 336{ 337 int error; 338 339 MAC_CHECK(vnode_label_associate_extattr, mp, mp->mnt_mntlabel, vp, 340 vp->v_label); 341 342 return (error); 343} 344 345void 346mac_vnode_label_associate_singlelabel(struct mount *mp, struct vnode *vp) 347{ 348 349 if (!mac_vnode_enforce) 350 return; 351 352 MAC_PERFORM(vnode_label_associate_singlelabel, mp, 353 mp ? mp->mnt_mntlabel : NULL, vp, vp->v_label); 354} 355 356int 357mac_vnode_notify_create(vfs_context_t ctx, struct mount *mp, 358 struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 359{ 360 kauth_cred_t cred; 361 int error; 362 363 if (!mac_vnode_enforce || 364 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 365 return (0); 366 367 cred = vfs_context_ucred(ctx); 368 MAC_CHECK(vnode_notify_create, cred, mp, mp->mnt_mntlabel, 369 dvp, dvp->v_label, vp, vp->v_label, cnp); 370 371 return (error); 372} 373 374/* 375 * Extended attribute 'name' was updated via 376 * vn_setxattr() or vn_removexattr(). Allow the 377 * policy to update the vnode label. 378 */ 379void 380mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp, 381 const char *name) 382{ 383 int error = 0; 384 385 if (!mac_vnode_enforce) 386 return; 387 388 MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp, 389 vp->v_label, name); 390 if (error == 0) 391 return; 392 393 vnode_lock(vp); 394 vnode_relabel(vp); 395 vnode_unlock(vp); 396 return; 397} 398 399static int 400mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp, 401 struct label *intlabel) 402{ 403 kauth_cred_t cred; 404 int error; 405 406 if (!mac_vnode_enforce && 407 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 408 return 0; 409 410 cred = vfs_context_ucred(ctx); 411 MAC_CHECK(vnode_label_store, cred, vp, vp->v_label, intlabel); 412 413 return (error); 414} 415 416int 417mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp, 418 struct label *scriptvnodelabel, struct label *execl) 419{ 420 kauth_cred_t cred; 421 int disjoint = 0; 422 423 if (!mac_proc_enforce && !mac_vnode_enforce) 424 return disjoint; 425 426 /* mark the new cred to indicate "matching" includes the label */ 427 new->cr_flags |= CRF_MAC_ENFORCE; 428 429 cred = vfs_context_ucred(ctx); 430 MAC_PERFORM(cred_label_update_execve, cred, new, vp, vp->v_label, 431 scriptvnodelabel, execl, &disjoint); 432 433 return (disjoint); 434} 435 436int 437mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp, 438 struct label *scriptvnodelabel, struct label *execlabel, struct proc *p) 439{ 440 kauth_cred_t cred; 441 int result = 0; 442 443 if (!mac_proc_enforce && !mac_vnode_enforce) 444 return result; 445 446 cred = vfs_context_ucred(ctx); 447 MAC_BOOLEAN(cred_check_label_update_execve, ||, cred, vp, vp->v_label, 448 scriptvnodelabel, execlabel, p); 449 450 return (result); 451} 452 453int 454mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp, 455 int acc_mode) 456{ 457 kauth_cred_t cred; 458 int error; 459 int mask; 460 461 if (!mac_vnode_enforce || 462 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 463 return 0; 464 465 cred = vfs_context_ucred(ctx); 466 /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */ 467 mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode); 468 MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask); 469 return (error); 470 } 471 472int 473mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp) 474{ 475 kauth_cred_t cred; 476 int error; 477 478 if (!mac_vnode_enforce || 479 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 480 return (0); 481 482 cred = vfs_context_ucred(ctx); 483 MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label); 484 return (error); 485} 486 487int 488mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp, 489 struct componentname *cnp) 490{ 491 kauth_cred_t cred; 492 int error; 493 494 if (!mac_vnode_enforce || 495 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 496 return (0); 497 498 cred = vfs_context_ucred(ctx); 499 MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp); 500 return (error); 501} 502 503int 504mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp, 505 struct componentname *cnp, struct vnode_attr *vap) 506{ 507 kauth_cred_t cred; 508 int error; 509 510 if (!mac_vnode_enforce || 511 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 512 return (0); 513 514 cred = vfs_context_ucred(ctx); 515 MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap); 516 return (error); 517} 518 519int 520mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp, 521 struct componentname *cnp) 522{ 523 kauth_cred_t cred; 524 int error; 525 526 if (!mac_vnode_enforce || 527 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 528 return (0); 529 530 cred = vfs_context_ucred(ctx); 531 MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp, 532 vp->v_label, cnp); 533 return (error); 534} 535#if 0 536int 537mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp, 538 acl_type_t type) 539{ 540 kauth_cred_t cred; 541 int error; 542 543 if (!mac_vnode_enforce || 544 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 545 return (0); 546 547 cred = vfs_context_ucred(ctx); 548 MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type); 549 return (error); 550} 551#endif 552 553int 554mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp, 555 const char *name) 556{ 557 kauth_cred_t cred; 558 int error; 559 560 if (!mac_vnode_enforce || 561 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 562 return (0); 563 564 cred = vfs_context_ucred(ctx); 565 MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name); 566 return (error); 567} 568int 569mac_vnode_check_exchangedata(vfs_context_t ctx, 570 struct vnode *v1, struct vnode *v2) 571{ 572 kauth_cred_t cred; 573 int error; 574 575 if (!mac_vnode_enforce || 576 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 577 return (0); 578 579 cred = vfs_context_ucred(ctx); 580 MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label, 581 v2, v2->v_label); 582 583 return (error); 584} 585 586#if 0 587int 588mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type) 589{ 590 kauth_cred_t cred; 591 int error; 592 593 if (!mac_vnode_enforce || 594 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 595 return (0); 596 597 cred = vfs_context_ucred(ctx); 598 MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type); 599 return (error); 600} 601#endif 602 603int 604mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp, 605 struct attrlist *alist) 606{ 607 kauth_cred_t cred; 608 int error; 609 610 if (!mac_vnode_enforce || 611 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 612 return (0); 613 614 cred = vfs_context_ucred(ctx); 615 MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist); 616 617 /* Falsify results instead of returning error? */ 618 return (error); 619} 620 621int 622mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp, 623 struct image_params *imgp) 624{ 625 kauth_cred_t cred; 626 int error; 627 628 if (!mac_vnode_enforce || !mac_proc_enforce) 629 return (0); 630 631 cred = vfs_context_ucred(ctx); 632 MAC_CHECK(vnode_check_exec, cred, vp, vp->v_label, 633 (imgp != NULL) ? imgp->ip_execlabelp : NULL, 634 (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL, 635 (imgp != NULL) ? &imgp->ip_csflags : NULL); 636 return (error); 637} 638 639int 640mac_vnode_check_signature(struct vnode *vp, unsigned char *sha1, 641 void * signature, size_t size) 642{ 643 int error; 644 645 if (!mac_vnode_enforce || !mac_proc_enforce) 646 return (0); 647 648 MAC_CHECK(vnode_check_signature, vp, vp->v_label, sha1, signature, size); 649 return (error); 650} 651 652#if 0 653int 654mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type) 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_getacl, cred, vp, vp->v_label, type); 665 return (error); 666} 667#endif 668 669int 670mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp, 671 const char *name, struct uio *uio) 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_getextattr, cred, vp, vp->v_label, 682 name, uio); 683 return (error); 684} 685 686int 687mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd) 688{ 689 kauth_cred_t cred; 690 int error; 691 692 if (!mac_vnode_enforce || 693 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 694 return (0); 695 696 cred = vfs_context_ucred(ctx); 697 MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd); 698 return (error); 699} 700 701int 702mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred, 703 struct knote *kn, struct vnode *vp) 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_kqfilter, cred, file_cred, kn, vp, 714 vp->v_label); 715 716 return (error); 717} 718 719int 720mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp, 721 struct vnode *vp, struct componentname *cnp) 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_link, cred, dvp, dvp->v_label, vp, 732 vp->v_label, cnp); 733 return (error); 734} 735 736int 737mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp) 738{ 739 kauth_cred_t cred; 740 int error; 741 742 if (!mac_vnode_enforce || 743 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 744 return (0); 745 746 cred = vfs_context_ucred(ctx); 747 MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label); 748 return (error); 749} 750 751int 752mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp, 753 struct componentname *cnp) 754{ 755 kauth_cred_t cred; 756 int error; 757 758 if (!mac_vnode_enforce || 759 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 760 return (0); 761 762 cred = vfs_context_ucred(ctx); 763 MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp); 764 return (error); 765} 766 767int 768mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode) 769{ 770 kauth_cred_t cred; 771 int error; 772 773 if (!mac_vnode_enforce || 774 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 775 return (0); 776 777 cred = vfs_context_ucred(ctx); 778 MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode); 779 return (error); 780} 781 782int 783mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred, 784 struct vnode *vp) 785{ 786 kauth_cred_t cred; 787 int error; 788 789 if (!mac_vnode_enforce || 790 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 791 return (0); 792 793 cred = vfs_context_ucred(ctx); 794 MAC_CHECK(vnode_check_read, cred, file_cred, vp, 795 vp->v_label); 796 797 return (error); 798} 799 800int 801mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp) 802{ 803 kauth_cred_t cred; 804 int error; 805 806 if (!mac_vnode_enforce || 807 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 808 return (0); 809 810 cred = vfs_context_ucred(ctx); 811 MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label); 812 return (error); 813} 814 815int 816mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp) 817{ 818 kauth_cred_t cred; 819 int error; 820 821 if (!mac_vnode_enforce || 822 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 823 return (0); 824 825 cred = vfs_context_ucred(ctx); 826 MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label); 827 return (error); 828} 829 830int 831mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp, 832 struct label *newlabel) 833{ 834 kauth_cred_t cred; 835 int error; 836 837 if (!mac_vnode_enforce || 838 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 839 return (0); 840 841 cred = vfs_context_ucred(ctx); 842 MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel); 843 844 return (error); 845} 846 847int 848mac_vnode_check_rename_from(vfs_context_t ctx, struct vnode *dvp, 849 struct vnode *vp, struct componentname *cnp) 850{ 851 kauth_cred_t cred; 852 int error; 853 854 if (!mac_vnode_enforce || 855 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 856 return (0); 857 858 cred = vfs_context_ucred(ctx); 859 MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp, 860 vp->v_label, cnp); 861 return (error); 862} 863 864int 865mac_vnode_check_rename_to(vfs_context_t ctx, struct vnode *dvp, 866 struct vnode *vp, int samedir, struct componentname *cnp) 867{ 868 kauth_cred_t cred; 869 int error; 870 871 if (!mac_vnode_enforce || 872 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 873 return (0); 874 875 cred = vfs_context_ucred(ctx); 876 MAC_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp, 877 vp != NULL ? vp->v_label : NULL, samedir, cnp); 878 return (error); 879} 880 881int 882mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp) 883{ 884 kauth_cred_t cred; 885 int error; 886 887 if (!mac_vnode_enforce || 888 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 889 return (0); 890 891 cred = vfs_context_ucred(ctx); 892 MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label); 893 return (error); 894} 895 896int 897mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which) 898{ 899 kauth_cred_t cred; 900 int error; 901 902 if (!mac_vnode_enforce || 903 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 904 return (0); 905 906 cred = vfs_context_ucred(ctx); 907 MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which); 908 return (error); 909} 910 911#if 0 912int 913mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type, 914 struct acl *acl) 915{ 916 kauth_cred_t cred; 917 int error; 918 919 if (!mac_vnode_enforce || 920 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 921 return (0); 922 923 cred = vfs_context_ucred(ctx); 924 MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl); 925 return (error); 926} 927#endif 928 929int 930mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp, 931 struct attrlist *alist) 932{ 933 kauth_cred_t cred; 934 int error; 935 936 if (!mac_vnode_enforce || 937 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 938 return (0); 939 940 cred = vfs_context_ucred(ctx); 941 MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist); 942 return (error); 943} 944 945int 946mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp, 947 const char *name, struct uio *uio) 948{ 949 kauth_cred_t cred; 950 int error; 951 952 if (!mac_vnode_enforce || 953 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 954 return (0); 955 956 cred = vfs_context_ucred(ctx); 957 MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label, 958 name, uio); 959 return (error); 960} 961 962int 963mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags) 964{ 965 kauth_cred_t cred; 966 int error; 967 968 if (!mac_vnode_enforce || 969 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 970 return (0); 971 972 cred = vfs_context_ucred(ctx); 973 MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags); 974 return (error); 975} 976 977int 978mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode) 979{ 980 kauth_cred_t cred; 981 int error; 982 983 if (!mac_vnode_enforce || 984 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 985 return (0); 986 987 cred = vfs_context_ucred(ctx); 988 MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode); 989 return (error); 990} 991 992int 993mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid, 994 gid_t gid) 995{ 996 kauth_cred_t cred; 997 int error; 998 999 if (!mac_vnode_enforce || 1000 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1001 return (0); 1002 1003 cred = vfs_context_ucred(ctx); 1004 MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid); 1005 return (error); 1006} 1007 1008int 1009mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp, 1010 struct timespec atime, struct timespec mtime) 1011{ 1012 kauth_cred_t cred; 1013 int error; 1014 1015 if (!mac_vnode_enforce || 1016 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1017 return (0); 1018 1019 cred = vfs_context_ucred(ctx); 1020 MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime, 1021 mtime); 1022 return (error); 1023} 1024 1025int 1026mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred, 1027 struct vnode *vp) 1028{ 1029 kauth_cred_t cred; 1030 int error; 1031 1032 if (!mac_vnode_enforce || 1033 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1034 return (0); 1035 1036 cred = vfs_context_ucred(ctx); 1037 MAC_CHECK(vnode_check_stat, cred, file_cred, vp, 1038 vp->v_label); 1039 return (error); 1040} 1041 1042int 1043mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred, 1044 struct vnode *vp) 1045{ 1046 kauth_cred_t cred; 1047 int error; 1048 1049 if (!mac_vnode_enforce || 1050 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1051 return (0); 1052 1053 cred = vfs_context_ucred(ctx); 1054 MAC_CHECK(vnode_check_truncate, cred, file_cred, vp, 1055 vp->v_label); 1056 1057 return (error); 1058} 1059 1060int 1061mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred, 1062 struct vnode *vp) 1063{ 1064 kauth_cred_t cred; 1065 int error; 1066 1067 if (!mac_vnode_enforce || 1068 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1069 return (0); 1070 1071 cred = vfs_context_ucred(ctx); 1072 MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label); 1073 1074 return (error); 1075} 1076 1077void 1078mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel) 1079{ 1080 kauth_cred_t cred = vfs_context_ucred(ctx); 1081 1082 vnode_lock(vp); 1083 MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel); 1084 vnode_unlock(vp); 1085} 1086 1087void 1088mac_mount_label_associate(vfs_context_t ctx, struct mount *mp) 1089{ 1090 kauth_cred_t cred = vfs_context_ucred(ctx); 1091 1092 /* XXX: eventually this logic may be handled by the policy? */ 1093 1094 /* We desire MULTILABEL for the root filesystem. */ 1095 if ((mp->mnt_flag & MNT_ROOTFS) && 1096 (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0)) 1097 mp->mnt_flag |= MNT_MULTILABEL; 1098 1099 /* MULTILABEL on DEVFS. */ 1100 if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0) 1101 mp->mnt_flag |= MNT_MULTILABEL; 1102 1103 /* MULTILABEL on FDESC pseudo-filesystem. */ 1104 if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0) 1105 mp->mnt_flag |= MNT_MULTILABEL; 1106 1107 /* MULTILABEL on all NFS filesystems. */ 1108 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0) 1109 mp->mnt_flag |= MNT_MULTILABEL; 1110 1111 /* MULTILABEL on all AFP filesystems. */ 1112 if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0) 1113 mp->mnt_flag |= MNT_MULTILABEL; 1114 1115 if (mp->mnt_vtable != NULL) { 1116 /* Any filesystem that supports native XATTRs. */ 1117 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR)) 1118 mp->mnt_flag |= MNT_MULTILABEL; 1119 1120 /* Filesystem does not support multilabel. */ 1121 if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) && 1122 (mp->mnt_flag & MNT_MULTILABEL)) 1123 mp->mnt_flag &= ~MNT_MULTILABEL; 1124 } 1125 1126 MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel); 1127#if MAC_DEBUG 1128 printf("MAC Framework enabling %s support: %s -> %s (%s)\n", 1129 mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel", 1130 mp->mnt_vfsstat.f_mntfromname, 1131 mp->mnt_vfsstat.f_mntonname, 1132 mp->mnt_vfsstat.f_fstypename); 1133#endif 1134} 1135 1136int 1137mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp, 1138 struct componentname *cnp, const char *vfc_name) 1139{ 1140 kauth_cred_t cred; 1141 int error; 1142 1143 if (!mac_vnode_enforce || 1144 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1145 return (0); 1146 1147 cred = vfs_context_ucred(ctx); 1148 MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name); 1149 1150 return (error); 1151} 1152 1153int 1154mac_mount_check_remount(vfs_context_t ctx, struct mount *mp) 1155{ 1156 kauth_cred_t cred; 1157 int error; 1158 1159 if (!mac_vnode_enforce || 1160 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1161 return (0); 1162 1163 cred = vfs_context_ucred(ctx); 1164 MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel); 1165 1166 return (error); 1167} 1168 1169int 1170mac_mount_check_umount(vfs_context_t ctx, struct mount *mp) 1171{ 1172 kauth_cred_t cred; 1173 int error; 1174 1175 if (!mac_vnode_enforce || 1176 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1177 return (0); 1178 1179 cred = vfs_context_ucred(ctx); 1180 MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel); 1181 1182 return (error); 1183} 1184 1185int 1186mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp, 1187 struct vfs_attr *vfa) 1188{ 1189 kauth_cred_t cred; 1190 int error; 1191 1192 if (!mac_vnode_enforce || 1193 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1194 return (0); 1195 1196 cred = vfs_context_ucred(ctx); 1197 MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa); 1198 return (error); 1199} 1200 1201int 1202mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp, 1203 struct vfs_attr *vfa) 1204{ 1205 kauth_cred_t cred; 1206 int error; 1207 1208 if (!mac_vnode_enforce || 1209 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1210 return (0); 1211 1212 cred = vfs_context_ucred(ctx); 1213 MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa); 1214 return (error); 1215} 1216 1217int 1218mac_mount_check_stat(vfs_context_t ctx, struct mount *mount) 1219{ 1220 kauth_cred_t cred; 1221 int error; 1222 1223 if (!mac_vnode_enforce || 1224 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1225 return (0); 1226 1227 cred = vfs_context_ucred(ctx); 1228 MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel); 1229 1230 return (error); 1231} 1232 1233int 1234mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount) 1235{ 1236 kauth_cred_t cred; 1237 int error; 1238 1239 if (!mac_vnode_enforce || 1240 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1241 return (0); 1242 1243 cred = vfs_context_ucred(ctx); 1244 MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel); 1245 1246 return (error); 1247} 1248 1249int 1250mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd) 1251{ 1252 kauth_cred_t cred; 1253 int error; 1254 1255 if (!mac_vnode_enforce || 1256 !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) 1257 return (0); 1258 1259 cred = vfs_context_ucred(ctx); 1260 MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd); 1261 1262 return (error); 1263} 1264 1265void 1266mac_devfs_label_associate_device(dev_t dev, struct devnode *de, 1267 const char *fullpath) 1268{ 1269 if (!mac_device_enforce) 1270 return; 1271 1272 MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label, 1273 fullpath); 1274} 1275 1276void 1277mac_devfs_label_associate_directory(const char *dirname, int dirnamelen, 1278 struct devnode *de, const char *fullpath) 1279{ 1280 if (!mac_device_enforce) 1281 return; 1282 1283 MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de, 1284 de->dn_label, fullpath); 1285} 1286 1287int 1288vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context) 1289{ 1290 int error; 1291 1292 if (!mac_vnode_enforce) 1293 return (0); 1294 1295 if (vp->v_mount == NULL) { 1296 printf("vn_setlabel: null v_mount\n"); 1297 if (vp->v_type != VNON) 1298 printf("vn_setlabel: null v_mount with non-VNON\n"); 1299 return (EBADF); 1300 } 1301 1302 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 1303 return (ENOTSUP); 1304 1305 /* 1306 * Multi-phase commit. First check the policies to confirm the 1307 * change is OK. Then commit via the filesystem. Finally, 1308 * update the actual vnode label. Question: maybe the filesystem 1309 * should update the vnode at the end as part of VNOP_SETLABEL()? 1310 */ 1311 error = mac_vnode_check_label_update(context, vp, intlabel); 1312 if (error) 1313 return (error); 1314 1315 error = VNOP_SETLABEL(vp, intlabel, context); 1316 if (error == ENOTSUP) { 1317 error = mac_vnode_label_store(context, vp, 1318 intlabel); 1319 if (error) { 1320 printf("%s: mac_vnode_label_store failed %d\n", 1321 __func__, error); 1322 return (error); 1323 } 1324 mac_vnode_label_update(context, vp, intlabel); 1325 } else 1326 if (error) { 1327 printf("vn_setlabel: vop setlabel failed %d\n", error); 1328 return (error); 1329 } 1330 1331 return (0); 1332} 1333 1334int 1335mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp, 1336 struct vnode *vp, vfs_context_t ctx) 1337{ 1338 struct fileproc *fp; 1339 struct socket *so; 1340 struct pipe *cpipe; 1341 struct vnode *fvp; 1342 struct proc *p; 1343 int error; 1344 1345 error = 0; 1346 1347 /* 1348 * If no backing file, let the policy choose which label to use. 1349 */ 1350 if (fnp->fd_fd == -1) { 1351 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx), 1352 mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label); 1353 return (0); 1354 } 1355 1356 p = vfs_context_proc(ctx); 1357 error = fp_lookup(p, fnp->fd_fd, &fp, 0); 1358 if (error) 1359 return (error); 1360 1361 if (fp->f_fglob == NULL) { 1362 error = EBADF; 1363 goto out; 1364 } 1365 1366 switch (fp->f_fglob->fg_type) { 1367 case DTYPE_VNODE: 1368 fvp = (struct vnode *)fp->f_fglob->fg_data; 1369 if ((error = vnode_getwithref(fvp))) 1370 goto out; 1371 MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label); 1372 (void)vnode_put(fvp); 1373 break; 1374 case DTYPE_SOCKET: 1375 so = (struct socket *)fp->f_fglob->fg_data; 1376 socket_lock(so, 1); 1377 MAC_PERFORM(vnode_label_associate_socket, 1378 vfs_context_ucred(ctx), (socket_t)so, so->so_label, 1379 vp, vp->v_label); 1380 socket_unlock(so, 1); 1381 break; 1382 case DTYPE_PSXSHM: 1383 pshm_label_associate(fp, vp, ctx); 1384 break; 1385 case DTYPE_PSXSEM: 1386 psem_label_associate(fp, vp, ctx); 1387 break; 1388 case DTYPE_PIPE: 1389 cpipe = (struct pipe *)fp->f_fglob->fg_data; 1390 /* kern/sys_pipe.c:pipe_select() suggests this test. */ 1391 if (cpipe == (struct pipe *)-1) { 1392 error = EINVAL; 1393 goto out; 1394 } 1395 PIPE_LOCK(cpipe); 1396 MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx), 1397 cpipe, cpipe->pipe_label, vp, vp->v_label); 1398 PIPE_UNLOCK(cpipe); 1399 break; 1400 case DTYPE_KQUEUE: 1401 case DTYPE_FSEVENTS: 1402 default: 1403 MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx), 1404 mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label, 1405 vp, vp->v_label); 1406 break; 1407 } 1408out: 1409 fp_drop(p, fnp->fd_fd, fp, 0); 1410 return (error); 1411} 1412