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