+
+#if CHECK_CS_VALIDATION_BITMAP
+#define stob(s) ((atop_64((s)) + 07) >> 3)
+extern boolean_t root_fs_upgrade_try;
+
+/*
+ * Should we use the code-sign bitmap to avoid repeated code-sign validation?
+ * Depends:
+ * a) Is the target vnode on the root filesystem?
+ * b) Has someone tried to mount the root filesystem read-write?
+ * If answers are (a) yes AND (b) no, then we can use the bitmap.
+ */
+#define USE_CODE_SIGN_BITMAP(vp) ( (vp != NULL) && (vp->v_mount != NULL) && (vp->v_mount->mnt_flag & MNT_ROOTFS) && !root_fs_upgrade_try)
+kern_return_t
+ubc_cs_validation_bitmap_allocate(
+ vnode_t vp)
+{
+ kern_return_t kr = KERN_SUCCESS;
+ struct ubc_info *uip;
+ char *target_bitmap;
+ vm_object_size_t bitmap_size;
+
+ if ( ! USE_CODE_SIGN_BITMAP(vp) || (! UBCINFOEXISTS(vp))) {
+ kr = KERN_INVALID_ARGUMENT;
+ } else {
+ uip = vp->v_ubcinfo;
+
+ if ( uip->cs_valid_bitmap == NULL ) {
+ bitmap_size = stob(uip->ui_size);
+ target_bitmap = (char*) kalloc( (vm_size_t)bitmap_size );
+ if (target_bitmap == 0) {
+ kr = KERN_NO_SPACE;
+ } else {
+ kr = KERN_SUCCESS;
+ }
+ if( kr == KERN_SUCCESS ) {
+ memset( target_bitmap, 0, (size_t)bitmap_size);
+ uip->cs_valid_bitmap = (void*)target_bitmap;
+ uip->cs_valid_bitmap_size = bitmap_size;
+ }
+ }
+ }
+ return kr;
+}
+
+kern_return_t
+ubc_cs_check_validation_bitmap (
+ vnode_t vp,
+ memory_object_offset_t offset,
+ int optype)
+{
+ kern_return_t kr = KERN_SUCCESS;
+
+ if ( ! USE_CODE_SIGN_BITMAP(vp) || ! UBCINFOEXISTS(vp)) {
+ kr = KERN_INVALID_ARGUMENT;
+ } else {
+ struct ubc_info *uip = vp->v_ubcinfo;
+ char *target_bitmap = uip->cs_valid_bitmap;
+
+ if ( target_bitmap == NULL ) {
+ kr = KERN_INVALID_ARGUMENT;
+ } else {
+ uint64_t bit, byte;
+ bit = atop_64( offset );
+ byte = bit >> 3;
+
+ if ( byte > uip->cs_valid_bitmap_size ) {
+ kr = KERN_INVALID_ARGUMENT;
+ } else {
+
+ if (optype == CS_BITMAP_SET) {
+ target_bitmap[byte] |= (1 << (bit & 07));
+ kr = KERN_SUCCESS;
+ } else if (optype == CS_BITMAP_CLEAR) {
+ target_bitmap[byte] &= ~(1 << (bit & 07));
+ kr = KERN_SUCCESS;
+ } else if (optype == CS_BITMAP_CHECK) {
+ if ( target_bitmap[byte] & (1 << (bit & 07))) {
+ kr = KERN_SUCCESS;
+ } else {
+ kr = KERN_FAILURE;
+ }
+ }
+ }
+ }
+ }
+ return kr;
+}
+
+void
+ubc_cs_validation_bitmap_deallocate(
+ vnode_t vp)
+{
+ struct ubc_info *uip;
+ void *target_bitmap;
+ vm_object_size_t bitmap_size;
+
+ if ( UBCINFOEXISTS(vp)) {
+ uip = vp->v_ubcinfo;
+
+ if ( (target_bitmap = uip->cs_valid_bitmap) != NULL ) {
+ bitmap_size = uip->cs_valid_bitmap_size;
+ kfree( target_bitmap, (vm_size_t) bitmap_size );
+ uip->cs_valid_bitmap = NULL;
+ }
+ }
+}
+#else
+kern_return_t ubc_cs_validation_bitmap_allocate(__unused vnode_t vp){
+ return KERN_INVALID_ARGUMENT;
+}
+
+kern_return_t ubc_cs_check_validation_bitmap(
+ __unused struct vnode *vp,
+ __unused memory_object_offset_t offset,
+ __unused int optype){
+
+ return KERN_INVALID_ARGUMENT;
+}
+
+void ubc_cs_validation_bitmap_deallocate(__unused vnode_t vp){
+ return;
+}
+#endif /* CHECK_CS_VALIDATION_BITMAP */