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