1 /*- 2 * Copyright (c) 1999-2002 Robert N. M. Watson 3 * Copyright (c) 2001 Ilmar S. Habibulin 4 * Copyright (c) 2001-2005 McAfee, Inc. 5 * Copyright (c) 2005 SPARTA, Inc. 6 * All rights reserved. 7 * 8 * This software was developed by Robert Watson and Ilmar Habibulin for the 9 * TrustedBSD Project. 10 * 11 * This software was developed for the FreeBSD Project in part by McAfee 12 * Research, the Security Research Division of McAfee, Inc. under 13 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 14 * CHATS research program. 15 * 16 * This software was enhanced by SPARTA ISSO under SPAWAR contract 17 * N66001-04-C-6019 ("SEFOS"). 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 1. Redistributions of source code must retain the above copyright 23 * notice, this list of conditions and the following disclaimer. 24 * 2. Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in the 26 * documentation and/or other materials provided with the distribution. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 */ 40 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #include "opt_mac.h" 45 46 #include <sys/param.h> 47 #include <sys/condvar.h> 48 #include <sys/extattr.h> 49 #include <sys/imgact.h> 50 #include <sys/kernel.h> 51 #include <sys/lock.h> 52 #include <sys/malloc.h> 53 #include <sys/mutex.h> 54 #include <sys/mac.h> 55 #include <sys/proc.h> 56 #include <sys/sbuf.h> 57 #include <sys/systm.h> 58 #include <sys/vnode.h> 59 #include <sys/mount.h> 60 #include <sys/file.h> 61 #include <sys/namei.h> 62 #include <sys/sysctl.h> 63 64 #include <vm/vm.h> 65 #include <vm/pmap.h> 66 #include <vm/vm_map.h> 67 #include <vm/vm_object.h> 68 69 #include <sys/mac_policy.h> 70 71 #include <fs/devfs/devfs.h> 72 73 #include <security/mac/mac_internal.h> 74 75 /* 76 * Warn about EA transactions only the first time they happen. 77 * Weak coherency, no locking. 78 */ 79 static int ea_warn_once = 0; 80 81 static int mac_enforce_fs = 1; 82 SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 83 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 84 TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 85 86 #ifdef MAC_DEBUG 87 static int mac_debug_label_fallback = 0; 88 SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 89 &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 90 "when label is corrupted."); 91 TUNABLE_INT("security.mac.debug_label_fallback", 92 &mac_debug_label_fallback); 93 94 static unsigned int nmacmounts, nmacvnodes, nmacdevfsdirents; 95 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 96 &nmacmounts, 0, "number of mounts in use"); 97 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 98 &nmacvnodes, 0, "number of vnodes in use"); 99 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 100 &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 101 #endif 102 103 static int mac_setlabel_vnode_extattr(struct ucred *cred, 104 struct vnode *vp, struct label *intlabel); 105 106 static struct label * 107 mac_devfsdirent_label_alloc(void) 108 { 109 struct label *label; 110 111 label = mac_labelzone_alloc(M_WAITOK); 112 MAC_PERFORM(init_devfsdirent_label, label); 113 MAC_DEBUG_COUNTER_INC(&nmacdevfsdirents); 114 return (label); 115 } 116 117 void 118 mac_init_devfsdirent(struct devfs_dirent *de) 119 { 120 121 de->de_label = mac_devfsdirent_label_alloc(); 122 } 123 124 static struct label * 125 mac_mount_label_alloc(void) 126 { 127 struct label *label; 128 129 label = mac_labelzone_alloc(M_WAITOK); 130 MAC_PERFORM(init_mount_label, label); 131 MAC_DEBUG_COUNTER_INC(&nmacmounts); 132 return (label); 133 } 134 135 static struct label * 136 mac_mount_fs_label_alloc(void) 137 { 138 struct label *label; 139 140 label = mac_labelzone_alloc(M_WAITOK); 141 MAC_PERFORM(init_mount_fs_label, label); 142 MAC_DEBUG_COUNTER_INC(&nmacmounts); 143 return (label); 144 } 145 146 void 147 mac_init_mount(struct mount *mp) 148 { 149 150 mp->mnt_mntlabel = mac_mount_label_alloc(); 151 mp->mnt_fslabel = mac_mount_fs_label_alloc(); 152 } 153 154 struct label * 155 mac_vnode_label_alloc(void) 156 { 157 struct label *label; 158 159 label = mac_labelzone_alloc(M_WAITOK); 160 MAC_PERFORM(init_vnode_label, label); 161 MAC_DEBUG_COUNTER_INC(&nmacvnodes); 162 return (label); 163 } 164 165 void 166 mac_init_vnode(struct vnode *vp) 167 { 168 169 vp->v_label = mac_vnode_label_alloc(); 170 } 171 172 static void 173 mac_devfsdirent_label_free(struct label *label) 174 { 175 176 MAC_PERFORM(destroy_devfsdirent_label, label); 177 mac_labelzone_free(label); 178 MAC_DEBUG_COUNTER_DEC(&nmacdevfsdirents); 179 } 180 181 void 182 mac_destroy_devfsdirent(struct devfs_dirent *de) 183 { 184 185 mac_devfsdirent_label_free(de->de_label); 186 de->de_label = NULL; 187 } 188 189 static void 190 mac_mount_label_free(struct label *label) 191 { 192 193 MAC_PERFORM(destroy_mount_label, label); 194 mac_labelzone_free(label); 195 MAC_DEBUG_COUNTER_DEC(&nmacmounts); 196 } 197 198 static void 199 mac_mount_fs_label_free(struct label *label) 200 { 201 202 MAC_PERFORM(destroy_mount_fs_label, label); 203 mac_labelzone_free(label); 204 MAC_DEBUG_COUNTER_DEC(&nmacmounts); 205 } 206 207 void 208 mac_destroy_mount(struct mount *mp) 209 { 210 211 mac_mount_fs_label_free(mp->mnt_fslabel); 212 mp->mnt_fslabel = NULL; 213 mac_mount_label_free(mp->mnt_mntlabel); 214 mp->mnt_mntlabel = NULL; 215 } 216 217 void 218 mac_vnode_label_free(struct label *label) 219 { 220 221 MAC_PERFORM(destroy_vnode_label, label); 222 mac_labelzone_free(label); 223 MAC_DEBUG_COUNTER_DEC(&nmacvnodes); 224 } 225 226 void 227 mac_destroy_vnode(struct vnode *vp) 228 { 229 230 mac_vnode_label_free(vp->v_label); 231 vp->v_label = NULL; 232 } 233 234 void 235 mac_copy_vnode_label(struct label *src, struct label *dest) 236 { 237 238 MAC_PERFORM(copy_vnode_label, src, dest); 239 } 240 241 int 242 mac_externalize_vnode_label(struct label *label, char *elements, 243 char *outbuf, size_t outbuflen) 244 { 245 int error; 246 247 MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen); 248 249 return (error); 250 } 251 252 int 253 mac_internalize_vnode_label(struct label *label, char *string) 254 { 255 int error; 256 257 MAC_INTERNALIZE(vnode, label, string); 258 259 return (error); 260 } 261 262 void 263 mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de, 264 struct vnode *vp) 265 { 266 267 MAC_PERFORM(update_devfsdirent, mp, de, de->de_label, vp, 268 vp->v_label); 269 } 270 271 void 272 mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 273 struct vnode *vp) 274 { 275 276 MAC_PERFORM(associate_vnode_devfs, mp, mp->mnt_fslabel, de, 277 de->de_label, vp, vp->v_label); 278 } 279 280 int 281 mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 282 { 283 int error; 284 285 ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 286 287 MAC_CHECK(associate_vnode_extattr, mp, mp->mnt_fslabel, vp, 288 vp->v_label); 289 290 return (error); 291 } 292 293 void 294 mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 295 { 296 297 MAC_PERFORM(associate_vnode_singlelabel, mp, mp->mnt_fslabel, vp, 298 vp->v_label); 299 } 300 301 int 302 mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 303 struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 304 { 305 int error; 306 307 ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 308 ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 309 310 error = VOP_OPENEXTATTR(vp, cred, curthread); 311 if (error == EOPNOTSUPP) { 312 /* XXX: Optionally abort if transactions not supported. */ 313 if (ea_warn_once == 0) { 314 printf("Warning: transactions not supported " 315 "in EA write.\n"); 316 ea_warn_once = 1; 317 } 318 } else if (error) 319 return (error); 320 321 MAC_CHECK(create_vnode_extattr, cred, mp, mp->mnt_fslabel, 322 dvp, dvp->v_label, vp, vp->v_label, cnp); 323 324 if (error) { 325 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 326 return (error); 327 } 328 329 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 330 331 if (error == EOPNOTSUPP) 332 error = 0; /* XXX */ 333 334 return (error); 335 } 336 337 static int 338 mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 339 struct label *intlabel) 340 { 341 int error; 342 343 ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 344 345 error = VOP_OPENEXTATTR(vp, cred, curthread); 346 if (error == EOPNOTSUPP) { 347 /* XXX: Optionally abort if transactions not supported. */ 348 if (ea_warn_once == 0) { 349 printf("Warning: transactions not supported " 350 "in EA write.\n"); 351 ea_warn_once = 1; 352 } 353 } else if (error) 354 return (error); 355 356 MAC_CHECK(setlabel_vnode_extattr, cred, vp, vp->v_label, intlabel); 357 358 if (error) { 359 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 360 return (error); 361 } 362 363 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 364 365 if (error == EOPNOTSUPP) 366 error = 0; /* XXX */ 367 368 return (error); 369 } 370 371 void 372 mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, 373 struct label *interpvnodelabel, struct image_params *imgp) 374 { 375 376 ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 377 378 if (!mac_enforce_process && !mac_enforce_fs) 379 return; 380 381 MAC_PERFORM(execve_transition, old, new, vp, vp->v_label, 382 interpvnodelabel, imgp, imgp->execlabel); 383 } 384 385 int 386 mac_execve_will_transition(struct ucred *old, struct vnode *vp, 387 struct label *interpvnodelabel, struct image_params *imgp) 388 { 389 int result; 390 391 ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 392 393 if (!mac_enforce_process && !mac_enforce_fs) 394 return (0); 395 396 result = 0; 397 MAC_BOOLEAN(execve_will_transition, ||, old, vp, vp->v_label, 398 interpvnodelabel, imgp, imgp->execlabel); 399 400 return (result); 401 } 402 403 int 404 mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 405 { 406 int error; 407 408 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 409 410 if (!mac_enforce_fs) 411 return (0); 412 413 MAC_CHECK(check_vnode_access, cred, vp, vp->v_label, acc_mode); 414 return (error); 415 } 416 417 int 418 mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 419 { 420 int error; 421 422 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 423 424 if (!mac_enforce_fs) 425 return (0); 426 427 MAC_CHECK(check_vnode_chdir, cred, dvp, dvp->v_label); 428 return (error); 429 } 430 431 int 432 mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 433 { 434 int error; 435 436 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 437 438 if (!mac_enforce_fs) 439 return (0); 440 441 MAC_CHECK(check_vnode_chroot, cred, dvp, dvp->v_label); 442 return (error); 443 } 444 445 int 446 mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 447 struct componentname *cnp, struct vattr *vap) 448 { 449 int error; 450 451 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 452 453 if (!mac_enforce_fs) 454 return (0); 455 456 MAC_CHECK(check_vnode_create, cred, dvp, dvp->v_label, cnp, vap); 457 return (error); 458 } 459 460 int 461 mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 462 struct componentname *cnp) 463 { 464 int error; 465 466 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 467 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 468 469 if (!mac_enforce_fs) 470 return (0); 471 472 MAC_CHECK(check_vnode_delete, cred, dvp, dvp->v_label, vp, 473 vp->v_label, cnp); 474 return (error); 475 } 476 477 int 478 mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 479 acl_type_t type) 480 { 481 int error; 482 483 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 484 485 if (!mac_enforce_fs) 486 return (0); 487 488 MAC_CHECK(check_vnode_deleteacl, cred, vp, vp->v_label, type); 489 return (error); 490 } 491 492 int 493 mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, 494 int attrnamespace, const char *name) 495 { 496 int error; 497 498 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr"); 499 500 if (!mac_enforce_fs) 501 return (0); 502 503 MAC_CHECK(check_vnode_deleteextattr, cred, vp, vp->v_label, 504 attrnamespace, name); 505 return (error); 506 } 507 508 int 509 mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, 510 struct image_params *imgp) 511 { 512 int error; 513 514 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 515 516 if (!mac_enforce_process && !mac_enforce_fs) 517 return (0); 518 519 MAC_CHECK(check_vnode_exec, cred, vp, vp->v_label, imgp, 520 imgp->execlabel); 521 522 return (error); 523 } 524 525 int 526 mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 527 { 528 int error; 529 530 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 531 532 if (!mac_enforce_fs) 533 return (0); 534 535 MAC_CHECK(check_vnode_getacl, cred, vp, vp->v_label, type); 536 return (error); 537 } 538 539 int 540 mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 541 int attrnamespace, const char *name, struct uio *uio) 542 { 543 int error; 544 545 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 546 547 if (!mac_enforce_fs) 548 return (0); 549 550 MAC_CHECK(check_vnode_getextattr, cred, vp, vp->v_label, 551 attrnamespace, name, uio); 552 return (error); 553 } 554 555 int 556 mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 557 struct vnode *vp, struct componentname *cnp) 558 { 559 int error; 560 561 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 562 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 563 564 if (!mac_enforce_fs) 565 return (0); 566 567 MAC_CHECK(check_vnode_link, cred, dvp, dvp->v_label, vp, 568 vp->v_label, cnp); 569 return (error); 570 } 571 572 int 573 mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, 574 int attrnamespace) 575 { 576 int error; 577 578 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr"); 579 580 if (!mac_enforce_fs) 581 return (0); 582 583 MAC_CHECK(check_vnode_listextattr, cred, vp, vp->v_label, 584 attrnamespace); 585 return (error); 586 } 587 588 int 589 mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 590 struct componentname *cnp) 591 { 592 int error; 593 594 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 595 596 if (!mac_enforce_fs) 597 return (0); 598 599 MAC_CHECK(check_vnode_lookup, cred, dvp, dvp->v_label, cnp); 600 return (error); 601 } 602 603 int 604 mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, 605 int prot, int flags) 606 { 607 int error; 608 609 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 610 611 if (!mac_enforce_fs || !mac_enforce_vm) 612 return (0); 613 614 MAC_CHECK(check_vnode_mmap, cred, vp, vp->v_label, prot, flags); 615 return (error); 616 } 617 618 void 619 mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 620 { 621 int result = *prot; 622 623 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 624 625 if (!mac_enforce_fs || !mac_enforce_vm) 626 return; 627 628 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, vp->v_label, 629 &result); 630 631 *prot = result; 632 } 633 634 int 635 mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 636 { 637 int error; 638 639 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 640 641 if (!mac_enforce_fs || !mac_enforce_vm) 642 return (0); 643 644 MAC_CHECK(check_vnode_mprotect, cred, vp, vp->v_label, prot); 645 return (error); 646 } 647 648 int 649 mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 650 { 651 int error; 652 653 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 654 655 if (!mac_enforce_fs) 656 return (0); 657 658 MAC_CHECK(check_vnode_open, cred, vp, vp->v_label, acc_mode); 659 return (error); 660 } 661 662 int 663 mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 664 struct vnode *vp) 665 { 666 int error; 667 668 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 669 670 if (!mac_enforce_fs) 671 return (0); 672 673 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 674 vp->v_label); 675 676 return (error); 677 } 678 679 int 680 mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 681 struct vnode *vp) 682 { 683 int error; 684 685 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 686 687 if (!mac_enforce_fs) 688 return (0); 689 690 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 691 vp->v_label); 692 693 return (error); 694 } 695 696 int 697 mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 698 { 699 int error; 700 701 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 702 703 if (!mac_enforce_fs) 704 return (0); 705 706 MAC_CHECK(check_vnode_readdir, cred, dvp, dvp->v_label); 707 return (error); 708 } 709 710 int 711 mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 712 { 713 int error; 714 715 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 716 717 if (!mac_enforce_fs) 718 return (0); 719 720 MAC_CHECK(check_vnode_readlink, cred, vp, vp->v_label); 721 return (error); 722 } 723 724 static int 725 mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 726 struct label *newlabel) 727 { 728 int error; 729 730 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 731 732 MAC_CHECK(check_vnode_relabel, cred, vp, vp->v_label, newlabel); 733 734 return (error); 735 } 736 737 int 738 mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 739 struct vnode *vp, struct componentname *cnp) 740 { 741 int error; 742 743 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 744 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 745 746 if (!mac_enforce_fs) 747 return (0); 748 749 MAC_CHECK(check_vnode_rename_from, cred, dvp, dvp->v_label, vp, 750 vp->v_label, cnp); 751 return (error); 752 } 753 754 int 755 mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 756 struct vnode *vp, int samedir, struct componentname *cnp) 757 { 758 int error; 759 760 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 761 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 762 763 if (!mac_enforce_fs) 764 return (0); 765 766 MAC_CHECK(check_vnode_rename_to, cred, dvp, dvp->v_label, vp, 767 vp != NULL ? vp->v_label : NULL, samedir, cnp); 768 return (error); 769 } 770 771 int 772 mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 773 { 774 int error; 775 776 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 777 778 if (!mac_enforce_fs) 779 return (0); 780 781 MAC_CHECK(check_vnode_revoke, cred, vp, vp->v_label); 782 return (error); 783 } 784 785 int 786 mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 787 struct acl *acl) 788 { 789 int error; 790 791 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 792 793 if (!mac_enforce_fs) 794 return (0); 795 796 MAC_CHECK(check_vnode_setacl, cred, vp, vp->v_label, type, acl); 797 return (error); 798 } 799 800 int 801 mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 802 int attrnamespace, const char *name, struct uio *uio) 803 { 804 int error; 805 806 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 807 808 if (!mac_enforce_fs) 809 return (0); 810 811 MAC_CHECK(check_vnode_setextattr, cred, vp, vp->v_label, 812 attrnamespace, name, uio); 813 return (error); 814 } 815 816 int 817 mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 818 { 819 int error; 820 821 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 822 823 if (!mac_enforce_fs) 824 return (0); 825 826 MAC_CHECK(check_vnode_setflags, cred, vp, vp->v_label, flags); 827 return (error); 828 } 829 830 int 831 mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 832 { 833 int error; 834 835 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 836 837 if (!mac_enforce_fs) 838 return (0); 839 840 MAC_CHECK(check_vnode_setmode, cred, vp, vp->v_label, mode); 841 return (error); 842 } 843 844 int 845 mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 846 gid_t gid) 847 { 848 int error; 849 850 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 851 852 if (!mac_enforce_fs) 853 return (0); 854 855 MAC_CHECK(check_vnode_setowner, cred, vp, vp->v_label, uid, gid); 856 return (error); 857 } 858 859 int 860 mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 861 struct timespec atime, struct timespec mtime) 862 { 863 int error; 864 865 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 866 867 if (!mac_enforce_fs) 868 return (0); 869 870 MAC_CHECK(check_vnode_setutimes, cred, vp, vp->v_label, atime, 871 mtime); 872 return (error); 873 } 874 875 int 876 mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 877 struct vnode *vp) 878 { 879 int error; 880 881 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 882 883 if (!mac_enforce_fs) 884 return (0); 885 886 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 887 vp->v_label); 888 return (error); 889 } 890 891 int 892 mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 893 struct vnode *vp) 894 { 895 int error; 896 897 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 898 899 if (!mac_enforce_fs) 900 return (0); 901 902 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 903 vp->v_label); 904 905 return (error); 906 } 907 908 void 909 mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 910 { 911 912 MAC_PERFORM(relabel_vnode, cred, vp, vp->v_label, newlabel); 913 } 914 915 void 916 mac_create_mount(struct ucred *cred, struct mount *mp) 917 { 918 919 MAC_PERFORM(create_mount, cred, mp, mp->mnt_mntlabel, 920 mp->mnt_fslabel); 921 } 922 923 int 924 mac_check_mount_stat(struct ucred *cred, struct mount *mount) 925 { 926 int error; 927 928 if (!mac_enforce_fs) 929 return (0); 930 931 MAC_CHECK(check_mount_stat, cred, mount, mount->mnt_mntlabel); 932 933 return (error); 934 } 935 936 void 937 mac_create_devfs_device(struct ucred *cred, struct mount *mp, 938 struct cdev *dev, struct devfs_dirent *de) 939 { 940 941 MAC_PERFORM(create_devfs_device, cred, mp, dev, de, de->de_label); 942 } 943 944 void 945 mac_create_devfs_symlink(struct ucred *cred, struct mount *mp, 946 struct devfs_dirent *dd, struct devfs_dirent *de) 947 { 948 949 MAC_PERFORM(create_devfs_symlink, cred, mp, dd, dd->de_label, de, 950 de->de_label); 951 } 952 953 void 954 mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, 955 struct devfs_dirent *de) 956 { 957 958 MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de, 959 de->de_label); 960 } 961 962 /* 963 * Implementation of VOP_SETLABEL() that relies on extended attributes 964 * to store label data. Can be referenced by filesystems supporting 965 * extended attributes. 966 */ 967 int 968 vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 969 { 970 struct vnode *vp = ap->a_vp; 971 struct label *intlabel = ap->a_label; 972 int error; 973 974 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 975 976 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 977 return (EOPNOTSUPP); 978 979 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 980 if (error) 981 return (error); 982 983 mac_relabel_vnode(ap->a_cred, vp, intlabel); 984 985 return (0); 986 } 987 988 int 989 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 990 { 991 int error; 992 993 if (vp->v_mount == NULL) { 994 /* printf("vn_setlabel: null v_mount\n"); */ 995 if (vp->v_type != VNON) 996 printf("vn_setlabel: null v_mount with non-VNON\n"); 997 return (EBADF); 998 } 999 1000 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 1001 return (EOPNOTSUPP); 1002 1003 /* 1004 * Multi-phase commit. First check the policies to confirm the 1005 * change is OK. Then commit via the filesystem. Finally, 1006 * update the actual vnode label. Question: maybe the filesystem 1007 * should update the vnode at the end as part of VOP_SETLABEL()? 1008 */ 1009 error = mac_check_vnode_relabel(cred, vp, intlabel); 1010 if (error) 1011 return (error); 1012 1013 /* 1014 * VADMIN provides the opportunity for the filesystem to make 1015 * decisions about who is and is not able to modify labels 1016 * and protections on files. This might not be right. We can't 1017 * assume VOP_SETLABEL() will do it, because we might implement 1018 * that as part of vop_stdsetlabel_ea(). 1019 */ 1020 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 1021 if (error) 1022 return (error); 1023 1024 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 1025 if (error) 1026 return (error); 1027 1028 return (0); 1029 } 1030 1031 void 1032 mac_associate_nfsd_label(struct ucred *cred) 1033 { 1034 1035 MAC_PERFORM(associate_nfsd_label, cred); 1036 } 1037