mac_vfs.c revision 121367
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: head/sys/security/mac/mac_vfs.c 121367 2003-10-22 20:29:41Z rwatson $"); 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 */ 76static int ea_warn_once = 0; 77 78static int mac_enforce_fs = 1; 79SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 80 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 81TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 82 83#ifdef MAC_DEBUG 84static int mac_debug_label_fallback = 0; 85SYSCTL_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."); 88TUNABLE_INT("security.mac.debug_label_fallback", 89 &mac_debug_label_fallback); 90 91static unsigned int nmacmounts, nmacvnodes, nmacdevfsdirents; 92SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 93 &nmacmounts, 0, "number of mounts in use"); 94SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 95 &nmacvnodes, 0, "number of vnodes in use"); 96SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 97 &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 98#endif 99 100static int mac_setlabel_vnode_extattr(struct ucred *cred, 101 struct vnode *vp, struct label *intlabel); 102 103void 104mac_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 112void 113mac_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 123void 124mac_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 132void 133mac_init_vnode(struct vnode *vp) 134{ 135 136 mac_init_vnode_label(&vp->v_label); 137} 138 139void 140mac_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 148void 149mac_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 159void 160mac_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 168void 169mac_destroy_vnode(struct vnode *vp) 170{ 171 172 mac_destroy_vnode_label(&vp->v_label); 173} 174 175void 176mac_copy_vnode_label(struct label *src, struct label *dest) 177{ 178 179 MAC_PERFORM(copy_vnode_label, src, dest); 180} 181 182int 183mac_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 193int 194mac_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 203void 204mac_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 212void 213mac_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 221int 222mac_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 234void 235mac_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 242int 243mac_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 278static int 279mac_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 312void 313mac_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 326int 327mac_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 344int 345mac_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 358int 359mac_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 372int 373mac_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 386int 387mac_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 401int 402mac_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 418int 419mac_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 433int 434mac_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 449int 450mac_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 466int 467mac_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 480int 481mac_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 496int 497mac_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 513int 514mac_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 529int 530mac_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 544int 545mac_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 558void 559mac_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 574int 575mac_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 588int 589mac_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 602int 603mac_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 619int 620mac_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 636int 637mac_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 650int 651mac_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 664static int 665mac_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 677int 678mac_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 694int 695mac_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 711int 712mac_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 725int 726mac_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 740int 741mac_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 756int 757mac_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 770int 771mac_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 784int 785mac_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 799int 800mac_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 815int 816mac_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 831int 832mac_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 848void 849mac_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 855void 856mac_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 863void 864mac_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 871int 872mac_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 884void 885mac_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 891void 892mac_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 900void 901mac_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 */ 914int 915vop_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 935int 936vn_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