1 /* 2 * $FreeBSD$ 3 * 4 * Copyright (c) 2011, 2012, 2013, 2015, 2016, Juniper Networks, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 31 #include "opt_capsicum.h" 32 #include "opt_mac.h" 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/capsicum.h> 37 #include <sys/eventhandler.h> 38 #include <sys/fcntl.h> 39 #include <sys/file.h> 40 #include <sys/filedesc.h> 41 #include <sys/imgact.h> 42 #include <sys/jail.h> 43 #include <sys/kernel.h> 44 #include <sys/mac.h> 45 #include <sys/mount.h> 46 #include <sys/namei.h> 47 #include <sys/priv.h> 48 #include <sys/proc.h> 49 #include <sys/sbuf.h> 50 #include <sys/stat.h> 51 #include <sys/sysctl.h> 52 #include <sys/vnode.h> 53 #include <fs/nullfs/null.h> 54 #include <security/mac/mac_policy.h> 55 56 #include "mac_veriexec.h" 57 #include "mac_veriexec_internal.h" 58 59 #define SLOT(l) \ 60 mac_label_get((l), mac_veriexec_slot) 61 #define SLOT_SET(l, v) \ 62 mac_label_set((l), mac_veriexec_slot, (v)) 63 64 #ifdef MAC_DEBUG 65 #define MAC_VERIEXEC_DBG(_lvl, _fmt, ...) \ 66 do { \ 67 VERIEXEC_DEBUG((_lvl), (MAC_VERIEXEC_FULLNAME ": " _fmt \ 68 "\n", ##__VA_ARGS__)); \ 69 } while(0) 70 #else 71 #define MAC_VERIEXEC_DBG(_lvl, _fmt, ...) 72 #endif 73 74 static int sysctl_mac_veriexec_state(SYSCTL_HANDLER_ARGS); 75 static int sysctl_mac_veriexec_db(SYSCTL_HANDLER_ARGS); 76 77 SYSCTL_DECL(_security_mac); 78 79 SYSCTL_NODE(_security_mac, OID_AUTO, veriexec, CTLFLAG_RW, 0, 80 "MAC/veriexec policy controls"); 81 82 int mac_veriexec_debug; 83 SYSCTL_INT(_security_mac_veriexec, OID_AUTO, debug, CTLFLAG_RW, 84 &mac_veriexec_debug, 0, "Debug level"); 85 86 static int mac_veriexec_state; 87 SYSCTL_PROC(_security_mac_veriexec, OID_AUTO, state, 88 CTLTYPE_STRING | CTLFLAG_RD, 0, 0, sysctl_mac_veriexec_state, "A", 89 "Verified execution subsystem state"); 90 91 SYSCTL_PROC(_security_mac_veriexec, OID_AUTO, db, 92 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_SKIP, 0, 0, sysctl_mac_veriexec_db, 93 "A", "Verified execution fingerprint database"); 94 95 static int mac_veriexec_slot; 96 97 MALLOC_DEFINE(M_VERIEXEC, "veriexec", "Verified execution data"); 98 99 /** 100 * @internal 101 * @brief Handler for security.mac.veriexec.db sysctl 102 * 103 * Display a human-readable form of the current fingerprint database. 104 */ 105 static int 106 sysctl_mac_veriexec_db(SYSCTL_HANDLER_ARGS) 107 { 108 struct sbuf sb; 109 int error; 110 111 error = sysctl_wire_old_buffer(req, 0); 112 if (error != 0) 113 return (error); 114 115 sbuf_new_for_sysctl(&sb, NULL, 1024, req); 116 mac_veriexec_metadata_print_db(&sb); 117 error = sbuf_finish(&sb); 118 sbuf_delete(&sb); 119 120 return (error); 121 } 122 123 /** 124 * @internal 125 * @brief Generate human-readable output about the current verified execution 126 * state. 127 * 128 * @param sbp sbuf to write output to 129 */ 130 static void 131 mac_veriexec_print_state(struct sbuf *sbp) 132 { 133 134 if (mac_veriexec_state & VERIEXEC_STATE_INACTIVE) 135 sbuf_printf(sbp, "inactive "); 136 if (mac_veriexec_state & VERIEXEC_STATE_LOADED) 137 sbuf_printf(sbp, "loaded "); 138 if (mac_veriexec_state & VERIEXEC_STATE_ACTIVE) 139 sbuf_printf(sbp, "active "); 140 if (mac_veriexec_state & VERIEXEC_STATE_ENFORCE) 141 sbuf_printf(sbp, "enforce "); 142 if (mac_veriexec_state & VERIEXEC_STATE_LOCKED) 143 sbuf_printf(sbp, "locked "); 144 if (mac_veriexec_state != 0) 145 sbuf_trim(sbp); 146 } 147 148 /** 149 * @internal 150 * @brief Handler for security.mac.veriexec.state sysctl 151 * 152 * Display a human-readable form of the current verified execution subsystem 153 * state. 154 */ 155 static int 156 sysctl_mac_veriexec_state(SYSCTL_HANDLER_ARGS) 157 { 158 struct sbuf sb; 159 int error; 160 161 sbuf_new(&sb, NULL, 128, SBUF_AUTOEXTEND); 162 mac_veriexec_print_state(&sb); 163 sbuf_finish(&sb); 164 165 error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb)); 166 sbuf_delete(&sb); 167 return (error); 168 } 169 170 /** 171 * @internal 172 * @brief Event handler called when a virtual file system is mounted. 173 * 174 * We need to record the file system identifier in the MAC per-policy slot 175 * assigned to veriexec, so we have a key to use in order to reference the 176 * mount point in the meta-data store. 177 * 178 * @param arg unused argument 179 * @param mp mount point that is being mounted 180 * @param fsrootvp vnode of the file system root 181 * @param td calling thread 182 */ 183 static void 184 mac_veriexec_vfs_mounted(void *arg __unused, struct mount *mp, 185 struct vnode *fsrootvp, struct thread *td) 186 { 187 struct vattr va; 188 int error; 189 190 error = VOP_GETATTR(fsrootvp, &va, td->td_ucred); 191 if (error) 192 return; 193 194 SLOT_SET(mp->mnt_label, va.va_fsid); 195 #ifdef MAC_DEBUG 196 MAC_VERIEXEC_DBG(3, "set fsid to %u for mount %p", va.va_fsid, mp); 197 #endif 198 } 199 200 /** 201 * @internal 202 * @brief Event handler called when a virtual file system is unmounted. 203 * 204 * If we recorded a file system identifier in the MAC per-policy slot assigned 205 * to veriexec, then we need to tell the meta-data store to clean up. 206 * 207 * @param arg unused argument 208 * @param mp mount point that is being unmounted 209 * @param td calling thread 210 */ 211 static void 212 mac_veriexec_vfs_unmounted(void *arg __unused, struct mount *mp, 213 struct thread *td) 214 { 215 dev_t fsid; 216 217 fsid = SLOT(mp->mnt_label); 218 if (fsid) { 219 MAC_VERIEXEC_DBG(3, "fsid %u, cleaning up mount", fsid); 220 mac_veriexec_metadata_unmounted(fsid, td); 221 } 222 } 223 224 /** 225 * @internal 226 * @brief The mount point is being initialized, set the value in the MAC 227 * per-policy slot for veriexec to zero. 228 * 229 * @note A value of zero in this slot indicates no file system identifier 230 * is assigned. 231 * 232 * @param label the label that is being initialized 233 */ 234 static void 235 mac_veriexec_mount_init_label(struct label *label) 236 { 237 238 SLOT_SET(label, 0); 239 } 240 241 /** 242 * @internal 243 * @brief The mount-point is being destroyed, reset the value in the MAC 244 * per-policy slot for veriexec back to zero. 245 * 246 * @note A value of zero in this slot indicates no file system identifier 247 * is assigned. 248 * 249 * @param label the label that is being destroyed 250 */ 251 static void 252 mac_veriexec_mount_destroy_label(struct label *label) 253 { 254 255 SLOT_SET(label, 0); 256 } 257 258 /** 259 * @internal 260 * @brief The vnode label is being initialized, set the value in the MAC 261 * per-policy slot for veriexec to @c FINGERPRINT_INVALID 262 * 263 * @note @c FINGERPRINT_INVALID indicates the fingerprint is invalid. 264 * 265 * @param label the label that is being initialized 266 */ 267 static void 268 mac_veriexec_vnode_init_label(struct label *label) 269 { 270 271 SLOT_SET(label, FINGERPRINT_INVALID); 272 } 273 274 /** 275 * @internal 276 * @brief The vnode label is being destroyed, reset the value in the MAC 277 * per-policy slot for veriexec back to @c FINGERPRINT_INVALID 278 * 279 * @note @c FINGERPRINT_INVALID indicates the fingerprint is invalid. 280 * 281 * @param label the label that is being destroyed 282 */ 283 static void 284 mac_veriexec_vnode_destroy_label(struct label *label) 285 { 286 287 SLOT_SET(label, FINGERPRINT_INVALID); 288 } 289 290 /** 291 * @internal 292 * @brief Copy the value in the MAC per-policy slot assigned to veriexec from 293 * the @p src label to the @p dest label 294 */ 295 static void 296 mac_veriexec_copy_label(struct label *src, struct label *dest) 297 { 298 299 SLOT_SET(dest, SLOT(src)); 300 } 301 302 /** 303 * @internal 304 * @brief Check if the requested process can be debugged 305 * 306 * @param cred credentials to use 307 * @param p process to debug 308 * 309 * @return 0 if debugging is allowed, otherwise an error code. 310 */ 311 static int 312 mac_veriexec_proc_check_debug(struct ucred *cred, struct proc *p) 313 { 314 int error, flags; 315 316 /* If we are not enforcing veriexec, nothing for us to check */ 317 if ((mac_veriexec_state & VERIEXEC_STATE_ENFORCE) == 0) 318 return (0); 319 320 error = mac_veriexec_metadata_get_executable_flags(cred, p, &flags, 0); 321 if (error != 0) 322 return (0); 323 324 return ((flags & VERIEXEC_NOTRACE) ? EACCES : 0); 325 } 326 327 /** 328 * @internal 329 * @brief A KLD load has been requested and needs to be validated. 330 * 331 * @param cred credentials to use 332 * @param vp vnode of the KLD that has been requested 333 * @param vlabel vnode label assigned to the vnode 334 * 335 * @return 0 if the KLD load is allowed, otherwise an error code. 336 */ 337 static int 338 mac_veriexec_kld_check_load(struct ucred *cred, struct vnode *vp, 339 struct label *vlabel) 340 { 341 struct vattr va; 342 struct thread *td = curthread; 343 fingerprint_status_t status; 344 int error; 345 346 /* 347 * If we are not actively enforcing, allow it 348 */ 349 if ((mac_veriexec_state & VERIEXEC_STATE_ENFORCE) == 0) 350 return (0); 351 352 /* Get vnode attributes */ 353 error = VOP_GETATTR(vp, &va, cred); 354 if (error) 355 return (error); 356 357 /* 358 * Fetch the fingerprint status for the vnode 359 * (starting with files first) 360 */ 361 error = mac_veriexec_metadata_fetch_fingerprint_status(vp, &va, td, 362 VERIEXEC_FILES_FIRST); 363 if (error && error != EAUTH) 364 return (error); 365 366 /* 367 * By now we should have status... 368 */ 369 status = mac_veriexec_get_fingerprint_status(vp); 370 switch (status) { 371 case FINGERPRINT_FILE: 372 case FINGERPRINT_VALID: 373 case FINGERPRINT_INDIRECT: 374 if (error) 375 return (error); 376 break; 377 default: 378 /* 379 * kldload should fail unless there is a valid fingerprint 380 * registered. 381 */ 382 MAC_VERIEXEC_DBG(2, "fingerprint status is %d for dev %u, " 383 "file %lu.%lu\n", status, va.va_fsid, va.va_fileid, 384 va.va_gen); 385 return (EAUTH); 386 } 387 388 /* Everything is good, allow the KLD to be loaded */ 389 return (0); 390 } 391 392 /** 393 * @internal 394 * @brief Check privileges that veriexec needs to be concerned about. 395 * 396 * The following privileges are checked by this function: 397 * - PRIV_KMEM_WRITE\n 398 * Check if writes to /dev/mem and /dev/kmem are allowed\n 399 * (Only trusted processes are allowed) 400 * 401 * @param cred credentials to use 402 * @param priv privilege to check 403 * 404 * @return 0 if the privilege is allowed, error code otherwise. 405 */ 406 static int 407 mac_veriexec_priv_check(struct ucred *cred, int priv) 408 { 409 410 /* If we are not enforcing veriexec, nothing for us to check */ 411 if ((mac_veriexec_state & VERIEXEC_STATE_ENFORCE) == 0) 412 return (0); 413 414 switch (priv) { 415 case PRIV_KMEM_WRITE: 416 if (!mac_veriexec_proc_is_trusted(cred, curproc)) 417 return (EPERM); 418 break; 419 default: 420 break; 421 } 422 return (0); 423 } 424 425 /** 426 * @internal 427 * @brief A program is being executed and needs to be validated. 428 * 429 * @param cred credentials to use 430 * @param vp vnode of the program that is being executed 431 * @param label vnode label assigned to the vnode 432 * @param imgp parameters for the image to be executed 433 * @param execlabel optional exec label 434 * 435 * @return 0 if the program should be allowed to execute, otherwise an error 436 * code. 437 */ 438 static int 439 mac_veriexec_vnode_check_exec(struct ucred *cred __unused, 440 struct vnode *vp __unused, struct label *label __unused, 441 struct image_params *imgp, struct label *execlabel __unused) 442 { 443 struct thread *td = curthread; 444 int error; 445 446 error = mac_veriexec_fingerprint_check_image(imgp, 0, td); 447 return (error); 448 } 449 450 /** 451 * @brief Check fingerprint for the specified vnode and validate it 452 * 453 * @param cred credentials to use 454 * @param vp vnode of the file 455 * @param accmode access mode to check (read, write, append, create, 456 * verify, etc.) 457 * 458 * @return 0 if the file validated, otherwise an error code. 459 */ 460 static int 461 mac_veriexec_check_vp(struct ucred *cred, struct vnode *vp, accmode_t accmode) 462 { 463 struct vattr va; 464 struct thread *td = curthread; 465 fingerprint_status_t status; 466 int error; 467 468 /* Get vnode attributes */ 469 error = VOP_GETATTR(vp, &va, cred); 470 if (error) 471 return (error); 472 473 /* Get the fingerprint status for the file */ 474 error = mac_veriexec_metadata_fetch_fingerprint_status(vp, &va, td, 475 VERIEXEC_FILES_FIRST); 476 if (error && error != EAUTH) 477 return (error); 478 479 /* 480 * By now we should have status... 481 */ 482 status = mac_veriexec_get_fingerprint_status(vp); 483 if (accmode & VWRITE) { 484 /* 485 * If file has a fingerprint then deny the write request, 486 * otherwise invalidate the status so we don't keep checking 487 * for the file having a fingerprint. 488 */ 489 switch (status) { 490 case FINGERPRINT_FILE: 491 case FINGERPRINT_VALID: 492 case FINGERPRINT_INDIRECT: 493 MAC_VERIEXEC_DBG(2, 494 "attempted write to fingerprinted file for dev " 495 "%u, file %lu.%lu\n", va.va_fsid, 496 va.va_fileid, va.va_gen); 497 return (EPERM); 498 default: 499 break; 500 } 501 } 502 if (accmode & VVERIFY) { 503 switch (status) { 504 case FINGERPRINT_FILE: 505 case FINGERPRINT_VALID: 506 case FINGERPRINT_INDIRECT: 507 if (error) 508 return (error); 509 break; 510 default: 511 /* 512 * Caller wants open to fail unless there is a valid 513 * fingerprint registered. 514 */ 515 MAC_VERIEXEC_DBG(2, "fingerprint status is %d for dev " 516 "%u, file %lu.%lu\n", status, va.va_fsid, 517 va.va_fileid, va.va_gen); 518 return (EAUTH); 519 } 520 } 521 return (0); 522 } 523 524 /** 525 * @brief Opening a file has been requested and may need to be validated. 526 * 527 * @param cred credentials to use 528 * @param vp vnode of the file to open 529 * @param label vnode label assigned to the vnode 530 * @param accmode access mode to use for opening the file (read, write, 531 * append, create, verify, etc.) 532 * 533 * @return 0 if opening the file should be allowed, otherwise an error code. 534 */ 535 static int 536 mac_veriexec_vnode_check_open(struct ucred *cred, struct vnode *vp, 537 struct label *label __unused, accmode_t accmode) 538 { 539 int error; 540 541 /* 542 * Look for the file on the fingerprint lists iff it has not been seen 543 * before. 544 */ 545 if ((mac_veriexec_state & VERIEXEC_STATE_ENFORCE) == 0) 546 return (0); 547 548 error = mac_veriexec_check_vp(cred, vp, accmode); 549 return (error); 550 } 551 552 /** 553 * @brief Check mode changes on file to ensure they should be allowed. 554 * 555 * We cannot allow chmod of SUID or SGID on verified files. 556 * 557 * @param cred credentials to use 558 * @param vp vnode of the file to open 559 * @param label vnode label assigned to the vnode 560 * @param mode mode flags to set 561 * 562 * @return 0 if the mode change should be allowed, EAUTH otherwise. 563 */ 564 static int 565 mac_veriexec_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 566 struct label *label __unused, mode_t mode) 567 { 568 int error; 569 570 if ((mac_veriexec_state & VERIEXEC_STATE_ENFORCE) == 0) 571 return (0); 572 573 /* 574 * Do not allow chmod (set-[gu]id) of verified file 575 */ 576 error = mac_veriexec_check_vp(cred, vp, VVERIFY); 577 if (error == EAUTH) /* it isn't verified */ 578 return (0); 579 if (error == 0 && (mode & (S_ISUID|S_ISGID)) != 0) 580 return (EAUTH); 581 return (0); 582 } 583 584 /** 585 * @internal 586 * @brief Initialize the mac_veriexec MAC policy 587 * 588 * @param mpc MAC policy configuration 589 */ 590 static void 591 mac_veriexec_init(struct mac_policy_conf *mpc __unused) 592 { 593 /* Initialize state */ 594 mac_veriexec_state = VERIEXEC_STATE_INACTIVE; 595 596 /* Initialize meta-data storage */ 597 mac_veriexec_metadata_init(); 598 599 /* Initialize fingerprint ops */ 600 mac_veriexec_fingerprint_init(); 601 602 /* Register event handlers */ 603 EVENTHANDLER_REGISTER(vfs_mounted, mac_veriexec_vfs_mounted, NULL, 604 EVENTHANDLER_PRI_FIRST); 605 EVENTHANDLER_REGISTER(vfs_unmounted, mac_veriexec_vfs_unmounted, NULL, 606 EVENTHANDLER_PRI_LAST); 607 } 608 609 /** 610 * @internal 611 * @brief MAC policy-specific syscall for mac_veriexec 612 * 613 * The following syscalls are implemented: 614 * - @c MAC_VERIEXEC_CHECK_SYSCALL 615 * Check if the file referenced by a file descriptor has a fingerprint 616 * registered in the meta-data store. 617 * 618 * @param td calling thread 619 * @param call system call number 620 * @param arg arugments to the syscall 621 * 622 * @return 0 on success, otherwise an error code. 623 */ 624 static int 625 mac_veriexec_syscall(struct thread *td, int call, void *arg) 626 { 627 struct image_params img; 628 struct nameidata nd; 629 cap_rights_t rights; 630 struct vattr va; 631 struct file *fp; 632 int error; 633 634 switch (call) { 635 case MAC_VERIEXEC_CHECK_FD_SYSCALL: 636 /* Get the vnode associated with the file descriptor passed */ 637 error = getvnode(td, (uintptr_t) arg, cap_rights_init(&rights, 638 CAP_READ), &fp); 639 if (error) 640 return (error); 641 if (fp->f_type != DTYPE_VNODE) { 642 MAC_VERIEXEC_DBG(3, "MAC_VERIEXEC_CHECK_SYSCALL: " 643 "file is not vnode type (type=0x%x)", 644 fp->f_type); 645 error = EINVAL; 646 goto cleanup_file; 647 } 648 649 /* 650 * setup the bits of image_params that are used by 651 * mac_veriexec_check_fingerprint(). 652 */ 653 bzero(&img, sizeof(img)); 654 img.proc = td->td_proc; 655 img.vp = fp->f_vnode; 656 img.attr = &va; 657 658 /* 659 * Get vnode attributes 660 * (need to obtain a lock on the vnode first) 661 */ 662 vn_lock(img.vp, LK_EXCLUSIVE | LK_RETRY); 663 error = VOP_GETATTR(fp->f_vnode, &va, td->td_ucred); 664 if (error) 665 goto check_done; 666 667 MAC_VERIEXEC_DBG(2, "mac_veriexec_fingerprint_check_image: " 668 "va_mode=%o, check_files=%d\n", va.va_mode, 669 ((va.va_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0)); 670 error = mac_veriexec_fingerprint_check_image(&img, 671 ((va.va_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0), td); 672 check_done: 673 /* Release the lock we obtained earlier */ 674 VOP_UNLOCK(img.vp, 0); 675 cleanup_file: 676 fdrop(fp, td); 677 break; 678 case MAC_VERIEXEC_CHECK_PATH_SYSCALL: 679 /* Look up the path to get the vnode */ 680 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, 681 UIO_USERSPACE, arg, td); 682 error = namei(&nd); 683 if (error != 0) 684 break; 685 NDFREE(&nd, NDF_ONLY_PNBUF); 686 687 /* Check the fingerprint status of the vnode */ 688 error = mac_veriexec_check_vp(td->td_ucred, nd.ni_vp, VVERIFY); 689 vput(nd.ni_vp); 690 break; 691 default: 692 error = EOPNOTSUPP; 693 } 694 return (error); 695 } 696 697 static struct mac_policy_ops mac_veriexec_ops = 698 { 699 .mpo_init = mac_veriexec_init, 700 .mpo_syscall = mac_veriexec_syscall, 701 .mpo_kld_check_load = mac_veriexec_kld_check_load, 702 .mpo_mount_destroy_label = mac_veriexec_mount_destroy_label, 703 .mpo_mount_init_label = mac_veriexec_mount_init_label, 704 .mpo_priv_check = mac_veriexec_priv_check, 705 .mpo_proc_check_debug = mac_veriexec_proc_check_debug, 706 .mpo_vnode_check_exec = mac_veriexec_vnode_check_exec, 707 .mpo_vnode_check_open = mac_veriexec_vnode_check_open, 708 .mpo_vnode_check_setmode = mac_veriexec_vnode_check_setmode, 709 .mpo_vnode_copy_label = mac_veriexec_copy_label, 710 .mpo_vnode_destroy_label = mac_veriexec_vnode_destroy_label, 711 .mpo_vnode_init_label = mac_veriexec_vnode_init_label, 712 }; 713 714 MAC_POLICY_SET(&mac_veriexec_ops, mac_veriexec, MAC_VERIEXEC_FULLNAME, 715 MPC_LOADTIME_FLAG_NOTLATE, &mac_veriexec_slot); 716 MODULE_VERSION(mac_veriexec, 1); 717 718 /** 719 * @brief Get the fingerprint status set on a vnode. 720 * 721 * @param vp vnode to obtain fingerprint status from 722 * 723 * @return Fingerprint status assigned to the vnode. 724 */ 725 fingerprint_status_t 726 mac_veriexec_get_fingerprint_status(struct vnode *vp) 727 { 728 fingerprint_status_t fps; 729 730 fps = SLOT(vp->v_label); 731 switch (fps) { 732 case FINGERPRINT_VALID: 733 case FINGERPRINT_INDIRECT: 734 case FINGERPRINT_FILE: 735 break; 736 default: 737 /* we may need to recurse */ 738 if (strcmp(vp->v_tag, "null") == 0) { 739 struct vnode *ldvp; 740 741 ldvp = NULLVPTOLOWERVP(vp); 742 return mac_veriexec_get_fingerprint_status(ldvp); 743 } 744 break; 745 } 746 return fps; 747 } 748 749 /** 750 * @brief Get the current verified execution subsystem state. 751 * 752 * @return Current set of verified execution subsystem state flags. 753 */ 754 int 755 mac_veriexec_get_state(void) 756 { 757 758 return (mac_veriexec_state); 759 } 760 761 /** 762 * @brief Determine if the verified execution subsystem state has specific 763 * flags set. 764 * 765 * @param state mask of flags to check 766 * 767 * @return State flags set within the masked bits 768 */ 769 int 770 mac_veriexec_in_state(int state) 771 { 772 773 return (mac_veriexec_state & state); 774 } 775 776 /** 777 * @brief Set the fingerprint status for a vnode 778 * 779 * Fingerprint status is stored in the MAC per-policy slot assigned to 780 * mac_veriexec. 781 * 782 * @param vp vnode to store the fingerprint status on 783 * @param fp_status fingerprint status to store 784 */ 785 void 786 mac_veriexec_set_fingerprint_status(struct vnode *vp, 787 fingerprint_status_t fp_status) 788 { 789 790 /* recurse until we find the real storage */ 791 if (strcmp(vp->v_tag, "null") == 0) { 792 struct vnode *ldvp; 793 794 ldvp = NULLVPTOLOWERVP(vp); 795 mac_veriexec_set_fingerprint_status(ldvp, fp_status); 796 return; 797 } 798 SLOT_SET(vp->v_label, fp_status); 799 } 800 801 /** 802 * @brief Set verified execution subsystem state flags 803 * 804 * @note Flags can only be added to the current state, not removed. 805 * 806 * @param state state flags to add to the current state 807 */ 808 void 809 mac_veriexec_set_state(int state) 810 { 811 812 mac_veriexec_state |= state; 813 } 814 815 /** 816 * @brief Determine if the process is trusted 817 * 818 * @param cred credentials to use 819 * @param p the process in question 820 * 821 * @return 1 if the process is trusted, otherwise 0. 822 */ 823 int 824 mac_veriexec_proc_is_trusted(struct ucred *cred, struct proc *p) 825 { 826 int error, flags; 827 828 error = mac_veriexec_metadata_get_executable_flags(cred, p, &flags, 0); 829 830 /* Any errors, deny access */ 831 if (error != 0) 832 return (0); 833 834 /* Check that the trusted flag is set */ 835 return ((flags & VERIEXEC_TRUSTED) == VERIEXEC_TRUSTED); 836 } 837