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