2 * Copyright (c) 1999-2014 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Author: Umesh Vaishampayan [umeshv@apple.com]
31 * 05-Aug-1999 umeshv Created.
33 * Functions related to Unified Buffer cache.
35 * Caller of UBC functions MUST have a valid reference on the vnode.
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/systm.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>
52 #include <sys/codesign.h>
53 #include <sys/codedir_internal.h>
54 #include <sys/fsevents.h>
55 #include <sys/fcntl.h>
57 #include <mach/mach_types.h>
58 #include <mach/memory_object_types.h>
59 #include <mach/memory_object_control.h>
60 #include <mach/vm_map.h>
61 #include <mach/mach_vm.h>
64 #include <kern/kern_types.h>
65 #include <kern/kalloc.h>
66 #include <kern/zalloc.h>
67 #include <kern/thread.h>
68 #include <vm/vm_kern.h>
69 #include <vm/vm_protos.h> /* last */
71 #include <libkern/crypto/sha1.h>
72 #include <libkern/crypto/sha2.h>
73 #include <libkern/libkern.h>
75 #include <security/mac_framework.h>
78 /* XXX These should be in a BSD accessible Mach header, but aren't. */
79 extern kern_return_t
memory_object_pages_resident(memory_object_control_t
,
81 extern kern_return_t
memory_object_signed(memory_object_control_t control
,
83 extern boolean_t
memory_object_is_slid(memory_object_control_t control
);
84 extern boolean_t
memory_object_is_signed(memory_object_control_t
);
86 extern void Debugger(const char *message
);
89 /* XXX no one uses this interface! */
90 kern_return_t
ubc_page_op_with_control(
91 memory_object_control_t control
,
102 #define assert(cond) \
103 ((void) ((cond) ? 0 : panic("Assert failed: %s", # cond)))
105 #include <kern/assert.h>
106 #endif /* DIAGNOSTIC */
108 static int ubc_info_init_internal(struct vnode
*vp
, int withfsize
, off_t filesize
);
109 static int ubc_umcallback(vnode_t
, void *);
110 static int ubc_msync_internal(vnode_t
, off_t
, off_t
, off_t
*, int, int *);
111 static void ubc_cs_free(struct ubc_info
*uip
);
113 struct zone
*ubc_info_zone
;
114 static uint32_t cs_blob_generation_count
= 1;
118 * Routines to navigate code signing data structures in the kernel...
123 #define PAGE_SHIFT_4K (12)
124 #define PAGE_SIZE_4K ((1<<PAGE_SHIFT_4K))
125 #define PAGE_MASK_4K ((PAGE_SIZE_4K-1))
126 #define round_page_4K(x) (((vm_offset_t)(x) + PAGE_MASK_4K) & ~((vm_offset_t)PAGE_MASK_4K))
132 const void *lower_bound
,
133 const void *upper_bound
)
135 if (upper_bound
< lower_bound
||
140 if (start
< lower_bound
||
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
);
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 */
157 cs_md_update cs_update
;
158 cs_md_final cs_final
;
161 static struct cs_hash cs_hash_sha1
= {
162 .cs_type
= CS_HASHTYPE_SHA1
,
163 .cs_size
= CS_SHA1_LEN
,
164 .cs_digest_size
= SHA_DIGEST_LENGTH
,
165 .cs_init
= (cs_md_init
)SHA1Init
,
166 .cs_update
= (cs_md_update
)SHA1Update
,
167 .cs_final
= (cs_md_final
)SHA1Final
,
170 static struct cs_hash cs_hash_sha256
= {
171 .cs_type
= CS_HASHTYPE_SHA256
,
172 .cs_size
= SHA256_DIGEST_LENGTH
,
173 .cs_digest_size
= SHA256_DIGEST_LENGTH
,
174 .cs_init
= (cs_md_init
)SHA256_Init
,
175 .cs_update
= (cs_md_update
)SHA256_Update
,
176 .cs_final
= (cs_md_final
)SHA256_Final
,
178 static struct cs_hash cs_hash_sha256_truncate
= {
179 .cs_type
= CS_HASHTYPE_SHA256_TRUNCATED
,
180 .cs_size
= CS_SHA256_TRUNCATED_LEN
,
181 .cs_digest_size
= SHA256_DIGEST_LENGTH
,
182 .cs_init
= (cs_md_init
)SHA256_Init
,
183 .cs_update
= (cs_md_update
)SHA256_Update
,
184 .cs_final
= (cs_md_final
)SHA256_Final
,
186 static struct cs_hash cs_hash_sha384
= {
187 .cs_type
= CS_HASHTYPE_SHA384
,
188 .cs_size
= SHA384_DIGEST_LENGTH
,
189 .cs_digest_size
= SHA384_DIGEST_LENGTH
,
190 .cs_init
= (cs_md_init
)SHA384_Init
,
191 .cs_update
= (cs_md_update
)SHA384_Update
,
192 .cs_final
= (cs_md_final
)SHA384_Final
,
196 static struct cs_hash
*
197 cs_find_md(uint8_t type
)
199 if (type
== CS_HASHTYPE_SHA1
) {
200 return &cs_hash_sha1
;
202 } else if (type
== CS_HASHTYPE_SHA256
) {
203 return &cs_hash_sha256
;
204 } else if (type
== CS_HASHTYPE_SHA256_TRUNCATED
) {
205 return &cs_hash_sha256_truncate
;
206 } else if (type
== CS_HASHTYPE_SHA384
) {
207 return &cs_hash_sha384
;
213 union cs_hash_union
{
215 SHA256_CTX sha256ctx
;
216 SHA384_CTX sha384ctx
;
221 * Choose among different hash algorithms.
222 * Higher is better, 0 => don't use at all.
224 static uint32_t hashPriorities
[] = {
226 CS_HASHTYPE_SHA256_TRUNCATED
,
232 hash_rank(const CS_CodeDirectory
*cd
)
234 uint32_t type
= cd
->hashType
;
237 for (n
= 0; n
< sizeof(hashPriorities
) / sizeof(hashPriorities
[0]); ++n
)
238 if (hashPriorities
[n
] == type
)
240 return 0; /* not supported */
245 * Locating a page hash
247 static const unsigned char *
249 const CS_CodeDirectory
*cd
,
252 const char *lower_bound
,
253 const char *upper_bound
)
255 const unsigned char *base
, *top
, *hash
;
256 uint32_t nCodeSlots
= ntohl(cd
->nCodeSlots
);
258 assert(cs_valid_range(cd
, cd
+ 1, lower_bound
, upper_bound
));
260 if((ntohl(cd
->version
) >= CS_SUPPORTSSCATTER
) && (ntohl(cd
->scatterOffset
))) {
261 /* Get first scatter struct */
262 const SC_Scatter
*scatter
= (const SC_Scatter
*)
263 ((const char*)cd
+ ntohl(cd
->scatterOffset
));
264 uint32_t hashindex
=0, scount
, sbase
=0;
265 /* iterate all scatter structs */
267 if((const char*)scatter
> (const char*)cd
+ ntohl(cd
->length
)) {
269 printf("CODE SIGNING: Scatter extends past Code Directory\n");
274 scount
= ntohl(scatter
->count
);
275 uint32_t new_base
= ntohl(scatter
->base
);
282 if((hashindex
> 0) && (new_base
<= sbase
)) {
284 printf("CODE SIGNING: unordered Scatter, prev base %d, cur base %d\n",
287 return NULL
; /* unordered scatter array */
291 /* this scatter beyond page we're looking for? */
296 if (sbase
+scount
>= page
) {
297 /* Found the scatter struct that is
298 * referencing our page */
300 /* base = address of first hash covered by scatter */
301 base
= (const unsigned char *)cd
+ ntohl(cd
->hashOffset
) +
302 hashindex
* hash_len
;
303 /* top = address of first hash after this scatter */
304 top
= base
+ scount
* hash_len
;
305 if (!cs_valid_range(base
, top
, lower_bound
,
307 hashindex
> nCodeSlots
) {
314 /* this scatter struct is before the page we're looking
320 hash
= base
+ (page
- sbase
) * hash_len
;
322 base
= (const unsigned char *)cd
+ ntohl(cd
->hashOffset
);
323 top
= base
+ nCodeSlots
* hash_len
;
324 if (!cs_valid_range(base
, top
, lower_bound
, upper_bound
) ||
328 assert(page
< nCodeSlots
);
330 hash
= base
+ page
* hash_len
;
333 if (!cs_valid_range(hash
, hash
+ hash_len
,
334 lower_bound
, upper_bound
)) {
342 * cs_validate_codedirectory
344 * Validate that pointers inside the code directory to make sure that
345 * all offsets and lengths are constrained within the buffer.
347 * Parameters: cd Pointer to code directory buffer
348 * length Length of buffer
351 * EBADEXEC Invalid code signature
355 cs_validate_codedirectory(const CS_CodeDirectory
*cd
, size_t length
)
357 struct cs_hash
*hashtype
;
359 if (length
< sizeof(*cd
))
361 if (ntohl(cd
->magic
) != CSMAGIC_CODEDIRECTORY
)
363 if (cd
->pageSize
!= PAGE_SHIFT_4K
)
365 hashtype
= cs_find_md(cd
->hashType
);
366 if (hashtype
== NULL
)
369 if (cd
->hashSize
!= hashtype
->cs_size
)
372 if (length
< ntohl(cd
->hashOffset
))
375 /* check that nSpecialSlots fits in the buffer in front of hashOffset */
376 if (ntohl(cd
->hashOffset
) / hashtype
->cs_size
< ntohl(cd
->nSpecialSlots
))
379 /* check that codeslots fits in the buffer */
380 if ((length
- ntohl(cd
->hashOffset
)) / hashtype
->cs_size
< ntohl(cd
->nCodeSlots
))
383 if (ntohl(cd
->version
) >= CS_SUPPORTSSCATTER
&& cd
->scatterOffset
) {
385 if (length
< ntohl(cd
->scatterOffset
))
388 const SC_Scatter
*scatter
= (const SC_Scatter
*)
389 (((const uint8_t *)cd
) + ntohl(cd
->scatterOffset
));
393 * Check each scatter buffer, since we don't know the
394 * length of the scatter buffer array, we have to
398 /* check that the end of each scatter buffer in within the length */
399 if (((const uint8_t *)scatter
) + sizeof(scatter
[0]) > (const uint8_t *)cd
+ length
)
401 uint32_t scount
= ntohl(scatter
->count
);
404 if (nPages
+ scount
< nPages
)
409 /* XXX check that basees doesn't overlap */
410 /* XXX check that targetOffset doesn't overlap */
412 #if 0 /* rdar://12579439 */
413 if (nPages
!= ntohl(cd
->nCodeSlots
))
418 if (length
< ntohl(cd
->identOffset
))
421 /* identifier is NUL terminated string */
422 if (cd
->identOffset
) {
423 const uint8_t *ptr
= (const uint8_t *)cd
+ ntohl(cd
->identOffset
);
424 if (memchr(ptr
, 0, length
- ntohl(cd
->identOffset
)) == NULL
)
428 /* team identifier is NULL terminated string */
429 if (ntohl(cd
->version
) >= CS_SUPPORTSTEAMID
&& ntohl(cd
->teamOffset
)) {
430 if (length
< ntohl(cd
->teamOffset
))
433 const uint8_t *ptr
= (const uint8_t *)cd
+ ntohl(cd
->teamOffset
);
434 if (memchr(ptr
, 0, length
- ntohl(cd
->teamOffset
)) == NULL
)
446 cs_validate_blob(const CS_GenericBlob
*blob
, size_t length
)
448 if (length
< sizeof(CS_GenericBlob
) || length
< ntohl(blob
->length
))
456 * Validate that superblob/embedded code directory to make sure that
457 * all internal pointers are valid.
459 * Will validate both a superblob csblob and a "raw" code directory.
462 * Parameters: buffer Pointer to code signature
463 * length Length of buffer
464 * rcd returns pointer to code directory
467 * EBADEXEC Invalid code signature
471 cs_validate_csblob(const uint8_t *addr
, size_t length
,
472 const CS_CodeDirectory
**rcd
)
474 const CS_GenericBlob
*blob
= (const CS_GenericBlob
*)(const void *)addr
;
479 error
= cs_validate_blob(blob
, length
);
483 length
= ntohl(blob
->length
);
485 if (ntohl(blob
->magic
) == CSMAGIC_EMBEDDED_SIGNATURE
) {
486 const CS_SuperBlob
*sb
;
488 const CS_CodeDirectory
*best_cd
= NULL
;
489 unsigned int best_rank
= 0;
491 if (length
< sizeof(CS_SuperBlob
))
494 sb
= (const CS_SuperBlob
*)blob
;
495 count
= ntohl(sb
->count
);
497 /* check that the array of BlobIndex fits in the rest of the data */
498 if ((length
- sizeof(CS_SuperBlob
)) / sizeof(CS_BlobIndex
) < count
)
501 /* now check each BlobIndex */
502 for (n
= 0; n
< count
; n
++) {
503 const CS_BlobIndex
*blobIndex
= &sb
->index
[n
];
504 uint32_t type
= ntohl(blobIndex
->type
);
505 uint32_t offset
= ntohl(blobIndex
->offset
);
509 const CS_GenericBlob
*subBlob
=
510 (const CS_GenericBlob
*)(const void *)(addr
+ offset
);
512 size_t subLength
= length
- offset
;
514 if ((error
= cs_validate_blob(subBlob
, subLength
)) != 0)
516 subLength
= ntohl(subBlob
->length
);
518 /* extra validation for CDs, that is also returned */
519 if (type
== CSSLOT_CODEDIRECTORY
|| (type
>= CSSLOT_ALTERNATE_CODEDIRECTORIES
&& type
< CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT
)) {
520 const CS_CodeDirectory
*candidate
= (const CS_CodeDirectory
*)subBlob
;
521 if ((error
= cs_validate_codedirectory(candidate
, subLength
)) != 0)
523 unsigned int rank
= hash_rank(candidate
);
525 printf("CodeDirectory type %d rank %d at slot 0x%x index %d\n", candidate
->hashType
, (int)rank
, (int)type
, (int)n
);
526 if (best_cd
== NULL
|| rank
> best_rank
) {
529 } else if (best_cd
!= NULL
&& rank
== best_rank
) {
530 /* repeat of a hash type (1:1 mapped to ranks), illegal and suspicious */
531 printf("multiple hash=%d CodeDirectories in signature; rejecting", best_cd
->hashType
);
535 if (best_cd
&& cs_debug
> 2)
536 printf("using CodeDirectory type %d (rank %d)\n", (int)best_cd
->hashType
, best_rank
);
540 } else if (ntohl(blob
->magic
) == CSMAGIC_CODEDIRECTORY
) {
542 if ((error
= cs_validate_codedirectory((const CS_CodeDirectory
*)(const void *)addr
, length
)) != 0)
544 *rcd
= (const CS_CodeDirectory
*)blob
;
558 * Find an blob from the superblob/code directory. The blob must have
559 * been been validated by cs_validate_csblob() before calling
560 * this. Use csblob_find_blob() instead.
562 * Will also find a "raw" code directory if its stored as well as
563 * searching the superblob.
565 * Parameters: buffer Pointer to code signature
566 * length Length of buffer
567 * type type of blob to find
568 * magic the magic number for that blob
570 * Returns: pointer Success
571 * NULL Buffer not found
574 const CS_GenericBlob
*
575 csblob_find_blob_bytes(const uint8_t *addr
, size_t length
, uint32_t type
, uint32_t magic
)
577 const CS_GenericBlob
*blob
= (const CS_GenericBlob
*)(const void *)addr
;
579 if (ntohl(blob
->magic
) == CSMAGIC_EMBEDDED_SIGNATURE
) {
580 const CS_SuperBlob
*sb
= (const CS_SuperBlob
*)blob
;
581 size_t n
, count
= ntohl(sb
->count
);
583 for (n
= 0; n
< count
; n
++) {
584 if (ntohl(sb
->index
[n
].type
) != type
)
586 uint32_t offset
= ntohl(sb
->index
[n
].offset
);
587 if (length
- sizeof(const CS_GenericBlob
) < offset
)
589 blob
= (const CS_GenericBlob
*)(const void *)(addr
+ offset
);
590 if (ntohl(blob
->magic
) != magic
)
594 } else if (type
== CSSLOT_CODEDIRECTORY
595 && ntohl(blob
->magic
) == CSMAGIC_CODEDIRECTORY
596 && magic
== CSMAGIC_CODEDIRECTORY
)
602 const CS_GenericBlob
*
603 csblob_find_blob(struct cs_blob
*csblob
, uint32_t type
, uint32_t magic
)
605 if ((csblob
->csb_flags
& CS_VALID
) == 0)
607 return csblob_find_blob_bytes((const uint8_t *)csblob
->csb_mem_kaddr
, csblob
->csb_mem_size
, type
, magic
);
610 static const uint8_t *
611 find_special_slot(const CS_CodeDirectory
*cd
, size_t slotsize
, uint32_t slot
)
613 /* there is no zero special slot since that is the first code slot */
614 if (ntohl(cd
->nSpecialSlots
) < slot
|| slot
== 0)
617 return ((const uint8_t *)cd
+ ntohl(cd
->hashOffset
) - (slotsize
* slot
));
620 static uint8_t cshash_zero
[CS_HASH_MAX_SIZE
] = { 0 };
623 csblob_get_entitlements(struct cs_blob
*csblob
, void **out_start
, size_t *out_length
)
625 uint8_t computed_hash
[CS_HASH_MAX_SIZE
];
626 const CS_GenericBlob
*entitlements
;
627 const CS_CodeDirectory
*code_dir
;
628 const uint8_t *embedded_hash
;
629 union cs_hash_union context
;
634 if (csblob
->csb_hashtype
== NULL
|| csblob
->csb_hashtype
->cs_digest_size
> sizeof(computed_hash
))
637 code_dir
= csblob
->csb_cd
;
639 entitlements
= csblob_find_blob(csblob
, CSSLOT_ENTITLEMENTS
, CSMAGIC_EMBEDDED_ENTITLEMENTS
);
640 embedded_hash
= find_special_slot(code_dir
, csblob
->csb_hashtype
->cs_size
, CSSLOT_ENTITLEMENTS
);
642 if (embedded_hash
== NULL
) {
646 } else if (entitlements
== NULL
) {
647 if (memcmp(embedded_hash
, cshash_zero
, csblob
->csb_hashtype
->cs_size
) != 0) {
654 csblob
->csb_hashtype
->cs_init(&context
);
655 csblob
->csb_hashtype
->cs_update(&context
, entitlements
, ntohl(entitlements
->length
));
656 csblob
->csb_hashtype
->cs_final(computed_hash
, &context
);
658 if (memcmp(computed_hash
, embedded_hash
, csblob
->csb_hashtype
->cs_size
) != 0)
661 *out_start
= __DECONST(void *, entitlements
);
662 *out_length
= ntohl(entitlements
->length
);
669 * End of routines to navigate code signing data structures in the kernel.
677 * Initialization of the zone for Unified Buffer Cache.
684 * ubc_info_zone(global) initialized for subsequent allocations
686 __private_extern__
void
691 i
= (vm_size_t
) sizeof (struct ubc_info
);
693 ubc_info_zone
= zinit (i
, 10000*i
, 8192, "ubc_info zone");
695 zone_change(ubc_info_zone
, Z_NOENCRYPT
, TRUE
);
702 * Allocate and attach an empty ubc_info structure to a vnode
704 * Parameters: vp Pointer to the vnode
707 * vnode_size:ENOMEM Not enough space
708 * vnode_size:??? Other error from vnode_getattr
712 ubc_info_init(struct vnode
*vp
)
714 return(ubc_info_init_internal(vp
, 0, 0));
719 * ubc_info_init_withsize
721 * Allocate and attach a sized ubc_info structure to a vnode
723 * Parameters: vp Pointer to the vnode
724 * filesize The size of the file
727 * vnode_size:ENOMEM Not enough space
728 * vnode_size:??? Other error from vnode_getattr
731 ubc_info_init_withsize(struct vnode
*vp
, off_t filesize
)
733 return(ubc_info_init_internal(vp
, 1, filesize
));
738 * ubc_info_init_internal
740 * Allocate and attach a ubc_info structure to a vnode
742 * Parameters: vp Pointer to the vnode
743 * withfsize{0,1} Zero if the size should be obtained
744 * from the vnode; otherwise, use filesize
745 * filesize The size of the file, if withfsize == 1
748 * vnode_size:ENOMEM Not enough space
749 * vnode_size:??? Other error from vnode_getattr
751 * Notes: We call a blocking zalloc(), and the zone was created as an
752 * expandable and collectable zone, so if no memory is available,
753 * it is possible for zalloc() to block indefinitely. zalloc()
754 * may also panic if the zone of zones is exhausted, since it's
757 * We unconditionally call vnode_pager_setup(), even if this is
758 * a reuse of a ubc_info; in that case, we should probably assert
759 * that it does not already have a pager association, but do not.
761 * Since memory_object_create_named() can only fail from receiving
762 * an invalid pager argument, the explicit check and panic is
763 * merely precautionary.
766 ubc_info_init_internal(vnode_t vp
, int withfsize
, off_t filesize
)
768 register struct ubc_info
*uip
;
772 memory_object_control_t control
;
777 * If there is not already a ubc_info attached to the vnode, we
778 * attach one; otherwise, we will reuse the one that's there.
780 if (uip
== UBC_INFO_NULL
) {
782 uip
= (struct ubc_info
*) zalloc(ubc_info_zone
);
783 bzero((char *)uip
, sizeof(struct ubc_info
));
786 uip
->ui_flags
= UI_INITED
;
787 uip
->ui_ucred
= NOCRED
;
789 assert(uip
->ui_flags
!= UI_NONE
);
790 assert(uip
->ui_vnode
== vp
);
792 /* now set this ubc_info in the vnode */
796 * Allocate a pager object for this vnode
798 * XXX The value of the pager parameter is currently ignored.
799 * XXX Presumably, this API changed to avoid the race between
800 * XXX setting the pager and the UI_HASPAGER flag.
802 pager
= (void *)vnode_pager_setup(vp
, uip
->ui_pager
);
806 * Explicitly set the pager into the ubc_info, after setting the
809 SET(uip
->ui_flags
, UI_HASPAGER
);
810 uip
->ui_pager
= pager
;
813 * Note: We can not use VNOP_GETATTR() to get accurate
814 * value of ui_size because this may be an NFS vnode, and
815 * nfs_getattr() can call vinvalbuf(); if this happens,
816 * ubc_info is not set up to deal with that event.
821 * create a vnode - vm_object association
822 * memory_object_create_named() creates a "named" reference on the
823 * memory object we hold this reference as long as the vnode is
824 * "alive." Since memory_object_create_named() took its own reference
825 * on the vnode pager we passed it, we can drop the reference
826 * vnode_pager_setup() returned here.
828 kret
= memory_object_create_named(pager
,
829 (memory_object_size_t
)uip
->ui_size
, &control
);
830 vnode_pager_deallocate(pager
);
831 if (kret
!= KERN_SUCCESS
)
832 panic("ubc_info_init: memory_object_create_named returned %d", kret
);
835 uip
->ui_control
= control
; /* cache the value of the mo control */
836 SET(uip
->ui_flags
, UI_HASOBJREF
); /* with a named reference */
838 if (withfsize
== 0) {
839 /* initialize the size */
840 error
= vnode_size(vp
, &uip
->ui_size
, vfs_context_current());
844 uip
->ui_size
= filesize
;
846 vp
->v_lflag
|= VNAMED_UBC
; /* vnode has a named ubc reference */
855 * Free a ubc_info structure
857 * Parameters: uip A pointer to the ubc_info to free
861 * Notes: If there is a credential that has subsequently been associated
862 * with the ubc_info via a call to ubc_setcred(), the reference
863 * to the credential is dropped.
865 * It's actually impossible for a ubc_info.ui_control to take the
866 * value MEMORY_OBJECT_CONTROL_NULL.
869 ubc_info_free(struct ubc_info
*uip
)
871 if (IS_VALID_CRED(uip
->ui_ucred
)) {
872 kauth_cred_unref(&uip
->ui_ucred
);
875 if (uip
->ui_control
!= MEMORY_OBJECT_CONTROL_NULL
)
876 memory_object_control_deallocate(uip
->ui_control
);
878 cluster_release(uip
);
881 zfree(ubc_info_zone
, uip
);
887 ubc_info_deallocate(struct ubc_info
*uip
)
892 errno_t
mach_to_bsd_errno(kern_return_t mach_err
)
898 case KERN_INVALID_ADDRESS
:
899 case KERN_INVALID_ARGUMENT
:
900 case KERN_NOT_IN_SET
:
901 case KERN_INVALID_NAME
:
902 case KERN_INVALID_TASK
:
903 case KERN_INVALID_RIGHT
:
904 case KERN_INVALID_VALUE
:
905 case KERN_INVALID_CAPABILITY
:
906 case KERN_INVALID_HOST
:
907 case KERN_MEMORY_PRESENT
:
908 case KERN_INVALID_PROCESSOR_SET
:
909 case KERN_INVALID_POLICY
:
910 case KERN_ALREADY_WAITING
:
911 case KERN_DEFAULT_SET
:
912 case KERN_EXCEPTION_PROTECTED
:
913 case KERN_INVALID_LEDGER
:
914 case KERN_INVALID_MEMORY_CONTROL
:
915 case KERN_INVALID_SECURITY
:
916 case KERN_NOT_DEPRESSED
:
917 case KERN_LOCK_OWNED
:
918 case KERN_LOCK_OWNED_SELF
:
921 case KERN_PROTECTION_FAILURE
:
922 case KERN_NOT_RECEIVER
:
924 case KERN_POLICY_STATIC
:
928 case KERN_RESOURCE_SHORTAGE
:
929 case KERN_UREFS_OVERFLOW
:
930 case KERN_INVALID_OBJECT
:
936 case KERN_MEMORY_FAILURE
:
937 case KERN_POLICY_LIMIT
:
938 case KERN_CODESIGN_ERROR
:
941 case KERN_MEMORY_ERROR
:
944 case KERN_ALREADY_IN_SET
:
945 case KERN_NAME_EXISTS
:
946 case KERN_RIGHT_EXISTS
:
952 case KERN_TERMINATED
:
953 case KERN_LOCK_SET_DESTROYED
:
954 case KERN_LOCK_UNSTABLE
:
955 case KERN_SEMAPHORE_DESTROYED
:
958 case KERN_RPC_SERVER_TERMINATED
:
961 case KERN_NOT_SUPPORTED
:
967 case KERN_NOT_WAITING
:
970 case KERN_OPERATION_TIMED_OUT
:
981 * Tell the VM that the the size of the file represented by the vnode has
984 * Parameters: vp The vp whose backing file size is
986 * nsize The new size of the backing file
989 * Returns: EINVAL for new size < 0
990 * ENOENT if no UBC info exists
991 * EAGAIN if UBC_SETSIZE_NO_FS_REENTRY option is set and new_size < old size
992 * Other errors (mapped to errno_t) returned by VM functions
994 * Notes: This function will indicate success if the new size is the
995 * same or larger than the old size (in this case, the
996 * remainder of the file will require modification or use of
997 * an existing upl to access successfully).
999 * This function will fail if the new file size is smaller,
1000 * and the memory region being invalidated was unable to
1001 * actually be invalidated and/or the last page could not be
1002 * flushed, if the new size is not aligned to a page
1003 * boundary. This is usually indicative of an I/O error.
1005 errno_t
ubc_setsize_ex(struct vnode
*vp
, off_t nsize
, ubc_setsize_opts_t opts
)
1007 off_t osize
; /* ui_size before change */
1008 off_t lastpg
, olastpgend
, lastoff
;
1009 struct ubc_info
*uip
;
1010 memory_object_control_t control
;
1011 kern_return_t kret
= KERN_SUCCESS
;
1013 if (nsize
< (off_t
)0)
1016 if (!UBCINFOEXISTS(vp
))
1019 uip
= vp
->v_ubcinfo
;
1020 osize
= uip
->ui_size
;
1022 if (ISSET(opts
, UBC_SETSIZE_NO_FS_REENTRY
) && nsize
< osize
)
1026 * Update the size before flushing the VM
1028 uip
->ui_size
= nsize
;
1030 if (nsize
>= osize
) { /* Nothing more to do */
1031 if (nsize
> osize
) {
1032 lock_vnode_and_post(vp
, NOTE_EXTEND
);
1039 * When the file shrinks, invalidate the pages beyond the
1040 * new size. Also get rid of garbage beyond nsize on the
1041 * last page. The ui_size already has the nsize, so any
1042 * subsequent page-in will zero-fill the tail properly
1044 lastpg
= trunc_page_64(nsize
);
1045 olastpgend
= round_page_64(osize
);
1046 control
= uip
->ui_control
;
1048 lastoff
= (nsize
& PAGE_MASK_64
);
1052 upl_page_info_t
*pl
;
1055 * new EOF ends up in the middle of a page
1056 * zero the tail of this page if it's currently
1057 * present in the cache
1059 kret
= ubc_create_upl(vp
, lastpg
, PAGE_SIZE
, &upl
, &pl
, UPL_SET_LITE
);
1061 if (kret
!= KERN_SUCCESS
)
1062 panic("ubc_setsize: ubc_create_upl (error = %d)\n", kret
);
1064 if (upl_valid_page(pl
, 0))
1065 cluster_zero(upl
, (uint32_t)lastoff
, PAGE_SIZE
- (uint32_t)lastoff
, NULL
);
1067 ubc_upl_abort_range(upl
, 0, PAGE_SIZE
, UPL_ABORT_FREE_ON_EMPTY
);
1069 lastpg
+= PAGE_SIZE_64
;
1071 if (olastpgend
> lastpg
) {
1075 flags
= MEMORY_OBJECT_DATA_FLUSH_ALL
;
1077 flags
= MEMORY_OBJECT_DATA_FLUSH
;
1079 * invalidate the pages beyond the new EOF page
1082 kret
= memory_object_lock_request(control
,
1083 (memory_object_offset_t
)lastpg
,
1084 (memory_object_size_t
)(olastpgend
- lastpg
), NULL
, NULL
,
1085 MEMORY_OBJECT_RETURN_NONE
, flags
, VM_PROT_NO_CHANGE
);
1086 if (kret
!= KERN_SUCCESS
)
1087 printf("ubc_setsize: invalidate failed (error = %d)\n", kret
);
1089 return mach_to_bsd_errno(kret
);
1092 // Returns true for success
1093 int ubc_setsize(vnode_t vp
, off_t nsize
)
1095 return ubc_setsize_ex(vp
, nsize
, 0) == 0;
1101 * Get the size of the file assocated with the specified vnode
1103 * Parameters: vp The vnode whose size is of interest
1105 * Returns: 0 There is no ubc_info associated with
1106 * this vnode, or the size is zero
1107 * !0 The size of the file
1109 * Notes: Using this routine, it is not possible for a caller to
1110 * successfully distinguish between a vnode associate with a zero
1111 * length file, and a vnode with no associated ubc_info. The
1112 * caller therefore needs to not care, or needs to ensure that
1113 * they have previously successfully called ubc_info_init() or
1114 * ubc_info_init_withsize().
1117 ubc_getsize(struct vnode
*vp
)
1119 /* people depend on the side effect of this working this way
1120 * as they call this for directory
1122 if (!UBCINFOEXISTS(vp
))
1124 return (vp
->v_ubcinfo
->ui_size
);
1131 * Call ubc_msync(vp, 0, EOF, NULL, UBC_PUSHALL) on all the vnodes for this
1134 * Parameters: mp The mount point
1136 * Returns: 0 Success
1138 * Notes: There is no failure indication for this function.
1140 * This function is used in the unmount path; since it may block
1141 * I/O indefinitely, it should not be used in the forced unmount
1142 * path, since a device unavailability could also block that
1145 * Because there is no device ejection interlock on USB, FireWire,
1146 * or similar devices, it's possible that an ejection that begins
1147 * subsequent to the vnode_iterate() completing, either on one of
1148 * those devices, or a network mount for which the server quits
1149 * responding, etc., may cause the caller to block indefinitely.
1151 __private_extern__
int
1152 ubc_umount(struct mount
*mp
)
1154 vnode_iterate(mp
, 0, ubc_umcallback
, 0);
1162 * Used by ubc_umount() as an internal implementation detail; see ubc_umount()
1163 * and vnode_iterate() for details of implementation.
1166 ubc_umcallback(vnode_t vp
, __unused
void * args
)
1169 if (UBCINFOEXISTS(vp
)) {
1171 (void) ubc_msync(vp
, (off_t
)0, ubc_getsize(vp
), NULL
, UBC_PUSHALL
);
1173 return (VNODE_RETURNED
);
1180 * Get the credentials currently active for the ubc_info associated with the
1183 * Parameters: vp The vnode whose ubc_info credentials
1184 * are to be retrieved
1186 * Returns: !NOCRED The credentials
1187 * NOCRED If there is no ubc_info for the vnode,
1188 * or if there is one, but it has not had
1189 * any credentials associated with it via
1190 * a call to ubc_setcred()
1193 ubc_getcred(struct vnode
*vp
)
1195 if (UBCINFOEXISTS(vp
))
1196 return (vp
->v_ubcinfo
->ui_ucred
);
1205 * If they are not already set, set the credentials of the ubc_info structure
1206 * associated with the vnode to those of the supplied thread; otherwise leave
1209 * Parameters: vp The vnode whose ubc_info creds are to
1211 * p The process whose credentials are to
1212 * be used, if not running on an assumed
1214 * thread The thread whose credentials are to
1217 * Returns: 1 This vnode has no associated ubc_info
1220 * Notes: This function takes a proc parameter to account for bootstrap
1221 * issues where a task or thread may call this routine, either
1222 * before credentials have been initialized by bsd_init(), or if
1223 * there is no BSD info asscoiate with a mach thread yet. This
1224 * is known to happen in both the initial swap and memory mapping
1227 * This function is generally used only in the following cases:
1229 * o a memory mapped file via the mmap() system call
1230 * o a swap store backing file
1231 * o subsequent to a successful write via vn_write()
1233 * The information is then used by the NFS client in order to
1234 * cons up a wire message in either the page-in or page-out path.
1236 * There are two potential problems with the use of this API:
1238 * o Because the write path only set it on a successful
1239 * write, there is a race window between setting the
1240 * credential and its use to evict the pages to the
1241 * remote file server
1243 * o Because a page-in may occur prior to a write, the
1244 * credential may not be set at this time, if the page-in
1245 * is not the result of a mapping established via mmap().
1247 * In both these cases, this will be triggered from the paging
1248 * path, which will instead use the credential of the current
1249 * process, which in this case is either the dynamic_pager or
1250 * the kernel task, both of which utilize "root" credentials.
1252 * This may potentially permit operations to occur which should
1253 * be denied, or it may cause to be denied operations which
1254 * should be permitted, depending on the configuration of the NFS
1258 ubc_setthreadcred(struct vnode
*vp
, proc_t p
, thread_t thread
)
1260 struct ubc_info
*uip
;
1262 struct uthread
*uthread
= get_bsdthread_info(thread
);
1264 if (!UBCINFOEXISTS(vp
))
1269 uip
= vp
->v_ubcinfo
;
1270 credp
= uip
->ui_ucred
;
1272 if (!IS_VALID_CRED(credp
)) {
1273 /* use per-thread cred, if assumed identity, else proc cred */
1274 if (uthread
== NULL
|| (uthread
->uu_flag
& UT_SETUID
) == 0) {
1275 uip
->ui_ucred
= kauth_cred_proc_ref(p
);
1277 uip
->ui_ucred
= uthread
->uu_ucred
;
1278 kauth_cred_ref(uip
->ui_ucred
);
1290 * If they are not already set, set the credentials of the ubc_info structure
1291 * associated with the vnode to those of the process; otherwise leave them
1294 * Parameters: vp The vnode whose ubc_info creds are to
1296 * p The process whose credentials are to
1299 * Returns: 0 This vnode has no associated ubc_info
1302 * Notes: The return values for this function are inverted from nearly
1303 * all other uses in the kernel.
1305 * See also ubc_setthreadcred(), above.
1307 * This function is considered deprecated, and generally should
1308 * not be used, as it is incompatible with per-thread credentials;
1309 * it exists for legacy KPI reasons.
1311 * DEPRECATION: ubc_setcred() is being deprecated. Please use
1312 * ubc_setthreadcred() instead.
1315 ubc_setcred(struct vnode
*vp
, proc_t p
)
1317 struct ubc_info
*uip
;
1320 /* If there is no ubc_info, deny the operation */
1321 if ( !UBCINFOEXISTS(vp
))
1325 * Check to see if there is already a credential reference in the
1326 * ubc_info; if there is not, take one on the supplied credential.
1329 uip
= vp
->v_ubcinfo
;
1330 credp
= uip
->ui_ucred
;
1331 if (!IS_VALID_CRED(credp
)) {
1332 uip
->ui_ucred
= kauth_cred_proc_ref(p
);
1342 * Get the pager associated with the ubc_info associated with the vnode.
1344 * Parameters: vp The vnode to obtain the pager from
1346 * Returns: !VNODE_PAGER_NULL The memory_object_t for the pager
1347 * VNODE_PAGER_NULL There is no ubc_info for this vnode
1349 * Notes: For each vnode that has a ubc_info associated with it, that
1350 * ubc_info SHALL have a pager associated with it, so in the
1351 * normal case, it's impossible to return VNODE_PAGER_NULL for
1352 * a vnode with an associated ubc_info.
1354 __private_extern__ memory_object_t
1355 ubc_getpager(struct vnode
*vp
)
1357 if (UBCINFOEXISTS(vp
))
1358 return (vp
->v_ubcinfo
->ui_pager
);
1367 * Get the memory object control associated with the ubc_info associated with
1370 * Parameters: vp The vnode to obtain the memory object
1374 * Returns: !MEMORY_OBJECT_CONTROL_NULL
1375 * MEMORY_OBJECT_CONTROL_NULL
1377 * Notes: Historically, if the flags were not "do not reactivate", this
1378 * function would look up the memory object using the pager if
1379 * it did not exist (this could be the case if the vnode had
1380 * been previously reactivated). The flags would also permit a
1381 * hold to be requested, which would have created an object
1382 * reference, if one had not already existed. This usage is
1383 * deprecated, as it would permit a race between finding and
1384 * taking the reference vs. a single reference being dropped in
1387 memory_object_control_t
1388 ubc_getobject(struct vnode
*vp
, __unused
int flags
)
1390 if (UBCINFOEXISTS(vp
))
1391 return((vp
->v_ubcinfo
->ui_control
));
1393 return (MEMORY_OBJECT_CONTROL_NULL
);
1397 ubc_strict_uncached_IO(struct vnode
*vp
)
1399 boolean_t result
= FALSE
;
1401 if (UBCINFOEXISTS(vp
)) {
1402 result
= memory_object_is_slid(vp
->v_ubcinfo
->ui_control
);
1410 * Convert a given block number to a memory backing object (file) offset for a
1413 * Parameters: vp The vnode in which the block is located
1414 * blkno The block number to convert
1416 * Returns: !-1 The offset into the backing object
1417 * -1 There is no ubc_info associated with
1419 * -1 An error occurred in the underlying VFS
1420 * while translating the block to an
1421 * offset; the most likely cause is that
1422 * the caller specified a block past the
1423 * end of the file, but this could also be
1424 * any other error from VNOP_BLKTOOFF().
1426 * Note: Representing the error in band loses some information, but does
1427 * not occlude a valid offset, since an off_t of -1 is normally
1428 * used to represent EOF. If we had a more reliable constant in
1429 * our header files for it (i.e. explicitly cast to an off_t), we
1430 * would use it here instead.
1433 ubc_blktooff(vnode_t vp
, daddr64_t blkno
)
1435 off_t file_offset
= -1;
1438 if (UBCINFOEXISTS(vp
)) {
1439 error
= VNOP_BLKTOOFF(vp
, blkno
, &file_offset
);
1444 return (file_offset
);
1451 * Convert a given offset in a memory backing object into a block number for a
1454 * Parameters: vp The vnode in which the offset is
1456 * offset The offset into the backing object
1458 * Returns: !-1 The returned block number
1459 * -1 There is no ubc_info associated with
1461 * -1 An error occurred in the underlying VFS
1462 * while translating the block to an
1463 * offset; the most likely cause is that
1464 * the caller specified a block past the
1465 * end of the file, but this could also be
1466 * any other error from VNOP_OFFTOBLK().
1468 * Note: Representing the error in band loses some information, but does
1469 * not occlude a valid block number, since block numbers exceed
1470 * the valid range for offsets, due to their relative sizes. If
1471 * we had a more reliable constant than -1 in our header files
1472 * for it (i.e. explicitly cast to an daddr64_t), we would use it
1476 ubc_offtoblk(vnode_t vp
, off_t offset
)
1478 daddr64_t blkno
= -1;
1481 if (UBCINFOEXISTS(vp
)) {
1482 error
= VNOP_OFFTOBLK(vp
, offset
, &blkno
);
1492 * ubc_pages_resident
1494 * Determine whether or not a given vnode has pages resident via the memory
1495 * object control associated with the ubc_info associated with the vnode
1497 * Parameters: vp The vnode we want to know about
1503 ubc_pages_resident(vnode_t vp
)
1506 boolean_t has_pages_resident
;
1508 if (!UBCINFOEXISTS(vp
))
1512 * The following call may fail if an invalid ui_control is specified,
1513 * or if there is no VM object associated with the control object. In
1514 * either case, reacting to it as if there were no pages resident will
1515 * result in correct behavior.
1517 kret
= memory_object_pages_resident(vp
->v_ubcinfo
->ui_control
, &has_pages_resident
);
1519 if (kret
!= KERN_SUCCESS
)
1522 if (has_pages_resident
== TRUE
)
1531 * Clean and/or invalidate a range in the memory object that backs this vnode
1533 * Parameters: vp The vnode whose associated ubc_info's
1534 * associated memory object is to have a
1535 * range invalidated within it
1536 * beg_off The start of the range, as an offset
1537 * end_off The end of the range, as an offset
1538 * resid_off The address of an off_t supplied by the
1539 * caller; may be set to NULL to ignore
1540 * flags See ubc_msync_internal()
1542 * Returns: 0 Success
1543 * !0 Failure; an errno is returned
1546 * *resid_off, modified If non-NULL, the contents are ALWAYS
1547 * modified; they are initialized to the
1548 * beg_off, and in case of an I/O error,
1549 * the difference between beg_off and the
1550 * current value will reflect what was
1551 * able to be written before the error
1552 * occurred. If no error is returned, the
1553 * value of the resid_off is undefined; do
1554 * NOT use it in place of end_off if you
1555 * intend to increment from the end of the
1556 * last call and call iteratively.
1558 * Notes: see ubc_msync_internal() for more detailed information.
1562 ubc_msync(vnode_t vp
, off_t beg_off
, off_t end_off
, off_t
*resid_off
, int flags
)
1568 *resid_off
= beg_off
;
1570 retval
= ubc_msync_internal(vp
, beg_off
, end_off
, resid_off
, flags
, &io_errno
);
1572 if (retval
== 0 && io_errno
== 0)
1579 * ubc_msync_internal
1581 * Clean and/or invalidate a range in the memory object that backs this vnode
1583 * Parameters: vp The vnode whose associated ubc_info's
1584 * associated memory object is to have a
1585 * range invalidated within it
1586 * beg_off The start of the range, as an offset
1587 * end_off The end of the range, as an offset
1588 * resid_off The address of an off_t supplied by the
1589 * caller; may be set to NULL to ignore
1590 * flags MUST contain at least one of the flags
1591 * UBC_INVALIDATE, UBC_PUSHDIRTY, or
1592 * UBC_PUSHALL; if UBC_PUSHDIRTY is used,
1593 * UBC_SYNC may also be specified to cause
1594 * this function to block until the
1595 * operation is complete. The behavior
1596 * of UBC_SYNC is otherwise undefined.
1597 * io_errno The address of an int to contain the
1598 * errno from a failed I/O operation, if
1599 * one occurs; may be set to NULL to
1602 * Returns: 1 Success
1606 * *resid_off, modified The contents of this offset MAY be
1607 * modified; in case of an I/O error, the
1608 * difference between beg_off and the
1609 * current value will reflect what was
1610 * able to be written before the error
1612 * *io_errno, modified The contents of this offset are set to
1613 * an errno, if an error occurs; if the
1614 * caller supplies an io_errno parameter,
1615 * they should be careful to initialize it
1616 * to 0 before calling this function to
1617 * enable them to distinguish an error
1618 * with a valid *resid_off from an invalid
1619 * one, and to avoid potentially falsely
1620 * reporting an error, depending on use.
1622 * Notes: If there is no ubc_info associated with the vnode supplied,
1623 * this function immediately returns success.
1625 * If the value of end_off is less than or equal to beg_off, this
1626 * function immediately returns success; that is, end_off is NOT
1629 * IMPORTANT: one of the flags UBC_INVALIDATE, UBC_PUSHDIRTY, or
1630 * UBC_PUSHALL MUST be specified; that is, it is NOT possible to
1631 * attempt to block on in-progress I/O by calling this function
1632 * with UBC_PUSHDIRTY, and then later call it with just UBC_SYNC
1633 * in order to block pending on the I/O already in progress.
1635 * The start offset is truncated to the page boundary and the
1636 * size is adjusted to include the last page in the range; that
1637 * is, end_off on exactly a page boundary will not change if it
1638 * is rounded, and the range of bytes written will be from the
1639 * truncate beg_off to the rounded (end_off - 1).
1642 ubc_msync_internal(vnode_t vp
, off_t beg_off
, off_t end_off
, off_t
*resid_off
, int flags
, int *io_errno
)
1644 memory_object_size_t tsize
;
1646 int request_flags
= 0;
1647 int flush_flags
= MEMORY_OBJECT_RETURN_NONE
;
1649 if ( !UBCINFOEXISTS(vp
))
1651 if ((flags
& (UBC_INVALIDATE
| UBC_PUSHDIRTY
| UBC_PUSHALL
)) == 0)
1653 if (end_off
<= beg_off
)
1656 if (flags
& UBC_INVALIDATE
)
1658 * discard the resident pages
1660 request_flags
= (MEMORY_OBJECT_DATA_FLUSH
| MEMORY_OBJECT_DATA_NO_CHANGE
);
1662 if (flags
& UBC_SYNC
)
1664 * wait for all the I/O to complete before returning
1666 request_flags
|= MEMORY_OBJECT_IO_SYNC
;
1668 if (flags
& UBC_PUSHDIRTY
)
1670 * we only return the dirty pages in the range
1672 flush_flags
= MEMORY_OBJECT_RETURN_DIRTY
;
1674 if (flags
& UBC_PUSHALL
)
1676 * then return all the interesting pages in the range (both
1677 * dirty and precious) to the pager
1679 flush_flags
= MEMORY_OBJECT_RETURN_ALL
;
1681 beg_off
= trunc_page_64(beg_off
);
1682 end_off
= round_page_64(end_off
);
1683 tsize
= (memory_object_size_t
)end_off
- beg_off
;
1685 /* flush and/or invalidate pages in the range requested */
1686 kret
= memory_object_lock_request(vp
->v_ubcinfo
->ui_control
,
1688 (memory_object_offset_t
*)resid_off
,
1689 io_errno
, flush_flags
, request_flags
,
1692 return ((kret
== KERN_SUCCESS
) ? 1 : 0);
1699 * Explicitly map a vnode that has an associate ubc_info, and add a reference
1700 * to it for the ubc system, if there isn't one already, so it will not be
1701 * recycled while it's in use, and set flags on the ubc_info to indicate that
1704 * Parameters: vp The vnode to map
1705 * flags The mapping flags for the vnode; this
1706 * will be a combination of one or more of
1707 * PROT_READ, PROT_WRITE, and PROT_EXEC
1709 * Returns: 0 Success
1710 * EPERM Permission was denied
1712 * Notes: An I/O reference on the vnode must already be held on entry
1714 * If there is no ubc_info associated with the vnode, this function
1715 * will return success.
1717 * If a permission error occurs, this function will return
1718 * failure; all other failures will cause this function to return
1721 * IMPORTANT: This is an internal use function, and its symbols
1722 * are not exported, hence its error checking is not very robust.
1723 * It is primarily used by:
1725 * o mmap(), when mapping a file
1726 * o When mapping a shared file (a shared library in the
1727 * shared segment region)
1728 * o When loading a program image during the exec process
1730 * ...all of these uses ignore the return code, and any fault that
1731 * results later because of a failure is handled in the fix-up path
1732 * of the fault handler. The interface exists primarily as a
1735 * Given that third party implementation of the type of interfaces
1736 * that would use this function, such as alternative executable
1737 * formats, etc., are unsupported, this function is not exported
1740 * The extra reference is held until the VM system unmaps the
1741 * vnode from its own context to maintain a vnode reference in
1742 * cases like open()/mmap()/close(), which leave the backing
1743 * object referenced by a mapped memory region in a process
1746 __private_extern__
int
1747 ubc_map(vnode_t vp
, int flags
)
1749 struct ubc_info
*uip
;
1752 int need_wakeup
= 0;
1754 if (UBCINFOEXISTS(vp
)) {
1757 uip
= vp
->v_ubcinfo
;
1759 while (ISSET(uip
->ui_flags
, UI_MAPBUSY
)) {
1760 SET(uip
->ui_flags
, UI_MAPWAITING
);
1761 (void) msleep(&uip
->ui_flags
, &vp
->v_lock
,
1762 PRIBIO
, "ubc_map", NULL
);
1764 SET(uip
->ui_flags
, UI_MAPBUSY
);
1767 error
= VNOP_MMAP(vp
, flags
, vfs_context_current());
1772 vnode_lock_spin(vp
);
1775 if ( !ISSET(uip
->ui_flags
, UI_ISMAPPED
))
1777 SET(uip
->ui_flags
, (UI_WASMAPPED
| UI_ISMAPPED
));
1778 if (flags
& PROT_WRITE
) {
1779 SET(uip
->ui_flags
, UI_MAPPEDWRITE
);
1782 CLR(uip
->ui_flags
, UI_MAPBUSY
);
1784 if (ISSET(uip
->ui_flags
, UI_MAPWAITING
)) {
1785 CLR(uip
->ui_flags
, UI_MAPWAITING
);
1791 wakeup(&uip
->ui_flags
);
1803 * Destroy the named memory object associated with the ubc_info control object
1804 * associated with the designated vnode, if there is a ubc_info associated
1805 * with the vnode, and a control object is associated with it
1807 * Parameters: vp The designated vnode
1811 * Notes: This function is called on vnode termination for all vnodes,
1812 * and must therefore not assume that there is a ubc_info that is
1813 * associated with the vnode, nor that there is a control object
1814 * associated with the ubc_info.
1816 * If all the conditions necessary are present, this function
1817 * calls memory_object_destory(), which will in turn end up
1818 * calling ubc_unmap() to release any vnode references that were
1819 * established via ubc_map().
1821 * IMPORTANT: This is an internal use function that is used
1822 * exclusively by the internal use function vclean().
1824 __private_extern__
void
1825 ubc_destroy_named(vnode_t vp
)
1827 memory_object_control_t control
;
1828 struct ubc_info
*uip
;
1831 if (UBCINFOEXISTS(vp
)) {
1832 uip
= vp
->v_ubcinfo
;
1834 /* Terminate the memory object */
1835 control
= ubc_getobject(vp
, UBC_HOLDOBJECT
);
1836 if (control
!= MEMORY_OBJECT_CONTROL_NULL
) {
1837 kret
= memory_object_destroy(control
, 0);
1838 if (kret
!= KERN_SUCCESS
)
1839 panic("ubc_destroy_named: memory_object_destroy failed");
1848 * Determine whether or not a vnode is currently in use by ubc at a level in
1849 * excess of the requested busycount
1851 * Parameters: vp The vnode to check
1852 * busycount The threshold busy count, used to bias
1853 * the count usually already held by the
1854 * caller to avoid races
1856 * Returns: 1 The vnode is in use over the threshold
1857 * 0 The vnode is not in use over the
1860 * Notes: Because the vnode is only held locked while actually asking
1861 * the use count, this function only represents a snapshot of the
1862 * current state of the vnode. If more accurate information is
1863 * required, an additional busycount should be held by the caller
1864 * and a non-zero busycount used.
1866 * If there is no ubc_info associated with the vnode, this
1867 * function will report that the vnode is not in use by ubc.
1870 ubc_isinuse(struct vnode
*vp
, int busycount
)
1872 if ( !UBCINFOEXISTS(vp
))
1874 return(ubc_isinuse_locked(vp
, busycount
, 0));
1879 * ubc_isinuse_locked
1881 * Determine whether or not a vnode is currently in use by ubc at a level in
1882 * excess of the requested busycount
1884 * Parameters: vp The vnode to check
1885 * busycount The threshold busy count, used to bias
1886 * the count usually already held by the
1887 * caller to avoid races
1888 * locked True if the vnode is already locked by
1891 * Returns: 1 The vnode is in use over the threshold
1892 * 0 The vnode is not in use over the
1895 * Notes: If the vnode is not locked on entry, it is locked while
1896 * actually asking the use count. If this is the case, this
1897 * function only represents a snapshot of the current state of
1898 * the vnode. If more accurate information is required, the
1899 * vnode lock should be held by the caller, otherwise an
1900 * additional busycount should be held by the caller and a
1901 * non-zero busycount used.
1903 * If there is no ubc_info associated with the vnode, this
1904 * function will report that the vnode is not in use by ubc.
1907 ubc_isinuse_locked(struct vnode
*vp
, int busycount
, int locked
)
1913 vnode_lock_spin(vp
);
1915 if ((vp
->v_usecount
- vp
->v_kusecount
) > busycount
)
1927 * Reverse the effects of a ubc_map() call for a given vnode
1929 * Parameters: vp vnode to unmap from ubc
1933 * Notes: This is an internal use function used by vnode_pager_unmap().
1934 * It will attempt to obtain a reference on the supplied vnode,
1935 * and if it can do so, and there is an associated ubc_info, and
1936 * the flags indicate that it was mapped via ubc_map(), then the
1937 * flag is cleared, the mapping removed, and the reference taken
1938 * by ubc_map() is released.
1940 * IMPORTANT: This MUST only be called by the VM
1941 * to prevent race conditions.
1943 __private_extern__
void
1944 ubc_unmap(struct vnode
*vp
)
1946 struct ubc_info
*uip
;
1948 int need_wakeup
= 0;
1950 if (vnode_getwithref(vp
))
1953 if (UBCINFOEXISTS(vp
)) {
1954 bool want_fsevent
= false;
1957 uip
= vp
->v_ubcinfo
;
1959 while (ISSET(uip
->ui_flags
, UI_MAPBUSY
)) {
1960 SET(uip
->ui_flags
, UI_MAPWAITING
);
1961 (void) msleep(&uip
->ui_flags
, &vp
->v_lock
,
1962 PRIBIO
, "ubc_unmap", NULL
);
1964 SET(uip
->ui_flags
, UI_MAPBUSY
);
1966 if (ISSET(uip
->ui_flags
, UI_ISMAPPED
)) {
1967 if (ISSET(uip
->ui_flags
, UI_MAPPEDWRITE
))
1968 want_fsevent
= true;
1973 * We want to clear the mapped flags after we've called
1974 * VNOP_MNOMAP to avoid certain races and allow
1975 * VNOP_MNOMAP to call ubc_is_mapped_writable.
1981 vfs_context_t ctx
= vfs_context_current();
1983 (void)VNOP_MNOMAP(vp
, ctx
);
1987 * Why do we want an fsevent here? Normally the
1988 * content modified fsevent is posted when a file is
1989 * closed and only if it's written to via conventional
1990 * means. It's perfectly legal to close a file and
1991 * keep your mappings and we don't currently track
1992 * whether it was written to via a mapping.
1993 * Therefore, we need to post an fsevent here if the
1994 * file was mapped writable. This may result in false
1995 * events, i.e. we post a notification when nothing
1996 * has really changed.
1998 if (want_fsevent
&& need_fsevent(FSE_CONTENT_MODIFIED
, vp
)) {
1999 add_fsevent(FSE_CONTENT_MODIFIED
, ctx
,
2008 vnode_lock_spin(vp
);
2011 CLR(uip
->ui_flags
, UI_ISMAPPED
| UI_MAPPEDWRITE
);
2013 CLR(uip
->ui_flags
, UI_MAPBUSY
);
2015 if (ISSET(uip
->ui_flags
, UI_MAPWAITING
)) {
2016 CLR(uip
->ui_flags
, UI_MAPWAITING
);
2022 wakeup(&uip
->ui_flags
);
2026 * the drop of the vnode ref will cleanup
2035 * Manipulate individual page state for a vnode with an associated ubc_info
2036 * with an associated memory object control.
2038 * Parameters: vp The vnode backing the page
2039 * f_offset A file offset interior to the page
2040 * ops The operations to perform, as a bitmap
2041 * (see below for more information)
2042 * phys_entryp The address of a ppnum_t; may be NULL
2044 * flagsp A pointer to an int to contain flags;
2045 * may be NULL to ignore
2047 * Returns: KERN_SUCCESS Success
2048 * KERN_INVALID_ARGUMENT If the memory object control has no VM
2050 * KERN_INVALID_OBJECT If UPL_POP_PHYSICAL and the object is
2051 * not physically contiguous
2052 * KERN_INVALID_OBJECT If !UPL_POP_PHYSICAL and the object is
2053 * physically contiguous
2054 * KERN_FAILURE If the page cannot be looked up
2057 * *phys_entryp (modified) If phys_entryp is non-NULL and
2059 * *flagsp (modified) If flagsp is non-NULL and there was
2060 * !UPL_POP_PHYSICAL and a KERN_SUCCESS
2062 * Notes: For object boundaries, it is considerably more efficient to
2063 * ensure that f_offset is in fact on a page boundary, as this
2064 * will avoid internal use of the hash table to identify the
2065 * page, and would therefore skip a number of early optimizations.
2066 * Since this is a page operation anyway, the caller should try
2067 * to pass only a page aligned offset because of this.
2069 * *flagsp may be modified even if this function fails. If it is
2070 * modified, it will contain the condition of the page before the
2071 * requested operation was attempted; these will only include the
2072 * bitmap flags, and not the PL_POP_PHYSICAL, UPL_POP_DUMP,
2073 * UPL_POP_SET, or UPL_POP_CLR bits.
2075 * The flags field may contain a specific operation, such as
2076 * UPL_POP_PHYSICAL or UPL_POP_DUMP:
2078 * o UPL_POP_PHYSICAL Fail if not contiguous; if
2079 * *phys_entryp and successful, set
2081 * o UPL_POP_DUMP Dump the specified page
2083 * Otherwise, it is treated as a bitmap of one or more page
2084 * operations to perform on the final memory object; allowable
2087 * o UPL_POP_DIRTY The page is dirty
2088 * o UPL_POP_PAGEOUT The page is paged out
2089 * o UPL_POP_PRECIOUS The page is precious
2090 * o UPL_POP_ABSENT The page is absent
2091 * o UPL_POP_BUSY The page is busy
2093 * If the page status is only being queried and not modified, then
2094 * not other bits should be specified. However, if it is being
2095 * modified, exactly ONE of the following bits should be set:
2097 * o UPL_POP_SET Set the current bitmap bits
2098 * o UPL_POP_CLR Clear the current bitmap bits
2100 * Thus to effect a combination of setting an clearing, it may be
2101 * necessary to call this function twice. If this is done, the
2102 * set should be used before the clear, since clearing may trigger
2103 * a wakeup on the destination page, and if the page is backed by
2104 * an encrypted swap file, setting will trigger the decryption
2105 * needed before the wakeup occurs.
2112 ppnum_t
*phys_entryp
,
2115 memory_object_control_t control
;
2117 control
= ubc_getobject(vp
, UBC_FLAGS_NONE
);
2118 if (control
== MEMORY_OBJECT_CONTROL_NULL
)
2119 return KERN_INVALID_ARGUMENT
;
2121 return (memory_object_page_op(control
,
2122 (memory_object_offset_t
)f_offset
,
2132 * Manipulate page state for a range of memory for a vnode with an associated
2133 * ubc_info with an associated memory object control, when page level state is
2134 * not required to be returned from the call (i.e. there are no phys_entryp or
2135 * flagsp parameters to this call, and it takes a range which may contain
2136 * multiple pages, rather than an offset interior to a single page).
2138 * Parameters: vp The vnode backing the page
2139 * f_offset_beg A file offset interior to the start page
2140 * f_offset_end A file offset interior to the end page
2141 * ops The operations to perform, as a bitmap
2142 * (see below for more information)
2143 * range The address of an int; may be NULL to
2146 * Returns: KERN_SUCCESS Success
2147 * KERN_INVALID_ARGUMENT If the memory object control has no VM
2149 * KERN_INVALID_OBJECT If the object is physically contiguous
2152 * *range (modified) If range is non-NULL, its contents will
2153 * be modified to contain the number of
2154 * bytes successfully operated upon.
2156 * Notes: IMPORTANT: This function cannot be used on a range that
2157 * consists of physically contiguous pages.
2159 * For object boundaries, it is considerably more efficient to
2160 * ensure that f_offset_beg and f_offset_end are in fact on page
2161 * boundaries, as this will avoid internal use of the hash table
2162 * to identify the page, and would therefore skip a number of
2163 * early optimizations. Since this is an operation on a set of
2164 * pages anyway, the caller should try to pass only a page aligned
2165 * offsets because of this.
2167 * *range will be modified only if this function succeeds.
2169 * The flags field MUST contain a specific operation; allowable
2172 * o UPL_ROP_ABSENT Returns the extent of the range
2173 * presented which is absent, starting
2174 * with the start address presented
2176 * o UPL_ROP_PRESENT Returns the extent of the range
2177 * presented which is present (resident),
2178 * starting with the start address
2180 * o UPL_ROP_DUMP Dump the pages which are found in the
2181 * target object for the target range.
2183 * IMPORTANT: For UPL_ROP_ABSENT and UPL_ROP_PRESENT; if there are
2184 * multiple regions in the range, only the first matching region
2195 memory_object_control_t control
;
2197 control
= ubc_getobject(vp
, UBC_FLAGS_NONE
);
2198 if (control
== MEMORY_OBJECT_CONTROL_NULL
)
2199 return KERN_INVALID_ARGUMENT
;
2201 return (memory_object_range_op(control
,
2202 (memory_object_offset_t
)f_offset_beg
,
2203 (memory_object_offset_t
)f_offset_end
,
2212 * Given a vnode, cause the population of a portion of the vm_object; based on
2213 * the nature of the request, the pages returned may contain valid data, or
2214 * they may be uninitialized.
2216 * Parameters: vp The vnode from which to create the upl
2217 * f_offset The start offset into the backing store
2218 * represented by the vnode
2219 * bufsize The size of the upl to create
2220 * uplp Pointer to the upl_t to receive the
2221 * created upl; MUST NOT be NULL
2222 * plp Pointer to receive the internal page
2223 * list for the created upl; MAY be NULL
2226 * Returns: KERN_SUCCESS The requested upl has been created
2227 * KERN_INVALID_ARGUMENT The bufsize argument is not an even
2228 * multiple of the page size
2229 * KERN_INVALID_ARGUMENT There is no ubc_info associated with
2230 * the vnode, or there is no memory object
2231 * control associated with the ubc_info
2232 * memory_object_upl_request:KERN_INVALID_VALUE
2233 * The supplied upl_flags argument is
2237 * *plp (modified) If non-NULL, the value of *plp will be
2238 * modified to point to the internal page
2239 * list; this modification may occur even
2240 * if this function is unsuccessful, in
2241 * which case the contents may be invalid
2243 * Note: If successful, the returned *uplp MUST subsequently be freed
2244 * via a call to ubc_upl_commit(), ubc_upl_commit_range(),
2245 * ubc_upl_abort(), or ubc_upl_abort_range().
2253 upl_page_info_t
**plp
,
2256 memory_object_control_t control
;
2263 if (bufsize
& 0xfff)
2264 return KERN_INVALID_ARGUMENT
;
2266 if (bufsize
> MAX_UPL_SIZE_BYTES
)
2267 return KERN_INVALID_ARGUMENT
;
2269 if (uplflags
& (UPL_UBC_MSYNC
| UPL_UBC_PAGEOUT
| UPL_UBC_PAGEIN
)) {
2271 if (uplflags
& UPL_UBC_MSYNC
) {
2272 uplflags
&= UPL_RET_ONLY_DIRTY
;
2274 uplflags
|= UPL_COPYOUT_FROM
| UPL_CLEAN_IN_PLACE
|
2275 UPL_SET_INTERNAL
| UPL_SET_LITE
;
2277 } else if (uplflags
& UPL_UBC_PAGEOUT
) {
2278 uplflags
&= UPL_RET_ONLY_DIRTY
;
2280 if (uplflags
& UPL_RET_ONLY_DIRTY
)
2281 uplflags
|= UPL_NOBLOCK
;
2283 uplflags
|= UPL_FOR_PAGEOUT
| UPL_CLEAN_IN_PLACE
|
2284 UPL_COPYOUT_FROM
| UPL_SET_INTERNAL
| UPL_SET_LITE
;
2286 uplflags
|= UPL_RET_ONLY_ABSENT
|
2287 UPL_NO_SYNC
| UPL_CLEAN_IN_PLACE
|
2288 UPL_SET_INTERNAL
| UPL_SET_LITE
;
2291 * if the requested size == PAGE_SIZE, we don't want to set
2292 * the UPL_NOBLOCK since we may be trying to recover from a
2293 * previous partial pagein I/O that occurred because we were low
2294 * on memory and bailed early in order to honor the UPL_NOBLOCK...
2295 * since we're only asking for a single page, we can block w/o fear
2296 * of tying up pages while waiting for more to become available
2298 if (bufsize
> PAGE_SIZE
)
2299 uplflags
|= UPL_NOBLOCK
;
2302 uplflags
&= ~UPL_FOR_PAGEOUT
;
2304 if (uplflags
& UPL_WILL_BE_DUMPED
) {
2305 uplflags
&= ~UPL_WILL_BE_DUMPED
;
2306 uplflags
|= (UPL_NO_SYNC
|UPL_SET_INTERNAL
);
2308 uplflags
|= (UPL_NO_SYNC
|UPL_CLEAN_IN_PLACE
|UPL_SET_INTERNAL
);
2310 control
= ubc_getobject(vp
, UBC_FLAGS_NONE
);
2311 if (control
== MEMORY_OBJECT_CONTROL_NULL
)
2312 return KERN_INVALID_ARGUMENT
;
2314 kr
= memory_object_upl_request(control
, f_offset
, bufsize
, uplp
, NULL
, NULL
, uplflags
);
2315 if (kr
== KERN_SUCCESS
&& plp
!= NULL
)
2316 *plp
= UPL_GET_INTERNAL_PAGE_LIST(*uplp
);
2322 * ubc_upl_maxbufsize
2324 * Return the maximum bufsize ubc_create_upl( ) will take.
2328 * Returns: maximum size buffer (in bytes) ubc_create_upl( ) will take.
2334 return(MAX_UPL_SIZE_BYTES
);
2340 * Map the page list assocated with the supplied upl into the kernel virtual
2341 * address space at the virtual address indicated by the dst_addr argument;
2342 * the entire upl is mapped
2344 * Parameters: upl The upl to map
2345 * dst_addr The address at which to map the upl
2347 * Returns: KERN_SUCCESS The upl has been mapped
2348 * KERN_INVALID_ARGUMENT The upl is UPL_NULL
2349 * KERN_FAILURE The upl is already mapped
2350 * vm_map_enter:KERN_INVALID_ARGUMENT
2351 * A failure code from vm_map_enter() due
2352 * to an invalid argument
2357 vm_offset_t
*dst_addr
)
2359 return (vm_upl_map(kernel_map
, upl
, dst_addr
));
2366 * Unmap the page list assocated with the supplied upl from the kernel virtual
2367 * address space; the entire upl is unmapped.
2369 * Parameters: upl The upl to unmap
2371 * Returns: KERN_SUCCESS The upl has been unmapped
2372 * KERN_FAILURE The upl is not currently mapped
2373 * KERN_INVALID_ARGUMENT If the upl is UPL_NULL
2379 return(vm_upl_unmap(kernel_map
, upl
));
2386 * Commit the contents of the upl to the backing store
2388 * Parameters: upl The upl to commit
2390 * Returns: KERN_SUCCESS The upl has been committed
2391 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
2392 * KERN_FAILURE The supplied upl does not represent
2393 * device memory, and the offset plus the
2394 * size would exceed the actual size of
2397 * Notes: In practice, the only return value for this function should be
2398 * KERN_SUCCESS, unless there has been data structure corruption;
2399 * since the upl is deallocated regardless of success or failure,
2400 * there's really nothing to do about this other than panic.
2402 * IMPORTANT: Use of this function should not be mixed with use of
2403 * ubc_upl_commit_range(), due to the unconditional deallocation
2410 upl_page_info_t
*pl
;
2413 pl
= UPL_GET_INTERNAL_PAGE_LIST(upl
);
2414 kr
= upl_commit(upl
, pl
, MAX_UPL_SIZE_BYTES
>> PAGE_SHIFT
);
2415 upl_deallocate(upl
);
2423 * Commit the contents of the specified range of the upl to the backing store
2425 * Parameters: upl The upl to commit
2426 * offset The offset into the upl
2427 * size The size of the region to be committed,
2428 * starting at the specified offset
2429 * flags commit type (see below)
2431 * Returns: KERN_SUCCESS The range has been committed
2432 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
2433 * KERN_FAILURE The supplied upl does not represent
2434 * device memory, and the offset plus the
2435 * size would exceed the actual size of
2438 * Notes: IMPORTANT: If the commit is successful, and the object is now
2439 * empty, the upl will be deallocated. Since the caller cannot
2440 * check that this is the case, the UPL_COMMIT_FREE_ON_EMPTY flag
2441 * should generally only be used when the offset is 0 and the size
2442 * is equal to the upl size.
2444 * The flags argument is a bitmap of flags on the rage of pages in
2445 * the upl to be committed; allowable flags are:
2447 * o UPL_COMMIT_FREE_ON_EMPTY Free the upl when it is
2448 * both empty and has been
2449 * successfully committed
2450 * o UPL_COMMIT_CLEAR_DIRTY Clear each pages dirty
2451 * bit; will prevent a
2453 * o UPL_COMMIT_SET_DIRTY Set each pages dirty
2454 * bit; will cause a later
2456 * o UPL_COMMIT_INACTIVATE Clear each pages
2457 * reference bit; the page
2458 * will not be accessed
2459 * o UPL_COMMIT_ALLOW_ACCESS Unbusy each page; pages
2460 * become busy when an
2461 * IOMemoryDescriptor is
2462 * mapped or redirected,
2463 * and we have to wait for
2466 * The flag UPL_COMMIT_NOTIFY_EMPTY is used internally, and should
2467 * not be specified by the caller.
2469 * The UPL_COMMIT_CLEAR_DIRTY and UPL_COMMIT_SET_DIRTY flags are
2470 * mutually exclusive, and should not be combined.
2473 ubc_upl_commit_range(
2475 upl_offset_t offset
,
2479 upl_page_info_t
*pl
;
2483 if (flags
& UPL_COMMIT_FREE_ON_EMPTY
)
2484 flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
2486 if (flags
& UPL_COMMIT_KERNEL_ONLY_FLAGS
) {
2487 return KERN_INVALID_ARGUMENT
;
2490 pl
= UPL_GET_INTERNAL_PAGE_LIST(upl
);
2492 kr
= upl_commit_range(upl
, offset
, size
, flags
,
2493 pl
, MAX_UPL_SIZE_BYTES
>> PAGE_SHIFT
, &empty
);
2495 if((flags
& UPL_COMMIT_FREE_ON_EMPTY
) && empty
)
2496 upl_deallocate(upl
);
2503 * ubc_upl_abort_range
2505 * Abort the contents of the specified range of the specified upl
2507 * Parameters: upl The upl to abort
2508 * offset The offset into the upl
2509 * size The size of the region to be aborted,
2510 * starting at the specified offset
2511 * abort_flags abort type (see below)
2513 * Returns: KERN_SUCCESS The range has been aborted
2514 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
2515 * KERN_FAILURE The supplied upl does not represent
2516 * device memory, and the offset plus the
2517 * size would exceed the actual size of
2520 * Notes: IMPORTANT: If the abort is successful, and the object is now
2521 * empty, the upl will be deallocated. Since the caller cannot
2522 * check that this is the case, the UPL_ABORT_FREE_ON_EMPTY flag
2523 * should generally only be used when the offset is 0 and the size
2524 * is equal to the upl size.
2526 * The abort_flags argument is a bitmap of flags on the range of
2527 * pages in the upl to be aborted; allowable flags are:
2529 * o UPL_ABORT_FREE_ON_EMPTY Free the upl when it is both
2530 * empty and has been successfully
2532 * o UPL_ABORT_RESTART The operation must be restarted
2533 * o UPL_ABORT_UNAVAILABLE The pages are unavailable
2534 * o UPL_ABORT_ERROR An I/O error occurred
2535 * o UPL_ABORT_DUMP_PAGES Just free the pages
2536 * o UPL_ABORT_NOTIFY_EMPTY RESERVED
2537 * o UPL_ABORT_ALLOW_ACCESS RESERVED
2539 * The UPL_ABORT_NOTIFY_EMPTY is an internal use flag and should
2540 * not be specified by the caller. It is intended to fulfill the
2541 * same role as UPL_COMMIT_NOTIFY_EMPTY does in the function
2542 * ubc_upl_commit_range(), but is never referenced internally.
2544 * The UPL_ABORT_ALLOW_ACCESS is defined, but neither set nor
2545 * referenced; do not use it.
2548 ubc_upl_abort_range(
2550 upl_offset_t offset
,
2555 boolean_t empty
= FALSE
;
2557 if (abort_flags
& UPL_ABORT_FREE_ON_EMPTY
)
2558 abort_flags
|= UPL_ABORT_NOTIFY_EMPTY
;
2560 kr
= upl_abort_range(upl
, offset
, size
, abort_flags
, &empty
);
2562 if((abort_flags
& UPL_ABORT_FREE_ON_EMPTY
) && empty
)
2563 upl_deallocate(upl
);
2572 * Abort the contents of the specified upl
2574 * Parameters: upl The upl to abort
2575 * abort_type abort type (see below)
2577 * Returns: KERN_SUCCESS The range has been aborted
2578 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
2579 * KERN_FAILURE The supplied upl does not represent
2580 * device memory, and the offset plus the
2581 * size would exceed the actual size of
2584 * Notes: IMPORTANT: If the abort is successful, and the object is now
2585 * empty, the upl will be deallocated. Since the caller cannot
2586 * check that this is the case, the UPL_ABORT_FREE_ON_EMPTY flag
2587 * should generally only be used when the offset is 0 and the size
2588 * is equal to the upl size.
2590 * The abort_type is a bitmap of flags on the range of
2591 * pages in the upl to be aborted; allowable flags are:
2593 * o UPL_ABORT_FREE_ON_EMPTY Free the upl when it is both
2594 * empty and has been successfully
2596 * o UPL_ABORT_RESTART The operation must be restarted
2597 * o UPL_ABORT_UNAVAILABLE The pages are unavailable
2598 * o UPL_ABORT_ERROR An I/O error occurred
2599 * o UPL_ABORT_DUMP_PAGES Just free the pages
2600 * o UPL_ABORT_NOTIFY_EMPTY RESERVED
2601 * o UPL_ABORT_ALLOW_ACCESS RESERVED
2603 * The UPL_ABORT_NOTIFY_EMPTY is an internal use flag and should
2604 * not be specified by the caller. It is intended to fulfill the
2605 * same role as UPL_COMMIT_NOTIFY_EMPTY does in the function
2606 * ubc_upl_commit_range(), but is never referenced internally.
2608 * The UPL_ABORT_ALLOW_ACCESS is defined, but neither set nor
2609 * referenced; do not use it.
2618 kr
= upl_abort(upl
, abort_type
);
2619 upl_deallocate(upl
);
2627 * Retrieve the internal page list for the specified upl
2629 * Parameters: upl The upl to obtain the page list from
2631 * Returns: !NULL The (upl_page_info_t *) for the page
2632 * list internal to the upl
2633 * NULL Error/no page list associated
2635 * Notes: IMPORTANT: The function is only valid on internal objects
2636 * where the list request was made with the UPL_INTERNAL flag.
2638 * This function is a utility helper function, since some callers
2639 * may not have direct access to the header defining the macro,
2640 * due to abstraction layering constraints.
2646 return (UPL_GET_INTERNAL_PAGE_LIST(upl
));
2651 UBCINFOEXISTS(const struct vnode
* vp
)
2653 return((vp
) && ((vp
)->v_type
== VREG
) && ((vp
)->v_ubcinfo
!= UBC_INFO_NULL
));
2658 ubc_upl_range_needed(
2663 upl_range_needed(upl
, index
, count
);
2666 boolean_t
ubc_is_mapped(const struct vnode
*vp
, boolean_t
*writable
)
2668 if (!UBCINFOEXISTS(vp
) || !ISSET(vp
->v_ubcinfo
->ui_flags
, UI_ISMAPPED
))
2671 *writable
= ISSET(vp
->v_ubcinfo
->ui_flags
, UI_MAPPEDWRITE
);
2675 boolean_t
ubc_is_mapped_writable(const struct vnode
*vp
)
2678 return ubc_is_mapped(vp
, &writable
) && writable
;
2685 #define CS_BLOB_PAGEABLE 0
2686 static volatile SInt32 cs_blob_size
= 0;
2687 static volatile SInt32 cs_blob_count
= 0;
2688 static SInt32 cs_blob_size_peak
= 0;
2689 static UInt32 cs_blob_size_max
= 0;
2690 static SInt32 cs_blob_count_peak
= 0;
2692 SYSCTL_INT(_vm
, OID_AUTO
, cs_blob_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, (int *)(uintptr_t)&cs_blob_count
, 0, "Current number of code signature blobs");
2693 SYSCTL_INT(_vm
, OID_AUTO
, cs_blob_size
, CTLFLAG_RD
| CTLFLAG_LOCKED
, (int *)(uintptr_t)&cs_blob_size
, 0, "Current size of all code signature blobs");
2694 SYSCTL_INT(_vm
, OID_AUTO
, cs_blob_count_peak
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_blob_count_peak
, 0, "Peak number of code signature blobs");
2695 SYSCTL_INT(_vm
, OID_AUTO
, cs_blob_size_peak
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_blob_size_peak
, 0, "Peak size of code signature blobs");
2696 SYSCTL_INT(_vm
, OID_AUTO
, cs_blob_size_max
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_blob_size_max
, 0, "Size of biggest code signature blob");
2699 * Function: csblob_parse_teamid
2701 * Description: This function returns a pointer to the team id
2702 stored within the codedirectory of the csblob.
2703 If the codedirectory predates team-ids, it returns
2705 This does not copy the name but returns a pointer to
2706 it within the CD. Subsequently, the CD must be
2707 available when this is used.
2711 csblob_parse_teamid(struct cs_blob
*csblob
)
2713 const CS_CodeDirectory
*cd
;
2715 cd
= csblob
->csb_cd
;
2717 if (ntohl(cd
->version
) < CS_SUPPORTSTEAMID
)
2720 if (cd
->teamOffset
== 0)
2723 const char *name
= ((const char *)cd
) + ntohl(cd
->teamOffset
);
2725 printf("found team-id %s in cdblob\n", name
);
2732 ubc_cs_blob_allocate(
2733 vm_offset_t
*blob_addr_p
,
2734 vm_size_t
*blob_size_p
)
2738 #if CS_BLOB_PAGEABLE
2739 *blob_size_p
= round_page(*blob_size_p
);
2740 kr
= kmem_alloc(kernel_map
, blob_addr_p
, *blob_size_p
, VM_KERN_MEMORY_SECURITY
);
2741 #else /* CS_BLOB_PAGEABLE */
2742 *blob_addr_p
= (vm_offset_t
) kalloc_tag(*blob_size_p
, VM_KERN_MEMORY_SECURITY
);
2743 if (*blob_addr_p
== 0) {
2748 #endif /* CS_BLOB_PAGEABLE */
2753 ubc_cs_blob_deallocate(
2754 vm_offset_t blob_addr
,
2755 vm_size_t blob_size
)
2757 #if CS_BLOB_PAGEABLE
2758 kmem_free(kernel_map
, blob_addr
, blob_size
);
2759 #else /* CS_BLOB_PAGEABLE */
2760 kfree((void *) blob_addr
, blob_size
);
2761 #endif /* CS_BLOB_PAGEABLE */
2772 struct cs_blob
**ret_blob
)
2775 struct ubc_info
*uip
;
2776 struct cs_blob
*blob
, *oblob
;
2778 ipc_port_t blob_handle
;
2779 memory_object_size_t blob_size
;
2780 const CS_CodeDirectory
*cd
;
2781 off_t blob_start_offset
, blob_end_offset
;
2782 union cs_hash_union mdctx
;
2783 boolean_t record_mtime
;
2786 record_mtime
= FALSE
;
2791 blob_handle
= IPC_PORT_NULL
;
2793 blob
= (struct cs_blob
*) kalloc(sizeof (struct cs_blob
));
2798 #if CS_BLOB_PAGEABLE
2799 /* get a memory entry on the blob */
2800 blob_size
= (memory_object_size_t
) size
;
2801 kr
= mach_make_memory_entry_64(kernel_map
,
2807 if (kr
!= KERN_SUCCESS
) {
2811 if (memory_object_round_page(blob_size
) !=
2812 (memory_object_size_t
) round_page(size
)) {
2813 printf("ubc_cs_blob_add: size mismatch 0x%llx 0x%lx !?\n",
2814 blob_size
, (size_t)size
);
2815 panic("XXX FBDP size mismatch 0x%llx 0x%lx\n", blob_size
, (size_t)size
);
2820 blob_size
= (memory_object_size_t
) size
;
2821 blob_handle
= IPC_PORT_NULL
;
2824 /* fill in the new blob */
2825 blob
->csb_cpu_type
= cputype
;
2826 blob
->csb_base_offset
= base_offset
;
2827 blob
->csb_mem_size
= size
;
2828 blob
->csb_mem_offset
= 0;
2829 blob
->csb_mem_handle
= blob_handle
;
2830 blob
->csb_mem_kaddr
= addr
;
2831 blob
->csb_flags
= 0;
2832 blob
->csb_platform_binary
= 0;
2833 blob
->csb_platform_path
= 0;
2834 blob
->csb_teamid
= NULL
;
2837 * Validate the blob's contents
2840 error
= cs_validate_csblob((const uint8_t *)addr
, size
, &cd
);
2844 printf("CODESIGNING: csblob invalid: %d\n", error
);
2845 /* The vnode checker can't make the rest of this function succeed if csblob validation failed, so bail */
2849 const unsigned char *md_base
;
2850 uint8_t hash
[CS_HASH_MAX_SIZE
];
2853 #if CS_BLOB_PAGEABLE
2854 #error "cd might move under CS_BLOB_PAGEABLE; reconsider this code"
2857 blob
->csb_hashtype
= cs_find_md(cd
->hashType
);
2858 if (blob
->csb_hashtype
== NULL
|| blob
->csb_hashtype
->cs_digest_size
> sizeof(hash
))
2859 panic("validated CodeDirectory but unsupported type");
2861 blob
->csb_flags
= (ntohl(cd
->flags
) & CS_ALLOWED_MACHO
) | CS_VALID
;
2862 blob
->csb_end_offset
= round_page_4K(ntohl(cd
->codeLimit
));
2863 if((ntohl(cd
->version
) >= CS_SUPPORTSSCATTER
) && (ntohl(cd
->scatterOffset
))) {
2864 const SC_Scatter
*scatter
= (const SC_Scatter
*)
2865 ((const char*)cd
+ ntohl(cd
->scatterOffset
));
2866 blob
->csb_start_offset
= ntohl(scatter
->base
) * PAGE_SIZE_4K
;
2868 blob
->csb_start_offset
= 0;
2870 /* compute the blob's cdhash */
2871 md_base
= (const unsigned char *) cd
;
2872 md_size
= ntohl(cd
->length
);
2874 blob
->csb_hashtype
->cs_init(&mdctx
);
2875 blob
->csb_hashtype
->cs_update(&mdctx
, md_base
, md_size
);
2876 blob
->csb_hashtype
->cs_final(hash
, &mdctx
);
2878 memcpy(blob
->csb_cdhash
, hash
, CS_CDHASH_LEN
);
2882 * Let policy module check whether the blob's signature is accepted.
2885 error
= mac_vnode_check_signature(vp
,
2888 (const void*)addr
, size
,
2892 printf("check_signature[pid: %d], error = %d\n", current_proc()->p_pid
, error
);
2895 if ((flags
& MAC_VNODE_CHECK_DYLD_SIM
) && !(cs_flags
& CS_PLATFORM_BINARY
)) {
2897 printf("check_signature[pid: %d], is not apple signed\n", current_proc()->p_pid
);
2903 if (cs_flags
& CS_PLATFORM_BINARY
) {
2905 printf("check_signature[pid: %d]: platform binary\n", current_proc()->p_pid
);
2906 blob
->csb_platform_binary
= 1;
2907 blob
->csb_platform_path
= !!(cs_flags
& CS_PLATFORM_PATH
);
2909 blob
->csb_platform_binary
= 0;
2910 blob
->csb_platform_path
= 0;
2911 blob
->csb_teamid
= csblob_parse_teamid(blob
);
2913 if (blob
->csb_teamid
)
2914 printf("check_signature[pid: %d]: team-id is %s\n", current_proc()->p_pid
, blob
->csb_teamid
);
2916 printf("check_signature[pid: %d]: no team-id\n", current_proc()->p_pid
);
2921 * Validate the blob's coverage
2923 blob_start_offset
= blob
->csb_base_offset
+ blob
->csb_start_offset
;
2924 blob_end_offset
= blob
->csb_base_offset
+ blob
->csb_end_offset
;
2926 if (blob_start_offset
>= blob_end_offset
||
2927 blob_start_offset
< 0 ||
2928 blob_end_offset
<= 0) {
2929 /* reject empty or backwards blob */
2935 if (! UBCINFOEXISTS(vp
)) {
2940 uip
= vp
->v_ubcinfo
;
2942 /* check if this new blob overlaps with an existing blob */
2943 for (oblob
= uip
->cs_blobs
;
2945 oblob
= oblob
->csb_next
) {
2946 off_t oblob_start_offset
, oblob_end_offset
;
2948 /* check for conflicting teamid */
2949 if (blob
->csb_platform_binary
) { //platform binary needs to be the same for app slices
2950 if (!oblob
->csb_platform_binary
) {
2955 } else if (blob
->csb_teamid
) { //teamid binary needs to be the same for app slices
2956 if (oblob
->csb_platform_binary
||
2957 oblob
->csb_teamid
== NULL
||
2958 strcmp(oblob
->csb_teamid
, blob
->csb_teamid
) != 0) {
2963 } else { // non teamid binary needs to be the same for app slices
2964 if (oblob
->csb_platform_binary
||
2965 oblob
->csb_teamid
!= NULL
) {
2972 oblob_start_offset
= (oblob
->csb_base_offset
+
2973 oblob
->csb_start_offset
);
2974 oblob_end_offset
= (oblob
->csb_base_offset
+
2975 oblob
->csb_end_offset
);
2976 if (blob_start_offset
>= oblob_end_offset
||
2977 blob_end_offset
<= oblob_start_offset
) {
2978 /* no conflict with this existing blob */
2981 if (blob_start_offset
== oblob_start_offset
&&
2982 blob_end_offset
== oblob_end_offset
&&
2983 blob
->csb_mem_size
== oblob
->csb_mem_size
&&
2984 blob
->csb_flags
== oblob
->csb_flags
&&
2985 (blob
->csb_cpu_type
== CPU_TYPE_ANY
||
2986 oblob
->csb_cpu_type
== CPU_TYPE_ANY
||
2987 blob
->csb_cpu_type
== oblob
->csb_cpu_type
) &&
2988 !bcmp(blob
->csb_cdhash
,
2992 * We already have this blob:
2993 * we'll return success but
2994 * throw away the new blob.
2996 if (oblob
->csb_cpu_type
== CPU_TYPE_ANY
) {
2998 * The old blob matches this one
2999 * but doesn't have any CPU type.
3000 * Update it with whatever the caller
3001 * provided this time.
3003 oblob
->csb_cpu_type
= cputype
;
3011 /* different blob: reject the new one */
3021 /* mark this vnode's VM object as having "signed pages" */
3022 kr
= memory_object_signed(uip
->ui_control
, TRUE
);
3023 if (kr
!= KERN_SUCCESS
) {
3029 if (uip
->cs_blobs
== NULL
) {
3030 /* loading 1st blob: record the file's current "modify time" */
3031 record_mtime
= TRUE
;
3034 /* set the generation count for cs_blobs */
3035 uip
->cs_add_gen
= cs_blob_generation_count
;
3038 * Add this blob to the list of blobs for this vnode.
3039 * We always add at the front of the list and we never remove a
3040 * blob from the list, so ubc_cs_get_blobs() can return whatever
3041 * the top of the list was and that list will remain valid
3042 * while we validate a page, even after we release the vnode's lock.
3044 blob
->csb_next
= uip
->cs_blobs
;
3045 uip
->cs_blobs
= blob
;
3047 OSAddAtomic(+1, &cs_blob_count
);
3048 if (cs_blob_count
> cs_blob_count_peak
) {
3049 cs_blob_count_peak
= cs_blob_count
; /* XXX atomic ? */
3051 OSAddAtomic((SInt32
) +blob
->csb_mem_size
, &cs_blob_size
);
3052 if ((SInt32
) cs_blob_size
> cs_blob_size_peak
) {
3053 cs_blob_size_peak
= (SInt32
) cs_blob_size
; /* XXX atomic ? */
3055 if ((UInt32
) blob
->csb_mem_size
> cs_blob_size_max
) {
3056 cs_blob_size_max
= (UInt32
) blob
->csb_mem_size
;
3061 const char *name
= vnode_getname_printable(vp
);
3063 printf("CODE SIGNING: proc %d(%s) "
3064 "loaded %s signatures for file (%s) "
3065 "range 0x%llx:0x%llx flags 0x%x\n",
3066 p
->p_pid
, p
->p_comm
,
3067 blob
->csb_cpu_type
== -1 ? "detached" : "embedded",
3069 blob
->csb_base_offset
+ blob
->csb_start_offset
,
3070 blob
->csb_base_offset
+ blob
->csb_end_offset
,
3072 vnode_putname_printable(name
);
3078 vnode_mtime(vp
, &uip
->cs_mtime
, vfs_context_current());
3084 error
= 0; /* success ! */
3089 printf("check_signature[pid: %d]: error = %d\n", current_proc()->p_pid
, error
);
3091 /* we failed; release what we allocated */
3093 kfree(blob
, sizeof (*blob
));
3096 if (blob_handle
!= IPC_PORT_NULL
) {
3097 mach_memory_entry_port_release(blob_handle
);
3098 blob_handle
= IPC_PORT_NULL
;
3102 if (error
== EAGAIN
) {
3104 * See above: error is EAGAIN if we were asked
3105 * to add an existing blob again. We cleaned the new
3106 * blob and we want to return success.
3110 * Since we're not failing, consume the data we received.
3112 ubc_cs_blob_deallocate(addr
, size
);
3119 csvnode_print_debug(struct vnode
*vp
)
3121 const char *name
= NULL
;
3122 struct ubc_info
*uip
;
3123 struct cs_blob
*blob
;
3125 name
= vnode_getname_printable(vp
);
3127 printf("csvnode: name: %s\n", name
);
3128 vnode_putname_printable(name
);
3131 vnode_lock_spin(vp
);
3133 if (! UBCINFOEXISTS(vp
)) {
3138 uip
= vp
->v_ubcinfo
;
3139 for (blob
= uip
->cs_blobs
; blob
!= NULL
; blob
= blob
->csb_next
) {
3140 printf("csvnode: range: %lu -> %lu flags: 0x%08x platform: %s path: %s team: %s\n",
3141 (unsigned long)blob
->csb_start_offset
,
3142 (unsigned long)blob
->csb_end_offset
,
3144 blob
->csb_platform_binary
? "yes" : "no",
3145 blob
->csb_platform_path
? "yes" : "no",
3146 blob
->csb_teamid
? blob
->csb_teamid
: "<NO-TEAM>");
3160 struct ubc_info
*uip
;
3161 struct cs_blob
*blob
;
3162 off_t offset_in_blob
;
3164 vnode_lock_spin(vp
);
3166 if (! UBCINFOEXISTS(vp
)) {
3171 uip
= vp
->v_ubcinfo
;
3172 for (blob
= uip
->cs_blobs
;
3174 blob
= blob
->csb_next
) {
3175 if (cputype
!= -1 && blob
->csb_cpu_type
== cputype
) {
3179 offset_in_blob
= offset
- blob
->csb_base_offset
;
3180 if (offset_in_blob
>= blob
->csb_start_offset
&&
3181 offset_in_blob
< blob
->csb_end_offset
) {
3182 /* our offset is covered by this blob */
3196 struct ubc_info
*uip
)
3198 struct cs_blob
*blob
, *next_blob
;
3200 for (blob
= uip
->cs_blobs
;
3203 next_blob
= blob
->csb_next
;
3204 if (blob
->csb_mem_kaddr
!= 0) {
3205 ubc_cs_blob_deallocate(blob
->csb_mem_kaddr
,
3206 blob
->csb_mem_size
);
3207 blob
->csb_mem_kaddr
= 0;
3209 if (blob
->csb_mem_handle
!= IPC_PORT_NULL
) {
3210 mach_memory_entry_port_release(blob
->csb_mem_handle
);
3212 blob
->csb_mem_handle
= IPC_PORT_NULL
;
3213 OSAddAtomic(-1, &cs_blob_count
);
3214 OSAddAtomic((SInt32
) -blob
->csb_mem_size
, &cs_blob_size
);
3215 kfree(blob
, sizeof (*blob
));
3217 #if CHECK_CS_VALIDATION_BITMAP
3218 ubc_cs_validation_bitmap_deallocate( uip
->ui_vnode
);
3220 uip
->cs_blobs
= NULL
;
3223 /* check cs blob generation on vnode
3225 * 0 : Success, the cs_blob attached is current
3226 * ENEEDAUTH : Generation count mismatch. Needs authentication again.
3229 ubc_cs_generation_check(
3232 int retval
= ENEEDAUTH
;
3234 vnode_lock_spin(vp
);
3236 if (UBCINFOEXISTS(vp
) && vp
->v_ubcinfo
->cs_add_gen
== cs_blob_generation_count
) {
3245 ubc_cs_blob_revalidate(
3247 struct cs_blob
*blob
,
3255 const CS_CodeDirectory
*cd
= NULL
;
3258 assert(blob
!= NULL
);
3260 error
= cs_validate_csblob((const uint8_t *)blob
->csb_mem_kaddr
, blob
->csb_mem_size
, &cd
);
3263 printf("CODESIGNING: csblob invalid: %d\n", error
);
3268 /* callout to mac_vnode_check_signature */
3270 error
= mac_vnode_check_signature(vp
, blob
->csb_base_offset
, blob
->csb_cdhash
,
3271 (const void*)blob
->csb_mem_kaddr
, (int)blob
->csb_mem_size
,
3273 if (cs_debug
&& error
) {
3274 printf("revalidate: check_signature[pid: %d], error = %d\n", current_proc()->p_pid
, error
);
3278 /* update generation number if success */
3279 vnode_lock_spin(vp
);
3280 if (UBCINFOEXISTS(vp
)) {
3282 vp
->v_ubcinfo
->cs_add_gen
= cs_blob_generation_count
;
3284 vp
->v_ubcinfo
->cs_add_gen
= 0;
3294 cs_blob_reset_cache()
3296 /* incrementing odd no by 2 makes sure '0' is never reached. */
3297 OSAddAtomic(+2, &cs_blob_generation_count
);
3298 printf("Reseting cs_blob cache from all vnodes. \n");
3305 struct ubc_info
*uip
;
3306 struct cs_blob
*blobs
;
3309 * No need to take the vnode lock here. The caller must be holding
3310 * a reference on the vnode (via a VM mapping or open file descriptor),
3311 * so the vnode will not go away. The ubc_info stays until the vnode
3312 * goes away. And we only modify "blobs" by adding to the head of the
3314 * The ubc_info could go away entirely if the vnode gets reclaimed as
3315 * part of a forced unmount. In the case of a code-signature validation
3316 * during a page fault, the "paging_in_progress" reference on the VM
3317 * object guarantess that the vnode pager (and the ubc_info) won't go
3318 * away during the fault.
3319 * Other callers need to protect against vnode reclaim by holding the
3320 * vnode lock, for example.
3323 if (! UBCINFOEXISTS(vp
)) {
3328 uip
= vp
->v_ubcinfo
;
3329 blobs
= uip
->cs_blobs
;
3338 struct timespec
*cs_mtime
)
3340 struct ubc_info
*uip
;
3342 if (! UBCINFOEXISTS(vp
)) {
3343 cs_mtime
->tv_sec
= 0;
3344 cs_mtime
->tv_nsec
= 0;
3348 uip
= vp
->v_ubcinfo
;
3349 cs_mtime
->tv_sec
= uip
->cs_mtime
.tv_sec
;
3350 cs_mtime
->tv_nsec
= uip
->cs_mtime
.tv_nsec
;
3353 unsigned long cs_validate_page_no_hash
= 0;
3354 unsigned long cs_validate_page_bad_hash
= 0;
3358 memory_object_t pager
,
3359 memory_object_offset_t page_offset
,
3363 union cs_hash_union mdctx
;
3364 struct cs_hash
*hashtype
= NULL
;
3365 unsigned char actual_hash
[CS_HASH_MAX_SIZE
];
3366 unsigned char expected_hash
[CS_HASH_MAX_SIZE
];
3367 boolean_t found_hash
;
3368 struct cs_blob
*blobs
, *blob
;
3369 const CS_CodeDirectory
*cd
;
3370 const unsigned char *hash
;
3371 boolean_t validated
;
3372 off_t offset
; /* page offset in the file */
3374 off_t codeLimit
= 0;
3375 const char *lower_bound
, *upper_bound
;
3376 vm_offset_t kaddr
, blob_addr
;
3380 offset
= page_offset
;
3382 /* retrieve the expected hash */
3384 blobs
= (struct cs_blob
*) _blobs
;
3388 blob
= blob
->csb_next
) {
3389 offset
= page_offset
- blob
->csb_base_offset
;
3390 if (offset
< blob
->csb_start_offset
||
3391 offset
>= blob
->csb_end_offset
) {
3392 /* our page is not covered by this blob */
3396 /* map the blob in the kernel address space */
3397 kaddr
= blob
->csb_mem_kaddr
;
3399 ksize
= (vm_size_t
) (blob
->csb_mem_size
+
3400 blob
->csb_mem_offset
);
3401 kr
= vm_map(kernel_map
,
3406 blob
->csb_mem_handle
,
3412 if (kr
!= KERN_SUCCESS
) {
3413 /* XXX FBDP what to do !? */
3414 printf("cs_validate_page: failed to map blob, "
3415 "size=0x%lx kr=0x%x\n",
3416 (size_t)blob
->csb_mem_size
, kr
);
3421 blob_addr
= kaddr
+ blob
->csb_mem_offset
;
3422 lower_bound
= CAST_DOWN(char *, blob_addr
);
3423 upper_bound
= lower_bound
+ blob
->csb_mem_size
;
3427 /* all CD's that have been injected is already validated */
3429 offset
= page_offset
- blob
->csb_base_offset
;
3430 if (offset
< blob
->csb_start_offset
||
3431 offset
>= blob
->csb_end_offset
) {
3432 /* our page is not covered by this blob */
3436 hashtype
= blob
->csb_hashtype
;
3437 if (hashtype
== NULL
)
3438 panic("unknown hash type ?");
3439 if (hashtype
->cs_digest_size
> sizeof(actual_hash
))
3440 panic("hash size too large");
3442 codeLimit
= ntohl(cd
->codeLimit
);
3444 hash
= hashes(cd
, (uint32_t)(offset
>>PAGE_SHIFT_4K
),
3446 lower_bound
, upper_bound
);
3448 bcopy(hash
, expected_hash
, hashtype
->cs_size
);
3456 if (found_hash
== FALSE
) {
3458 * We can't verify this page because there is no signature
3459 * for it (yet). It's possible that this part of the object
3460 * is not signed, or that signatures for that part have not
3462 * Report that the page has not been validated and let the
3463 * caller decide if it wants to accept it or not.
3465 cs_validate_page_no_hash
++;
3467 printf("CODE SIGNING: cs_validate_page: "
3468 "mobj %p off 0x%llx: no hash to validate !?\n",
3469 pager
, page_offset
);
3477 size
= PAGE_SIZE_4K
;
3478 const uint32_t *asha1
, *esha1
;
3479 if ((off_t
)(offset
+ size
) > codeLimit
) {
3480 /* partial page at end of segment */
3481 assert(offset
< codeLimit
);
3482 size
= (size_t) (codeLimit
& PAGE_MASK_4K
);
3483 *tainted
|= CS_VALIDATE_NX
;
3486 hashtype
->cs_init(&mdctx
);
3487 hashtype
->cs_update(&mdctx
, data
, size
);
3488 hashtype
->cs_final(actual_hash
, &mdctx
);
3490 asha1
= (const uint32_t *) actual_hash
;
3491 esha1
= (const uint32_t *) expected_hash
;
3493 if (bcmp(expected_hash
, actual_hash
, hashtype
->cs_size
) != 0) {
3495 printf("CODE SIGNING: cs_validate_page: "
3496 "mobj %p off 0x%llx size 0x%lx: "
3497 "actual [0x%x 0x%x 0x%x 0x%x 0x%x] != "
3498 "expected [0x%x 0x%x 0x%x 0x%x 0x%x]\n",
3499 pager
, page_offset
, size
,
3500 asha1
[0], asha1
[1], asha1
[2],
3502 esha1
[0], esha1
[1], esha1
[2],
3503 esha1
[3], esha1
[4]);
3505 cs_validate_page_bad_hash
++;
3506 *tainted
|= CS_VALIDATE_TAINTED
;
3508 if (cs_debug
> 10) {
3509 printf("CODE SIGNING: cs_validate_page: "
3510 "mobj %p off 0x%llx size 0x%lx: "
3512 pager
, page_offset
, size
);
3525 unsigned char *cdhash
)
3527 struct cs_blob
*blobs
, *blob
;
3533 blobs
= ubc_get_cs_blobs(vp
);
3536 blob
= blob
->csb_next
) {
3537 /* compute offset relative to this blob */
3538 rel_offset
= offset
- blob
->csb_base_offset
;
3539 if (rel_offset
>= blob
->csb_start_offset
&&
3540 rel_offset
< blob
->csb_end_offset
) {
3541 /* this blob does cover our "offset" ! */
3547 /* we didn't find a blob covering "offset" */
3548 ret
= EBADEXEC
; /* XXX any better error ? */
3550 /* get the SHA1 hash of that blob */
3551 bcopy(blob
->csb_cdhash
, cdhash
, sizeof (blob
->csb_cdhash
));
3560 #if CHECK_CS_VALIDATION_BITMAP
3561 #define stob(s) ((atop_64((s)) + 07) >> 3)
3562 extern boolean_t root_fs_upgrade_try
;
3565 * Should we use the code-sign bitmap to avoid repeated code-sign validation?
3567 * a) Is the target vnode on the root filesystem?
3568 * b) Has someone tried to mount the root filesystem read-write?
3569 * If answers are (a) yes AND (b) no, then we can use the bitmap.
3571 #define USE_CODE_SIGN_BITMAP(vp) ( (vp != NULL) && (vp->v_mount != NULL) && (vp->v_mount->mnt_flag & MNT_ROOTFS) && !root_fs_upgrade_try)
3573 ubc_cs_validation_bitmap_allocate(
3576 kern_return_t kr
= KERN_SUCCESS
;
3577 struct ubc_info
*uip
;
3578 char *target_bitmap
;
3579 vm_object_size_t bitmap_size
;
3581 if ( ! USE_CODE_SIGN_BITMAP(vp
) || (! UBCINFOEXISTS(vp
))) {
3582 kr
= KERN_INVALID_ARGUMENT
;
3584 uip
= vp
->v_ubcinfo
;
3586 if ( uip
->cs_valid_bitmap
== NULL
) {
3587 bitmap_size
= stob(uip
->ui_size
);
3588 target_bitmap
= (char*) kalloc( (vm_size_t
)bitmap_size
);
3589 if (target_bitmap
== 0) {
3594 if( kr
== KERN_SUCCESS
) {
3595 memset( target_bitmap
, 0, (size_t)bitmap_size
);
3596 uip
->cs_valid_bitmap
= (void*)target_bitmap
;
3597 uip
->cs_valid_bitmap_size
= bitmap_size
;
3605 ubc_cs_check_validation_bitmap (
3607 memory_object_offset_t offset
,
3610 kern_return_t kr
= KERN_SUCCESS
;
3612 if ( ! USE_CODE_SIGN_BITMAP(vp
) || ! UBCINFOEXISTS(vp
)) {
3613 kr
= KERN_INVALID_ARGUMENT
;
3615 struct ubc_info
*uip
= vp
->v_ubcinfo
;
3616 char *target_bitmap
= uip
->cs_valid_bitmap
;
3618 if ( target_bitmap
== NULL
) {
3619 kr
= KERN_INVALID_ARGUMENT
;
3622 bit
= atop_64( offset
);
3625 if ( byte
> uip
->cs_valid_bitmap_size
) {
3626 kr
= KERN_INVALID_ARGUMENT
;
3629 if (optype
== CS_BITMAP_SET
) {
3630 target_bitmap
[byte
] |= (1 << (bit
& 07));
3632 } else if (optype
== CS_BITMAP_CLEAR
) {
3633 target_bitmap
[byte
] &= ~(1 << (bit
& 07));
3635 } else if (optype
== CS_BITMAP_CHECK
) {
3636 if ( target_bitmap
[byte
] & (1 << (bit
& 07))) {
3649 ubc_cs_validation_bitmap_deallocate(
3652 struct ubc_info
*uip
;
3653 void *target_bitmap
;
3654 vm_object_size_t bitmap_size
;
3656 if ( UBCINFOEXISTS(vp
)) {
3657 uip
= vp
->v_ubcinfo
;
3659 if ( (target_bitmap
= uip
->cs_valid_bitmap
) != NULL
) {
3660 bitmap_size
= uip
->cs_valid_bitmap_size
;
3661 kfree( target_bitmap
, (vm_size_t
) bitmap_size
);
3662 uip
->cs_valid_bitmap
= NULL
;
3667 kern_return_t
ubc_cs_validation_bitmap_allocate(__unused vnode_t vp
){
3668 return KERN_INVALID_ARGUMENT
;
3671 kern_return_t
ubc_cs_check_validation_bitmap(
3672 __unused
struct vnode
*vp
,
3673 __unused memory_object_offset_t offset
,
3674 __unused
int optype
){
3676 return KERN_INVALID_ARGUMENT
;
3679 void ubc_cs_validation_bitmap_deallocate(__unused vnode_t vp
){
3682 #endif /* CHECK_CS_VALIDATION_BITMAP */