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