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