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