1 /*- 2 * Copyright (c) 1999-2002, 2009 Robert N. M. Watson 3 * Copyright (c) 2001 Ilmar S. Habibulin 4 * Copyright (c) 2001-2005 McAfee, Inc. 5 * Copyright (c) 2005-2006 SPARTA, Inc. 6 * Copyright (c) 2008 Apple Inc. 7 * All rights reserved. 8 * 9 * This software was developed by Robert Watson and Ilmar Habibulin for the 10 * TrustedBSD Project. 11 * 12 * This software was developed for the FreeBSD Project in part by McAfee 13 * Research, the Security Research Division of McAfee, Inc. under 14 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 15 * CHATS research program. 16 * 17 * This software was enhanced by SPARTA ISSO under SPAWAR contract 18 * N66001-04-C-6019 ("SEFOS"). 19 * 20 * This software was developed at the University of Cambridge Computer 21 * Laboratory with support from a grant from Google, Inc. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 */ 44 45 #include <sys/cdefs.h> 46 __FBSDID("$FreeBSD$"); 47 48 #include "opt_mac.h" 49 50 #include <sys/param.h> 51 #include <sys/condvar.h> 52 #include <sys/extattr.h> 53 #include <sys/imgact.h> 54 #include <sys/kernel.h> 55 #include <sys/lock.h> 56 #include <sys/malloc.h> 57 #include <sys/mutex.h> 58 #include <sys/proc.h> 59 #include <sys/sbuf.h> 60 #include <sys/systm.h> 61 #include <sys/vnode.h> 62 #include <sys/mount.h> 63 #include <sys/file.h> 64 #include <sys/namei.h> 65 #include <sys/sdt.h> 66 #include <sys/sysctl.h> 67 68 #include <vm/vm.h> 69 #include <vm/pmap.h> 70 #include <vm/vm_map.h> 71 #include <vm/vm_object.h> 72 73 #include <fs/devfs/devfs.h> 74 75 #include <security/mac/mac_framework.h> 76 #include <security/mac/mac_internal.h> 77 #include <security/mac/mac_policy.h> 78 79 /* 80 * Warn about EA transactions only the first time they happen. No locking on 81 * this variable. 82 */ 83 static int ea_warn_once = 0; 84 85 static int mac_vnode_setlabel_extattr(struct ucred *cred, 86 struct vnode *vp, struct label *intlabel); 87 88 static struct label * 89 mac_devfs_label_alloc(void) 90 { 91 struct label *label; 92 93 label = mac_labelzone_alloc(M_WAITOK); 94 MAC_POLICY_PERFORM(devfs_init_label, label); 95 return (label); 96 } 97 98 void 99 mac_devfs_init(struct devfs_dirent *de) 100 { 101 102 if (mac_labeled & MPC_OBJECT_DEVFS) 103 de->de_label = mac_devfs_label_alloc(); 104 else 105 de->de_label = NULL; 106 } 107 108 static struct label * 109 mac_mount_label_alloc(void) 110 { 111 struct label *label; 112 113 label = mac_labelzone_alloc(M_WAITOK); 114 MAC_POLICY_PERFORM(mount_init_label, label); 115 return (label); 116 } 117 118 void 119 mac_mount_init(struct mount *mp) 120 { 121 122 if (mac_labeled & MPC_OBJECT_MOUNT) 123 mp->mnt_label = mac_mount_label_alloc(); 124 else 125 mp->mnt_label = NULL; 126 } 127 128 struct label * 129 mac_vnode_label_alloc(void) 130 { 131 struct label *label; 132 133 label = mac_labelzone_alloc(M_WAITOK); 134 MAC_POLICY_PERFORM(vnode_init_label, label); 135 return (label); 136 } 137 138 void 139 mac_vnode_init(struct vnode *vp) 140 { 141 142 if (mac_labeled & MPC_OBJECT_VNODE) 143 vp->v_label = mac_vnode_label_alloc(); 144 else 145 vp->v_label = NULL; 146 } 147 148 static void 149 mac_devfs_label_free(struct label *label) 150 { 151 152 MAC_POLICY_PERFORM_NOSLEEP(devfs_destroy_label, label); 153 mac_labelzone_free(label); 154 } 155 156 void 157 mac_devfs_destroy(struct devfs_dirent *de) 158 { 159 160 if (de->de_label != NULL) { 161 mac_devfs_label_free(de->de_label); 162 de->de_label = NULL; 163 } 164 } 165 166 static void 167 mac_mount_label_free(struct label *label) 168 { 169 170 MAC_POLICY_PERFORM_NOSLEEP(mount_destroy_label, label); 171 mac_labelzone_free(label); 172 } 173 174 void 175 mac_mount_destroy(struct mount *mp) 176 { 177 178 if (mp->mnt_label != NULL) { 179 mac_mount_label_free(mp->mnt_label); 180 mp->mnt_label = NULL; 181 } 182 } 183 184 void 185 mac_vnode_label_free(struct label *label) 186 { 187 188 MAC_POLICY_PERFORM_NOSLEEP(vnode_destroy_label, label); 189 mac_labelzone_free(label); 190 } 191 192 void 193 mac_vnode_destroy(struct vnode *vp) 194 { 195 196 if (vp->v_label != NULL) { 197 mac_vnode_label_free(vp->v_label); 198 vp->v_label = NULL; 199 } 200 } 201 202 void 203 mac_vnode_copy_label(struct label *src, struct label *dest) 204 { 205 206 MAC_POLICY_PERFORM_NOSLEEP(vnode_copy_label, src, dest); 207 } 208 209 int 210 mac_vnode_externalize_label(struct label *label, char *elements, 211 char *outbuf, size_t outbuflen) 212 { 213 int error; 214 215 MAC_POLICY_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen); 216 217 return (error); 218 } 219 220 int 221 mac_vnode_internalize_label(struct label *label, char *string) 222 { 223 int error; 224 225 MAC_POLICY_INTERNALIZE(vnode, label, string); 226 227 return (error); 228 } 229 230 void 231 mac_devfs_update(struct mount *mp, struct devfs_dirent *de, struct vnode *vp) 232 { 233 234 MAC_POLICY_PERFORM_NOSLEEP(devfs_update, mp, de, de->de_label, vp, 235 vp->v_label); 236 } 237 238 void 239 mac_devfs_vnode_associate(struct mount *mp, struct devfs_dirent *de, 240 struct vnode *vp) 241 { 242 243 MAC_POLICY_PERFORM_NOSLEEP(devfs_vnode_associate, mp, mp->mnt_label, 244 de, de->de_label, vp, vp->v_label); 245 } 246 247 int 248 mac_vnode_associate_extattr(struct mount *mp, struct vnode *vp) 249 { 250 int error; 251 252 ASSERT_VOP_LOCKED(vp, "mac_vnode_associate_extattr"); 253 254 MAC_POLICY_CHECK(vnode_associate_extattr, mp, mp->mnt_label, vp, 255 vp->v_label); 256 257 return (error); 258 } 259 260 void 261 mac_vnode_associate_singlelabel(struct mount *mp, struct vnode *vp) 262 { 263 264 MAC_POLICY_PERFORM_NOSLEEP(vnode_associate_singlelabel, mp, 265 mp->mnt_label, vp, vp->v_label); 266 } 267 268 /* 269 * Functions implementing extended-attribute backed labels for file systems 270 * that support it. 271 * 272 * Where possible, we use EA transactions to make writes to multiple 273 * attributes across difference policies mutually atomic. We allow work to 274 * continue on file systems not supporting EA transactions, but generate a 275 * printf warning. 276 */ 277 int 278 mac_vnode_create_extattr(struct ucred *cred, struct mount *mp, 279 struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 280 { 281 int error; 282 283 ASSERT_VOP_LOCKED(dvp, "mac_vnode_create_extattr"); 284 ASSERT_VOP_LOCKED(vp, "mac_vnode_create_extattr"); 285 286 error = VOP_OPENEXTATTR(vp, cred, curthread); 287 if (error == EOPNOTSUPP) { 288 if (ea_warn_once == 0) { 289 printf("Warning: transactions not supported " 290 "in EA write.\n"); 291 ea_warn_once = 1; 292 } 293 } else if (error) 294 return (error); 295 296 MAC_POLICY_CHECK(vnode_create_extattr, cred, mp, mp->mnt_label, dvp, 297 dvp->v_label, vp, vp->v_label, cnp); 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 if (error == EOPNOTSUPP) 306 error = 0; 307 308 return (error); 309 } 310 311 static int 312 mac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp, 313 struct label *intlabel) 314 { 315 int error; 316 317 ASSERT_VOP_LOCKED(vp, "mac_vnode_setlabel_extattr"); 318 319 error = VOP_OPENEXTATTR(vp, cred, curthread); 320 if (error == EOPNOTSUPP) { 321 if (ea_warn_once == 0) { 322 printf("Warning: transactions not supported " 323 "in EA write.\n"); 324 ea_warn_once = 1; 325 } 326 } else if (error) 327 return (error); 328 329 MAC_POLICY_CHECK(vnode_setlabel_extattr, cred, vp, vp->v_label, 330 intlabel); 331 332 if (error) { 333 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 334 return (error); 335 } 336 337 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 338 if (error == EOPNOTSUPP) 339 error = 0; 340 341 return (error); 342 } 343 344 void 345 mac_vnode_execve_transition(struct ucred *old, struct ucred *new, 346 struct vnode *vp, struct label *interpvplabel, struct image_params *imgp) 347 { 348 349 ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_transition"); 350 351 MAC_POLICY_PERFORM(vnode_execve_transition, old, new, vp, 352 vp->v_label, interpvplabel, imgp, imgp->execlabel); 353 } 354 355 int 356 mac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp, 357 struct label *interpvplabel, struct image_params *imgp) 358 { 359 int result; 360 361 ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_will_transition"); 362 363 result = 0; 364 /* No sleeping since the process lock will be held by the caller. */ 365 MAC_POLICY_BOOLEAN_NOSLEEP(vnode_execve_will_transition, ||, old, vp, 366 vp->v_label, interpvplabel, imgp, imgp->execlabel); 367 368 return (result); 369 } 370 371 MAC_CHECK_PROBE_DEFINE3(vnode_check_access, "struct ucred *", 372 "struct vnode *", "accmode_t"); 373 374 int 375 mac_vnode_check_access_impl(struct ucred *cred, struct vnode *vp, accmode_t accmode) 376 { 377 int error; 378 379 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_access"); 380 381 MAC_POLICY_CHECK(vnode_check_access, cred, vp, vp->v_label, accmode); 382 MAC_CHECK_PROBE3(vnode_check_access, error, cred, vp, accmode); 383 384 return (error); 385 } 386 387 MAC_CHECK_PROBE_DEFINE2(vnode_check_chdir, "struct ucred *", 388 "struct vnode *"); 389 390 int 391 mac_vnode_check_chdir(struct ucred *cred, struct vnode *dvp) 392 { 393 int error; 394 395 ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_chdir"); 396 397 MAC_POLICY_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label); 398 MAC_CHECK_PROBE2(vnode_check_chdir, error, cred, dvp); 399 400 return (error); 401 } 402 403 MAC_CHECK_PROBE_DEFINE2(vnode_check_chroot, "struct ucred *", 404 "struct vnode *"); 405 406 int 407 mac_vnode_check_chroot(struct ucred *cred, struct vnode *dvp) 408 { 409 int error; 410 411 ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_chroot"); 412 413 MAC_POLICY_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label); 414 MAC_CHECK_PROBE2(vnode_check_chroot, error, cred, dvp); 415 416 return (error); 417 } 418 419 MAC_CHECK_PROBE_DEFINE4(vnode_check_create, "struct ucred *", 420 "struct vnode *", "struct componentname *", "struct vattr *"); 421 422 int 423 mac_vnode_check_create(struct ucred *cred, struct vnode *dvp, 424 struct componentname *cnp, struct vattr *vap) 425 { 426 int error; 427 428 ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_create"); 429 430 MAC_POLICY_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, 431 vap); 432 MAC_CHECK_PROBE4(vnode_check_create, error, cred, dvp, cnp, vap); 433 434 return (error); 435 } 436 437 MAC_CHECK_PROBE_DEFINE3(vnode_check_deleteacl, "struct ucred *", 438 "struct vnode *", "acl_type_t"); 439 440 int 441 mac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 442 acl_type_t type) 443 { 444 int error; 445 446 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_deleteacl"); 447 448 MAC_POLICY_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type); 449 MAC_CHECK_PROBE3(vnode_check_deleteacl, error, cred, vp, type); 450 451 return (error); 452 } 453 454 MAC_CHECK_PROBE_DEFINE4(vnode_check_deleteextattr, "struct ucred *", 455 "struct vnode *", "int", "const char *"); 456 457 int 458 mac_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp, 459 int attrnamespace, const char *name) 460 { 461 int error; 462 463 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_deleteextattr"); 464 465 MAC_POLICY_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, 466 attrnamespace, name); 467 MAC_CHECK_PROBE4(vnode_check_deleteextattr, error, cred, vp, 468 attrnamespace, name); 469 470 return (error); 471 } 472 473 MAC_CHECK_PROBE_DEFINE3(vnode_check_exec, "struct ucred *", "struct vnode *", 474 "struct image_params *"); 475 476 int 477 mac_vnode_check_exec(struct ucred *cred, struct vnode *vp, 478 struct image_params *imgp) 479 { 480 int error; 481 482 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_exec"); 483 484 MAC_POLICY_CHECK(vnode_check_exec, cred, vp, vp->v_label, imgp, 485 imgp->execlabel); 486 MAC_CHECK_PROBE3(vnode_check_exec, error, cred, vp, imgp); 487 488 return (error); 489 } 490 491 MAC_CHECK_PROBE_DEFINE3(vnode_check_getacl, "struct ucred *", 492 "struct vnode *", "acl_type_t"); 493 494 int 495 mac_vnode_check_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 496 { 497 int error; 498 499 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_getacl"); 500 501 MAC_POLICY_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type); 502 MAC_CHECK_PROBE3(vnode_check_getacl, error, cred, vp, type); 503 504 return (error); 505 } 506 507 MAC_CHECK_PROBE_DEFINE4(vnode_check_getextattr, "struct ucred *", 508 "struct vnode *", "int", "const char *"); 509 510 int 511 mac_vnode_check_getextattr(struct ucred *cred, struct vnode *vp, 512 int attrnamespace, const char *name) 513 { 514 int error; 515 516 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_getextattr"); 517 518 MAC_POLICY_CHECK(vnode_check_getextattr, cred, vp, vp->v_label, 519 attrnamespace, name); 520 MAC_CHECK_PROBE4(vnode_check_getextattr, error, cred, vp, 521 attrnamespace, name); 522 523 return (error); 524 } 525 526 MAC_CHECK_PROBE_DEFINE4(vnode_check_link, "struct ucred *", "struct vnode *", 527 "struct vnode *", "struct componentname *"); 528 529 int 530 mac_vnode_check_link(struct ucred *cred, struct vnode *dvp, 531 struct vnode *vp, struct componentname *cnp) 532 { 533 int error; 534 535 ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_link"); 536 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_link"); 537 538 MAC_POLICY_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp, 539 vp->v_label, cnp); 540 MAC_CHECK_PROBE4(vnode_check_link, error, cred, dvp, vp, cnp); 541 542 return (error); 543 } 544 545 MAC_CHECK_PROBE_DEFINE3(vnode_check_listextattr, "struct ucred *", 546 "struct vnode *", "int"); 547 548 int 549 mac_vnode_check_listextattr(struct ucred *cred, struct vnode *vp, 550 int attrnamespace) 551 { 552 int error; 553 554 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_listextattr"); 555 556 MAC_POLICY_CHECK(vnode_check_listextattr, cred, vp, vp->v_label, 557 attrnamespace); 558 MAC_CHECK_PROBE3(vnode_check_listextattr, error, cred, vp, 559 attrnamespace); 560 561 return (error); 562 } 563 564 MAC_CHECK_PROBE_DEFINE3(vnode_check_lookup, "struct ucred *", 565 "struct vnode *", "struct componentname *"); 566 567 int 568 mac_vnode_check_lookup_impl(struct ucred *cred, struct vnode *dvp, 569 struct componentname *cnp) 570 { 571 int error; 572 573 ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_lookup"); 574 575 if ((cnp->cn_flags & NOMACCHECK) != 0) 576 return (0); 577 MAC_POLICY_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp); 578 MAC_CHECK_PROBE3(vnode_check_lookup, error, cred, dvp, cnp); 579 580 return (error); 581 } 582 583 MAC_CHECK_PROBE_DEFINE4(vnode_check_mmap, "struct ucred *", "struct vnode *", 584 "int", "int"); 585 586 int 587 mac_vnode_check_mmap_impl(struct ucred *cred, struct vnode *vp, int prot, 588 int flags) 589 { 590 int error; 591 592 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mmap"); 593 594 MAC_POLICY_CHECK(vnode_check_mmap, cred, vp, vp->v_label, prot, flags); 595 MAC_CHECK_PROBE4(vnode_check_mmap, error, cred, vp, prot, flags); 596 597 return (error); 598 } 599 600 void 601 mac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, 602 int *prot) 603 { 604 int result = *prot; 605 606 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mmap_downgrade"); 607 608 MAC_POLICY_PERFORM(vnode_check_mmap_downgrade, cred, vp, vp->v_label, 609 &result); 610 611 *prot = result; 612 } 613 614 MAC_CHECK_PROBE_DEFINE3(vnode_check_mprotect, "struct ucred *", 615 "struct vnode *", "int"); 616 617 int 618 mac_vnode_check_mprotect(struct ucred *cred, struct vnode *vp, int prot) 619 { 620 int error; 621 622 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mprotect"); 623 624 MAC_POLICY_CHECK(vnode_check_mprotect, cred, vp, vp->v_label, prot); 625 MAC_CHECK_PROBE3(vnode_check_mprotect, error, cred, vp, prot); 626 627 return (error); 628 } 629 630 MAC_CHECK_PROBE_DEFINE3(vnode_check_open, "struct ucred *", "struct vnode *", 631 "accmode_t"); 632 633 int 634 mac_vnode_check_open_impl(struct ucred *cred, struct vnode *vp, accmode_t accmode) 635 { 636 int error; 637 638 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_open"); 639 640 MAC_POLICY_CHECK(vnode_check_open, cred, vp, vp->v_label, accmode); 641 MAC_CHECK_PROBE3(vnode_check_open, error, cred, vp, accmode); 642 643 return (error); 644 } 645 646 MAC_CHECK_PROBE_DEFINE3(vnode_check_poll, "struct ucred *", "struct ucred *", 647 "struct vnode *"); 648 649 int 650 mac_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred, 651 struct vnode *vp) 652 { 653 int error; 654 655 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_poll"); 656 657 MAC_POLICY_CHECK(vnode_check_poll, active_cred, file_cred, vp, 658 vp->v_label); 659 MAC_CHECK_PROBE3(vnode_check_poll, error, active_cred, file_cred, 660 vp); 661 662 return (error); 663 } 664 665 MAC_CHECK_PROBE_DEFINE3(vnode_check_read, "struct ucred *", "struct ucred *", 666 "struct vnode *"); 667 668 int 669 mac_vnode_check_read_impl(struct ucred *active_cred, struct ucred *file_cred, 670 struct vnode *vp) 671 { 672 int error; 673 674 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_read"); 675 676 MAC_POLICY_CHECK(vnode_check_read, active_cred, file_cred, vp, 677 vp->v_label); 678 MAC_CHECK_PROBE3(vnode_check_read, error, active_cred, file_cred, 679 vp); 680 681 return (error); 682 } 683 684 MAC_CHECK_PROBE_DEFINE2(vnode_check_readdir, "struct ucred *", 685 "struct vnode *"); 686 687 int 688 mac_vnode_check_readdir(struct ucred *cred, struct vnode *dvp) 689 { 690 int error; 691 692 ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_readdir"); 693 694 MAC_POLICY_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label); 695 MAC_CHECK_PROBE2(vnode_check_readdir, error, cred, dvp); 696 697 return (error); 698 } 699 700 MAC_CHECK_PROBE_DEFINE2(vnode_check_readlink, "struct ucred *", 701 "struct vnode *"); 702 703 int 704 mac_vnode_check_readlink_impl(struct ucred *cred, struct vnode *vp) 705 { 706 int error; 707 708 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_readlink"); 709 710 MAC_POLICY_CHECK(vnode_check_readlink, cred, vp, vp->v_label); 711 MAC_CHECK_PROBE2(vnode_check_readlink, error, cred, vp); 712 713 return (error); 714 } 715 716 MAC_CHECK_PROBE_DEFINE3(vnode_check_relabel, "struct ucred *", 717 "struct vnode *", "struct label *"); 718 719 static int 720 mac_vnode_check_relabel(struct ucred *cred, struct vnode *vp, 721 struct label *newlabel) 722 { 723 int error; 724 725 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_relabel"); 726 727 MAC_POLICY_CHECK(vnode_check_relabel, cred, vp, vp->v_label, newlabel); 728 MAC_CHECK_PROBE3(vnode_check_relabel, error, cred, vp, newlabel); 729 730 return (error); 731 } 732 733 MAC_CHECK_PROBE_DEFINE4(vnode_check_rename_from, "struct ucred *", 734 "struct vnode *", "struct vnode *", "struct componentname *"); 735 736 int 737 mac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 738 struct vnode *vp, struct componentname *cnp) 739 { 740 int error; 741 742 ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_rename_from"); 743 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_rename_from"); 744 745 MAC_POLICY_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp, 746 vp->v_label, cnp); 747 MAC_CHECK_PROBE4(vnode_check_rename_from, error, cred, dvp, vp, cnp); 748 749 return (error); 750 } 751 752 MAC_CHECK_PROBE_DEFINE4(vnode_check_rename_to, "struct ucred *", 753 "struct vnode *", "struct vnode *", "struct componentname *"); 754 755 int 756 mac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 757 struct vnode *vp, int samedir, struct componentname *cnp) 758 { 759 int error; 760 761 ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_rename_to"); 762 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_rename_to"); 763 764 MAC_POLICY_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp, 765 vp != NULL ? vp->v_label : NULL, samedir, cnp); 766 MAC_CHECK_PROBE4(vnode_check_rename_to, error, cred, dvp, vp, cnp); 767 return (error); 768 } 769 770 MAC_CHECK_PROBE_DEFINE2(vnode_check_revoke, "struct ucred *", 771 "struct vnode *"); 772 773 int 774 mac_vnode_check_revoke(struct ucred *cred, struct vnode *vp) 775 { 776 int error; 777 778 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_revoke"); 779 780 MAC_POLICY_CHECK(vnode_check_revoke, cred, vp, vp->v_label); 781 MAC_CHECK_PROBE2(vnode_check_revoke, error, cred, vp); 782 783 return (error); 784 } 785 786 MAC_CHECK_PROBE_DEFINE4(vnode_check_setacl, "struct ucred *", 787 "struct vnode *", "acl_type_t", "struct acl *"); 788 789 int 790 mac_vnode_check_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 791 struct acl *acl) 792 { 793 int error; 794 795 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setacl"); 796 797 MAC_POLICY_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl); 798 MAC_CHECK_PROBE4(vnode_check_setacl, error, cred, vp, type, acl); 799 800 return (error); 801 } 802 803 MAC_CHECK_PROBE_DEFINE4(vnode_check_setextattr, "struct ucred *", 804 "struct vnode *", "int", "const char *"); 805 806 int 807 mac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 808 int attrnamespace, const char *name) 809 { 810 int error; 811 812 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setextattr"); 813 814 MAC_POLICY_CHECK(vnode_check_setextattr, cred, vp, vp->v_label, 815 attrnamespace, name); 816 MAC_CHECK_PROBE4(vnode_check_setextattr, error, cred, vp, 817 attrnamespace, name); 818 819 return (error); 820 } 821 822 MAC_CHECK_PROBE_DEFINE3(vnode_check_setflags, "struct ucred *", 823 "struct vnode *", "u_long"); 824 825 int 826 mac_vnode_check_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 827 { 828 int error; 829 830 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setflags"); 831 832 MAC_POLICY_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags); 833 MAC_CHECK_PROBE3(vnode_check_setflags, error, cred, vp, flags); 834 835 return (error); 836 } 837 838 MAC_CHECK_PROBE_DEFINE3(vnode_check_setmode, "struct ucred *", 839 "struct vnode *", "mode_t"); 840 841 int 842 mac_vnode_check_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 843 { 844 int error; 845 846 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setmode"); 847 848 MAC_POLICY_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode); 849 MAC_CHECK_PROBE3(vnode_check_setmode, error, cred, vp, mode); 850 851 return (error); 852 } 853 854 MAC_CHECK_PROBE_DEFINE4(vnode_check_setowner, "struct ucred *", 855 "struct vnode *", "uid_t", "gid_t"); 856 857 int 858 mac_vnode_check_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 859 gid_t gid) 860 { 861 int error; 862 863 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setowner"); 864 865 MAC_POLICY_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid); 866 MAC_CHECK_PROBE4(vnode_check_setowner, error, cred, vp, uid, gid); 867 868 return (error); 869 } 870 871 MAC_CHECK_PROBE_DEFINE4(vnode_check_setutimes, "struct ucred *", 872 "struct vnode *", "struct timespec *", "struct timespec *"); 873 874 int 875 mac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 876 struct timespec atime, struct timespec mtime) 877 { 878 int error; 879 880 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setutimes"); 881 882 MAC_POLICY_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime, 883 mtime); 884 MAC_CHECK_PROBE4(vnode_check_setutimes, error, cred, vp, &atime, 885 &mtime); 886 887 return (error); 888 } 889 890 MAC_CHECK_PROBE_DEFINE3(vnode_check_stat, "struct ucred *", "struct ucred *", 891 "struct vnode *"); 892 893 int 894 mac_vnode_check_stat_impl(struct ucred *active_cred, struct ucred *file_cred, 895 struct vnode *vp) 896 { 897 int error; 898 899 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_stat"); 900 901 MAC_POLICY_CHECK(vnode_check_stat, active_cred, file_cred, vp, 902 vp->v_label); 903 MAC_CHECK_PROBE3(vnode_check_stat, error, active_cred, file_cred, 904 vp); 905 906 return (error); 907 } 908 909 MAC_CHECK_PROBE_DEFINE4(vnode_check_unlink, "struct ucred *", 910 "struct vnode *", "struct vnode *", "struct componentname *"); 911 912 int 913 mac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 914 struct vnode *vp, struct componentname *cnp) 915 { 916 int error; 917 918 ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_unlink"); 919 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_unlink"); 920 921 MAC_POLICY_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp, 922 vp->v_label, cnp); 923 MAC_CHECK_PROBE4(vnode_check_unlink, error, cred, dvp, vp, cnp); 924 925 return (error); 926 } 927 928 MAC_CHECK_PROBE_DEFINE3(vnode_check_write, "struct ucred *", 929 "struct ucred *", "struct vnode *"); 930 931 int 932 mac_vnode_check_write_impl(struct ucred *active_cred, struct ucred *file_cred, 933 struct vnode *vp) 934 { 935 int error; 936 937 ASSERT_VOP_LOCKED(vp, "mac_vnode_check_write"); 938 939 MAC_POLICY_CHECK(vnode_check_write, active_cred, file_cred, vp, 940 vp->v_label); 941 MAC_CHECK_PROBE3(vnode_check_write, error, active_cred, file_cred, 942 vp); 943 944 return (error); 945 } 946 947 void 948 mac_vnode_relabel(struct ucred *cred, struct vnode *vp, 949 struct label *newlabel) 950 { 951 952 MAC_POLICY_PERFORM(vnode_relabel, cred, vp, vp->v_label, newlabel); 953 } 954 955 void 956 mac_mount_create(struct ucred *cred, struct mount *mp) 957 { 958 959 MAC_POLICY_PERFORM(mount_create, cred, mp, mp->mnt_label); 960 } 961 962 MAC_CHECK_PROBE_DEFINE2(mount_check_stat, "struct ucred *", 963 "struct mount *"); 964 965 int 966 mac_mount_check_stat(struct ucred *cred, struct mount *mount) 967 { 968 int error; 969 970 MAC_POLICY_CHECK_NOSLEEP(mount_check_stat, cred, mount, mount->mnt_label); 971 MAC_CHECK_PROBE2(mount_check_stat, error, cred, mount); 972 973 return (error); 974 } 975 976 void 977 mac_devfs_create_device(struct ucred *cred, struct mount *mp, 978 struct cdev *dev, struct devfs_dirent *de) 979 { 980 981 MAC_POLICY_PERFORM_NOSLEEP(devfs_create_device, cred, mp, dev, de, 982 de->de_label); 983 } 984 985 void 986 mac_devfs_create_symlink(struct ucred *cred, struct mount *mp, 987 struct devfs_dirent *dd, struct devfs_dirent *de) 988 { 989 990 MAC_POLICY_PERFORM_NOSLEEP(devfs_create_symlink, cred, mp, dd, 991 dd->de_label, de, de->de_label); 992 } 993 994 void 995 mac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen, 996 struct devfs_dirent *de) 997 { 998 999 MAC_POLICY_PERFORM_NOSLEEP(devfs_create_directory, mp, dirname, 1000 dirnamelen, de, de->de_label); 1001 } 1002 1003 /* 1004 * Implementation of VOP_SETLABEL() that relies on extended attributes to 1005 * store label data. Can be referenced by filesystems supporting extended 1006 * attributes. 1007 */ 1008 int 1009 vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 1010 { 1011 struct vnode *vp = ap->a_vp; 1012 struct label *intlabel = ap->a_label; 1013 int error; 1014 1015 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 1016 1017 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 1018 return (EOPNOTSUPP); 1019 1020 error = mac_vnode_setlabel_extattr(ap->a_cred, vp, intlabel); 1021 if (error) 1022 return (error); 1023 1024 /* 1025 * XXXRW: See the comment below in vn_setlabel() as to why this might 1026 * be the wrong place to call mac_vnode_relabel(). 1027 */ 1028 mac_vnode_relabel(ap->a_cred, vp, intlabel); 1029 1030 return (0); 1031 } 1032 1033 int 1034 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 1035 { 1036 int error; 1037 1038 if (vp->v_mount == NULL) { 1039 /* printf("vn_setlabel: null v_mount\n"); */ 1040 if (vp->v_type != VNON) 1041 printf("vn_setlabel: null v_mount with non-VNON\n"); 1042 return (EBADF); 1043 } 1044 1045 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 1046 return (EOPNOTSUPP); 1047 1048 /* 1049 * Multi-phase commit. First check the policies to confirm the 1050 * change is OK. Then commit via the filesystem. Finally, update 1051 * the actual vnode label. 1052 */ 1053 error = mac_vnode_check_relabel(cred, vp, intlabel); 1054 if (error) 1055 return (error); 1056 1057 /* 1058 * VADMIN provides the opportunity for the filesystem to make 1059 * decisions about who is and is not able to modify labels and 1060 * protections on files. This might not be right. We can't assume 1061 * VOP_SETLABEL() will do it, because we might implement that as part 1062 * of vop_stdsetlabel_ea(). 1063 */ 1064 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 1065 if (error) 1066 return (error); 1067 1068 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 1069 if (error) 1070 return (error); 1071 1072 /* 1073 * It would be more symmetric if mac_vnode_relabel() was called here 1074 * rather than in VOP_SETLABEL(), but we don't for historical reasons. 1075 * We should think about moving it so that the filesystem is 1076 * responsible only for persistence in VOP_SETLABEL(), not the vnode 1077 * label update itself. 1078 */ 1079 1080 return (0); 1081 } 1082 1083 #ifdef DEBUG_VFS_LOCKS 1084 void 1085 mac_vnode_assert_locked(struct vnode *vp, const char *func) 1086 { 1087 1088 ASSERT_VOP_LOCKED(vp, func); 1089 } 1090 #endif 1091