xref: /xnu-8796.141.3/bsd/kern/ubc_subr.c (revision 1b191cb58250d0705d8a51287127505aa4bc0789)
1 /*
2  * Copyright (c) 1999-2020 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 [[email protected]]
31  *		05-Aug-1999	umeshv	Created.
32  *
33  *	Functions related to Unified Buffer cache.
34  *
35  * Caller of UBC functions MUST have a valid reference on the vnode.
36  *
37  */
38 
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/lock.h>
43 #include <sys/mman.h>
44 #include <sys/mount_internal.h>
45 #include <sys/vnode_internal.h>
46 #include <sys/ubc_internal.h>
47 #include <sys/ucred.h>
48 #include <sys/proc_internal.h>
49 #include <sys/kauth.h>
50 #include <sys/buf.h>
51 #include <sys/user.h>
52 #include <sys/codesign.h>
53 #include <sys/codedir_internal.h>
54 #include <sys/fsevents.h>
55 #include <sys/fcntl.h>
56 #include <sys/reboot.h>
57 #include <sys/code_signing.h>
58 
59 #include <mach/mach_types.h>
60 #include <mach/memory_object_types.h>
61 #include <mach/memory_object_control.h>
62 #include <mach/vm_map.h>
63 #include <mach/mach_vm.h>
64 #include <mach/upl.h>
65 
66 #include <kern/kern_types.h>
67 #include <kern/kalloc.h>
68 #include <kern/zalloc.h>
69 #include <kern/thread.h>
70 #include <vm/pmap.h>
71 #include <vm/vm_kern.h>
72 #include <vm/vm_protos.h> /* last */
73 
74 #include <libkern/crypto/sha1.h>
75 #include <libkern/crypto/sha2.h>
76 #include <libkern/libkern.h>
77 
78 #include <security/mac_framework.h>
79 #include <stdbool.h>
80 #include <stdatomic.h>
81 #include <libkern/amfi/amfi.h>
82 
83 /* XXX These should be in a BSD accessible Mach header, but aren't. */
84 extern kern_return_t memory_object_pages_resident(memory_object_control_t,
85     boolean_t *);
86 extern kern_return_t    memory_object_signed(memory_object_control_t control,
87     boolean_t is_signed);
88 extern boolean_t        memory_object_is_signed(memory_object_control_t);
89 extern void             memory_object_mark_trusted(
90 	memory_object_control_t         control);
91 
92 extern void Debugger(const char *message);
93 
94 #if DIAGNOSTIC
95 #if defined(assert)
96 #undef assert
97 #endif
98 #define assert(cond)    \
99     ((void) ((cond) ? 0 : panic("Assert failed: %s", # cond)))
100 #else
101 #include <kern/assert.h>
102 #endif /* DIAGNOSTIC */
103 
104 static int ubc_info_init_internal(struct vnode *vp, int withfsize, off_t filesize);
105 static int ubc_umcallback(vnode_t, void *);
106 static int ubc_msync_internal(vnode_t, off_t, off_t, off_t *, int, int *);
107 static void ubc_cs_free(struct ubc_info *uip);
108 
109 static boolean_t ubc_cs_supports_multilevel_hash(struct cs_blob *blob);
110 static kern_return_t ubc_cs_convert_to_multilevel_hash(struct cs_blob *blob);
111 
112 ZONE_DEFINE_TYPE(ubc_info_zone, "ubc_info zone", struct ubc_info,
113     ZC_ZFREE_CLEARMEM);
114 static uint32_t cs_blob_generation_count = 1;
115 
116 /*
117  * CODESIGNING
118  * Routines to navigate code signing data structures in the kernel...
119  */
120 
121 ZONE_DEFINE_ID(ZONE_ID_CS_BLOB, "cs_blob zone", struct cs_blob,
122     ZC_READONLY | ZC_ZFREE_CLEARMEM);
123 
124 extern int cs_debug;
125 
126 #define PAGE_SHIFT_4K           (12)
127 
128 static boolean_t
cs_valid_range(const void * start,const void * end,const void * lower_bound,const void * upper_bound)129 cs_valid_range(
130 	const void *start,
131 	const void *end,
132 	const void *lower_bound,
133 	const void *upper_bound)
134 {
135 	if (upper_bound < lower_bound ||
136 	    end < start) {
137 		return FALSE;
138 	}
139 
140 	if (start < lower_bound ||
141 	    end > upper_bound) {
142 		return FALSE;
143 	}
144 
145 	return TRUE;
146 }
147 
148 typedef void (*cs_md_init)(void *ctx);
149 typedef void (*cs_md_update)(void *ctx, const void *data, size_t size);
150 typedef void (*cs_md_final)(void *hash, void *ctx);
151 
152 struct cs_hash {
153 	uint8_t             cs_type;    /* type code as per code signing */
154 	size_t              cs_size;    /* size of effective hash (may be truncated) */
155 	size_t              cs_digest_size;/* size of native hash */
156 	cs_md_init          cs_init;
157 	cs_md_update        cs_update;
158 	cs_md_final         cs_final;
159 };
160 
161 uint8_t
cs_hash_type(struct cs_hash const * const cs_hash)162 cs_hash_type(
163 	struct cs_hash const * const cs_hash)
164 {
165 	return cs_hash->cs_type;
166 }
167 
168 static const struct cs_hash cs_hash_sha1 = {
169 	.cs_type = CS_HASHTYPE_SHA1,
170 	.cs_size = CS_SHA1_LEN,
171 	.cs_digest_size = SHA_DIGEST_LENGTH,
172 	.cs_init = (cs_md_init)SHA1Init,
173 	.cs_update = (cs_md_update)SHA1Update,
174 	.cs_final = (cs_md_final)SHA1Final,
175 };
176 #if CRYPTO_SHA2
177 static const struct cs_hash cs_hash_sha256 = {
178 	.cs_type = CS_HASHTYPE_SHA256,
179 	.cs_size = SHA256_DIGEST_LENGTH,
180 	.cs_digest_size = SHA256_DIGEST_LENGTH,
181 	.cs_init = (cs_md_init)SHA256_Init,
182 	.cs_update = (cs_md_update)SHA256_Update,
183 	.cs_final = (cs_md_final)SHA256_Final,
184 };
185 static const struct cs_hash cs_hash_sha256_truncate = {
186 	.cs_type = CS_HASHTYPE_SHA256_TRUNCATED,
187 	.cs_size = CS_SHA256_TRUNCATED_LEN,
188 	.cs_digest_size = SHA256_DIGEST_LENGTH,
189 	.cs_init = (cs_md_init)SHA256_Init,
190 	.cs_update = (cs_md_update)SHA256_Update,
191 	.cs_final = (cs_md_final)SHA256_Final,
192 };
193 static const struct cs_hash cs_hash_sha384 = {
194 	.cs_type = CS_HASHTYPE_SHA384,
195 	.cs_size = SHA384_DIGEST_LENGTH,
196 	.cs_digest_size = SHA384_DIGEST_LENGTH,
197 	.cs_init = (cs_md_init)SHA384_Init,
198 	.cs_update = (cs_md_update)SHA384_Update,
199 	.cs_final = (cs_md_final)SHA384_Final,
200 };
201 #endif
202 
203 static struct cs_hash const *
cs_find_md(uint8_t type)204 cs_find_md(uint8_t type)
205 {
206 	if (type == CS_HASHTYPE_SHA1) {
207 		return &cs_hash_sha1;
208 #if CRYPTO_SHA2
209 	} else if (type == CS_HASHTYPE_SHA256) {
210 		return &cs_hash_sha256;
211 	} else if (type == CS_HASHTYPE_SHA256_TRUNCATED) {
212 		return &cs_hash_sha256_truncate;
213 	} else if (type == CS_HASHTYPE_SHA384) {
214 		return &cs_hash_sha384;
215 #endif
216 	}
217 	return NULL;
218 }
219 
220 union cs_hash_union {
221 	SHA1_CTX                sha1ctxt;
222 	SHA256_CTX              sha256ctx;
223 	SHA384_CTX              sha384ctx;
224 };
225 
226 
227 /*
228  * Choose among different hash algorithms.
229  * Higher is better, 0 => don't use at all.
230  */
231 static const uint32_t hashPriorities[] = {
232 	CS_HASHTYPE_SHA1,
233 	CS_HASHTYPE_SHA256_TRUNCATED,
234 	CS_HASHTYPE_SHA256,
235 	CS_HASHTYPE_SHA384,
236 };
237 
238 static unsigned int
hash_rank(const CS_CodeDirectory * cd)239 hash_rank(const CS_CodeDirectory *cd)
240 {
241 	uint32_t type = cd->hashType;
242 	unsigned int n;
243 
244 	for (n = 0; n < sizeof(hashPriorities) / sizeof(hashPriorities[0]); ++n) {
245 		if (hashPriorities[n] == type) {
246 			return n + 1;
247 		}
248 	}
249 	return 0;       /* not supported */
250 }
251 
252 
253 /*
254  * Locating a page hash
255  */
256 static const unsigned char *
hashes(const CS_CodeDirectory * cd,uint32_t page,size_t hash_len,const char * lower_bound,const char * upper_bound)257 hashes(
258 	const CS_CodeDirectory *cd,
259 	uint32_t page,
260 	size_t hash_len,
261 	const char *lower_bound,
262 	const char *upper_bound)
263 {
264 	const unsigned char *base, *top, *hash;
265 	uint32_t nCodeSlots = ntohl(cd->nCodeSlots);
266 
267 	assert(cs_valid_range(cd, cd + 1, lower_bound, upper_bound));
268 
269 	if ((ntohl(cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(cd->scatterOffset))) {
270 		/* Get first scatter struct */
271 		const SC_Scatter *scatter = (const SC_Scatter*)
272 		    ((const char*)cd + ntohl(cd->scatterOffset));
273 		uint32_t hashindex = 0, scount, sbase = 0;
274 		/* iterate all scatter structs */
275 		do {
276 			if ((const char*)scatter > (const char*)cd + ntohl(cd->length)) {
277 				if (cs_debug) {
278 					printf("CODE SIGNING: Scatter extends past Code Directory\n");
279 				}
280 				return NULL;
281 			}
282 
283 			scount = ntohl(scatter->count);
284 			uint32_t new_base = ntohl(scatter->base);
285 
286 			/* last scatter? */
287 			if (scount == 0) {
288 				return NULL;
289 			}
290 
291 			if ((hashindex > 0) && (new_base <= sbase)) {
292 				if (cs_debug) {
293 					printf("CODE SIGNING: unordered Scatter, prev base %d, cur base %d\n",
294 					    sbase, new_base);
295 				}
296 				return NULL;    /* unordered scatter array */
297 			}
298 			sbase = new_base;
299 
300 			/* this scatter beyond page we're looking for? */
301 			if (sbase > page) {
302 				return NULL;
303 			}
304 
305 			if (sbase + scount >= page) {
306 				/* Found the scatter struct that is
307 				 * referencing our page */
308 
309 				/* base = address of first hash covered by scatter */
310 				base = (const unsigned char *)cd + ntohl(cd->hashOffset) +
311 				    hashindex * hash_len;
312 				/* top = address of first hash after this scatter */
313 				top = base + scount * hash_len;
314 				if (!cs_valid_range(base, top, lower_bound,
315 				    upper_bound) ||
316 				    hashindex > nCodeSlots) {
317 					return NULL;
318 				}
319 
320 				break;
321 			}
322 
323 			/* this scatter struct is before the page we're looking
324 			 * for. Iterate. */
325 			hashindex += scount;
326 			scatter++;
327 		} while (1);
328 
329 		hash = base + (page - sbase) * hash_len;
330 	} else {
331 		base = (const unsigned char *)cd + ntohl(cd->hashOffset);
332 		top = base + nCodeSlots * hash_len;
333 		if (!cs_valid_range(base, top, lower_bound, upper_bound) ||
334 		    page > nCodeSlots) {
335 			return NULL;
336 		}
337 		assert(page < nCodeSlots);
338 
339 		hash = base + page * hash_len;
340 	}
341 
342 	if (!cs_valid_range(hash, hash + hash_len,
343 	    lower_bound, upper_bound)) {
344 		hash = NULL;
345 	}
346 
347 	return hash;
348 }
349 
350 /*
351  * cs_validate_codedirectory
352  *
353  * Validate that pointers inside the code directory to make sure that
354  * all offsets and lengths are constrained within the buffer.
355  *
356  * Parameters:	cd			Pointer to code directory buffer
357  *		length			Length of buffer
358  *
359  * Returns:	0			Success
360  *		EBADEXEC		Invalid code signature
361  */
362 
363 static int
cs_validate_codedirectory(const CS_CodeDirectory * cd,size_t length)364 cs_validate_codedirectory(const CS_CodeDirectory *cd, size_t length)
365 {
366 	struct cs_hash const *hashtype;
367 
368 	if (length < sizeof(*cd)) {
369 		return EBADEXEC;
370 	}
371 	if (ntohl(cd->magic) != CSMAGIC_CODEDIRECTORY) {
372 		return EBADEXEC;
373 	}
374 	if ((cd->pageSize != PAGE_SHIFT_4K) && (cd->pageSize != PAGE_SHIFT)) {
375 		printf("disallowing unsupported code signature page shift: %u\n", cd->pageSize);
376 		return EBADEXEC;
377 	}
378 	hashtype = cs_find_md(cd->hashType);
379 	if (hashtype == NULL) {
380 		return EBADEXEC;
381 	}
382 
383 	if (cd->hashSize != hashtype->cs_size) {
384 		return EBADEXEC;
385 	}
386 
387 	if (length < ntohl(cd->hashOffset)) {
388 		return EBADEXEC;
389 	}
390 
391 	/* check that nSpecialSlots fits in the buffer in front of hashOffset */
392 	if (ntohl(cd->hashOffset) / hashtype->cs_size < ntohl(cd->nSpecialSlots)) {
393 		return EBADEXEC;
394 	}
395 
396 	/* check that codeslots fits in the buffer */
397 	if ((length - ntohl(cd->hashOffset)) / hashtype->cs_size < ntohl(cd->nCodeSlots)) {
398 		return EBADEXEC;
399 	}
400 
401 	if (ntohl(cd->version) >= CS_SUPPORTSSCATTER && cd->scatterOffset) {
402 		if (length < ntohl(cd->scatterOffset)) {
403 			return EBADEXEC;
404 		}
405 
406 		const SC_Scatter *scatter = (const SC_Scatter *)
407 		    (((const uint8_t *)cd) + ntohl(cd->scatterOffset));
408 		uint32_t nPages = 0;
409 
410 		/*
411 		 * Check each scatter buffer, since we don't know the
412 		 * length of the scatter buffer array, we have to
413 		 * check each entry.
414 		 */
415 		while (1) {
416 			/* check that the end of each scatter buffer in within the length */
417 			if (((const uint8_t *)scatter) + sizeof(scatter[0]) > (const uint8_t *)cd + length) {
418 				return EBADEXEC;
419 			}
420 			uint32_t scount = ntohl(scatter->count);
421 			if (scount == 0) {
422 				break;
423 			}
424 			if (nPages + scount < nPages) {
425 				return EBADEXEC;
426 			}
427 			nPages += scount;
428 			scatter++;
429 
430 			/* XXX check that basees doesn't overlap */
431 			/* XXX check that targetOffset doesn't overlap */
432 		}
433 #if 0 /* rdar://12579439 */
434 		if (nPages != ntohl(cd->nCodeSlots)) {
435 			return EBADEXEC;
436 		}
437 #endif
438 	}
439 
440 	if (length < ntohl(cd->identOffset)) {
441 		return EBADEXEC;
442 	}
443 
444 	/* identifier is NUL terminated string */
445 	if (cd->identOffset) {
446 		const uint8_t *ptr = (const uint8_t *)cd + ntohl(cd->identOffset);
447 		if (memchr(ptr, 0, length - ntohl(cd->identOffset)) == NULL) {
448 			return EBADEXEC;
449 		}
450 	}
451 
452 	/* team identifier is NULL terminated string */
453 	if (ntohl(cd->version) >= CS_SUPPORTSTEAMID && ntohl(cd->teamOffset)) {
454 		if (length < ntohl(cd->teamOffset)) {
455 			return EBADEXEC;
456 		}
457 
458 		const uint8_t *ptr = (const uint8_t *)cd + ntohl(cd->teamOffset);
459 		if (memchr(ptr, 0, length - ntohl(cd->teamOffset)) == NULL) {
460 			return EBADEXEC;
461 		}
462 	}
463 
464 	/* linkage is variable length binary data */
465 	if (ntohl(cd->version) >= CS_SUPPORTSLINKAGE && cd->linkageHashType != 0) {
466 		const uintptr_t ptr = (uintptr_t)cd + ntohl(cd->linkageOffset);
467 		const uintptr_t ptr_end = ptr + ntohl(cd->linkageSize);
468 
469 		if (ptr_end < ptr || ptr < (uintptr_t)cd || ptr_end > (uintptr_t)cd + length) {
470 			return EBADEXEC;
471 		}
472 	}
473 
474 
475 	return 0;
476 }
477 
478 /*
479  *
480  */
481 
482 static int
cs_validate_blob(const CS_GenericBlob * blob,size_t length)483 cs_validate_blob(const CS_GenericBlob *blob, size_t length)
484 {
485 	if (length < sizeof(CS_GenericBlob) || length < ntohl(blob->length)) {
486 		return EBADEXEC;
487 	}
488 	return 0;
489 }
490 
491 /*
492  * cs_validate_csblob
493  *
494  * Validate that superblob/embedded code directory to make sure that
495  * all internal pointers are valid.
496  *
497  * Will validate both a superblob csblob and a "raw" code directory.
498  *
499  *
500  * Parameters:	buffer			Pointer to code signature
501  *		length			Length of buffer
502  *		rcd			returns pointer to code directory
503  *
504  * Returns:	0			Success
505  *		EBADEXEC		Invalid code signature
506  */
507 
508 static int
cs_validate_csblob(const uint8_t * addr,const size_t blob_size,const CS_CodeDirectory ** rcd,const CS_GenericBlob ** rentitlements,const CS_GenericBlob ** rder_entitlements)509 cs_validate_csblob(
510 	const uint8_t *addr,
511 	const size_t blob_size,
512 	const CS_CodeDirectory **rcd,
513 	const CS_GenericBlob **rentitlements,
514 	const CS_GenericBlob **rder_entitlements)
515 {
516 	const CS_GenericBlob *blob;
517 	int error;
518 	size_t length;
519 	const CS_GenericBlob *self_constraint = NULL;
520 	const CS_GenericBlob *parent_constraint = NULL;
521 	const CS_GenericBlob *responsible_proc_constraint = NULL;
522 
523 	*rcd = NULL;
524 	*rentitlements = NULL;
525 	*rder_entitlements = NULL;
526 
527 	blob = (const CS_GenericBlob *)(const void *)addr;
528 
529 	length = blob_size;
530 	error = cs_validate_blob(blob, length);
531 	if (error) {
532 		return error;
533 	}
534 	length = ntohl(blob->length);
535 
536 	if (ntohl(blob->magic) == CSMAGIC_EMBEDDED_SIGNATURE) {
537 		const CS_SuperBlob *sb;
538 		uint32_t n, count;
539 		const CS_CodeDirectory *best_cd = NULL;
540 		unsigned int best_rank = 0;
541 #if XNU_PLATFORM_WatchOS
542 		const CS_CodeDirectory *sha1_cd = NULL;
543 #endif
544 
545 		if (length < sizeof(CS_SuperBlob)) {
546 			return EBADEXEC;
547 		}
548 
549 		sb = (const CS_SuperBlob *)blob;
550 		count = ntohl(sb->count);
551 
552 		/* check that the array of BlobIndex fits in the rest of the data */
553 		if ((length - sizeof(CS_SuperBlob)) / sizeof(CS_BlobIndex) < count) {
554 			return EBADEXEC;
555 		}
556 
557 		/* now check each BlobIndex */
558 		for (n = 0; n < count; n++) {
559 			const CS_BlobIndex *blobIndex = &sb->index[n];
560 			uint32_t type = ntohl(blobIndex->type);
561 			uint32_t offset = ntohl(blobIndex->offset);
562 			if (length < offset) {
563 				return EBADEXEC;
564 			}
565 
566 			const CS_GenericBlob *subBlob =
567 			    (const CS_GenericBlob *)(const void *)(addr + offset);
568 
569 			size_t subLength = length - offset;
570 
571 			if ((error = cs_validate_blob(subBlob, subLength)) != 0) {
572 				return error;
573 			}
574 			subLength = ntohl(subBlob->length);
575 
576 			/* extra validation for CDs, that is also returned */
577 			if (type == CSSLOT_CODEDIRECTORY || (type >= CSSLOT_ALTERNATE_CODEDIRECTORIES && type < CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT)) {
578 				const CS_CodeDirectory *candidate = (const CS_CodeDirectory *)subBlob;
579 				if ((error = cs_validate_codedirectory(candidate, subLength)) != 0) {
580 					return error;
581 				}
582 				unsigned int rank = hash_rank(candidate);
583 				if (cs_debug > 3) {
584 					printf("CodeDirectory type %d rank %d at slot 0x%x index %d\n", candidate->hashType, (int)rank, (int)type, (int)n);
585 				}
586 				if (best_cd == NULL || rank > best_rank) {
587 					best_cd = candidate;
588 					best_rank = rank;
589 
590 					if (cs_debug > 2) {
591 						printf("using CodeDirectory type %d (rank %d)\n", (int)best_cd->hashType, best_rank);
592 					}
593 					*rcd = best_cd;
594 				} else if (best_cd != NULL && rank == best_rank) {
595 					/* repeat of a hash type (1:1 mapped to ranks), illegal and suspicious */
596 					printf("multiple hash=%d CodeDirectories in signature; rejecting\n", best_cd->hashType);
597 					return EBADEXEC;
598 				}
599 #if XNU_PLATFORM_WatchOS
600 				if (candidate->hashType == CS_HASHTYPE_SHA1) {
601 					if (sha1_cd != NULL) {
602 						printf("multiple sha1 CodeDirectories in signature; rejecting\n");
603 						return EBADEXEC;
604 					}
605 					sha1_cd = candidate;
606 				}
607 #endif
608 			} else if (type == CSSLOT_ENTITLEMENTS) {
609 				if (ntohl(subBlob->magic) != CSMAGIC_EMBEDDED_ENTITLEMENTS) {
610 					return EBADEXEC;
611 				}
612 				if (*rentitlements != NULL) {
613 					printf("multiple entitlements blobs\n");
614 					return EBADEXEC;
615 				}
616 				*rentitlements = subBlob;
617 			} else if (type == CSSLOT_DER_ENTITLEMENTS) {
618 				if (ntohl(subBlob->magic) != CSMAGIC_EMBEDDED_DER_ENTITLEMENTS) {
619 					return EBADEXEC;
620 				}
621 				if (*rder_entitlements != NULL) {
622 					printf("multiple der entitlements blobs\n");
623 					return EBADEXEC;
624 				}
625 				*rder_entitlements = subBlob;
626 			} else if (type == CSSLOT_LAUNCH_CONSTRAINT_SELF) {
627 				if (ntohl(subBlob->magic) != CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT) {
628 					return EBADEXEC;
629 				}
630 				if (self_constraint != NULL) {
631 					printf("multiple self constraint blobs\n");
632 					return EBADEXEC;
633 				}
634 				self_constraint = subBlob;
635 			} else if (type == CSSLOT_LAUNCH_CONSTRAINT_PARENT) {
636 				if (ntohl(subBlob->magic) != CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT) {
637 					return EBADEXEC;
638 				}
639 				if (parent_constraint != NULL) {
640 					printf("multiple parent constraint blobs\n");
641 					return EBADEXEC;
642 				}
643 				parent_constraint = subBlob;
644 			} else if (type == CSSLOT_LAUNCH_CONSTRAINT_RESPONSIBLE) {
645 				if (ntohl(subBlob->magic) != CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT) {
646 					return EBADEXEC;
647 				}
648 				if (responsible_proc_constraint != NULL) {
649 					printf("multiple responsible process constraint blobs\n");
650 					return EBADEXEC;
651 				}
652 				responsible_proc_constraint = subBlob;
653 			}
654 		}
655 
656 #if XNU_PLATFORM_WatchOS
657 		/* To keep watchOS fast enough, we have to resort to sha1 for
658 		 * some code.
659 		 *
660 		 * At the time of writing this comment, known sha1 attacks are
661 		 * collision attacks (not preimage or second preimage
662 		 * attacks), which do not apply to platform binaries since
663 		 * they have a fixed hash in the trust cache.  Given this
664 		 * property, we only prefer sha1 code directories for adhoc
665 		 * signatures, which always have to be in a trust cache to be
666 		 * valid (can-load-cdhash does not exist for watchOS). Those
667 		 * are, incidentally, also the platform binaries, for which we
668 		 * care about the performance hit that sha256 would bring us.
669 		 *
670 		 * Platform binaries may still contain a (not chosen) sha256
671 		 * code directory, which keeps software updates that switch to
672 		 * sha256-only small.
673 		 */
674 
675 		if (*rcd != NULL && sha1_cd != NULL && (ntohl(sha1_cd->flags) & CS_ADHOC)) {
676 			if (sha1_cd->flags != (*rcd)->flags) {
677 				printf("mismatched flags between hash %d (flags: %#x) and sha1 (flags: %#x) cd.\n",
678 				    (int)(*rcd)->hashType, (*rcd)->flags, sha1_cd->flags);
679 				*rcd = NULL;
680 				return EBADEXEC;
681 			}
682 
683 			*rcd = sha1_cd;
684 		}
685 #endif
686 	} else if (ntohl(blob->magic) == CSMAGIC_CODEDIRECTORY) {
687 		if ((error = cs_validate_codedirectory((const CS_CodeDirectory *)(const void *)addr, length)) != 0) {
688 			return error;
689 		}
690 		*rcd = (const CS_CodeDirectory *)blob;
691 	} else {
692 		return EBADEXEC;
693 	}
694 
695 	if (*rcd == NULL) {
696 		return EBADEXEC;
697 	}
698 
699 	return 0;
700 }
701 
702 /*
703  * cs_find_blob_bytes
704  *
705  * Find an blob from the superblob/code directory. The blob must have
706  * been been validated by cs_validate_csblob() before calling
707  * this. Use csblob_find_blob() instead.
708  *
709  * Will also find a "raw" code directory if its stored as well as
710  * searching the superblob.
711  *
712  * Parameters:	buffer			Pointer to code signature
713  *		length			Length of buffer
714  *		type			type of blob to find
715  *		magic			the magic number for that blob
716  *
717  * Returns:	pointer			Success
718  *		NULL			Buffer not found
719  */
720 
721 const CS_GenericBlob *
csblob_find_blob_bytes(const uint8_t * addr,size_t length,uint32_t type,uint32_t magic)722 csblob_find_blob_bytes(const uint8_t *addr, size_t length, uint32_t type, uint32_t magic)
723 {
724 	const CS_GenericBlob *blob = (const CS_GenericBlob *)(const void *)addr;
725 
726 	if ((addr + length) < addr) {
727 		panic("CODE SIGNING: CS Blob length overflow for addr: %p", addr);
728 	}
729 
730 	if (ntohl(blob->magic) == CSMAGIC_EMBEDDED_SIGNATURE) {
731 		const CS_SuperBlob *sb = (const CS_SuperBlob *)blob;
732 		size_t n, count = ntohl(sb->count);
733 
734 		for (n = 0; n < count; n++) {
735 			if (ntohl(sb->index[n].type) != type) {
736 				continue;
737 			}
738 			uint32_t offset = ntohl(sb->index[n].offset);
739 			if (length - sizeof(const CS_GenericBlob) < offset) {
740 				return NULL;
741 			}
742 			blob = (const CS_GenericBlob *)(const void *)(addr + offset);
743 			if (ntohl(blob->magic) != magic) {
744 				continue;
745 			}
746 			if (((vm_address_t)blob + ntohl(blob->length)) < (vm_address_t)blob) {
747 				panic("CODE SIGNING: CS Blob length overflow for blob at: %p", blob);
748 			} else if (((vm_address_t)blob + ntohl(blob->length)) > (vm_address_t)(addr + length)) {
749 				continue;
750 			}
751 			return blob;
752 		}
753 	} else if (type == CSSLOT_CODEDIRECTORY && ntohl(blob->magic) == CSMAGIC_CODEDIRECTORY
754 	    && magic == CSMAGIC_CODEDIRECTORY) {
755 		if (((vm_address_t)blob + ntohl(blob->length)) < (vm_address_t)blob) {
756 			panic("CODE SIGNING: CS Blob length overflow for code directory blob at: %p", blob);
757 		} else if (((vm_address_t)blob + ntohl(blob->length)) > (vm_address_t)(addr + length)) {
758 			return NULL;
759 		}
760 		return blob;
761 	}
762 	return NULL;
763 }
764 
765 
766 const CS_GenericBlob *
csblob_find_blob(struct cs_blob * csblob,uint32_t type,uint32_t magic)767 csblob_find_blob(struct cs_blob *csblob, uint32_t type, uint32_t magic)
768 {
769 	if ((csblob->csb_flags & CS_VALID) == 0) {
770 		return NULL;
771 	}
772 	return csblob_find_blob_bytes((const uint8_t *)csblob->csb_mem_kaddr, csblob->csb_mem_size, type, magic);
773 }
774 
775 static const uint8_t *
find_special_slot(const CS_CodeDirectory * cd,size_t slotsize,uint32_t slot)776 find_special_slot(const CS_CodeDirectory *cd, size_t slotsize, uint32_t slot)
777 {
778 	/* there is no zero special slot since that is the first code slot */
779 	if (ntohl(cd->nSpecialSlots) < slot || slot == 0) {
780 		return NULL;
781 	}
782 
783 	return (const uint8_t *)cd + ntohl(cd->hashOffset) - (slotsize * slot);
784 }
785 
786 static uint8_t cshash_zero[CS_HASH_MAX_SIZE] = { 0 };
787 
788 static int
csblob_find_special_slot_blob(struct cs_blob * csblob,uint32_t slot,uint32_t magic,const CS_GenericBlob ** out_start,size_t * out_length)789 csblob_find_special_slot_blob(struct cs_blob* csblob, uint32_t slot, uint32_t magic, const CS_GenericBlob **out_start, size_t *out_length)
790 {
791 	uint8_t computed_hash[CS_HASH_MAX_SIZE];
792 	const CS_GenericBlob *blob;
793 	const CS_CodeDirectory *code_dir;
794 	const uint8_t *embedded_hash;
795 	union cs_hash_union context;
796 
797 	if (out_start) {
798 		*out_start = NULL;
799 	}
800 	if (out_length) {
801 		*out_length = 0;
802 	}
803 
804 	if (csblob->csb_hashtype == NULL || csblob->csb_hashtype->cs_digest_size > sizeof(computed_hash)) {
805 		return EBADEXEC;
806 	}
807 
808 	code_dir = csblob->csb_cd;
809 
810 	blob = csblob_find_blob_bytes((const uint8_t *)csblob->csb_mem_kaddr, csblob->csb_mem_size, slot, magic);
811 
812 	embedded_hash = find_special_slot(code_dir, csblob->csb_hashtype->cs_size, slot);
813 
814 	if (embedded_hash == NULL) {
815 		if (blob) {
816 			return EBADEXEC;
817 		}
818 		return 0;
819 	} else if (blob == NULL) {
820 		if (memcmp(embedded_hash, cshash_zero, csblob->csb_hashtype->cs_size) != 0) {
821 			return EBADEXEC;
822 		} else {
823 			return 0;
824 		}
825 	}
826 
827 	csblob->csb_hashtype->cs_init(&context);
828 	csblob->csb_hashtype->cs_update(&context, blob, ntohl(blob->length));
829 	csblob->csb_hashtype->cs_final(computed_hash, &context);
830 
831 	if (memcmp(computed_hash, embedded_hash, csblob->csb_hashtype->cs_size) != 0) {
832 		return EBADEXEC;
833 	}
834 	if (out_start) {
835 		*out_start = blob;
836 	}
837 	if (out_length) {
838 		*out_length = ntohl(blob->length);
839 	}
840 
841 	return 0;
842 }
843 
844 int
csblob_get_entitlements(struct cs_blob * csblob,void ** out_start,size_t * out_length)845 csblob_get_entitlements(struct cs_blob *csblob, void **out_start, size_t *out_length)
846 {
847 	uint8_t computed_hash[CS_HASH_MAX_SIZE];
848 	const CS_GenericBlob *entitlements;
849 	const CS_CodeDirectory *code_dir;
850 	const uint8_t *embedded_hash;
851 	union cs_hash_union context;
852 
853 	*out_start = NULL;
854 	*out_length = 0;
855 
856 	if (csblob->csb_hashtype == NULL || csblob->csb_hashtype->cs_digest_size > sizeof(computed_hash)) {
857 		return EBADEXEC;
858 	}
859 
860 	code_dir = csblob->csb_cd;
861 
862 	if ((csblob->csb_flags & CS_VALID) == 0) {
863 		entitlements = NULL;
864 	} else {
865 		entitlements = csblob->csb_entitlements_blob;
866 	}
867 	embedded_hash = find_special_slot(code_dir, csblob->csb_hashtype->cs_size, CSSLOT_ENTITLEMENTS);
868 
869 	if (embedded_hash == NULL) {
870 		if (entitlements) {
871 			return EBADEXEC;
872 		}
873 		return 0;
874 	} else if (entitlements == NULL) {
875 		if (memcmp(embedded_hash, cshash_zero, csblob->csb_hashtype->cs_size) != 0) {
876 			return EBADEXEC;
877 		} else {
878 			return 0;
879 		}
880 	}
881 
882 	csblob->csb_hashtype->cs_init(&context);
883 	csblob->csb_hashtype->cs_update(&context, entitlements, ntohl(entitlements->length));
884 	csblob->csb_hashtype->cs_final(computed_hash, &context);
885 
886 	if (memcmp(computed_hash, embedded_hash, csblob->csb_hashtype->cs_size) != 0) {
887 		return EBADEXEC;
888 	}
889 
890 	*out_start = __DECONST(void *, entitlements);
891 	*out_length = ntohl(entitlements->length);
892 
893 	return 0;
894 }
895 
896 const CS_GenericBlob*
csblob_get_der_entitlements_unsafe(struct cs_blob * csblob)897 csblob_get_der_entitlements_unsafe(struct cs_blob * csblob)
898 {
899 	if ((csblob->csb_flags & CS_VALID) == 0) {
900 		return NULL;
901 	}
902 
903 	return csblob->csb_der_entitlements_blob;
904 }
905 
906 int
csblob_get_der_entitlements(struct cs_blob * csblob,const CS_GenericBlob ** out_start,size_t * out_length)907 csblob_get_der_entitlements(struct cs_blob *csblob, const CS_GenericBlob **out_start, size_t *out_length)
908 {
909 	uint8_t computed_hash[CS_HASH_MAX_SIZE];
910 	const CS_GenericBlob *der_entitlements;
911 	const CS_CodeDirectory *code_dir;
912 	const uint8_t *embedded_hash;
913 	union cs_hash_union context;
914 
915 	*out_start = NULL;
916 	*out_length = 0;
917 
918 	if (csblob->csb_hashtype == NULL || csblob->csb_hashtype->cs_digest_size > sizeof(computed_hash)) {
919 		return EBADEXEC;
920 	}
921 
922 	code_dir = csblob->csb_cd;
923 
924 	if ((csblob->csb_flags & CS_VALID) == 0) {
925 		der_entitlements = NULL;
926 	} else {
927 		der_entitlements = csblob->csb_der_entitlements_blob;
928 	}
929 	embedded_hash = find_special_slot(code_dir, csblob->csb_hashtype->cs_size, CSSLOT_DER_ENTITLEMENTS);
930 
931 	if (embedded_hash == NULL) {
932 		if (der_entitlements) {
933 			return EBADEXEC;
934 		}
935 		return 0;
936 	} else if (der_entitlements == NULL) {
937 		if (memcmp(embedded_hash, cshash_zero, csblob->csb_hashtype->cs_size) != 0) {
938 			return EBADEXEC;
939 		} else {
940 			return 0;
941 		}
942 	}
943 
944 	csblob->csb_hashtype->cs_init(&context);
945 	csblob->csb_hashtype->cs_update(&context, der_entitlements, ntohl(der_entitlements->length));
946 	csblob->csb_hashtype->cs_final(computed_hash, &context);
947 
948 	if (memcmp(computed_hash, embedded_hash, csblob->csb_hashtype->cs_size) != 0) {
949 		return EBADEXEC;
950 	}
951 
952 	*out_start = der_entitlements;
953 	*out_length = ntohl(der_entitlements->length);
954 
955 	return 0;
956 }
957 
958 static bool
ubc_cs_blob_pagewise_allocate(__unused vm_size_t size)959 ubc_cs_blob_pagewise_allocate(
960 	__unused vm_size_t size)
961 {
962 #if CODE_SIGNING_MONITOR
963 	/* If the monitor isn't enabled, then we don't need to page-align */
964 	if (csm_enabled() == false) {
965 		return false;
966 	}
967 
968 	/*
969 	 * Small allocations can be maanged by the monitor itself. We only need to allocate
970 	 * page-wise when it is a sufficiently large allocation and the monitor cannot manage
971 	 * it on its own.
972 	 */
973 	if (size <= csm_signature_size_limit()) {
974 		return false;
975 	}
976 
977 	return true;
978 #else
979 	/* Without a monitor, we never need to page align */
980 	return false;
981 #endif /* CODE_SIGNING_MONITOR */
982 }
983 
984 int
csblob_register_profile_uuid(struct cs_blob __unused * csblob,const uuid_t __unused profile_uuid,void __unused * profile_addr,vm_size_t __unused profile_size)985 csblob_register_profile_uuid(
986 	struct cs_blob __unused *csblob,
987 	const uuid_t __unused profile_uuid,
988 	void __unused *profile_addr,
989 	vm_size_t __unused profile_size)
990 {
991 #if CODE_SIGNING_MONITOR
992 	/* Profiles only need to be registered for monitor environments */
993 	assert(profile_addr != NULL);
994 	assert(profile_size != 0);
995 	assert(csblob != NULL);
996 
997 	kern_return_t kr = csm_register_provisioning_profile(
998 		profile_uuid,
999 		profile_addr, profile_size);
1000 
1001 	if ((kr != KERN_SUCCESS) && (kr != KERN_ALREADY_IN_SET)) {
1002 		return EPERM;
1003 	}
1004 
1005 	/* Associate the profile with the monitor's signature object */
1006 	kr = csm_associate_provisioning_profile(
1007 		csblob->csb_csm_obj,
1008 		profile_uuid);
1009 
1010 	if ((kr != KERN_SUCCESS) && (kr != KERN_NOT_SUPPORTED)) {
1011 		return EPERM;
1012 	}
1013 
1014 	return 0;
1015 #else
1016 	return 0;
1017 #endif /* CODE_SIGNING_MONITOR */
1018 }
1019 
1020 /*
1021  * CODESIGNING
1022  * End of routines to navigate code signing data structures in the kernel.
1023  */
1024 
1025 
1026 
1027 /*
1028  * ubc_info_init
1029  *
1030  * Allocate and attach an empty ubc_info structure to a vnode
1031  *
1032  * Parameters:	vp			Pointer to the vnode
1033  *
1034  * Returns:	0			Success
1035  *	vnode_size:ENOMEM		Not enough space
1036  *	vnode_size:???			Other error from vnode_getattr
1037  *
1038  */
1039 int
ubc_info_init(struct vnode * vp)1040 ubc_info_init(struct vnode *vp)
1041 {
1042 	return ubc_info_init_internal(vp, 0, 0);
1043 }
1044 
1045 
1046 /*
1047  * ubc_info_init_withsize
1048  *
1049  * Allocate and attach a sized ubc_info structure to a vnode
1050  *
1051  * Parameters:	vp			Pointer to the vnode
1052  *		filesize		The size of the file
1053  *
1054  * Returns:	0			Success
1055  *	vnode_size:ENOMEM		Not enough space
1056  *	vnode_size:???			Other error from vnode_getattr
1057  */
1058 int
ubc_info_init_withsize(struct vnode * vp,off_t filesize)1059 ubc_info_init_withsize(struct vnode *vp, off_t filesize)
1060 {
1061 	return ubc_info_init_internal(vp, 1, filesize);
1062 }
1063 
1064 
1065 /*
1066  * ubc_info_init_internal
1067  *
1068  * Allocate and attach a ubc_info structure to a vnode
1069  *
1070  * Parameters:	vp			Pointer to the vnode
1071  *		withfsize{0,1}		Zero if the size should be obtained
1072  *					from the vnode; otherwise, use filesize
1073  *		filesize		The size of the file, if withfsize == 1
1074  *
1075  * Returns:	0			Success
1076  *	vnode_size:ENOMEM		Not enough space
1077  *	vnode_size:???			Other error from vnode_getattr
1078  *
1079  * Notes:	We call a blocking zalloc(), and the zone was created as an
1080  *		expandable and collectable zone, so if no memory is available,
1081  *		it is possible for zalloc() to block indefinitely.  zalloc()
1082  *		may also panic if the zone of zones is exhausted, since it's
1083  *		NOT expandable.
1084  *
1085  *		We unconditionally call vnode_pager_setup(), even if this is
1086  *		a reuse of a ubc_info; in that case, we should probably assert
1087  *		that it does not already have a pager association, but do not.
1088  *
1089  *		Since memory_object_create_named() can only fail from receiving
1090  *		an invalid pager argument, the explicit check and panic is
1091  *		merely precautionary.
1092  */
1093 static int
ubc_info_init_internal(vnode_t vp,int withfsize,off_t filesize)1094 ubc_info_init_internal(vnode_t vp, int withfsize, off_t filesize)
1095 {
1096 	struct ubc_info *uip;
1097 	void *  pager;
1098 	int error = 0;
1099 	kern_return_t kret;
1100 	memory_object_control_t control;
1101 
1102 	uip = vp->v_ubcinfo;
1103 
1104 	/*
1105 	 * If there is not already a ubc_info attached to the vnode, we
1106 	 * attach one; otherwise, we will reuse the one that's there.
1107 	 */
1108 	if (uip == UBC_INFO_NULL) {
1109 		uip = zalloc_flags(ubc_info_zone, Z_WAITOK | Z_ZERO);
1110 
1111 		uip->ui_vnode = vp;
1112 		uip->ui_flags = UI_INITED;
1113 		uip->ui_ucred = NOCRED;
1114 	}
1115 	assert(uip->ui_flags != UI_NONE);
1116 	assert(uip->ui_vnode == vp);
1117 
1118 	/* now set this ubc_info in the vnode */
1119 	vp->v_ubcinfo = uip;
1120 
1121 	/*
1122 	 * Allocate a pager object for this vnode
1123 	 *
1124 	 * XXX The value of the pager parameter is currently ignored.
1125 	 * XXX Presumably, this API changed to avoid the race between
1126 	 * XXX setting the pager and the UI_HASPAGER flag.
1127 	 */
1128 	pager = (void *)vnode_pager_setup(vp, uip->ui_pager);
1129 	assert(pager);
1130 
1131 	/*
1132 	 * Explicitly set the pager into the ubc_info, after setting the
1133 	 * UI_HASPAGER flag.
1134 	 */
1135 	SET(uip->ui_flags, UI_HASPAGER);
1136 	uip->ui_pager = pager;
1137 
1138 	/*
1139 	 * Note: We can not use VNOP_GETATTR() to get accurate
1140 	 * value of ui_size because this may be an NFS vnode, and
1141 	 * nfs_getattr() can call vinvalbuf(); if this happens,
1142 	 * ubc_info is not set up to deal with that event.
1143 	 * So use bogus size.
1144 	 */
1145 
1146 	/*
1147 	 * create a vnode - vm_object association
1148 	 * memory_object_create_named() creates a "named" reference on the
1149 	 * memory object we hold this reference as long as the vnode is
1150 	 * "alive."  Since memory_object_create_named() took its own reference
1151 	 * on the vnode pager we passed it, we can drop the reference
1152 	 * vnode_pager_setup() returned here.
1153 	 */
1154 	kret = memory_object_create_named(pager,
1155 	    (memory_object_size_t)uip->ui_size, &control);
1156 	vnode_pager_deallocate(pager);
1157 	if (kret != KERN_SUCCESS) {
1158 		panic("ubc_info_init: memory_object_create_named returned %d", kret);
1159 	}
1160 
1161 	assert(control);
1162 	uip->ui_control = control;      /* cache the value of the mo control */
1163 	SET(uip->ui_flags, UI_HASOBJREF);       /* with a named reference */
1164 
1165 	if (withfsize == 0) {
1166 		/* initialize the size */
1167 		error = vnode_size(vp, &uip->ui_size, vfs_context_current());
1168 		if (error) {
1169 			uip->ui_size = 0;
1170 		}
1171 	} else {
1172 		uip->ui_size = filesize;
1173 	}
1174 	vp->v_lflag |= VNAMED_UBC;      /* vnode has a named ubc reference */
1175 
1176 	return error;
1177 }
1178 
1179 
1180 /*
1181  * ubc_info_free
1182  *
1183  * Free a ubc_info structure
1184  *
1185  * Parameters:	uip			A pointer to the ubc_info to free
1186  *
1187  * Returns:	(void)
1188  *
1189  * Notes:	If there is a credential that has subsequently been associated
1190  *		with the ubc_info, the reference to the credential is dropped.
1191  *
1192  *		It's actually impossible for a ubc_info.ui_control to take the
1193  *		value MEMORY_OBJECT_CONTROL_NULL.
1194  */
1195 static void
ubc_info_free(struct ubc_info * uip)1196 ubc_info_free(struct ubc_info *uip)
1197 {
1198 	if (IS_VALID_CRED(uip->ui_ucred)) {
1199 		kauth_cred_unref(&uip->ui_ucred);
1200 	}
1201 
1202 	if (uip->ui_control != MEMORY_OBJECT_CONTROL_NULL) {
1203 		memory_object_control_deallocate(uip->ui_control);
1204 	}
1205 
1206 	cluster_release(uip);
1207 	ubc_cs_free(uip);
1208 
1209 	zfree(ubc_info_zone, uip);
1210 	return;
1211 }
1212 
1213 
1214 void
ubc_info_deallocate(struct ubc_info * uip)1215 ubc_info_deallocate(struct ubc_info *uip)
1216 {
1217 	ubc_info_free(uip);
1218 }
1219 
1220 /*
1221  * ubc_setsize_ex
1222  *
1223  * Tell the VM that the the size of the file represented by the vnode has
1224  * changed
1225  *
1226  * Parameters:	vp	   The vp whose backing file size is
1227  *					   being changed
1228  *				nsize  The new size of the backing file
1229  *				opts   Options
1230  *
1231  * Returns:	EINVAL for new size < 0
1232  *			ENOENT if no UBC info exists
1233  *          EAGAIN if UBC_SETSIZE_NO_FS_REENTRY option is set and new_size < old size
1234  *          Other errors (mapped to errno_t) returned by VM functions
1235  *
1236  * Notes:   This function will indicate success if the new size is the
1237  *		    same or larger than the old size (in this case, the
1238  *		    remainder of the file will require modification or use of
1239  *		    an existing upl to access successfully).
1240  *
1241  *		    This function will fail if the new file size is smaller,
1242  *		    and the memory region being invalidated was unable to
1243  *		    actually be invalidated and/or the last page could not be
1244  *		    flushed, if the new size is not aligned to a page
1245  *		    boundary.  This is usually indicative of an I/O error.
1246  */
1247 errno_t
ubc_setsize_ex(struct vnode * vp,off_t nsize,ubc_setsize_opts_t opts)1248 ubc_setsize_ex(struct vnode *vp, off_t nsize, ubc_setsize_opts_t opts)
1249 {
1250 	off_t osize;    /* ui_size before change */
1251 	off_t lastpg, olastpgend, lastoff;
1252 	struct ubc_info *uip;
1253 	memory_object_control_t control;
1254 	kern_return_t kret = KERN_SUCCESS;
1255 
1256 	if (nsize < (off_t)0) {
1257 		return EINVAL;
1258 	}
1259 
1260 	if (!UBCINFOEXISTS(vp)) {
1261 		return ENOENT;
1262 	}
1263 
1264 	uip = vp->v_ubcinfo;
1265 	osize = uip->ui_size;
1266 
1267 	if (ISSET(opts, UBC_SETSIZE_NO_FS_REENTRY) && nsize < osize) {
1268 		return EAGAIN;
1269 	}
1270 
1271 	/*
1272 	 * Update the size before flushing the VM
1273 	 */
1274 	uip->ui_size = nsize;
1275 
1276 	if (nsize >= osize) {   /* Nothing more to do */
1277 		if (nsize > osize) {
1278 			lock_vnode_and_post(vp, NOTE_EXTEND);
1279 		}
1280 
1281 		return 0;
1282 	}
1283 
1284 	/*
1285 	 * When the file shrinks, invalidate the pages beyond the
1286 	 * new size. Also get rid of garbage beyond nsize on the
1287 	 * last page. The ui_size already has the nsize, so any
1288 	 * subsequent page-in will zero-fill the tail properly
1289 	 */
1290 	lastpg = trunc_page_64(nsize);
1291 	olastpgend = round_page_64(osize);
1292 	control = uip->ui_control;
1293 	assert(control);
1294 	lastoff = (nsize & PAGE_MASK_64);
1295 
1296 	if (lastoff) {
1297 		upl_t           upl;
1298 		upl_page_info_t *pl;
1299 
1300 		/*
1301 		 * new EOF ends up in the middle of a page
1302 		 * zero the tail of this page if it's currently
1303 		 * present in the cache
1304 		 */
1305 		kret = ubc_create_upl_kernel(vp, lastpg, PAGE_SIZE, &upl, &pl, UPL_SET_LITE | UPL_WILL_MODIFY, VM_KERN_MEMORY_FILE);
1306 
1307 		if (kret != KERN_SUCCESS) {
1308 			panic("ubc_setsize: ubc_create_upl (error = %d)", kret);
1309 		}
1310 
1311 		if (upl_valid_page(pl, 0)) {
1312 			cluster_zero(upl, (uint32_t)lastoff, PAGE_SIZE - (uint32_t)lastoff, NULL);
1313 		}
1314 
1315 		ubc_upl_abort_range(upl, 0, PAGE_SIZE, UPL_ABORT_FREE_ON_EMPTY);
1316 
1317 		lastpg += PAGE_SIZE_64;
1318 	}
1319 	if (olastpgend > lastpg) {
1320 		int     flags;
1321 
1322 		if (lastpg == 0) {
1323 			flags = MEMORY_OBJECT_DATA_FLUSH_ALL;
1324 		} else {
1325 			flags = MEMORY_OBJECT_DATA_FLUSH;
1326 		}
1327 		/*
1328 		 * invalidate the pages beyond the new EOF page
1329 		 *
1330 		 */
1331 		kret = memory_object_lock_request(control,
1332 		    (memory_object_offset_t)lastpg,
1333 		    (memory_object_size_t)(olastpgend - lastpg), NULL, NULL,
1334 		    MEMORY_OBJECT_RETURN_NONE, flags, VM_PROT_NO_CHANGE);
1335 		if (kret != KERN_SUCCESS) {
1336 			printf("ubc_setsize: invalidate failed (error = %d)\n", kret);
1337 		}
1338 	}
1339 	return mach_to_bsd_errno(kret);
1340 }
1341 
1342 // Returns true for success
1343 int
ubc_setsize(vnode_t vp,off_t nsize)1344 ubc_setsize(vnode_t vp, off_t nsize)
1345 {
1346 	return ubc_setsize_ex(vp, nsize, 0) == 0;
1347 }
1348 
1349 /*
1350  * ubc_getsize
1351  *
1352  * Get the size of the file assocated with the specified vnode
1353  *
1354  * Parameters:	vp			The vnode whose size is of interest
1355  *
1356  * Returns:	0			There is no ubc_info associated with
1357  *					this vnode, or the size is zero
1358  *		!0			The size of the file
1359  *
1360  * Notes:	Using this routine, it is not possible for a caller to
1361  *		successfully distinguish between a vnode associate with a zero
1362  *		length file, and a vnode with no associated ubc_info.  The
1363  *		caller therefore needs to not care, or needs to ensure that
1364  *		they have previously successfully called ubc_info_init() or
1365  *		ubc_info_init_withsize().
1366  */
1367 off_t
ubc_getsize(struct vnode * vp)1368 ubc_getsize(struct vnode *vp)
1369 {
1370 	/* people depend on the side effect of this working this way
1371 	 * as they call this for directory
1372 	 */
1373 	if (!UBCINFOEXISTS(vp)) {
1374 		return (off_t)0;
1375 	}
1376 	return vp->v_ubcinfo->ui_size;
1377 }
1378 
1379 
1380 /*
1381  * ubc_umount
1382  *
1383  * Call ubc_msync(vp, 0, EOF, NULL, UBC_PUSHALL) on all the vnodes for this
1384  * mount point
1385  *
1386  * Parameters:	mp			The mount point
1387  *
1388  * Returns:	0			Success
1389  *
1390  * Notes:	There is no failure indication for this function.
1391  *
1392  *		This function is used in the unmount path; since it may block
1393  *		I/O indefinitely, it should not be used in the forced unmount
1394  *		path, since a device unavailability could also block that
1395  *		indefinitely.
1396  *
1397  *		Because there is no device ejection interlock on USB, FireWire,
1398  *		or similar devices, it's possible that an ejection that begins
1399  *		subsequent to the vnode_iterate() completing, either on one of
1400  *		those devices, or a network mount for which the server quits
1401  *		responding, etc., may cause the caller to block indefinitely.
1402  */
1403 __private_extern__ int
ubc_umount(struct mount * mp)1404 ubc_umount(struct mount *mp)
1405 {
1406 	vnode_iterate(mp, 0, ubc_umcallback, 0);
1407 	return 0;
1408 }
1409 
1410 
1411 /*
1412  * ubc_umcallback
1413  *
1414  * Used by ubc_umount() as an internal implementation detail; see ubc_umount()
1415  * and vnode_iterate() for details of implementation.
1416  */
1417 static int
ubc_umcallback(vnode_t vp,__unused void * args)1418 ubc_umcallback(vnode_t vp, __unused void * args)
1419 {
1420 	if (UBCINFOEXISTS(vp)) {
1421 		(void) ubc_msync(vp, (off_t)0, ubc_getsize(vp), NULL, UBC_PUSHALL);
1422 	}
1423 	return VNODE_RETURNED;
1424 }
1425 
1426 
1427 /*
1428  * ubc_getcred
1429  *
1430  * Get the credentials currently active for the ubc_info associated with the
1431  * vnode.
1432  *
1433  * Parameters:	vp			The vnode whose ubc_info credentials
1434  *					are to be retrieved
1435  *
1436  * Returns:	!NOCRED			The credentials
1437  *		NOCRED			If there is no ubc_info for the vnode,
1438  *					or if there is one, but it has not had
1439  *					any credentials associated with it.
1440  */
1441 kauth_cred_t
ubc_getcred(struct vnode * vp)1442 ubc_getcred(struct vnode *vp)
1443 {
1444 	if (UBCINFOEXISTS(vp)) {
1445 		return vp->v_ubcinfo->ui_ucred;
1446 	}
1447 
1448 	return NOCRED;
1449 }
1450 
1451 
1452 /*
1453  * ubc_setthreadcred
1454  *
1455  * If they are not already set, set the credentials of the ubc_info structure
1456  * associated with the vnode to those of the supplied thread; otherwise leave
1457  * them alone.
1458  *
1459  * Parameters:	vp			The vnode whose ubc_info creds are to
1460  *					be set
1461  *		p			The process whose credentials are to
1462  *					be used, if not running on an assumed
1463  *					credential
1464  *		thread			The thread whose credentials are to
1465  *					be used
1466  *
1467  * Returns:	1			This vnode has no associated ubc_info
1468  *		0			Success
1469  *
1470  * Notes:	This function is generally used only in the following cases:
1471  *
1472  *		o	a memory mapped file via the mmap() system call
1473  *		o	a swap store backing file
1474  *		o	subsequent to a successful write via vn_write()
1475  *
1476  *		The information is then used by the NFS client in order to
1477  *		cons up a wire message in either the page-in or page-out path.
1478  *
1479  *		There are two potential problems with the use of this API:
1480  *
1481  *		o	Because the write path only set it on a successful
1482  *			write, there is a race window between setting the
1483  *			credential and its use to evict the pages to the
1484  *			remote file server
1485  *
1486  *		o	Because a page-in may occur prior to a write, the
1487  *			credential may not be set at this time, if the page-in
1488  *			is not the result of a mapping established via mmap().
1489  *
1490  *		In both these cases, this will be triggered from the paging
1491  *		path, which will instead use the credential of the current
1492  *		process, which in this case is either the dynamic_pager or
1493  *		the kernel task, both of which utilize "root" credentials.
1494  *
1495  *		This may potentially permit operations to occur which should
1496  *		be denied, or it may cause to be denied operations which
1497  *		should be permitted, depending on the configuration of the NFS
1498  *		server.
1499  */
1500 int
ubc_setthreadcred(struct vnode * vp,proc_t p,thread_t thread)1501 ubc_setthreadcred(struct vnode *vp, proc_t p, thread_t thread)
1502 {
1503 #pragma unused(p, thread)
1504 	assert(p == current_proc());
1505 	assert(thread == current_thread());
1506 
1507 	return ubc_setcred(vp, kauth_cred_get());
1508 }
1509 
1510 
1511 /*
1512  * ubc_setcred
1513  *
1514  * If they are not already set, set the credentials of the ubc_info structure
1515  * associated with the vnode to those specified; otherwise leave them
1516  * alone.
1517  *
1518  * Parameters:	vp			The vnode whose ubc_info creds are to
1519  *					be set
1520  *		ucred			The credentials to use
1521  *
1522  * Returns:	0			This vnode has no associated ubc_info
1523  *		1			Success
1524  *
1525  * Notes:	The return values for this function are inverted from nearly
1526  *		all other uses in the kernel.
1527  *
1528  *		See also ubc_setthreadcred(), above.
1529  */
1530 int
ubc_setcred(struct vnode * vp,kauth_cred_t ucred)1531 ubc_setcred(struct vnode *vp, kauth_cred_t ucred)
1532 {
1533 	struct ubc_info *uip;
1534 
1535 	/* If there is no ubc_info, deny the operation */
1536 	if (!UBCINFOEXISTS(vp)) {
1537 		return 0;
1538 	}
1539 
1540 	/*
1541 	 * Check to see if there is already a credential reference in the
1542 	 * ubc_info; if there is not, take one on the supplied credential.
1543 	 */
1544 	vnode_lock(vp);
1545 	uip = vp->v_ubcinfo;
1546 	if (!IS_VALID_CRED(uip->ui_ucred)) {
1547 		kauth_cred_ref(ucred);
1548 		uip->ui_ucred = ucred;
1549 	}
1550 	vnode_unlock(vp);
1551 
1552 	return 1;
1553 }
1554 
1555 /*
1556  * ubc_getpager
1557  *
1558  * Get the pager associated with the ubc_info associated with the vnode.
1559  *
1560  * Parameters:	vp			The vnode to obtain the pager from
1561  *
1562  * Returns:	!VNODE_PAGER_NULL	The memory_object_t for the pager
1563  *		VNODE_PAGER_NULL	There is no ubc_info for this vnode
1564  *
1565  * Notes:	For each vnode that has a ubc_info associated with it, that
1566  *		ubc_info SHALL have a pager associated with it, so in the
1567  *		normal case, it's impossible to return VNODE_PAGER_NULL for
1568  *		a vnode with an associated ubc_info.
1569  */
1570 __private_extern__ memory_object_t
ubc_getpager(struct vnode * vp)1571 ubc_getpager(struct vnode *vp)
1572 {
1573 	if (UBCINFOEXISTS(vp)) {
1574 		return vp->v_ubcinfo->ui_pager;
1575 	}
1576 
1577 	return 0;
1578 }
1579 
1580 
1581 /*
1582  * ubc_getobject
1583  *
1584  * Get the memory object control associated with the ubc_info associated with
1585  * the vnode
1586  *
1587  * Parameters:	vp			The vnode to obtain the memory object
1588  *					from
1589  *		flags			DEPRECATED
1590  *
1591  * Returns:	!MEMORY_OBJECT_CONTROL_NULL
1592  *		MEMORY_OBJECT_CONTROL_NULL
1593  *
1594  * Notes:	Historically, if the flags were not "do not reactivate", this
1595  *		function would look up the memory object using the pager if
1596  *		it did not exist (this could be the case if the vnode had
1597  *		been previously reactivated).  The flags would also permit a
1598  *		hold to be requested, which would have created an object
1599  *		reference, if one had not already existed.  This usage is
1600  *		deprecated, as it would permit a race between finding and
1601  *		taking the reference vs. a single reference being dropped in
1602  *		another thread.
1603  */
1604 memory_object_control_t
ubc_getobject(struct vnode * vp,__unused int flags)1605 ubc_getobject(struct vnode *vp, __unused int flags)
1606 {
1607 	if (UBCINFOEXISTS(vp)) {
1608 		return vp->v_ubcinfo->ui_control;
1609 	}
1610 
1611 	return MEMORY_OBJECT_CONTROL_NULL;
1612 }
1613 
1614 /*
1615  * ubc_blktooff
1616  *
1617  * Convert a given block number to a memory backing object (file) offset for a
1618  * given vnode
1619  *
1620  * Parameters:	vp			The vnode in which the block is located
1621  *		blkno			The block number to convert
1622  *
1623  * Returns:	!-1			The offset into the backing object
1624  *		-1			There is no ubc_info associated with
1625  *					the vnode
1626  *		-1			An error occurred in the underlying VFS
1627  *					while translating the block to an
1628  *					offset; the most likely cause is that
1629  *					the caller specified a block past the
1630  *					end of the file, but this could also be
1631  *					any other error from VNOP_BLKTOOFF().
1632  *
1633  * Note:	Representing the error in band loses some information, but does
1634  *		not occlude a valid offset, since an off_t of -1 is normally
1635  *		used to represent EOF.  If we had a more reliable constant in
1636  *		our header files for it (i.e. explicitly cast to an off_t), we
1637  *		would use it here instead.
1638  */
1639 off_t
ubc_blktooff(vnode_t vp,daddr64_t blkno)1640 ubc_blktooff(vnode_t vp, daddr64_t blkno)
1641 {
1642 	off_t file_offset = -1;
1643 	int error;
1644 
1645 	if (UBCINFOEXISTS(vp)) {
1646 		error = VNOP_BLKTOOFF(vp, blkno, &file_offset);
1647 		if (error) {
1648 			file_offset = -1;
1649 		}
1650 	}
1651 
1652 	return file_offset;
1653 }
1654 
1655 
1656 /*
1657  * ubc_offtoblk
1658  *
1659  * Convert a given offset in a memory backing object into a block number for a
1660  * given vnode
1661  *
1662  * Parameters:	vp			The vnode in which the offset is
1663  *					located
1664  *		offset			The offset into the backing object
1665  *
1666  * Returns:	!-1			The returned block number
1667  *		-1			There is no ubc_info associated with
1668  *					the vnode
1669  *		-1			An error occurred in the underlying VFS
1670  *					while translating the block to an
1671  *					offset; the most likely cause is that
1672  *					the caller specified a block past the
1673  *					end of the file, but this could also be
1674  *					any other error from VNOP_OFFTOBLK().
1675  *
1676  * Note:	Representing the error in band loses some information, but does
1677  *		not occlude a valid block number, since block numbers exceed
1678  *		the valid range for offsets, due to their relative sizes.  If
1679  *		we had a more reliable constant than -1 in our header files
1680  *		for it (i.e. explicitly cast to an daddr64_t), we would use it
1681  *		here instead.
1682  */
1683 daddr64_t
ubc_offtoblk(vnode_t vp,off_t offset)1684 ubc_offtoblk(vnode_t vp, off_t offset)
1685 {
1686 	daddr64_t blkno = -1;
1687 	int error = 0;
1688 
1689 	if (UBCINFOEXISTS(vp)) {
1690 		error = VNOP_OFFTOBLK(vp, offset, &blkno);
1691 		if (error) {
1692 			blkno = -1;
1693 		}
1694 	}
1695 
1696 	return blkno;
1697 }
1698 
1699 
1700 /*
1701  * ubc_pages_resident
1702  *
1703  * Determine whether or not a given vnode has pages resident via the memory
1704  * object control associated with the ubc_info associated with the vnode
1705  *
1706  * Parameters:	vp			The vnode we want to know about
1707  *
1708  * Returns:	1			Yes
1709  *		0			No
1710  */
1711 int
ubc_pages_resident(vnode_t vp)1712 ubc_pages_resident(vnode_t vp)
1713 {
1714 	kern_return_t           kret;
1715 	boolean_t                       has_pages_resident;
1716 
1717 	if (!UBCINFOEXISTS(vp)) {
1718 		return 0;
1719 	}
1720 
1721 	/*
1722 	 * The following call may fail if an invalid ui_control is specified,
1723 	 * or if there is no VM object associated with the control object.  In
1724 	 * either case, reacting to it as if there were no pages resident will
1725 	 * result in correct behavior.
1726 	 */
1727 	kret = memory_object_pages_resident(vp->v_ubcinfo->ui_control, &has_pages_resident);
1728 
1729 	if (kret != KERN_SUCCESS) {
1730 		return 0;
1731 	}
1732 
1733 	if (has_pages_resident == TRUE) {
1734 		return 1;
1735 	}
1736 
1737 	return 0;
1738 }
1739 
1740 /*
1741  * ubc_msync
1742  *
1743  * Clean and/or invalidate a range in the memory object that backs this vnode
1744  *
1745  * Parameters:	vp			The vnode whose associated ubc_info's
1746  *					associated memory object is to have a
1747  *					range invalidated within it
1748  *		beg_off			The start of the range, as an offset
1749  *		end_off			The end of the range, as an offset
1750  *		resid_off		The address of an off_t supplied by the
1751  *					caller; may be set to NULL to ignore
1752  *		flags			See ubc_msync_internal()
1753  *
1754  * Returns:	0			Success
1755  *		!0			Failure; an errno is returned
1756  *
1757  * Implicit Returns:
1758  *		*resid_off, modified	If non-NULL, the  contents are ALWAYS
1759  *					modified; they are initialized to the
1760  *					beg_off, and in case of an I/O error,
1761  *					the difference between beg_off and the
1762  *					current value will reflect what was
1763  *					able to be written before the error
1764  *					occurred.  If no error is returned, the
1765  *					value of the resid_off is undefined; do
1766  *					NOT use it in place of end_off if you
1767  *					intend to increment from the end of the
1768  *					last call and call iteratively.
1769  *
1770  * Notes:	see ubc_msync_internal() for more detailed information.
1771  *
1772  */
1773 errno_t
ubc_msync(vnode_t vp,off_t beg_off,off_t end_off,off_t * resid_off,int flags)1774 ubc_msync(vnode_t vp, off_t beg_off, off_t end_off, off_t *resid_off, int flags)
1775 {
1776 	int retval;
1777 	int io_errno = 0;
1778 
1779 	if (resid_off) {
1780 		*resid_off = beg_off;
1781 	}
1782 
1783 	retval = ubc_msync_internal(vp, beg_off, end_off, resid_off, flags, &io_errno);
1784 
1785 	if (retval == 0 && io_errno == 0) {
1786 		return EINVAL;
1787 	}
1788 	return io_errno;
1789 }
1790 
1791 
1792 /*
1793  * ubc_msync_internal
1794  *
1795  * Clean and/or invalidate a range in the memory object that backs this vnode
1796  *
1797  * Parameters:	vp			The vnode whose associated ubc_info's
1798  *					associated memory object is to have a
1799  *					range invalidated within it
1800  *		beg_off			The start of the range, as an offset
1801  *		end_off			The end of the range, as an offset
1802  *		resid_off		The address of an off_t supplied by the
1803  *					caller; may be set to NULL to ignore
1804  *		flags			MUST contain at least one of the flags
1805  *					UBC_INVALIDATE, UBC_PUSHDIRTY, or
1806  *					UBC_PUSHALL; if UBC_PUSHDIRTY is used,
1807  *					UBC_SYNC may also be specified to cause
1808  *					this function to block until the
1809  *					operation is complete.  The behavior
1810  *					of UBC_SYNC is otherwise undefined.
1811  *		io_errno		The address of an int to contain the
1812  *					errno from a failed I/O operation, if
1813  *					one occurs; may be set to NULL to
1814  *					ignore
1815  *
1816  * Returns:	1			Success
1817  *		0			Failure
1818  *
1819  * Implicit Returns:
1820  *		*resid_off, modified	The contents of this offset MAY be
1821  *					modified; in case of an I/O error, the
1822  *					difference between beg_off and the
1823  *					current value will reflect what was
1824  *					able to be written before the error
1825  *					occurred.
1826  *		*io_errno, modified	The contents of this offset are set to
1827  *					an errno, if an error occurs; if the
1828  *					caller supplies an io_errno parameter,
1829  *					they should be careful to initialize it
1830  *					to 0 before calling this function to
1831  *					enable them to distinguish an error
1832  *					with a valid *resid_off from an invalid
1833  *					one, and to avoid potentially falsely
1834  *					reporting an error, depending on use.
1835  *
1836  * Notes:	If there is no ubc_info associated with the vnode supplied,
1837  *		this function immediately returns success.
1838  *
1839  *		If the value of end_off is less than or equal to beg_off, this
1840  *		function immediately returns success; that is, end_off is NOT
1841  *		inclusive.
1842  *
1843  *		IMPORTANT: one of the flags UBC_INVALIDATE, UBC_PUSHDIRTY, or
1844  *		UBC_PUSHALL MUST be specified; that is, it is NOT possible to
1845  *		attempt to block on in-progress I/O by calling this function
1846  *		with UBC_PUSHDIRTY, and then later call it with just UBC_SYNC
1847  *		in order to block pending on the I/O already in progress.
1848  *
1849  *		The start offset is truncated to the page boundary and the
1850  *		size is adjusted to include the last page in the range; that
1851  *		is, end_off on exactly a page boundary will not change if it
1852  *		is rounded, and the range of bytes written will be from the
1853  *		truncate beg_off to the rounded (end_off - 1).
1854  */
1855 static int
ubc_msync_internal(vnode_t vp,off_t beg_off,off_t end_off,off_t * resid_off,int flags,int * io_errno)1856 ubc_msync_internal(vnode_t vp, off_t beg_off, off_t end_off, off_t *resid_off, int flags, int *io_errno)
1857 {
1858 	memory_object_size_t    tsize;
1859 	kern_return_t           kret;
1860 	int request_flags = 0;
1861 	int flush_flags   = MEMORY_OBJECT_RETURN_NONE;
1862 
1863 	if (!UBCINFOEXISTS(vp)) {
1864 		return 0;
1865 	}
1866 	if ((flags & (UBC_INVALIDATE | UBC_PUSHDIRTY | UBC_PUSHALL)) == 0) {
1867 		return 0;
1868 	}
1869 	if (end_off <= beg_off) {
1870 		return 1;
1871 	}
1872 
1873 	if (flags & UBC_INVALIDATE) {
1874 		/*
1875 		 * discard the resident pages
1876 		 */
1877 		request_flags = (MEMORY_OBJECT_DATA_FLUSH | MEMORY_OBJECT_DATA_NO_CHANGE);
1878 	}
1879 
1880 	if (flags & UBC_SYNC) {
1881 		/*
1882 		 * wait for all the I/O to complete before returning
1883 		 */
1884 		request_flags |= MEMORY_OBJECT_IO_SYNC;
1885 	}
1886 
1887 	if (flags & UBC_PUSHDIRTY) {
1888 		/*
1889 		 * we only return the dirty pages in the range
1890 		 */
1891 		flush_flags = MEMORY_OBJECT_RETURN_DIRTY;
1892 	}
1893 
1894 	if (flags & UBC_PUSHALL) {
1895 		/*
1896 		 * then return all the interesting pages in the range (both
1897 		 * dirty and precious) to the pager
1898 		 */
1899 		flush_flags = MEMORY_OBJECT_RETURN_ALL;
1900 	}
1901 
1902 	beg_off = trunc_page_64(beg_off);
1903 	end_off = round_page_64(end_off);
1904 	tsize   = (memory_object_size_t)end_off - beg_off;
1905 
1906 	/* flush and/or invalidate pages in the range requested */
1907 	kret = memory_object_lock_request(vp->v_ubcinfo->ui_control,
1908 	    beg_off, tsize,
1909 	    (memory_object_offset_t *)resid_off,
1910 	    io_errno, flush_flags, request_flags,
1911 	    VM_PROT_NO_CHANGE);
1912 
1913 	return (kret == KERN_SUCCESS) ? 1 : 0;
1914 }
1915 
1916 
1917 /*
1918  * ubc_map
1919  *
1920  * Explicitly map a vnode that has an associate ubc_info, and add a reference
1921  * to it for the ubc system, if there isn't one already, so it will not be
1922  * recycled while it's in use, and set flags on the ubc_info to indicate that
1923  * we have done this
1924  *
1925  * Parameters:	vp			The vnode to map
1926  *		flags			The mapping flags for the vnode; this
1927  *					will be a combination of one or more of
1928  *					PROT_READ, PROT_WRITE, and PROT_EXEC
1929  *
1930  * Returns:	0			Success
1931  *		EPERM			Permission was denied
1932  *
1933  * Notes:	An I/O reference on the vnode must already be held on entry
1934  *
1935  *		If there is no ubc_info associated with the vnode, this function
1936  *		will return success.
1937  *
1938  *		If a permission error occurs, this function will return
1939  *		failure; all other failures will cause this function to return
1940  *		success.
1941  *
1942  *		IMPORTANT: This is an internal use function, and its symbols
1943  *		are not exported, hence its error checking is not very robust.
1944  *		It is primarily used by:
1945  *
1946  *		o	mmap(), when mapping a file
1947  *		o	When mapping a shared file (a shared library in the
1948  *			shared segment region)
1949  *		o	When loading a program image during the exec process
1950  *
1951  *		...all of these uses ignore the return code, and any fault that
1952  *		results later because of a failure is handled in the fix-up path
1953  *		of the fault handler.  The interface exists primarily as a
1954  *		performance hint.
1955  *
1956  *		Given that third party implementation of the type of interfaces
1957  *		that would use this function, such as alternative executable
1958  *		formats, etc., are unsupported, this function is not exported
1959  *		for general use.
1960  *
1961  *		The extra reference is held until the VM system unmaps the
1962  *		vnode from its own context to maintain a vnode reference in
1963  *		cases like open()/mmap()/close(), which leave the backing
1964  *		object referenced by a mapped memory region in a process
1965  *		address space.
1966  */
1967 __private_extern__ int
ubc_map(vnode_t vp,int flags)1968 ubc_map(vnode_t vp, int flags)
1969 {
1970 	struct ubc_info *uip;
1971 	int error = 0;
1972 	int need_ref = 0;
1973 	int need_wakeup = 0;
1974 
1975 	if (UBCINFOEXISTS(vp)) {
1976 		vnode_lock(vp);
1977 		uip = vp->v_ubcinfo;
1978 
1979 		while (ISSET(uip->ui_flags, UI_MAPBUSY)) {
1980 			SET(uip->ui_flags, UI_MAPWAITING);
1981 			(void) msleep(&uip->ui_flags, &vp->v_lock,
1982 			    PRIBIO, "ubc_map", NULL);
1983 		}
1984 		SET(uip->ui_flags, UI_MAPBUSY);
1985 		vnode_unlock(vp);
1986 
1987 		error = VNOP_MMAP(vp, flags, vfs_context_current());
1988 
1989 		/*
1990 		 * rdar://problem/22587101 required that we stop propagating
1991 		 * EPERM up the stack. Otherwise, we would have to funnel up
1992 		 * the error at all the call sites for memory_object_map().
1993 		 * The risk is in having to undo the map/object/entry state at
1994 		 * all these call sites. It would also affect more than just mmap()
1995 		 * e.g. vm_remap().
1996 		 *
1997 		 *	if (error != EPERM)
1998 		 *              error = 0;
1999 		 */
2000 
2001 		error = 0;
2002 
2003 		vnode_lock_spin(vp);
2004 
2005 		if (error == 0) {
2006 			if (!ISSET(uip->ui_flags, UI_ISMAPPED)) {
2007 				need_ref = 1;
2008 			}
2009 			SET(uip->ui_flags, (UI_WASMAPPED | UI_ISMAPPED));
2010 			if (flags & PROT_WRITE) {
2011 				SET(uip->ui_flags, (UI_WASMAPPEDWRITE | UI_MAPPEDWRITE));
2012 			}
2013 		}
2014 		CLR(uip->ui_flags, UI_MAPBUSY);
2015 
2016 		if (ISSET(uip->ui_flags, UI_MAPWAITING)) {
2017 			CLR(uip->ui_flags, UI_MAPWAITING);
2018 			need_wakeup = 1;
2019 		}
2020 		vnode_unlock(vp);
2021 
2022 		if (need_wakeup) {
2023 			wakeup(&uip->ui_flags);
2024 		}
2025 
2026 		if (need_ref) {
2027 			/*
2028 			 * Make sure we get a ref as we can't unwind from here
2029 			 */
2030 			if (vnode_ref_ext(vp, 0, VNODE_REF_FORCE)) {
2031 				panic("%s : VNODE_REF_FORCE failed", __FUNCTION__);
2032 			}
2033 			/*
2034 			 * Vnodes that are on "unreliable" media (like disk
2035 			 * images, network filesystems, 3rd-party filesystems,
2036 			 * and possibly external devices) could see their
2037 			 * contents be changed via the backing store without
2038 			 * triggering copy-on-write, so we can't fully rely
2039 			 * on copy-on-write and might have to resort to
2040 			 * copy-on-read to protect "privileged" processes and
2041 			 * prevent privilege escalation.
2042 			 *
2043 			 * The root filesystem is considered "reliable" because
2044 			 * there's not much point in trying to protect
2045 			 * ourselves from such a vulnerability and the extra
2046 			 * cost of copy-on-read (CPU time and memory pressure)
2047 			 * could result in some serious regressions.
2048 			 */
2049 			if (vp->v_mount != NULL &&
2050 			    ((vp->v_mount->mnt_flag & MNT_ROOTFS) ||
2051 			    vnode_on_reliable_media(vp))) {
2052 				/*
2053 				 * This vnode is deemed "reliable" so mark
2054 				 * its VM object as "trusted".
2055 				 */
2056 				memory_object_mark_trusted(uip->ui_control);
2057 			} else {
2058 //				printf("BUGGYCOW: %s:%d vp %p \"%s\" in mnt %p \"%s\" is untrusted\n", __FUNCTION__, __LINE__, vp, vp->v_name, vp->v_mount, vp->v_mount->mnt_vnodecovered->v_name);
2059 			}
2060 		}
2061 	}
2062 	return error;
2063 }
2064 
2065 
2066 /*
2067  * ubc_destroy_named
2068  *
2069  * Destroy the named memory object associated with the ubc_info control object
2070  * associated with the designated vnode, if there is a ubc_info associated
2071  * with the vnode, and a control object is associated with it
2072  *
2073  * Parameters:	vp			The designated vnode
2074  *
2075  * Returns:	(void)
2076  *
2077  * Notes:	This function is called on vnode termination for all vnodes,
2078  *		and must therefore not assume that there is a ubc_info that is
2079  *		associated with the vnode, nor that there is a control object
2080  *		associated with the ubc_info.
2081  *
2082  *		If all the conditions necessary are present, this function
2083  *		calls memory_object_destory(), which will in turn end up
2084  *		calling ubc_unmap() to release any vnode references that were
2085  *		established via ubc_map().
2086  *
2087  *		IMPORTANT: This is an internal use function that is used
2088  *		exclusively by the internal use function vclean().
2089  */
2090 __private_extern__ void
ubc_destroy_named(vnode_t vp)2091 ubc_destroy_named(vnode_t vp)
2092 {
2093 	memory_object_control_t control;
2094 	struct ubc_info *uip;
2095 	kern_return_t kret;
2096 
2097 	if (UBCINFOEXISTS(vp)) {
2098 		uip = vp->v_ubcinfo;
2099 
2100 		/* Terminate the memory object  */
2101 		control = ubc_getobject(vp, UBC_HOLDOBJECT);
2102 		if (control != MEMORY_OBJECT_CONTROL_NULL) {
2103 			kret = memory_object_destroy(control, 0);
2104 			if (kret != KERN_SUCCESS) {
2105 				panic("ubc_destroy_named: memory_object_destroy failed");
2106 			}
2107 		}
2108 	}
2109 }
2110 
2111 
2112 /*
2113  * ubc_isinuse
2114  *
2115  * Determine whether or not a vnode is currently in use by ubc at a level in
2116  * excess of the requested busycount
2117  *
2118  * Parameters:	vp			The vnode to check
2119  *		busycount		The threshold busy count, used to bias
2120  *					the count usually already held by the
2121  *					caller to avoid races
2122  *
2123  * Returns:	1			The vnode is in use over the threshold
2124  *		0			The vnode is not in use over the
2125  *					threshold
2126  *
2127  * Notes:	Because the vnode is only held locked while actually asking
2128  *		the use count, this function only represents a snapshot of the
2129  *		current state of the vnode.  If more accurate information is
2130  *		required, an additional busycount should be held by the caller
2131  *		and a non-zero busycount used.
2132  *
2133  *		If there is no ubc_info associated with the vnode, this
2134  *		function will report that the vnode is not in use by ubc.
2135  */
2136 int
ubc_isinuse(struct vnode * vp,int busycount)2137 ubc_isinuse(struct vnode *vp, int busycount)
2138 {
2139 	if (!UBCINFOEXISTS(vp)) {
2140 		return 0;
2141 	}
2142 	return ubc_isinuse_locked(vp, busycount, 0);
2143 }
2144 
2145 
2146 /*
2147  * ubc_isinuse_locked
2148  *
2149  * Determine whether or not a vnode is currently in use by ubc at a level in
2150  * excess of the requested busycount
2151  *
2152  * Parameters:	vp			The vnode to check
2153  *		busycount		The threshold busy count, used to bias
2154  *					the count usually already held by the
2155  *					caller to avoid races
2156  *		locked			True if the vnode is already locked by
2157  *					the caller
2158  *
2159  * Returns:	1			The vnode is in use over the threshold
2160  *		0			The vnode is not in use over the
2161  *					threshold
2162  *
2163  * Notes:	If the vnode is not locked on entry, it is locked while
2164  *		actually asking the use count.  If this is the case, this
2165  *		function only represents a snapshot of the current state of
2166  *		the vnode.  If more accurate information is required, the
2167  *		vnode lock should be held by the caller, otherwise an
2168  *		additional busycount should be held by the caller and a
2169  *		non-zero busycount used.
2170  *
2171  *		If there is no ubc_info associated with the vnode, this
2172  *		function will report that the vnode is not in use by ubc.
2173  */
2174 int
ubc_isinuse_locked(struct vnode * vp,int busycount,int locked)2175 ubc_isinuse_locked(struct vnode *vp, int busycount, int locked)
2176 {
2177 	int retval = 0;
2178 
2179 
2180 	if (!locked) {
2181 		vnode_lock_spin(vp);
2182 	}
2183 
2184 	if ((vp->v_usecount - vp->v_kusecount) > busycount) {
2185 		retval = 1;
2186 	}
2187 
2188 	if (!locked) {
2189 		vnode_unlock(vp);
2190 	}
2191 	return retval;
2192 }
2193 
2194 
2195 /*
2196  * ubc_unmap
2197  *
2198  * Reverse the effects of a ubc_map() call for a given vnode
2199  *
2200  * Parameters:	vp			vnode to unmap from ubc
2201  *
2202  * Returns:	(void)
2203  *
2204  * Notes:	This is an internal use function used by vnode_pager_unmap().
2205  *		It will attempt to obtain a reference on the supplied vnode,
2206  *		and if it can do so, and there is an associated ubc_info, and
2207  *		the flags indicate that it was mapped via ubc_map(), then the
2208  *		flag is cleared, the mapping removed, and the reference taken
2209  *		by ubc_map() is released.
2210  *
2211  *		IMPORTANT: This MUST only be called by the VM
2212  *		to prevent race conditions.
2213  */
2214 __private_extern__ void
ubc_unmap(struct vnode * vp)2215 ubc_unmap(struct vnode *vp)
2216 {
2217 	struct ubc_info *uip;
2218 	int     need_rele = 0;
2219 	int     need_wakeup = 0;
2220 
2221 	if (vnode_getwithref(vp)) {
2222 		return;
2223 	}
2224 
2225 	if (UBCINFOEXISTS(vp)) {
2226 		bool want_fsevent = false;
2227 
2228 		vnode_lock(vp);
2229 		uip = vp->v_ubcinfo;
2230 
2231 		while (ISSET(uip->ui_flags, UI_MAPBUSY)) {
2232 			SET(uip->ui_flags, UI_MAPWAITING);
2233 			(void) msleep(&uip->ui_flags, &vp->v_lock,
2234 			    PRIBIO, "ubc_unmap", NULL);
2235 		}
2236 		SET(uip->ui_flags, UI_MAPBUSY);
2237 
2238 		if (ISSET(uip->ui_flags, UI_ISMAPPED)) {
2239 			if (ISSET(uip->ui_flags, UI_MAPPEDWRITE)) {
2240 				want_fsevent = true;
2241 			}
2242 
2243 			need_rele = 1;
2244 
2245 			/*
2246 			 * We want to clear the mapped flags after we've called
2247 			 * VNOP_MNOMAP to avoid certain races and allow
2248 			 * VNOP_MNOMAP to call ubc_is_mapped_writable.
2249 			 */
2250 		}
2251 		vnode_unlock(vp);
2252 
2253 		if (need_rele) {
2254 			vfs_context_t ctx = vfs_context_current();
2255 
2256 			(void)VNOP_MNOMAP(vp, ctx);
2257 
2258 #if CONFIG_FSE
2259 			/*
2260 			 * Why do we want an fsevent here?  Normally the
2261 			 * content modified fsevent is posted when a file is
2262 			 * closed and only if it's written to via conventional
2263 			 * means.  It's perfectly legal to close a file and
2264 			 * keep your mappings and we don't currently track
2265 			 * whether it was written to via a mapping.
2266 			 * Therefore, we need to post an fsevent here if the
2267 			 * file was mapped writable.  This may result in false
2268 			 * events, i.e. we post a notification when nothing
2269 			 * has really changed.
2270 			 */
2271 			if (want_fsevent && need_fsevent(FSE_CONTENT_MODIFIED, vp)) {
2272 				add_fsevent(FSE_CONTENT_MODIFIED_NO_HLINK, ctx,
2273 				    FSE_ARG_VNODE, vp,
2274 				    FSE_ARG_DONE);
2275 			}
2276 #endif
2277 
2278 			vnode_rele(vp);
2279 		}
2280 
2281 		vnode_lock_spin(vp);
2282 
2283 		if (need_rele) {
2284 			CLR(uip->ui_flags, UI_ISMAPPED | UI_MAPPEDWRITE);
2285 		}
2286 
2287 		CLR(uip->ui_flags, UI_MAPBUSY);
2288 
2289 		if (ISSET(uip->ui_flags, UI_MAPWAITING)) {
2290 			CLR(uip->ui_flags, UI_MAPWAITING);
2291 			need_wakeup = 1;
2292 		}
2293 		vnode_unlock(vp);
2294 
2295 		if (need_wakeup) {
2296 			wakeup(&uip->ui_flags);
2297 		}
2298 	}
2299 	/*
2300 	 * the drop of the vnode ref will cleanup
2301 	 */
2302 	vnode_put(vp);
2303 }
2304 
2305 
2306 /*
2307  * ubc_page_op
2308  *
2309  * Manipulate individual page state for a vnode with an associated ubc_info
2310  * with an associated memory object control.
2311  *
2312  * Parameters:	vp			The vnode backing the page
2313  *		f_offset		A file offset interior to the page
2314  *		ops			The operations to perform, as a bitmap
2315  *					(see below for more information)
2316  *		phys_entryp		The address of a ppnum_t; may be NULL
2317  *					to ignore
2318  *		flagsp			A pointer to an int to contain flags;
2319  *					may be NULL to ignore
2320  *
2321  * Returns:	KERN_SUCCESS		Success
2322  *		KERN_INVALID_ARGUMENT	If the memory object control has no VM
2323  *					object associated
2324  *		KERN_INVALID_OBJECT	If UPL_POP_PHYSICAL and the object is
2325  *					not physically contiguous
2326  *		KERN_INVALID_OBJECT	If !UPL_POP_PHYSICAL and the object is
2327  *					physically contiguous
2328  *		KERN_FAILURE		If the page cannot be looked up
2329  *
2330  * Implicit Returns:
2331  *		*phys_entryp (modified)	If phys_entryp is non-NULL and
2332  *					UPL_POP_PHYSICAL
2333  *		*flagsp (modified)	If flagsp is non-NULL and there was
2334  *					!UPL_POP_PHYSICAL and a KERN_SUCCESS
2335  *
2336  * Notes:	For object boundaries, it is considerably more efficient to
2337  *		ensure that f_offset is in fact on a page boundary, as this
2338  *		will avoid internal use of the hash table to identify the
2339  *		page, and would therefore skip a number of early optimizations.
2340  *		Since this is a page operation anyway, the caller should try
2341  *		to pass only a page aligned offset because of this.
2342  *
2343  *		*flagsp may be modified even if this function fails.  If it is
2344  *		modified, it will contain the condition of the page before the
2345  *		requested operation was attempted; these will only include the
2346  *		bitmap flags, and not the PL_POP_PHYSICAL, UPL_POP_DUMP,
2347  *		UPL_POP_SET, or UPL_POP_CLR bits.
2348  *
2349  *		The flags field may contain a specific operation, such as
2350  *		UPL_POP_PHYSICAL or UPL_POP_DUMP:
2351  *
2352  *		o	UPL_POP_PHYSICAL	Fail if not contiguous; if
2353  *						*phys_entryp and successful, set
2354  *						*phys_entryp
2355  *		o	UPL_POP_DUMP		Dump the specified page
2356  *
2357  *		Otherwise, it is treated as a bitmap of one or more page
2358  *		operations to perform on the final memory object; allowable
2359  *		bit values are:
2360  *
2361  *		o	UPL_POP_DIRTY		The page is dirty
2362  *		o	UPL_POP_PAGEOUT		The page is paged out
2363  *		o	UPL_POP_PRECIOUS	The page is precious
2364  *		o	UPL_POP_ABSENT		The page is absent
2365  *		o	UPL_POP_BUSY		The page is busy
2366  *
2367  *		If the page status is only being queried and not modified, then
2368  *		not other bits should be specified.  However, if it is being
2369  *		modified, exactly ONE of the following bits should be set:
2370  *
2371  *		o	UPL_POP_SET		Set the current bitmap bits
2372  *		o	UPL_POP_CLR		Clear the current bitmap bits
2373  *
2374  *		Thus to effect a combination of setting an clearing, it may be
2375  *		necessary to call this function twice.  If this is done, the
2376  *		set should be used before the clear, since clearing may trigger
2377  *		a wakeup on the destination page, and if the page is backed by
2378  *		an encrypted swap file, setting will trigger the decryption
2379  *		needed before the wakeup occurs.
2380  */
2381 kern_return_t
ubc_page_op(struct vnode * vp,off_t f_offset,int ops,ppnum_t * phys_entryp,int * flagsp)2382 ubc_page_op(
2383 	struct vnode    *vp,
2384 	off_t           f_offset,
2385 	int             ops,
2386 	ppnum_t *phys_entryp,
2387 	int             *flagsp)
2388 {
2389 	memory_object_control_t         control;
2390 
2391 	control = ubc_getobject(vp, UBC_FLAGS_NONE);
2392 	if (control == MEMORY_OBJECT_CONTROL_NULL) {
2393 		return KERN_INVALID_ARGUMENT;
2394 	}
2395 
2396 	return memory_object_page_op(control,
2397 	           (memory_object_offset_t)f_offset,
2398 	           ops,
2399 	           phys_entryp,
2400 	           flagsp);
2401 }
2402 
2403 
2404 /*
2405  * ubc_range_op
2406  *
2407  * Manipulate page state for a range of memory for a vnode with an associated
2408  * ubc_info with an associated memory object control, when page level state is
2409  * not required to be returned from the call (i.e. there are no phys_entryp or
2410  * flagsp parameters to this call, and it takes a range which may contain
2411  * multiple pages, rather than an offset interior to a single page).
2412  *
2413  * Parameters:	vp			The vnode backing the page
2414  *		f_offset_beg		A file offset interior to the start page
2415  *		f_offset_end		A file offset interior to the end page
2416  *		ops			The operations to perform, as a bitmap
2417  *					(see below for more information)
2418  *		range			The address of an int; may be NULL to
2419  *					ignore
2420  *
2421  * Returns:	KERN_SUCCESS		Success
2422  *		KERN_INVALID_ARGUMENT	If the memory object control has no VM
2423  *					object associated
2424  *		KERN_INVALID_OBJECT	If the object is physically contiguous
2425  *
2426  * Implicit Returns:
2427  *		*range (modified)	If range is non-NULL, its contents will
2428  *					be modified to contain the number of
2429  *					bytes successfully operated upon.
2430  *
2431  * Notes:	IMPORTANT: This function cannot be used on a range that
2432  *		consists of physically contiguous pages.
2433  *
2434  *		For object boundaries, it is considerably more efficient to
2435  *		ensure that f_offset_beg and f_offset_end are in fact on page
2436  *		boundaries, as this will avoid internal use of the hash table
2437  *		to identify the page, and would therefore skip a number of
2438  *		early optimizations.  Since this is an operation on a set of
2439  *		pages anyway, the caller should try to pass only a page aligned
2440  *		offsets because of this.
2441  *
2442  *		*range will be modified only if this function succeeds.
2443  *
2444  *		The flags field MUST contain a specific operation; allowable
2445  *		values are:
2446  *
2447  *		o	UPL_ROP_ABSENT	Returns the extent of the range
2448  *					presented which is absent, starting
2449  *					with the start address presented
2450  *
2451  *		o	UPL_ROP_PRESENT	Returns the extent of the range
2452  *					presented which is present (resident),
2453  *					starting with the start address
2454  *					presented
2455  *		o	UPL_ROP_DUMP	Dump the pages which are found in the
2456  *					target object for the target range.
2457  *
2458  *		IMPORTANT: For UPL_ROP_ABSENT and UPL_ROP_PRESENT; if there are
2459  *		multiple regions in the range, only the first matching region
2460  *		is returned.
2461  */
2462 kern_return_t
ubc_range_op(struct vnode * vp,off_t f_offset_beg,off_t f_offset_end,int ops,int * range)2463 ubc_range_op(
2464 	struct vnode    *vp,
2465 	off_t           f_offset_beg,
2466 	off_t           f_offset_end,
2467 	int             ops,
2468 	int             *range)
2469 {
2470 	memory_object_control_t         control;
2471 
2472 	control = ubc_getobject(vp, UBC_FLAGS_NONE);
2473 	if (control == MEMORY_OBJECT_CONTROL_NULL) {
2474 		return KERN_INVALID_ARGUMENT;
2475 	}
2476 
2477 	return memory_object_range_op(control,
2478 	           (memory_object_offset_t)f_offset_beg,
2479 	           (memory_object_offset_t)f_offset_end,
2480 	           ops,
2481 	           range);
2482 }
2483 
2484 
2485 /*
2486  * ubc_create_upl
2487  *
2488  * Given a vnode, cause the population of a portion of the vm_object; based on
2489  * the nature of the request, the pages returned may contain valid data, or
2490  * they may be uninitialized.
2491  *
2492  * Parameters:	vp			The vnode from which to create the upl
2493  *		f_offset		The start offset into the backing store
2494  *					represented by the vnode
2495  *		bufsize			The size of the upl to create
2496  *		uplp			Pointer to the upl_t to receive the
2497  *					created upl; MUST NOT be NULL
2498  *		plp			Pointer to receive the internal page
2499  *					list for the created upl; MAY be NULL
2500  *					to ignore
2501  *
2502  * Returns:	KERN_SUCCESS		The requested upl has been created
2503  *		KERN_INVALID_ARGUMENT	The bufsize argument is not an even
2504  *					multiple of the page size
2505  *		KERN_INVALID_ARGUMENT	There is no ubc_info associated with
2506  *					the vnode, or there is no memory object
2507  *					control associated with the ubc_info
2508  *	memory_object_upl_request:KERN_INVALID_VALUE
2509  *					The supplied upl_flags argument is
2510  *					invalid
2511  * Implicit Returns:
2512  *		*uplp (modified)
2513  *		*plp (modified)		If non-NULL, the value of *plp will be
2514  *					modified to point to the internal page
2515  *					list; this modification may occur even
2516  *					if this function is unsuccessful, in
2517  *					which case the contents may be invalid
2518  *
2519  * Note:	If successful, the returned *uplp MUST subsequently be freed
2520  *		via a call to ubc_upl_commit(), ubc_upl_commit_range(),
2521  *		ubc_upl_abort(), or ubc_upl_abort_range().
2522  */
2523 kern_return_t
ubc_create_upl_external(struct vnode * vp,off_t f_offset,int bufsize,upl_t * uplp,upl_page_info_t ** plp,int uplflags)2524 ubc_create_upl_external(
2525 	struct vnode    *vp,
2526 	off_t           f_offset,
2527 	int             bufsize,
2528 	upl_t           *uplp,
2529 	upl_page_info_t **plp,
2530 	int             uplflags)
2531 {
2532 	return ubc_create_upl_kernel(vp, f_offset, bufsize, uplp, plp, uplflags, vm_tag_bt());
2533 }
2534 
2535 kern_return_t
ubc_create_upl_kernel(struct vnode * vp,off_t f_offset,int bufsize,upl_t * uplp,upl_page_info_t ** plp,int uplflags,vm_tag_t tag)2536 ubc_create_upl_kernel(
2537 	struct vnode    *vp,
2538 	off_t           f_offset,
2539 	int             bufsize,
2540 	upl_t           *uplp,
2541 	upl_page_info_t **plp,
2542 	int             uplflags,
2543 	vm_tag_t tag)
2544 {
2545 	memory_object_control_t         control;
2546 	kern_return_t                   kr;
2547 
2548 	if (plp != NULL) {
2549 		*plp = NULL;
2550 	}
2551 	*uplp = NULL;
2552 
2553 	if (bufsize & 0xfff) {
2554 		return KERN_INVALID_ARGUMENT;
2555 	}
2556 
2557 	if (bufsize > MAX_UPL_SIZE_BYTES) {
2558 		return KERN_INVALID_ARGUMENT;
2559 	}
2560 
2561 	if (uplflags & (UPL_UBC_MSYNC | UPL_UBC_PAGEOUT | UPL_UBC_PAGEIN)) {
2562 		if (uplflags & UPL_UBC_MSYNC) {
2563 			uplflags &= UPL_RET_ONLY_DIRTY;
2564 
2565 			uplflags |= UPL_COPYOUT_FROM | UPL_CLEAN_IN_PLACE |
2566 			    UPL_SET_INTERNAL | UPL_SET_LITE;
2567 		} else if (uplflags & UPL_UBC_PAGEOUT) {
2568 			uplflags &= UPL_RET_ONLY_DIRTY;
2569 
2570 			if (uplflags & UPL_RET_ONLY_DIRTY) {
2571 				uplflags |= UPL_NOBLOCK;
2572 			}
2573 
2574 			uplflags |= UPL_FOR_PAGEOUT | UPL_CLEAN_IN_PLACE |
2575 			    UPL_COPYOUT_FROM | UPL_SET_INTERNAL | UPL_SET_LITE;
2576 		} else {
2577 			uplflags |= UPL_RET_ONLY_ABSENT |
2578 			    UPL_NO_SYNC | UPL_CLEAN_IN_PLACE |
2579 			    UPL_SET_INTERNAL | UPL_SET_LITE;
2580 
2581 			/*
2582 			 * if the requested size == PAGE_SIZE, we don't want to set
2583 			 * the UPL_NOBLOCK since we may be trying to recover from a
2584 			 * previous partial pagein I/O that occurred because we were low
2585 			 * on memory and bailed early in order to honor the UPL_NOBLOCK...
2586 			 * since we're only asking for a single page, we can block w/o fear
2587 			 * of tying up pages while waiting for more to become available
2588 			 */
2589 			if (bufsize > PAGE_SIZE) {
2590 				uplflags |= UPL_NOBLOCK;
2591 			}
2592 		}
2593 	} else {
2594 		uplflags &= ~UPL_FOR_PAGEOUT;
2595 
2596 		if (uplflags & UPL_WILL_BE_DUMPED) {
2597 			uplflags &= ~UPL_WILL_BE_DUMPED;
2598 			uplflags |= (UPL_NO_SYNC | UPL_SET_INTERNAL);
2599 		} else {
2600 			uplflags |= (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_SET_INTERNAL);
2601 		}
2602 	}
2603 	control = ubc_getobject(vp, UBC_FLAGS_NONE);
2604 	if (control == MEMORY_OBJECT_CONTROL_NULL) {
2605 		return KERN_INVALID_ARGUMENT;
2606 	}
2607 
2608 	kr = memory_object_upl_request(control, f_offset, bufsize, uplp, NULL, NULL, uplflags, tag);
2609 	if (kr == KERN_SUCCESS && plp != NULL) {
2610 		*plp = UPL_GET_INTERNAL_PAGE_LIST(*uplp);
2611 	}
2612 	return kr;
2613 }
2614 
2615 
2616 /*
2617  * ubc_upl_maxbufsize
2618  *
2619  * Return the maximum bufsize ubc_create_upl( ) will take.
2620  *
2621  * Parameters:	none
2622  *
2623  * Returns:	maximum size buffer (in bytes) ubc_create_upl( ) will take.
2624  */
2625 upl_size_t
ubc_upl_maxbufsize(void)2626 ubc_upl_maxbufsize(
2627 	void)
2628 {
2629 	return MAX_UPL_SIZE_BYTES;
2630 }
2631 
2632 /*
2633  * ubc_upl_map
2634  *
2635  * Map the page list assocated with the supplied upl into the kernel virtual
2636  * address space at the virtual address indicated by the dst_addr argument;
2637  * the entire upl is mapped
2638  *
2639  * Parameters:	upl			The upl to map
2640  *		dst_addr		The address at which to map the upl
2641  *
2642  * Returns:	KERN_SUCCESS		The upl has been mapped
2643  *		KERN_INVALID_ARGUMENT	The upl is UPL_NULL
2644  *		KERN_FAILURE		The upl is already mapped
2645  *	vm_map_enter:KERN_INVALID_ARGUMENT
2646  *					A failure code from vm_map_enter() due
2647  *					to an invalid argument
2648  */
2649 kern_return_t
ubc_upl_map(upl_t upl,vm_offset_t * dst_addr)2650 ubc_upl_map(
2651 	upl_t           upl,
2652 	vm_offset_t     *dst_addr)
2653 {
2654 	return vm_upl_map(kernel_map, upl, dst_addr);
2655 }
2656 
2657 /*
2658  * ubc_upl_map_range:- similar to ubc_upl_map but the focus is on a range
2659  * of the UPL. Takes an offset, size, and protection so that only a  part
2660  * of the UPL can be mapped with the right protections.
2661  */
2662 kern_return_t
ubc_upl_map_range(upl_t upl,vm_offset_t offset_to_map,vm_size_t size_to_map,vm_prot_t prot_to_map,vm_offset_t * dst_addr)2663 ubc_upl_map_range(
2664 	upl_t           upl,
2665 	vm_offset_t     offset_to_map,
2666 	vm_size_t       size_to_map,
2667 	vm_prot_t       prot_to_map,
2668 	vm_offset_t     *dst_addr)
2669 {
2670 	return vm_upl_map_range(kernel_map, upl, offset_to_map, size_to_map, prot_to_map, dst_addr);
2671 }
2672 
2673 
2674 /*
2675  * ubc_upl_unmap
2676  *
2677  * Unmap the page list assocated with the supplied upl from the kernel virtual
2678  * address space; the entire upl is unmapped.
2679  *
2680  * Parameters:	upl			The upl to unmap
2681  *
2682  * Returns:	KERN_SUCCESS		The upl has been unmapped
2683  *		KERN_FAILURE		The upl is not currently mapped
2684  *		KERN_INVALID_ARGUMENT	If the upl is UPL_NULL
2685  */
2686 kern_return_t
ubc_upl_unmap(upl_t upl)2687 ubc_upl_unmap(
2688 	upl_t   upl)
2689 {
2690 	return vm_upl_unmap(kernel_map, upl);
2691 }
2692 
2693 /*
2694  * ubc_upl_unmap_range:- similar to ubc_upl_unmap but the focus is
2695  * on part of the UPL that is mapped. The offset and size parameter
2696  * specifies what part of the UPL needs to be unmapped.
2697  *
2698  * Note: Currrently offset & size are unused as we always initiate the unmap from the
2699  * very beginning of the UPL's mapping and track the mapped size in the UPL. But we
2700  * might want to allow unmapping a UPL in the middle, for example, and we can use the
2701  * offset + size parameters for that purpose.
2702  */
2703 kern_return_t
ubc_upl_unmap_range(upl_t upl,vm_offset_t offset_to_unmap,vm_size_t size_to_unmap)2704 ubc_upl_unmap_range(
2705 	upl_t   upl,
2706 	vm_offset_t     offset_to_unmap,
2707 	vm_size_t       size_to_unmap)
2708 {
2709 	return vm_upl_unmap_range(kernel_map, upl, offset_to_unmap, size_to_unmap);
2710 }
2711 
2712 
2713 /*
2714  * ubc_upl_commit
2715  *
2716  * Commit the contents of the upl to the backing store
2717  *
2718  * Parameters:	upl			The upl to commit
2719  *
2720  * Returns:	KERN_SUCCESS		The upl has been committed
2721  *		KERN_INVALID_ARGUMENT	The supplied upl was UPL_NULL
2722  *		KERN_FAILURE		The supplied upl does not represent
2723  *					device memory, and the offset plus the
2724  *					size would exceed the actual size of
2725  *					the upl
2726  *
2727  * Notes:	In practice, the only return value for this function should be
2728  *		KERN_SUCCESS, unless there has been data structure corruption;
2729  *		since the upl is deallocated regardless of success or failure,
2730  *		there's really nothing to do about this other than panic.
2731  *
2732  *		IMPORTANT: Use of this function should not be mixed with use of
2733  *		ubc_upl_commit_range(), due to the unconditional deallocation
2734  *		by this function.
2735  */
2736 kern_return_t
ubc_upl_commit(upl_t upl)2737 ubc_upl_commit(
2738 	upl_t                   upl)
2739 {
2740 	upl_page_info_t *pl;
2741 	kern_return_t   kr;
2742 
2743 	pl = UPL_GET_INTERNAL_PAGE_LIST(upl);
2744 	kr = upl_commit(upl, pl, MAX_UPL_SIZE_BYTES >> PAGE_SHIFT);
2745 	upl_deallocate(upl);
2746 	return kr;
2747 }
2748 
2749 
2750 /*
2751  * ubc_upl_commit
2752  *
2753  * Commit the contents of the specified range of the upl to the backing store
2754  *
2755  * Parameters:	upl			The upl to commit
2756  *		offset			The offset into the upl
2757  *		size			The size of the region to be committed,
2758  *					starting at the specified offset
2759  *		flags			commit type (see below)
2760  *
2761  * Returns:	KERN_SUCCESS		The range has been committed
2762  *		KERN_INVALID_ARGUMENT	The supplied upl was UPL_NULL
2763  *		KERN_FAILURE		The supplied upl does not represent
2764  *					device memory, and the offset plus the
2765  *					size would exceed the actual size of
2766  *					the upl
2767  *
2768  * Notes:	IMPORTANT: If the commit is successful, and the object is now
2769  *		empty, the upl will be deallocated.  Since the caller cannot
2770  *		check that this is the case, the UPL_COMMIT_FREE_ON_EMPTY flag
2771  *		should generally only be used when the offset is 0 and the size
2772  *		is equal to the upl size.
2773  *
2774  *		The flags argument is a bitmap of flags on the rage of pages in
2775  *		the upl to be committed; allowable flags are:
2776  *
2777  *		o	UPL_COMMIT_FREE_ON_EMPTY	Free the upl when it is
2778  *							both empty and has been
2779  *							successfully committed
2780  *		o	UPL_COMMIT_CLEAR_DIRTY		Clear each pages dirty
2781  *							bit; will prevent a
2782  *							later pageout
2783  *		o	UPL_COMMIT_SET_DIRTY		Set each pages dirty
2784  *							bit; will cause a later
2785  *							pageout
2786  *		o	UPL_COMMIT_INACTIVATE		Clear each pages
2787  *							reference bit; the page
2788  *							will not be accessed
2789  *		o	UPL_COMMIT_ALLOW_ACCESS		Unbusy each page; pages
2790  *							become busy when an
2791  *							IOMemoryDescriptor is
2792  *							mapped or redirected,
2793  *							and we have to wait for
2794  *							an IOKit driver
2795  *
2796  *		The flag UPL_COMMIT_NOTIFY_EMPTY is used internally, and should
2797  *		not be specified by the caller.
2798  *
2799  *		The UPL_COMMIT_CLEAR_DIRTY and UPL_COMMIT_SET_DIRTY flags are
2800  *		mutually exclusive, and should not be combined.
2801  */
2802 kern_return_t
ubc_upl_commit_range(upl_t upl,upl_offset_t offset,upl_size_t size,int flags)2803 ubc_upl_commit_range(
2804 	upl_t                   upl,
2805 	upl_offset_t            offset,
2806 	upl_size_t              size,
2807 	int                             flags)
2808 {
2809 	upl_page_info_t *pl;
2810 	boolean_t               empty;
2811 	kern_return_t   kr;
2812 
2813 	if (flags & UPL_COMMIT_FREE_ON_EMPTY) {
2814 		flags |= UPL_COMMIT_NOTIFY_EMPTY;
2815 	}
2816 
2817 	if (flags & UPL_COMMIT_KERNEL_ONLY_FLAGS) {
2818 		return KERN_INVALID_ARGUMENT;
2819 	}
2820 
2821 	pl = UPL_GET_INTERNAL_PAGE_LIST(upl);
2822 
2823 	kr = upl_commit_range(upl, offset, size, flags,
2824 	    pl, MAX_UPL_SIZE_BYTES >> PAGE_SHIFT, &empty);
2825 
2826 	if ((flags & UPL_COMMIT_FREE_ON_EMPTY) && empty) {
2827 		upl_deallocate(upl);
2828 	}
2829 
2830 	return kr;
2831 }
2832 
2833 
2834 /*
2835  * ubc_upl_abort_range
2836  *
2837  * Abort the contents of the specified range of the specified upl
2838  *
2839  * Parameters:	upl			The upl to abort
2840  *		offset			The offset into the upl
2841  *		size			The size of the region to be aborted,
2842  *					starting at the specified offset
2843  *		abort_flags		abort type (see below)
2844  *
2845  * Returns:	KERN_SUCCESS		The range has been aborted
2846  *		KERN_INVALID_ARGUMENT	The supplied upl was UPL_NULL
2847  *		KERN_FAILURE		The supplied upl does not represent
2848  *					device memory, and the offset plus the
2849  *					size would exceed the actual size of
2850  *					the upl
2851  *
2852  * Notes:	IMPORTANT: If the abort is successful, and the object is now
2853  *		empty, the upl will be deallocated.  Since the caller cannot
2854  *		check that this is the case, the UPL_ABORT_FREE_ON_EMPTY flag
2855  *		should generally only be used when the offset is 0 and the size
2856  *		is equal to the upl size.
2857  *
2858  *		The abort_flags argument is a bitmap of flags on the range of
2859  *		pages in the upl to be aborted; allowable flags are:
2860  *
2861  *		o	UPL_ABORT_FREE_ON_EMPTY	Free the upl when it is both
2862  *						empty and has been successfully
2863  *						aborted
2864  *		o	UPL_ABORT_RESTART	The operation must be restarted
2865  *		o	UPL_ABORT_UNAVAILABLE	The pages are unavailable
2866  *		o	UPL_ABORT_ERROR		An I/O error occurred
2867  *		o	UPL_ABORT_DUMP_PAGES	Just free the pages
2868  *		o	UPL_ABORT_NOTIFY_EMPTY	RESERVED
2869  *		o	UPL_ABORT_ALLOW_ACCESS	RESERVED
2870  *
2871  *		The UPL_ABORT_NOTIFY_EMPTY is an internal use flag and should
2872  *		not be specified by the caller.  It is intended to fulfill the
2873  *		same role as UPL_COMMIT_NOTIFY_EMPTY does in the function
2874  *		ubc_upl_commit_range(), but is never referenced internally.
2875  *
2876  *		The UPL_ABORT_ALLOW_ACCESS is defined, but neither set nor
2877  *		referenced; do not use it.
2878  */
2879 kern_return_t
ubc_upl_abort_range(upl_t upl,upl_offset_t offset,upl_size_t size,int abort_flags)2880 ubc_upl_abort_range(
2881 	upl_t                   upl,
2882 	upl_offset_t            offset,
2883 	upl_size_t              size,
2884 	int                             abort_flags)
2885 {
2886 	kern_return_t   kr;
2887 	boolean_t               empty = FALSE;
2888 
2889 	if (abort_flags & UPL_ABORT_FREE_ON_EMPTY) {
2890 		abort_flags |= UPL_ABORT_NOTIFY_EMPTY;
2891 	}
2892 
2893 	kr = upl_abort_range(upl, offset, size, abort_flags, &empty);
2894 
2895 	if ((abort_flags & UPL_ABORT_FREE_ON_EMPTY) && empty) {
2896 		upl_deallocate(upl);
2897 	}
2898 
2899 	return kr;
2900 }
2901 
2902 
2903 /*
2904  * ubc_upl_abort
2905  *
2906  * Abort the contents of the specified upl
2907  *
2908  * Parameters:	upl			The upl to abort
2909  *		abort_type		abort type (see below)
2910  *
2911  * Returns:	KERN_SUCCESS		The range has been aborted
2912  *		KERN_INVALID_ARGUMENT	The supplied upl was UPL_NULL
2913  *		KERN_FAILURE		The supplied upl does not represent
2914  *					device memory, and the offset plus the
2915  *					size would exceed the actual size of
2916  *					the upl
2917  *
2918  * Notes:	IMPORTANT: If the abort is successful, and the object is now
2919  *		empty, the upl will be deallocated.  Since the caller cannot
2920  *		check that this is the case, the UPL_ABORT_FREE_ON_EMPTY flag
2921  *		should generally only be used when the offset is 0 and the size
2922  *		is equal to the upl size.
2923  *
2924  *		The abort_type is a bitmap of flags on the range of
2925  *		pages in the upl to be aborted; allowable flags are:
2926  *
2927  *		o	UPL_ABORT_FREE_ON_EMPTY	Free the upl when it is both
2928  *						empty and has been successfully
2929  *						aborted
2930  *		o	UPL_ABORT_RESTART	The operation must be restarted
2931  *		o	UPL_ABORT_UNAVAILABLE	The pages are unavailable
2932  *		o	UPL_ABORT_ERROR		An I/O error occurred
2933  *		o	UPL_ABORT_DUMP_PAGES	Just free the pages
2934  *		o	UPL_ABORT_NOTIFY_EMPTY	RESERVED
2935  *		o	UPL_ABORT_ALLOW_ACCESS	RESERVED
2936  *
2937  *		The UPL_ABORT_NOTIFY_EMPTY is an internal use flag and should
2938  *		not be specified by the caller.  It is intended to fulfill the
2939  *		same role as UPL_COMMIT_NOTIFY_EMPTY does in the function
2940  *		ubc_upl_commit_range(), but is never referenced internally.
2941  *
2942  *		The UPL_ABORT_ALLOW_ACCESS is defined, but neither set nor
2943  *		referenced; do not use it.
2944  */
2945 kern_return_t
ubc_upl_abort(upl_t upl,int abort_type)2946 ubc_upl_abort(
2947 	upl_t                   upl,
2948 	int                             abort_type)
2949 {
2950 	kern_return_t   kr;
2951 
2952 	kr = upl_abort(upl, abort_type);
2953 	upl_deallocate(upl);
2954 	return kr;
2955 }
2956 
2957 
2958 /*
2959  * ubc_upl_pageinfo
2960  *
2961  *  Retrieve the internal page list for the specified upl
2962  *
2963  * Parameters:	upl			The upl to obtain the page list from
2964  *
2965  * Returns:	!NULL			The (upl_page_info_t *) for the page
2966  *					list internal to the upl
2967  *		NULL			Error/no page list associated
2968  *
2969  * Notes:	IMPORTANT: The function is only valid on internal objects
2970  *		where the list request was made with the UPL_INTERNAL flag.
2971  *
2972  *		This function is a utility helper function, since some callers
2973  *		may not have direct access to the header defining the macro,
2974  *		due to abstraction layering constraints.
2975  */
2976 upl_page_info_t *
ubc_upl_pageinfo(upl_t upl)2977 ubc_upl_pageinfo(
2978 	upl_t                   upl)
2979 {
2980 	return UPL_GET_INTERNAL_PAGE_LIST(upl);
2981 }
2982 
2983 
2984 int
UBCINFOEXISTS(const struct vnode * vp)2985 UBCINFOEXISTS(const struct vnode * vp)
2986 {
2987 	return (vp) && ((vp)->v_type == VREG) && ((vp)->v_ubcinfo != UBC_INFO_NULL);
2988 }
2989 
2990 
2991 void
ubc_upl_range_needed(upl_t upl,int index,int count)2992 ubc_upl_range_needed(
2993 	upl_t           upl,
2994 	int             index,
2995 	int             count)
2996 {
2997 	upl_range_needed(upl, index, count);
2998 }
2999 
3000 boolean_t
ubc_is_mapped(const struct vnode * vp,boolean_t * writable)3001 ubc_is_mapped(const struct vnode *vp, boolean_t *writable)
3002 {
3003 	if (!UBCINFOEXISTS(vp) || !ISSET(vp->v_ubcinfo->ui_flags, UI_ISMAPPED)) {
3004 		return FALSE;
3005 	}
3006 	if (writable) {
3007 		*writable = ISSET(vp->v_ubcinfo->ui_flags, UI_MAPPEDWRITE);
3008 	}
3009 	return TRUE;
3010 }
3011 
3012 boolean_t
ubc_is_mapped_writable(const struct vnode * vp)3013 ubc_is_mapped_writable(const struct vnode *vp)
3014 {
3015 	boolean_t writable;
3016 	return ubc_is_mapped(vp, &writable) && writable;
3017 }
3018 
3019 boolean_t
ubc_was_mapped(const struct vnode * vp,boolean_t * writable)3020 ubc_was_mapped(const struct vnode *vp, boolean_t *writable)
3021 {
3022 	if (!UBCINFOEXISTS(vp) || !ISSET(vp->v_ubcinfo->ui_flags, UI_WASMAPPED)) {
3023 		return FALSE;
3024 	}
3025 	if (writable) {
3026 		*writable = ISSET(vp->v_ubcinfo->ui_flags, UI_WASMAPPEDWRITE);
3027 	}
3028 	return TRUE;
3029 }
3030 
3031 boolean_t
ubc_was_mapped_writable(const struct vnode * vp)3032 ubc_was_mapped_writable(const struct vnode *vp)
3033 {
3034 	boolean_t writable;
3035 	return ubc_was_mapped(vp, &writable) && writable;
3036 }
3037 
3038 
3039 /*
3040  * CODE SIGNING
3041  */
3042 static atomic_size_t cs_blob_size = 0;
3043 static atomic_uint_fast32_t cs_blob_count = 0;
3044 static atomic_size_t cs_blob_size_peak = 0;
3045 static atomic_size_t cs_blob_size_max = 0;
3046 static atomic_uint_fast32_t cs_blob_count_peak = 0;
3047 
3048 SYSCTL_UINT(_vm, OID_AUTO, cs_blob_count, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_count, 0, "Current number of code signature blobs");
3049 SYSCTL_ULONG(_vm, OID_AUTO, cs_blob_size, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_size, "Current size of all code signature blobs");
3050 SYSCTL_UINT(_vm, OID_AUTO, cs_blob_count_peak, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_count_peak, 0, "Peak number of code signature blobs");
3051 SYSCTL_ULONG(_vm, OID_AUTO, cs_blob_size_peak, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_size_peak, "Peak size of code signature blobs");
3052 SYSCTL_ULONG(_vm, OID_AUTO, cs_blob_size_max, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_size_max, "Size of biggest code signature blob");
3053 
3054 /*
3055  * Function: csblob_parse_teamid
3056  *
3057  * Description: This function returns a pointer to the team id
3058  *               stored within the codedirectory of the csblob.
3059  *               If the codedirectory predates team-ids, it returns
3060  *               NULL.
3061  *               This does not copy the name but returns a pointer to
3062  *               it within the CD. Subsequently, the CD must be
3063  *               available when this is used.
3064  */
3065 
3066 static const char *
csblob_parse_teamid(struct cs_blob * csblob)3067 csblob_parse_teamid(struct cs_blob *csblob)
3068 {
3069 	const CS_CodeDirectory *cd;
3070 
3071 	cd = csblob->csb_cd;
3072 
3073 	if (ntohl(cd->version) < CS_SUPPORTSTEAMID) {
3074 		return NULL;
3075 	}
3076 
3077 	if (cd->teamOffset == 0) {
3078 		return NULL;
3079 	}
3080 
3081 	const char *name = ((const char *)cd) + ntohl(cd->teamOffset);
3082 	if (cs_debug > 1) {
3083 		printf("found team-id %s in cdblob\n", name);
3084 	}
3085 
3086 	return name;
3087 }
3088 
3089 kern_return_t
ubc_cs_blob_allocate(vm_offset_t * blob_addr_p,vm_size_t * blob_size_p)3090 ubc_cs_blob_allocate(
3091 	vm_offset_t     *blob_addr_p,
3092 	vm_size_t       *blob_size_p)
3093 {
3094 	kern_return_t   kr = KERN_FAILURE;
3095 	vm_size_t       allocation_size = 0;
3096 
3097 	if (!blob_addr_p || !blob_size_p) {
3098 		return KERN_INVALID_ARGUMENT;
3099 	}
3100 	allocation_size = *blob_size_p;
3101 
3102 	if (ubc_cs_blob_pagewise_allocate(allocation_size) == true) {
3103 		/* Round up to page size */
3104 		allocation_size = round_page(allocation_size);
3105 
3106 		/* Allocate page-wise */
3107 		kr = kmem_alloc(
3108 			kernel_map,
3109 			blob_addr_p,
3110 			allocation_size,
3111 			KMA_KOBJECT | KMA_DATA | KMA_ZERO,
3112 			VM_KERN_MEMORY_SECURITY);
3113 	} else {
3114 		*blob_addr_p = (vm_offset_t)kalloc_data_tag(
3115 			allocation_size,
3116 			Z_WAITOK | Z_ZERO,
3117 			VM_KERN_MEMORY_SECURITY);
3118 
3119 		assert(*blob_addr_p != 0);
3120 		kr = KERN_SUCCESS;
3121 	}
3122 
3123 	if (kr == KERN_SUCCESS) {
3124 		*blob_size_p = allocation_size;
3125 	}
3126 
3127 	return kr;
3128 }
3129 
3130 void
ubc_cs_blob_deallocate(vm_offset_t blob_addr,vm_size_t blob_size)3131 ubc_cs_blob_deallocate(
3132 	vm_offset_t     blob_addr,
3133 	vm_size_t       blob_size)
3134 {
3135 	if (ubc_cs_blob_pagewise_allocate(blob_size) == true) {
3136 		kmem_free(kernel_map, blob_addr, blob_size);
3137 	} else {
3138 		kfree_data(blob_addr, blob_size);
3139 	}
3140 }
3141 
3142 /*
3143  * Some codesigned files use a lowest common denominator page size of
3144  * 4KiB, but can be used on systems that have a runtime page size of
3145  * 16KiB. Since faults will only occur on 16KiB ranges in
3146  * cs_validate_range(), we can convert the original Code Directory to
3147  * a multi-level scheme where groups of 4 hashes are combined to form
3148  * a new hash, which represents 16KiB in the on-disk file.  This can
3149  * reduce the wired memory requirement for the Code Directory by
3150  * 75%. Care must be taken for binaries that use the "fourk" VM pager
3151  * for unaligned access, which may still attempt to validate on
3152  * non-16KiB multiples for compatibility with 3rd party binaries.
3153  */
3154 static boolean_t
ubc_cs_supports_multilevel_hash(struct cs_blob * blob __unused)3155 ubc_cs_supports_multilevel_hash(struct cs_blob *blob __unused)
3156 {
3157 	const CS_CodeDirectory *cd;
3158 
3159 #if CODE_SIGNING_MONITOR
3160 	// TODO: <rdar://problem/30954826>
3161 	if (csm_enabled() == true) {
3162 		return FALSE;
3163 	}
3164 #endif
3165 
3166 	/*
3167 	 * Only applies to binaries that ship as part of the OS,
3168 	 * primarily the shared cache.
3169 	 */
3170 	if (!blob->csb_platform_binary || blob->csb_teamid != NULL) {
3171 		return FALSE;
3172 	}
3173 
3174 	/*
3175 	 * If the runtime page size matches the code signing page
3176 	 * size, there is no work to do.
3177 	 */
3178 	if (PAGE_SHIFT <= blob->csb_hash_pageshift) {
3179 		return FALSE;
3180 	}
3181 
3182 	cd = blob->csb_cd;
3183 
3184 	/*
3185 	 * There must be a valid integral multiple of hashes
3186 	 */
3187 	if (ntohl(cd->nCodeSlots) & (PAGE_MASK >> blob->csb_hash_pageshift)) {
3188 		return FALSE;
3189 	}
3190 
3191 	/*
3192 	 * Scatter lists must also have ranges that have an integral number of hashes
3193 	 */
3194 	if ((ntohl(cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(cd->scatterOffset))) {
3195 		const SC_Scatter *scatter = (const SC_Scatter*)
3196 		    ((const char*)cd + ntohl(cd->scatterOffset));
3197 		/* iterate all scatter structs to make sure they are all aligned */
3198 		do {
3199 			uint32_t sbase = ntohl(scatter->base);
3200 			uint32_t scount = ntohl(scatter->count);
3201 
3202 			/* last scatter? */
3203 			if (scount == 0) {
3204 				break;
3205 			}
3206 
3207 			if (sbase & (PAGE_MASK >> blob->csb_hash_pageshift)) {
3208 				return FALSE;
3209 			}
3210 
3211 			if (scount & (PAGE_MASK >> blob->csb_hash_pageshift)) {
3212 				return FALSE;
3213 			}
3214 
3215 			scatter++;
3216 		} while (1);
3217 	}
3218 
3219 	/* Covered range must be a multiple of the new page size */
3220 	if (ntohl(cd->codeLimit) & PAGE_MASK) {
3221 		return FALSE;
3222 	}
3223 
3224 	/* All checks pass */
3225 	return TRUE;
3226 }
3227 
3228 /*
3229  * Reconstruct a cs_blob with the code signature fields. This helper function
3230  * is useful because a lot of things often change the base address of the code
3231  * signature blob, which requires reconstructing some of the other pointers
3232  * within.
3233  */
3234 static errno_t
ubc_cs_blob_reconstruct(struct cs_blob * cs_blob,const vm_address_t signature_addr,const vm_address_t signature_size,const vm_offset_t code_directory_offset)3235 ubc_cs_blob_reconstruct(
3236 	struct cs_blob *cs_blob,
3237 	const vm_address_t signature_addr,
3238 	const vm_address_t signature_size,
3239 	const vm_offset_t code_directory_offset)
3240 {
3241 	const CS_CodeDirectory *code_directory = NULL;
3242 
3243 	/* Setup the signature blob address */
3244 	cs_blob->csb_mem_kaddr = (void*)signature_addr;
3245 	cs_blob->csb_mem_size = signature_size;
3246 
3247 	/* Setup the code directory in the blob */
3248 	code_directory = (const CS_CodeDirectory*)(signature_addr + code_directory_offset);
3249 	cs_blob->csb_cd = code_directory;
3250 
3251 	/* Setup the XML entitlements */
3252 	cs_blob->csb_entitlements_blob = csblob_find_blob_bytes(
3253 		(uint8_t*)signature_addr,
3254 		signature_size,
3255 		CSSLOT_ENTITLEMENTS,
3256 		CSMAGIC_EMBEDDED_ENTITLEMENTS);
3257 
3258 	/* Setup the DER entitlements */
3259 	cs_blob->csb_der_entitlements_blob = csblob_find_blob_bytes(
3260 		(uint8_t*)signature_addr,
3261 		signature_size,
3262 		CSSLOT_DER_ENTITLEMENTS,
3263 		CSMAGIC_EMBEDDED_DER_ENTITLEMENTS);
3264 
3265 	return 0;
3266 }
3267 
3268 /*
3269  * Given a validated cs_blob, we reformat the structure to only include
3270  * the blobs which are required by the kernel for our current platform.
3271  * This saves significant memory with agile signatures.
3272  *
3273  * To support rewriting the code directory, potentially through
3274  * multilevel hashes, we provide a mechanism to allocate a code directory
3275  * of a specified size and zero it out --> caller can fill it in.
3276  *
3277  * We don't need to perform a lot of overflow checks as the assumption
3278  * here is that the cs_blob has already been validated.
3279  */
3280 static errno_t
ubc_cs_reconstitute_code_signature(const struct cs_blob * const blob,vm_address_t * const ret_mem_kaddr,vm_size_t * const ret_mem_size,vm_size_t code_directory_size,CS_CodeDirectory ** const code_directory)3281 ubc_cs_reconstitute_code_signature(
3282 	const struct cs_blob * const blob,
3283 	vm_address_t * const ret_mem_kaddr,
3284 	vm_size_t * const ret_mem_size,
3285 	vm_size_t code_directory_size,
3286 	CS_CodeDirectory ** const code_directory
3287 	)
3288 {
3289 	vm_address_t new_blob_addr = 0;
3290 	vm_size_t new_blob_size = 0;
3291 	vm_size_t new_code_directory_size = 0;
3292 	const CS_GenericBlob *best_code_directory = NULL;
3293 	const CS_GenericBlob *first_code_directory = NULL;
3294 	const CS_GenericBlob *der_entitlements_blob = NULL;
3295 	const CS_GenericBlob *entitlements_blob = NULL;
3296 	const CS_GenericBlob *cms_blob = NULL;
3297 	const CS_GenericBlob *launch_constraint_self = NULL;
3298 	const CS_GenericBlob *launch_constraint_parent = NULL;
3299 	const CS_GenericBlob *launch_constraint_responsible = NULL;
3300 	CS_SuperBlob *superblob = NULL;
3301 	uint32_t num_blobs = 0;
3302 	uint32_t blob_index = 0;
3303 	uint32_t blob_offset = 0;
3304 	kern_return_t ret;
3305 	int err;
3306 
3307 	if (!blob) {
3308 		if (cs_debug > 1) {
3309 			printf("CODE SIGNING: CS Blob passed in is NULL\n");
3310 		}
3311 		return EINVAL;
3312 	}
3313 
3314 	best_code_directory = (const CS_GenericBlob*)blob->csb_cd;
3315 	if (!best_code_directory) {
3316 		/* This case can never happen, and it is a sign of bad things */
3317 		panic("CODE SIGNING: Validated CS Blob has no code directory");
3318 	}
3319 
3320 	new_code_directory_size = code_directory_size;
3321 	if (new_code_directory_size == 0) {
3322 		new_code_directory_size = ntohl(best_code_directory->length);
3323 	}
3324 
3325 	/*
3326 	 * A code signature can contain multiple code directories, each of which contains hashes
3327 	 * of pages based on a hashing algorithm. The kernel selects which hashing algorithm is
3328 	 * the strongest, and consequently, marks one of these code directories as the best
3329 	 * matched one. More often than not, the best matched one is _not_ the first one.
3330 	 *
3331 	 * However, the CMS blob which cryptographically verifies the code signature is only
3332 	 * signed against the first code directory. Therefore, if the CMS blob is present, we also
3333 	 * need the first code directory to be able to verify it. Given this, we organize the
3334 	 * new cs_blob as following order:
3335 	 *
3336 	 * 1. best code directory
3337 	 * 2. DER encoded entitlements blob (if present)
3338 	 * 3. launch constraint self (if present)
3339 	 * 4. launch constraint parent (if present)
3340 	 * 5. launch constraint responsible (if present)
3341 	 * 6. entitlements blob (if present)
3342 	 * 7. cms blob (if present)
3343 	 * 8. first code directory (if not already the best match, and if cms blob is present)
3344 	 *
3345 	 * This order is chosen deliberately, as later on, we expect to get rid of the CMS blob
3346 	 * and the first code directory once their verification is complete.
3347 	 */
3348 
3349 	/* Storage for the super blob header */
3350 	new_blob_size += sizeof(CS_SuperBlob);
3351 
3352 	/* Guaranteed storage for the best code directory */
3353 	new_blob_size += sizeof(CS_BlobIndex);
3354 	new_blob_size += new_code_directory_size;
3355 	num_blobs += 1;
3356 
3357 	/* Conditional storage for the DER entitlements blob */
3358 	der_entitlements_blob = blob->csb_der_entitlements_blob;
3359 	if (der_entitlements_blob) {
3360 		new_blob_size += sizeof(CS_BlobIndex);
3361 		new_blob_size += ntohl(der_entitlements_blob->length);
3362 		num_blobs += 1;
3363 	}
3364 
3365 	/* Conditional storage for the launch constraints self blob */
3366 	launch_constraint_self = csblob_find_blob_bytes(
3367 		(const uint8_t *)blob->csb_mem_kaddr,
3368 		blob->csb_mem_size,
3369 		CSSLOT_LAUNCH_CONSTRAINT_SELF,
3370 		CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT);
3371 	if (launch_constraint_self) {
3372 		new_blob_size += sizeof(CS_BlobIndex);
3373 		new_blob_size += ntohl(launch_constraint_self->length);
3374 		num_blobs += 1;
3375 	}
3376 
3377 	/* Conditional storage for the launch constraints parent blob */
3378 	launch_constraint_parent = csblob_find_blob_bytes(
3379 		(const uint8_t *)blob->csb_mem_kaddr,
3380 		blob->csb_mem_size,
3381 		CSSLOT_LAUNCH_CONSTRAINT_PARENT,
3382 		CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT);
3383 	if (launch_constraint_parent) {
3384 		new_blob_size += sizeof(CS_BlobIndex);
3385 		new_blob_size += ntohl(launch_constraint_parent->length);
3386 		num_blobs += 1;
3387 	}
3388 
3389 	/* Conditional storage for the launch constraints responsible blob */
3390 	launch_constraint_responsible = csblob_find_blob_bytes(
3391 		(const uint8_t *)blob->csb_mem_kaddr,
3392 		blob->csb_mem_size,
3393 		CSSLOT_LAUNCH_CONSTRAINT_RESPONSIBLE,
3394 		CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT);
3395 	if (launch_constraint_responsible) {
3396 		new_blob_size += sizeof(CS_BlobIndex);
3397 		new_blob_size += ntohl(launch_constraint_responsible->length);
3398 		num_blobs += 1;
3399 	}
3400 
3401 	/* Conditional storage for the entitlements blob */
3402 	entitlements_blob = blob->csb_entitlements_blob;
3403 	if (entitlements_blob) {
3404 		new_blob_size += sizeof(CS_BlobIndex);
3405 		new_blob_size += ntohl(entitlements_blob->length);
3406 		num_blobs += 1;
3407 	}
3408 
3409 	/* Conditional storage for the CMS blob */
3410 	cms_blob = csblob_find_blob_bytes((const uint8_t *)blob->csb_mem_kaddr, blob->csb_mem_size, CSSLOT_SIGNATURESLOT, CSMAGIC_BLOBWRAPPER);
3411 	if (cms_blob) {
3412 		new_blob_size += sizeof(CS_BlobIndex);
3413 		new_blob_size += ntohl(cms_blob->length);
3414 		num_blobs += 1;
3415 	}
3416 
3417 	/*
3418 	 * Conditional storage for the first code directory.
3419 	 * This is only needed if a CMS blob exists and the best code directory isn't already
3420 	 * the first one. It is an error if we find a CMS blob but do not find a first code directory.
3421 	 */
3422 	if (cms_blob) {
3423 		first_code_directory = csblob_find_blob_bytes((const uint8_t *)blob->csb_mem_kaddr, blob->csb_mem_size, CSSLOT_CODEDIRECTORY, CSMAGIC_CODEDIRECTORY);
3424 		if (first_code_directory == best_code_directory) {
3425 			/* We don't need the first code directory anymore, since the best one is already it */
3426 			first_code_directory = NULL;
3427 		} else if (first_code_directory) {
3428 			new_blob_size += sizeof(CS_BlobIndex);
3429 			new_blob_size += ntohl(first_code_directory->length);
3430 			num_blobs += 1;
3431 		} else {
3432 			printf("CODE SIGNING: Invalid CS Blob: found CMS blob but not a first code directory\n");
3433 			return EINVAL;
3434 		}
3435 	}
3436 
3437 	/*
3438 	 * The blob size could be rouded up to page size here, so we keep a copy
3439 	 * of the actual superblob length as well.
3440 	 */
3441 	vm_size_t new_blob_allocation_size = new_blob_size;
3442 	ret = ubc_cs_blob_allocate(&new_blob_addr, &new_blob_allocation_size);
3443 	if (ret != KERN_SUCCESS) {
3444 		printf("CODE SIGNING: Failed to allocate memory for new code signing blob: %d\n", ret);
3445 		return ENOMEM;
3446 	}
3447 
3448 	/*
3449 	 * Fill out the superblob header and then all the blobs in the order listed
3450 	 * above.
3451 	 */
3452 	superblob = (CS_SuperBlob*)new_blob_addr;
3453 	superblob->magic = htonl(CSMAGIC_EMBEDDED_SIGNATURE);
3454 	superblob->length = htonl((uint32_t)new_blob_size);
3455 	superblob->count = htonl(num_blobs);
3456 
3457 	blob_index = 0;
3458 	blob_offset = sizeof(CS_SuperBlob) + (num_blobs * sizeof(CS_BlobIndex));
3459 
3460 	/* Best code directory */
3461 	superblob->index[blob_index].offset = htonl(blob_offset);
3462 	if (first_code_directory) {
3463 		superblob->index[blob_index].type = htonl(CSSLOT_ALTERNATE_CODEDIRECTORIES);
3464 	} else {
3465 		superblob->index[blob_index].type = htonl(CSSLOT_CODEDIRECTORY);
3466 	}
3467 
3468 	if (code_directory_size > 0) {
3469 		/* We zero out the code directory, as we expect the caller to fill it in */
3470 		memset((void*)(new_blob_addr + blob_offset), 0, new_code_directory_size);
3471 	} else {
3472 		memcpy((void*)(new_blob_addr + blob_offset), best_code_directory, new_code_directory_size);
3473 	}
3474 
3475 	if (code_directory) {
3476 		*code_directory = (CS_CodeDirectory*)(new_blob_addr + blob_offset);
3477 	}
3478 	blob_offset += new_code_directory_size;
3479 
3480 	/* DER entitlements blob */
3481 	if (der_entitlements_blob) {
3482 		blob_index += 1;
3483 		superblob->index[blob_index].offset = htonl(blob_offset);
3484 		superblob->index[blob_index].type = htonl(CSSLOT_DER_ENTITLEMENTS);
3485 
3486 		memcpy((void*)(new_blob_addr + blob_offset), der_entitlements_blob, ntohl(der_entitlements_blob->length));
3487 		blob_offset += ntohl(der_entitlements_blob->length);
3488 	}
3489 
3490 	/* Launch constraints self blob */
3491 	if (launch_constraint_self) {
3492 		blob_index += 1;
3493 		superblob->index[blob_index].offset = htonl(blob_offset);
3494 		superblob->index[blob_index].type = htonl(CSSLOT_LAUNCH_CONSTRAINT_SELF);
3495 
3496 		memcpy(
3497 			(void*)(new_blob_addr + blob_offset),
3498 			launch_constraint_self,
3499 			ntohl(launch_constraint_self->length));
3500 
3501 		blob_offset += ntohl(launch_constraint_self->length);
3502 	}
3503 
3504 	/* Launch constraints parent blob */
3505 	if (launch_constraint_parent) {
3506 		blob_index += 1;
3507 		superblob->index[blob_index].offset = htonl(blob_offset);
3508 		superblob->index[blob_index].type = htonl(CSSLOT_LAUNCH_CONSTRAINT_PARENT);
3509 
3510 		memcpy(
3511 			(void*)(new_blob_addr + blob_offset),
3512 			launch_constraint_parent,
3513 			ntohl(launch_constraint_parent->length));
3514 
3515 		blob_offset += ntohl(launch_constraint_parent->length);
3516 	}
3517 
3518 	/* Launch constraints responsible blob */
3519 	if (launch_constraint_responsible) {
3520 		blob_index += 1;
3521 		superblob->index[blob_index].offset = htonl(blob_offset);
3522 		superblob->index[blob_index].type = htonl(CSSLOT_LAUNCH_CONSTRAINT_RESPONSIBLE);
3523 
3524 		memcpy(
3525 			(void*)(new_blob_addr + blob_offset),
3526 			launch_constraint_responsible,
3527 			ntohl(launch_constraint_responsible->length));
3528 
3529 		blob_offset += ntohl(launch_constraint_responsible->length);
3530 	}
3531 
3532 	/* Entitlements blob */
3533 	if (entitlements_blob) {
3534 		blob_index += 1;
3535 		superblob->index[blob_index].offset = htonl(blob_offset);
3536 		superblob->index[blob_index].type = htonl(CSSLOT_ENTITLEMENTS);
3537 
3538 		memcpy((void*)(new_blob_addr + blob_offset), entitlements_blob, ntohl(entitlements_blob->length));
3539 		blob_offset += ntohl(entitlements_blob->length);
3540 	}
3541 
3542 	/* CMS blob */
3543 	if (cms_blob) {
3544 		blob_index += 1;
3545 		superblob->index[blob_index].offset = htonl(blob_offset);
3546 		superblob->index[blob_index].type = htonl(CSSLOT_SIGNATURESLOT);
3547 		memcpy((void*)(new_blob_addr + blob_offset), cms_blob, ntohl(cms_blob->length));
3548 		blob_offset += ntohl(cms_blob->length);
3549 	}
3550 
3551 	/* First code directory */
3552 	if (first_code_directory) {
3553 		blob_index += 1;
3554 		superblob->index[blob_index].offset = htonl(blob_offset);
3555 		superblob->index[blob_index].type = htonl(CSSLOT_CODEDIRECTORY);
3556 		memcpy((void*)(new_blob_addr + blob_offset), first_code_directory, ntohl(first_code_directory->length));
3557 		blob_offset += ntohl(first_code_directory->length);
3558 	}
3559 
3560 	/*
3561 	 * We only validate the blob in case we copied in the best code directory.
3562 	 * In case the code directory size we were passed in wasn't 0, we memset the best
3563 	 * code directory to 0 and expect the caller to fill it in. In the same spirit, we
3564 	 * expect the caller to validate the code signature after they fill in the code
3565 	 * directory.
3566 	 */
3567 	if (code_directory_size == 0) {
3568 		const CS_CodeDirectory *validated_code_directory = NULL;
3569 		const CS_GenericBlob *validated_entitlements_blob = NULL;
3570 		const CS_GenericBlob *validated_der_entitlements_blob = NULL;
3571 
3572 		ret = cs_validate_csblob(
3573 			(const uint8_t *)superblob,
3574 			new_blob_size,
3575 			&validated_code_directory,
3576 			&validated_entitlements_blob,
3577 			&validated_der_entitlements_blob);
3578 
3579 		if (ret) {
3580 			printf("unable to validate reconstituted cs_blob: %d\n", ret);
3581 			err = EINVAL;
3582 			goto fail;
3583 		}
3584 	}
3585 
3586 	if (ret_mem_kaddr) {
3587 		*ret_mem_kaddr = new_blob_addr;
3588 	}
3589 	if (ret_mem_size) {
3590 		*ret_mem_size = new_blob_allocation_size;
3591 	}
3592 
3593 	return 0;
3594 
3595 fail:
3596 	ubc_cs_blob_deallocate(new_blob_addr, new_blob_allocation_size);
3597 	return err;
3598 }
3599 
3600 /*
3601  * We use this function to clear out unnecessary bits from the code signature
3602  * blob which are no longer needed. We free these bits and give them back to
3603  * the kernel. This is needed since reconstitution includes extra data which is
3604  * needed only for verification but has no point in keeping afterwards.
3605  *
3606  * This results in significant memory reduction, especially for 3rd party apps
3607  * since we also get rid of the CMS blob.
3608  */
3609 static errno_t
ubc_cs_reconstitute_code_signature_2nd_stage(struct cs_blob * blob)3610 ubc_cs_reconstitute_code_signature_2nd_stage(
3611 	struct cs_blob *blob
3612 	)
3613 {
3614 	kern_return_t ret = KERN_FAILURE;
3615 	const CS_GenericBlob *launch_constraint_self = NULL;
3616 	const CS_GenericBlob *launch_constraint_parent = NULL;
3617 	const CS_GenericBlob *launch_constraint_responsible = NULL;
3618 	CS_SuperBlob *superblob = NULL;
3619 	uint32_t num_blobs = 0;
3620 	vm_size_t last_needed_blob_offset = 0;
3621 	vm_offset_t code_directory_offset = 0;
3622 
3623 	/*
3624 	 * Ordering of blobs we need to keep:
3625 	 * 1. Code directory
3626 	 * 2. DER encoded entitlements (if present)
3627 	 * 3. Launch constraints self (if present)
3628 	 * 3. Launch constraints parent (if present)
3629 	 * 3. Launch constraints responsible (if present)
3630 	 *
3631 	 * We need to clear out the remaining page after these blobs end, and fix up
3632 	 * the superblob for the changes. Things gets a little more complicated for
3633 	 * blobs which may not have been kmem_allocated. For those, we simply just
3634 	 * allocate the new required space and copy into it.
3635 	 */
3636 
3637 	if (blob == NULL) {
3638 		printf("NULL blob passed in for 2nd stage reconstitution\n");
3639 		return EINVAL;
3640 	}
3641 	assert(blob->csb_reconstituted == true);
3642 
3643 	/* Ensure we're not page-wise allocated when in this function */
3644 	assert(ubc_cs_blob_pagewise_allocate(blob->csb_mem_size) == false);
3645 
3646 	if (!blob->csb_cd) {
3647 		/* This case can never happen, and it is a sign of bad things */
3648 		panic("validated cs_blob has no code directory");
3649 	}
3650 	superblob = (CS_SuperBlob*)blob->csb_mem_kaddr;
3651 
3652 	num_blobs = 1;
3653 	last_needed_blob_offset = ntohl(superblob->index[0].offset) + ntohl(blob->csb_cd->length);
3654 
3655 	/* Check for DER entitlements */
3656 	if (blob->csb_der_entitlements_blob) {
3657 		num_blobs += 1;
3658 		last_needed_blob_offset += ntohl(blob->csb_der_entitlements_blob->length);
3659 	}
3660 
3661 	/* Check for launch constraints self */
3662 	launch_constraint_self = csblob_find_blob_bytes(
3663 		(const uint8_t *)blob->csb_mem_kaddr,
3664 		blob->csb_mem_size,
3665 		CSSLOT_LAUNCH_CONSTRAINT_SELF,
3666 		CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT);
3667 	if (launch_constraint_self) {
3668 		num_blobs += 1;
3669 		last_needed_blob_offset += ntohl(launch_constraint_self->length);
3670 	}
3671 
3672 	/* Check for launch constraints parent */
3673 	launch_constraint_parent = csblob_find_blob_bytes(
3674 		(const uint8_t *)blob->csb_mem_kaddr,
3675 		blob->csb_mem_size,
3676 		CSSLOT_LAUNCH_CONSTRAINT_PARENT,
3677 		CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT);
3678 	if (launch_constraint_parent) {
3679 		num_blobs += 1;
3680 		last_needed_blob_offset += ntohl(launch_constraint_parent->length);
3681 	}
3682 
3683 	/* Check for launch constraints responsible */
3684 	launch_constraint_responsible = csblob_find_blob_bytes(
3685 		(const uint8_t *)blob->csb_mem_kaddr,
3686 		blob->csb_mem_size,
3687 		CSSLOT_LAUNCH_CONSTRAINT_RESPONSIBLE,
3688 		CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT);
3689 	if (launch_constraint_responsible) {
3690 		num_blobs += 1;
3691 		last_needed_blob_offset += ntohl(launch_constraint_responsible->length);
3692 	}
3693 
3694 	superblob->count = htonl(num_blobs);
3695 	superblob->length = htonl((uint32_t)last_needed_blob_offset);
3696 
3697 	/*
3698 	 * There is a chance that the code directory is marked within the superblob as an
3699 	 * alternate code directory. This happens when the first code directory isn't the
3700 	 * best one chosen by the kernel, so to be able to access both the first and the best,
3701 	 * we save the best one as an alternate one. Since we're getting rid of the first one
3702 	 * here, we mark the best one as the first one.
3703 	 */
3704 	superblob->index[0].type = htonl(CSSLOT_CODEDIRECTORY);
3705 
3706 	vm_address_t new_superblob = 0;
3707 	vm_size_t new_superblob_size = last_needed_blob_offset;
3708 
3709 	ret = ubc_cs_blob_allocate(&new_superblob, &new_superblob_size);
3710 	if (ret != KERN_SUCCESS) {
3711 		printf("unable to allocate memory for 2nd stage reconstitution: %d\n", ret);
3712 		return ENOMEM;
3713 	}
3714 	assert(new_superblob_size == last_needed_blob_offset);
3715 
3716 	/* Calculate the code directory offset */
3717 	code_directory_offset = (vm_offset_t)blob->csb_cd - (vm_offset_t)blob->csb_mem_kaddr;
3718 
3719 	/* Copy in the updated superblob into the new memory */
3720 	memcpy((void*)new_superblob, superblob, new_superblob_size);
3721 
3722 	/* Free the old code signature and old memory */
3723 	ubc_cs_blob_deallocate((vm_offset_t)blob->csb_mem_kaddr, blob->csb_mem_size);
3724 
3725 	/* Reconstruct critical fields in the blob object */
3726 	ubc_cs_blob_reconstruct(
3727 		blob,
3728 		new_superblob,
3729 		new_superblob_size,
3730 		code_directory_offset);
3731 
3732 	/* XML entitlements should've been removed */
3733 	assert(blob->csb_entitlements_blob == NULL);
3734 
3735 	const CS_CodeDirectory *validated_code_directory = NULL;
3736 	const CS_GenericBlob *validated_entitlements_blob = NULL;
3737 	const CS_GenericBlob *validated_der_entitlements_blob = NULL;
3738 
3739 	ret = cs_validate_csblob(
3740 		(const uint8_t*)blob->csb_mem_kaddr,
3741 		blob->csb_mem_size,
3742 		&validated_code_directory,
3743 		&validated_entitlements_blob,
3744 		&validated_der_entitlements_blob);
3745 	if (ret) {
3746 		printf("unable to validate code signature after 2nd stage reconstitution: %d\n", ret);
3747 		return EINVAL;
3748 	}
3749 
3750 	return 0;
3751 }
3752 
3753 static int
ubc_cs_convert_to_multilevel_hash(struct cs_blob * blob)3754 ubc_cs_convert_to_multilevel_hash(struct cs_blob *blob)
3755 {
3756 	const CS_CodeDirectory  *old_cd, *cd;
3757 	CS_CodeDirectory        *new_cd;
3758 	const CS_GenericBlob *entitlements;
3759 	const CS_GenericBlob *der_entitlements;
3760 	vm_offset_t     new_blob_addr;
3761 	vm_size_t       new_blob_size;
3762 	vm_size_t       new_cdsize;
3763 	int                             error;
3764 
3765 	uint32_t                hashes_per_new_hash_shift = (uint32_t)(PAGE_SHIFT - blob->csb_hash_pageshift);
3766 
3767 	if (cs_debug > 1) {
3768 		printf("CODE SIGNING: Attempting to convert Code Directory for %lu -> %lu page shift\n",
3769 		    (unsigned long)blob->csb_hash_pageshift, (unsigned long)PAGE_SHIFT);
3770 	}
3771 
3772 	old_cd = blob->csb_cd;
3773 
3774 	/* Up to the hashes, we can copy all data */
3775 	new_cdsize  = ntohl(old_cd->hashOffset);
3776 	new_cdsize += (ntohl(old_cd->nCodeSlots) >> hashes_per_new_hash_shift) * old_cd->hashSize;
3777 
3778 	error = ubc_cs_reconstitute_code_signature(blob, &new_blob_addr, &new_blob_size, new_cdsize, &new_cd);
3779 	if (error != 0) {
3780 		printf("CODE SIGNING: Failed to reconsitute code signature: %d\n", error);
3781 		return error;
3782 	}
3783 	entitlements = csblob_find_blob_bytes((uint8_t*)new_blob_addr, new_blob_size, CSSLOT_ENTITLEMENTS, CSMAGIC_EMBEDDED_ENTITLEMENTS);
3784 	der_entitlements = csblob_find_blob_bytes((uint8_t*)new_blob_addr, new_blob_size, CSSLOT_DER_ENTITLEMENTS, CSMAGIC_EMBEDDED_DER_ENTITLEMENTS);
3785 
3786 	memcpy(new_cd, old_cd, ntohl(old_cd->hashOffset));
3787 
3788 	/* Update fields in the Code Directory structure */
3789 	new_cd->length = htonl((uint32_t)new_cdsize);
3790 
3791 	uint32_t nCodeSlots = ntohl(new_cd->nCodeSlots);
3792 	nCodeSlots >>= hashes_per_new_hash_shift;
3793 	new_cd->nCodeSlots = htonl(nCodeSlots);
3794 
3795 	new_cd->pageSize = (uint8_t)PAGE_SHIFT; /* Not byte-swapped */
3796 
3797 	if ((ntohl(new_cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(new_cd->scatterOffset))) {
3798 		SC_Scatter *scatter = (SC_Scatter*)
3799 		    ((char *)new_cd + ntohl(new_cd->scatterOffset));
3800 		/* iterate all scatter structs to scale their counts */
3801 		do {
3802 			uint32_t scount = ntohl(scatter->count);
3803 			uint32_t sbase  = ntohl(scatter->base);
3804 
3805 			/* last scatter? */
3806 			if (scount == 0) {
3807 				break;
3808 			}
3809 
3810 			scount >>= hashes_per_new_hash_shift;
3811 			scatter->count = htonl(scount);
3812 
3813 			sbase >>= hashes_per_new_hash_shift;
3814 			scatter->base = htonl(sbase);
3815 
3816 			scatter++;
3817 		} while (1);
3818 	}
3819 
3820 	/* For each group of hashes, hash them together */
3821 	const unsigned char *src_base = (const unsigned char *)old_cd + ntohl(old_cd->hashOffset);
3822 	unsigned char *dst_base = (unsigned char *)new_cd + ntohl(new_cd->hashOffset);
3823 
3824 	uint32_t hash_index;
3825 	for (hash_index = 0; hash_index < nCodeSlots; hash_index++) {
3826 		union cs_hash_union     mdctx;
3827 
3828 		uint32_t source_hash_len = old_cd->hashSize << hashes_per_new_hash_shift;
3829 		const unsigned char *src = src_base + hash_index * source_hash_len;
3830 		unsigned char *dst = dst_base + hash_index * new_cd->hashSize;
3831 
3832 		blob->csb_hashtype->cs_init(&mdctx);
3833 		blob->csb_hashtype->cs_update(&mdctx, src, source_hash_len);
3834 		blob->csb_hashtype->cs_final(dst, &mdctx);
3835 	}
3836 
3837 	error = cs_validate_csblob((const uint8_t *)new_blob_addr, new_blob_size, &cd, &entitlements, &der_entitlements);
3838 	if (error != 0) {
3839 		printf("CODE SIGNING: Failed to validate new Code Signing Blob: %d\n",
3840 		    error);
3841 
3842 		ubc_cs_blob_deallocate(new_blob_addr, new_blob_size);
3843 		return error;
3844 	}
3845 
3846 	/* New Code Directory is ready for use, swap it out in the blob structure */
3847 	ubc_cs_blob_deallocate((vm_offset_t)blob->csb_mem_kaddr, blob->csb_mem_size);
3848 
3849 	blob->csb_mem_size = new_blob_size;
3850 	blob->csb_mem_kaddr = (void *)new_blob_addr;
3851 	blob->csb_cd = cd;
3852 	blob->csb_entitlements_blob = NULL;
3853 
3854 	blob->csb_der_entitlements_blob = der_entitlements; /* may be NULL, not yet validated */
3855 	blob->csb_reconstituted = true;
3856 
3857 	/* The blob has some cached attributes of the Code Directory, so update those */
3858 
3859 	blob->csb_hash_firstlevel_pageshift = blob->csb_hash_pageshift; /* Save the original page size */
3860 
3861 	blob->csb_hash_pageshift = PAGE_SHIFT;
3862 	blob->csb_end_offset = ntohl(cd->codeLimit);
3863 	if ((ntohl(cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(cd->scatterOffset))) {
3864 		const SC_Scatter *scatter = (const SC_Scatter*)
3865 		    ((const char*)cd + ntohl(cd->scatterOffset));
3866 		blob->csb_start_offset = ((off_t)ntohl(scatter->base)) * PAGE_SIZE;
3867 	} else {
3868 		blob->csb_start_offset = 0;
3869 	}
3870 
3871 	return 0;
3872 }
3873 
3874 static void
cs_blob_cleanup(struct cs_blob * blob)3875 cs_blob_cleanup(struct cs_blob *blob)
3876 {
3877 	if (blob->csb_entitlements != NULL) {
3878 		amfi->OSEntitlements_invalidate(blob->csb_entitlements);
3879 		osobject_release(blob->csb_entitlements);
3880 		blob->csb_entitlements = NULL;
3881 	}
3882 
3883 #if CODE_SIGNING_MONITOR
3884 	if (blob->csb_csm_obj != NULL) {
3885 		/* Unconditionally remove any profiles we may have associated */
3886 		csm_disassociate_provisioning_profile(blob->csb_csm_obj);
3887 
3888 		kern_return_t kr = csm_unregister_code_signature(blob->csb_csm_obj);
3889 		if (kr == KERN_SUCCESS) {
3890 			/*
3891 			 * If the code signature was monitor managed, the monitor will have freed it
3892 			 * itself in the unregistration call. It means we do not need to free the data
3893 			 * over here.
3894 			 */
3895 			if (blob->csb_csm_managed) {
3896 				blob->csb_mem_kaddr = NULL;
3897 				blob->csb_mem_size = 0;
3898 			}
3899 		}
3900 	}
3901 
3902 	/* Unconditionally remove references to the monitor */
3903 	blob->csb_csm_obj = NULL;
3904 	blob->csb_csm_managed = false;
3905 #endif
3906 
3907 	if (blob->csb_mem_kaddr) {
3908 		ubc_cs_blob_deallocate((vm_offset_t)blob->csb_mem_kaddr, blob->csb_mem_size);
3909 	}
3910 	blob->csb_mem_kaddr = NULL;
3911 	blob->csb_mem_size = 0;
3912 }
3913 
3914 static void
cs_blob_ro_free(struct cs_blob * blob)3915 cs_blob_ro_free(struct cs_blob *blob)
3916 {
3917 	struct cs_blob tmp;
3918 
3919 	if (blob != NULL) {
3920 		/*
3921 		 * cs_blob_cleanup clears fields, so we need to pass it a
3922 		 * mutable copy.
3923 		 */
3924 		tmp = *blob;
3925 		cs_blob_cleanup(&tmp);
3926 
3927 		zfree_ro(ZONE_ID_CS_BLOB, blob);
3928 	}
3929 }
3930 
3931 /*
3932  * Free a cs_blob previously created by cs_blob_create_validated.
3933  */
3934 void
cs_blob_free(struct cs_blob * blob)3935 cs_blob_free(
3936 	struct cs_blob *blob)
3937 {
3938 	cs_blob_ro_free(blob);
3939 }
3940 
3941 static int
cs_blob_init_validated(vm_address_t * const addr,vm_size_t size,struct cs_blob * blob,CS_CodeDirectory const ** const ret_cd)3942 cs_blob_init_validated(
3943 	vm_address_t * const addr,
3944 	vm_size_t size,
3945 	struct cs_blob *blob,
3946 	CS_CodeDirectory const ** const ret_cd)
3947 {
3948 	int error = EINVAL;
3949 	const CS_CodeDirectory *cd = NULL;
3950 	const CS_GenericBlob *entitlements = NULL;
3951 	const CS_GenericBlob *der_entitlements = NULL;
3952 	union cs_hash_union mdctx;
3953 	size_t length;
3954 
3955 	bzero(blob, sizeof(*blob));
3956 
3957 	/* fill in the new blob */
3958 	blob->csb_mem_size = size;
3959 	blob->csb_mem_offset = 0;
3960 	blob->csb_mem_kaddr = (void *)*addr;
3961 	blob->csb_flags = 0;
3962 	blob->csb_signer_type = CS_SIGNER_TYPE_UNKNOWN;
3963 	blob->csb_platform_binary = 0;
3964 	blob->csb_platform_path = 0;
3965 	blob->csb_teamid = NULL;
3966 #if CONFIG_SUPPLEMENTAL_SIGNATURES
3967 	blob->csb_supplement_teamid = NULL;
3968 #endif
3969 	blob->csb_entitlements_blob = NULL;
3970 	blob->csb_der_entitlements_blob = NULL;
3971 	blob->csb_entitlements = NULL;
3972 #if CODE_SIGNING_MONITOR
3973 	blob->csb_csm_obj = NULL;
3974 	blob->csb_csm_managed = false;
3975 #endif
3976 	blob->csb_reconstituted = false;
3977 	blob->csb_validation_category = CS_VALIDATION_CATEGORY_INVALID;
3978 
3979 	/* Transfer ownership. Even on error, this function will deallocate */
3980 	*addr = 0;
3981 
3982 	/*
3983 	 * Validate the blob's contents
3984 	 */
3985 	length = (size_t) size;
3986 	error = cs_validate_csblob((const uint8_t *)blob->csb_mem_kaddr,
3987 	    length, &cd, &entitlements, &der_entitlements);
3988 	if (error) {
3989 		if (cs_debug) {
3990 			printf("CODESIGNING: csblob invalid: %d\n", error);
3991 		}
3992 		/*
3993 		 * The vnode checker can't make the rest of this function
3994 		 * succeed if csblob validation failed, so bail */
3995 		goto out;
3996 	} else {
3997 		const unsigned char *md_base;
3998 		uint8_t hash[CS_HASH_MAX_SIZE];
3999 		int md_size;
4000 		vm_offset_t hash_pagemask;
4001 
4002 		blob->csb_cd = cd;
4003 		blob->csb_entitlements_blob = entitlements; /* may be NULL, not yet validated */
4004 		blob->csb_der_entitlements_blob = der_entitlements; /* may be NULL, not yet validated */
4005 		blob->csb_hashtype = cs_find_md(cd->hashType);
4006 		if (blob->csb_hashtype == NULL || blob->csb_hashtype->cs_digest_size > sizeof(hash)) {
4007 			panic("validated CodeDirectory but unsupported type");
4008 		}
4009 
4010 		blob->csb_hash_pageshift = cd->pageSize;
4011 		hash_pagemask = (1U << cd->pageSize) - 1;
4012 		blob->csb_hash_firstlevel_pageshift = 0;
4013 		blob->csb_flags = (ntohl(cd->flags) & CS_ALLOWED_MACHO) | CS_VALID;
4014 		blob->csb_end_offset = (((vm_offset_t)ntohl(cd->codeLimit) + hash_pagemask) & ~hash_pagemask);
4015 		if ((ntohl(cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(cd->scatterOffset))) {
4016 			const SC_Scatter *scatter = (const SC_Scatter*)
4017 			    ((const char*)cd + ntohl(cd->scatterOffset));
4018 			blob->csb_start_offset = ((off_t)ntohl(scatter->base)) * (1U << blob->csb_hash_pageshift);
4019 		} else {
4020 			blob->csb_start_offset = 0;
4021 		}
4022 		/* compute the blob's cdhash */
4023 		md_base = (const unsigned char *) cd;
4024 		md_size = ntohl(cd->length);
4025 
4026 		blob->csb_hashtype->cs_init(&mdctx);
4027 		blob->csb_hashtype->cs_update(&mdctx, md_base, md_size);
4028 		blob->csb_hashtype->cs_final(hash, &mdctx);
4029 
4030 		memcpy(blob->csb_cdhash, hash, CS_CDHASH_LEN);
4031 
4032 #if CONFIG_SUPPLEMENTAL_SIGNATURES
4033 		blob->csb_linkage_hashtype = NULL;
4034 		if (ntohl(cd->version) >= CS_SUPPORTSLINKAGE && cd->linkageHashType != 0 &&
4035 		    ntohl(cd->linkageSize) >= CS_CDHASH_LEN) {
4036 			blob->csb_linkage_hashtype = cs_find_md(cd->linkageHashType);
4037 
4038 			if (blob->csb_linkage_hashtype != NULL) {
4039 				memcpy(blob->csb_linkage, (uint8_t const*)cd + ntohl(cd->linkageOffset),
4040 				    CS_CDHASH_LEN);
4041 			}
4042 		}
4043 #endif
4044 	}
4045 
4046 	error = 0;
4047 
4048 out:
4049 	if (error != 0) {
4050 		cs_blob_cleanup(blob);
4051 		blob = NULL;
4052 		cd = NULL;
4053 	}
4054 
4055 	if (ret_cd != NULL) {
4056 		*ret_cd = cd;
4057 	}
4058 
4059 	return error;
4060 }
4061 
4062 /*
4063  * Validate the code signature blob, create a struct cs_blob wrapper
4064  * and return it together with a pointer to the chosen code directory
4065  * and entitlements blob.
4066  *
4067  * Note that this takes ownership of the memory as addr, mainly because
4068  * this function can actually replace the passed in blob with another
4069  * one, e.g. when performing multilevel hashing optimization.
4070  */
4071 int
cs_blob_create_validated(vm_address_t * const addr,vm_size_t size,struct cs_blob ** const ret_blob,CS_CodeDirectory const ** const ret_cd)4072 cs_blob_create_validated(
4073 	vm_address_t * const            addr,
4074 	vm_size_t                       size,
4075 	struct cs_blob ** const         ret_blob,
4076 	CS_CodeDirectory const ** const     ret_cd)
4077 {
4078 	struct cs_blob blob = {};
4079 	struct cs_blob *ro_blob;
4080 	int error;
4081 
4082 	if (ret_blob) {
4083 		*ret_blob = NULL;
4084 	}
4085 
4086 	if ((error = cs_blob_init_validated(addr, size, &blob, ret_cd)) != 0) {
4087 		return error;
4088 	}
4089 
4090 	if (ret_blob != NULL) {
4091 		ro_blob = zalloc_ro(ZONE_ID_CS_BLOB, Z_WAITOK | Z_NOFAIL);
4092 		zalloc_ro_update_elem(ZONE_ID_CS_BLOB, ro_blob, &blob);
4093 		*ret_blob = ro_blob;
4094 	}
4095 
4096 	return error;
4097 }
4098 
4099 #if CONFIG_SUPPLEMENTAL_SIGNATURES
4100 static void
cs_blob_supplement_free(struct cs_blob * const blob)4101 cs_blob_supplement_free(struct cs_blob * const blob)
4102 {
4103 	void *teamid;
4104 
4105 	if (blob != NULL) {
4106 		if (blob->csb_supplement_teamid != NULL) {
4107 			teamid = blob->csb_supplement_teamid;
4108 			vm_size_t teamid_size = strlen(blob->csb_supplement_teamid) + 1;
4109 			kfree_data(teamid, teamid_size);
4110 		}
4111 		cs_blob_ro_free(blob);
4112 	}
4113 }
4114 #endif
4115 
4116 static void
ubc_cs_blob_adjust_statistics(struct cs_blob const * blob)4117 ubc_cs_blob_adjust_statistics(struct cs_blob const *blob)
4118 {
4119 	/* Note that the atomic ops are not enough to guarantee
4120 	 * correctness: If a blob with an intermediate size is inserted
4121 	 * concurrently, we can lose a peak value assignment. But these
4122 	 * statistics are only advisory anyway, so we're not going to
4123 	 * employ full locking here. (Consequently, we are also okay with
4124 	 * relaxed ordering of those accesses.)
4125 	 */
4126 
4127 	unsigned int new_cs_blob_count = os_atomic_add(&cs_blob_count, 1, relaxed);
4128 	if (new_cs_blob_count > os_atomic_load(&cs_blob_count_peak, relaxed)) {
4129 		os_atomic_store(&cs_blob_count_peak, new_cs_blob_count, relaxed);
4130 	}
4131 
4132 	size_t new_cs_blob_size = os_atomic_add(&cs_blob_size, blob->csb_mem_size, relaxed);
4133 
4134 	if (new_cs_blob_size > os_atomic_load(&cs_blob_size_peak, relaxed)) {
4135 		os_atomic_store(&cs_blob_size_peak, new_cs_blob_size, relaxed);
4136 	}
4137 	if (blob->csb_mem_size > os_atomic_load(&cs_blob_size_max, relaxed)) {
4138 		os_atomic_store(&cs_blob_size_max, blob->csb_mem_size, relaxed);
4139 	}
4140 }
4141 
4142 static void
cs_blob_set_cpu_type(struct cs_blob * blob,cpu_type_t cputype)4143 cs_blob_set_cpu_type(struct cs_blob *blob, cpu_type_t cputype)
4144 {
4145 	zalloc_ro_update_field(ZONE_ID_CS_BLOB, blob, csb_cpu_type, &cputype);
4146 }
4147 
4148 __abortlike
4149 static void
panic_cs_blob_backref_mismatch(struct cs_blob * blob,struct vnode * vp)4150 panic_cs_blob_backref_mismatch(struct cs_blob *blob, struct vnode *vp)
4151 {
4152 	panic("cs_blob vnode backref mismatch: blob=%p, vp=%p, "
4153 	    "blob->csb_vnode=%p", blob, vp, blob->csb_vnode);
4154 }
4155 
4156 void
cs_blob_require(struct cs_blob * blob,vnode_t vp)4157 cs_blob_require(struct cs_blob *blob, vnode_t vp)
4158 {
4159 	zone_require_ro(ZONE_ID_CS_BLOB, sizeof(struct cs_blob), blob);
4160 
4161 	if (vp != NULL && __improbable(blob->csb_vnode != vp)) {
4162 		panic_cs_blob_backref_mismatch(blob, vp);
4163 	}
4164 }
4165 
4166 #if CODE_SIGNING_MONITOR
4167 
4168 /**
4169  * Independently verify the authenticity of the code signature through the monitor
4170  * environment. This is required as otherwise the monitor won't allow associations
4171  * of the code signature with address spaces.
4172  *
4173  * Once we've verified the code signature, we no longer need to keep around any
4174  * provisioning profiles we may have registered with it. AMFI associates profiles
4175  * with the monitor during its validation (which happens before the monitor's).
4176  */
4177 static errno_t
verify_code_signature_monitor(struct cs_blob * cs_blob)4178 verify_code_signature_monitor(
4179 	struct cs_blob *cs_blob)
4180 {
4181 	kern_return_t ret = KERN_DENIED;
4182 
4183 	ret = csm_verify_code_signature(cs_blob->csb_csm_obj);
4184 	if ((ret != KERN_SUCCESS) && (ret != KERN_NOT_SUPPORTED)) {
4185 		printf("unable to verify code signature with monitor: %d\n", ret);
4186 		return EPERM;
4187 	}
4188 
4189 	ret = csm_disassociate_provisioning_profile(cs_blob->csb_csm_obj);
4190 	if ((ret != KERN_SUCCESS) && (ret != KERN_NOT_FOUND) && (ret != KERN_NOT_SUPPORTED)) {
4191 		printf("unable to disassociate profile from code signature: %d\n", ret);
4192 		return EPERM;
4193 	}
4194 
4195 	/* Associate the OSEntitlements kernel object with the monitor */
4196 	ret = csm_associate_os_entitlements(cs_blob->csb_csm_obj, cs_blob->csb_entitlements);
4197 	if ((ret != KERN_SUCCESS) && (ret != KERN_NOT_SUPPORTED)) {
4198 		printf("unable to associate OSEntitlements with monitor: %d\n", ret);
4199 		return EPERM;
4200 	}
4201 
4202 	return 0;
4203 }
4204 
4205 /**
4206  * Register the code signature with the code signing monitor environment. This
4207  * will effectively make the blob data immutable, either because the blob memory
4208  * will be allocated and managed directory by the monitor, or because the monitor
4209  * will lockdown the memory associated with the blob.
4210  */
4211 static errno_t
register_code_signature_monitor(struct vnode * vnode,struct cs_blob * cs_blob,vm_offset_t code_directory_offset)4212 register_code_signature_monitor(
4213 	struct vnode *vnode,
4214 	struct cs_blob *cs_blob,
4215 	vm_offset_t code_directory_offset)
4216 {
4217 	kern_return_t ret = KERN_DENIED;
4218 	vm_address_t monitor_signature_addr = 0;
4219 	void *monitor_sig_object = NULL;
4220 	const char *vnode_path_ptr = NULL;
4221 
4222 	/*
4223 	 * Attempt to resolve the path for this vnode and pass it in to the code
4224 	 * signing monitor during registration.
4225 	 */
4226 	int vnode_path_len = MAXPATHLEN;
4227 	char *vnode_path = kalloc_data(vnode_path_len, Z_WAITOK);
4228 
4229 	errno_t error = vnode_getwithref(vnode);
4230 	if (error == 0) {
4231 		error = vn_getpath(vnode, vnode_path, &vnode_path_len);
4232 		if (error == 0) {
4233 			vnode_path_ptr = vnode_path;
4234 		}
4235 
4236 		/* Release reference count on the vnode */
4237 		(void)vnode_put(vnode);
4238 	}
4239 
4240 	ret = csm_register_code_signature(
4241 		(vm_address_t)cs_blob->csb_mem_kaddr,
4242 		cs_blob->csb_mem_size,
4243 		code_directory_offset,
4244 		vnode_path_ptr,
4245 		&monitor_sig_object,
4246 		&monitor_signature_addr);
4247 
4248 	kfree_data(vnode_path, MAXPATHLEN);
4249 	vnode_path_ptr = NULL;
4250 
4251 	if (ret == KERN_SUCCESS) {
4252 		/* Reconstruct the cs_blob if the monitor used its own allocation */
4253 		if (monitor_signature_addr != (vm_address_t)cs_blob->csb_mem_kaddr) {
4254 			vm_address_t monitor_signature_size = cs_blob->csb_mem_size;
4255 
4256 			/* Free the old memory for the blob */
4257 			ubc_cs_blob_deallocate(
4258 				(vm_address_t)cs_blob->csb_mem_kaddr,
4259 				cs_blob->csb_mem_size);
4260 
4261 			/* Reconstruct critical fields in the blob object */
4262 			ubc_cs_blob_reconstruct(
4263 				cs_blob,
4264 				monitor_signature_addr,
4265 				monitor_signature_size,
4266 				code_directory_offset);
4267 
4268 			/* Mark the signature as monitor managed */
4269 			cs_blob->csb_csm_managed = true;
4270 		}
4271 	} else if (ret != KERN_NOT_SUPPORTED) {
4272 		printf("unable to register code signature with monitor: %d\n", ret);
4273 		return EPERM;
4274 	}
4275 
4276 	/* Save the monitor handle for the signature object -- may be NULL */
4277 	cs_blob->csb_csm_obj = monitor_sig_object;
4278 
4279 	return 0;
4280 }
4281 
4282 #endif /* CODE_SIGNING_MONITOR */
4283 
4284 /**
4285  * Accelerate entitlements for a code signature object. When we have a code
4286  * signing monitor, this acceleration is done within the monitor which then
4287  * passes back a CoreEntitlements query context the kernel can use. When we
4288  * don't have a code signing monitor, we accelerate the queries within the
4289  * kernel memory itself.
4290  *
4291  * This function must be called when the storage for the code signature can
4292  * no longer change.
4293  */
4294 static errno_t
accelerate_entitlement_queries(struct cs_blob * cs_blob)4295 accelerate_entitlement_queries(
4296 	struct cs_blob *cs_blob)
4297 {
4298 	kern_return_t ret = KERN_NOT_SUPPORTED;
4299 
4300 #if CODE_SIGNING_MONITOR
4301 	CEQueryContext_t ce_ctx = NULL;
4302 	const char *signing_id = NULL;
4303 
4304 	ret = csm_accelerate_entitlements(cs_blob->csb_csm_obj, &ce_ctx);
4305 	if ((ret != KERN_SUCCESS) && (ret != KERN_NOT_SUPPORTED)) {
4306 		printf("unable to accelerate entitlements through the monitor: %d\n", ret);
4307 		return EPERM;
4308 	}
4309 
4310 	if (ret == KERN_SUCCESS) {
4311 		/* Call cannot not fail at this stage */
4312 		ret = csm_acquire_signing_identifier(cs_blob->csb_csm_obj, &signing_id);
4313 		assert(ret == KERN_SUCCESS);
4314 
4315 		/* Adjust the OSEntitlements context with AMFI */
4316 		ret = amfi->OSEntitlements.adjustContextWithMonitor(
4317 			cs_blob->csb_entitlements,
4318 			ce_ctx,
4319 			cs_blob->csb_csm_obj,
4320 			signing_id,
4321 			cs_blob->csb_flags);
4322 		if (ret != KERN_SUCCESS) {
4323 			printf("unable to adjust OSEntitlements context with monitor: %d\n", ret);
4324 			return EPERM;
4325 		}
4326 
4327 		return 0;
4328 	}
4329 #endif
4330 
4331 	/*
4332 	 * If we reach here, then either we don't have a code signing monitor, or
4333 	 * the code signing monitor isn't enabled for code signing, in which case,
4334 	 * AMFI is going to accelerate the entitlements context and adjust its
4335 	 * context on its own.
4336 	 */
4337 	assert(ret == KERN_NOT_SUPPORTED);
4338 
4339 	ret = amfi->OSEntitlements.adjustContextWithoutMonitor(
4340 		cs_blob->csb_entitlements,
4341 		cs_blob);
4342 
4343 	if (ret != KERN_SUCCESS) {
4344 		printf("unable to adjust OSEntitlements context without monitor: %d\n", ret);
4345 		return EPERM;
4346 	}
4347 
4348 	return 0;
4349 }
4350 
4351 /**
4352  * Ensure and validate that some security critical code signing blobs haven't
4353  * been stripped off from the code signature. This can happen if an attacker
4354  * chose to load a code signature sans these critical blobs, or if there is a
4355  * bug in reconstitution logic which remove these blobs from the code signature.
4356  */
4357 static errno_t
validate_auxiliary_signed_blobs(struct cs_blob * cs_blob)4358 validate_auxiliary_signed_blobs(
4359 	struct cs_blob *cs_blob)
4360 {
4361 	struct cs_blob_identifier {
4362 		uint32_t cs_slot;
4363 		uint32_t cs_magic;
4364 	};
4365 
4366 	const struct cs_blob_identifier identifiers[] = {
4367 		{CSSLOT_LAUNCH_CONSTRAINT_SELF, CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT},
4368 		{CSSLOT_LAUNCH_CONSTRAINT_PARENT, CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT},
4369 		{CSSLOT_LAUNCH_CONSTRAINT_RESPONSIBLE, CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT}
4370 	};
4371 	const uint32_t num_identifiers = sizeof(identifiers) / sizeof(identifiers[0]);
4372 
4373 	for (uint32_t i = 0; i < num_identifiers; i++) {
4374 		errno_t err = csblob_find_special_slot_blob(
4375 			cs_blob,
4376 			identifiers[i].cs_slot,
4377 			identifiers[i].cs_magic,
4378 			NULL,
4379 			NULL);
4380 
4381 		if (err != 0) {
4382 			printf("unable to validate security-critical blob: %d [%u|%u]\n",
4383 			    err, identifiers[i].cs_slot, identifiers[i].cs_magic);
4384 
4385 			return EPERM;
4386 		}
4387 	}
4388 
4389 	return 0;
4390 }
4391 
4392 /**
4393  * Setup multi-level hashing for the code signature. This isn't supported on most
4394  * shipping devices, but on ones where it is, it can result in significant savings
4395  * of memory from the code signature standpoint.
4396  *
4397  * Multi-level hashing is used to condense the code directory hashes in order to
4398  * improve memory consumption. We take four 4K page hashes, and condense them into
4399  * a single 16K hash, hence reducing the space consumed by the code directory by
4400  * about ~75%.
4401  */
4402 static errno_t
setup_multilevel_hashing(struct cs_blob * cs_blob)4403 setup_multilevel_hashing(
4404 	struct cs_blob *cs_blob)
4405 {
4406 	code_signing_monitor_type_t monitor_type = CS_MONITOR_TYPE_NONE;
4407 	errno_t err = -1;
4408 
4409 	/*
4410 	 * When we have a code signing monitor, we do not support multi-level hashing
4411 	 * since the code signature data is expected to be locked within memory which
4412 	 * cannot be written to by the kernel.
4413 	 *
4414 	 * Even when the code signing monitor isn't explicitly enabled, there are other
4415 	 * reasons for not performing multi-level hashing. For instance, Rosetta creates
4416 	 * issues with multi-level hashing on Apple Silicon Macs.
4417 	 */
4418 	code_signing_configuration(&monitor_type, NULL);
4419 	if (monitor_type != CS_MONITOR_TYPE_NONE) {
4420 		return 0;
4421 	}
4422 
4423 	/* We need to check if multi-level hashing is supported for this blob */
4424 	if (ubc_cs_supports_multilevel_hash(cs_blob) == false) {
4425 		return 0;
4426 	}
4427 
4428 	err = ubc_cs_convert_to_multilevel_hash(cs_blob);
4429 	if (err != 0) {
4430 		printf("unable to setup multi-level hashing: %d\n", err);
4431 		return err;
4432 	}
4433 
4434 	assert(cs_blob->csb_reconstituted == true);
4435 	return 0;
4436 }
4437 
4438 /**
4439  * Once code signature validation is complete, we can remove even more blobs from the
4440  * code signature as they are no longer needed. This goes on to conserve even more
4441  * system memory.
4442  */
4443 static errno_t
reconstitute_code_signature_2nd_stage(struct cs_blob * cs_blob)4444 reconstitute_code_signature_2nd_stage(
4445 	struct cs_blob *cs_blob)
4446 {
4447 	kern_return_t ret = KERN_NOT_SUPPORTED;
4448 	errno_t err = EPERM;
4449 
4450 	/* If we never reconstituted before, we won't be reconstituting again */
4451 	if (cs_blob->csb_reconstituted == false) {
4452 		return 0;
4453 	}
4454 
4455 #if CODE_SIGNING_MONITOR
4456 	/*
4457 	 * When we have a code signing monitor, the code signature is immutable until the
4458 	 * monitor decides to unlock parts of it. Therefore, 2nd stage reconstitution takes
4459 	 * place in the monitor when we have a monitor available.
4460 	 *
4461 	 * If the monitor isn't enforcing code signing (in which case the code signature is
4462 	 * NOT immutable), then we perform 2nd stage reconstitution within the kernel itself.
4463 	 */
4464 	vm_address_t unneeded_addr = 0;
4465 	vm_size_t unneeded_size = 0;
4466 
4467 	ret = csm_reconstitute_code_signature(
4468 		cs_blob->csb_csm_obj,
4469 		&unneeded_addr,
4470 		&unneeded_size);
4471 
4472 	if ((ret == KERN_SUCCESS) && unneeded_addr && unneeded_size) {
4473 		/* Free the unneded part of the blob */
4474 		kmem_free(kernel_map, unneeded_addr, unneeded_size);
4475 
4476 		/* Adjust the size in the blob object */
4477 		cs_blob->csb_mem_size -= unneeded_size;
4478 	}
4479 #endif
4480 
4481 	if (ret == KERN_SUCCESS) {
4482 		goto success;
4483 	} else if (ret != KERN_NOT_SUPPORTED) {
4484 		/*
4485 		 * A monitor environment is available, and it failed in performing 2nd stage
4486 		 * reconstitution. This is a fatal issue for code signing validation.
4487 		 */
4488 		printf("unable to reconstitute code signature through monitor: %d\n", ret);
4489 		return EPERM;
4490 	}
4491 
4492 	/* No monitor available if we reached here */
4493 	err = ubc_cs_reconstitute_code_signature_2nd_stage(cs_blob);
4494 	if (err != 0) {
4495 		return err;
4496 	}
4497 
4498 success:
4499 	/*
4500 	 * Regardless of whether we are performing 2nd stage reconstitution in the monitor
4501 	 * or in the kernel, we remove references to XML entitlements from the blob here.
4502 	 * None of the 2nd stage reconstitution code ever keeps these around, and they have
4503 	 * been explicitly deprecated and disallowed.
4504 	 */
4505 	cs_blob->csb_entitlements_blob = NULL;
4506 
4507 	return 0;
4508 }
4509 
4510 /**
4511  * A code signature blob often contains blob which aren't needed in the kernel. Since
4512  * the code signature is wired into kernel memory for the time it is used, it behooves
4513  * us to remove any blobs we have no need for in order to conserve memory.
4514  *
4515  * Some platforms support copying the entire SuperBlob stored in kernel memory into
4516  * userspace memory through the "csops" system call. There is an expectation that when
4517  * this happens, all the blobs which were a part of the code signature are copied in
4518  * to userspace memory. As a result, these platforms cannot reconstitute the code
4519  * signature since, or rather, these platforms cannot remove blobs from the signature,
4520  * thereby making reconstitution useless.
4521  */
4522 static errno_t
reconstitute_code_signature(struct cs_blob * cs_blob)4523 reconstitute_code_signature(
4524 	struct cs_blob *cs_blob)
4525 {
4526 	CS_CodeDirectory *code_directory = NULL;
4527 	vm_address_t signature_addr = 0;
4528 	vm_size_t signature_size = 0;
4529 	vm_offset_t code_directory_offset = 0;
4530 	bool platform_supports_reconstitution = false;
4531 
4532 #if CONFIG_CODE_SIGNATURE_RECONSTITUTION
4533 	platform_supports_reconstitution = true;
4534 #endif
4535 
4536 	/*
4537 	 * We can skip reconstitution if the code signing monitor isn't available or not
4538 	 * enabled. But if we do have a monitor, then reconsitution becomes required, as
4539 	 * there is an expectation of performing 2nd stage reconstitution through the
4540 	 * monitor itself.
4541 	 */
4542 	if (platform_supports_reconstitution == false) {
4543 #if CODE_SIGNING_MONITOR
4544 		if (csm_enabled() == true) {
4545 			printf("reconstitution required when code signing monitor is enabled\n");
4546 			return EPERM;
4547 		}
4548 #endif
4549 		return 0;
4550 	}
4551 
4552 	errno_t err = ubc_cs_reconstitute_code_signature(
4553 		cs_blob,
4554 		&signature_addr,
4555 		&signature_size,
4556 		0,
4557 		&code_directory);
4558 
4559 	if (err != 0) {
4560 		printf("unable to reconstitute code signature: %d\n", err);
4561 		return err;
4562 	}
4563 
4564 	/* Calculate the code directory offset */
4565 	code_directory_offset = (vm_offset_t)code_directory - signature_addr;
4566 
4567 	/* Reconstitution allocates new memory -- free the old one */
4568 	ubc_cs_blob_deallocate((vm_address_t)cs_blob->csb_mem_kaddr, cs_blob->csb_mem_size);
4569 
4570 	/* Reconstruct critical fields in the blob object */
4571 	ubc_cs_blob_reconstruct(
4572 		cs_blob,
4573 		signature_addr,
4574 		signature_size,
4575 		code_directory_offset);
4576 
4577 	/* Mark the object as reconstituted */
4578 	cs_blob->csb_reconstituted = true;
4579 
4580 	return 0;
4581 }
4582 
4583 int
ubc_cs_blob_add(struct vnode * vp,uint32_t platform,cpu_type_t cputype,cpu_subtype_t cpusubtype,off_t base_offset,vm_address_t * addr,vm_size_t size,struct image_params * imgp,__unused int flags,struct cs_blob ** ret_blob)4584 ubc_cs_blob_add(
4585 	struct vnode    *vp,
4586 	uint32_t        platform,
4587 	cpu_type_t      cputype,
4588 	cpu_subtype_t   cpusubtype,
4589 	off_t           base_offset,
4590 	vm_address_t    *addr,
4591 	vm_size_t       size,
4592 	struct image_params *imgp,
4593 	__unused int    flags,
4594 	struct cs_blob  **ret_blob)
4595 {
4596 	ptrauth_generic_signature_t cs_blob_sig = {0};
4597 	struct ubc_info *uip = NULL;
4598 	struct cs_blob tmp_blob = {0};
4599 	struct cs_blob *blob_ro = NULL;
4600 	struct cs_blob *oblob = NULL;
4601 	CS_CodeDirectory const *cd = NULL;
4602 	off_t blob_start_offset = 0;
4603 	off_t blob_end_offset = 0;
4604 	boolean_t record_mtime = false;
4605 	kern_return_t kr = KERN_DENIED;
4606 	errno_t error = -1;
4607 
4608 #if HAS_APPLE_PAC
4609 	void *signed_entitlements = NULL;
4610 #if CODE_SIGNING_MONITOR
4611 	void *signed_monitor_obj = NULL;
4612 #endif
4613 #endif
4614 
4615 	if (ret_blob) {
4616 		*ret_blob = NULL;
4617 	}
4618 
4619 	/*
4620 	 * Create the struct cs_blob abstract data type which will get attached to
4621 	 * the vnode object. This function also validates the structural integrity
4622 	 * of the code signature blob being passed in.
4623 	 *
4624 	 * We initialize a temporary blob whose contents are then copied into an RO
4625 	 * blob which we allocate from the read-only allocator.
4626 	 */
4627 	error = cs_blob_init_validated(addr, size, &tmp_blob, &cd);
4628 	if (error != 0) {
4629 		printf("unable to create a validated cs_blob object: %d\n", error);
4630 		return error;
4631 	}
4632 
4633 	tmp_blob.csb_cpu_type = cputype;
4634 	tmp_blob.csb_cpu_subtype = cpusubtype & ~CPU_SUBTYPE_MASK;
4635 	tmp_blob.csb_base_offset = base_offset;
4636 
4637 	/* Perform 1st stage reconstitution */
4638 	error = reconstitute_code_signature(&tmp_blob);
4639 	if (error != 0) {
4640 		goto out;
4641 	}
4642 
4643 	/*
4644 	 * There is a strong design pattern we have to follow carefully within this
4645 	 * function. Since we're storing the struct cs_blob within RO-allocated
4646 	 * memory, it is immutable to modifications from within the kernel itself.
4647 	 *
4648 	 * However, before the contents of the blob are transferred to the immutable
4649 	 * cs_blob, they are kept on the stack. In order to protect against a kernel
4650 	 * R/W attacker, we must protect this stack variable. Most importantly, any
4651 	 * code paths which can block for a while must compute a PAC signature over
4652 	 * the stack variable, then perform the blocking operation, and then ensure
4653 	 * that the PAC signature over the stack variable is still valid to ensure
4654 	 * that an attacker did not overwrite contents of the blob by introducing a
4655 	 * maliciously long blocking operation, giving them the time required to go
4656 	 * and overwrite the contents of the blob.
4657 	 *
4658 	 * The most important fields to protect here are the OSEntitlements and the
4659 	 * code signing monitor object references. For these ones, we keep around
4660 	 * extra signed pointers diversified against the read-only blobs' memory
4661 	 * and then update the stack variable with these before updating the full
4662 	 * read-only blob.
4663 	 */
4664 
4665 	blob_ro = zalloc_ro(ZONE_ID_CS_BLOB, Z_WAITOK | Z_NOFAIL);
4666 	assert(blob_ro != NULL);
4667 
4668 	tmp_blob.csb_ro_addr = blob_ro;
4669 	tmp_blob.csb_vnode = vp;
4670 
4671 	/* AMFI needs to see the current blob state at the RO address */
4672 	zalloc_ro_update_elem(ZONE_ID_CS_BLOB, blob_ro, &tmp_blob);
4673 
4674 #if CODE_SIGNING_MONITOR
4675 	error = register_code_signature_monitor(
4676 		vp,
4677 		&tmp_blob,
4678 		(vm_offset_t)tmp_blob.csb_cd - (vm_offset_t)tmp_blob.csb_mem_kaddr);
4679 
4680 	if (error != 0) {
4681 		goto out;
4682 	}
4683 
4684 #if HAS_APPLE_PAC
4685 	signed_monitor_obj = ptrauth_sign_unauthenticated(
4686 		tmp_blob.csb_csm_obj,
4687 		ptrauth_key_process_independent_data,
4688 		ptrauth_blend_discriminator(&blob_ro->csb_csm_obj,
4689 		OS_PTRAUTH_DISCRIMINATOR("cs_blob.csb_csm_obj")));
4690 #endif /* HAS_APPLE_PAC */
4691 
4692 #endif /* CODE_SIGNING_MONITOR */
4693 
4694 #if CONFIG_MACF
4695 	unsigned int cs_flags = tmp_blob.csb_flags;
4696 	unsigned int signer_type = tmp_blob.csb_signer_type;
4697 
4698 	error = mac_vnode_check_signature(
4699 		vp,
4700 		&tmp_blob,
4701 		imgp,
4702 		&cs_flags,
4703 		&signer_type,
4704 		flags,
4705 		platform);
4706 
4707 	if (error != 0) {
4708 		printf("validation of code signature failed through MACF policy: %d\n", error);
4709 		goto out;
4710 	}
4711 
4712 #if HAS_APPLE_PAC
4713 	signed_entitlements = ptrauth_sign_unauthenticated(
4714 		tmp_blob.csb_entitlements,
4715 		ptrauth_key_process_independent_data,
4716 		ptrauth_blend_discriminator(&blob_ro->csb_entitlements,
4717 		OS_PTRAUTH_DISCRIMINATOR("cs_blob.csb_entitlements")));
4718 #endif
4719 
4720 	tmp_blob.csb_flags = cs_flags;
4721 	tmp_blob.csb_signer_type = signer_type;
4722 
4723 	if (tmp_blob.csb_flags & CS_PLATFORM_BINARY) {
4724 		tmp_blob.csb_platform_binary = 1;
4725 		tmp_blob.csb_platform_path = !!(tmp_blob.csb_flags & CS_PLATFORM_PATH);
4726 		tmp_blob.csb_teamid = NULL;
4727 	} else {
4728 		tmp_blob.csb_platform_binary = 0;
4729 		tmp_blob.csb_platform_path = 0;
4730 	}
4731 
4732 	if ((flags & MAC_VNODE_CHECK_DYLD_SIM) && !tmp_blob.csb_platform_binary) {
4733 		printf("dyld simulator runtime is not apple signed: proc: %d\n",
4734 		    proc_getpid(current_proc()));
4735 
4736 		error = EPERM;
4737 		goto out;
4738 	}
4739 #endif /* CONFIG_MACF */
4740 
4741 #if CODE_SIGNING_MONITOR
4742 	error = verify_code_signature_monitor(&tmp_blob);
4743 	if (error != 0) {
4744 		goto out;
4745 	}
4746 #endif
4747 
4748 	/* Perform 2nd stage reconstitution */
4749 	error = reconstitute_code_signature_2nd_stage(&tmp_blob);
4750 	if (error != 0) {
4751 		goto out;
4752 	}
4753 
4754 	/* Setup any multi-level hashing for the code signature */
4755 	error = setup_multilevel_hashing(&tmp_blob);
4756 	if (error != 0) {
4757 		goto out;
4758 	}
4759 
4760 	/* Ensure security critical auxiliary blobs still exist */
4761 	error = validate_auxiliary_signed_blobs(&tmp_blob);
4762 	if (error != 0) {
4763 		goto out;
4764 	}
4765 
4766 	/*
4767 	 * Accelerate the entitlement queries for this code signature. This must
4768 	 * be done only after we know that the code signature pointers within the
4769 	 * struct cs_blob aren't going to be shifted around anymore, which is why
4770 	 * this acceleration is done after setting up multilevel hashing, since
4771 	 * that is the last part of signature validation which can shift the code
4772 	 * signature around.
4773 	 */
4774 	error = accelerate_entitlement_queries(&tmp_blob);
4775 	if (error != 0) {
4776 		goto out;
4777 	}
4778 
4779 	/*
4780 	 * Parse and set the Team ID for this code signature. This only needs to
4781 	 * happen when the signature isn't marked as platform. Like above, this
4782 	 * has to happen after we know the pointers within struct cs_blob aren't
4783 	 * going to be shifted anymore.
4784 	 */
4785 	if ((tmp_blob.csb_flags & CS_PLATFORM_BINARY) == 0) {
4786 		tmp_blob.csb_teamid = csblob_parse_teamid(&tmp_blob);
4787 	}
4788 
4789 	/*
4790 	 * Validate the code signing blob's coverage. Ideally, we can just do this
4791 	 * in the beginning, right after structural validation, however, multilevel
4792 	 * hashing can change some offets.
4793 	 */
4794 	blob_start_offset = tmp_blob.csb_base_offset + tmp_blob.csb_start_offset;
4795 	blob_end_offset = tmp_blob.csb_base_offset + tmp_blob.csb_end_offset;
4796 	if (blob_start_offset >= blob_end_offset) {
4797 		error = EINVAL;
4798 		goto out;
4799 	} else if (blob_start_offset < 0 || blob_end_offset <= 0) {
4800 		error = EINVAL;
4801 		goto out;
4802 	}
4803 
4804 	/*
4805 	 * The vnode_lock, linked list traversal, and marking of the memory object as
4806 	 * signed can all be blocking operations. Compute a PAC over the tmp_blob.
4807 	 */
4808 	cs_blob_sig = ptrauth_utils_sign_blob_generic(
4809 		&tmp_blob,
4810 		sizeof(tmp_blob),
4811 		OS_PTRAUTH_DISCRIMINATOR("ubc_cs_blob_add.blocking_op0"),
4812 		PTRAUTH_ADDR_DIVERSIFY);
4813 
4814 	vnode_lock(vp);
4815 	if (!UBCINFOEXISTS(vp)) {
4816 		vnode_unlock(vp);
4817 		error = ENOENT;
4818 		goto out;
4819 	}
4820 	uip = vp->v_ubcinfo;
4821 
4822 	/* check if this new blob overlaps with an existing blob */
4823 	for (oblob = ubc_get_cs_blobs(vp);
4824 	    oblob != NULL;
4825 	    oblob = oblob->csb_next) {
4826 		off_t oblob_start_offset, oblob_end_offset;
4827 
4828 		if (tmp_blob.csb_signer_type != oblob->csb_signer_type) {  // signer type needs to be the same for slices
4829 			vnode_unlock(vp);
4830 			error = EALREADY;
4831 			goto out;
4832 		} else if (tmp_blob.csb_platform_binary) {  //platform binary needs to be the same for app slices
4833 			if (!oblob->csb_platform_binary) {
4834 				vnode_unlock(vp);
4835 				error = EALREADY;
4836 				goto out;
4837 			}
4838 		} else if (tmp_blob.csb_teamid) {  //teamid binary needs to be the same for app slices
4839 			if (oblob->csb_platform_binary ||
4840 			    oblob->csb_teamid == NULL ||
4841 			    strcmp(oblob->csb_teamid, tmp_blob.csb_teamid) != 0) {
4842 				vnode_unlock(vp);
4843 				error = EALREADY;
4844 				goto out;
4845 			}
4846 		} else {  // non teamid binary needs to be the same for app slices
4847 			if (oblob->csb_platform_binary ||
4848 			    oblob->csb_teamid != NULL) {
4849 				vnode_unlock(vp);
4850 				error = EALREADY;
4851 				goto out;
4852 			}
4853 		}
4854 
4855 		oblob_start_offset = (oblob->csb_base_offset +
4856 		    oblob->csb_start_offset);
4857 		oblob_end_offset = (oblob->csb_base_offset +
4858 		    oblob->csb_end_offset);
4859 		if (blob_start_offset >= oblob_end_offset ||
4860 		    blob_end_offset <= oblob_start_offset) {
4861 			/* no conflict with this existing blob */
4862 		} else {
4863 			/* conflict ! */
4864 			if (blob_start_offset == oblob_start_offset &&
4865 			    blob_end_offset == oblob_end_offset &&
4866 			    tmp_blob.csb_mem_size == oblob->csb_mem_size &&
4867 			    tmp_blob.csb_flags == oblob->csb_flags &&
4868 			    (tmp_blob.csb_cpu_type == CPU_TYPE_ANY ||
4869 			    oblob->csb_cpu_type == CPU_TYPE_ANY ||
4870 			    tmp_blob.csb_cpu_type == oblob->csb_cpu_type) &&
4871 			    !bcmp(tmp_blob.csb_cdhash,
4872 			    oblob->csb_cdhash,
4873 			    CS_CDHASH_LEN)) {
4874 				/*
4875 				 * We already have this blob:
4876 				 * we'll return success but
4877 				 * throw away the new blob.
4878 				 */
4879 				if (oblob->csb_cpu_type == CPU_TYPE_ANY) {
4880 					/*
4881 					 * The old blob matches this one
4882 					 * but doesn't have any CPU type.
4883 					 * Update it with whatever the caller
4884 					 * provided this time.
4885 					 */
4886 					cs_blob_set_cpu_type(oblob, cputype);
4887 				}
4888 
4889 				/* The signature is still accepted, so update the
4890 				 * generation count. */
4891 				uip->cs_add_gen = cs_blob_generation_count;
4892 
4893 				vnode_unlock(vp);
4894 				if (ret_blob) {
4895 					*ret_blob = oblob;
4896 				}
4897 				error = EAGAIN;
4898 				goto out;
4899 			} else {
4900 				/* different blob: reject the new one */
4901 				vnode_unlock(vp);
4902 				error = EALREADY;
4903 				goto out;
4904 			}
4905 		}
4906 	}
4907 
4908 	/* mark this vnode's VM object as having "signed pages" */
4909 	kr = memory_object_signed(uip->ui_control, TRUE);
4910 	if (kr != KERN_SUCCESS) {
4911 		vnode_unlock(vp);
4912 		error = ENOENT;
4913 		goto out;
4914 	}
4915 
4916 	if (uip->cs_blobs == NULL) {
4917 		/* loading 1st blob: record the file's current "modify time" */
4918 		record_mtime = TRUE;
4919 	}
4920 
4921 	/* set the generation count for cs_blobs */
4922 	uip->cs_add_gen = cs_blob_generation_count;
4923 
4924 	/* Authenticate the PAC signature after blocking operation */
4925 	ptrauth_utils_auth_blob_generic(
4926 		&tmp_blob,
4927 		sizeof(tmp_blob),
4928 		OS_PTRAUTH_DISCRIMINATOR("ubc_cs_blob_add.blocking_op0"),
4929 		PTRAUTH_ADDR_DIVERSIFY,
4930 		cs_blob_sig);
4931 
4932 	/* Update the system statistics for code signatures blobs */
4933 	ubc_cs_blob_adjust_statistics(&tmp_blob);
4934 
4935 	/* Update the list pointer to reference other blobs for this vnode */
4936 	tmp_blob.csb_next = uip->cs_blobs;
4937 
4938 #if HAS_APPLE_PAC
4939 	/*
4940 	 * Update all the critical pointers in the blob with the RO diversified
4941 	 * values before updating the read-only blob with the full contents of
4942 	 * the struct cs_blob. We need to use memcpy here as otherwise a simple
4943 	 * assignment will cause the compiler to re-sign using the stack variable
4944 	 * as the address diversifier.
4945 	 */
4946 	memcpy((void*)&tmp_blob.csb_entitlements, &signed_entitlements, sizeof(void*));
4947 #if CODE_SIGNING_MONITOR
4948 	memcpy((void*)&tmp_blob.csb_csm_obj, &signed_monitor_obj, sizeof(void*));
4949 #endif
4950 #endif
4951 	zalloc_ro_update_elem(ZONE_ID_CS_BLOB, blob_ro, &tmp_blob);
4952 
4953 	/* Add a fence to ensure writes to the blob are visible on all threads */
4954 	os_atomic_thread_fence(seq_cst);
4955 
4956 	/*
4957 	 * Add the cs_blob to the front of the list of blobs for this vnode. We
4958 	 * add to the front of the list, and we never remove a blob from the list
4959 	 * which means ubc_cs_get_blobs can return whatever the top of the list
4960 	 * is, while still keeping the list valid. Useful for if we validate a
4961 	 * page while adding in a new blob for this vnode.
4962 	 */
4963 	uip->cs_blobs = blob_ro;
4964 
4965 	/* Make sure to reload pointer from uip to double check */
4966 	if (uip->cs_blobs->csb_next) {
4967 		zone_require_ro(ZONE_ID_CS_BLOB, sizeof(struct cs_blob), uip->cs_blobs->csb_next);
4968 	}
4969 
4970 	if (cs_debug > 1) {
4971 		proc_t p;
4972 		const char *name = vnode_getname_printable(vp);
4973 		p = current_proc();
4974 		printf("CODE SIGNING: proc %d(%s) "
4975 		    "loaded %s signatures for file (%s) "
4976 		    "range 0x%llx:0x%llx flags 0x%x\n",
4977 		    proc_getpid(p), p->p_comm,
4978 		    blob_ro->csb_cpu_type == -1 ? "detached" : "embedded",
4979 		    name,
4980 		    blob_ro->csb_base_offset + blob_ro->csb_start_offset,
4981 		    blob_ro->csb_base_offset + blob_ro->csb_end_offset,
4982 		    blob_ro->csb_flags);
4983 		vnode_putname_printable(name);
4984 	}
4985 
4986 	vnode_unlock(vp);
4987 
4988 	if (record_mtime) {
4989 		vnode_mtime(vp, &uip->cs_mtime, vfs_context_current());
4990 	}
4991 
4992 	if (ret_blob) {
4993 		*ret_blob = blob_ro;
4994 	}
4995 
4996 	error = 0;      /* success ! */
4997 
4998 out:
4999 	if (error) {
5000 		if (error != EAGAIN) {
5001 			printf("check_signature[pid: %d]: error = %d\n", proc_getpid(current_proc()), error);
5002 		}
5003 
5004 		cs_blob_cleanup(&tmp_blob);
5005 		if (blob_ro) {
5006 			zfree_ro(ZONE_ID_CS_BLOB, blob_ro);
5007 		}
5008 	}
5009 
5010 	if (error == EAGAIN) {
5011 		/*
5012 		 * See above:  error is EAGAIN if we were asked
5013 		 * to add an existing blob again.  We cleaned the new
5014 		 * blob and we want to return success.
5015 		 */
5016 		error = 0;
5017 	}
5018 
5019 	return error;
5020 }
5021 
5022 #if CONFIG_SUPPLEMENTAL_SIGNATURES
5023 int
ubc_cs_blob_add_supplement(struct vnode * vp,struct vnode * orig_vp,off_t base_offset,vm_address_t * addr,vm_size_t size,struct cs_blob ** ret_blob)5024 ubc_cs_blob_add_supplement(
5025 	struct vnode    *vp,
5026 	struct vnode    *orig_vp,
5027 	off_t           base_offset,
5028 	vm_address_t    *addr,
5029 	vm_size_t       size,
5030 	struct cs_blob  **ret_blob)
5031 {
5032 	kern_return_t           kr;
5033 	struct ubc_info         *uip, *orig_uip;
5034 	int                     error;
5035 	struct cs_blob          tmp_blob;
5036 	struct cs_blob          *orig_blob;
5037 	struct cs_blob          *blob_ro = NULL;
5038 	CS_CodeDirectory const *cd;
5039 	off_t                   blob_start_offset, blob_end_offset;
5040 
5041 	if (ret_blob) {
5042 		*ret_blob = NULL;
5043 	}
5044 
5045 	/* Create the struct cs_blob wrapper that will be attached to the vnode.
5046 	 * Validates the passed in blob in the process. */
5047 	error = cs_blob_init_validated(addr, size, &tmp_blob, &cd);
5048 
5049 	if (error != 0) {
5050 		printf("malformed code signature supplement blob: %d\n", error);
5051 		return error;
5052 	}
5053 
5054 	tmp_blob.csb_cpu_type = -1;
5055 	tmp_blob.csb_base_offset = base_offset;
5056 
5057 	tmp_blob.csb_reconstituted = false;
5058 
5059 	vnode_lock(orig_vp);
5060 	if (!UBCINFOEXISTS(orig_vp)) {
5061 		vnode_unlock(orig_vp);
5062 		error = ENOENT;
5063 		goto out;
5064 	}
5065 
5066 	orig_uip = orig_vp->v_ubcinfo;
5067 
5068 	/* check that the supplement's linked cdhash matches a cdhash of
5069 	 * the target image.
5070 	 */
5071 
5072 	if (tmp_blob.csb_linkage_hashtype == NULL) {
5073 		proc_t p;
5074 		const char *iname = vnode_getname_printable(vp);
5075 		p = current_proc();
5076 
5077 		printf("CODE SIGNING: proc %d(%s) supplemental signature for file (%s) "
5078 		    "is not a supplemental.\n",
5079 		    proc_getpid(p), p->p_comm, iname);
5080 
5081 		error = EINVAL;
5082 
5083 		vnode_putname_printable(iname);
5084 		vnode_unlock(orig_vp);
5085 		goto out;
5086 	}
5087 	bool found_but_not_valid = false;
5088 	for (orig_blob = ubc_get_cs_blobs(orig_vp); orig_blob != NULL;
5089 	    orig_blob = orig_blob->csb_next) {
5090 		if (orig_blob->csb_hashtype == tmp_blob.csb_linkage_hashtype &&
5091 		    memcmp(orig_blob->csb_cdhash, tmp_blob.csb_linkage, CS_CDHASH_LEN) == 0) {
5092 			// Found match!
5093 			found_but_not_valid = ((orig_blob->csb_flags & CS_VALID) != CS_VALID);
5094 			break;
5095 		}
5096 	}
5097 
5098 	if (orig_blob == NULL || found_but_not_valid) {
5099 		// Not found.
5100 
5101 		proc_t p;
5102 		const char *iname = vnode_getname_printable(vp);
5103 		p = current_proc();
5104 
5105 		error = (orig_blob == NULL) ? ESRCH : EPERM;
5106 
5107 		printf("CODE SIGNING: proc %d(%s) supplemental signature for file (%s) "
5108 		    "does not match any attached cdhash (error: %d).\n",
5109 		    proc_getpid(p), p->p_comm, iname, error);
5110 
5111 		vnode_putname_printable(iname);
5112 		vnode_unlock(orig_vp);
5113 		goto out;
5114 	}
5115 
5116 	vnode_unlock(orig_vp);
5117 
5118 	blob_ro = zalloc_ro(ZONE_ID_CS_BLOB, Z_WAITOK | Z_NOFAIL);
5119 	tmp_blob.csb_ro_addr = blob_ro;
5120 	tmp_blob.csb_vnode = vp;
5121 
5122 	/* AMFI needs to see the current blob state at the RO address. */
5123 	zalloc_ro_update_elem(ZONE_ID_CS_BLOB, blob_ro, &tmp_blob);
5124 
5125 	// validate the signature against policy!
5126 #if CONFIG_MACF
5127 	unsigned int signer_type = tmp_blob.csb_signer_type;
5128 	error = mac_vnode_check_supplemental_signature(vp, &tmp_blob, orig_vp, orig_blob, &signer_type);
5129 
5130 	tmp_blob.csb_signer_type = signer_type;
5131 
5132 	if (error) {
5133 		if (cs_debug) {
5134 			printf("check_supplemental_signature[pid: %d], error = %d\n", proc_getpid(current_proc()), error);
5135 		}
5136 		goto out;
5137 	}
5138 #endif
5139 
5140 	// We allowed the supplemental signature blob so
5141 	// copy the platform bit or team-id from the linked signature and whether or not the original is developer code
5142 	tmp_blob.csb_platform_binary = 0;
5143 	tmp_blob.csb_platform_path = 0;
5144 	if (orig_blob->csb_platform_binary == 1) {
5145 		tmp_blob.csb_platform_binary = orig_blob->csb_platform_binary;
5146 		tmp_blob.csb_platform_path = orig_blob->csb_platform_path;
5147 	} else if (orig_blob->csb_teamid != NULL) {
5148 		vm_size_t teamid_size = strlen(orig_blob->csb_teamid) + 1;
5149 		tmp_blob.csb_supplement_teamid = kalloc_data(teamid_size, Z_WAITOK);
5150 		if (tmp_blob.csb_supplement_teamid == NULL) {
5151 			error = ENOMEM;
5152 			goto out;
5153 		}
5154 		strlcpy(tmp_blob.csb_supplement_teamid, orig_blob->csb_teamid, teamid_size);
5155 	}
5156 	tmp_blob.csb_flags = (orig_blob->csb_flags & CS_DEV_CODE);
5157 
5158 	// Validate the blob's coverage
5159 	blob_start_offset = tmp_blob.csb_base_offset + tmp_blob.csb_start_offset;
5160 	blob_end_offset = tmp_blob.csb_base_offset + tmp_blob.csb_end_offset;
5161 
5162 	if (blob_start_offset >= blob_end_offset || blob_start_offset < 0 || blob_end_offset <= 0) {
5163 		/* reject empty or backwards blob */
5164 		error = EINVAL;
5165 		goto out;
5166 	}
5167 
5168 	vnode_lock(vp);
5169 	if (!UBCINFOEXISTS(vp)) {
5170 		vnode_unlock(vp);
5171 		error = ENOENT;
5172 		goto out;
5173 	}
5174 	uip = vp->v_ubcinfo;
5175 
5176 	struct cs_blob *existing = uip->cs_blob_supplement;
5177 	if (existing != NULL) {
5178 		if (tmp_blob.csb_hashtype == existing->csb_hashtype &&
5179 		    memcmp(tmp_blob.csb_cdhash, existing->csb_cdhash, CS_CDHASH_LEN) == 0) {
5180 			error = EAGAIN; // non-fatal
5181 		} else {
5182 			error = EALREADY; // fatal
5183 		}
5184 
5185 		vnode_unlock(vp);
5186 		goto out;
5187 	}
5188 
5189 	/* mark this vnode's VM object as having "signed pages" */
5190 	kr = memory_object_signed(uip->ui_control, TRUE);
5191 	if (kr != KERN_SUCCESS) {
5192 		vnode_unlock(vp);
5193 		error = ENOENT;
5194 		goto out;
5195 	}
5196 
5197 
5198 	/* We still adjust statistics even for supplemental blobs, as they
5199 	 * consume memory just the same. */
5200 	ubc_cs_blob_adjust_statistics(&tmp_blob);
5201 	/* Unlike regular cs_blobs, we only ever support one supplement. */
5202 	tmp_blob.csb_next = NULL;
5203 	zalloc_ro_update_elem(ZONE_ID_CS_BLOB, blob_ro, &tmp_blob);
5204 
5205 	os_atomic_thread_fence(seq_cst); // Fence to prevent reordering here
5206 	uip->cs_blob_supplement = blob_ro;
5207 
5208 	/* Make sure to reload pointer from uip to double check */
5209 	if (__improbable(uip->cs_blob_supplement->csb_next)) {
5210 		panic("csb_next does not match expected NULL value");
5211 	}
5212 
5213 	vnode_unlock(vp);
5214 
5215 
5216 	if (cs_debug > 1) {
5217 		proc_t p;
5218 		const char *name = vnode_getname_printable(vp);
5219 		p = current_proc();
5220 		printf("CODE SIGNING: proc %d(%s) "
5221 		    "loaded supplemental signature for file (%s) "
5222 		    "range 0x%llx:0x%llx\n",
5223 		    proc_getpid(p), p->p_comm,
5224 		    name,
5225 		    blob_ro->csb_base_offset + blob_ro->csb_start_offset,
5226 		    blob_ro->csb_base_offset + blob_ro->csb_end_offset);
5227 		vnode_putname_printable(name);
5228 	}
5229 
5230 	if (ret_blob) {
5231 		*ret_blob = blob_ro;
5232 	}
5233 
5234 	error = 0; // Success!
5235 out:
5236 	if (error) {
5237 		if (cs_debug) {
5238 			printf("ubc_cs_blob_add_supplement[pid: %d]: error = %d\n", proc_getpid(current_proc()), error);
5239 		}
5240 
5241 		cs_blob_cleanup(&tmp_blob);
5242 		if (blob_ro) {
5243 			zfree_ro(ZONE_ID_CS_BLOB, blob_ro);
5244 		}
5245 	}
5246 
5247 	if (error == EAGAIN) {
5248 		/* We were asked to add an existing blob.
5249 		 * We cleaned up and ignore the attempt. */
5250 		error = 0;
5251 	}
5252 
5253 	return error;
5254 }
5255 #endif
5256 
5257 
5258 
5259 void
csvnode_print_debug(struct vnode * vp)5260 csvnode_print_debug(struct vnode *vp)
5261 {
5262 	const char      *name = NULL;
5263 	struct ubc_info *uip;
5264 	struct cs_blob *blob;
5265 
5266 	name = vnode_getname_printable(vp);
5267 	if (name) {
5268 		printf("csvnode: name: %s\n", name);
5269 		vnode_putname_printable(name);
5270 	}
5271 
5272 	vnode_lock_spin(vp);
5273 
5274 	if (!UBCINFOEXISTS(vp)) {
5275 		blob = NULL;
5276 		goto out;
5277 	}
5278 
5279 	uip = vp->v_ubcinfo;
5280 	for (blob = uip->cs_blobs; blob != NULL; blob = blob->csb_next) {
5281 		printf("csvnode: range: %lu -> %lu flags: 0x%08x platform: %s path: %s team: %s\n",
5282 		    (unsigned long)blob->csb_start_offset,
5283 		    (unsigned long)blob->csb_end_offset,
5284 		    blob->csb_flags,
5285 		    blob->csb_platform_binary ? "yes" : "no",
5286 		    blob->csb_platform_path ? "yes" : "no",
5287 		    blob->csb_teamid ? blob->csb_teamid : "<NO-TEAM>");
5288 	}
5289 
5290 out:
5291 	vnode_unlock(vp);
5292 }
5293 
5294 #if CONFIG_SUPPLEMENTAL_SIGNATURES
5295 struct cs_blob *
ubc_cs_blob_get_supplement(struct vnode * vp,off_t offset)5296 ubc_cs_blob_get_supplement(
5297 	struct vnode    *vp,
5298 	off_t           offset)
5299 {
5300 	struct cs_blob *blob;
5301 	off_t offset_in_blob;
5302 
5303 	vnode_lock_spin(vp);
5304 
5305 	if (!UBCINFOEXISTS(vp)) {
5306 		blob = NULL;
5307 		goto out;
5308 	}
5309 
5310 	blob = vp->v_ubcinfo->cs_blob_supplement;
5311 
5312 	if (blob == NULL) {
5313 		// no supplemental blob
5314 		goto out;
5315 	}
5316 
5317 
5318 	if (offset != -1) {
5319 		offset_in_blob = offset - blob->csb_base_offset;
5320 		if (offset_in_blob < blob->csb_start_offset || offset_in_blob >= blob->csb_end_offset) {
5321 			// not actually covered by this blob
5322 			blob = NULL;
5323 		}
5324 	}
5325 
5326 out:
5327 	vnode_unlock(vp);
5328 
5329 	return blob;
5330 }
5331 #endif
5332 
5333 struct cs_blob *
ubc_cs_blob_get(struct vnode * vp,cpu_type_t cputype,cpu_subtype_t cpusubtype,off_t offset)5334 ubc_cs_blob_get(
5335 	struct vnode    *vp,
5336 	cpu_type_t      cputype,
5337 	cpu_subtype_t   cpusubtype,
5338 	off_t           offset)
5339 {
5340 	struct cs_blob  *blob;
5341 	off_t offset_in_blob;
5342 
5343 	vnode_lock_spin(vp);
5344 
5345 	if (!UBCINFOEXISTS(vp)) {
5346 		blob = NULL;
5347 		goto out;
5348 	}
5349 
5350 	for (blob = ubc_get_cs_blobs(vp);
5351 	    blob != NULL;
5352 	    blob = blob->csb_next) {
5353 		if (cputype != -1 && blob->csb_cpu_type == cputype && (cpusubtype == -1 || blob->csb_cpu_subtype == (cpusubtype & ~CPU_SUBTYPE_MASK))) {
5354 			break;
5355 		}
5356 		if (offset != -1) {
5357 			offset_in_blob = offset - blob->csb_base_offset;
5358 			if (offset_in_blob >= blob->csb_start_offset &&
5359 			    offset_in_blob < blob->csb_end_offset) {
5360 				/* our offset is covered by this blob */
5361 				break;
5362 			}
5363 		}
5364 	}
5365 
5366 out:
5367 	vnode_unlock(vp);
5368 
5369 	return blob;
5370 }
5371 
5372 void
ubc_cs_free_and_vnode_unlock(vnode_t vp)5373 ubc_cs_free_and_vnode_unlock(
5374 	vnode_t vp)
5375 {
5376 	struct ubc_info *uip = vp->v_ubcinfo;
5377 	struct cs_blob  *cs_blobs, *blob, *next_blob;
5378 
5379 	if (!(uip->ui_flags & UI_CSBLOBINVALID)) {
5380 		vnode_unlock(vp);
5381 		return;
5382 	}
5383 
5384 	uip->ui_flags &= ~UI_CSBLOBINVALID;
5385 
5386 	cs_blobs = uip->cs_blobs;
5387 	uip->cs_blobs = NULL;
5388 
5389 #if CHECK_CS_VALIDATION_BITMAP
5390 	ubc_cs_validation_bitmap_deallocate( uip );
5391 #endif
5392 
5393 #if CONFIG_SUPPLEMENTAL_SIGNATURES
5394 	struct cs_blob  *cs_blob_supplement = uip->cs_blob_supplement;
5395 	uip->cs_blob_supplement = NULL;
5396 #endif
5397 
5398 	vnode_unlock(vp);
5399 
5400 	for (blob = cs_blobs;
5401 	    blob != NULL;
5402 	    blob = next_blob) {
5403 		next_blob = blob->csb_next;
5404 		os_atomic_add(&cs_blob_count, -1, relaxed);
5405 		os_atomic_add(&cs_blob_size, -blob->csb_mem_size, relaxed);
5406 		cs_blob_ro_free(blob);
5407 	}
5408 
5409 #if CONFIG_SUPPLEMENTAL_SIGNATURES
5410 	if (cs_blob_supplement != NULL) {
5411 		os_atomic_add(&cs_blob_count, -1, relaxed);
5412 		os_atomic_add(&cs_blob_size, -cs_blob_supplement->csb_mem_size, relaxed);
5413 		cs_blob_supplement_free(cs_blob_supplement);
5414 	}
5415 #endif
5416 }
5417 
5418 static void
ubc_cs_free(struct ubc_info * uip)5419 ubc_cs_free(
5420 	struct ubc_info *uip)
5421 {
5422 	struct cs_blob  *blob, *next_blob;
5423 
5424 	for (blob = uip->cs_blobs;
5425 	    blob != NULL;
5426 	    blob = next_blob) {
5427 		next_blob = blob->csb_next;
5428 		os_atomic_add(&cs_blob_count, -1, relaxed);
5429 		os_atomic_add(&cs_blob_size, -blob->csb_mem_size, relaxed);
5430 		cs_blob_ro_free(blob);
5431 	}
5432 #if CHECK_CS_VALIDATION_BITMAP
5433 	ubc_cs_validation_bitmap_deallocate( uip );
5434 #endif
5435 	uip->cs_blobs = NULL;
5436 #if CONFIG_SUPPLEMENTAL_SIGNATURES
5437 	if (uip->cs_blob_supplement != NULL) {
5438 		blob = uip->cs_blob_supplement;
5439 		os_atomic_add(&cs_blob_count, -1, relaxed);
5440 		os_atomic_add(&cs_blob_size, -blob->csb_mem_size, relaxed);
5441 		cs_blob_supplement_free(uip->cs_blob_supplement);
5442 		uip->cs_blob_supplement = NULL;
5443 	}
5444 #endif
5445 }
5446 
5447 /* check cs blob generation on vnode
5448  * returns:
5449  *    0         : Success, the cs_blob attached is current
5450  *    ENEEDAUTH : Generation count mismatch. Needs authentication again.
5451  */
5452 int
ubc_cs_generation_check(struct vnode * vp)5453 ubc_cs_generation_check(
5454 	struct vnode    *vp)
5455 {
5456 	int retval = ENEEDAUTH;
5457 
5458 	vnode_lock_spin(vp);
5459 
5460 	if (UBCINFOEXISTS(vp) && vp->v_ubcinfo->cs_add_gen == cs_blob_generation_count) {
5461 		retval = 0;
5462 	}
5463 
5464 	vnode_unlock(vp);
5465 	return retval;
5466 }
5467 
5468 int
ubc_cs_blob_revalidate(struct vnode * vp,struct cs_blob * blob,struct image_params * imgp,int flags,uint32_t platform)5469 ubc_cs_blob_revalidate(
5470 	struct vnode    *vp,
5471 	struct cs_blob *blob,
5472 	struct image_params *imgp,
5473 	int flags,
5474 	uint32_t platform
5475 	)
5476 {
5477 	int error = 0;
5478 	const CS_CodeDirectory *cd = NULL;
5479 	const CS_GenericBlob *entitlements = NULL;
5480 	const CS_GenericBlob *der_entitlements = NULL;
5481 	size_t size;
5482 	assert(vp != NULL);
5483 	assert(blob != NULL);
5484 
5485 	if ((blob->csb_flags & CS_VALID) == 0) {
5486 		// If the blob attached to the vnode was invalidated, don't try to revalidate it
5487 		// Blob invalidation only occurs when the file that the blob is attached to is
5488 		// opened for writing, giving us a signal that the file is modified.
5489 		printf("CODESIGNING: can not re-validate a previously invalidated blob, reboot or create a new file.\n");
5490 		error = EPERM;
5491 		goto out;
5492 	}
5493 
5494 	size = blob->csb_mem_size;
5495 	error = cs_validate_csblob((const uint8_t *)blob->csb_mem_kaddr,
5496 	    size, &cd, &entitlements, &der_entitlements);
5497 	if (error) {
5498 		if (cs_debug) {
5499 			printf("CODESIGNING: csblob invalid: %d\n", error);
5500 		}
5501 		goto out;
5502 	}
5503 
5504 	unsigned int cs_flags = (ntohl(cd->flags) & CS_ALLOWED_MACHO) | CS_VALID;
5505 	unsigned int signer_type = CS_SIGNER_TYPE_UNKNOWN;
5506 
5507 	if (blob->csb_reconstituted) {
5508 		/*
5509 		 * Code signatures that have been modified after validation
5510 		 * cannot be revalidated inline from their in-memory blob.
5511 		 *
5512 		 * That's okay, though, because the only path left that relies
5513 		 * on revalidation of existing in-memory blobs is the legacy
5514 		 * detached signature database path, which only exists on macOS,
5515 		 * which does not do reconstitution of any kind.
5516 		 */
5517 		if (cs_debug) {
5518 			printf("CODESIGNING: revalidate: not inline revalidating reconstituted signature.\n");
5519 		}
5520 
5521 		/*
5522 		 * EAGAIN tells the caller that they may reread the code
5523 		 * signature and try attaching it again, which is the same
5524 		 * thing they would do if there was no cs_blob yet in the
5525 		 * first place.
5526 		 *
5527 		 * Conveniently, after ubc_cs_blob_add did a successful
5528 		 * validation, it will detect that a matching cs_blob (cdhash,
5529 		 * offset, arch etc.) already exists, and return success
5530 		 * without re-adding a cs_blob to the vnode.
5531 		 */
5532 		return EAGAIN;
5533 	}
5534 
5535 	/* callout to mac_vnode_check_signature */
5536 #if CONFIG_MACF
5537 	error = mac_vnode_check_signature(vp, blob, imgp, &cs_flags, &signer_type, flags, platform);
5538 	if (cs_debug && error) {
5539 		printf("revalidate: check_signature[pid: %d], error = %d\n", proc_getpid(current_proc()), error);
5540 	}
5541 #else
5542 	(void)flags;
5543 	(void)signer_type;
5544 #endif
5545 
5546 	/* update generation number if success */
5547 	vnode_lock_spin(vp);
5548 	struct cs_signer_info signer_info = {
5549 		.csb_flags = cs_flags,
5550 		.csb_signer_type = signer_type
5551 	};
5552 	zalloc_ro_update_field(ZONE_ID_CS_BLOB, blob, csb_signer_info, &signer_info);
5553 	if (UBCINFOEXISTS(vp)) {
5554 		if (error == 0) {
5555 			vp->v_ubcinfo->cs_add_gen = cs_blob_generation_count;
5556 		} else {
5557 			vp->v_ubcinfo->cs_add_gen = 0;
5558 		}
5559 	}
5560 
5561 	vnode_unlock(vp);
5562 
5563 out:
5564 	return error;
5565 }
5566 
5567 void
cs_blob_reset_cache()5568 cs_blob_reset_cache()
5569 {
5570 	/* incrementing odd no by 2 makes sure '0' is never reached. */
5571 	OSAddAtomic(+2, &cs_blob_generation_count);
5572 	printf("Reseting cs_blob cache from all vnodes. \n");
5573 }
5574 
5575 struct cs_blob *
ubc_get_cs_blobs(struct vnode * vp)5576 ubc_get_cs_blobs(
5577 	struct vnode    *vp)
5578 {
5579 	struct ubc_info *uip;
5580 	struct cs_blob  *blobs;
5581 
5582 	/*
5583 	 * No need to take the vnode lock here.  The caller must be holding
5584 	 * a reference on the vnode (via a VM mapping or open file descriptor),
5585 	 * so the vnode will not go away.  The ubc_info stays until the vnode
5586 	 * goes away.  And we only modify "blobs" by adding to the head of the
5587 	 * list.
5588 	 * The ubc_info could go away entirely if the vnode gets reclaimed as
5589 	 * part of a forced unmount.  In the case of a code-signature validation
5590 	 * during a page fault, the "paging_in_progress" reference on the VM
5591 	 * object guarantess that the vnode pager (and the ubc_info) won't go
5592 	 * away during the fault.
5593 	 * Other callers need to protect against vnode reclaim by holding the
5594 	 * vnode lock, for example.
5595 	 */
5596 
5597 	if (!UBCINFOEXISTS(vp)) {
5598 		blobs = NULL;
5599 		goto out;
5600 	}
5601 
5602 	uip = vp->v_ubcinfo;
5603 	blobs = uip->cs_blobs;
5604 	if (blobs != NULL) {
5605 		cs_blob_require(blobs, vp);
5606 	}
5607 
5608 out:
5609 	return blobs;
5610 }
5611 
5612 #if CONFIG_SUPPLEMENTAL_SIGNATURES
5613 struct cs_blob *
ubc_get_cs_supplement(struct vnode * vp)5614 ubc_get_cs_supplement(
5615 	struct vnode    *vp)
5616 {
5617 	struct ubc_info *uip;
5618 	struct cs_blob  *blob;
5619 
5620 	/*
5621 	 * No need to take the vnode lock here.  The caller must be holding
5622 	 * a reference on the vnode (via a VM mapping or open file descriptor),
5623 	 * so the vnode will not go away.  The ubc_info stays until the vnode
5624 	 * goes away.
5625 	 * The ubc_info could go away entirely if the vnode gets reclaimed as
5626 	 * part of a forced unmount.  In the case of a code-signature validation
5627 	 * during a page fault, the "paging_in_progress" reference on the VM
5628 	 * object guarantess that the vnode pager (and the ubc_info) won't go
5629 	 * away during the fault.
5630 	 * Other callers need to protect against vnode reclaim by holding the
5631 	 * vnode lock, for example.
5632 	 */
5633 
5634 	if (!UBCINFOEXISTS(vp)) {
5635 		blob = NULL;
5636 		goto out;
5637 	}
5638 
5639 	uip = vp->v_ubcinfo;
5640 	blob = uip->cs_blob_supplement;
5641 	if (blob != NULL) {
5642 		cs_blob_require(blob, vp);
5643 	}
5644 
5645 out:
5646 	return blob;
5647 }
5648 #endif
5649 
5650 
5651 void
ubc_get_cs_mtime(struct vnode * vp,struct timespec * cs_mtime)5652 ubc_get_cs_mtime(
5653 	struct vnode    *vp,
5654 	struct timespec *cs_mtime)
5655 {
5656 	struct ubc_info *uip;
5657 
5658 	if (!UBCINFOEXISTS(vp)) {
5659 		cs_mtime->tv_sec = 0;
5660 		cs_mtime->tv_nsec = 0;
5661 		return;
5662 	}
5663 
5664 	uip = vp->v_ubcinfo;
5665 	cs_mtime->tv_sec = uip->cs_mtime.tv_sec;
5666 	cs_mtime->tv_nsec = uip->cs_mtime.tv_nsec;
5667 }
5668 
5669 unsigned long cs_validate_page_no_hash = 0;
5670 unsigned long cs_validate_page_bad_hash = 0;
5671 static boolean_t
cs_validate_hash(struct cs_blob * blobs,memory_object_t pager,memory_object_offset_t page_offset,const void * data,vm_size_t * bytes_processed,unsigned * tainted)5672 cs_validate_hash(
5673 	struct cs_blob          *blobs,
5674 	memory_object_t         pager,
5675 	memory_object_offset_t  page_offset,
5676 	const void              *data,
5677 	vm_size_t               *bytes_processed,
5678 	unsigned                *tainted)
5679 {
5680 	union cs_hash_union     mdctx;
5681 	struct cs_hash const    *hashtype = NULL;
5682 	unsigned char           actual_hash[CS_HASH_MAX_SIZE];
5683 	unsigned char           expected_hash[CS_HASH_MAX_SIZE];
5684 	boolean_t               found_hash;
5685 	struct cs_blob          *blob;
5686 	const CS_CodeDirectory  *cd;
5687 	const unsigned char     *hash;
5688 	boolean_t               validated;
5689 	off_t                   offset; /* page offset in the file */
5690 	size_t                  size;
5691 	off_t                   codeLimit = 0;
5692 	const char              *lower_bound, *upper_bound;
5693 	vm_offset_t             kaddr, blob_addr;
5694 
5695 	/* retrieve the expected hash */
5696 	found_hash = FALSE;
5697 
5698 	for (blob = blobs;
5699 	    blob != NULL;
5700 	    blob = blob->csb_next) {
5701 		offset = page_offset - blob->csb_base_offset;
5702 		if (offset < blob->csb_start_offset ||
5703 		    offset >= blob->csb_end_offset) {
5704 			/* our page is not covered by this blob */
5705 			continue;
5706 		}
5707 
5708 		/* blob data has been released */
5709 		kaddr = (vm_offset_t)blob->csb_mem_kaddr;
5710 		if (kaddr == 0) {
5711 			continue;
5712 		}
5713 
5714 		blob_addr = kaddr + blob->csb_mem_offset;
5715 		lower_bound = CAST_DOWN(char *, blob_addr);
5716 		upper_bound = lower_bound + blob->csb_mem_size;
5717 
5718 		cd = blob->csb_cd;
5719 		if (cd != NULL) {
5720 			/* all CD's that have been injected is already validated */
5721 
5722 			hashtype = blob->csb_hashtype;
5723 			if (hashtype == NULL) {
5724 				panic("unknown hash type ?");
5725 			}
5726 			if (hashtype->cs_digest_size > sizeof(actual_hash)) {
5727 				panic("hash size too large");
5728 			}
5729 			if (offset & ((1U << blob->csb_hash_pageshift) - 1)) {
5730 				panic("offset not aligned to cshash boundary");
5731 			}
5732 
5733 			codeLimit = ntohl(cd->codeLimit);
5734 
5735 			hash = hashes(cd, (uint32_t)(offset >> blob->csb_hash_pageshift),
5736 			    hashtype->cs_size,
5737 			    lower_bound, upper_bound);
5738 			if (hash != NULL) {
5739 				bcopy(hash, expected_hash, hashtype->cs_size);
5740 				found_hash = TRUE;
5741 			}
5742 
5743 			break;
5744 		}
5745 	}
5746 
5747 	if (found_hash == FALSE) {
5748 		/*
5749 		 * We can't verify this page because there is no signature
5750 		 * for it (yet).  It's possible that this part of the object
5751 		 * is not signed, or that signatures for that part have not
5752 		 * been loaded yet.
5753 		 * Report that the page has not been validated and let the
5754 		 * caller decide if it wants to accept it or not.
5755 		 */
5756 		cs_validate_page_no_hash++;
5757 		if (cs_debug > 1) {
5758 			printf("CODE SIGNING: cs_validate_page: "
5759 			    "mobj %p off 0x%llx: no hash to validate !?\n",
5760 			    pager, page_offset);
5761 		}
5762 		validated = FALSE;
5763 		*tainted = 0;
5764 	} else {
5765 		*tainted = 0;
5766 
5767 		size = (1U << blob->csb_hash_pageshift);
5768 		*bytes_processed = size;
5769 
5770 		const uint32_t *asha1, *esha1;
5771 		if ((off_t)(offset + size) > codeLimit) {
5772 			/* partial page at end of segment */
5773 			assert(offset < codeLimit);
5774 			size = (size_t) (codeLimit & (size - 1));
5775 			*tainted |= CS_VALIDATE_NX;
5776 		}
5777 
5778 		hashtype->cs_init(&mdctx);
5779 
5780 		if (blob->csb_hash_firstlevel_pageshift) {
5781 			const unsigned char *partial_data = (const unsigned char *)data;
5782 			size_t i;
5783 			for (i = 0; i < size;) {
5784 				union cs_hash_union     partialctx;
5785 				unsigned char partial_digest[CS_HASH_MAX_SIZE];
5786 				size_t partial_size = MIN(size - i, (1U << blob->csb_hash_firstlevel_pageshift));
5787 
5788 				hashtype->cs_init(&partialctx);
5789 				hashtype->cs_update(&partialctx, partial_data, partial_size);
5790 				hashtype->cs_final(partial_digest, &partialctx);
5791 
5792 				/* Update cumulative multi-level hash */
5793 				hashtype->cs_update(&mdctx, partial_digest, hashtype->cs_size);
5794 				partial_data = partial_data + partial_size;
5795 				i += partial_size;
5796 			}
5797 		} else {
5798 			hashtype->cs_update(&mdctx, data, size);
5799 		}
5800 		hashtype->cs_final(actual_hash, &mdctx);
5801 
5802 		asha1 = (const uint32_t *) actual_hash;
5803 		esha1 = (const uint32_t *) expected_hash;
5804 
5805 		if (bcmp(expected_hash, actual_hash, hashtype->cs_size) != 0) {
5806 			if (cs_debug) {
5807 				printf("CODE SIGNING: cs_validate_page: "
5808 				    "mobj %p off 0x%llx size 0x%lx: "
5809 				    "actual [0x%x 0x%x 0x%x 0x%x 0x%x] != "
5810 				    "expected [0x%x 0x%x 0x%x 0x%x 0x%x]\n",
5811 				    pager, page_offset, size,
5812 				    asha1[0], asha1[1], asha1[2],
5813 				    asha1[3], asha1[4],
5814 				    esha1[0], esha1[1], esha1[2],
5815 				    esha1[3], esha1[4]);
5816 			}
5817 			cs_validate_page_bad_hash++;
5818 			*tainted |= CS_VALIDATE_TAINTED;
5819 		} else {
5820 			if (cs_debug > 10) {
5821 				printf("CODE SIGNING: cs_validate_page: "
5822 				    "mobj %p off 0x%llx size 0x%lx: "
5823 				    "SHA1 OK\n",
5824 				    pager, page_offset, size);
5825 			}
5826 		}
5827 		validated = TRUE;
5828 	}
5829 
5830 	return validated;
5831 }
5832 
5833 boolean_t
cs_validate_range(struct vnode * vp,memory_object_t pager,memory_object_offset_t page_offset,const void * data,vm_size_t dsize,unsigned * tainted)5834 cs_validate_range(
5835 	struct vnode    *vp,
5836 	memory_object_t         pager,
5837 	memory_object_offset_t  page_offset,
5838 	const void              *data,
5839 	vm_size_t               dsize,
5840 	unsigned                *tainted)
5841 {
5842 	vm_size_t offset_in_range;
5843 	boolean_t all_subranges_validated = TRUE; /* turn false if any subrange fails */
5844 
5845 	struct cs_blob *blobs = ubc_get_cs_blobs(vp);
5846 
5847 #if CONFIG_SUPPLEMENTAL_SIGNATURES
5848 	if (blobs == NULL && proc_is_translated(current_proc())) {
5849 		struct cs_blob *supp = ubc_get_cs_supplement(vp);
5850 
5851 		if (supp != NULL) {
5852 			blobs = supp;
5853 		} else {
5854 			return FALSE;
5855 		}
5856 	}
5857 #endif
5858 
5859 
5860 
5861 	*tainted = 0;
5862 
5863 	for (offset_in_range = 0;
5864 	    offset_in_range < dsize;
5865 	    /* offset_in_range updated based on bytes processed */) {
5866 		unsigned subrange_tainted = 0;
5867 		boolean_t subrange_validated;
5868 		vm_size_t bytes_processed = 0;
5869 
5870 		subrange_validated = cs_validate_hash(blobs,
5871 		    pager,
5872 		    page_offset + offset_in_range,
5873 		    (const void *)((const char *)data + offset_in_range),
5874 		    &bytes_processed,
5875 		    &subrange_tainted);
5876 
5877 		*tainted |= subrange_tainted;
5878 
5879 		if (bytes_processed == 0) {
5880 			/* Cannote make forward progress, so return an error */
5881 			all_subranges_validated = FALSE;
5882 			break;
5883 		} else if (subrange_validated == FALSE) {
5884 			all_subranges_validated = FALSE;
5885 			/* Keep going to detect other types of failures in subranges */
5886 		}
5887 
5888 		offset_in_range += bytes_processed;
5889 	}
5890 
5891 	return all_subranges_validated;
5892 }
5893 
5894 void
cs_validate_page(struct vnode * vp,memory_object_t pager,memory_object_offset_t page_offset,const void * data,int * validated_p,int * tainted_p,int * nx_p)5895 cs_validate_page(
5896 	struct vnode            *vp,
5897 	memory_object_t         pager,
5898 	memory_object_offset_t  page_offset,
5899 	const void              *data,
5900 	int                     *validated_p,
5901 	int                     *tainted_p,
5902 	int                     *nx_p)
5903 {
5904 	vm_size_t offset_in_page;
5905 	struct cs_blob *blobs;
5906 
5907 	blobs = ubc_get_cs_blobs(vp);
5908 
5909 #if CONFIG_SUPPLEMENTAL_SIGNATURES
5910 	if (blobs == NULL && proc_is_translated(current_proc())) {
5911 		struct cs_blob *supp = ubc_get_cs_supplement(vp);
5912 
5913 		if (supp != NULL) {
5914 			blobs = supp;
5915 		}
5916 	}
5917 #endif
5918 
5919 	*validated_p = VMP_CS_ALL_FALSE;
5920 	*tainted_p = VMP_CS_ALL_FALSE;
5921 	*nx_p = VMP_CS_ALL_FALSE;
5922 
5923 	for (offset_in_page = 0;
5924 	    offset_in_page < PAGE_SIZE;
5925 	    /* offset_in_page updated based on bytes processed */) {
5926 		unsigned subrange_tainted = 0;
5927 		boolean_t subrange_validated;
5928 		vm_size_t bytes_processed = 0;
5929 		int sub_bit;
5930 
5931 		subrange_validated = cs_validate_hash(blobs,
5932 		    pager,
5933 		    page_offset + offset_in_page,
5934 		    (const void *)((const char *)data + offset_in_page),
5935 		    &bytes_processed,
5936 		    &subrange_tainted);
5937 
5938 		if (bytes_processed == 0) {
5939 			/* 4k chunk not code-signed: try next one */
5940 			offset_in_page += FOURK_PAGE_SIZE;
5941 			continue;
5942 		}
5943 		if (offset_in_page == 0 &&
5944 		    bytes_processed > PAGE_SIZE - FOURK_PAGE_SIZE) {
5945 			/* all processed: no 4k granularity */
5946 			if (subrange_validated) {
5947 				*validated_p = VMP_CS_ALL_TRUE;
5948 			}
5949 			if (subrange_tainted & CS_VALIDATE_TAINTED) {
5950 				*tainted_p = VMP_CS_ALL_TRUE;
5951 			}
5952 			if (subrange_tainted & CS_VALIDATE_NX) {
5953 				*nx_p = VMP_CS_ALL_TRUE;
5954 			}
5955 			break;
5956 		}
5957 		/* we only handle 4k or 16k code-signing granularity... */
5958 		assertf(bytes_processed <= FOURK_PAGE_SIZE,
5959 		    "vp %p blobs %p offset 0x%llx + 0x%llx bytes_processed 0x%llx\n",
5960 		    vp, blobs, (uint64_t)page_offset,
5961 		    (uint64_t)offset_in_page, (uint64_t)bytes_processed);
5962 		sub_bit = 1 << (offset_in_page >> FOURK_PAGE_SHIFT);
5963 		if (subrange_validated) {
5964 			*validated_p |= sub_bit;
5965 		}
5966 		if (subrange_tainted & CS_VALIDATE_TAINTED) {
5967 			*tainted_p |= sub_bit;
5968 		}
5969 		if (subrange_tainted & CS_VALIDATE_NX) {
5970 			*nx_p |= sub_bit;
5971 		}
5972 		/* go to next 4k chunk */
5973 		offset_in_page += FOURK_PAGE_SIZE;
5974 	}
5975 
5976 	return;
5977 }
5978 
5979 int
ubc_cs_getcdhash(vnode_t vp,off_t offset,unsigned char * cdhash)5980 ubc_cs_getcdhash(
5981 	vnode_t         vp,
5982 	off_t           offset,
5983 	unsigned char   *cdhash)
5984 {
5985 	struct cs_blob  *blobs, *blob;
5986 	off_t           rel_offset;
5987 	int             ret;
5988 
5989 	vnode_lock(vp);
5990 
5991 	blobs = ubc_get_cs_blobs(vp);
5992 	for (blob = blobs;
5993 	    blob != NULL;
5994 	    blob = blob->csb_next) {
5995 		/* compute offset relative to this blob */
5996 		rel_offset = offset - blob->csb_base_offset;
5997 		if (rel_offset >= blob->csb_start_offset &&
5998 		    rel_offset < blob->csb_end_offset) {
5999 			/* this blob does cover our "offset" ! */
6000 			break;
6001 		}
6002 	}
6003 
6004 	if (blob == NULL) {
6005 		/* we didn't find a blob covering "offset" */
6006 		ret = EBADEXEC; /* XXX any better error ? */
6007 	} else {
6008 		/* get the SHA1 hash of that blob */
6009 		bcopy(blob->csb_cdhash, cdhash, sizeof(blob->csb_cdhash));
6010 		ret = 0;
6011 	}
6012 
6013 	vnode_unlock(vp);
6014 
6015 	return ret;
6016 }
6017 
6018 boolean_t
ubc_cs_is_range_codesigned(vnode_t vp,mach_vm_offset_t start,mach_vm_size_t size)6019 ubc_cs_is_range_codesigned(
6020 	vnode_t                 vp,
6021 	mach_vm_offset_t        start,
6022 	mach_vm_size_t          size)
6023 {
6024 	struct cs_blob          *csblob;
6025 	mach_vm_offset_t        blob_start;
6026 	mach_vm_offset_t        blob_end;
6027 
6028 	if (vp == NULL) {
6029 		/* no file: no code signature */
6030 		return FALSE;
6031 	}
6032 	if (size == 0) {
6033 		/* no range: no code signature */
6034 		return FALSE;
6035 	}
6036 	if (start + size < start) {
6037 		/* overflow */
6038 		return FALSE;
6039 	}
6040 
6041 	csblob = ubc_cs_blob_get(vp, -1, -1, start);
6042 	if (csblob == NULL) {
6043 		return FALSE;
6044 	}
6045 
6046 	/*
6047 	 * We currently check if the range is covered by a single blob,
6048 	 * which should always be the case for the dyld shared cache.
6049 	 * If we ever want to make this routine handle other cases, we
6050 	 * would have to iterate if the blob does not cover the full range.
6051 	 */
6052 	blob_start = (mach_vm_offset_t) (csblob->csb_base_offset +
6053 	    csblob->csb_start_offset);
6054 	blob_end = (mach_vm_offset_t) (csblob->csb_base_offset +
6055 	    csblob->csb_end_offset);
6056 	if (blob_start > start || blob_end < (start + size)) {
6057 		/* range not fully covered by this code-signing blob */
6058 		return FALSE;
6059 	}
6060 
6061 	return TRUE;
6062 }
6063 
6064 #if CHECK_CS_VALIDATION_BITMAP
6065 #define stob(s) (((atop_64(round_page_64(s))) + 07) >> 3)
6066 extern  boolean_t       root_fs_upgrade_try;
6067 
6068 /*
6069  * Should we use the code-sign bitmap to avoid repeated code-sign validation?
6070  * Depends:
6071  * a) Is the target vnode on the root filesystem?
6072  * b) Has someone tried to mount the root filesystem read-write?
6073  * If answers are (a) yes AND (b) no, then we can use the bitmap.
6074  */
6075 #define USE_CODE_SIGN_BITMAP(vp)        ( (vp != NULL) && (vp->v_mount != NULL) && (vp->v_mount->mnt_flag & MNT_ROOTFS) && !root_fs_upgrade_try)
6076 kern_return_t
ubc_cs_validation_bitmap_allocate(vnode_t vp)6077 ubc_cs_validation_bitmap_allocate(
6078 	vnode_t         vp)
6079 {
6080 	kern_return_t   kr = KERN_SUCCESS;
6081 	struct ubc_info *uip;
6082 	char            *target_bitmap;
6083 	vm_object_size_t        bitmap_size;
6084 
6085 	if (!USE_CODE_SIGN_BITMAP(vp) || (!UBCINFOEXISTS(vp))) {
6086 		kr = KERN_INVALID_ARGUMENT;
6087 	} else {
6088 		uip = vp->v_ubcinfo;
6089 
6090 		if (uip->cs_valid_bitmap == NULL) {
6091 			bitmap_size = stob(uip->ui_size);
6092 			target_bitmap = (char*) kalloc_data((vm_size_t)bitmap_size, Z_WAITOK | Z_ZERO);
6093 			if (target_bitmap == 0) {
6094 				kr = KERN_NO_SPACE;
6095 			} else {
6096 				kr = KERN_SUCCESS;
6097 			}
6098 			if (kr == KERN_SUCCESS) {
6099 				uip->cs_valid_bitmap = (void*)target_bitmap;
6100 				uip->cs_valid_bitmap_size = bitmap_size;
6101 			}
6102 		}
6103 	}
6104 	return kr;
6105 }
6106 
6107 kern_return_t
ubc_cs_check_validation_bitmap(vnode_t vp,memory_object_offset_t offset,int optype)6108 ubc_cs_check_validation_bitmap(
6109 	vnode_t                 vp,
6110 	memory_object_offset_t          offset,
6111 	int                     optype)
6112 {
6113 	kern_return_t   kr = KERN_SUCCESS;
6114 
6115 	if (!USE_CODE_SIGN_BITMAP(vp) || !UBCINFOEXISTS(vp)) {
6116 		kr = KERN_INVALID_ARGUMENT;
6117 	} else {
6118 		struct ubc_info *uip = vp->v_ubcinfo;
6119 		char            *target_bitmap = uip->cs_valid_bitmap;
6120 
6121 		if (target_bitmap == NULL) {
6122 			kr = KERN_INVALID_ARGUMENT;
6123 		} else {
6124 			uint64_t        bit, byte;
6125 			bit = atop_64( offset );
6126 			byte = bit >> 3;
6127 
6128 			if (byte > uip->cs_valid_bitmap_size) {
6129 				kr = KERN_INVALID_ARGUMENT;
6130 			} else {
6131 				if (optype == CS_BITMAP_SET) {
6132 					target_bitmap[byte] |= (1 << (bit & 07));
6133 					kr = KERN_SUCCESS;
6134 				} else if (optype == CS_BITMAP_CLEAR) {
6135 					target_bitmap[byte] &= ~(1 << (bit & 07));
6136 					kr = KERN_SUCCESS;
6137 				} else if (optype == CS_BITMAP_CHECK) {
6138 					if (target_bitmap[byte] & (1 << (bit & 07))) {
6139 						kr = KERN_SUCCESS;
6140 					} else {
6141 						kr = KERN_FAILURE;
6142 					}
6143 				}
6144 			}
6145 		}
6146 	}
6147 	return kr;
6148 }
6149 
6150 void
ubc_cs_validation_bitmap_deallocate(struct ubc_info * uip)6151 ubc_cs_validation_bitmap_deallocate(
6152 	struct ubc_info *uip)
6153 {
6154 	if (uip->cs_valid_bitmap != NULL) {
6155 		kfree_data(uip->cs_valid_bitmap, (vm_size_t)uip->cs_valid_bitmap_size);
6156 		uip->cs_valid_bitmap = NULL;
6157 	}
6158 }
6159 #else
6160 kern_return_t
ubc_cs_validation_bitmap_allocate(__unused vnode_t vp)6161 ubc_cs_validation_bitmap_allocate(__unused vnode_t vp)
6162 {
6163 	return KERN_INVALID_ARGUMENT;
6164 }
6165 
6166 kern_return_t
ubc_cs_check_validation_bitmap(__unused struct vnode * vp,__unused memory_object_offset_t offset,__unused int optype)6167 ubc_cs_check_validation_bitmap(
6168 	__unused struct vnode *vp,
6169 	__unused memory_object_offset_t offset,
6170 	__unused int optype)
6171 {
6172 	return KERN_INVALID_ARGUMENT;
6173 }
6174 
6175 void
ubc_cs_validation_bitmap_deallocate(__unused struct ubc_info * uip)6176 ubc_cs_validation_bitmap_deallocate(__unused struct ubc_info *uip)
6177 {
6178 	return;
6179 }
6180 #endif /* CHECK_CS_VALIDATION_BITMAP */
6181 
6182 #if CODE_SIGNING_MONITOR
6183 
6184 kern_return_t
cs_associate_blob_with_mapping(void * pmap,vm_map_offset_t start,vm_map_size_t size,vm_object_offset_t offset,void * blobs_p)6185 cs_associate_blob_with_mapping(
6186 	void                    *pmap,
6187 	vm_map_offset_t         start,
6188 	vm_map_size_t           size,
6189 	vm_object_offset_t      offset,
6190 	void                    *blobs_p)
6191 {
6192 	off_t                   blob_start_offset, blob_end_offset;
6193 	kern_return_t           kr;
6194 	struct cs_blob          *blobs, *blob;
6195 	vm_offset_t             kaddr;
6196 	void                    *monitor_sig_obj = NULL;
6197 
6198 	if (csm_enabled() == false) {
6199 		return KERN_NOT_SUPPORTED;
6200 	}
6201 
6202 	blobs = (struct cs_blob *)blobs_p;
6203 
6204 	for (blob = blobs;
6205 	    blob != NULL;
6206 	    blob = blob->csb_next) {
6207 		blob_start_offset = (blob->csb_base_offset +
6208 		    blob->csb_start_offset);
6209 		blob_end_offset = (blob->csb_base_offset +
6210 		    blob->csb_end_offset);
6211 		if ((off_t) offset < blob_start_offset ||
6212 		    (off_t) offset >= blob_end_offset ||
6213 		    (off_t) (offset + size) <= blob_start_offset ||
6214 		    (off_t) (offset + size) > blob_end_offset) {
6215 			continue;
6216 		}
6217 
6218 		kaddr = (vm_offset_t)blob->csb_mem_kaddr;
6219 		if (kaddr == 0) {
6220 			/* blob data has been released */
6221 			continue;
6222 		}
6223 
6224 		monitor_sig_obj = blob->csb_csm_obj;
6225 		if (monitor_sig_obj == NULL) {
6226 			continue;
6227 		}
6228 
6229 		break;
6230 	}
6231 
6232 	if (monitor_sig_obj != NULL) {
6233 		vm_offset_t segment_offset = offset - blob_start_offset;
6234 		kr = csm_associate_code_signature(pmap, monitor_sig_obj, start, size, segment_offset);
6235 	} else {
6236 		kr = KERN_CODESIGN_ERROR;
6237 	}
6238 
6239 	return kr;
6240 }
6241 
6242 #endif /* CODE_SIGNING_MONITOR */
6243