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
);
156 size_t cs_digest_size
;
158 cs_md_update cs_update
;
159 cs_md_final cs_final
;
162 static struct cs_hash cs_hash_sha1
= {
163 .cs_type
= CS_HASHTYPE_SHA1
,
164 .cs_cd_size
= CS_SHA1_LEN
,
165 .cs_size
= CS_SHA1_LEN
,
166 .cs_digest_size
= SHA_DIGEST_LENGTH
,
167 .cs_init
= (cs_md_init
)SHA1Init
,
168 .cs_update
= (cs_md_update
)SHA1Update
,
169 .cs_final
= (cs_md_final
)SHA1Final
,
172 static struct cs_hash cs_hash_sha256
= {
173 .cs_type
= CS_HASHTYPE_SHA256
,
174 .cs_cd_size
= SHA256_DIGEST_LENGTH
,
175 .cs_size
= SHA256_DIGEST_LENGTH
,
176 .cs_digest_size
= SHA256_DIGEST_LENGTH
,
177 .cs_init
= (cs_md_init
)SHA256_Init
,
178 .cs_update
= (cs_md_update
)SHA256_Update
,
179 .cs_final
= (cs_md_final
)SHA256_Final
,
181 static struct cs_hash cs_hash_sha256_truncate
= {
182 .cs_type
= CS_HASHTYPE_SHA256_TRUNCATED
,
183 .cs_cd_size
= CS_SHA256_TRUNCATED_LEN
,
184 .cs_size
= CS_SHA256_TRUNCATED_LEN
,
185 .cs_digest_size
= SHA256_DIGEST_LENGTH
,
186 .cs_init
= (cs_md_init
)SHA256_Init
,
187 .cs_update
= (cs_md_update
)SHA256_Update
,
188 .cs_final
= (cs_md_final
)SHA256_Final
,
192 static struct cs_hash
*
193 cs_find_md(uint8_t type
)
195 if (type
== CS_HASHTYPE_SHA1
) {
196 return &cs_hash_sha1
;
198 } else if (type
== CS_HASHTYPE_SHA256
) {
199 return &cs_hash_sha256
;
200 } else if (type
== CS_HASHTYPE_SHA256_TRUNCATED
) {
201 return &cs_hash_sha256_truncate
;
207 union cs_hash_union
{
209 SHA256_CTX sha256ctx
;
214 * Locate the CodeDirectory from an embedded signature blob
217 CS_CodeDirectory
*findCodeDirectory(
218 const CS_SuperBlob
*embedded
,
219 const char *lower_bound
,
220 const char *upper_bound
)
222 const CS_CodeDirectory
*cd
= NULL
;
225 cs_valid_range(embedded
, embedded
+ 1, lower_bound
, upper_bound
) &&
226 ntohl(embedded
->magic
) == CSMAGIC_EMBEDDED_SIGNATURE
) {
227 const CS_BlobIndex
*limit
;
228 const CS_BlobIndex
*p
;
230 limit
= &embedded
->index
[ntohl(embedded
->count
)];
231 if (!cs_valid_range(&embedded
->index
[0], limit
,
232 lower_bound
, upper_bound
)) {
235 for (p
= embedded
->index
; p
< limit
; ++p
) {
236 if (ntohl(p
->type
) == CSSLOT_CODEDIRECTORY
) {
237 const unsigned char *base
;
239 base
= (const unsigned char *)embedded
;
240 cd
= (const CS_CodeDirectory
*)(base
+ ntohl(p
->offset
));
246 * Detached signatures come as a bare CS_CodeDirectory,
249 cd
= (const CS_CodeDirectory
*) embedded
;
253 cs_valid_range(cd
, cd
+ 1, lower_bound
, upper_bound
) &&
254 cs_valid_range(cd
, (const char *) cd
+ ntohl(cd
->length
),
255 lower_bound
, upper_bound
) &&
256 cs_valid_range(cd
, (const char *) cd
+ ntohl(cd
->hashOffset
),
257 lower_bound
, upper_bound
) &&
258 cs_valid_range(cd
, (const char *) cd
+
259 ntohl(cd
->hashOffset
) +
260 (ntohl(cd
->nCodeSlots
) * SHA1_RESULTLEN
),
261 lower_bound
, upper_bound
) &&
263 ntohl(cd
->magic
) == CSMAGIC_CODEDIRECTORY
) {
267 // not found or not a valid code directory
273 * Locating a page hash
275 static const unsigned char *
277 const CS_CodeDirectory
*cd
,
280 const char *lower_bound
,
281 const char *upper_bound
)
283 const unsigned char *base
, *top
, *hash
;
284 uint32_t nCodeSlots
= ntohl(cd
->nCodeSlots
);
286 assert(cs_valid_range(cd
, cd
+ 1, lower_bound
, upper_bound
));
288 if((ntohl(cd
->version
) >= CS_SUPPORTSSCATTER
) && (ntohl(cd
->scatterOffset
))) {
289 /* Get first scatter struct */
290 const SC_Scatter
*scatter
= (const SC_Scatter
*)
291 ((const char*)cd
+ ntohl(cd
->scatterOffset
));
292 uint32_t hashindex
=0, scount
, sbase
=0;
293 /* iterate all scatter structs */
295 if((const char*)scatter
> (const char*)cd
+ ntohl(cd
->length
)) {
297 printf("CODE SIGNING: Scatter extends past Code Directory\n");
302 scount
= ntohl(scatter
->count
);
303 uint32_t new_base
= ntohl(scatter
->base
);
310 if((hashindex
> 0) && (new_base
<= sbase
)) {
312 printf("CODE SIGNING: unordered Scatter, prev base %d, cur base %d\n",
315 return NULL
; /* unordered scatter array */
319 /* this scatter beyond page we're looking for? */
324 if (sbase
+scount
>= page
) {
325 /* Found the scatter struct that is
326 * referencing our page */
328 /* base = address of first hash covered by scatter */
329 base
= (const unsigned char *)cd
+ ntohl(cd
->hashOffset
) +
330 hashindex
* hash_len
;
331 /* top = address of first hash after this scatter */
332 top
= base
+ scount
* hash_len
;
333 if (!cs_valid_range(base
, top
, lower_bound
,
335 hashindex
> nCodeSlots
) {
342 /* this scatter struct is before the page we're looking
348 hash
= base
+ (page
- sbase
) * hash_len
;
350 base
= (const unsigned char *)cd
+ ntohl(cd
->hashOffset
);
351 top
= base
+ nCodeSlots
* hash_len
;
352 if (!cs_valid_range(base
, top
, lower_bound
, upper_bound
) ||
356 assert(page
< nCodeSlots
);
358 hash
= base
+ page
* hash_len
;
361 if (!cs_valid_range(hash
, hash
+ hash_len
,
362 lower_bound
, upper_bound
)) {
370 * cs_validate_codedirectory
372 * Validate that pointers inside the code directory to make sure that
373 * all offsets and lengths are constrained within the buffer.
375 * Parameters: cd Pointer to code directory buffer
376 * length Length of buffer
379 * EBADEXEC Invalid code signature
383 cs_validate_codedirectory(const CS_CodeDirectory
*cd
, size_t length
)
385 struct cs_hash
*hashtype
;
387 if (length
< sizeof(*cd
))
389 if (ntohl(cd
->magic
) != CSMAGIC_CODEDIRECTORY
)
391 if (cd
->pageSize
!= PAGE_SHIFT_4K
)
393 hashtype
= cs_find_md(cd
->hashType
);
394 if (hashtype
== NULL
)
397 if (cd
->hashSize
!= hashtype
->cs_cd_size
)
401 if (length
< ntohl(cd
->hashOffset
))
404 /* check that nSpecialSlots fits in the buffer in front of hashOffset */
405 if (ntohl(cd
->hashOffset
) / hashtype
->cs_size
< ntohl(cd
->nSpecialSlots
))
408 /* check that codeslots fits in the buffer */
409 if ((length
- ntohl(cd
->hashOffset
)) / hashtype
->cs_size
< ntohl(cd
->nCodeSlots
))
412 if (ntohl(cd
->version
) >= CS_SUPPORTSSCATTER
&& cd
->scatterOffset
) {
414 if (length
< ntohl(cd
->scatterOffset
))
417 const SC_Scatter
*scatter
= (const SC_Scatter
*)
418 (((const uint8_t *)cd
) + ntohl(cd
->scatterOffset
));
422 * Check each scatter buffer, since we don't know the
423 * length of the scatter buffer array, we have to
427 /* check that the end of each scatter buffer in within the length */
428 if (((const uint8_t *)scatter
) + sizeof(scatter
[0]) > (const uint8_t *)cd
+ length
)
430 uint32_t scount
= ntohl(scatter
->count
);
433 if (nPages
+ scount
< nPages
)
438 /* XXX check that basees doesn't overlap */
439 /* XXX check that targetOffset doesn't overlap */
441 #if 0 /* rdar://12579439 */
442 if (nPages
!= ntohl(cd
->nCodeSlots
))
447 if (length
< ntohl(cd
->identOffset
))
450 /* identifier is NUL terminated string */
451 if (cd
->identOffset
) {
452 const uint8_t *ptr
= (const uint8_t *)cd
+ ntohl(cd
->identOffset
);
453 if (memchr(ptr
, 0, length
- ntohl(cd
->identOffset
)) == NULL
)
457 /* team identifier is NULL terminated string */
458 if (ntohl(cd
->version
) >= CS_SUPPORTSTEAMID
&& ntohl(cd
->teamOffset
)) {
459 if (length
< ntohl(cd
->teamOffset
))
462 const uint8_t *ptr
= (const uint8_t *)cd
+ ntohl(cd
->teamOffset
);
463 if (memchr(ptr
, 0, length
- ntohl(cd
->teamOffset
)) == NULL
)
475 cs_validate_blob(const CS_GenericBlob
*blob
, size_t length
)
477 if (length
< sizeof(CS_GenericBlob
) || length
< ntohl(blob
->length
))
485 * Validate that superblob/embedded code directory to make sure that
486 * all internal pointers are valid.
488 * Will validate both a superblob csblob and a "raw" code directory.
491 * Parameters: buffer Pointer to code signature
492 * length Length of buffer
493 * rcd returns pointer to code directory
496 * EBADEXEC Invalid code signature
500 cs_validate_csblob(const uint8_t *addr
, size_t length
,
501 const CS_CodeDirectory
**rcd
)
503 const CS_GenericBlob
*blob
= (const CS_GenericBlob
*)(const void *)addr
;
508 error
= cs_validate_blob(blob
, length
);
512 length
= ntohl(blob
->length
);
514 if (ntohl(blob
->magic
) == CSMAGIC_EMBEDDED_SIGNATURE
) {
515 const CS_SuperBlob
*sb
= (const CS_SuperBlob
*)blob
;
516 uint32_t n
, count
= ntohl(sb
->count
);
518 if (length
< sizeof(CS_SuperBlob
))
521 /* check that the array of BlobIndex fits in the rest of the data */
522 if ((length
- sizeof(CS_SuperBlob
)) / sizeof(CS_BlobIndex
) < count
)
525 /* now check each BlobIndex */
526 for (n
= 0; n
< count
; n
++) {
527 const CS_BlobIndex
*blobIndex
= &sb
->index
[n
];
528 if (length
< ntohl(blobIndex
->offset
))
531 const CS_GenericBlob
*subBlob
=
532 (const CS_GenericBlob
*)(const void *)(addr
+ ntohl(blobIndex
->offset
));
534 size_t subLength
= length
- ntohl(blobIndex
->offset
);
536 if ((error
= cs_validate_blob(subBlob
, subLength
)) != 0)
538 subLength
= ntohl(subBlob
->length
);
540 /* extra validation for CDs, that is also returned */
541 if (ntohl(blobIndex
->type
) == CSSLOT_CODEDIRECTORY
) {
542 const CS_CodeDirectory
*cd
= (const CS_CodeDirectory
*)subBlob
;
543 if ((error
= cs_validate_codedirectory(cd
, subLength
)) != 0)
549 } else if (ntohl(blob
->magic
) == CSMAGIC_CODEDIRECTORY
) {
551 if ((error
= cs_validate_codedirectory((const CS_CodeDirectory
*)(const void *)addr
, length
)) != 0)
553 *rcd
= (const CS_CodeDirectory
*)blob
;
567 * Find an blob from the superblob/code directory. The blob must have
568 * been been validated by cs_validate_csblob() before calling
569 * this. Use csblob_find_blob() instead.
571 * Will also find a "raw" code directory if its stored as well as
572 * searching the superblob.
574 * Parameters: buffer Pointer to code signature
575 * length Length of buffer
576 * type type of blob to find
577 * magic the magic number for that blob
579 * Returns: pointer Success
580 * NULL Buffer not found
583 const CS_GenericBlob
*
584 csblob_find_blob_bytes(const uint8_t *addr
, size_t length
, uint32_t type
, uint32_t magic
)
586 const CS_GenericBlob
*blob
= (const CS_GenericBlob
*)(const void *)addr
;
588 if (ntohl(blob
->magic
) == CSMAGIC_EMBEDDED_SIGNATURE
) {
589 const CS_SuperBlob
*sb
= (const CS_SuperBlob
*)blob
;
590 size_t n
, count
= ntohl(sb
->count
);
592 for (n
= 0; n
< count
; n
++) {
593 if (ntohl(sb
->index
[n
].type
) != type
)
595 uint32_t offset
= ntohl(sb
->index
[n
].offset
);
596 if (length
- sizeof(const CS_GenericBlob
) < offset
)
598 blob
= (const CS_GenericBlob
*)(const void *)(addr
+ offset
);
599 if (ntohl(blob
->magic
) != magic
)
603 } else if (type
== CSSLOT_CODEDIRECTORY
604 && ntohl(blob
->magic
) == CSMAGIC_CODEDIRECTORY
605 && magic
== CSMAGIC_CODEDIRECTORY
)
611 const CS_GenericBlob
*
612 csblob_find_blob(struct cs_blob
*csblob
, uint32_t type
, uint32_t magic
)
614 if ((csblob
->csb_flags
& CS_VALID
) == 0)
616 return csblob_find_blob_bytes((const uint8_t *)csblob
->csb_mem_kaddr
, csblob
->csb_mem_size
, type
, magic
);
619 static const uint8_t *
620 find_special_slot(const CS_CodeDirectory
*cd
, size_t slotsize
, uint32_t slot
)
622 /* there is no zero special slot since that is the first code slot */
623 if (ntohl(cd
->nSpecialSlots
) < slot
|| slot
== 0)
626 return ((const uint8_t *)cd
+ ntohl(cd
->hashOffset
) - (slotsize
* slot
));
629 static uint8_t cshash_zero
[CS_HASH_MAX_SIZE
] = { 0 };
632 csblob_get_entitlements(struct cs_blob
*csblob
, void **out_start
, size_t *out_length
)
634 uint8_t computed_hash
[CS_HASH_MAX_SIZE
];
635 const CS_GenericBlob
*entitlements
;
636 const CS_CodeDirectory
*code_dir
;
637 const uint8_t *embedded_hash
;
638 union cs_hash_union context
;
643 if (csblob
->csb_hashtype
== NULL
|| csblob
->csb_hashtype
->cs_digest_size
> sizeof(computed_hash
))
646 if ((code_dir
= (const CS_CodeDirectory
*)csblob_find_blob(csblob
, CSSLOT_CODEDIRECTORY
, CSMAGIC_CODEDIRECTORY
)) == NULL
)
649 entitlements
= csblob_find_blob(csblob
, CSSLOT_ENTITLEMENTS
, CSMAGIC_EMBEDDED_ENTITLEMENTS
);
650 embedded_hash
= find_special_slot(code_dir
, csblob
->csb_hashtype
->cs_size
, CSSLOT_ENTITLEMENTS
);
652 if (embedded_hash
== NULL
) {
656 } else if (entitlements
== NULL
&& memcmp(embedded_hash
, cshash_zero
, csblob
->csb_hashtype
->cs_size
) != 0) {
660 csblob
->csb_hashtype
->cs_init(&context
);
661 csblob
->csb_hashtype
->cs_update(&context
, entitlements
, ntohl(entitlements
->length
));
662 csblob
->csb_hashtype
->cs_final(computed_hash
, &context
);
664 if (memcmp(computed_hash
, embedded_hash
, csblob
->csb_hashtype
->cs_size
) != 0)
667 *out_start
= __DECONST(void *, entitlements
);
668 *out_length
= ntohl(entitlements
->length
);
675 * End of routines to navigate code signing data structures in the kernel.
683 * Initialization of the zone for Unified Buffer Cache.
690 * ubc_info_zone(global) initialized for subsequent allocations
692 __private_extern__
void
697 i
= (vm_size_t
) sizeof (struct ubc_info
);
699 ubc_info_zone
= zinit (i
, 10000*i
, 8192, "ubc_info zone");
701 zone_change(ubc_info_zone
, Z_NOENCRYPT
, TRUE
);
708 * Allocate and attach an empty ubc_info structure to a vnode
710 * Parameters: vp Pointer to the vnode
713 * vnode_size:ENOMEM Not enough space
714 * vnode_size:??? Other error from vnode_getattr
718 ubc_info_init(struct vnode
*vp
)
720 return(ubc_info_init_internal(vp
, 0, 0));
725 * ubc_info_init_withsize
727 * Allocate and attach a sized ubc_info structure to a vnode
729 * Parameters: vp Pointer to the vnode
730 * filesize The size of the file
733 * vnode_size:ENOMEM Not enough space
734 * vnode_size:??? Other error from vnode_getattr
737 ubc_info_init_withsize(struct vnode
*vp
, off_t filesize
)
739 return(ubc_info_init_internal(vp
, 1, filesize
));
744 * ubc_info_init_internal
746 * Allocate and attach a ubc_info structure to a vnode
748 * Parameters: vp Pointer to the vnode
749 * withfsize{0,1} Zero if the size should be obtained
750 * from the vnode; otherwise, use filesize
751 * filesize The size of the file, if withfsize == 1
754 * vnode_size:ENOMEM Not enough space
755 * vnode_size:??? Other error from vnode_getattr
757 * Notes: We call a blocking zalloc(), and the zone was created as an
758 * expandable and collectable zone, so if no memory is available,
759 * it is possible for zalloc() to block indefinitely. zalloc()
760 * may also panic if the zone of zones is exhausted, since it's
763 * We unconditionally call vnode_pager_setup(), even if this is
764 * a reuse of a ubc_info; in that case, we should probably assert
765 * that it does not already have a pager association, but do not.
767 * Since memory_object_create_named() can only fail from receiving
768 * an invalid pager argument, the explicit check and panic is
769 * merely precautionary.
772 ubc_info_init_internal(vnode_t vp
, int withfsize
, off_t filesize
)
774 register struct ubc_info
*uip
;
778 memory_object_control_t control
;
783 * If there is not already a ubc_info attached to the vnode, we
784 * attach one; otherwise, we will reuse the one that's there.
786 if (uip
== UBC_INFO_NULL
) {
788 uip
= (struct ubc_info
*) zalloc(ubc_info_zone
);
789 bzero((char *)uip
, sizeof(struct ubc_info
));
792 uip
->ui_flags
= UI_INITED
;
793 uip
->ui_ucred
= NOCRED
;
795 assert(uip
->ui_flags
!= UI_NONE
);
796 assert(uip
->ui_vnode
== vp
);
798 /* now set this ubc_info in the vnode */
802 * Allocate a pager object for this vnode
804 * XXX The value of the pager parameter is currently ignored.
805 * XXX Presumably, this API changed to avoid the race between
806 * XXX setting the pager and the UI_HASPAGER flag.
808 pager
= (void *)vnode_pager_setup(vp
, uip
->ui_pager
);
812 * Explicitly set the pager into the ubc_info, after setting the
815 SET(uip
->ui_flags
, UI_HASPAGER
);
816 uip
->ui_pager
= pager
;
819 * Note: We can not use VNOP_GETATTR() to get accurate
820 * value of ui_size because this may be an NFS vnode, and
821 * nfs_getattr() can call vinvalbuf(); if this happens,
822 * ubc_info is not set up to deal with that event.
827 * create a vnode - vm_object association
828 * memory_object_create_named() creates a "named" reference on the
829 * memory object we hold this reference as long as the vnode is
830 * "alive." Since memory_object_create_named() took its own reference
831 * on the vnode pager we passed it, we can drop the reference
832 * vnode_pager_setup() returned here.
834 kret
= memory_object_create_named(pager
,
835 (memory_object_size_t
)uip
->ui_size
, &control
);
836 vnode_pager_deallocate(pager
);
837 if (kret
!= KERN_SUCCESS
)
838 panic("ubc_info_init: memory_object_create_named returned %d", kret
);
841 uip
->ui_control
= control
; /* cache the value of the mo control */
842 SET(uip
->ui_flags
, UI_HASOBJREF
); /* with a named reference */
844 if (withfsize
== 0) {
845 /* initialize the size */
846 error
= vnode_size(vp
, &uip
->ui_size
, vfs_context_current());
850 uip
->ui_size
= filesize
;
852 vp
->v_lflag
|= VNAMED_UBC
; /* vnode has a named ubc reference */
861 * Free a ubc_info structure
863 * Parameters: uip A pointer to the ubc_info to free
867 * Notes: If there is a credential that has subsequently been associated
868 * with the ubc_info via a call to ubc_setcred(), the reference
869 * to the credential is dropped.
871 * It's actually impossible for a ubc_info.ui_control to take the
872 * value MEMORY_OBJECT_CONTROL_NULL.
875 ubc_info_free(struct ubc_info
*uip
)
877 if (IS_VALID_CRED(uip
->ui_ucred
)) {
878 kauth_cred_unref(&uip
->ui_ucred
);
881 if (uip
->ui_control
!= MEMORY_OBJECT_CONTROL_NULL
)
882 memory_object_control_deallocate(uip
->ui_control
);
884 cluster_release(uip
);
887 zfree(ubc_info_zone
, uip
);
893 ubc_info_deallocate(struct ubc_info
*uip
)
898 errno_t
mach_to_bsd_errno(kern_return_t mach_err
)
904 case KERN_INVALID_ADDRESS
:
905 case KERN_INVALID_ARGUMENT
:
906 case KERN_NOT_IN_SET
:
907 case KERN_INVALID_NAME
:
908 case KERN_INVALID_TASK
:
909 case KERN_INVALID_RIGHT
:
910 case KERN_INVALID_VALUE
:
911 case KERN_INVALID_CAPABILITY
:
912 case KERN_INVALID_HOST
:
913 case KERN_MEMORY_PRESENT
:
914 case KERN_INVALID_PROCESSOR_SET
:
915 case KERN_INVALID_POLICY
:
916 case KERN_ALREADY_WAITING
:
917 case KERN_DEFAULT_SET
:
918 case KERN_EXCEPTION_PROTECTED
:
919 case KERN_INVALID_LEDGER
:
920 case KERN_INVALID_MEMORY_CONTROL
:
921 case KERN_INVALID_SECURITY
:
922 case KERN_NOT_DEPRESSED
:
923 case KERN_LOCK_OWNED
:
924 case KERN_LOCK_OWNED_SELF
:
927 case KERN_PROTECTION_FAILURE
:
928 case KERN_NOT_RECEIVER
:
930 case KERN_POLICY_STATIC
:
934 case KERN_RESOURCE_SHORTAGE
:
935 case KERN_UREFS_OVERFLOW
:
936 case KERN_INVALID_OBJECT
:
942 case KERN_MEMORY_FAILURE
:
943 case KERN_POLICY_LIMIT
:
944 case KERN_CODESIGN_ERROR
:
947 case KERN_MEMORY_ERROR
:
950 case KERN_ALREADY_IN_SET
:
951 case KERN_NAME_EXISTS
:
952 case KERN_RIGHT_EXISTS
:
958 case KERN_TERMINATED
:
959 case KERN_LOCK_SET_DESTROYED
:
960 case KERN_LOCK_UNSTABLE
:
961 case KERN_SEMAPHORE_DESTROYED
:
964 case KERN_RPC_SERVER_TERMINATED
:
967 case KERN_NOT_SUPPORTED
:
973 case KERN_NOT_WAITING
:
976 case KERN_OPERATION_TIMED_OUT
:
987 * Tell the VM that the the size of the file represented by the vnode has
990 * Parameters: vp The vp whose backing file size is
992 * nsize The new size of the backing file
995 * Returns: EINVAL for new size < 0
996 * ENOENT if no UBC info exists
997 * EAGAIN if UBC_SETSIZE_NO_FS_REENTRY option is set and new_size < old size
998 * Other errors (mapped to errno_t) returned by VM functions
1000 * Notes: This function will indicate success if the new size is the
1001 * same or larger than the old size (in this case, the
1002 * remainder of the file will require modification or use of
1003 * an existing upl to access successfully).
1005 * This function will fail if the new file size is smaller,
1006 * and the memory region being invalidated was unable to
1007 * actually be invalidated and/or the last page could not be
1008 * flushed, if the new size is not aligned to a page
1009 * boundary. This is usually indicative of an I/O error.
1011 errno_t
ubc_setsize_ex(struct vnode
*vp
, off_t nsize
, ubc_setsize_opts_t opts
)
1013 off_t osize
; /* ui_size before change */
1014 off_t lastpg
, olastpgend
, lastoff
;
1015 struct ubc_info
*uip
;
1016 memory_object_control_t control
;
1017 kern_return_t kret
= KERN_SUCCESS
;
1019 if (nsize
< (off_t
)0)
1022 if (!UBCINFOEXISTS(vp
))
1025 uip
= vp
->v_ubcinfo
;
1026 osize
= uip
->ui_size
;
1028 if (ISSET(opts
, UBC_SETSIZE_NO_FS_REENTRY
) && nsize
< osize
)
1032 * Update the size before flushing the VM
1034 uip
->ui_size
= nsize
;
1036 if (nsize
>= osize
) { /* Nothing more to do */
1037 if (nsize
> osize
) {
1038 lock_vnode_and_post(vp
, NOTE_EXTEND
);
1045 * When the file shrinks, invalidate the pages beyond the
1046 * new size. Also get rid of garbage beyond nsize on the
1047 * last page. The ui_size already has the nsize, so any
1048 * subsequent page-in will zero-fill the tail properly
1050 lastpg
= trunc_page_64(nsize
);
1051 olastpgend
= round_page_64(osize
);
1052 control
= uip
->ui_control
;
1054 lastoff
= (nsize
& PAGE_MASK_64
);
1058 upl_page_info_t
*pl
;
1061 * new EOF ends up in the middle of a page
1062 * zero the tail of this page if it's currently
1063 * present in the cache
1065 kret
= ubc_create_upl(vp
, lastpg
, PAGE_SIZE
, &upl
, &pl
, UPL_SET_LITE
);
1067 if (kret
!= KERN_SUCCESS
)
1068 panic("ubc_setsize: ubc_create_upl (error = %d)\n", kret
);
1070 if (upl_valid_page(pl
, 0))
1071 cluster_zero(upl
, (uint32_t)lastoff
, PAGE_SIZE
- (uint32_t)lastoff
, NULL
);
1073 ubc_upl_abort_range(upl
, 0, PAGE_SIZE
, UPL_ABORT_FREE_ON_EMPTY
);
1075 lastpg
+= PAGE_SIZE_64
;
1077 if (olastpgend
> lastpg
) {
1081 flags
= MEMORY_OBJECT_DATA_FLUSH_ALL
;
1083 flags
= MEMORY_OBJECT_DATA_FLUSH
;
1085 * invalidate the pages beyond the new EOF page
1088 kret
= memory_object_lock_request(control
,
1089 (memory_object_offset_t
)lastpg
,
1090 (memory_object_size_t
)(olastpgend
- lastpg
), NULL
, NULL
,
1091 MEMORY_OBJECT_RETURN_NONE
, flags
, VM_PROT_NO_CHANGE
);
1092 if (kret
!= KERN_SUCCESS
)
1093 printf("ubc_setsize: invalidate failed (error = %d)\n", kret
);
1095 return mach_to_bsd_errno(kret
);
1098 // Returns true for success
1099 int ubc_setsize(vnode_t vp
, off_t nsize
)
1101 return ubc_setsize_ex(vp
, nsize
, 0) == 0;
1107 * Get the size of the file assocated with the specified vnode
1109 * Parameters: vp The vnode whose size is of interest
1111 * Returns: 0 There is no ubc_info associated with
1112 * this vnode, or the size is zero
1113 * !0 The size of the file
1115 * Notes: Using this routine, it is not possible for a caller to
1116 * successfully distinguish between a vnode associate with a zero
1117 * length file, and a vnode with no associated ubc_info. The
1118 * caller therefore needs to not care, or needs to ensure that
1119 * they have previously successfully called ubc_info_init() or
1120 * ubc_info_init_withsize().
1123 ubc_getsize(struct vnode
*vp
)
1125 /* people depend on the side effect of this working this way
1126 * as they call this for directory
1128 if (!UBCINFOEXISTS(vp
))
1130 return (vp
->v_ubcinfo
->ui_size
);
1137 * Call ubc_msync(vp, 0, EOF, NULL, UBC_PUSHALL) on all the vnodes for this
1140 * Parameters: mp The mount point
1142 * Returns: 0 Success
1144 * Notes: There is no failure indication for this function.
1146 * This function is used in the unmount path; since it may block
1147 * I/O indefinitely, it should not be used in the forced unmount
1148 * path, since a device unavailability could also block that
1151 * Because there is no device ejection interlock on USB, FireWire,
1152 * or similar devices, it's possible that an ejection that begins
1153 * subsequent to the vnode_iterate() completing, either on one of
1154 * those devices, or a network mount for which the server quits
1155 * responding, etc., may cause the caller to block indefinitely.
1157 __private_extern__
int
1158 ubc_umount(struct mount
*mp
)
1160 vnode_iterate(mp
, 0, ubc_umcallback
, 0);
1168 * Used by ubc_umount() as an internal implementation detail; see ubc_umount()
1169 * and vnode_iterate() for details of implementation.
1172 ubc_umcallback(vnode_t vp
, __unused
void * args
)
1175 if (UBCINFOEXISTS(vp
)) {
1177 (void) ubc_msync(vp
, (off_t
)0, ubc_getsize(vp
), NULL
, UBC_PUSHALL
);
1179 return (VNODE_RETURNED
);
1186 * Get the credentials currently active for the ubc_info associated with the
1189 * Parameters: vp The vnode whose ubc_info credentials
1190 * are to be retrieved
1192 * Returns: !NOCRED The credentials
1193 * NOCRED If there is no ubc_info for the vnode,
1194 * or if there is one, but it has not had
1195 * any credentials associated with it via
1196 * a call to ubc_setcred()
1199 ubc_getcred(struct vnode
*vp
)
1201 if (UBCINFOEXISTS(vp
))
1202 return (vp
->v_ubcinfo
->ui_ucred
);
1211 * If they are not already set, set the credentials of the ubc_info structure
1212 * associated with the vnode to those of the supplied thread; otherwise leave
1215 * Parameters: vp The vnode whose ubc_info creds are to
1217 * p The process whose credentials are to
1218 * be used, if not running on an assumed
1220 * thread The thread whose credentials are to
1223 * Returns: 1 This vnode has no associated ubc_info
1226 * Notes: This function takes a proc parameter to account for bootstrap
1227 * issues where a task or thread may call this routine, either
1228 * before credentials have been initialized by bsd_init(), or if
1229 * there is no BSD info asscoiate with a mach thread yet. This
1230 * is known to happen in both the initial swap and memory mapping
1233 * This function is generally used only in the following cases:
1235 * o a memory mapped file via the mmap() system call
1236 * o a swap store backing file
1237 * o subsequent to a successful write via vn_write()
1239 * The information is then used by the NFS client in order to
1240 * cons up a wire message in either the page-in or page-out path.
1242 * There are two potential problems with the use of this API:
1244 * o Because the write path only set it on a successful
1245 * write, there is a race window between setting the
1246 * credential and its use to evict the pages to the
1247 * remote file server
1249 * o Because a page-in may occur prior to a write, the
1250 * credential may not be set at this time, if the page-in
1251 * is not the result of a mapping established via mmap().
1253 * In both these cases, this will be triggered from the paging
1254 * path, which will instead use the credential of the current
1255 * process, which in this case is either the dynamic_pager or
1256 * the kernel task, both of which utilize "root" credentials.
1258 * This may potentially permit operations to occur which should
1259 * be denied, or it may cause to be denied operations which
1260 * should be permitted, depending on the configuration of the NFS
1264 ubc_setthreadcred(struct vnode
*vp
, proc_t p
, thread_t thread
)
1266 struct ubc_info
*uip
;
1268 struct uthread
*uthread
= get_bsdthread_info(thread
);
1270 if (!UBCINFOEXISTS(vp
))
1275 uip
= vp
->v_ubcinfo
;
1276 credp
= uip
->ui_ucred
;
1278 if (!IS_VALID_CRED(credp
)) {
1279 /* use per-thread cred, if assumed identity, else proc cred */
1280 if (uthread
== NULL
|| (uthread
->uu_flag
& UT_SETUID
) == 0) {
1281 uip
->ui_ucred
= kauth_cred_proc_ref(p
);
1283 uip
->ui_ucred
= uthread
->uu_ucred
;
1284 kauth_cred_ref(uip
->ui_ucred
);
1296 * If they are not already set, set the credentials of the ubc_info structure
1297 * associated with the vnode to those of the process; otherwise leave them
1300 * Parameters: vp The vnode whose ubc_info creds are to
1302 * p The process whose credentials are to
1305 * Returns: 0 This vnode has no associated ubc_info
1308 * Notes: The return values for this function are inverted from nearly
1309 * all other uses in the kernel.
1311 * See also ubc_setthreadcred(), above.
1313 * This function is considered deprecated, and generally should
1314 * not be used, as it is incompatible with per-thread credentials;
1315 * it exists for legacy KPI reasons.
1317 * DEPRECATION: ubc_setcred() is being deprecated. Please use
1318 * ubc_setthreadcred() instead.
1321 ubc_setcred(struct vnode
*vp
, proc_t p
)
1323 struct ubc_info
*uip
;
1326 /* If there is no ubc_info, deny the operation */
1327 if ( !UBCINFOEXISTS(vp
))
1331 * Check to see if there is already a credential reference in the
1332 * ubc_info; if there is not, take one on the supplied credential.
1335 uip
= vp
->v_ubcinfo
;
1336 credp
= uip
->ui_ucred
;
1337 if (!IS_VALID_CRED(credp
)) {
1338 uip
->ui_ucred
= kauth_cred_proc_ref(p
);
1348 * Get the pager associated with the ubc_info associated with the vnode.
1350 * Parameters: vp The vnode to obtain the pager from
1352 * Returns: !VNODE_PAGER_NULL The memory_object_t for the pager
1353 * VNODE_PAGER_NULL There is no ubc_info for this vnode
1355 * Notes: For each vnode that has a ubc_info associated with it, that
1356 * ubc_info SHALL have a pager associated with it, so in the
1357 * normal case, it's impossible to return VNODE_PAGER_NULL for
1358 * a vnode with an associated ubc_info.
1360 __private_extern__ memory_object_t
1361 ubc_getpager(struct vnode
*vp
)
1363 if (UBCINFOEXISTS(vp
))
1364 return (vp
->v_ubcinfo
->ui_pager
);
1373 * Get the memory object control associated with the ubc_info associated with
1376 * Parameters: vp The vnode to obtain the memory object
1380 * Returns: !MEMORY_OBJECT_CONTROL_NULL
1381 * MEMORY_OBJECT_CONTROL_NULL
1383 * Notes: Historically, if the flags were not "do not reactivate", this
1384 * function would look up the memory object using the pager if
1385 * it did not exist (this could be the case if the vnode had
1386 * been previously reactivated). The flags would also permit a
1387 * hold to be requested, which would have created an object
1388 * reference, if one had not already existed. This usage is
1389 * deprecated, as it would permit a race between finding and
1390 * taking the reference vs. a single reference being dropped in
1393 memory_object_control_t
1394 ubc_getobject(struct vnode
*vp
, __unused
int flags
)
1396 if (UBCINFOEXISTS(vp
))
1397 return((vp
->v_ubcinfo
->ui_control
));
1399 return (MEMORY_OBJECT_CONTROL_NULL
);
1403 ubc_strict_uncached_IO(struct vnode
*vp
)
1405 boolean_t result
= FALSE
;
1407 if (UBCINFOEXISTS(vp
)) {
1408 result
= memory_object_is_slid(vp
->v_ubcinfo
->ui_control
);
1416 * Convert a given block number to a memory backing object (file) offset for a
1419 * Parameters: vp The vnode in which the block is located
1420 * blkno The block number to convert
1422 * Returns: !-1 The offset into the backing object
1423 * -1 There is no ubc_info associated with
1425 * -1 An error occurred in the underlying VFS
1426 * while translating the block to an
1427 * offset; the most likely cause is that
1428 * the caller specified a block past the
1429 * end of the file, but this could also be
1430 * any other error from VNOP_BLKTOOFF().
1432 * Note: Representing the error in band loses some information, but does
1433 * not occlude a valid offset, since an off_t of -1 is normally
1434 * used to represent EOF. If we had a more reliable constant in
1435 * our header files for it (i.e. explicitly cast to an off_t), we
1436 * would use it here instead.
1439 ubc_blktooff(vnode_t vp
, daddr64_t blkno
)
1441 off_t file_offset
= -1;
1444 if (UBCINFOEXISTS(vp
)) {
1445 error
= VNOP_BLKTOOFF(vp
, blkno
, &file_offset
);
1450 return (file_offset
);
1457 * Convert a given offset in a memory backing object into a block number for a
1460 * Parameters: vp The vnode in which the offset is
1462 * offset The offset into the backing object
1464 * Returns: !-1 The returned block number
1465 * -1 There is no ubc_info associated with
1467 * -1 An error occurred in the underlying VFS
1468 * while translating the block to an
1469 * offset; the most likely cause is that
1470 * the caller specified a block past the
1471 * end of the file, but this could also be
1472 * any other error from VNOP_OFFTOBLK().
1474 * Note: Representing the error in band loses some information, but does
1475 * not occlude a valid block number, since block numbers exceed
1476 * the valid range for offsets, due to their relative sizes. If
1477 * we had a more reliable constant than -1 in our header files
1478 * for it (i.e. explicitly cast to an daddr64_t), we would use it
1482 ubc_offtoblk(vnode_t vp
, off_t offset
)
1484 daddr64_t blkno
= -1;
1487 if (UBCINFOEXISTS(vp
)) {
1488 error
= VNOP_OFFTOBLK(vp
, offset
, &blkno
);
1498 * ubc_pages_resident
1500 * Determine whether or not a given vnode has pages resident via the memory
1501 * object control associated with the ubc_info associated with the vnode
1503 * Parameters: vp The vnode we want to know about
1509 ubc_pages_resident(vnode_t vp
)
1512 boolean_t has_pages_resident
;
1514 if (!UBCINFOEXISTS(vp
))
1518 * The following call may fail if an invalid ui_control is specified,
1519 * or if there is no VM object associated with the control object. In
1520 * either case, reacting to it as if there were no pages resident will
1521 * result in correct behavior.
1523 kret
= memory_object_pages_resident(vp
->v_ubcinfo
->ui_control
, &has_pages_resident
);
1525 if (kret
!= KERN_SUCCESS
)
1528 if (has_pages_resident
== TRUE
)
1537 * Clean and/or invalidate a range in the memory object that backs this vnode
1539 * Parameters: vp The vnode whose associated ubc_info's
1540 * associated memory object is to have a
1541 * range invalidated within it
1542 * beg_off The start of the range, as an offset
1543 * end_off The end of the range, as an offset
1544 * resid_off The address of an off_t supplied by the
1545 * caller; may be set to NULL to ignore
1546 * flags See ubc_msync_internal()
1548 * Returns: 0 Success
1549 * !0 Failure; an errno is returned
1552 * *resid_off, modified If non-NULL, the contents are ALWAYS
1553 * modified; they are initialized to the
1554 * beg_off, and in case of an I/O error,
1555 * the difference between beg_off and the
1556 * current value will reflect what was
1557 * able to be written before the error
1558 * occurred. If no error is returned, the
1559 * value of the resid_off is undefined; do
1560 * NOT use it in place of end_off if you
1561 * intend to increment from the end of the
1562 * last call and call iteratively.
1564 * Notes: see ubc_msync_internal() for more detailed information.
1568 ubc_msync(vnode_t vp
, off_t beg_off
, off_t end_off
, off_t
*resid_off
, int flags
)
1574 *resid_off
= beg_off
;
1576 retval
= ubc_msync_internal(vp
, beg_off
, end_off
, resid_off
, flags
, &io_errno
);
1578 if (retval
== 0 && io_errno
== 0)
1585 * ubc_msync_internal
1587 * Clean and/or invalidate a range in the memory object that backs this vnode
1589 * Parameters: vp The vnode whose associated ubc_info's
1590 * associated memory object is to have a
1591 * range invalidated within it
1592 * beg_off The start of the range, as an offset
1593 * end_off The end of the range, as an offset
1594 * resid_off The address of an off_t supplied by the
1595 * caller; may be set to NULL to ignore
1596 * flags MUST contain at least one of the flags
1597 * UBC_INVALIDATE, UBC_PUSHDIRTY, or
1598 * UBC_PUSHALL; if UBC_PUSHDIRTY is used,
1599 * UBC_SYNC may also be specified to cause
1600 * this function to block until the
1601 * operation is complete. The behavior
1602 * of UBC_SYNC is otherwise undefined.
1603 * io_errno The address of an int to contain the
1604 * errno from a failed I/O operation, if
1605 * one occurs; may be set to NULL to
1608 * Returns: 1 Success
1612 * *resid_off, modified The contents of this offset MAY be
1613 * modified; in case of an I/O error, the
1614 * difference between beg_off and the
1615 * current value will reflect what was
1616 * able to be written before the error
1618 * *io_errno, modified The contents of this offset are set to
1619 * an errno, if an error occurs; if the
1620 * caller supplies an io_errno parameter,
1621 * they should be careful to initialize it
1622 * to 0 before calling this function to
1623 * enable them to distinguish an error
1624 * with a valid *resid_off from an invalid
1625 * one, and to avoid potentially falsely
1626 * reporting an error, depending on use.
1628 * Notes: If there is no ubc_info associated with the vnode supplied,
1629 * this function immediately returns success.
1631 * If the value of end_off is less than or equal to beg_off, this
1632 * function immediately returns success; that is, end_off is NOT
1635 * IMPORTANT: one of the flags UBC_INVALIDATE, UBC_PUSHDIRTY, or
1636 * UBC_PUSHALL MUST be specified; that is, it is NOT possible to
1637 * attempt to block on in-progress I/O by calling this function
1638 * with UBC_PUSHDIRTY, and then later call it with just UBC_SYNC
1639 * in order to block pending on the I/O already in progress.
1641 * The start offset is truncated to the page boundary and the
1642 * size is adjusted to include the last page in the range; that
1643 * is, end_off on exactly a page boundary will not change if it
1644 * is rounded, and the range of bytes written will be from the
1645 * truncate beg_off to the rounded (end_off - 1).
1648 ubc_msync_internal(vnode_t vp
, off_t beg_off
, off_t end_off
, off_t
*resid_off
, int flags
, int *io_errno
)
1650 memory_object_size_t tsize
;
1652 int request_flags
= 0;
1653 int flush_flags
= MEMORY_OBJECT_RETURN_NONE
;
1655 if ( !UBCINFOEXISTS(vp
))
1657 if ((flags
& (UBC_INVALIDATE
| UBC_PUSHDIRTY
| UBC_PUSHALL
)) == 0)
1659 if (end_off
<= beg_off
)
1662 if (flags
& UBC_INVALIDATE
)
1664 * discard the resident pages
1666 request_flags
= (MEMORY_OBJECT_DATA_FLUSH
| MEMORY_OBJECT_DATA_NO_CHANGE
);
1668 if (flags
& UBC_SYNC
)
1670 * wait for all the I/O to complete before returning
1672 request_flags
|= MEMORY_OBJECT_IO_SYNC
;
1674 if (flags
& UBC_PUSHDIRTY
)
1676 * we only return the dirty pages in the range
1678 flush_flags
= MEMORY_OBJECT_RETURN_DIRTY
;
1680 if (flags
& UBC_PUSHALL
)
1682 * then return all the interesting pages in the range (both
1683 * dirty and precious) to the pager
1685 flush_flags
= MEMORY_OBJECT_RETURN_ALL
;
1687 beg_off
= trunc_page_64(beg_off
);
1688 end_off
= round_page_64(end_off
);
1689 tsize
= (memory_object_size_t
)end_off
- beg_off
;
1691 /* flush and/or invalidate pages in the range requested */
1692 kret
= memory_object_lock_request(vp
->v_ubcinfo
->ui_control
,
1694 (memory_object_offset_t
*)resid_off
,
1695 io_errno
, flush_flags
, request_flags
,
1698 return ((kret
== KERN_SUCCESS
) ? 1 : 0);
1705 * Explicitly map a vnode that has an associate ubc_info, and add a reference
1706 * to it for the ubc system, if there isn't one already, so it will not be
1707 * recycled while it's in use, and set flags on the ubc_info to indicate that
1710 * Parameters: vp The vnode to map
1711 * flags The mapping flags for the vnode; this
1712 * will be a combination of one or more of
1713 * PROT_READ, PROT_WRITE, and PROT_EXEC
1715 * Returns: 0 Success
1716 * EPERM Permission was denied
1718 * Notes: An I/O reference on the vnode must already be held on entry
1720 * If there is no ubc_info associated with the vnode, this function
1721 * will return success.
1723 * If a permission error occurs, this function will return
1724 * failure; all other failures will cause this function to return
1727 * IMPORTANT: This is an internal use function, and its symbols
1728 * are not exported, hence its error checking is not very robust.
1729 * It is primarily used by:
1731 * o mmap(), when mapping a file
1732 * o When mapping a shared file (a shared library in the
1733 * shared segment region)
1734 * o When loading a program image during the exec process
1736 * ...all of these uses ignore the return code, and any fault that
1737 * results later because of a failure is handled in the fix-up path
1738 * of the fault handler. The interface exists primarily as a
1741 * Given that third party implementation of the type of interfaces
1742 * that would use this function, such as alternative executable
1743 * formats, etc., are unsupported, this function is not exported
1746 * The extra reference is held until the VM system unmaps the
1747 * vnode from its own context to maintain a vnode reference in
1748 * cases like open()/mmap()/close(), which leave the backing
1749 * object referenced by a mapped memory region in a process
1752 __private_extern__
int
1753 ubc_map(vnode_t vp
, int flags
)
1755 struct ubc_info
*uip
;
1758 int need_wakeup
= 0;
1760 if (UBCINFOEXISTS(vp
)) {
1763 uip
= vp
->v_ubcinfo
;
1765 while (ISSET(uip
->ui_flags
, UI_MAPBUSY
)) {
1766 SET(uip
->ui_flags
, UI_MAPWAITING
);
1767 (void) msleep(&uip
->ui_flags
, &vp
->v_lock
,
1768 PRIBIO
, "ubc_map", NULL
);
1770 SET(uip
->ui_flags
, UI_MAPBUSY
);
1773 error
= VNOP_MMAP(vp
, flags
, vfs_context_current());
1778 vnode_lock_spin(vp
);
1781 if ( !ISSET(uip
->ui_flags
, UI_ISMAPPED
))
1783 SET(uip
->ui_flags
, (UI_WASMAPPED
| UI_ISMAPPED
));
1784 if (flags
& PROT_WRITE
) {
1785 SET(uip
->ui_flags
, UI_MAPPEDWRITE
);
1788 CLR(uip
->ui_flags
, UI_MAPBUSY
);
1790 if (ISSET(uip
->ui_flags
, UI_MAPWAITING
)) {
1791 CLR(uip
->ui_flags
, UI_MAPWAITING
);
1797 wakeup(&uip
->ui_flags
);
1809 * Destroy the named memory object associated with the ubc_info control object
1810 * associated with the designated vnode, if there is a ubc_info associated
1811 * with the vnode, and a control object is associated with it
1813 * Parameters: vp The designated vnode
1817 * Notes: This function is called on vnode termination for all vnodes,
1818 * and must therefore not assume that there is a ubc_info that is
1819 * associated with the vnode, nor that there is a control object
1820 * associated with the ubc_info.
1822 * If all the conditions necessary are present, this function
1823 * calls memory_object_destory(), which will in turn end up
1824 * calling ubc_unmap() to release any vnode references that were
1825 * established via ubc_map().
1827 * IMPORTANT: This is an internal use function that is used
1828 * exclusively by the internal use function vclean().
1830 __private_extern__
void
1831 ubc_destroy_named(vnode_t vp
)
1833 memory_object_control_t control
;
1834 struct ubc_info
*uip
;
1837 if (UBCINFOEXISTS(vp
)) {
1838 uip
= vp
->v_ubcinfo
;
1840 /* Terminate the memory object */
1841 control
= ubc_getobject(vp
, UBC_HOLDOBJECT
);
1842 if (control
!= MEMORY_OBJECT_CONTROL_NULL
) {
1843 kret
= memory_object_destroy(control
, 0);
1844 if (kret
!= KERN_SUCCESS
)
1845 panic("ubc_destroy_named: memory_object_destroy failed");
1854 * Determine whether or not a vnode is currently in use by ubc at a level in
1855 * excess of the requested busycount
1857 * Parameters: vp The vnode to check
1858 * busycount The threshold busy count, used to bias
1859 * the count usually already held by the
1860 * caller to avoid races
1862 * Returns: 1 The vnode is in use over the threshold
1863 * 0 The vnode is not in use over the
1866 * Notes: Because the vnode is only held locked while actually asking
1867 * the use count, this function only represents a snapshot of the
1868 * current state of the vnode. If more accurate information is
1869 * required, an additional busycount should be held by the caller
1870 * and a non-zero busycount used.
1872 * If there is no ubc_info associated with the vnode, this
1873 * function will report that the vnode is not in use by ubc.
1876 ubc_isinuse(struct vnode
*vp
, int busycount
)
1878 if ( !UBCINFOEXISTS(vp
))
1880 return(ubc_isinuse_locked(vp
, busycount
, 0));
1885 * ubc_isinuse_locked
1887 * Determine whether or not a vnode is currently in use by ubc at a level in
1888 * excess of the requested busycount
1890 * Parameters: vp The vnode to check
1891 * busycount The threshold busy count, used to bias
1892 * the count usually already held by the
1893 * caller to avoid races
1894 * locked True if the vnode is already locked by
1897 * Returns: 1 The vnode is in use over the threshold
1898 * 0 The vnode is not in use over the
1901 * Notes: If the vnode is not locked on entry, it is locked while
1902 * actually asking the use count. If this is the case, this
1903 * function only represents a snapshot of the current state of
1904 * the vnode. If more accurate information is required, the
1905 * vnode lock should be held by the caller, otherwise an
1906 * additional busycount should be held by the caller and a
1907 * non-zero busycount used.
1909 * If there is no ubc_info associated with the vnode, this
1910 * function will report that the vnode is not in use by ubc.
1913 ubc_isinuse_locked(struct vnode
*vp
, int busycount
, int locked
)
1919 vnode_lock_spin(vp
);
1921 if ((vp
->v_usecount
- vp
->v_kusecount
) > busycount
)
1933 * Reverse the effects of a ubc_map() call for a given vnode
1935 * Parameters: vp vnode to unmap from ubc
1939 * Notes: This is an internal use function used by vnode_pager_unmap().
1940 * It will attempt to obtain a reference on the supplied vnode,
1941 * and if it can do so, and there is an associated ubc_info, and
1942 * the flags indicate that it was mapped via ubc_map(), then the
1943 * flag is cleared, the mapping removed, and the reference taken
1944 * by ubc_map() is released.
1946 * IMPORTANT: This MUST only be called by the VM
1947 * to prevent race conditions.
1949 __private_extern__
void
1950 ubc_unmap(struct vnode
*vp
)
1952 struct ubc_info
*uip
;
1954 int need_wakeup
= 0;
1956 if (vnode_getwithref(vp
))
1959 if (UBCINFOEXISTS(vp
)) {
1960 bool want_fsevent
= false;
1963 uip
= vp
->v_ubcinfo
;
1965 while (ISSET(uip
->ui_flags
, UI_MAPBUSY
)) {
1966 SET(uip
->ui_flags
, UI_MAPWAITING
);
1967 (void) msleep(&uip
->ui_flags
, &vp
->v_lock
,
1968 PRIBIO
, "ubc_unmap", NULL
);
1970 SET(uip
->ui_flags
, UI_MAPBUSY
);
1972 if (ISSET(uip
->ui_flags
, UI_ISMAPPED
)) {
1973 if (ISSET(uip
->ui_flags
, UI_MAPPEDWRITE
))
1974 want_fsevent
= true;
1979 * We want to clear the mapped flags after we've called
1980 * VNOP_MNOMAP to avoid certain races and allow
1981 * VNOP_MNOMAP to call ubc_is_mapped_writable.
1987 vfs_context_t ctx
= vfs_context_current();
1989 (void)VNOP_MNOMAP(vp
, ctx
);
1993 * Why do we want an fsevent here? Normally the
1994 * content modified fsevent is posted when a file is
1995 * closed and only if it's written to via conventional
1996 * means. It's perfectly legal to close a file and
1997 * keep your mappings and we don't currently track
1998 * whether it was written to via a mapping.
1999 * Therefore, we need to post an fsevent here if the
2000 * file was mapped writable. This may result in false
2001 * events, i.e. we post a notification when nothing
2002 * has really changed.
2004 if (want_fsevent
&& need_fsevent(FSE_CONTENT_MODIFIED
, vp
)) {
2005 add_fsevent(FSE_CONTENT_MODIFIED
, ctx
,
2014 vnode_lock_spin(vp
);
2017 CLR(uip
->ui_flags
, UI_ISMAPPED
| UI_MAPPEDWRITE
);
2019 CLR(uip
->ui_flags
, UI_MAPBUSY
);
2021 if (ISSET(uip
->ui_flags
, UI_MAPWAITING
)) {
2022 CLR(uip
->ui_flags
, UI_MAPWAITING
);
2028 wakeup(&uip
->ui_flags
);
2032 * the drop of the vnode ref will cleanup
2041 * Manipulate individual page state for a vnode with an associated ubc_info
2042 * with an associated memory object control.
2044 * Parameters: vp The vnode backing the page
2045 * f_offset A file offset interior to the page
2046 * ops The operations to perform, as a bitmap
2047 * (see below for more information)
2048 * phys_entryp The address of a ppnum_t; may be NULL
2050 * flagsp A pointer to an int to contain flags;
2051 * may be NULL to ignore
2053 * Returns: KERN_SUCCESS Success
2054 * KERN_INVALID_ARGUMENT If the memory object control has no VM
2056 * KERN_INVALID_OBJECT If UPL_POP_PHYSICAL and the object is
2057 * not physically contiguous
2058 * KERN_INVALID_OBJECT If !UPL_POP_PHYSICAL and the object is
2059 * physically contiguous
2060 * KERN_FAILURE If the page cannot be looked up
2063 * *phys_entryp (modified) If phys_entryp is non-NULL and
2065 * *flagsp (modified) If flagsp is non-NULL and there was
2066 * !UPL_POP_PHYSICAL and a KERN_SUCCESS
2068 * Notes: For object boundaries, it is considerably more efficient to
2069 * ensure that f_offset is in fact on a page boundary, as this
2070 * will avoid internal use of the hash table to identify the
2071 * page, and would therefore skip a number of early optimizations.
2072 * Since this is a page operation anyway, the caller should try
2073 * to pass only a page aligned offset because of this.
2075 * *flagsp may be modified even if this function fails. If it is
2076 * modified, it will contain the condition of the page before the
2077 * requested operation was attempted; these will only include the
2078 * bitmap flags, and not the PL_POP_PHYSICAL, UPL_POP_DUMP,
2079 * UPL_POP_SET, or UPL_POP_CLR bits.
2081 * The flags field may contain a specific operation, such as
2082 * UPL_POP_PHYSICAL or UPL_POP_DUMP:
2084 * o UPL_POP_PHYSICAL Fail if not contiguous; if
2085 * *phys_entryp and successful, set
2087 * o UPL_POP_DUMP Dump the specified page
2089 * Otherwise, it is treated as a bitmap of one or more page
2090 * operations to perform on the final memory object; allowable
2093 * o UPL_POP_DIRTY The page is dirty
2094 * o UPL_POP_PAGEOUT The page is paged out
2095 * o UPL_POP_PRECIOUS The page is precious
2096 * o UPL_POP_ABSENT The page is absent
2097 * o UPL_POP_BUSY The page is busy
2099 * If the page status is only being queried and not modified, then
2100 * not other bits should be specified. However, if it is being
2101 * modified, exactly ONE of the following bits should be set:
2103 * o UPL_POP_SET Set the current bitmap bits
2104 * o UPL_POP_CLR Clear the current bitmap bits
2106 * Thus to effect a combination of setting an clearing, it may be
2107 * necessary to call this function twice. If this is done, the
2108 * set should be used before the clear, since clearing may trigger
2109 * a wakeup on the destination page, and if the page is backed by
2110 * an encrypted swap file, setting will trigger the decryption
2111 * needed before the wakeup occurs.
2118 ppnum_t
*phys_entryp
,
2121 memory_object_control_t control
;
2123 control
= ubc_getobject(vp
, UBC_FLAGS_NONE
);
2124 if (control
== MEMORY_OBJECT_CONTROL_NULL
)
2125 return KERN_INVALID_ARGUMENT
;
2127 return (memory_object_page_op(control
,
2128 (memory_object_offset_t
)f_offset
,
2138 * Manipulate page state for a range of memory for a vnode with an associated
2139 * ubc_info with an associated memory object control, when page level state is
2140 * not required to be returned from the call (i.e. there are no phys_entryp or
2141 * flagsp parameters to this call, and it takes a range which may contain
2142 * multiple pages, rather than an offset interior to a single page).
2144 * Parameters: vp The vnode backing the page
2145 * f_offset_beg A file offset interior to the start page
2146 * f_offset_end A file offset interior to the end page
2147 * ops The operations to perform, as a bitmap
2148 * (see below for more information)
2149 * range The address of an int; may be NULL to
2152 * Returns: KERN_SUCCESS Success
2153 * KERN_INVALID_ARGUMENT If the memory object control has no VM
2155 * KERN_INVALID_OBJECT If the object is physically contiguous
2158 * *range (modified) If range is non-NULL, its contents will
2159 * be modified to contain the number of
2160 * bytes successfully operated upon.
2162 * Notes: IMPORTANT: This function cannot be used on a range that
2163 * consists of physically contiguous pages.
2165 * For object boundaries, it is considerably more efficient to
2166 * ensure that f_offset_beg and f_offset_end are in fact on page
2167 * boundaries, as this will avoid internal use of the hash table
2168 * to identify the page, and would therefore skip a number of
2169 * early optimizations. Since this is an operation on a set of
2170 * pages anyway, the caller should try to pass only a page aligned
2171 * offsets because of this.
2173 * *range will be modified only if this function succeeds.
2175 * The flags field MUST contain a specific operation; allowable
2178 * o UPL_ROP_ABSENT Returns the extent of the range
2179 * presented which is absent, starting
2180 * with the start address presented
2182 * o UPL_ROP_PRESENT Returns the extent of the range
2183 * presented which is present (resident),
2184 * starting with the start address
2186 * o UPL_ROP_DUMP Dump the pages which are found in the
2187 * target object for the target range.
2189 * IMPORTANT: For UPL_ROP_ABSENT and UPL_ROP_PRESENT; if there are
2190 * multiple regions in the range, only the first matching region
2201 memory_object_control_t control
;
2203 control
= ubc_getobject(vp
, UBC_FLAGS_NONE
);
2204 if (control
== MEMORY_OBJECT_CONTROL_NULL
)
2205 return KERN_INVALID_ARGUMENT
;
2207 return (memory_object_range_op(control
,
2208 (memory_object_offset_t
)f_offset_beg
,
2209 (memory_object_offset_t
)f_offset_end
,
2218 * Given a vnode, cause the population of a portion of the vm_object; based on
2219 * the nature of the request, the pages returned may contain valid data, or
2220 * they may be uninitialized.
2222 * Parameters: vp The vnode from which to create the upl
2223 * f_offset The start offset into the backing store
2224 * represented by the vnode
2225 * bufsize The size of the upl to create
2226 * uplp Pointer to the upl_t to receive the
2227 * created upl; MUST NOT be NULL
2228 * plp Pointer to receive the internal page
2229 * list for the created upl; MAY be NULL
2232 * Returns: KERN_SUCCESS The requested upl has been created
2233 * KERN_INVALID_ARGUMENT The bufsize argument is not an even
2234 * multiple of the page size
2235 * KERN_INVALID_ARGUMENT There is no ubc_info associated with
2236 * the vnode, or there is no memory object
2237 * control associated with the ubc_info
2238 * memory_object_upl_request:KERN_INVALID_VALUE
2239 * The supplied upl_flags argument is
2243 * *plp (modified) If non-NULL, the value of *plp will be
2244 * modified to point to the internal page
2245 * list; this modification may occur even
2246 * if this function is unsuccessful, in
2247 * which case the contents may be invalid
2249 * Note: If successful, the returned *uplp MUST subsequently be freed
2250 * via a call to ubc_upl_commit(), ubc_upl_commit_range(),
2251 * ubc_upl_abort(), or ubc_upl_abort_range().
2259 upl_page_info_t
**plp
,
2262 memory_object_control_t control
;
2269 if (bufsize
& 0xfff)
2270 return KERN_INVALID_ARGUMENT
;
2272 if (bufsize
> MAX_UPL_SIZE_BYTES
)
2273 return KERN_INVALID_ARGUMENT
;
2275 if (uplflags
& (UPL_UBC_MSYNC
| UPL_UBC_PAGEOUT
| UPL_UBC_PAGEIN
)) {
2277 if (uplflags
& UPL_UBC_MSYNC
) {
2278 uplflags
&= UPL_RET_ONLY_DIRTY
;
2280 uplflags
|= UPL_COPYOUT_FROM
| UPL_CLEAN_IN_PLACE
|
2281 UPL_SET_INTERNAL
| UPL_SET_LITE
;
2283 } else if (uplflags
& UPL_UBC_PAGEOUT
) {
2284 uplflags
&= UPL_RET_ONLY_DIRTY
;
2286 if (uplflags
& UPL_RET_ONLY_DIRTY
)
2287 uplflags
|= UPL_NOBLOCK
;
2289 uplflags
|= UPL_FOR_PAGEOUT
| UPL_CLEAN_IN_PLACE
|
2290 UPL_COPYOUT_FROM
| UPL_SET_INTERNAL
| UPL_SET_LITE
;
2292 uplflags
|= UPL_RET_ONLY_ABSENT
|
2293 UPL_NO_SYNC
| UPL_CLEAN_IN_PLACE
|
2294 UPL_SET_INTERNAL
| UPL_SET_LITE
;
2297 * if the requested size == PAGE_SIZE, we don't want to set
2298 * the UPL_NOBLOCK since we may be trying to recover from a
2299 * previous partial pagein I/O that occurred because we were low
2300 * on memory and bailed early in order to honor the UPL_NOBLOCK...
2301 * since we're only asking for a single page, we can block w/o fear
2302 * of tying up pages while waiting for more to become available
2304 if (bufsize
> PAGE_SIZE
)
2305 uplflags
|= UPL_NOBLOCK
;
2308 uplflags
&= ~UPL_FOR_PAGEOUT
;
2310 if (uplflags
& UPL_WILL_BE_DUMPED
) {
2311 uplflags
&= ~UPL_WILL_BE_DUMPED
;
2312 uplflags
|= (UPL_NO_SYNC
|UPL_SET_INTERNAL
);
2314 uplflags
|= (UPL_NO_SYNC
|UPL_CLEAN_IN_PLACE
|UPL_SET_INTERNAL
);
2316 control
= ubc_getobject(vp
, UBC_FLAGS_NONE
);
2317 if (control
== MEMORY_OBJECT_CONTROL_NULL
)
2318 return KERN_INVALID_ARGUMENT
;
2320 kr
= memory_object_upl_request(control
, f_offset
, bufsize
, uplp
, NULL
, NULL
, uplflags
);
2321 if (kr
== KERN_SUCCESS
&& plp
!= NULL
)
2322 *plp
= UPL_GET_INTERNAL_PAGE_LIST(*uplp
);
2328 * ubc_upl_maxbufsize
2330 * Return the maximum bufsize ubc_create_upl( ) will take.
2334 * Returns: maximum size buffer (in bytes) ubc_create_upl( ) will take.
2340 return(MAX_UPL_SIZE_BYTES
);
2346 * Map the page list assocated with the supplied upl into the kernel virtual
2347 * address space at the virtual address indicated by the dst_addr argument;
2348 * the entire upl is mapped
2350 * Parameters: upl The upl to map
2351 * dst_addr The address at which to map the upl
2353 * Returns: KERN_SUCCESS The upl has been mapped
2354 * KERN_INVALID_ARGUMENT The upl is UPL_NULL
2355 * KERN_FAILURE The upl is already mapped
2356 * vm_map_enter:KERN_INVALID_ARGUMENT
2357 * A failure code from vm_map_enter() due
2358 * to an invalid argument
2363 vm_offset_t
*dst_addr
)
2365 return (vm_upl_map(kernel_map
, upl
, dst_addr
));
2372 * Unmap the page list assocated with the supplied upl from the kernel virtual
2373 * address space; the entire upl is unmapped.
2375 * Parameters: upl The upl to unmap
2377 * Returns: KERN_SUCCESS The upl has been unmapped
2378 * KERN_FAILURE The upl is not currently mapped
2379 * KERN_INVALID_ARGUMENT If the upl is UPL_NULL
2385 return(vm_upl_unmap(kernel_map
, upl
));
2392 * Commit the contents of the upl to the backing store
2394 * Parameters: upl The upl to commit
2396 * Returns: KERN_SUCCESS The upl has been committed
2397 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
2398 * KERN_FAILURE The supplied upl does not represent
2399 * device memory, and the offset plus the
2400 * size would exceed the actual size of
2403 * Notes: In practice, the only return value for this function should be
2404 * KERN_SUCCESS, unless there has been data structure corruption;
2405 * since the upl is deallocated regardless of success or failure,
2406 * there's really nothing to do about this other than panic.
2408 * IMPORTANT: Use of this function should not be mixed with use of
2409 * ubc_upl_commit_range(), due to the unconditional deallocation
2416 upl_page_info_t
*pl
;
2419 pl
= UPL_GET_INTERNAL_PAGE_LIST(upl
);
2420 kr
= upl_commit(upl
, pl
, MAX_UPL_SIZE_BYTES
>> PAGE_SHIFT
);
2421 upl_deallocate(upl
);
2429 * Commit the contents of the specified range of the upl to the backing store
2431 * Parameters: upl The upl to commit
2432 * offset The offset into the upl
2433 * size The size of the region to be committed,
2434 * starting at the specified offset
2435 * flags commit type (see below)
2437 * Returns: KERN_SUCCESS The range has been committed
2438 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
2439 * KERN_FAILURE The supplied upl does not represent
2440 * device memory, and the offset plus the
2441 * size would exceed the actual size of
2444 * Notes: IMPORTANT: If the commit is successful, and the object is now
2445 * empty, the upl will be deallocated. Since the caller cannot
2446 * check that this is the case, the UPL_COMMIT_FREE_ON_EMPTY flag
2447 * should generally only be used when the offset is 0 and the size
2448 * is equal to the upl size.
2450 * The flags argument is a bitmap of flags on the rage of pages in
2451 * the upl to be committed; allowable flags are:
2453 * o UPL_COMMIT_FREE_ON_EMPTY Free the upl when it is
2454 * both empty and has been
2455 * successfully committed
2456 * o UPL_COMMIT_CLEAR_DIRTY Clear each pages dirty
2457 * bit; will prevent a
2459 * o UPL_COMMIT_SET_DIRTY Set each pages dirty
2460 * bit; will cause a later
2462 * o UPL_COMMIT_INACTIVATE Clear each pages
2463 * reference bit; the page
2464 * will not be accessed
2465 * o UPL_COMMIT_ALLOW_ACCESS Unbusy each page; pages
2466 * become busy when an
2467 * IOMemoryDescriptor is
2468 * mapped or redirected,
2469 * and we have to wait for
2472 * The flag UPL_COMMIT_NOTIFY_EMPTY is used internally, and should
2473 * not be specified by the caller.
2475 * The UPL_COMMIT_CLEAR_DIRTY and UPL_COMMIT_SET_DIRTY flags are
2476 * mutually exclusive, and should not be combined.
2479 ubc_upl_commit_range(
2481 upl_offset_t offset
,
2485 upl_page_info_t
*pl
;
2489 if (flags
& UPL_COMMIT_FREE_ON_EMPTY
)
2490 flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
2492 if (flags
& UPL_COMMIT_KERNEL_ONLY_FLAGS
) {
2493 return KERN_INVALID_ARGUMENT
;
2496 pl
= UPL_GET_INTERNAL_PAGE_LIST(upl
);
2498 kr
= upl_commit_range(upl
, offset
, size
, flags
,
2499 pl
, MAX_UPL_SIZE_BYTES
>> PAGE_SHIFT
, &empty
);
2501 if((flags
& UPL_COMMIT_FREE_ON_EMPTY
) && empty
)
2502 upl_deallocate(upl
);
2509 * ubc_upl_abort_range
2511 * Abort the contents of the specified range of the specified upl
2513 * Parameters: upl The upl to abort
2514 * offset The offset into the upl
2515 * size The size of the region to be aborted,
2516 * starting at the specified offset
2517 * abort_flags abort type (see below)
2519 * Returns: KERN_SUCCESS The range has been aborted
2520 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
2521 * KERN_FAILURE The supplied upl does not represent
2522 * device memory, and the offset plus the
2523 * size would exceed the actual size of
2526 * Notes: IMPORTANT: If the abort is successful, and the object is now
2527 * empty, the upl will be deallocated. Since the caller cannot
2528 * check that this is the case, the UPL_ABORT_FREE_ON_EMPTY flag
2529 * should generally only be used when the offset is 0 and the size
2530 * is equal to the upl size.
2532 * The abort_flags argument is a bitmap of flags on the range of
2533 * pages in the upl to be aborted; allowable flags are:
2535 * o UPL_ABORT_FREE_ON_EMPTY Free the upl when it is both
2536 * empty and has been successfully
2538 * o UPL_ABORT_RESTART The operation must be restarted
2539 * o UPL_ABORT_UNAVAILABLE The pages are unavailable
2540 * o UPL_ABORT_ERROR An I/O error occurred
2541 * o UPL_ABORT_DUMP_PAGES Just free the pages
2542 * o UPL_ABORT_NOTIFY_EMPTY RESERVED
2543 * o UPL_ABORT_ALLOW_ACCESS RESERVED
2545 * The UPL_ABORT_NOTIFY_EMPTY is an internal use flag and should
2546 * not be specified by the caller. It is intended to fulfill the
2547 * same role as UPL_COMMIT_NOTIFY_EMPTY does in the function
2548 * ubc_upl_commit_range(), but is never referenced internally.
2550 * The UPL_ABORT_ALLOW_ACCESS is defined, but neither set nor
2551 * referenced; do not use it.
2554 ubc_upl_abort_range(
2556 upl_offset_t offset
,
2561 boolean_t empty
= FALSE
;
2563 if (abort_flags
& UPL_ABORT_FREE_ON_EMPTY
)
2564 abort_flags
|= UPL_ABORT_NOTIFY_EMPTY
;
2566 kr
= upl_abort_range(upl
, offset
, size
, abort_flags
, &empty
);
2568 if((abort_flags
& UPL_ABORT_FREE_ON_EMPTY
) && empty
)
2569 upl_deallocate(upl
);
2578 * Abort the contents of the specified upl
2580 * Parameters: upl The upl to abort
2581 * abort_type abort type (see below)
2583 * Returns: KERN_SUCCESS The range has been aborted
2584 * KERN_INVALID_ARGUMENT The supplied upl was UPL_NULL
2585 * KERN_FAILURE The supplied upl does not represent
2586 * device memory, and the offset plus the
2587 * size would exceed the actual size of
2590 * Notes: IMPORTANT: If the abort is successful, and the object is now
2591 * empty, the upl will be deallocated. Since the caller cannot
2592 * check that this is the case, the UPL_ABORT_FREE_ON_EMPTY flag
2593 * should generally only be used when the offset is 0 and the size
2594 * is equal to the upl size.
2596 * The abort_type is a bitmap of flags on the range of
2597 * pages in the upl to be aborted; allowable flags are:
2599 * o UPL_ABORT_FREE_ON_EMPTY Free the upl when it is both
2600 * empty and has been successfully
2602 * o UPL_ABORT_RESTART The operation must be restarted
2603 * o UPL_ABORT_UNAVAILABLE The pages are unavailable
2604 * o UPL_ABORT_ERROR An I/O error occurred
2605 * o UPL_ABORT_DUMP_PAGES Just free the pages
2606 * o UPL_ABORT_NOTIFY_EMPTY RESERVED
2607 * o UPL_ABORT_ALLOW_ACCESS RESERVED
2609 * The UPL_ABORT_NOTIFY_EMPTY is an internal use flag and should
2610 * not be specified by the caller. It is intended to fulfill the
2611 * same role as UPL_COMMIT_NOTIFY_EMPTY does in the function
2612 * ubc_upl_commit_range(), but is never referenced internally.
2614 * The UPL_ABORT_ALLOW_ACCESS is defined, but neither set nor
2615 * referenced; do not use it.
2624 kr
= upl_abort(upl
, abort_type
);
2625 upl_deallocate(upl
);
2633 * Retrieve the internal page list for the specified upl
2635 * Parameters: upl The upl to obtain the page list from
2637 * Returns: !NULL The (upl_page_info_t *) for the page
2638 * list internal to the upl
2639 * NULL Error/no page list associated
2641 * Notes: IMPORTANT: The function is only valid on internal objects
2642 * where the list request was made with the UPL_INTERNAL flag.
2644 * This function is a utility helper function, since some callers
2645 * may not have direct access to the header defining the macro,
2646 * due to abstraction layering constraints.
2652 return (UPL_GET_INTERNAL_PAGE_LIST(upl
));
2657 UBCINFOEXISTS(const struct vnode
* vp
)
2659 return((vp
) && ((vp
)->v_type
== VREG
) && ((vp
)->v_ubcinfo
!= UBC_INFO_NULL
));
2664 ubc_upl_range_needed(
2669 upl_range_needed(upl
, index
, count
);
2672 boolean_t
ubc_is_mapped(const struct vnode
*vp
, boolean_t
*writable
)
2674 if (!UBCINFOEXISTS(vp
) || !ISSET(vp
->v_ubcinfo
->ui_flags
, UI_ISMAPPED
))
2677 *writable
= ISSET(vp
->v_ubcinfo
->ui_flags
, UI_MAPPEDWRITE
);
2681 boolean_t
ubc_is_mapped_writable(const struct vnode
*vp
)
2684 return ubc_is_mapped(vp
, &writable
) && writable
;
2691 #define CS_BLOB_PAGEABLE 0
2692 static volatile SInt32 cs_blob_size
= 0;
2693 static volatile SInt32 cs_blob_count
= 0;
2694 static SInt32 cs_blob_size_peak
= 0;
2695 static UInt32 cs_blob_size_max
= 0;
2696 static SInt32 cs_blob_count_peak
= 0;
2698 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");
2699 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");
2700 SYSCTL_INT(_vm
, OID_AUTO
, cs_blob_count_peak
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_blob_count_peak
, 0, "Peak number of code signature blobs");
2701 SYSCTL_INT(_vm
, OID_AUTO
, cs_blob_size_peak
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_blob_size_peak
, 0, "Peak size of code signature blobs");
2702 SYSCTL_INT(_vm
, OID_AUTO
, cs_blob_size_max
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_blob_size_max
, 0, "Size of biggest code signature blob");
2705 * Function: csblob_parse_teamid
2707 * Description: This function returns a pointer to the team id
2708 stored within the codedirectory of the csblob.
2709 If the codedirectory predates team-ids, it returns
2711 This does not copy the name but returns a pointer to
2712 it within the CD. Subsequently, the CD must be
2713 available when this is used.
2717 csblob_parse_teamid(struct cs_blob
*csblob
)
2719 const CS_CodeDirectory
*cd
;
2721 if ((cd
= (const CS_CodeDirectory
*)csblob_find_blob(
2722 csblob
, CSSLOT_CODEDIRECTORY
, CSMAGIC_CODEDIRECTORY
)) == NULL
)
2725 if (ntohl(cd
->version
) < CS_SUPPORTSTEAMID
)
2728 if (cd
->teamOffset
== 0)
2731 const char *name
= ((const char *)cd
) + ntohl(cd
->teamOffset
);
2733 printf("found team-id %s in cdblob\n", name
);
2740 ubc_cs_blob_allocate(
2741 vm_offset_t
*blob_addr_p
,
2742 vm_size_t
*blob_size_p
)
2746 #if CS_BLOB_PAGEABLE
2747 *blob_size_p
= round_page(*blob_size_p
);
2748 kr
= kmem_alloc(kernel_map
, blob_addr_p
, *blob_size_p
, VM_KERN_MEMORY_SECURITY
);
2749 #else /* CS_BLOB_PAGEABLE */
2750 *blob_addr_p
= (vm_offset_t
) kalloc_tag(*blob_size_p
, VM_KERN_MEMORY_SECURITY
);
2751 if (*blob_addr_p
== 0) {
2756 #endif /* CS_BLOB_PAGEABLE */
2761 ubc_cs_blob_deallocate(
2762 vm_offset_t blob_addr
,
2763 vm_size_t blob_size
)
2765 #if CS_BLOB_PAGEABLE
2766 kmem_free(kernel_map
, blob_addr
, blob_size
);
2767 #else /* CS_BLOB_PAGEABLE */
2768 kfree((void *) blob_addr
, blob_size
);
2769 #endif /* CS_BLOB_PAGEABLE */
2780 struct cs_blob
**ret_blob
)
2783 struct ubc_info
*uip
;
2784 struct cs_blob
*blob
, *oblob
;
2786 ipc_port_t blob_handle
;
2787 memory_object_size_t blob_size
;
2788 const CS_CodeDirectory
*cd
;
2789 off_t blob_start_offset
, blob_end_offset
;
2790 union cs_hash_union mdctx
;
2791 boolean_t record_mtime
;
2794 record_mtime
= FALSE
;
2799 blob_handle
= IPC_PORT_NULL
;
2801 blob
= (struct cs_blob
*) kalloc(sizeof (struct cs_blob
));
2806 #if CS_BLOB_PAGEABLE
2807 /* get a memory entry on the blob */
2808 blob_size
= (memory_object_size_t
) size
;
2809 kr
= mach_make_memory_entry_64(kernel_map
,
2815 if (kr
!= KERN_SUCCESS
) {
2819 if (memory_object_round_page(blob_size
) !=
2820 (memory_object_size_t
) round_page(size
)) {
2821 printf("ubc_cs_blob_add: size mismatch 0x%llx 0x%lx !?\n",
2822 blob_size
, (size_t)size
);
2823 panic("XXX FBDP size mismatch 0x%llx 0x%lx\n", blob_size
, (size_t)size
);
2828 blob_size
= (memory_object_size_t
) size
;
2829 blob_handle
= IPC_PORT_NULL
;
2832 /* fill in the new blob */
2833 blob
->csb_cpu_type
= cputype
;
2834 blob
->csb_base_offset
= base_offset
;
2835 blob
->csb_mem_size
= size
;
2836 blob
->csb_mem_offset
= 0;
2837 blob
->csb_mem_handle
= blob_handle
;
2838 blob
->csb_mem_kaddr
= addr
;
2839 blob
->csb_flags
= 0;
2840 blob
->csb_platform_binary
= 0;
2841 blob
->csb_platform_path
= 0;
2842 blob
->csb_teamid
= NULL
;
2845 * Validate the blob's contents
2848 error
= cs_validate_csblob((const uint8_t *)addr
, size
, &cd
);
2851 printf("CODESIGNING: csblob invalid: %d\n", error
);
2852 blob
->csb_flags
= 0;
2853 blob
->csb_start_offset
= 0;
2854 blob
->csb_end_offset
= 0;
2855 memset(blob
->csb_cdhash
, 0, sizeof(blob
->csb_cdhash
));
2856 /* let the vnode checker determine if the signature is valid or not */
2858 const unsigned char *md_base
;
2859 uint8_t hash
[CS_HASH_MAX_SIZE
];
2862 blob
->csb_hashtype
= cs_find_md(cd
->hashType
);
2863 if (blob
->csb_hashtype
== NULL
|| blob
->csb_hashtype
->cs_digest_size
> sizeof(hash
))
2864 panic("validated CodeDirectory but unsupported type");
2865 if (blob
->csb_hashtype
->cs_cd_size
< CS_CDHASH_LEN
) {
2867 printf("cs_cd_size is too small for a cdhash\n");
2872 blob
->csb_flags
= (ntohl(cd
->flags
) & CS_ALLOWED_MACHO
) | CS_VALID
;
2873 blob
->csb_end_offset
= round_page_4K(ntohl(cd
->codeLimit
));
2874 if((ntohl(cd
->version
) >= CS_SUPPORTSSCATTER
) && (ntohl(cd
->scatterOffset
))) {
2875 const SC_Scatter
*scatter
= (const SC_Scatter
*)
2876 ((const char*)cd
+ ntohl(cd
->scatterOffset
));
2877 blob
->csb_start_offset
= ntohl(scatter
->base
) * PAGE_SIZE_4K
;
2879 blob
->csb_start_offset
= 0;
2881 /* compute the blob's cdhash */
2882 md_base
= (const unsigned char *) cd
;
2883 md_size
= ntohl(cd
->length
);
2885 blob
->csb_hashtype
->cs_init(&mdctx
);
2886 blob
->csb_hashtype
->cs_update(&mdctx
, md_base
, md_size
);
2887 blob
->csb_hashtype
->cs_final(hash
, &mdctx
);
2889 memcpy(blob
->csb_cdhash
, hash
, CS_CDHASH_LEN
);
2893 * Let policy module check whether the blob's signature is accepted.
2896 error
= mac_vnode_check_signature(vp
,
2899 (const void*)addr
, size
,
2903 printf("check_signature[pid: %d], error = %d\n", current_proc()->p_pid
, error
);
2906 if ((flags
& MAC_VNODE_CHECK_DYLD_SIM
) && !(cs_flags
& CS_PLATFORM_BINARY
)) {
2908 printf("check_signature[pid: %d], is not apple signed\n", current_proc()->p_pid
);
2914 if (cs_flags
& CS_PLATFORM_BINARY
) {
2916 printf("check_signature[pid: %d]: platform binary\n", current_proc()->p_pid
);
2917 blob
->csb_platform_binary
= 1;
2918 blob
->csb_platform_path
= !!(cs_flags
& CS_PLATFORM_PATH
);
2920 blob
->csb_platform_binary
= 0;
2921 blob
->csb_platform_path
= 0;
2922 blob
->csb_teamid
= csblob_parse_teamid(blob
);
2924 if (blob
->csb_teamid
)
2925 printf("check_signature[pid: %d]: team-id is %s\n", current_proc()->p_pid
, blob
->csb_teamid
);
2927 printf("check_signature[pid: %d]: no team-id\n", current_proc()->p_pid
);
2932 * Validate the blob's coverage
2934 blob_start_offset
= blob
->csb_base_offset
+ blob
->csb_start_offset
;
2935 blob_end_offset
= blob
->csb_base_offset
+ blob
->csb_end_offset
;
2937 if (blob_start_offset
>= blob_end_offset
||
2938 blob_start_offset
< 0 ||
2939 blob_end_offset
<= 0) {
2940 /* reject empty or backwards blob */
2946 if (! UBCINFOEXISTS(vp
)) {
2951 uip
= vp
->v_ubcinfo
;
2953 /* check if this new blob overlaps with an existing blob */
2954 for (oblob
= uip
->cs_blobs
;
2956 oblob
= oblob
->csb_next
) {
2957 off_t oblob_start_offset
, oblob_end_offset
;
2959 /* check for conflicting teamid */
2960 if (blob
->csb_platform_binary
) { //platform binary needs to be the same for app slices
2961 if (!oblob
->csb_platform_binary
) {
2966 } else if (blob
->csb_teamid
) { //teamid binary needs to be the same for app slices
2967 if (oblob
->csb_platform_binary
||
2968 oblob
->csb_teamid
== NULL
||
2969 strcmp(oblob
->csb_teamid
, blob
->csb_teamid
) != 0) {
2974 } else { // non teamid binary needs to be the same for app slices
2975 if (oblob
->csb_platform_binary
||
2976 oblob
->csb_teamid
!= NULL
) {
2983 oblob_start_offset
= (oblob
->csb_base_offset
+
2984 oblob
->csb_start_offset
);
2985 oblob_end_offset
= (oblob
->csb_base_offset
+
2986 oblob
->csb_end_offset
);
2987 if (blob_start_offset
>= oblob_end_offset
||
2988 blob_end_offset
<= oblob_start_offset
) {
2989 /* no conflict with this existing blob */
2992 if (blob_start_offset
== oblob_start_offset
&&
2993 blob_end_offset
== oblob_end_offset
&&
2994 blob
->csb_mem_size
== oblob
->csb_mem_size
&&
2995 blob
->csb_flags
== oblob
->csb_flags
&&
2996 (blob
->csb_cpu_type
== CPU_TYPE_ANY
||
2997 oblob
->csb_cpu_type
== CPU_TYPE_ANY
||
2998 blob
->csb_cpu_type
== oblob
->csb_cpu_type
) &&
2999 !bcmp(blob
->csb_cdhash
,
3003 * We already have this blob:
3004 * we'll return success but
3005 * throw away the new blob.
3007 if (oblob
->csb_cpu_type
== CPU_TYPE_ANY
) {
3009 * The old blob matches this one
3010 * but doesn't have any CPU type.
3011 * Update it with whatever the caller
3012 * provided this time.
3014 oblob
->csb_cpu_type
= cputype
;
3022 /* different blob: reject the new one */
3032 /* mark this vnode's VM object as having "signed pages" */
3033 kr
= memory_object_signed(uip
->ui_control
, TRUE
);
3034 if (kr
!= KERN_SUCCESS
) {
3040 if (uip
->cs_blobs
== NULL
) {
3041 /* loading 1st blob: record the file's current "modify time" */
3042 record_mtime
= TRUE
;
3045 /* set the generation count for cs_blobs */
3046 uip
->cs_add_gen
= cs_blob_generation_count
;
3049 * Add this blob to the list of blobs for this vnode.
3050 * We always add at the front of the list and we never remove a
3051 * blob from the list, so ubc_cs_get_blobs() can return whatever
3052 * the top of the list was and that list will remain valid
3053 * while we validate a page, even after we release the vnode's lock.
3055 blob
->csb_next
= uip
->cs_blobs
;
3056 uip
->cs_blobs
= blob
;
3058 OSAddAtomic(+1, &cs_blob_count
);
3059 if (cs_blob_count
> cs_blob_count_peak
) {
3060 cs_blob_count_peak
= cs_blob_count
; /* XXX atomic ? */
3062 OSAddAtomic((SInt32
) +blob
->csb_mem_size
, &cs_blob_size
);
3063 if ((SInt32
) cs_blob_size
> cs_blob_size_peak
) {
3064 cs_blob_size_peak
= (SInt32
) cs_blob_size
; /* XXX atomic ? */
3066 if ((UInt32
) blob
->csb_mem_size
> cs_blob_size_max
) {
3067 cs_blob_size_max
= (UInt32
) blob
->csb_mem_size
;
3072 const char *name
= vnode_getname_printable(vp
);
3074 printf("CODE SIGNING: proc %d(%s) "
3075 "loaded %s signatures for file (%s) "
3076 "range 0x%llx:0x%llx flags 0x%x\n",
3077 p
->p_pid
, p
->p_comm
,
3078 blob
->csb_cpu_type
== -1 ? "detached" : "embedded",
3080 blob
->csb_base_offset
+ blob
->csb_start_offset
,
3081 blob
->csb_base_offset
+ blob
->csb_end_offset
,
3083 vnode_putname_printable(name
);
3089 vnode_mtime(vp
, &uip
->cs_mtime
, vfs_context_current());
3095 error
= 0; /* success ! */
3100 printf("check_signature[pid: %d]: error = %d\n", current_proc()->p_pid
, error
);
3102 /* we failed; release what we allocated */
3104 kfree(blob
, sizeof (*blob
));
3107 if (blob_handle
!= IPC_PORT_NULL
) {
3108 mach_memory_entry_port_release(blob_handle
);
3109 blob_handle
= IPC_PORT_NULL
;
3113 if (error
== EAGAIN
) {
3115 * See above: error is EAGAIN if we were asked
3116 * to add an existing blob again. We cleaned the new
3117 * blob and we want to return success.
3121 * Since we're not failing, consume the data we received.
3123 ubc_cs_blob_deallocate(addr
, size
);
3130 csvnode_print_debug(struct vnode
*vp
)
3132 const char *name
= NULL
;
3133 struct ubc_info
*uip
;
3134 struct cs_blob
*blob
;
3136 name
= vnode_getname_printable(vp
);
3138 printf("csvnode: name: %s\n", name
);
3139 vnode_putname_printable(name
);
3142 vnode_lock_spin(vp
);
3144 if (! UBCINFOEXISTS(vp
)) {
3149 uip
= vp
->v_ubcinfo
;
3150 for (blob
= uip
->cs_blobs
; blob
!= NULL
; blob
= blob
->csb_next
) {
3151 printf("csvnode: range: %lu -> %lu flags: 0x%08x platform: %s path: %s team: %s\n",
3152 (unsigned long)blob
->csb_start_offset
,
3153 (unsigned long)blob
->csb_end_offset
,
3155 blob
->csb_platform_binary
? "yes" : "no",
3156 blob
->csb_platform_path
? "yes" : "no",
3157 blob
->csb_teamid
? blob
->csb_teamid
: "<NO-TEAM>");
3171 struct ubc_info
*uip
;
3172 struct cs_blob
*blob
;
3173 off_t offset_in_blob
;
3175 vnode_lock_spin(vp
);
3177 if (! UBCINFOEXISTS(vp
)) {
3182 uip
= vp
->v_ubcinfo
;
3183 for (blob
= uip
->cs_blobs
;
3185 blob
= blob
->csb_next
) {
3186 if (cputype
!= -1 && blob
->csb_cpu_type
== cputype
) {
3190 offset_in_blob
= offset
- blob
->csb_base_offset
;
3191 if (offset_in_blob
>= blob
->csb_start_offset
&&
3192 offset_in_blob
< blob
->csb_end_offset
) {
3193 /* our offset is covered by this blob */
3207 struct ubc_info
*uip
)
3209 struct cs_blob
*blob
, *next_blob
;
3211 for (blob
= uip
->cs_blobs
;
3214 next_blob
= blob
->csb_next
;
3215 if (blob
->csb_mem_kaddr
!= 0) {
3216 ubc_cs_blob_deallocate(blob
->csb_mem_kaddr
,
3217 blob
->csb_mem_size
);
3218 blob
->csb_mem_kaddr
= 0;
3220 if (blob
->csb_mem_handle
!= IPC_PORT_NULL
) {
3221 mach_memory_entry_port_release(blob
->csb_mem_handle
);
3223 blob
->csb_mem_handle
= IPC_PORT_NULL
;
3224 OSAddAtomic(-1, &cs_blob_count
);
3225 OSAddAtomic((SInt32
) -blob
->csb_mem_size
, &cs_blob_size
);
3226 kfree(blob
, sizeof (*blob
));
3228 #if CHECK_CS_VALIDATION_BITMAP
3229 ubc_cs_validation_bitmap_deallocate( uip
->ui_vnode
);
3231 uip
->cs_blobs
= NULL
;
3234 /* check cs blob generation on vnode
3236 * 0 : Success, the cs_blob attached is current
3237 * ENEEDAUTH : Generation count mismatch. Needs authentication again.
3240 ubc_cs_generation_check(
3243 int retval
= ENEEDAUTH
;
3245 vnode_lock_spin(vp
);
3247 if (UBCINFOEXISTS(vp
) && vp
->v_ubcinfo
->cs_add_gen
== cs_blob_generation_count
) {
3256 ubc_cs_blob_revalidate(
3258 struct cs_blob
*blob
,
3266 const CS_CodeDirectory
*cd
= NULL
;
3269 assert(blob
!= NULL
);
3271 error
= cs_validate_csblob((const uint8_t *)blob
->csb_mem_kaddr
, blob
->csb_mem_size
, &cd
);
3274 printf("CODESIGNING: csblob invalid: %d\n", error
);
3279 /* callout to mac_vnode_check_signature */
3281 error
= mac_vnode_check_signature(vp
, blob
->csb_base_offset
, blob
->csb_cdhash
,
3282 (const void*)blob
->csb_mem_kaddr
, (int)blob
->csb_mem_size
,
3284 if (cs_debug
&& error
) {
3285 printf("revalidate: check_signature[pid: %d], error = %d\n", current_proc()->p_pid
, error
);
3289 /* update generation number if success */
3290 vnode_lock_spin(vp
);
3291 if (UBCINFOEXISTS(vp
)) {
3293 vp
->v_ubcinfo
->cs_add_gen
= cs_blob_generation_count
;
3295 vp
->v_ubcinfo
->cs_add_gen
= 0;
3305 cs_blob_reset_cache()
3307 /* incrementing odd no by 2 makes sure '0' is never reached. */
3308 OSAddAtomic(+2, &cs_blob_generation_count
);
3309 printf("Reseting cs_blob cache from all vnodes. \n");
3316 struct ubc_info
*uip
;
3317 struct cs_blob
*blobs
;
3320 * No need to take the vnode lock here. The caller must be holding
3321 * a reference on the vnode (via a VM mapping or open file descriptor),
3322 * so the vnode will not go away. The ubc_info stays until the vnode
3323 * goes away. And we only modify "blobs" by adding to the head of the
3325 * The ubc_info could go away entirely if the vnode gets reclaimed as
3326 * part of a forced unmount. In the case of a code-signature validation
3327 * during a page fault, the "paging_in_progress" reference on the VM
3328 * object guarantess that the vnode pager (and the ubc_info) won't go
3329 * away during the fault.
3330 * Other callers need to protect against vnode reclaim by holding the
3331 * vnode lock, for example.
3334 if (! UBCINFOEXISTS(vp
)) {
3339 uip
= vp
->v_ubcinfo
;
3340 blobs
= uip
->cs_blobs
;
3349 struct timespec
*cs_mtime
)
3351 struct ubc_info
*uip
;
3353 if (! UBCINFOEXISTS(vp
)) {
3354 cs_mtime
->tv_sec
= 0;
3355 cs_mtime
->tv_nsec
= 0;
3359 uip
= vp
->v_ubcinfo
;
3360 cs_mtime
->tv_sec
= uip
->cs_mtime
.tv_sec
;
3361 cs_mtime
->tv_nsec
= uip
->cs_mtime
.tv_nsec
;
3364 unsigned long cs_validate_page_no_hash
= 0;
3365 unsigned long cs_validate_page_bad_hash
= 0;
3369 memory_object_t pager
,
3370 memory_object_offset_t page_offset
,
3374 union cs_hash_union mdctx
;
3375 struct cs_hash
*hashtype
= NULL
;
3376 unsigned char actual_hash
[CS_HASH_MAX_SIZE
];
3377 unsigned char expected_hash
[SHA1_RESULTLEN
];
3378 boolean_t found_hash
;
3379 struct cs_blob
*blobs
, *blob
;
3380 const CS_CodeDirectory
*cd
;
3381 const CS_SuperBlob
*embedded
;
3382 const unsigned char *hash
;
3383 boolean_t validated
;
3384 off_t offset
; /* page offset in the file */
3386 off_t codeLimit
= 0;
3387 const char *lower_bound
, *upper_bound
;
3388 vm_offset_t kaddr
, blob_addr
;
3392 offset
= page_offset
;
3394 /* retrieve the expected hash */
3396 blobs
= (struct cs_blob
*) _blobs
;
3400 blob
= blob
->csb_next
) {
3401 offset
= page_offset
- blob
->csb_base_offset
;
3402 if (offset
< blob
->csb_start_offset
||
3403 offset
>= blob
->csb_end_offset
) {
3404 /* our page is not covered by this blob */
3408 /* map the blob in the kernel address space */
3409 kaddr
= blob
->csb_mem_kaddr
;
3411 ksize
= (vm_size_t
) (blob
->csb_mem_size
+
3412 blob
->csb_mem_offset
);
3413 kr
= vm_map(kernel_map
,
3418 blob
->csb_mem_handle
,
3424 if (kr
!= KERN_SUCCESS
) {
3425 /* XXX FBDP what to do !? */
3426 printf("cs_validate_page: failed to map blob, "
3427 "size=0x%lx kr=0x%x\n",
3428 (size_t)blob
->csb_mem_size
, kr
);
3433 blob_addr
= kaddr
+ blob
->csb_mem_offset
;
3435 lower_bound
= CAST_DOWN(char *, blob_addr
);
3436 upper_bound
= lower_bound
+ blob
->csb_mem_size
;
3438 embedded
= (const CS_SuperBlob
*) blob_addr
;
3439 cd
= findCodeDirectory(embedded
, lower_bound
, upper_bound
);
3441 /* all CD's that have been injected is already validated */
3443 offset
= page_offset
- blob
->csb_base_offset
;
3444 if (offset
< blob
->csb_start_offset
||
3445 offset
>= blob
->csb_end_offset
) {
3446 /* our page is not covered by this blob */
3450 hashtype
= blob
->csb_hashtype
;
3451 if (hashtype
== NULL
)
3452 panic("unknown hash type ?");
3453 if (hashtype
->cs_digest_size
> sizeof(actual_hash
))
3454 panic("hash size too large");
3456 codeLimit
= ntohl(cd
->codeLimit
);
3458 hash
= hashes(cd
, (uint32_t)(offset
>>PAGE_SHIFT_4K
),
3460 lower_bound
, upper_bound
);
3462 bcopy(hash
, expected_hash
, sizeof(expected_hash
));
3470 if (found_hash
== FALSE
) {
3472 * We can't verify this page because there is no signature
3473 * for it (yet). It's possible that this part of the object
3474 * is not signed, or that signatures for that part have not
3476 * Report that the page has not been validated and let the
3477 * caller decide if it wants to accept it or not.
3479 cs_validate_page_no_hash
++;
3481 printf("CODE SIGNING: cs_validate_page: "
3482 "mobj %p off 0x%llx: no hash to validate !?\n",
3483 pager
, page_offset
);
3491 size
= PAGE_SIZE_4K
;
3492 const uint32_t *asha1
, *esha1
;
3493 if ((off_t
)(offset
+ size
) > codeLimit
) {
3494 /* partial page at end of segment */
3495 assert(offset
< codeLimit
);
3496 size
= (size_t) (codeLimit
& PAGE_MASK_4K
);
3497 *tainted
|= CS_VALIDATE_NX
;
3500 hashtype
->cs_init(&mdctx
);
3501 hashtype
->cs_update(&mdctx
, data
, size
);
3502 hashtype
->cs_final(actual_hash
, &mdctx
);
3504 asha1
= (const uint32_t *) actual_hash
;
3505 esha1
= (const uint32_t *) expected_hash
;
3507 if (bcmp(expected_hash
, actual_hash
, hashtype
->cs_cd_size
) != 0) {
3509 printf("CODE SIGNING: cs_validate_page: "
3510 "mobj %p off 0x%llx size 0x%lx: "
3511 "actual [0x%x 0x%x 0x%x 0x%x 0x%x] != "
3512 "expected [0x%x 0x%x 0x%x 0x%x 0x%x]\n",
3513 pager
, page_offset
, size
,
3514 asha1
[0], asha1
[1], asha1
[2],
3516 esha1
[0], esha1
[1], esha1
[2],
3517 esha1
[3], esha1
[4]);
3519 cs_validate_page_bad_hash
++;
3520 *tainted
|= CS_VALIDATE_TAINTED
;
3522 if (cs_debug
> 10) {
3523 printf("CODE SIGNING: cs_validate_page: "
3524 "mobj %p off 0x%llx size 0x%lx: "
3526 pager
, page_offset
, size
);
3539 unsigned char *cdhash
)
3541 struct cs_blob
*blobs
, *blob
;
3547 blobs
= ubc_get_cs_blobs(vp
);
3550 blob
= blob
->csb_next
) {
3551 /* compute offset relative to this blob */
3552 rel_offset
= offset
- blob
->csb_base_offset
;
3553 if (rel_offset
>= blob
->csb_start_offset
&&
3554 rel_offset
< blob
->csb_end_offset
) {
3555 /* this blob does cover our "offset" ! */
3561 /* we didn't find a blob covering "offset" */
3562 ret
= EBADEXEC
; /* XXX any better error ? */
3564 /* get the SHA1 hash of that blob */
3565 bcopy(blob
->csb_cdhash
, cdhash
, sizeof (blob
->csb_cdhash
));
3574 #if CHECK_CS_VALIDATION_BITMAP
3575 #define stob(s) ((atop_64((s)) + 07) >> 3)
3576 extern boolean_t root_fs_upgrade_try
;
3579 * Should we use the code-sign bitmap to avoid repeated code-sign validation?
3581 * a) Is the target vnode on the root filesystem?
3582 * b) Has someone tried to mount the root filesystem read-write?
3583 * If answers are (a) yes AND (b) no, then we can use the bitmap.
3585 #define USE_CODE_SIGN_BITMAP(vp) ( (vp != NULL) && (vp->v_mount != NULL) && (vp->v_mount->mnt_flag & MNT_ROOTFS) && !root_fs_upgrade_try)
3587 ubc_cs_validation_bitmap_allocate(
3590 kern_return_t kr
= KERN_SUCCESS
;
3591 struct ubc_info
*uip
;
3592 char *target_bitmap
;
3593 vm_object_size_t bitmap_size
;
3595 if ( ! USE_CODE_SIGN_BITMAP(vp
) || (! UBCINFOEXISTS(vp
))) {
3596 kr
= KERN_INVALID_ARGUMENT
;
3598 uip
= vp
->v_ubcinfo
;
3600 if ( uip
->cs_valid_bitmap
== NULL
) {
3601 bitmap_size
= stob(uip
->ui_size
);
3602 target_bitmap
= (char*) kalloc( (vm_size_t
)bitmap_size
);
3603 if (target_bitmap
== 0) {
3608 if( kr
== KERN_SUCCESS
) {
3609 memset( target_bitmap
, 0, (size_t)bitmap_size
);
3610 uip
->cs_valid_bitmap
= (void*)target_bitmap
;
3611 uip
->cs_valid_bitmap_size
= bitmap_size
;
3619 ubc_cs_check_validation_bitmap (
3621 memory_object_offset_t offset
,
3624 kern_return_t kr
= KERN_SUCCESS
;
3626 if ( ! USE_CODE_SIGN_BITMAP(vp
) || ! UBCINFOEXISTS(vp
)) {
3627 kr
= KERN_INVALID_ARGUMENT
;
3629 struct ubc_info
*uip
= vp
->v_ubcinfo
;
3630 char *target_bitmap
= uip
->cs_valid_bitmap
;
3632 if ( target_bitmap
== NULL
) {
3633 kr
= KERN_INVALID_ARGUMENT
;
3636 bit
= atop_64( offset
);
3639 if ( byte
> uip
->cs_valid_bitmap_size
) {
3640 kr
= KERN_INVALID_ARGUMENT
;
3643 if (optype
== CS_BITMAP_SET
) {
3644 target_bitmap
[byte
] |= (1 << (bit
& 07));
3646 } else if (optype
== CS_BITMAP_CLEAR
) {
3647 target_bitmap
[byte
] &= ~(1 << (bit
& 07));
3649 } else if (optype
== CS_BITMAP_CHECK
) {
3650 if ( target_bitmap
[byte
] & (1 << (bit
& 07))) {
3663 ubc_cs_validation_bitmap_deallocate(
3666 struct ubc_info
*uip
;
3667 void *target_bitmap
;
3668 vm_object_size_t bitmap_size
;
3670 if ( UBCINFOEXISTS(vp
)) {
3671 uip
= vp
->v_ubcinfo
;
3673 if ( (target_bitmap
= uip
->cs_valid_bitmap
) != NULL
) {
3674 bitmap_size
= uip
->cs_valid_bitmap_size
;
3675 kfree( target_bitmap
, (vm_size_t
) bitmap_size
);
3676 uip
->cs_valid_bitmap
= NULL
;
3681 kern_return_t
ubc_cs_validation_bitmap_allocate(__unused vnode_t vp
){
3682 return KERN_INVALID_ARGUMENT
;
3685 kern_return_t
ubc_cs_check_validation_bitmap(
3686 __unused
struct vnode
*vp
,
3687 __unused memory_object_offset_t offset
,
3688 __unused
int optype
){
3690 return KERN_INVALID_ARGUMENT
;
3693 void ubc_cs_validation_bitmap_deallocate(__unused vnode_t vp
){
3696 #endif /* CHECK_CS_VALIDATION_BITMAP */