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