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