1/* 2 * Copyright (c) 1999-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * File: ubc_subr.c 30 * Author: Umesh Vaishampayan [umeshv@apple.com] 31 * 05-Aug-1999 umeshv Created. 32 * 33 * Functions related to Unified Buffer cache. 34 * 35 * Caller of UBC functions MUST have a valid reference on the vnode. 36 * 37 */ 38 39#include <sys/types.h> 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/lock.h> 43#include <sys/mman.h> 44#include <sys/mount_internal.h> 45#include <sys/vnode_internal.h> 46#include <sys/ubc_internal.h> 47#include <sys/ucred.h> 48#include <sys/proc_internal.h> 49#include <sys/kauth.h> 50#include <sys/buf.h> 51#include <sys/user.h> 52#include <sys/codesign.h> 53#include <sys/codedir_internal.h> 54#include <sys/fsevents.h> 55 56#include <mach/mach_types.h> 57#include <mach/memory_object_types.h> 58#include <mach/memory_object_control.h> 59#include <mach/vm_map.h> 60#include <mach/mach_vm.h> 61#include <mach/upl.h> 62 63#include <kern/kern_types.h> 64#include <kern/kalloc.h> 65#include <kern/zalloc.h> 66#include <kern/thread.h> 67#include <vm/vm_kern.h> 68#include <vm/vm_protos.h> /* last */ 69 70#include <libkern/crypto/sha1.h> 71#include <libkern/libkern.h> 72 73#include <security/mac_framework.h> 74#include <stdbool.h> 75 76/* XXX These should be in a BSD accessible Mach header, but aren't. */ 77extern kern_return_t memory_object_pages_resident(memory_object_control_t, 78 boolean_t *); 79extern kern_return_t memory_object_signed(memory_object_control_t control, 80 boolean_t is_signed); 81extern boolean_t memory_object_is_slid(memory_object_control_t control); 82extern boolean_t memory_object_is_signed(memory_object_control_t); 83 84extern void Debugger(const char *message); 85 86 87/* XXX no one uses this interface! */ 88kern_return_t ubc_page_op_with_control( 89 memory_object_control_t control, 90 off_t f_offset, 91 int ops, 92 ppnum_t *phys_entryp, 93 int *flagsp); 94 95 96#if DIAGNOSTIC 97#if defined(assert) 98#undef assert 99#endif 100#define assert(cond) \ 101 ((void) ((cond) ? 0 : panic("Assert failed: %s", # cond))) 102#else 103#include <kern/assert.h> 104#endif /* DIAGNOSTIC */ 105 106static int ubc_info_init_internal(struct vnode *vp, int withfsize, off_t filesize); 107static int ubc_umcallback(vnode_t, void *); 108static int ubc_msync_internal(vnode_t, off_t, off_t, off_t *, int, int *); 109static void ubc_cs_free(struct ubc_info *uip); 110 111struct zone *ubc_info_zone; 112static uint32_t cs_blob_generation_count = 1; 113 114/* 115 * CODESIGNING 116 * Routines to navigate code signing data structures in the kernel... 117 */ 118 119extern int cs_debug; 120 121#define PAGE_SHIFT_4K (12) 122#define PAGE_SIZE_4K ((1<<PAGE_SHIFT_4K)) 123#define PAGE_MASK_4K ((PAGE_SIZE_4K-1)) 124#define round_page_4K(x) (((vm_offset_t)(x) + PAGE_MASK_4K) & ~((vm_offset_t)PAGE_MASK_4K)) 125 126static boolean_t 127cs_valid_range( 128 const void *start, 129 const void *end, 130 const void *lower_bound, 131 const void *upper_bound) 132{ 133 if (upper_bound < lower_bound || 134 end < start) { 135 return FALSE; 136 } 137 138 if (start < lower_bound || 139 end > upper_bound) { 140 return FALSE; 141 } 142 143 return TRUE; 144} 145 146/* 147 * Locate the CodeDirectory from an embedded signature blob 148 */ 149const 150CS_CodeDirectory *findCodeDirectory( 151 const CS_SuperBlob *embedded, 152 char *lower_bound, 153 char *upper_bound) 154{ 155 const CS_CodeDirectory *cd = NULL; 156 157 if (embedded && 158 cs_valid_range(embedded, embedded + 1, lower_bound, upper_bound) && 159 ntohl(embedded->magic) == CSMAGIC_EMBEDDED_SIGNATURE) { 160 const CS_BlobIndex *limit; 161 const CS_BlobIndex *p; 162 163 limit = &embedded->index[ntohl(embedded->count)]; 164 if (!cs_valid_range(&embedded->index[0], limit, 165 lower_bound, upper_bound)) { 166 return NULL; 167 } 168 for (p = embedded->index; p < limit; ++p) { 169 if (ntohl(p->type) == CSSLOT_CODEDIRECTORY) { 170 const unsigned char *base; 171 172 base = (const unsigned char *)embedded; 173 cd = (const CS_CodeDirectory *)(base + ntohl(p->offset)); 174 break; 175 } 176 } 177 } else { 178 /* 179 * Detached signatures come as a bare CS_CodeDirectory, 180 * without a blob. 181 */ 182 cd = (const CS_CodeDirectory *) embedded; 183 } 184 185 if (cd && 186 cs_valid_range(cd, cd + 1, lower_bound, upper_bound) && 187 cs_valid_range(cd, (const char *) cd + ntohl(cd->length), 188 lower_bound, upper_bound) && 189 cs_valid_range(cd, (const char *) cd + ntohl(cd->hashOffset), 190 lower_bound, upper_bound) && 191 cs_valid_range(cd, (const char *) cd + 192 ntohl(cd->hashOffset) + 193 (ntohl(cd->nCodeSlots) * SHA1_RESULTLEN), 194 lower_bound, upper_bound) && 195 196 ntohl(cd->magic) == CSMAGIC_CODEDIRECTORY) { 197 return cd; 198 } 199 200 // not found or not a valid code directory 201 return NULL; 202} 203 204 205/* 206 * Locating a page hash 207 */ 208static const unsigned char * 209hashes( 210 const CS_CodeDirectory *cd, 211 unsigned page, 212 char *lower_bound, 213 char *upper_bound) 214{ 215 const unsigned char *base, *top, *hash; 216 uint32_t nCodeSlots = ntohl(cd->nCodeSlots); 217 218 assert(cs_valid_range(cd, cd + 1, lower_bound, upper_bound)); 219 220 if((ntohl(cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(cd->scatterOffset))) { 221 /* Get first scatter struct */ 222 const SC_Scatter *scatter = (const SC_Scatter*) 223 ((const char*)cd + ntohl(cd->scatterOffset)); 224 uint32_t hashindex=0, scount, sbase=0; 225 /* iterate all scatter structs */ 226 do { 227 if((const char*)scatter > (const char*)cd + ntohl(cd->length)) { 228 if(cs_debug) { 229 printf("CODE SIGNING: Scatter extends past Code Directory\n"); 230 } 231 return NULL; 232 } 233 234 scount = ntohl(scatter->count); 235 uint32_t new_base = ntohl(scatter->base); 236 237 /* last scatter? */ 238 if (scount == 0) { 239 return NULL; 240 } 241 242 if((hashindex > 0) && (new_base <= sbase)) { 243 if(cs_debug) { 244 printf("CODE SIGNING: unordered Scatter, prev base %d, cur base %d\n", 245 sbase, new_base); 246 } 247 return NULL; /* unordered scatter array */ 248 } 249 sbase = new_base; 250 251 /* this scatter beyond page we're looking for? */ 252 if (sbase > page) { 253 return NULL; 254 } 255 256 if (sbase+scount >= page) { 257 /* Found the scatter struct that is 258 * referencing our page */ 259 260 /* base = address of first hash covered by scatter */ 261 base = (const unsigned char *)cd + ntohl(cd->hashOffset) + 262 hashindex * SHA1_RESULTLEN; 263 /* top = address of first hash after this scatter */ 264 top = base + scount * SHA1_RESULTLEN; 265 if (!cs_valid_range(base, top, lower_bound, 266 upper_bound) || 267 hashindex > nCodeSlots) { 268 return NULL; 269 } 270 271 break; 272 } 273 274 /* this scatter struct is before the page we're looking 275 * for. Iterate. */ 276 hashindex+=scount; 277 scatter++; 278 } while(1); 279 280 hash = base + (page - sbase) * SHA1_RESULTLEN; 281 } else { 282 base = (const unsigned char *)cd + ntohl(cd->hashOffset); 283 top = base + nCodeSlots * SHA1_RESULTLEN; 284 if (!cs_valid_range(base, top, lower_bound, upper_bound) || 285 page > nCodeSlots) { 286 return NULL; 287 } 288 assert(page < nCodeSlots); 289 290 hash = base + page * SHA1_RESULTLEN; 291 } 292 293 if (!cs_valid_range(hash, hash + SHA1_RESULTLEN, 294 lower_bound, upper_bound)) { 295 hash = NULL; 296 } 297 298 return hash; 299} 300 301/* 302 * cs_validate_codedirectory 303 * 304 * Validate that pointers inside the code directory to make sure that 305 * all offsets and lengths are constrained within the buffer. 306 * 307 * Parameters: cd Pointer to code directory buffer 308 * length Length of buffer 309 * 310 * Returns: 0 Success 311 * EBADEXEC Invalid code signature 312 */ 313 314static int 315cs_validate_codedirectory(const CS_CodeDirectory *cd, size_t length) 316{ 317 318 if (length < sizeof(*cd)) 319 return EBADEXEC; 320 if (ntohl(cd->magic) != CSMAGIC_CODEDIRECTORY) 321 return EBADEXEC; 322 if (cd->hashSize != SHA1_RESULTLEN) 323 return EBADEXEC; 324 if (cd->pageSize != PAGE_SHIFT_4K) 325 return EBADEXEC; 326 if (cd->hashType != CS_HASHTYPE_SHA1) 327 return EBADEXEC; 328 329 if (length < ntohl(cd->hashOffset)) 330 return EBADEXEC; 331 332 /* check that nSpecialSlots fits in the buffer in front of hashOffset */ 333 if (ntohl(cd->hashOffset) / SHA1_RESULTLEN < ntohl(cd->nSpecialSlots)) 334 return EBADEXEC; 335 336 /* check that codeslots fits in the buffer */ 337 if ((length - ntohl(cd->hashOffset)) / SHA1_RESULTLEN < ntohl(cd->nCodeSlots)) 338 return EBADEXEC; 339 340 if (ntohl(cd->version) >= CS_SUPPORTSSCATTER && cd->scatterOffset) { 341 342 if (length < ntohl(cd->scatterOffset)) 343 return EBADEXEC; 344 345 SC_Scatter *scatter = (SC_Scatter *) 346 (((uint8_t *)cd) + ntohl(cd->scatterOffset)); 347 uint32_t nPages = 0; 348 349 /* 350 * Check each scatter buffer, since we don't know the 351 * length of the scatter buffer array, we have to 352 * check each entry. 353 */ 354 while(1) { 355 /* check that the end of each scatter buffer in within the length */ 356 if (((const uint8_t *)scatter) + sizeof(scatter[0]) > (const uint8_t *)cd + length) 357 return EBADEXEC; 358 uint32_t scount = ntohl(scatter->count); 359 if (scount == 0) 360 break; 361 if (nPages + scount < nPages) 362 return EBADEXEC; 363 nPages += scount; 364 scatter++; 365 366 /* XXX check that basees doesn't overlap */ 367 /* XXX check that targetOffset doesn't overlap */ 368 } 369#if 0 /* rdar://12579439 */ 370 if (nPages != ntohl(cd->nCodeSlots)) 371 return EBADEXEC; 372#endif 373 } 374 375 if (length < ntohl(cd->identOffset)) 376 return EBADEXEC; 377 378 /* identifier is NUL terminated string */ 379 if (cd->identOffset) { 380 uint8_t *ptr = (uint8_t *)cd + ntohl(cd->identOffset); 381 if (memchr(ptr, 0, length - ntohl(cd->identOffset)) == NULL) 382 return EBADEXEC; 383 } 384 385 /* team identifier is NULL terminated string */ 386 if (ntohl(cd->version) >= CS_SUPPORTSTEAMID && ntohl(cd->teamOffset)) { 387 if (length < ntohl(cd->teamOffset)) 388 return EBADEXEC; 389 390 uint8_t *ptr = (uint8_t *)cd + ntohl(cd->teamOffset); 391 if (memchr(ptr, 0, length - ntohl(cd->teamOffset)) == NULL) 392 return EBADEXEC; 393 } 394 395 return 0; 396} 397 398/* 399 * 400 */ 401 402static int 403cs_validate_blob(const CS_GenericBlob *blob, size_t length) 404{ 405 if (length < sizeof(CS_GenericBlob) || length < ntohl(blob->length)) 406 return EBADEXEC; 407 return 0; 408} 409 410/* 411 * cs_validate_csblob 412 * 413 * Validate that superblob/embedded code directory to make sure that 414 * all internal pointers are valid. 415 * 416 * Will validate both a superblob csblob and a "raw" code directory. 417 * 418 * 419 * Parameters: buffer Pointer to code signature 420 * length Length of buffer 421 * rcd returns pointer to code directory 422 * 423 * Returns: 0 Success 424 * EBADEXEC Invalid code signature 425 */ 426 427static int 428cs_validate_csblob(const uint8_t *addr, size_t length, 429 const CS_CodeDirectory **rcd) 430{ 431 const CS_GenericBlob *blob = (const CS_GenericBlob *)(void *)addr; 432 int error; 433 434 *rcd = NULL; 435 436 error = cs_validate_blob(blob, length); 437 if (error) 438 return error; 439 440 length = ntohl(blob->length); 441 442 if (ntohl(blob->magic) == CSMAGIC_EMBEDDED_SIGNATURE) { 443 const CS_SuperBlob *sb = (const CS_SuperBlob *)blob; 444 uint32_t n, count = ntohl(sb->count); 445 446 if (length < sizeof(CS_SuperBlob)) 447 return EBADEXEC; 448 449 /* check that the array of BlobIndex fits in the rest of the data */ 450 if ((length - sizeof(CS_SuperBlob)) / sizeof(CS_BlobIndex) < count) 451 return EBADEXEC; 452 453 /* now check each BlobIndex */ 454 for (n = 0; n < count; n++) { 455 const CS_BlobIndex *blobIndex = &sb->index[n]; 456 if (length < ntohl(blobIndex->offset)) 457 return EBADEXEC; 458 459 const CS_GenericBlob *subBlob = 460 (const CS_GenericBlob *)(void *)(addr + ntohl(blobIndex->offset)); 461 462 size_t subLength = length - ntohl(blobIndex->offset); 463 464 if ((error = cs_validate_blob(subBlob, subLength)) != 0) 465 return error; 466 subLength = ntohl(subBlob->length); 467 468 /* extra validation for CDs, that is also returned */ 469 if (ntohl(blobIndex->type) == CSSLOT_CODEDIRECTORY) { 470 const CS_CodeDirectory *cd = (const CS_CodeDirectory *)subBlob; 471 if ((error = cs_validate_codedirectory(cd, subLength)) != 0) 472 return error; 473 *rcd = cd; 474 } 475 } 476 477 } else if (ntohl(blob->magic) == CSMAGIC_CODEDIRECTORY) { 478 479 if ((error = cs_validate_codedirectory((const CS_CodeDirectory *)(void *)addr, length)) != 0) 480 return error; 481 *rcd = (const CS_CodeDirectory *)blob; 482 } else { 483 return EBADEXEC; 484 } 485 486 if (*rcd == NULL) 487 return EBADEXEC; 488 489 return 0; 490} 491 492/* 493 * cs_find_blob_bytes 494 * 495 * Find an blob from the superblob/code directory. The blob must have 496 * been been validated by cs_validate_csblob() before calling 497 * this. Use cs_find_blob() instead. 498 * 499 * Will also find a "raw" code directory if its stored as well as 500 * searching the superblob. 501 * 502 * Parameters: buffer Pointer to code signature 503 * length Length of buffer 504 * type type of blob to find 505 * magic the magic number for that blob 506 * 507 * Returns: pointer Success 508 * NULL Buffer not found 509 */ 510 511static const CS_GenericBlob * 512cs_find_blob_bytes(const uint8_t *addr, size_t length, uint32_t type, uint32_t magic) 513{ 514 const CS_GenericBlob *blob = (const CS_GenericBlob *)(void *)addr; 515 516 if (ntohl(blob->magic) == CSMAGIC_EMBEDDED_SIGNATURE) { 517 const CS_SuperBlob *sb = (const CS_SuperBlob *)blob; 518 size_t n, count = ntohl(sb->count); 519 520 for (n = 0; n < count; n++) { 521 if (ntohl(sb->index[n].type) != type) 522 continue; 523 uint32_t offset = ntohl(sb->index[n].offset); 524 if (length - sizeof(const CS_GenericBlob) < offset) 525 return NULL; 526 blob = (const CS_GenericBlob *)(void *)(addr + offset); 527 if (ntohl(blob->magic) != magic) 528 continue; 529 return blob; 530 } 531 } else if (type == CSSLOT_CODEDIRECTORY 532 && ntohl(blob->magic) == CSMAGIC_CODEDIRECTORY 533 && magic == CSMAGIC_CODEDIRECTORY) 534 return blob; 535 return NULL; 536} 537 538 539const CS_GenericBlob * 540cs_find_blob(struct cs_blob *csblob, uint32_t type, uint32_t magic) 541{ 542 if ((csblob->csb_flags & CS_VALID) == 0) 543 return NULL; 544 return cs_find_blob_bytes((const uint8_t *)csblob->csb_mem_kaddr, csblob->csb_mem_size, type, magic); 545} 546 547static const uint8_t * 548cs_find_special_slot(const CS_CodeDirectory *cd, uint32_t slot) 549{ 550 /* there is no zero special slot since that is the first code slot */ 551 if (ntohl(cd->nSpecialSlots) < slot || slot == 0) 552 return NULL; 553 554 return ((const uint8_t *)cd + ntohl(cd->hashOffset) - (SHA1_RESULTLEN * slot)); 555} 556 557/* 558 * CODESIGNING 559 * End of routines to navigate code signing data structures in the kernel. 560 */ 561 562/* 563 * ENTITLEMENTS 564 * Routines to navigate entitlements in the kernel. 565 */ 566 567/* Retrieve the entitlements blob for a process. 568 * Returns: 569 * EINVAL no text vnode associated with the process 570 * EBADEXEC invalid code signing data 571 * 0 no error occurred 572 * 573 * On success, out_start and out_length will point to the 574 * entitlements blob if found; or will be set to NULL/zero 575 * if there were no entitlements. 576 */ 577 578static uint8_t sha1_zero[SHA1_RESULTLEN] = { 0 }; 579 580int 581cs_entitlements_blob_get(proc_t p, void **out_start, size_t *out_length) 582{ 583 uint8_t computed_hash[SHA1_RESULTLEN]; 584 const CS_GenericBlob *entitlements; 585 const CS_CodeDirectory *code_dir; 586 struct cs_blob *csblob; 587 const uint8_t *embedded_hash; 588 SHA1_CTX context; 589 590 *out_start = NULL; 591 *out_length = 0; 592 593 if (NULL == p->p_textvp) 594 return EINVAL; 595 596 if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL) 597 return 0; 598 599 if ((code_dir = (const CS_CodeDirectory *)cs_find_blob(csblob, CSSLOT_CODEDIRECTORY, CSMAGIC_CODEDIRECTORY)) == NULL) 600 return 0; 601 602 entitlements = cs_find_blob(csblob, CSSLOT_ENTITLEMENTS, CSMAGIC_EMBEDDED_ENTITLEMENTS); 603 embedded_hash = cs_find_special_slot(code_dir, CSSLOT_ENTITLEMENTS); 604 605 if (embedded_hash == NULL) { 606 if (entitlements) 607 return EBADEXEC; 608 return 0; 609 } else if (entitlements == NULL && memcmp(embedded_hash, sha1_zero, SHA1_RESULTLEN) != 0) { 610 return EBADEXEC; 611 } 612 613 SHA1Init(&context); 614 SHA1Update(&context, entitlements, ntohl(entitlements->length)); 615 SHA1Final(computed_hash, &context); 616 if (memcmp(computed_hash, embedded_hash, SHA1_RESULTLEN) != 0) 617 return EBADEXEC; 618 619 *out_start = (void *)entitlements; 620 *out_length = ntohl(entitlements->length); 621 622 return 0; 623} 624 625/* Retrieve the codesign identity for a process. 626 * Returns: 627 * NULL an error occured 628 * string the cs_identity 629 */ 630 631const char * 632cs_identity_get(proc_t p) 633{ 634 const CS_CodeDirectory *code_dir; 635 struct cs_blob *csblob; 636 637 if (NULL == p->p_textvp) 638 return NULL; 639 640 if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL) 641 return NULL; 642 643 if ((code_dir = (const CS_CodeDirectory *)cs_find_blob(csblob, CSSLOT_CODEDIRECTORY, CSMAGIC_CODEDIRECTORY)) == NULL) 644 return NULL; 645 646 if (code_dir->identOffset == 0) 647 return NULL; 648 649 return ((const char *)code_dir) + ntohl(code_dir->identOffset); 650} 651 652 653 654/* Retrieve the codesign blob for a process. 655 * Returns: 656 * EINVAL no text vnode associated with the process 657 * 0 no error occurred 658 * 659 * On success, out_start and out_length will point to the 660 * cms blob if found; or will be set to NULL/zero 661 * if there were no blob. 662 */ 663 664int 665cs_blob_get(proc_t p, void **out_start, size_t *out_length) 666{ 667 struct cs_blob *csblob; 668 669 *out_start = NULL; 670 *out_length = 0; 671 672 if (NULL == p->p_textvp) 673 return EINVAL; 674 675 if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL) 676 return 0; 677 678 *out_start = (void *)csblob->csb_mem_kaddr; 679 *out_length = csblob->csb_mem_size; 680 681 return 0; 682} 683 684uint8_t * 685cs_get_cdhash(struct proc *p) 686{ 687 struct cs_blob *csblob; 688 689 if (NULL == p->p_textvp) 690 return NULL; 691 692 if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL) 693 return NULL; 694 695 return csblob->csb_sha1; 696} 697 698/* 699 * ENTITLEMENTS 700 * End of routines to navigate entitlements in the kernel. 701 */ 702 703 704 705/* 706 * ubc_init 707 * 708 * Initialization of the zone for Unified Buffer Cache. 709 * 710 * Parameters: (void) 711 * 712 * Returns: (void) 713 * 714 * Implicit returns: 715 * ubc_info_zone(global) initialized for subsequent allocations 716 */ 717__private_extern__ void 718ubc_init(void) 719{ 720 int i; 721 722 i = (vm_size_t) sizeof (struct ubc_info); 723 724 ubc_info_zone = zinit (i, 10000*i, 8192, "ubc_info zone"); 725 726 zone_change(ubc_info_zone, Z_NOENCRYPT, TRUE); 727} 728 729 730/* 731 * ubc_info_init 732 * 733 * Allocate and attach an empty ubc_info structure to a vnode 734 * 735 * Parameters: vp Pointer to the vnode 736 * 737 * Returns: 0 Success 738 * vnode_size:ENOMEM Not enough space 739 * vnode_size:??? Other error from vnode_getattr 740 * 741 */ 742int 743ubc_info_init(struct vnode *vp) 744{ 745 return(ubc_info_init_internal(vp, 0, 0)); 746} 747 748 749/* 750 * ubc_info_init_withsize 751 * 752 * Allocate and attach a sized ubc_info structure to a vnode 753 * 754 * Parameters: vp Pointer to the vnode 755 * filesize The size of the file 756 * 757 * Returns: 0 Success 758 * vnode_size:ENOMEM Not enough space 759 * vnode_size:??? Other error from vnode_getattr 760 */ 761int 762ubc_info_init_withsize(struct vnode *vp, off_t filesize) 763{ 764 return(ubc_info_init_internal(vp, 1, filesize)); 765} 766 767 768/* 769 * ubc_info_init_internal 770 * 771 * Allocate and attach a ubc_info structure to a vnode 772 * 773 * Parameters: vp Pointer to the vnode 774 * withfsize{0,1} Zero if the size should be obtained 775 * from the vnode; otherwise, use filesize 776 * filesize The size of the file, if withfsize == 1 777 * 778 * Returns: 0 Success 779 * vnode_size:ENOMEM Not enough space 780 * vnode_size:??? Other error from vnode_getattr 781 * 782 * Notes: We call a blocking zalloc(), and the zone was created as an 783 * expandable and collectable zone, so if no memory is available, 784 * it is possible for zalloc() to block indefinitely. zalloc() 785 * may also panic if the zone of zones is exhausted, since it's 786 * NOT expandable. 787 * 788 * We unconditionally call vnode_pager_setup(), even if this is 789 * a reuse of a ubc_info; in that case, we should probably assert 790 * that it does not already have a pager association, but do not. 791 * 792 * Since memory_object_create_named() can only fail from receiving 793 * an invalid pager argument, the explicit check and panic is 794 * merely precautionary. 795 */ 796static int 797ubc_info_init_internal(vnode_t vp, int withfsize, off_t filesize) 798{ 799 register struct ubc_info *uip; 800 void * pager; 801 int error = 0; 802 kern_return_t kret; 803 memory_object_control_t control; 804 805 uip = vp->v_ubcinfo; 806 807 /* 808 * If there is not already a ubc_info attached to the vnode, we 809 * attach one; otherwise, we will reuse the one that's there. 810 */ 811 if (uip == UBC_INFO_NULL) { 812 813 uip = (struct ubc_info *) zalloc(ubc_info_zone); 814 bzero((char *)uip, sizeof(struct ubc_info)); 815 816 uip->ui_vnode = vp; 817 uip->ui_flags = UI_INITED; 818 uip->ui_ucred = NOCRED; 819 } 820 assert(uip->ui_flags != UI_NONE); 821 assert(uip->ui_vnode == vp); 822 823 /* now set this ubc_info in the vnode */ 824 vp->v_ubcinfo = uip; 825 826 /* 827 * Allocate a pager object for this vnode 828 * 829 * XXX The value of the pager parameter is currently ignored. 830 * XXX Presumably, this API changed to avoid the race between 831 * XXX setting the pager and the UI_HASPAGER flag. 832 */ 833 pager = (void *)vnode_pager_setup(vp, uip->ui_pager); 834 assert(pager); 835 836 /* 837 * Explicitly set the pager into the ubc_info, after setting the 838 * UI_HASPAGER flag. 839 */ 840 SET(uip->ui_flags, UI_HASPAGER); 841 uip->ui_pager = pager; 842 843 /* 844 * Note: We can not use VNOP_GETATTR() to get accurate 845 * value of ui_size because this may be an NFS vnode, and 846 * nfs_getattr() can call vinvalbuf(); if this happens, 847 * ubc_info is not set up to deal with that event. 848 * So use bogus size. 849 */ 850 851 /* 852 * create a vnode - vm_object association 853 * memory_object_create_named() creates a "named" reference on the 854 * memory object we hold this reference as long as the vnode is 855 * "alive." Since memory_object_create_named() took its own reference 856 * on the vnode pager we passed it, we can drop the reference 857 * vnode_pager_setup() returned here. 858 */ 859 kret = memory_object_create_named(pager, 860 (memory_object_size_t)uip->ui_size, &control); 861 vnode_pager_deallocate(pager); 862 if (kret != KERN_SUCCESS) 863 panic("ubc_info_init: memory_object_create_named returned %d", kret); 864 865 assert(control); 866 uip->ui_control = control; /* cache the value of the mo control */ 867 SET(uip->ui_flags, UI_HASOBJREF); /* with a named reference */ 868 869 if (withfsize == 0) { 870 /* initialize the size */ 871 error = vnode_size(vp, &uip->ui_size, vfs_context_current()); 872 if (error) 873 uip->ui_size = 0; 874 } else { 875 uip->ui_size = filesize; 876 } 877 vp->v_lflag |= VNAMED_UBC; /* vnode has a named ubc reference */ 878 879 return (error); 880} 881 882 883/* 884 * ubc_info_free 885 * 886 * Free a ubc_info structure 887 * 888 * Parameters: uip A pointer to the ubc_info to free 889 * 890 * Returns: (void) 891 * 892 * Notes: If there is a credential that has subsequently been associated 893 * with the ubc_info via a call to ubc_setcred(), the reference 894 * to the credential is dropped. 895 * 896 * It's actually impossible for a ubc_info.ui_control to take the 897 * value MEMORY_OBJECT_CONTROL_NULL. 898 */ 899static void 900ubc_info_free(struct ubc_info *uip) 901{ 902 if (IS_VALID_CRED(uip->ui_ucred)) { 903 kauth_cred_unref(&uip->ui_ucred); 904 } 905 906 if (uip->ui_control != MEMORY_OBJECT_CONTROL_NULL) 907 memory_object_control_deallocate(uip->ui_control); 908 909 cluster_release(uip); 910 ubc_cs_free(uip); 911 912 zfree(ubc_info_zone, uip); 913 return; 914} 915 916 917void 918ubc_info_deallocate(struct ubc_info *uip) 919{ 920 ubc_info_free(uip); 921} 922 923/* 924 * This should be public but currently it is only used below so we 925 * defer making that change. 926 */ 927static errno_t mach_to_bsd_errno(kern_return_t mach_err) 928{ 929 switch (mach_err) { 930 case KERN_SUCCESS: 931 return 0; 932 933 case KERN_INVALID_ADDRESS: 934 case KERN_INVALID_ARGUMENT: 935 case KERN_NOT_IN_SET: 936 case KERN_INVALID_NAME: 937 case KERN_INVALID_TASK: 938 case KERN_INVALID_RIGHT: 939 case KERN_INVALID_VALUE: 940 case KERN_INVALID_CAPABILITY: 941 case KERN_INVALID_HOST: 942 case KERN_MEMORY_PRESENT: 943 case KERN_INVALID_PROCESSOR_SET: 944 case KERN_INVALID_POLICY: 945 case KERN_ALREADY_WAITING: 946 case KERN_DEFAULT_SET: 947 case KERN_EXCEPTION_PROTECTED: 948 case KERN_INVALID_LEDGER: 949 case KERN_INVALID_MEMORY_CONTROL: 950 case KERN_INVALID_SECURITY: 951 case KERN_NOT_DEPRESSED: 952 case KERN_LOCK_OWNED: 953 case KERN_LOCK_OWNED_SELF: 954 return EINVAL; 955 956 case KERN_PROTECTION_FAILURE: 957 case KERN_NOT_RECEIVER: 958 case KERN_NO_ACCESS: 959 case KERN_POLICY_STATIC: 960 return EACCES; 961 962 case KERN_NO_SPACE: 963 case KERN_RESOURCE_SHORTAGE: 964 case KERN_UREFS_OVERFLOW: 965 case KERN_INVALID_OBJECT: 966 return ENOMEM; 967 968 case KERN_FAILURE: 969 return EIO; 970 971 case KERN_MEMORY_FAILURE: 972 case KERN_POLICY_LIMIT: 973 case KERN_CODESIGN_ERROR: 974 return EPERM; 975 976 case KERN_MEMORY_ERROR: 977 return EBUSY; 978 979 case KERN_ALREADY_IN_SET: 980 case KERN_NAME_EXISTS: 981 case KERN_RIGHT_EXISTS: 982 return EEXIST; 983 984 case KERN_ABORTED: 985 return EINTR; 986 987 case KERN_TERMINATED: 988 case KERN_LOCK_SET_DESTROYED: 989 case KERN_LOCK_UNSTABLE: 990 case KERN_SEMAPHORE_DESTROYED: 991 return ENOENT; 992 993 case KERN_RPC_SERVER_TERMINATED: 994 return ECONNRESET; 995 996 case KERN_NOT_SUPPORTED: 997 return ENOTSUP; 998 999 case KERN_NODE_DOWN: 1000 return ENETDOWN; 1001 1002 case KERN_NOT_WAITING: 1003 return ENOENT; 1004 1005 case KERN_OPERATION_TIMED_OUT: 1006 return ETIMEDOUT; 1007 1008 default: 1009 return EIO; 1010 } 1011} 1012 1013/* 1014 * ubc_setsize_ex 1015 * 1016 * Tell the VM that the the size of the file represented by the vnode has 1017 * changed 1018 * 1019 * Parameters: vp The vp whose backing file size is 1020 * being changed 1021 * nsize The new size of the backing file 1022 * opts Options 1023 * 1024 * Returns: EINVAL for new size < 0 1025 * ENOENT if no UBC info exists 1026 * EAGAIN if UBC_SETSIZE_NO_FS_REENTRY option is set and new_size < old size 1027 * Other errors (mapped to errno_t) returned by VM functions 1028 * 1029 * Notes: This function will indicate success if the new size is the 1030 * same or larger than the old size (in this case, the 1031 * remainder of the file will require modification or use of 1032 * an existing upl to access successfully). 1033 * 1034 * This function will fail if the new file size is smaller, 1035 * and the memory region being invalidated was unable to 1036 * actually be invalidated and/or the last page could not be 1037 * flushed, if the new size is not aligned to a page 1038 * boundary. This is usually indicative of an I/O error. 1039 */ 1040errno_t ubc_setsize_ex(struct vnode *vp, off_t nsize, ubc_setsize_opts_t opts) 1041{ 1042 off_t osize; /* ui_size before change */ 1043 off_t lastpg, olastpgend, lastoff; 1044 struct ubc_info *uip; 1045 memory_object_control_t control; 1046 kern_return_t kret = KERN_SUCCESS; 1047 1048 if (nsize < (off_t)0) 1049 return EINVAL; 1050 1051 if (!UBCINFOEXISTS(vp)) 1052 return ENOENT; 1053 1054 uip = vp->v_ubcinfo; 1055 osize = uip->ui_size; 1056 1057 if (ISSET(opts, UBC_SETSIZE_NO_FS_REENTRY) && nsize < osize) 1058 return EAGAIN; 1059 1060 /* 1061 * Update the size before flushing the VM 1062 */ 1063 uip->ui_size = nsize; 1064 1065 if (nsize >= osize) { /* Nothing more to do */ 1066 if (nsize > osize) { 1067 lock_vnode_and_post(vp, NOTE_EXTEND); 1068 } 1069 1070 return 0; 1071 } 1072 1073 /* 1074 * When the file shrinks, invalidate the pages beyond the 1075 * new size. Also get rid of garbage beyond nsize on the 1076 * last page. The ui_size already has the nsize, so any 1077 * subsequent page-in will zero-fill the tail properly 1078 */ 1079 lastpg = trunc_page_64(nsize); 1080 olastpgend = round_page_64(osize); 1081 control = uip->ui_control; 1082 assert(control); 1083 lastoff = (nsize & PAGE_MASK_64); 1084 1085 if (lastoff) { 1086 upl_t upl; 1087 upl_page_info_t *pl; 1088 1089 /* 1090 * new EOF ends up in the middle of a page 1091 * zero the tail of this page if it's currently 1092 * present in the cache 1093 */ 1094 kret = ubc_create_upl(vp, lastpg, PAGE_SIZE, &upl, &pl, UPL_SET_LITE); 1095 1096 if (kret != KERN_SUCCESS) 1097 panic("ubc_setsize: ubc_create_upl (error = %d)\n", kret); 1098 1099 if (upl_valid_page(pl, 0)) 1100 cluster_zero(upl, (uint32_t)lastoff, PAGE_SIZE - (uint32_t)lastoff, NULL); 1101 1102 ubc_upl_abort_range(upl, 0, PAGE_SIZE, UPL_ABORT_FREE_ON_EMPTY); 1103 1104 lastpg += PAGE_SIZE_64; 1105 } 1106 if (olastpgend > lastpg) { 1107 int flags; 1108 1109 if (lastpg == 0) 1110 flags = MEMORY_OBJECT_DATA_FLUSH_ALL; 1111 else 1112 flags = MEMORY_OBJECT_DATA_FLUSH; 1113 /* 1114 * invalidate the pages beyond the new EOF page 1115 * 1116 */ 1117 kret = memory_object_lock_request(control, 1118 (memory_object_offset_t)lastpg, 1119 (memory_object_size_t)(olastpgend - lastpg), NULL, NULL, 1120 MEMORY_OBJECT_RETURN_NONE, flags, VM_PROT_NO_CHANGE); 1121 if (kret != KERN_SUCCESS) 1122 printf("ubc_setsize: invalidate failed (error = %d)\n", kret); 1123 } 1124 return mach_to_bsd_errno(kret); 1125} 1126 1127// Returns true for success 1128int ubc_setsize(vnode_t vp, off_t nsize) 1129{ 1130 return ubc_setsize_ex(vp, nsize, 0) == 0; 1131} 1132 1133/* 1134 * ubc_getsize 1135 * 1136 * Get the size of the file assocated with the specified vnode 1137 * 1138 * Parameters: vp The vnode whose size is of interest 1139 * 1140 * Returns: 0 There is no ubc_info associated with 1141 * this vnode, or the size is zero 1142 * !0 The size of the file 1143 * 1144 * Notes: Using this routine, it is not possible for a caller to 1145 * successfully distinguish between a vnode associate with a zero 1146 * length file, and a vnode with no associated ubc_info. The 1147 * caller therefore needs to not care, or needs to ensure that 1148 * they have previously successfully called ubc_info_init() or 1149 * ubc_info_init_withsize(). 1150 */ 1151off_t 1152ubc_getsize(struct vnode *vp) 1153{ 1154 /* people depend on the side effect of this working this way 1155 * as they call this for directory 1156 */ 1157 if (!UBCINFOEXISTS(vp)) 1158 return ((off_t)0); 1159 return (vp->v_ubcinfo->ui_size); 1160} 1161 1162 1163/* 1164 * ubc_umount 1165 * 1166 * Call ubc_msync(vp, 0, EOF, NULL, UBC_PUSHALL) on all the vnodes for this 1167 * mount point 1168 * 1169 * Parameters: mp The mount point 1170 * 1171 * Returns: 0 Success 1172 * 1173 * Notes: There is no failure indication for this function. 1174 * 1175 * This function is used in the unmount path; since it may block 1176 * I/O indefinitely, it should not be used in the forced unmount 1177 * path, since a device unavailability could also block that 1178 * indefinitely. 1179 * 1180 * Because there is no device ejection interlock on USB, FireWire, 1181 * or similar devices, it's possible that an ejection that begins 1182 * subsequent to the vnode_iterate() completing, either on one of 1183 * those devices, or a network mount for which the server quits 1184 * responding, etc., may cause the caller to block indefinitely. 1185 */ 1186__private_extern__ int 1187ubc_umount(struct mount *mp) 1188{ 1189 vnode_iterate(mp, 0, ubc_umcallback, 0); 1190 return(0); 1191} 1192 1193 1194/* 1195 * ubc_umcallback 1196 * 1197 * Used by ubc_umount() as an internal implementation detail; see ubc_umount() 1198 * and vnode_iterate() for details of implementation. 1199 */ 1200static int 1201ubc_umcallback(vnode_t vp, __unused void * args) 1202{ 1203 1204 if (UBCINFOEXISTS(vp)) { 1205 1206 (void) ubc_msync(vp, (off_t)0, ubc_getsize(vp), NULL, UBC_PUSHALL); 1207 } 1208 return (VNODE_RETURNED); 1209} 1210 1211 1212/* 1213 * ubc_getcred 1214 * 1215 * Get the credentials currently active for the ubc_info associated with the 1216 * vnode. 1217 * 1218 * Parameters: vp The vnode whose ubc_info credentials 1219 * are to be retrieved 1220 * 1221 * Returns: !NOCRED The credentials 1222 * NOCRED If there is no ubc_info for the vnode, 1223 * or if there is one, but it has not had 1224 * any credentials associated with it via 1225 * a call to ubc_setcred() 1226 */ 1227kauth_cred_t 1228ubc_getcred(struct vnode *vp) 1229{ 1230 if (UBCINFOEXISTS(vp)) 1231 return (vp->v_ubcinfo->ui_ucred); 1232 1233 return (NOCRED); 1234} 1235 1236 1237/* 1238 * ubc_setthreadcred 1239 * 1240 * If they are not already set, set the credentials of the ubc_info structure 1241 * associated with the vnode to those of the supplied thread; otherwise leave 1242 * them alone. 1243 * 1244 * Parameters: vp The vnode whose ubc_info creds are to 1245 * be set 1246 * p The process whose credentials are to 1247 * be used, if not running on an assumed 1248 * credential 1249 * thread The thread whose credentials are to 1250 * be used 1251 * 1252 * Returns: 1 This vnode has no associated ubc_info 1253 * 0 Success 1254 * 1255 * Notes: This function takes a proc parameter to account for bootstrap 1256 * issues where a task or thread may call this routine, either 1257 * before credentials have been initialized by bsd_init(), or if 1258 * there is no BSD info asscoiate with a mach thread yet. This 1259 * is known to happen in both the initial swap and memory mapping 1260 * calls. 1261 * 1262 * This function is generally used only in the following cases: 1263 * 1264 * o a memory mapped file via the mmap() system call 1265 * o a swap store backing file 1266 * o subsequent to a successful write via vn_write() 1267 * 1268 * The information is then used by the NFS client in order to 1269 * cons up a wire message in either the page-in or page-out path. 1270 * 1271 * There are two potential problems with the use of this API: 1272 * 1273 * o Because the write path only set it on a successful 1274 * write, there is a race window between setting the 1275 * credential and its use to evict the pages to the 1276 * remote file server 1277 * 1278 * o Because a page-in may occur prior to a write, the 1279 * credential may not be set at this time, if the page-in 1280 * is not the result of a mapping established via mmap(). 1281 * 1282 * In both these cases, this will be triggered from the paging 1283 * path, which will instead use the credential of the current 1284 * process, which in this case is either the dynamic_pager or 1285 * the kernel task, both of which utilize "root" credentials. 1286 * 1287 * This may potentially permit operations to occur which should 1288 * be denied, or it may cause to be denied operations which 1289 * should be permitted, depending on the configuration of the NFS 1290 * server. 1291 */ 1292int 1293ubc_setthreadcred(struct vnode *vp, proc_t p, thread_t thread) 1294{ 1295 struct ubc_info *uip; 1296 kauth_cred_t credp; 1297 struct uthread *uthread = get_bsdthread_info(thread); 1298 1299 if (!UBCINFOEXISTS(vp)) 1300 return (1); 1301 1302 vnode_lock(vp); 1303 1304 uip = vp->v_ubcinfo; 1305 credp = uip->ui_ucred; 1306 1307 if (!IS_VALID_CRED(credp)) { 1308 /* use per-thread cred, if assumed identity, else proc cred */ 1309 if (uthread == NULL || (uthread->uu_flag & UT_SETUID) == 0) { 1310 uip->ui_ucred = kauth_cred_proc_ref(p); 1311 } else { 1312 uip->ui_ucred = uthread->uu_ucred; 1313 kauth_cred_ref(uip->ui_ucred); 1314 } 1315 } 1316 vnode_unlock(vp); 1317 1318 return (0); 1319} 1320 1321 1322/* 1323 * ubc_setcred 1324 * 1325 * If they are not already set, set the credentials of the ubc_info structure 1326 * associated with the vnode to those of the process; otherwise leave them 1327 * alone. 1328 * 1329 * Parameters: vp The vnode whose ubc_info creds are to 1330 * be set 1331 * p The process whose credentials are to 1332 * be used 1333 * 1334 * Returns: 0 This vnode has no associated ubc_info 1335 * 1 Success 1336 * 1337 * Notes: The return values for this function are inverted from nearly 1338 * all other uses in the kernel. 1339 * 1340 * See also ubc_setthreadcred(), above. 1341 * 1342 * This function is considered deprecated, and generally should 1343 * not be used, as it is incompatible with per-thread credentials; 1344 * it exists for legacy KPI reasons. 1345 * 1346 * DEPRECATION: ubc_setcred() is being deprecated. Please use 1347 * ubc_setthreadcred() instead. 1348 */ 1349int 1350ubc_setcred(struct vnode *vp, proc_t p) 1351{ 1352 struct ubc_info *uip; 1353 kauth_cred_t credp; 1354 1355 /* If there is no ubc_info, deny the operation */ 1356 if ( !UBCINFOEXISTS(vp)) 1357 return (0); 1358 1359 /* 1360 * Check to see if there is already a credential reference in the 1361 * ubc_info; if there is not, take one on the supplied credential. 1362 */ 1363 vnode_lock(vp); 1364 uip = vp->v_ubcinfo; 1365 credp = uip->ui_ucred; 1366 if (!IS_VALID_CRED(credp)) { 1367 uip->ui_ucred = kauth_cred_proc_ref(p); 1368 } 1369 vnode_unlock(vp); 1370 1371 return (1); 1372} 1373 1374/* 1375 * ubc_getpager 1376 * 1377 * Get the pager associated with the ubc_info associated with the vnode. 1378 * 1379 * Parameters: vp The vnode to obtain the pager from 1380 * 1381 * Returns: !VNODE_PAGER_NULL The memory_object_t for the pager 1382 * VNODE_PAGER_NULL There is no ubc_info for this vnode 1383 * 1384 * Notes: For each vnode that has a ubc_info associated with it, that 1385 * ubc_info SHALL have a pager associated with it, so in the 1386 * normal case, it's impossible to return VNODE_PAGER_NULL for 1387 * a vnode with an associated ubc_info. 1388 */ 1389__private_extern__ memory_object_t 1390ubc_getpager(struct vnode *vp) 1391{ 1392 if (UBCINFOEXISTS(vp)) 1393 return (vp->v_ubcinfo->ui_pager); 1394 1395 return (0); 1396} 1397 1398 1399/* 1400 * ubc_getobject 1401 * 1402 * Get the memory object control associated with the ubc_info associated with 1403 * the vnode 1404 * 1405 * Parameters: vp The vnode to obtain the memory object 1406 * from 1407 * flags DEPRECATED 1408 * 1409 * Returns: !MEMORY_OBJECT_CONTROL_NULL 1410 * MEMORY_OBJECT_CONTROL_NULL 1411 * 1412 * Notes: Historically, if the flags were not "do not reactivate", this 1413 * function would look up the memory object using the pager if 1414 * it did not exist (this could be the case if the vnode had 1415 * been previously reactivated). The flags would also permit a 1416 * hold to be requested, which would have created an object 1417 * reference, if one had not already existed. This usage is 1418 * deprecated, as it would permit a race between finding and 1419 * taking the reference vs. a single reference being dropped in 1420 * another thread. 1421 */ 1422memory_object_control_t 1423ubc_getobject(struct vnode *vp, __unused int flags) 1424{ 1425 if (UBCINFOEXISTS(vp)) 1426 return((vp->v_ubcinfo->ui_control)); 1427 1428 return (MEMORY_OBJECT_CONTROL_NULL); 1429} 1430 1431boolean_t 1432ubc_strict_uncached_IO(struct vnode *vp) 1433{ 1434 boolean_t result = FALSE; 1435 1436 if (UBCINFOEXISTS(vp)) { 1437 result = memory_object_is_slid(vp->v_ubcinfo->ui_control); 1438 } 1439 return result; 1440} 1441 1442/* 1443 * ubc_blktooff 1444 * 1445 * Convert a given block number to a memory backing object (file) offset for a 1446 * given vnode 1447 * 1448 * Parameters: vp The vnode in which the block is located 1449 * blkno The block number to convert 1450 * 1451 * Returns: !-1 The offset into the backing object 1452 * -1 There is no ubc_info associated with 1453 * the vnode 1454 * -1 An error occurred in the underlying VFS 1455 * while translating the block to an 1456 * offset; the most likely cause is that 1457 * the caller specified a block past the 1458 * end of the file, but this could also be 1459 * any other error from VNOP_BLKTOOFF(). 1460 * 1461 * Note: Representing the error in band loses some information, but does 1462 * not occlude a valid offset, since an off_t of -1 is normally 1463 * used to represent EOF. If we had a more reliable constant in 1464 * our header files for it (i.e. explicitly cast to an off_t), we 1465 * would use it here instead. 1466 */ 1467off_t 1468ubc_blktooff(vnode_t vp, daddr64_t blkno) 1469{ 1470 off_t file_offset = -1; 1471 int error; 1472 1473 if (UBCINFOEXISTS(vp)) { 1474 error = VNOP_BLKTOOFF(vp, blkno, &file_offset); 1475 if (error) 1476 file_offset = -1; 1477 } 1478 1479 return (file_offset); 1480} 1481 1482 1483/* 1484 * ubc_offtoblk 1485 * 1486 * Convert a given offset in a memory backing object into a block number for a 1487 * given vnode 1488 * 1489 * Parameters: vp The vnode in which the offset is 1490 * located 1491 * offset The offset into the backing object 1492 * 1493 * Returns: !-1 The returned block number 1494 * -1 There is no ubc_info associated with 1495 * the vnode 1496 * -1 An error occurred in the underlying VFS 1497 * while translating the block to an 1498 * offset; the most likely cause is that 1499 * the caller specified a block past the 1500 * end of the file, but this could also be 1501 * any other error from VNOP_OFFTOBLK(). 1502 * 1503 * Note: Representing the error in band loses some information, but does 1504 * not occlude a valid block number, since block numbers exceed 1505 * the valid range for offsets, due to their relative sizes. If 1506 * we had a more reliable constant than -1 in our header files 1507 * for it (i.e. explicitly cast to an daddr64_t), we would use it 1508 * here instead. 1509 */ 1510daddr64_t 1511ubc_offtoblk(vnode_t vp, off_t offset) 1512{ 1513 daddr64_t blkno = -1; 1514 int error = 0; 1515 1516 if (UBCINFOEXISTS(vp)) { 1517 error = VNOP_OFFTOBLK(vp, offset, &blkno); 1518 if (error) 1519 blkno = -1; 1520 } 1521 1522 return (blkno); 1523} 1524 1525 1526/* 1527 * ubc_pages_resident 1528 * 1529 * Determine whether or not a given vnode has pages resident via the memory 1530 * object control associated with the ubc_info associated with the vnode 1531 * 1532 * Parameters: vp The vnode we want to know about 1533 * 1534 * Returns: 1 Yes 1535 * 0 No 1536 */ 1537int 1538ubc_pages_resident(vnode_t vp) 1539{ 1540 kern_return_t kret; 1541 boolean_t has_pages_resident; 1542 1543 if (!UBCINFOEXISTS(vp)) 1544 return (0); 1545 1546 /* 1547 * The following call may fail if an invalid ui_control is specified, 1548 * or if there is no VM object associated with the control object. In 1549 * either case, reacting to it as if there were no pages resident will 1550 * result in correct behavior. 1551 */ 1552 kret = memory_object_pages_resident(vp->v_ubcinfo->ui_control, &has_pages_resident); 1553 1554 if (kret != KERN_SUCCESS) 1555 return (0); 1556 1557 if (has_pages_resident == TRUE) 1558 return (1); 1559 1560 return (0); 1561} 1562 1563/* 1564 * ubc_msync 1565 * 1566 * Clean and/or invalidate a range in the memory object that backs this vnode 1567 * 1568 * Parameters: vp The vnode whose associated ubc_info's 1569 * associated memory object is to have a 1570 * range invalidated within it 1571 * beg_off The start of the range, as an offset 1572 * end_off The end of the range, as an offset 1573 * resid_off The address of an off_t supplied by the 1574 * caller; may be set to NULL to ignore 1575 * flags See ubc_msync_internal() 1576 * 1577 * Returns: 0 Success 1578 * !0 Failure; an errno is returned 1579 * 1580 * Implicit Returns: 1581 * *resid_off, modified If non-NULL, the contents are ALWAYS 1582 * modified; they are initialized to the 1583 * beg_off, and in case of an I/O error, 1584 * the difference between beg_off and the 1585 * current value will reflect what was 1586 * able to be written before the error 1587 * occurred. If no error is returned, the 1588 * value of the resid_off is undefined; do 1589 * NOT use it in place of end_off if you 1590 * intend to increment from the end of the 1591 * last call and call iteratively. 1592 * 1593 * Notes: see ubc_msync_internal() for more detailed information. 1594 * 1595 */ 1596errno_t 1597ubc_msync(vnode_t vp, off_t beg_off, off_t end_off, off_t *resid_off, int flags) 1598{ 1599 int retval; 1600 int io_errno = 0; 1601 1602 if (resid_off) 1603 *resid_off = beg_off; 1604 1605 retval = ubc_msync_internal(vp, beg_off, end_off, resid_off, flags, &io_errno); 1606 1607 if (retval == 0 && io_errno == 0) 1608 return (EINVAL); 1609 return (io_errno); 1610} 1611 1612 1613/* 1614 * ubc_msync_internal 1615 * 1616 * Clean and/or invalidate a range in the memory object that backs this vnode 1617 * 1618 * Parameters: vp The vnode whose associated ubc_info's 1619 * associated memory object is to have a 1620 * range invalidated within it 1621 * beg_off The start of the range, as an offset 1622 * end_off The end of the range, as an offset 1623 * resid_off The address of an off_t supplied by the 1624 * caller; may be set to NULL to ignore 1625 * flags MUST contain at least one of the flags 1626 * UBC_INVALIDATE, UBC_PUSHDIRTY, or 1627 * UBC_PUSHALL; if UBC_PUSHDIRTY is used, 1628 * UBC_SYNC may also be specified to cause 1629 * this function to block until the 1630 * operation is complete. The behavior 1631 * of UBC_SYNC is otherwise undefined. 1632 * io_errno The address of an int to contain the 1633 * errno from a failed I/O operation, if 1634 * one occurs; may be set to NULL to 1635 * ignore 1636 * 1637 * Returns: 1 Success 1638 * 0 Failure 1639 * 1640 * Implicit Returns: 1641 * *resid_off, modified The contents of this offset MAY be 1642 * modified; in case of an I/O error, the 1643 * difference between beg_off and the 1644 * current value will reflect what was 1645 * able to be written before the error 1646 * occurred. 1647 * *io_errno, modified The contents of this offset are set to 1648 * an errno, if an error occurs; if the 1649 * caller supplies an io_errno parameter, 1650 * they should be careful to initialize it 1651 * to 0 before calling this function to 1652 * enable them to distinguish an error 1653 * with a valid *resid_off from an invalid 1654 * one, and to avoid potentially falsely 1655 * reporting an error, depending on use. 1656 * 1657 * Notes: If there is no ubc_info associated with the vnode supplied, 1658 * this function immediately returns success. 1659 * 1660 * If the value of end_off is less than or equal to beg_off, this 1661 * function immediately returns success; that is, end_off is NOT 1662 * inclusive. 1663 * 1664 * IMPORTANT: one of the flags UBC_INVALIDATE, UBC_PUSHDIRTY, or 1665 * UBC_PUSHALL MUST be specified; that is, it is NOT possible to 1666 * attempt to block on in-progress I/O by calling this function 1667 * with UBC_PUSHDIRTY, and then later call it with just UBC_SYNC 1668 * in order to block pending on the I/O already in progress. 1669 * 1670 * The start offset is truncated to the page boundary and the 1671 * size is adjusted to include the last page in the range; that 1672 * is, end_off on exactly a page boundary will not change if it 1673 * is rounded, and the range of bytes written will be from the 1674 * truncate beg_off to the rounded (end_off - 1). 1675 */ 1676static int 1677ubc_msync_internal(vnode_t vp, off_t beg_off, off_t end_off, off_t *resid_off, int flags, int *io_errno) 1678{ 1679 memory_object_size_t tsize; 1680 kern_return_t kret; 1681 int request_flags = 0; 1682 int flush_flags = MEMORY_OBJECT_RETURN_NONE; 1683 1684 if ( !UBCINFOEXISTS(vp)) 1685 return (0); 1686 if ((flags & (UBC_INVALIDATE | UBC_PUSHDIRTY | UBC_PUSHALL)) == 0) 1687 return (0); 1688 if (end_off <= beg_off) 1689 return (1); 1690 1691 if (flags & UBC_INVALIDATE) 1692 /* 1693 * discard the resident pages 1694 */ 1695 request_flags = (MEMORY_OBJECT_DATA_FLUSH | MEMORY_OBJECT_DATA_NO_CHANGE); 1696 1697 if (flags & UBC_SYNC) 1698 /* 1699 * wait for all the I/O to complete before returning 1700 */ 1701 request_flags |= MEMORY_OBJECT_IO_SYNC; 1702 1703 if (flags & UBC_PUSHDIRTY) 1704 /* 1705 * we only return the dirty pages in the range 1706 */ 1707 flush_flags = MEMORY_OBJECT_RETURN_DIRTY; 1708 1709 if (flags & UBC_PUSHALL) 1710 /* 1711 * then return all the interesting pages in the range (both 1712 * dirty and precious) to the pager 1713 */ 1714 flush_flags = MEMORY_OBJECT_RETURN_ALL; 1715 1716 beg_off = trunc_page_64(beg_off); 1717 end_off = round_page_64(end_off); 1718 tsize = (memory_object_size_t)end_off - beg_off; 1719 1720 /* flush and/or invalidate pages in the range requested */ 1721 kret = memory_object_lock_request(vp->v_ubcinfo->ui_control, 1722 beg_off, tsize, 1723 (memory_object_offset_t *)resid_off, 1724 io_errno, flush_flags, request_flags, 1725 VM_PROT_NO_CHANGE); 1726 1727 return ((kret == KERN_SUCCESS) ? 1 : 0); 1728} 1729 1730 1731/* 1732 * ubc_map 1733 * 1734 * Explicitly map a vnode that has an associate ubc_info, and add a reference 1735 * to it for the ubc system, if there isn't one already, so it will not be 1736 * recycled while it's in use, and set flags on the ubc_info to indicate that 1737 * we have done this 1738 * 1739 * Parameters: vp The vnode to map 1740 * flags The mapping flags for the vnode; this 1741 * will be a combination of one or more of 1742 * PROT_READ, PROT_WRITE, and PROT_EXEC 1743 * 1744 * Returns: 0 Success 1745 * EPERM Permission was denied 1746 * 1747 * Notes: An I/O reference on the vnode must already be held on entry 1748 * 1749 * If there is no ubc_info associated with the vnode, this function 1750 * will return success. 1751 * 1752 * If a permission error occurs, this function will return 1753 * failure; all other failures will cause this function to return 1754 * success. 1755 * 1756 * IMPORTANT: This is an internal use function, and its symbols 1757 * are not exported, hence its error checking is not very robust. 1758 * It is primarily used by: 1759 * 1760 * o mmap(), when mapping a file 1761 * o When mapping a shared file (a shared library in the 1762 * shared segment region) 1763 * o When loading a program image during the exec process 1764 * 1765 * ...all of these uses ignore the return code, and any fault that 1766 * results later because of a failure is handled in the fix-up path 1767 * of the fault handler. The interface exists primarily as a 1768 * performance hint. 1769 * 1770 * Given that third party implementation of the type of interfaces 1771 * that would use this function, such as alternative executable 1772 * formats, etc., are unsupported, this function is not exported 1773 * for general use. 1774 * 1775 * The extra reference is held until the VM system unmaps the 1776 * vnode from its own context to maintain a vnode reference in 1777 * cases like open()/mmap()/close(), which leave the backing 1778 * object referenced by a mapped memory region in a process 1779 * address space. 1780 */ 1781__private_extern__ int 1782ubc_map(vnode_t vp, int flags) 1783{ 1784 struct ubc_info *uip; 1785 int error = 0; 1786 int need_ref = 0; 1787 int need_wakeup = 0; 1788 1789 if (UBCINFOEXISTS(vp)) { 1790 1791 vnode_lock(vp); 1792 uip = vp->v_ubcinfo; 1793 1794 while (ISSET(uip->ui_flags, UI_MAPBUSY)) { 1795 SET(uip->ui_flags, UI_MAPWAITING); 1796 (void) msleep(&uip->ui_flags, &vp->v_lock, 1797 PRIBIO, "ubc_map", NULL); 1798 } 1799 SET(uip->ui_flags, UI_MAPBUSY); 1800 vnode_unlock(vp); 1801 1802 error = VNOP_MMAP(vp, flags, vfs_context_current()); 1803 1804 if (error != EPERM) 1805 error = 0; 1806 1807 vnode_lock_spin(vp); 1808 1809 if (error == 0) { 1810 if ( !ISSET(uip->ui_flags, UI_ISMAPPED)) 1811 need_ref = 1; 1812 SET(uip->ui_flags, (UI_WASMAPPED | UI_ISMAPPED)); 1813 if (flags & PROT_WRITE) { 1814 SET(uip->ui_flags, UI_MAPPEDWRITE); 1815 } 1816 } 1817 CLR(uip->ui_flags, UI_MAPBUSY); 1818 1819 if (ISSET(uip->ui_flags, UI_MAPWAITING)) { 1820 CLR(uip->ui_flags, UI_MAPWAITING); 1821 need_wakeup = 1; 1822 } 1823 vnode_unlock(vp); 1824 1825 if (need_wakeup) 1826 wakeup(&uip->ui_flags); 1827 1828 if (need_ref) 1829 vnode_ref(vp); 1830 } 1831 return (error); 1832} 1833 1834 1835/* 1836 * ubc_destroy_named 1837 * 1838 * Destroy the named memory object associated with the ubc_info control object 1839 * associated with the designated vnode, if there is a ubc_info associated 1840 * with the vnode, and a control object is associated with it 1841 * 1842 * Parameters: vp The designated vnode 1843 * 1844 * Returns: (void) 1845 * 1846 * Notes: This function is called on vnode termination for all vnodes, 1847 * and must therefore not assume that there is a ubc_info that is 1848 * associated with the vnode, nor that there is a control object 1849 * associated with the ubc_info. 1850 * 1851 * If all the conditions necessary are present, this function 1852 * calls memory_object_destory(), which will in turn end up 1853 * calling ubc_unmap() to release any vnode references that were 1854 * established via ubc_map(). 1855 * 1856 * IMPORTANT: This is an internal use function that is used 1857 * exclusively by the internal use function vclean(). 1858 */ 1859__private_extern__ void 1860ubc_destroy_named(vnode_t vp) 1861{ 1862 memory_object_control_t control; 1863 struct ubc_info *uip; 1864 kern_return_t kret; 1865 1866 if (UBCINFOEXISTS(vp)) { 1867 uip = vp->v_ubcinfo; 1868 1869 /* Terminate the memory object */ 1870 control = ubc_getobject(vp, UBC_HOLDOBJECT); 1871 if (control != MEMORY_OBJECT_CONTROL_NULL) { 1872 kret = memory_object_destroy(control, 0); 1873 if (kret != KERN_SUCCESS) 1874 panic("ubc_destroy_named: memory_object_destroy failed"); 1875 } 1876 } 1877} 1878 1879 1880/* 1881 * ubc_isinuse 1882 * 1883 * Determine whether or not a vnode is currently in use by ubc at a level in 1884 * excess of the requested busycount 1885 * 1886 * Parameters: vp The vnode to check 1887 * busycount The threshold busy count, used to bias 1888 * the count usually already held by the 1889 * caller to avoid races 1890 * 1891 * Returns: 1 The vnode is in use over the threshold 1892 * 0 The vnode is not in use over the 1893 * threshold 1894 * 1895 * Notes: Because the vnode is only held locked while actually asking 1896 * the use count, this function only represents a snapshot of the 1897 * current state of the vnode. If more accurate information is 1898 * required, an additional busycount should be held by the caller 1899 * and a non-zero busycount used. 1900 * 1901 * If there is no ubc_info associated with the vnode, this 1902 * function will report that the vnode is not in use by ubc. 1903 */ 1904int 1905ubc_isinuse(struct vnode *vp, int busycount) 1906{ 1907 if ( !UBCINFOEXISTS(vp)) 1908 return (0); 1909 return(ubc_isinuse_locked(vp, busycount, 0)); 1910} 1911 1912 1913/* 1914 * ubc_isinuse_locked 1915 * 1916 * Determine whether or not a vnode is currently in use by ubc at a level in 1917 * excess of the requested busycount 1918 * 1919 * Parameters: vp The vnode to check 1920 * busycount The threshold busy count, used to bias 1921 * the count usually already held by the 1922 * caller to avoid races 1923 * locked True if the vnode is already locked by 1924 * the caller 1925 * 1926 * Returns: 1 The vnode is in use over the threshold 1927 * 0 The vnode is not in use over the 1928 * threshold 1929 * 1930 * Notes: If the vnode is not locked on entry, it is locked while 1931 * actually asking the use count. If this is the case, this 1932 * function only represents a snapshot of the current state of 1933 * the vnode. If more accurate information is required, the 1934 * vnode lock should be held by the caller, otherwise an 1935 * additional busycount should be held by the caller and a 1936 * non-zero busycount used. 1937 * 1938 * If there is no ubc_info associated with the vnode, this 1939 * function will report that the vnode is not in use by ubc. 1940 */ 1941int 1942ubc_isinuse_locked(struct vnode *vp, int busycount, int locked) 1943{ 1944 int retval = 0; 1945 1946 1947 if (!locked) 1948 vnode_lock_spin(vp); 1949 1950 if ((vp->v_usecount - vp->v_kusecount) > busycount) 1951 retval = 1; 1952 1953 if (!locked) 1954 vnode_unlock(vp); 1955 return (retval); 1956} 1957 1958 1959/* 1960 * ubc_unmap 1961 * 1962 * Reverse the effects of a ubc_map() call for a given vnode 1963 * 1964 * Parameters: vp vnode to unmap from ubc 1965 * 1966 * Returns: (void) 1967 * 1968 * Notes: This is an internal use function used by vnode_pager_unmap(). 1969 * It will attempt to obtain a reference on the supplied vnode, 1970 * and if it can do so, and there is an associated ubc_info, and 1971 * the flags indicate that it was mapped via ubc_map(), then the 1972 * flag is cleared, the mapping removed, and the reference taken 1973 * by ubc_map() is released. 1974 * 1975 * IMPORTANT: This MUST only be called by the VM 1976 * to prevent race conditions. 1977 */ 1978__private_extern__ void 1979ubc_unmap(struct vnode *vp) 1980{ 1981 struct ubc_info *uip; 1982 int need_rele = 0; 1983 int need_wakeup = 0; 1984 1985 if (vnode_getwithref(vp)) 1986 return; 1987 1988 if (UBCINFOEXISTS(vp)) { 1989 bool want_fsevent = false; 1990 1991 vnode_lock(vp); 1992 uip = vp->v_ubcinfo; 1993 1994 while (ISSET(uip->ui_flags, UI_MAPBUSY)) { 1995 SET(uip->ui_flags, UI_MAPWAITING); 1996 (void) msleep(&uip->ui_flags, &vp->v_lock, 1997 PRIBIO, "ubc_unmap", NULL); 1998 } 1999 SET(uip->ui_flags, UI_MAPBUSY); 2000 2001 if (ISSET(uip->ui_flags, UI_ISMAPPED)) { 2002 if (ISSET(uip->ui_flags, UI_MAPPEDWRITE)) 2003 want_fsevent = true; 2004 2005 need_rele = 1; 2006 2007 /* 2008 * We want to clear the mapped flags after we've called 2009 * VNOP_MNOMAP to avoid certain races and allow 2010 * VNOP_MNOMAP to call ubc_is_mapped_writable. 2011 */ 2012 } 2013 vnode_unlock(vp); 2014 2015 if (need_rele) { 2016 vfs_context_t ctx = vfs_context_current(); 2017 2018 (void)VNOP_MNOMAP(vp, ctx); 2019 2020#if CONFIG_FSE 2021 /* 2022 * Why do we want an fsevent here? Normally the 2023 * content modified fsevent is posted when a file is 2024 * closed and only if it's written to via conventional 2025 * means. It's perfectly legal to close a file and 2026 * keep your mappings and we don't currently track 2027 * whether it was written to via a mapping. 2028 * Therefore, we need to post an fsevent here if the 2029 * file was mapped writable. This may result in false 2030 * events, i.e. we post a notification when nothing 2031 * has really changed. 2032 */ 2033 if (want_fsevent && need_fsevent(FSE_CONTENT_MODIFIED, vp)) { 2034 add_fsevent(FSE_CONTENT_MODIFIED, ctx, 2035 FSE_ARG_VNODE, vp, 2036 FSE_ARG_DONE); 2037 } 2038#endif 2039 2040 vnode_rele(vp); 2041 } 2042 2043 vnode_lock_spin(vp); 2044 2045 if (need_rele) 2046 CLR(uip->ui_flags, UI_ISMAPPED | UI_MAPPEDWRITE); 2047 2048 CLR(uip->ui_flags, UI_MAPBUSY); 2049 2050 if (ISSET(uip->ui_flags, UI_MAPWAITING)) { 2051 CLR(uip->ui_flags, UI_MAPWAITING); 2052 need_wakeup = 1; 2053 } 2054 vnode_unlock(vp); 2055 2056 if (need_wakeup) 2057 wakeup(&uip->ui_flags); 2058 2059 } 2060 /* 2061 * the drop of the vnode ref will cleanup 2062 */ 2063 vnode_put(vp); 2064} 2065 2066 2067/* 2068 * ubc_page_op 2069 * 2070 * Manipulate individual page state for a vnode with an associated ubc_info 2071 * with an associated memory object control. 2072 * 2073 * Parameters: vp The vnode backing the page 2074 * f_offset A file offset interior to the page 2075 * ops The operations to perform, as a bitmap 2076 * (see below for more information) 2077 * phys_entryp The address of a ppnum_t; may be NULL 2078 * to ignore 2079 * flagsp A pointer to an int to contain flags; 2080 * may be NULL to ignore 2081 * 2082 * Returns: KERN_SUCCESS Success 2083 * KERN_INVALID_ARGUMENT If the memory object control has no VM 2084 * object associated 2085 * KERN_INVALID_OBJECT If UPL_POP_PHYSICAL and the object is 2086 * not physically contiguous 2087 * KERN_INVALID_OBJECT If !UPL_POP_PHYSICAL and the object is 2088 * physically contiguous 2089 * KERN_FAILURE If the page cannot be looked up 2090 * 2091 * Implicit Returns: 2092 * *phys_entryp (modified) If phys_entryp is non-NULL and 2093 * UPL_POP_PHYSICAL 2094 * *flagsp (modified) If flagsp is non-NULL and there was 2095 * !UPL_POP_PHYSICAL and a KERN_SUCCESS 2096 * 2097 * Notes: For object boundaries, it is considerably more efficient to 2098 * ensure that f_offset is in fact on a page boundary, as this 2099 * will avoid internal use of the hash table to identify the 2100 * page, and would therefore skip a number of early optimizations. 2101 * Since this is a page operation anyway, the caller should try 2102 * to pass only a page aligned offset because of this. 2103 * 2104 * *flagsp may be modified even if this function fails. If it is 2105 * modified, it will contain the condition of the page before the 2106 * requested operation was attempted; these will only include the 2107 * bitmap flags, and not the PL_POP_PHYSICAL, UPL_POP_DUMP, 2108 * UPL_POP_SET, or UPL_POP_CLR bits. 2109 * 2110 * The flags field may contain a specific operation, such as 2111 * UPL_POP_PHYSICAL or UPL_POP_DUMP: 2112 * 2113 * o UPL_POP_PHYSICAL Fail if not contiguous; if 2114 * *phys_entryp and successful, set 2115 * *phys_entryp 2116 * o UPL_POP_DUMP Dump the specified page 2117 * 2118 * Otherwise, it is treated as a bitmap of one or more page 2119 * operations to perform on the final memory object; allowable 2120 * bit values are: 2121 * 2122 * o UPL_POP_DIRTY The page is dirty 2123 * o UPL_POP_PAGEOUT The page is paged out 2124 * o UPL_POP_PRECIOUS The page is precious 2125 * o UPL_POP_ABSENT The page is absent 2126 * o UPL_POP_BUSY The page is busy 2127 * 2128 * If the page status is only being queried and not modified, then 2129 * not other bits should be specified. However, if it is being 2130 * modified, exactly ONE of the following bits should be set: 2131 * 2132 * o UPL_POP_SET Set the current bitmap bits 2133 * o UPL_POP_CLR Clear the current bitmap bits 2134 * 2135 * Thus to effect a combination of setting an clearing, it may be 2136 * necessary to call this function twice. If this is done, the 2137 * set should be used before the clear, since clearing may trigger 2138 * a wakeup on the destination page, and if the page is backed by 2139 * an encrypted swap file, setting will trigger the decryption 2140 * needed before the wakeup occurs. 2141 */ 2142kern_return_t 2143ubc_page_op( 2144 struct vnode *vp, 2145 off_t f_offset, 2146 int ops, 2147 ppnum_t *phys_entryp, 2148 int *flagsp) 2149{ 2150 memory_object_control_t control; 2151 2152 control = ubc_getobject(vp, UBC_FLAGS_NONE); 2153 if (control == MEMORY_OBJECT_CONTROL_NULL) 2154 return KERN_INVALID_ARGUMENT; 2155 2156 return (memory_object_page_op(control, 2157 (memory_object_offset_t)f_offset, 2158 ops, 2159 phys_entryp, 2160 flagsp)); 2161} 2162 2163 2164/* 2165 * ubc_range_op 2166 * 2167 * Manipulate page state for a range of memory for a vnode with an associated 2168 * ubc_info with an associated memory object control, when page level state is 2169 * not required to be returned from the call (i.e. there are no phys_entryp or 2170 * flagsp parameters to this call, and it takes a range which may contain 2171 * multiple pages, rather than an offset interior to a single page). 2172 * 2173 * Parameters: vp The vnode backing the page 2174 * f_offset_beg A file offset interior to the start page 2175 * f_offset_end A file offset interior to the end page 2176 * ops The operations to perform, as a bitmap 2177 * (see below for more information) 2178 * range The address of an int; may be NULL to 2179 * ignore 2180 * 2181 * Returns: KERN_SUCCESS Success 2182 * KERN_INVALID_ARGUMENT If the memory object control has no VM 2183 * object associated 2184 * KERN_INVALID_OBJECT If the object is physically contiguous 2185 * 2186 * Implicit Returns: 2187 * *range (modified) If range is non-NULL, its contents will 2188 * be modified to contain the number of 2189 * bytes successfully operated upon. 2190 * 2191 * Notes: IMPORTANT: This function cannot be used on a range that 2192 * consists of physically contiguous pages. 2193 * 2194 * For object boundaries, it is considerably more efficient to 2195 * ensure that f_offset_beg and f_offset_end are in fact on page 2196 * boundaries, as this will avoid internal use of the hash table 2197 * to identify the page, and would therefore skip a number of 2198 * early optimizations. Since this is an operation on a set of 2199 * pages anyway, the caller should try to pass only a page aligned 2200 * offsets because of this. 2201 * 2202 * *range will be modified only if this function succeeds. 2203 * 2204 * The flags field MUST contain a specific operation; allowable 2205 * values are: 2206 * 2207 * o UPL_ROP_ABSENT Returns the extent of the range 2208 * presented which is absent, starting 2209 * with the start address presented 2210 * 2211 * o UPL_ROP_PRESENT Returns the extent of the range 2212 * presented which is present (resident), 2213 * starting with the start address 2214 * presented 2215 * o UPL_ROP_DUMP Dump the pages which are found in the 2216 * target object for the target range. 2217 * 2218 * IMPORTANT: For UPL_ROP_ABSENT and UPL_ROP_PRESENT; if there are 2219 * multiple regions in the range, only the first matching region 2220 * is returned. 2221 */ 2222kern_return_t 2223ubc_range_op( 2224 struct vnode *vp, 2225 off_t f_offset_beg, 2226 off_t f_offset_end, 2227 int ops, 2228 int *range) 2229{ 2230 memory_object_control_t control; 2231 2232 control = ubc_getobject(vp, UBC_FLAGS_NONE); 2233 if (control == MEMORY_OBJECT_CONTROL_NULL) 2234 return KERN_INVALID_ARGUMENT; 2235 2236 return (memory_object_range_op(control, 2237 (memory_object_offset_t)f_offset_beg, 2238 (memory_object_offset_t)f_offset_end, 2239 ops, 2240 range)); 2241} 2242 2243 2244/* 2245 * ubc_create_upl 2246 * 2247 * Given a vnode, cause the population of a portion of the vm_object; based on 2248 * the nature of the request, the pages returned may contain valid data, or 2249 * they may be uninitialized. 2250 * 2251 * Parameters: vp The vnode from which to create the upl 2252 * f_offset The start offset into the backing store 2253 * represented by the vnode 2254 * bufsize The size of the upl to create 2255 * uplp Pointer to the upl_t to receive the 2256 * created upl; MUST NOT be NULL 2257 * plp Pointer to receive the internal page 2258 * list for the created upl; MAY be NULL 2259 * to ignore 2260 * 2261 * Returns: KERN_SUCCESS The requested upl has been created 2262 * KERN_INVALID_ARGUMENT The bufsize argument is not an even 2263 * multiple of the page size 2264 * KERN_INVALID_ARGUMENT There is no ubc_info associated with 2265 * the vnode, or there is no memory object 2266 * control associated with the ubc_info 2267 * memory_object_upl_request:KERN_INVALID_VALUE 2268 * The supplied upl_flags argument is 2269 * invalid 2270 * Implicit Returns: 2271 * *uplp (modified) 2272 * *plp (modified) If non-NULL, the value of *plp will be 2273 * modified to point to the internal page 2274 * list; this modification may occur even 2275 * if this function is unsuccessful, in 2276 * which case the contents may be invalid 2277 * 2278 * Note: If successful, the returned *uplp MUST subsequently be freed 2279 * via a call to ubc_upl_commit(), ubc_upl_commit_range(), 2280 * ubc_upl_abort(), or ubc_upl_abort_range(). 2281 */ 2282kern_return_t 2283ubc_create_upl( 2284 struct vnode *vp, 2285 off_t f_offset, 2286 int bufsize, 2287 upl_t *uplp, 2288 upl_page_info_t **plp, 2289 int uplflags) 2290{ 2291 memory_object_control_t control; 2292 kern_return_t kr; 2293 2294 if (plp != NULL) 2295 *plp = NULL; 2296 *uplp = NULL; 2297 2298 if (bufsize & 0xfff) 2299 return KERN_INVALID_ARGUMENT; 2300 2301 if (bufsize > MAX_UPL_SIZE_BYTES) 2302 return KERN_INVALID_ARGUMENT; 2303 2304 if (uplflags & (UPL_UBC_MSYNC | UPL_UBC_PAGEOUT | UPL_UBC_PAGEIN)) { 2305 2306 if (uplflags & UPL_UBC_MSYNC) { 2307 uplflags &= UPL_RET_ONLY_DIRTY; 2308 2309 uplflags |= UPL_COPYOUT_FROM | UPL_CLEAN_IN_PLACE | 2310 UPL_SET_INTERNAL | UPL_SET_LITE; 2311 2312 } else if (uplflags & UPL_UBC_PAGEOUT) { 2313 uplflags &= UPL_RET_ONLY_DIRTY; 2314 2315 if (uplflags & UPL_RET_ONLY_DIRTY) 2316 uplflags |= UPL_NOBLOCK; 2317 2318 uplflags |= UPL_FOR_PAGEOUT | UPL_CLEAN_IN_PLACE | 2319 UPL_COPYOUT_FROM | UPL_SET_INTERNAL | UPL_SET_LITE; 2320 } else { 2321 uplflags |= UPL_RET_ONLY_ABSENT | 2322 UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | 2323 UPL_SET_INTERNAL | UPL_SET_LITE; 2324 2325 /* 2326 * if the requested size == PAGE_SIZE, we don't want to set 2327 * the UPL_NOBLOCK since we may be trying to recover from a 2328 * previous partial pagein I/O that occurred because we were low 2329 * on memory and bailed early in order to honor the UPL_NOBLOCK... 2330 * since we're only asking for a single page, we can block w/o fear 2331 * of tying up pages while waiting for more to become available 2332 */ 2333 if (bufsize > PAGE_SIZE) 2334 uplflags |= UPL_NOBLOCK; 2335 } 2336 } else { 2337 uplflags &= ~UPL_FOR_PAGEOUT; 2338 2339 if (uplflags & UPL_WILL_BE_DUMPED) { 2340 uplflags &= ~UPL_WILL_BE_DUMPED; 2341 uplflags |= (UPL_NO_SYNC|UPL_SET_INTERNAL); 2342 } else 2343 uplflags |= (UPL_NO_SYNC|UPL_CLEAN_IN_PLACE|UPL_SET_INTERNAL); 2344 } 2345 control = ubc_getobject(vp, UBC_FLAGS_NONE); 2346 if (control == MEMORY_OBJECT_CONTROL_NULL) 2347 return KERN_INVALID_ARGUMENT; 2348 2349 kr = memory_object_upl_request(control, f_offset, bufsize, uplp, NULL, NULL, uplflags); 2350 if (kr == KERN_SUCCESS && plp != NULL) 2351 *plp = UPL_GET_INTERNAL_PAGE_LIST(*uplp); 2352 return kr; 2353} 2354 2355 2356/* 2357 * ubc_upl_maxbufsize 2358 * 2359 * Return the maximum bufsize ubc_create_upl( ) will take. 2360 * 2361 * Parameters: none 2362 * 2363 * Returns: maximum size buffer (in bytes) ubc_create_upl( ) will take. 2364 */ 2365upl_size_t 2366ubc_upl_maxbufsize( 2367 void) 2368{ 2369 return(MAX_UPL_SIZE_BYTES); 2370} 2371 2372/* 2373 * ubc_upl_map 2374 * 2375 * Map the page list assocated with the supplied upl into the kernel virtual 2376 * address space at the virtual address indicated by the dst_addr argument; 2377 * the entire upl is mapped 2378 * 2379 * Parameters: upl The upl to map 2380 * dst_addr The address at which to map the upl 2381 * 2382 * Returns: KERN_SUCCESS The upl has been mapped 2383 * KERN_INVALID_ARGUMENT The upl is UPL_NULL 2384 * KERN_FAILURE The upl is already mapped 2385 * vm_map_enter:KERN_INVALID_ARGUMENT 2386 * A failure code from vm_map_enter() due 2387 * to an invalid argument 2388 */ 2389kern_return_t 2390ubc_upl_map( 2391 upl_t upl, 2392 vm_offset_t *dst_addr) 2393{ 2394 return (vm_upl_map(kernel_map, upl, dst_addr)); 2395} 2396 2397 2398/* 2399 * ubc_upl_unmap 2400 * 2401 * Unmap the page list assocated with the supplied upl from the kernel virtual 2402 * address space; the entire upl is unmapped. 2403 * 2404 * Parameters: upl The upl to unmap 2405 * 2406 * Returns: KERN_SUCCESS The upl has been unmapped 2407 * KERN_FAILURE The upl is not currently mapped 2408 * KERN_INVALID_ARGUMENT If the upl is UPL_NULL 2409 */ 2410kern_return_t 2411ubc_upl_unmap( 2412 upl_t upl) 2413{ 2414 return(vm_upl_unmap(kernel_map, upl)); 2415} 2416 2417 2418/* 2419 * ubc_upl_commit 2420 * 2421 * Commit the contents of the upl to the backing store 2422 * 2423 * Parameters: upl The upl to commit 2424 * 2425 * Returns: KERN_SUCCESS The upl has been committed 2426 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL 2427 * KERN_FAILURE The supplied upl does not represent 2428 * device memory, and the offset plus the 2429 * size would exceed the actual size of 2430 * the upl 2431 * 2432 * Notes: In practice, the only return value for this function should be 2433 * KERN_SUCCESS, unless there has been data structure corruption; 2434 * since the upl is deallocated regardless of success or failure, 2435 * there's really nothing to do about this other than panic. 2436 * 2437 * IMPORTANT: Use of this function should not be mixed with use of 2438 * ubc_upl_commit_range(), due to the unconditional deallocation 2439 * by this function. 2440 */ 2441kern_return_t 2442ubc_upl_commit( 2443 upl_t upl) 2444{ 2445 upl_page_info_t *pl; 2446 kern_return_t kr; 2447 2448 pl = UPL_GET_INTERNAL_PAGE_LIST(upl); 2449 kr = upl_commit(upl, pl, MAX_UPL_SIZE_BYTES >> PAGE_SHIFT); 2450 upl_deallocate(upl); 2451 return kr; 2452} 2453 2454 2455/* 2456 * ubc_upl_commit 2457 * 2458 * Commit the contents of the specified range of the upl to the backing store 2459 * 2460 * Parameters: upl The upl to commit 2461 * offset The offset into the upl 2462 * size The size of the region to be committed, 2463 * starting at the specified offset 2464 * flags commit type (see below) 2465 * 2466 * Returns: KERN_SUCCESS The range has been committed 2467 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL 2468 * KERN_FAILURE The supplied upl does not represent 2469 * device memory, and the offset plus the 2470 * size would exceed the actual size of 2471 * the upl 2472 * 2473 * Notes: IMPORTANT: If the commit is successful, and the object is now 2474 * empty, the upl will be deallocated. Since the caller cannot 2475 * check that this is the case, the UPL_COMMIT_FREE_ON_EMPTY flag 2476 * should generally only be used when the offset is 0 and the size 2477 * is equal to the upl size. 2478 * 2479 * The flags argument is a bitmap of flags on the rage of pages in 2480 * the upl to be committed; allowable flags are: 2481 * 2482 * o UPL_COMMIT_FREE_ON_EMPTY Free the upl when it is 2483 * both empty and has been 2484 * successfully committed 2485 * o UPL_COMMIT_CLEAR_DIRTY Clear each pages dirty 2486 * bit; will prevent a 2487 * later pageout 2488 * o UPL_COMMIT_SET_DIRTY Set each pages dirty 2489 * bit; will cause a later 2490 * pageout 2491 * o UPL_COMMIT_INACTIVATE Clear each pages 2492 * reference bit; the page 2493 * will not be accessed 2494 * o UPL_COMMIT_ALLOW_ACCESS Unbusy each page; pages 2495 * become busy when an 2496 * IOMemoryDescriptor is 2497 * mapped or redirected, 2498 * and we have to wait for 2499 * an IOKit driver 2500 * 2501 * The flag UPL_COMMIT_NOTIFY_EMPTY is used internally, and should 2502 * not be specified by the caller. 2503 * 2504 * The UPL_COMMIT_CLEAR_DIRTY and UPL_COMMIT_SET_DIRTY flags are 2505 * mutually exclusive, and should not be combined. 2506 */ 2507kern_return_t 2508ubc_upl_commit_range( 2509 upl_t upl, 2510 upl_offset_t offset, 2511 upl_size_t size, 2512 int flags) 2513{ 2514 upl_page_info_t *pl; 2515 boolean_t empty; 2516 kern_return_t kr; 2517 2518 if (flags & UPL_COMMIT_FREE_ON_EMPTY) 2519 flags |= UPL_COMMIT_NOTIFY_EMPTY; 2520 2521 if (flags & UPL_COMMIT_KERNEL_ONLY_FLAGS) { 2522 return KERN_INVALID_ARGUMENT; 2523 } 2524 2525 pl = UPL_GET_INTERNAL_PAGE_LIST(upl); 2526 2527 kr = upl_commit_range(upl, offset, size, flags, 2528 pl, MAX_UPL_SIZE_BYTES >> PAGE_SHIFT, &empty); 2529 2530 if((flags & UPL_COMMIT_FREE_ON_EMPTY) && empty) 2531 upl_deallocate(upl); 2532 2533 return kr; 2534} 2535 2536 2537/* 2538 * ubc_upl_abort_range 2539 * 2540 * Abort the contents of the specified range of the specified upl 2541 * 2542 * Parameters: upl The upl to abort 2543 * offset The offset into the upl 2544 * size The size of the region to be aborted, 2545 * starting at the specified offset 2546 * abort_flags abort type (see below) 2547 * 2548 * Returns: KERN_SUCCESS The range has been aborted 2549 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL 2550 * KERN_FAILURE The supplied upl does not represent 2551 * device memory, and the offset plus the 2552 * size would exceed the actual size of 2553 * the upl 2554 * 2555 * Notes: IMPORTANT: If the abort is successful, and the object is now 2556 * empty, the upl will be deallocated. Since the caller cannot 2557 * check that this is the case, the UPL_ABORT_FREE_ON_EMPTY flag 2558 * should generally only be used when the offset is 0 and the size 2559 * is equal to the upl size. 2560 * 2561 * The abort_flags argument is a bitmap of flags on the range of 2562 * pages in the upl to be aborted; allowable flags are: 2563 * 2564 * o UPL_ABORT_FREE_ON_EMPTY Free the upl when it is both 2565 * empty and has been successfully 2566 * aborted 2567 * o UPL_ABORT_RESTART The operation must be restarted 2568 * o UPL_ABORT_UNAVAILABLE The pages are unavailable 2569 * o UPL_ABORT_ERROR An I/O error occurred 2570 * o UPL_ABORT_DUMP_PAGES Just free the pages 2571 * o UPL_ABORT_NOTIFY_EMPTY RESERVED 2572 * o UPL_ABORT_ALLOW_ACCESS RESERVED 2573 * 2574 * The UPL_ABORT_NOTIFY_EMPTY is an internal use flag and should 2575 * not be specified by the caller. It is intended to fulfill the 2576 * same role as UPL_COMMIT_NOTIFY_EMPTY does in the function 2577 * ubc_upl_commit_range(), but is never referenced internally. 2578 * 2579 * The UPL_ABORT_ALLOW_ACCESS is defined, but neither set nor 2580 * referenced; do not use it. 2581 */ 2582kern_return_t 2583ubc_upl_abort_range( 2584 upl_t upl, 2585 upl_offset_t offset, 2586 upl_size_t size, 2587 int abort_flags) 2588{ 2589 kern_return_t kr; 2590 boolean_t empty = FALSE; 2591 2592 if (abort_flags & UPL_ABORT_FREE_ON_EMPTY) 2593 abort_flags |= UPL_ABORT_NOTIFY_EMPTY; 2594 2595 kr = upl_abort_range(upl, offset, size, abort_flags, &empty); 2596 2597 if((abort_flags & UPL_ABORT_FREE_ON_EMPTY) && empty) 2598 upl_deallocate(upl); 2599 2600 return kr; 2601} 2602 2603 2604/* 2605 * ubc_upl_abort 2606 * 2607 * Abort the contents of the specified upl 2608 * 2609 * Parameters: upl The upl to abort 2610 * abort_type abort type (see below) 2611 * 2612 * Returns: KERN_SUCCESS The range has been aborted 2613 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL 2614 * KERN_FAILURE The supplied upl does not represent 2615 * device memory, and the offset plus the 2616 * size would exceed the actual size of 2617 * the upl 2618 * 2619 * Notes: IMPORTANT: If the abort is successful, and the object is now 2620 * empty, the upl will be deallocated. Since the caller cannot 2621 * check that this is the case, the UPL_ABORT_FREE_ON_EMPTY flag 2622 * should generally only be used when the offset is 0 and the size 2623 * is equal to the upl size. 2624 * 2625 * The abort_type is a bitmap of flags on the range of 2626 * pages in the upl to be aborted; allowable flags are: 2627 * 2628 * o UPL_ABORT_FREE_ON_EMPTY Free the upl when it is both 2629 * empty and has been successfully 2630 * aborted 2631 * o UPL_ABORT_RESTART The operation must be restarted 2632 * o UPL_ABORT_UNAVAILABLE The pages are unavailable 2633 * o UPL_ABORT_ERROR An I/O error occurred 2634 * o UPL_ABORT_DUMP_PAGES Just free the pages 2635 * o UPL_ABORT_NOTIFY_EMPTY RESERVED 2636 * o UPL_ABORT_ALLOW_ACCESS RESERVED 2637 * 2638 * The UPL_ABORT_NOTIFY_EMPTY is an internal use flag and should 2639 * not be specified by the caller. It is intended to fulfill the 2640 * same role as UPL_COMMIT_NOTIFY_EMPTY does in the function 2641 * ubc_upl_commit_range(), but is never referenced internally. 2642 * 2643 * The UPL_ABORT_ALLOW_ACCESS is defined, but neither set nor 2644 * referenced; do not use it. 2645 */ 2646kern_return_t 2647ubc_upl_abort( 2648 upl_t upl, 2649 int abort_type) 2650{ 2651 kern_return_t kr; 2652 2653 kr = upl_abort(upl, abort_type); 2654 upl_deallocate(upl); 2655 return kr; 2656} 2657 2658 2659/* 2660 * ubc_upl_pageinfo 2661 * 2662 * Retrieve the internal page list for the specified upl 2663 * 2664 * Parameters: upl The upl to obtain the page list from 2665 * 2666 * Returns: !NULL The (upl_page_info_t *) for the page 2667 * list internal to the upl 2668 * NULL Error/no page list associated 2669 * 2670 * Notes: IMPORTANT: The function is only valid on internal objects 2671 * where the list request was made with the UPL_INTERNAL flag. 2672 * 2673 * This function is a utility helper function, since some callers 2674 * may not have direct access to the header defining the macro, 2675 * due to abstraction layering constraints. 2676 */ 2677upl_page_info_t * 2678ubc_upl_pageinfo( 2679 upl_t upl) 2680{ 2681 return (UPL_GET_INTERNAL_PAGE_LIST(upl)); 2682} 2683 2684 2685int 2686UBCINFOEXISTS(const struct vnode * vp) 2687{ 2688 return((vp) && ((vp)->v_type == VREG) && ((vp)->v_ubcinfo != UBC_INFO_NULL)); 2689} 2690 2691 2692void 2693ubc_upl_range_needed( 2694 upl_t upl, 2695 int index, 2696 int count) 2697{ 2698 upl_range_needed(upl, index, count); 2699} 2700 2701boolean_t ubc_is_mapped(const struct vnode *vp, boolean_t *writable) 2702{ 2703 if (!UBCINFOEXISTS(vp) || !ISSET(vp->v_ubcinfo->ui_flags, UI_ISMAPPED)) 2704 return FALSE; 2705 if (writable) 2706 *writable = ISSET(vp->v_ubcinfo->ui_flags, UI_MAPPEDWRITE); 2707 return TRUE; 2708} 2709 2710boolean_t ubc_is_mapped_writable(const struct vnode *vp) 2711{ 2712 boolean_t writable; 2713 return ubc_is_mapped(vp, &writable) && writable; 2714} 2715 2716 2717/* 2718 * CODE SIGNING 2719 */ 2720#define CS_BLOB_PAGEABLE 0 2721static volatile SInt32 cs_blob_size = 0; 2722static volatile SInt32 cs_blob_count = 0; 2723static SInt32 cs_blob_size_peak = 0; 2724static UInt32 cs_blob_size_max = 0; 2725static SInt32 cs_blob_count_peak = 0; 2726 2727int cs_validation = 1; 2728 2729#ifndef SECURE_KERNEL 2730SYSCTL_INT(_vm, OID_AUTO, cs_validation, CTLFLAG_RW | CTLFLAG_LOCKED, &cs_validation, 0, "Do validate code signatures"); 2731#endif 2732SYSCTL_INT(_vm, OID_AUTO, cs_blob_count, CTLFLAG_RD | CTLFLAG_LOCKED, (int *)(uintptr_t)&cs_blob_count, 0, "Current number of code signature blobs"); 2733SYSCTL_INT(_vm, OID_AUTO, cs_blob_size, CTLFLAG_RD | CTLFLAG_LOCKED, (int *)(uintptr_t)&cs_blob_size, 0, "Current size of all code signature blobs"); 2734SYSCTL_INT(_vm, OID_AUTO, cs_blob_count_peak, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_count_peak, 0, "Peak number of code signature blobs"); 2735SYSCTL_INT(_vm, OID_AUTO, cs_blob_size_peak, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_size_peak, 0, "Peak size of code signature blobs"); 2736SYSCTL_INT(_vm, OID_AUTO, cs_blob_size_max, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_size_max, 0, "Size of biggest code signature blob"); 2737 2738 2739kern_return_t 2740ubc_cs_blob_allocate( 2741 vm_offset_t *blob_addr_p, 2742 vm_size_t *blob_size_p) 2743{ 2744 kern_return_t kr; 2745 2746#if CS_BLOB_PAGEABLE 2747 *blob_size_p = round_page(*blob_size_p); 2748 kr = kmem_alloc(kernel_map, blob_addr_p, *blob_size_p); 2749#else /* CS_BLOB_PAGEABLE */ 2750 *blob_addr_p = (vm_offset_t) kalloc(*blob_size_p); 2751 if (*blob_addr_p == 0) { 2752 kr = KERN_NO_SPACE; 2753 } else { 2754 kr = KERN_SUCCESS; 2755 } 2756#endif /* CS_BLOB_PAGEABLE */ 2757 return kr; 2758} 2759 2760void 2761ubc_cs_blob_deallocate( 2762 vm_offset_t blob_addr, 2763 vm_size_t blob_size) 2764{ 2765#if CS_BLOB_PAGEABLE 2766 kmem_free(kernel_map, blob_addr, blob_size); 2767#else /* CS_BLOB_PAGEABLE */ 2768 kfree((void *) blob_addr, blob_size); 2769#endif /* CS_BLOB_PAGEABLE */ 2770} 2771 2772int 2773ubc_cs_sigpup_add( 2774 struct vnode *vp, 2775 vm_address_t address, 2776 vm_size_t size) 2777{ 2778 kern_return_t kr; 2779 struct ubc_info *uip; 2780 struct cs_blob *blob; 2781 memory_object_control_t control; 2782 const CS_CodeDirectory *cd; 2783 int error; 2784 2785 control = ubc_getobject(vp, UBC_FLAGS_NONE); 2786 if (control == MEMORY_OBJECT_CONTROL_NULL) 2787 return KERN_INVALID_ARGUMENT; 2788 2789 if (memory_object_is_signed(control)) 2790 return 0; 2791 2792 blob = (struct cs_blob *) kalloc(sizeof (struct cs_blob)); 2793 if (blob == NULL) 2794 return ENOMEM; 2795 2796 /* fill in the new blob */ 2797 blob->csb_cpu_type = CPU_TYPE_ANY; 2798 blob->csb_base_offset = 0; 2799 blob->csb_mem_size = size; 2800 blob->csb_mem_offset = 0; 2801 blob->csb_mem_handle = IPC_PORT_NULL; 2802 blob->csb_mem_kaddr = address; 2803 blob->csb_sigpup = 1; 2804 blob->csb_platform_binary = 0; 2805 blob->csb_teamid = NULL; 2806 2807 /* 2808 * Validate the blob's contents 2809 */ 2810 cd = findCodeDirectory( 2811 (const CS_SuperBlob *) address, 2812 (char *) address, 2813 (char *) address + blob->csb_mem_size); 2814 if (cd == NULL) { 2815 /* no code directory => useless blob ! */ 2816 error = EINVAL; 2817 goto out; 2818 } 2819 2820 blob->csb_flags = ntohl(cd->flags) | CS_VALID; 2821 blob->csb_end_offset = round_page_4K(ntohl(cd->codeLimit)); 2822 if((ntohl(cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(cd->scatterOffset))) { 2823 const SC_Scatter *scatter = (const SC_Scatter*) 2824 ((const char*)cd + ntohl(cd->scatterOffset)); 2825 blob->csb_start_offset = ntohl(scatter->base) * PAGE_SIZE_4K; 2826 } else { 2827 blob->csb_start_offset = (blob->csb_end_offset - (ntohl(cd->nCodeSlots) * PAGE_SIZE_4K)); 2828 } 2829 2830 /* 2831 * We don't need to check with the policy module, since the input data is supposed to be already checked 2832 */ 2833 2834 vnode_lock(vp); 2835 if (! UBCINFOEXISTS(vp)) { 2836 vnode_unlock(vp); 2837 if (cs_debug) 2838 printf("out ubc object\n"); 2839 error = ENOENT; 2840 goto out; 2841 } 2842 uip = vp->v_ubcinfo; 2843 2844 /* someone raced us to adding the code directory */ 2845 if (uip->cs_blobs != NULL) { 2846 if (cs_debug) 2847 printf("sigpup: vnode already have CD ?\n"); 2848 vnode_unlock(vp); 2849 error = EEXIST; 2850 goto out; 2851 } 2852 2853 blob->csb_next = uip->cs_blobs; 2854 uip->cs_blobs = blob; 2855 2856 OSAddAtomic(+1, &cs_blob_count); 2857 OSAddAtomic((SInt32) +blob->csb_mem_size, &cs_blob_size); 2858 2859 /* mark this vnode's VM object as having "signed pages" */ 2860 kr = memory_object_signed(uip->ui_control, TRUE); 2861 if (kr != KERN_SUCCESS) { 2862 vnode_unlock(vp); 2863 if (cs_debug) 2864 printf("sigpup: not signable ?\n"); 2865 error = ENOENT; 2866 goto out; 2867 } 2868 2869 vnode_unlock(vp); 2870 2871 error = 0; 2872out: 2873 if (error) { 2874 if (cs_debug) 2875 printf("sigpup: not signable ?\n"); 2876 /* we failed; release what we allocated */ 2877 if (blob) { 2878 kfree(blob, sizeof (*blob)); 2879 blob = NULL; 2880 } 2881 } 2882 2883 return error; 2884} 2885 2886int 2887ubc_cs_blob_add( 2888 struct vnode *vp, 2889 cpu_type_t cputype, 2890 off_t base_offset, 2891 vm_address_t addr, 2892 vm_size_t size) 2893{ 2894 kern_return_t kr; 2895 struct ubc_info *uip; 2896 struct cs_blob *blob, *oblob; 2897 int error; 2898 ipc_port_t blob_handle; 2899 memory_object_size_t blob_size; 2900 const CS_CodeDirectory *cd; 2901 off_t blob_start_offset, blob_end_offset; 2902 SHA1_CTX sha1ctxt; 2903 boolean_t record_mtime; 2904 int is_platform_binary; 2905 2906 record_mtime = FALSE; 2907 is_platform_binary = 0; 2908 2909 blob_handle = IPC_PORT_NULL; 2910 2911 blob = (struct cs_blob *) kalloc(sizeof (struct cs_blob)); 2912 if (blob == NULL) { 2913 return ENOMEM; 2914 } 2915 2916#if CS_BLOB_PAGEABLE 2917 /* get a memory entry on the blob */ 2918 blob_size = (memory_object_size_t) size; 2919 kr = mach_make_memory_entry_64(kernel_map, 2920 &blob_size, 2921 addr, 2922 VM_PROT_READ, 2923 &blob_handle, 2924 IPC_PORT_NULL); 2925 if (kr != KERN_SUCCESS) { 2926 error = ENOMEM; 2927 goto out; 2928 } 2929 if (memory_object_round_page(blob_size) != 2930 (memory_object_size_t) round_page(size)) { 2931 printf("ubc_cs_blob_add: size mismatch 0x%llx 0x%lx !?\n", 2932 blob_size, (size_t)size); 2933 panic("XXX FBDP size mismatch 0x%llx 0x%lx\n", blob_size, (size_t)size); 2934 error = EINVAL; 2935 goto out; 2936 } 2937#else 2938 blob_size = (memory_object_size_t) size; 2939 blob_handle = IPC_PORT_NULL; 2940#endif 2941 2942 /* fill in the new blob */ 2943 blob->csb_cpu_type = cputype; 2944 blob->csb_sigpup = 0; 2945 blob->csb_base_offset = base_offset; 2946 blob->csb_mem_size = size; 2947 blob->csb_mem_offset = 0; 2948 blob->csb_mem_handle = blob_handle; 2949 blob->csb_mem_kaddr = addr; 2950 blob->csb_flags = 0; 2951 blob->csb_platform_binary = 0; 2952 blob->csb_teamid = NULL; 2953 2954 /* 2955 * Validate the blob's contents 2956 */ 2957 2958 error = cs_validate_csblob((const uint8_t *)addr, size, &cd); 2959 if (error) { 2960 if (cs_debug) 2961 printf("CODESIGNING: csblob invalid: %d\n", error); 2962 blob->csb_flags = 0; 2963 blob->csb_start_offset = 0; 2964 blob->csb_end_offset = 0; 2965 memset(blob->csb_sha1, 0, SHA1_RESULTLEN); 2966 /* let the vnode checker determine if the signature is valid or not */ 2967 } else { 2968 const unsigned char *sha1_base; 2969 int sha1_size; 2970 2971 blob->csb_flags = (ntohl(cd->flags) & CS_ALLOWED_MACHO) | CS_VALID; 2972 blob->csb_end_offset = round_page_4K(ntohl(cd->codeLimit)); 2973 if((ntohl(cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(cd->scatterOffset))) { 2974 const SC_Scatter *scatter = (const SC_Scatter*) 2975 ((const char*)cd + ntohl(cd->scatterOffset)); 2976 blob->csb_start_offset = ntohl(scatter->base) * PAGE_SIZE_4K; 2977 } else { 2978 blob->csb_start_offset = (blob->csb_end_offset - 2979 (ntohl(cd->nCodeSlots) * PAGE_SIZE_4K)); 2980 } 2981 /* compute the blob's SHA1 hash */ 2982 sha1_base = (const unsigned char *) cd; 2983 sha1_size = ntohl(cd->length); 2984 SHA1Init(&sha1ctxt); 2985 SHA1Update(&sha1ctxt, sha1_base, sha1_size); 2986 SHA1Final(blob->csb_sha1, &sha1ctxt); 2987 } 2988 2989 /* 2990 * Let policy module check whether the blob's signature is accepted. 2991 */ 2992#if CONFIG_MACF 2993 error = mac_vnode_check_signature(vp, base_offset, blob->csb_sha1, (const void*)cd, size, &is_platform_binary); 2994 if (error) { 2995 if (cs_debug) 2996 printf("check_signature[pid: %d], error = %d\n", current_proc()->p_pid, error); 2997 goto out; 2998 } 2999#endif 3000 3001 if (is_platform_binary) { 3002 if (cs_debug > 1) 3003 printf("check_signature[pid: %d]: platform binary\n", current_proc()->p_pid); 3004 blob->csb_platform_binary = 1; 3005 } else { 3006 blob->csb_platform_binary = 0; 3007 blob->csb_teamid = csblob_get_teamid(blob); 3008 if (cs_debug > 1) { 3009 if (blob->csb_teamid) 3010 printf("check_signature[pid: %d]: team-id is %s\n", current_proc()->p_pid, blob->csb_teamid); 3011 else 3012 printf("check_signature[pid: %d]: no team-id\n", current_proc()->p_pid); 3013 } 3014 } 3015 3016 /* 3017 * Validate the blob's coverage 3018 */ 3019 blob_start_offset = blob->csb_base_offset + blob->csb_start_offset; 3020 blob_end_offset = blob->csb_base_offset + blob->csb_end_offset; 3021 3022 if (blob_start_offset >= blob_end_offset || 3023 blob_start_offset < 0 || 3024 blob_end_offset <= 0) { 3025 /* reject empty or backwards blob */ 3026 error = EINVAL; 3027 goto out; 3028 } 3029 3030 vnode_lock(vp); 3031 if (! UBCINFOEXISTS(vp)) { 3032 vnode_unlock(vp); 3033 error = ENOENT; 3034 goto out; 3035 } 3036 uip = vp->v_ubcinfo; 3037 3038 /* check if this new blob overlaps with an existing blob */ 3039 for (oblob = uip->cs_blobs; 3040 oblob != NULL; 3041 oblob = oblob->csb_next) { 3042 off_t oblob_start_offset, oblob_end_offset; 3043 3044 /* check for conflicting teamid */ 3045 if (blob->csb_platform_binary) { //platform binary needs to be the same for app slices 3046 if (!oblob->csb_platform_binary) { 3047 vnode_unlock(vp); 3048 error = EALREADY; 3049 goto out; 3050 } 3051 } else if (blob->csb_teamid) { //teamid binary needs to be the same for app slices 3052 if (oblob->csb_platform_binary || 3053 oblob->csb_teamid == NULL || 3054 strcmp(oblob->csb_teamid, blob->csb_teamid) != 0) { 3055 vnode_unlock(vp); 3056 error = EALREADY; 3057 goto out; 3058 } 3059 } else { // non teamid binary needs to be the same for app slices 3060 if (oblob->csb_platform_binary || 3061 oblob->csb_teamid != NULL) { 3062 vnode_unlock(vp); 3063 error = EALREADY; 3064 goto out; 3065 } 3066 } 3067 3068 oblob_start_offset = (oblob->csb_base_offset + 3069 oblob->csb_start_offset); 3070 oblob_end_offset = (oblob->csb_base_offset + 3071 oblob->csb_end_offset); 3072 if (blob_start_offset >= oblob_end_offset || 3073 blob_end_offset <= oblob_start_offset) { 3074 /* no conflict with this existing blob */ 3075 } else { 3076 /* conflict ! */ 3077 if (blob_start_offset == oblob_start_offset && 3078 blob_end_offset == oblob_end_offset && 3079 blob->csb_mem_size == oblob->csb_mem_size && 3080 blob->csb_flags == oblob->csb_flags && 3081 (blob->csb_cpu_type == CPU_TYPE_ANY || 3082 oblob->csb_cpu_type == CPU_TYPE_ANY || 3083 blob->csb_cpu_type == oblob->csb_cpu_type) && 3084 !bcmp(blob->csb_sha1, 3085 oblob->csb_sha1, 3086 SHA1_RESULTLEN)) { 3087 /* 3088 * We already have this blob: 3089 * we'll return success but 3090 * throw away the new blob. 3091 */ 3092 if (oblob->csb_cpu_type == CPU_TYPE_ANY) { 3093 /* 3094 * The old blob matches this one 3095 * but doesn't have any CPU type. 3096 * Update it with whatever the caller 3097 * provided this time. 3098 */ 3099 oblob->csb_cpu_type = cputype; 3100 } 3101 vnode_unlock(vp); 3102 error = EAGAIN; 3103 goto out; 3104 } else { 3105 /* different blob: reject the new one */ 3106 vnode_unlock(vp); 3107 error = EALREADY; 3108 goto out; 3109 } 3110 } 3111 3112 } 3113 3114 3115 /* mark this vnode's VM object as having "signed pages" */ 3116 kr = memory_object_signed(uip->ui_control, TRUE); 3117 if (kr != KERN_SUCCESS) { 3118 vnode_unlock(vp); 3119 error = ENOENT; 3120 goto out; 3121 } 3122 3123 if (uip->cs_blobs == NULL) { 3124 /* loading 1st blob: record the file's current "modify time" */ 3125 record_mtime = TRUE; 3126 } 3127 3128 /* set the generation count for cs_blobs */ 3129 uip->cs_add_gen = cs_blob_generation_count; 3130 3131 /* 3132 * Add this blob to the list of blobs for this vnode. 3133 * We always add at the front of the list and we never remove a 3134 * blob from the list, so ubc_cs_get_blobs() can return whatever 3135 * the top of the list was and that list will remain valid 3136 * while we validate a page, even after we release the vnode's lock. 3137 */ 3138 blob->csb_next = uip->cs_blobs; 3139 uip->cs_blobs = blob; 3140 3141 OSAddAtomic(+1, &cs_blob_count); 3142 if (cs_blob_count > cs_blob_count_peak) { 3143 cs_blob_count_peak = cs_blob_count; /* XXX atomic ? */ 3144 } 3145 OSAddAtomic((SInt32) +blob->csb_mem_size, &cs_blob_size); 3146 if ((SInt32) cs_blob_size > cs_blob_size_peak) { 3147 cs_blob_size_peak = (SInt32) cs_blob_size; /* XXX atomic ? */ 3148 } 3149 if ((UInt32) blob->csb_mem_size > cs_blob_size_max) { 3150 cs_blob_size_max = (UInt32) blob->csb_mem_size; 3151 } 3152 3153 if (cs_debug > 1) { 3154 proc_t p; 3155 const char *name = vnode_getname_printable(vp); 3156 p = current_proc(); 3157 printf("CODE SIGNING: proc %d(%s) " 3158 "loaded %s signatures for file (%s) " 3159 "range 0x%llx:0x%llx flags 0x%x\n", 3160 p->p_pid, p->p_comm, 3161 blob->csb_cpu_type == -1 ? "detached" : "embedded", 3162 name, 3163 blob->csb_base_offset + blob->csb_start_offset, 3164 blob->csb_base_offset + blob->csb_end_offset, 3165 blob->csb_flags); 3166 vnode_putname_printable(name); 3167 } 3168 3169 vnode_unlock(vp); 3170 3171 if (record_mtime) { 3172 vnode_mtime(vp, &uip->cs_mtime, vfs_context_current()); 3173 } 3174 3175 error = 0; /* success ! */ 3176 3177out: 3178 if (error) { 3179 if (cs_debug) 3180 printf("check_signature[pid: %d]: error = %d\n", current_proc()->p_pid, error); 3181 3182 /* we failed; release what we allocated */ 3183 if (blob) { 3184 kfree(blob, sizeof (*blob)); 3185 blob = NULL; 3186 } 3187 if (blob_handle != IPC_PORT_NULL) { 3188 mach_memory_entry_port_release(blob_handle); 3189 blob_handle = IPC_PORT_NULL; 3190 } 3191 } 3192 3193 if (error == EAGAIN) { 3194 /* 3195 * See above: error is EAGAIN if we were asked 3196 * to add an existing blob again. We cleaned the new 3197 * blob and we want to return success. 3198 */ 3199 error = 0; 3200 /* 3201 * Since we're not failing, consume the data we received. 3202 */ 3203 ubc_cs_blob_deallocate(addr, size); 3204 } 3205 3206 return error; 3207} 3208 3209struct cs_blob * 3210ubc_cs_blob_get( 3211 struct vnode *vp, 3212 cpu_type_t cputype, 3213 off_t offset) 3214{ 3215 struct ubc_info *uip; 3216 struct cs_blob *blob; 3217 off_t offset_in_blob; 3218 3219 vnode_lock_spin(vp); 3220 3221 if (! UBCINFOEXISTS(vp)) { 3222 blob = NULL; 3223 goto out; 3224 } 3225 3226 uip = vp->v_ubcinfo; 3227 for (blob = uip->cs_blobs; 3228 blob != NULL; 3229 blob = blob->csb_next) { 3230 if (cputype != -1 && blob->csb_cpu_type == cputype) { 3231 break; 3232 } 3233 if (offset != -1) { 3234 offset_in_blob = offset - blob->csb_base_offset; 3235 if (offset_in_blob >= blob->csb_start_offset && 3236 offset_in_blob < blob->csb_end_offset) { 3237 /* our offset is covered by this blob */ 3238 break; 3239 } 3240 } 3241 } 3242 3243 if (cs_debug && blob != NULL && blob->csb_sigpup) { 3244 printf("found sig pup blob\n"); 3245 } 3246 3247out: 3248 vnode_unlock(vp); 3249 3250 return blob; 3251} 3252 3253static void 3254ubc_cs_free( 3255 struct ubc_info *uip) 3256{ 3257 struct cs_blob *blob, *next_blob; 3258 3259 for (blob = uip->cs_blobs; 3260 blob != NULL; 3261 blob = next_blob) { 3262 next_blob = blob->csb_next; 3263 if (blob->csb_mem_kaddr != 0 && !blob->csb_sigpup) { 3264 ubc_cs_blob_deallocate(blob->csb_mem_kaddr, 3265 blob->csb_mem_size); 3266 blob->csb_mem_kaddr = 0; 3267 } 3268 if (blob->csb_mem_handle != IPC_PORT_NULL) { 3269 mach_memory_entry_port_release(blob->csb_mem_handle); 3270 } 3271 blob->csb_mem_handle = IPC_PORT_NULL; 3272 OSAddAtomic(-1, &cs_blob_count); 3273 OSAddAtomic((SInt32) -blob->csb_mem_size, &cs_blob_size); 3274 kfree(blob, sizeof (*blob)); 3275 } 3276#if CHECK_CS_VALIDATION_BITMAP 3277 ubc_cs_validation_bitmap_deallocate( uip->ui_vnode ); 3278#endif 3279 uip->cs_blobs = NULL; 3280} 3281 3282/* check cs blob generation on vnode 3283 * returns: 3284 * 0 : Success, the cs_blob attached is current 3285 * ENEEDAUTH : Generation count mismatch. Needs authentication again. 3286 */ 3287int 3288ubc_cs_generation_check( 3289 struct vnode *vp) 3290{ 3291 int retval = ENEEDAUTH; 3292 3293 vnode_lock_spin(vp); 3294 3295 if (UBCINFOEXISTS(vp) && vp->v_ubcinfo->cs_add_gen == cs_blob_generation_count) { 3296 retval = 0; 3297 } 3298 3299 vnode_unlock(vp); 3300 return retval; 3301} 3302 3303int 3304ubc_cs_blob_revalidate( 3305 struct vnode *vp, 3306 struct cs_blob *blob 3307 ) 3308{ 3309 int error = 0; 3310#if CONFIG_MACF 3311 int is_platform_binary = 0; 3312#endif 3313 const CS_CodeDirectory *cd = NULL; 3314 3315 assert(vp != NULL); 3316 assert(blob != NULL); 3317 3318 error = cs_validate_csblob((const uint8_t *)blob->csb_mem_kaddr, blob->csb_mem_size, &cd); 3319 if (error) { 3320 if (cs_debug) { 3321 printf("CODESIGNING: csblob invalid: %d\n", error); 3322 } 3323 goto out; 3324 } 3325 3326 /* callout to mac_vnode_check_signature */ 3327#if CONFIG_MACF 3328 error = mac_vnode_check_signature(vp, blob->csb_base_offset, blob->csb_sha1, (const void*)cd, blob->csb_cpu_type, &is_platform_binary); 3329 if (cs_debug && error) { 3330 printf("revalidate: check_signature[pid: %d], error = %d\n", current_proc()->p_pid, error); 3331 } 3332#endif 3333 3334 /* update generation number if success */ 3335 vnode_lock_spin(vp); 3336 if (UBCINFOEXISTS(vp)) { 3337 if (error == 0) 3338 vp->v_ubcinfo->cs_add_gen = cs_blob_generation_count; 3339 else 3340 vp->v_ubcinfo->cs_add_gen = 0; 3341 } 3342 3343 vnode_unlock(vp); 3344 3345out: 3346 return error; 3347} 3348 3349void 3350cs_blob_reset_cache() 3351{ 3352 /* incrementing odd no by 2 makes sure '0' is never reached. */ 3353 OSAddAtomic(+2, &cs_blob_generation_count); 3354 printf("Reseting cs_blob cache from all vnodes. \n"); 3355} 3356 3357struct cs_blob * 3358ubc_get_cs_blobs( 3359 struct vnode *vp) 3360{ 3361 struct ubc_info *uip; 3362 struct cs_blob *blobs; 3363 3364 /* 3365 * No need to take the vnode lock here. The caller must be holding 3366 * a reference on the vnode (via a VM mapping or open file descriptor), 3367 * so the vnode will not go away. The ubc_info stays until the vnode 3368 * goes away. And we only modify "blobs" by adding to the head of the 3369 * list. 3370 * The ubc_info could go away entirely if the vnode gets reclaimed as 3371 * part of a forced unmount. In the case of a code-signature validation 3372 * during a page fault, the "paging_in_progress" reference on the VM 3373 * object guarantess that the vnode pager (and the ubc_info) won't go 3374 * away during the fault. 3375 * Other callers need to protect against vnode reclaim by holding the 3376 * vnode lock, for example. 3377 */ 3378 3379 if (! UBCINFOEXISTS(vp)) { 3380 blobs = NULL; 3381 goto out; 3382 } 3383 3384 uip = vp->v_ubcinfo; 3385 blobs = uip->cs_blobs; 3386 3387out: 3388 return blobs; 3389} 3390 3391void 3392ubc_get_cs_mtime( 3393 struct vnode *vp, 3394 struct timespec *cs_mtime) 3395{ 3396 struct ubc_info *uip; 3397 3398 if (! UBCINFOEXISTS(vp)) { 3399 cs_mtime->tv_sec = 0; 3400 cs_mtime->tv_nsec = 0; 3401 return; 3402 } 3403 3404 uip = vp->v_ubcinfo; 3405 cs_mtime->tv_sec = uip->cs_mtime.tv_sec; 3406 cs_mtime->tv_nsec = uip->cs_mtime.tv_nsec; 3407} 3408 3409unsigned long cs_validate_page_no_hash = 0; 3410unsigned long cs_validate_page_bad_hash = 0; 3411boolean_t 3412cs_validate_page( 3413 void *_blobs, 3414 memory_object_t pager, 3415 memory_object_offset_t page_offset, 3416 const void *data, 3417 boolean_t *tainted) 3418{ 3419 SHA1_CTX sha1ctxt; 3420 unsigned char actual_hash[SHA1_RESULTLEN]; 3421 unsigned char expected_hash[SHA1_RESULTLEN]; 3422 boolean_t found_hash; 3423 struct cs_blob *blobs, *blob; 3424 const CS_CodeDirectory *cd; 3425 const CS_SuperBlob *embedded; 3426 const unsigned char *hash; 3427 boolean_t validated; 3428 off_t offset; /* page offset in the file */ 3429 size_t size; 3430 off_t codeLimit = 0; 3431 char *lower_bound, *upper_bound; 3432 vm_offset_t kaddr, blob_addr; 3433 vm_size_t ksize; 3434 kern_return_t kr; 3435 3436 offset = page_offset; 3437 3438 /* retrieve the expected hash */ 3439 found_hash = FALSE; 3440 blobs = (struct cs_blob *) _blobs; 3441 3442 for (blob = blobs; 3443 blob != NULL; 3444 blob = blob->csb_next) { 3445 offset = page_offset - blob->csb_base_offset; 3446 if (offset < blob->csb_start_offset || 3447 offset >= blob->csb_end_offset) { 3448 /* our page is not covered by this blob */ 3449 continue; 3450 } 3451 3452 /* map the blob in the kernel address space */ 3453 kaddr = blob->csb_mem_kaddr; 3454 if (kaddr == 0) { 3455 ksize = (vm_size_t) (blob->csb_mem_size + 3456 blob->csb_mem_offset); 3457 kr = vm_map(kernel_map, 3458 &kaddr, 3459 ksize, 3460 0, 3461 VM_FLAGS_ANYWHERE, 3462 blob->csb_mem_handle, 3463 0, 3464 TRUE, 3465 VM_PROT_READ, 3466 VM_PROT_READ, 3467 VM_INHERIT_NONE); 3468 if (kr != KERN_SUCCESS) { 3469 /* XXX FBDP what to do !? */ 3470 printf("cs_validate_page: failed to map blob, " 3471 "size=0x%lx kr=0x%x\n", 3472 (size_t)blob->csb_mem_size, kr); 3473 break; 3474 } 3475 } 3476 if (blob->csb_sigpup && cs_debug) 3477 printf("checking for a sigpup CD\n"); 3478 3479 blob_addr = kaddr + blob->csb_mem_offset; 3480 3481 lower_bound = CAST_DOWN(char *, blob_addr); 3482 upper_bound = lower_bound + blob->csb_mem_size; 3483 3484 embedded = (const CS_SuperBlob *) blob_addr; 3485 cd = findCodeDirectory(embedded, lower_bound, upper_bound); 3486 if (cd != NULL) { 3487 if (cd->pageSize != PAGE_SHIFT_4K || 3488 cd->hashType != CS_HASHTYPE_SHA1 || 3489 cd->hashSize != SHA1_RESULTLEN) { 3490 /* bogus blob ? */ 3491 if (blob->csb_sigpup && cs_debug) 3492 printf("page foo bogus sigpup CD\n"); 3493 continue; 3494 } 3495 3496 offset = page_offset - blob->csb_base_offset; 3497 if (offset < blob->csb_start_offset || 3498 offset >= blob->csb_end_offset) { 3499 /* our page is not covered by this blob */ 3500 if (blob->csb_sigpup && cs_debug) 3501 printf("OOB sigpup CD\n"); 3502 continue; 3503 } 3504 3505 codeLimit = ntohl(cd->codeLimit); 3506 if (blob->csb_sigpup && cs_debug) 3507 printf("sigpup codesize %d\n", (int)codeLimit); 3508 3509 hash = hashes(cd, (unsigned)(offset>>PAGE_SHIFT_4K), 3510 lower_bound, upper_bound); 3511 if (hash != NULL) { 3512 bcopy(hash, expected_hash, 3513 sizeof (expected_hash)); 3514 found_hash = TRUE; 3515 if (blob->csb_sigpup && cs_debug) 3516 printf("sigpup hash\n"); 3517 } 3518 3519 break; 3520 } else { 3521 if (blob->csb_sigpup && cs_debug) 3522 printf("sig pup had no valid CD\n"); 3523 3524 } 3525 } 3526 3527 if (found_hash == FALSE) { 3528 /* 3529 * We can't verify this page because there is no signature 3530 * for it (yet). It's possible that this part of the object 3531 * is not signed, or that signatures for that part have not 3532 * been loaded yet. 3533 * Report that the page has not been validated and let the 3534 * caller decide if it wants to accept it or not. 3535 */ 3536 cs_validate_page_no_hash++; 3537 if (cs_debug > 1) { 3538 printf("CODE SIGNING: cs_validate_page: " 3539 "mobj %p off 0x%llx: no hash to validate !?\n", 3540 pager, page_offset); 3541 } 3542 validated = FALSE; 3543 *tainted = FALSE; 3544 } else { 3545 3546 size = PAGE_SIZE_4K; 3547 const uint32_t *asha1, *esha1; 3548 if ((off_t)(offset + size) > codeLimit) { 3549 /* partial page at end of segment */ 3550 assert(offset < codeLimit); 3551 size = (size_t) (codeLimit & PAGE_MASK_4K); 3552 } 3553 /* compute the actual page's SHA1 hash */ 3554 SHA1Init(&sha1ctxt); 3555 SHA1UpdateUsePhysicalAddress(&sha1ctxt, data, size); 3556 SHA1Final(actual_hash, &sha1ctxt); 3557 3558 asha1 = (const uint32_t *) actual_hash; 3559 esha1 = (const uint32_t *) expected_hash; 3560 3561 if (bcmp(expected_hash, actual_hash, SHA1_RESULTLEN) != 0) { 3562 if (cs_debug) { 3563 printf("CODE SIGNING: cs_validate_page: " 3564 "mobj %p off 0x%llx size 0x%lx: " 3565 "actual [0x%x 0x%x 0x%x 0x%x 0x%x] != " 3566 "expected [0x%x 0x%x 0x%x 0x%x 0x%x]\n", 3567 pager, page_offset, size, 3568 asha1[0], asha1[1], asha1[2], 3569 asha1[3], asha1[4], 3570 esha1[0], esha1[1], esha1[2], 3571 esha1[3], esha1[4]); 3572 } 3573 cs_validate_page_bad_hash++; 3574 *tainted = TRUE; 3575 } else { 3576 if (cs_debug > 10) { 3577 printf("CODE SIGNING: cs_validate_page: " 3578 "mobj %p off 0x%llx size 0x%lx: " 3579 "SHA1 OK\n", 3580 pager, page_offset, size); 3581 } 3582 *tainted = FALSE; 3583 } 3584 validated = TRUE; 3585 } 3586 3587 return validated; 3588} 3589 3590int 3591ubc_cs_getcdhash( 3592 vnode_t vp, 3593 off_t offset, 3594 unsigned char *cdhash) 3595{ 3596 struct cs_blob *blobs, *blob; 3597 off_t rel_offset; 3598 int ret; 3599 3600 vnode_lock(vp); 3601 3602 blobs = ubc_get_cs_blobs(vp); 3603 for (blob = blobs; 3604 blob != NULL; 3605 blob = blob->csb_next) { 3606 /* compute offset relative to this blob */ 3607 rel_offset = offset - blob->csb_base_offset; 3608 if (rel_offset >= blob->csb_start_offset && 3609 rel_offset < blob->csb_end_offset) { 3610 /* this blob does cover our "offset" ! */ 3611 break; 3612 } 3613 } 3614 3615 if (blob == NULL) { 3616 /* we didn't find a blob covering "offset" */ 3617 ret = EBADEXEC; /* XXX any better error ? */ 3618 } else { 3619 /* get the SHA1 hash of that blob */ 3620 bcopy(blob->csb_sha1, cdhash, sizeof (blob->csb_sha1)); 3621 ret = 0; 3622 } 3623 3624 vnode_unlock(vp); 3625 3626 return ret; 3627} 3628 3629#if CHECK_CS_VALIDATION_BITMAP 3630#define stob(s) ((atop_64((s)) + 07) >> 3) 3631extern boolean_t root_fs_upgrade_try; 3632 3633/* 3634 * Should we use the code-sign bitmap to avoid repeated code-sign validation? 3635 * Depends: 3636 * a) Is the target vnode on the root filesystem? 3637 * b) Has someone tried to mount the root filesystem read-write? 3638 * If answers are (a) yes AND (b) no, then we can use the bitmap. 3639 */ 3640#define USE_CODE_SIGN_BITMAP(vp) ( (vp != NULL) && (vp->v_mount != NULL) && (vp->v_mount->mnt_flag & MNT_ROOTFS) && !root_fs_upgrade_try) 3641kern_return_t 3642ubc_cs_validation_bitmap_allocate( 3643 vnode_t vp) 3644{ 3645 kern_return_t kr = KERN_SUCCESS; 3646 struct ubc_info *uip; 3647 char *target_bitmap; 3648 vm_object_size_t bitmap_size; 3649 3650 if ( ! USE_CODE_SIGN_BITMAP(vp) || (! UBCINFOEXISTS(vp))) { 3651 kr = KERN_INVALID_ARGUMENT; 3652 } else { 3653 uip = vp->v_ubcinfo; 3654 3655 if ( uip->cs_valid_bitmap == NULL ) { 3656 bitmap_size = stob(uip->ui_size); 3657 target_bitmap = (char*) kalloc( (vm_size_t)bitmap_size ); 3658 if (target_bitmap == 0) { 3659 kr = KERN_NO_SPACE; 3660 } else { 3661 kr = KERN_SUCCESS; 3662 } 3663 if( kr == KERN_SUCCESS ) { 3664 memset( target_bitmap, 0, (size_t)bitmap_size); 3665 uip->cs_valid_bitmap = (void*)target_bitmap; 3666 uip->cs_valid_bitmap_size = bitmap_size; 3667 } 3668 } 3669 } 3670 return kr; 3671} 3672 3673kern_return_t 3674ubc_cs_check_validation_bitmap ( 3675 vnode_t vp, 3676 memory_object_offset_t offset, 3677 int optype) 3678{ 3679 kern_return_t kr = KERN_SUCCESS; 3680 3681 if ( ! USE_CODE_SIGN_BITMAP(vp) || ! UBCINFOEXISTS(vp)) { 3682 kr = KERN_INVALID_ARGUMENT; 3683 } else { 3684 struct ubc_info *uip = vp->v_ubcinfo; 3685 char *target_bitmap = uip->cs_valid_bitmap; 3686 3687 if ( target_bitmap == NULL ) { 3688 kr = KERN_INVALID_ARGUMENT; 3689 } else { 3690 uint64_t bit, byte; 3691 bit = atop_64( offset ); 3692 byte = bit >> 3; 3693 3694 if ( byte > uip->cs_valid_bitmap_size ) { 3695 kr = KERN_INVALID_ARGUMENT; 3696 } else { 3697 3698 if (optype == CS_BITMAP_SET) { 3699 target_bitmap[byte] |= (1 << (bit & 07)); 3700 kr = KERN_SUCCESS; 3701 } else if (optype == CS_BITMAP_CLEAR) { 3702 target_bitmap[byte] &= ~(1 << (bit & 07)); 3703 kr = KERN_SUCCESS; 3704 } else if (optype == CS_BITMAP_CHECK) { 3705 if ( target_bitmap[byte] & (1 << (bit & 07))) { 3706 kr = KERN_SUCCESS; 3707 } else { 3708 kr = KERN_FAILURE; 3709 } 3710 } 3711 } 3712 } 3713 } 3714 return kr; 3715} 3716 3717void 3718ubc_cs_validation_bitmap_deallocate( 3719 vnode_t vp) 3720{ 3721 struct ubc_info *uip; 3722 void *target_bitmap; 3723 vm_object_size_t bitmap_size; 3724 3725 if ( UBCINFOEXISTS(vp)) { 3726 uip = vp->v_ubcinfo; 3727 3728 if ( (target_bitmap = uip->cs_valid_bitmap) != NULL ) { 3729 bitmap_size = uip->cs_valid_bitmap_size; 3730 kfree( target_bitmap, (vm_size_t) bitmap_size ); 3731 uip->cs_valid_bitmap = NULL; 3732 } 3733 } 3734} 3735#else 3736kern_return_t ubc_cs_validation_bitmap_allocate(__unused vnode_t vp){ 3737 return KERN_INVALID_ARGUMENT; 3738} 3739 3740kern_return_t ubc_cs_check_validation_bitmap( 3741 __unused struct vnode *vp, 3742 __unused memory_object_offset_t offset, 3743 __unused int optype){ 3744 3745 return KERN_INVALID_ARGUMENT; 3746} 3747 3748void ubc_cs_validation_bitmap_deallocate(__unused vnode_t vp){ 3749 return; 3750} 3751#endif /* CHECK_CS_VALIDATION_BITMAP */ 3752