Loading...
iokit/bsddev/IOKitBSDInit.cpp xnu-12377.101.15 xnu-8792.81.2
--- xnu/xnu-12377.101.15/iokit/bsddev/IOKitBSDInit.cpp
+++ xnu/xnu-8792.81.2/iokit/bsddev/IOKitBSDInit.cpp
@@ -39,7 +39,6 @@
 extern "C" {
 #include <libkern/amfi/amfi.h>
 #include <sys/codesign.h>
-#include <sys/code_signing.h>
 #include <vm/pmap.h>
 #include <vm/vm_map.h>
 #include <pexpert/pexpert.h>
@@ -52,9 +51,6 @@
 #include <sys/vnode_internal.h>
 #include <sys/mount.h>
 #include <corecrypto/ccsha2.h>
-#include <kdp/sk_core.h>
-#include <pexpert/device_tree.h>
-#include <kern/startup.h>
 
 // how long to wait for matching root device, secs
 #if DEBUG
@@ -83,8 +79,6 @@
 #define kIOCoreDumpPath         "/private/var/vm/kernelcore"
 #endif
 
-#define kIOCoreDumpPrebootPath      "/private/preboot/kernelcore"
-
 #define SYSTEM_NVRAM_PREFIX     "40A0DDD2-77F8-4392-B4A3-1E7304206516:"
 
 #if CONFIG_KDP_INTERACTIVE_DEBUGGING
@@ -107,10 +101,8 @@
 
 #if IOPOLLED_COREFILE
 static void IOOpenPolledCoreFile(thread_call_param_t __unused, thread_call_param_t corefilename);
-static void IOResolveCoreFilePath();
 
 thread_call_t corefile_open_call = NULL;
-SECURITY_READ_ONLY_LATE(const char*) kdp_corefile_path = kIOCoreDumpPath;
 #endif
 
 kern_return_t
@@ -227,19 +219,7 @@
 OSDictionary *
 IOUUIDMatching( void )
 {
-	OSObject     * obj;
-	OSDictionary * result;
-
-	obj = OSUnserialize(
-		"{"
-		"'IOProviderClass' = 'IOResources';"
-		"'IOResourceMatch' = ('IOBSD', 'boot-uuid-media');"
-		"}",
-		NULL);
-	result = OSDynamicCast(OSDictionary, obj);
-	assert(result);
-
-	return result;
+	return IOService::resourceMatching( "boot-uuid-media" );
 }
 
 OSDictionary *
@@ -664,12 +644,7 @@
 
 	if (reboot) {
 		IOLog("\nAbout to reboot into Recovery!\n");
-		// Mitigation for SEP hanging on kPERestartCPU (radar://164664790).
-		// We panic and on the next boot we should land into recovery.
-		// This should be reverted back to calling
-		// PEHaltRestart(kPERestartCPU) in rdar://169561102.
-		panic("Reboot into Recovery (this panic is expected)");
-		// (void)PEHaltRestart(kPERestartCPU);
+		(void)PEHaltRestart(kPERestartCPU);
 	}
 
 	return true;
@@ -694,7 +669,6 @@
 	OSDataAllocation<char> str;
 	const char *        look = NULL;
 	int                 len;
-	int                 wdt = 0;
 	bool                debugInfoPrintedOnce = false;
 	bool                needNetworkKexts = false;
 	const char *        uuidStr = NULL;
@@ -778,11 +752,7 @@
 			data = (OSData *)regEntry->getProperty("RAMDisk");      /* Find the ram disk, if there */
 			if (data) {                                                                                      /* We found one */
 				uintptr_t *ramdParms;
-				/* BEGIN IGNORE CODESTYLE */
-				__typed_allocators_ignore_push
 				ramdParms = (uintptr_t *)data->getBytesNoCopy();        /* Point to the ram disk base and size */
-				__typed_allocators_ignore_pop
-				/* END IGNORE CODESTYLE */
 #if __LP64__
 #define MAX_PHYS_RAM    (((uint64_t)UINT_MAX) << 12)
 				if (ramdParms[1] > MAX_PHYS_RAM) {
@@ -904,13 +874,12 @@
 		IOService::startDeferredMatches();
 	}
 
-	PE_parse_boot_argn("wdt", &wdt, sizeof(wdt));
 	do {
 		t.tv_sec = ROOTDEVICETIMEOUT;
 		t.tv_nsec = 0;
 		matching->retain();
 		service = IOService::waitForService( matching, &t );
-		if ((-1 != wdt) && (!service || (mountAttempts == 10))) {
+		if ((!service) || (mountAttempts == 10)) {
 #if !XNU_TARGET_OS_OSX || !defined(__arm64__)
 			PE_display_icon( 0, "noroot");
 			IOLog( "Still waiting for root device\n" );
@@ -934,7 +903,7 @@
 #if XNU_TARGET_OS_OSX && defined(__arm64__)
 			// The disk isn't found - have the user pick from System Recovery.
 			(void)IOSetRecoveryBoot(BSD_BOOTFAIL_MEDIA_MISSING, NULL, true);
-#elif XNU_TARGET_OS_IOS || XNU_TARGET_OS_XR
+#elif XNU_TARGET_OS_IOS
 			panic("Failed to mount root device");
 #endif
 		}
@@ -1144,44 +1113,31 @@
 
 #if IOPOLLED_COREFILE
 
-#define ONE_MB                  1024ULL * 1024ULL
-
 #if defined(XNU_TARGET_OS_BRIDGE)
 // On bridgeOS allocate a 150MB corefile and leave 150MB free
-#define kIOCoreDumpSize         150ULL * ONE_MB
-#define kIOCoreDumpFreeSize     150ULL * ONE_MB
-
-#elif defined(XNU_TARGET_OS_OSX)
-
+#define kIOCoreDumpSize         150ULL*1024ULL*1024ULL
+#define kIOCoreDumpFreeSize     150ULL*1024ULL*1024ULL
+
+#elif !defined(XNU_TARGET_OS_OSX) /* defined(XNU_TARGET_OS_BRIDGE) */
+// On embedded devices with >3GB DRAM we allocate a 500MB corefile
+// otherwise allocate a 350MB corefile. Leave 350 MB free
+
+#define kIOCoreDumpMinSize      350ULL*1024ULL*1024ULL
+#define kIOCoreDumpLargeSize    500ULL*1024ULL*1024ULL
+
+#define kIOCoreDumpFreeSize     350ULL*1024ULL*1024ULL
+
+#else /* defined(XNU_TARGET_OS_BRIDGE) */
 // on macOS devices allocate a corefile sized at 1GB / 32GB of DRAM,
 // fallback to a 1GB corefile and leave at least 1GB free
-#define kIOCoreDumpMinSize              1024ULL * ONE_MB
-#define kIOCoreDumpIncrementalSize      1024ULL * ONE_MB
-
-#define kIOCoreDumpFreeSize     1024ULL * ONE_MB
+#define kIOCoreDumpMinSize              1024ULL*1024ULL*1024ULL
+#define kIOCoreDumpIncrementalSize      1024ULL*1024ULL*1024ULL
+
+#define kIOCoreDumpFreeSize     1024ULL*1024ULL*1024ULL
 
 // on older macOS devices we allocate a 1MB file at boot
 // to store a panic time stackshot
-#define kIOStackshotFileSize    ONE_MB
-
-#elif defined(XNU_TARGET_OS_XR)
-
-// XR OS requries larger corefile storage because XNU core can take
-// up to ~500MB.
-
-#define kIOCoreDumpMinSize      350ULL * ONE_MB
-#define kIOCoreDumpLargeSize    750ULL * ONE_MB
-
-#define kIOCoreDumpFreeSize     350ULL * ONE_MB
-
-#else /* defined(XNU_TARGET_OS_BRIDGE) */
-
-// On embedded devices with >3GB DRAM we allocate a 500MB corefile
-// otherwise allocate a 350MB corefile. Leave 350 MB free
-#define kIOCoreDumpMinSize      350ULL * ONE_MB
-#define kIOCoreDumpLargeSize    500ULL * ONE_MB
-
-#define kIOCoreDumpFreeSize     350ULL * ONE_MB
+#define kIOStackshotFileSize    1024ULL*1024ULL
 
 #endif /* defined(XNU_TARGET_OS_BRIDGE) */
 
@@ -1198,39 +1154,6 @@
 }
 
 static void
-IOResolveCoreFilePath()
-{
-	DTEntry node;
-	const char *value = NULL;
-	unsigned int size = 0;
-
-	if (kSuccess != SecureDTLookupEntry(NULL, "/product", &node)) {
-		return;
-	}
-	if (kSuccess != SecureDTGetProperty(node, "kernel-core-dump-location", (void const **) &value, &size)) {
-		return;
-	}
-	if (size == 0) {
-		return;
-	}
-
-	// The kdp_corefile_path is allowed to be one of 2 options to working locations.
-	// This value is set on EARLY_BOOT since we need to know it before any volumes are mounted. The mount
-	// event triggers IOOpenPolledCoreFile() which opens the file. Once we commit to using the path from EDT
-	// we can't back out since a different path may reside in a different volume.
-	// In case the path from EDT can't be opened, there will not be a kernel core-dump
-	if (strlcmp(value, "preboot", size) == 0) {
-		kdp_corefile_path = kIOCoreDumpPrebootPath;
-	} else if (strlcmp(value, "default", size) != 0) {
-		IOLog("corefile path selection in device-tree is not one of the allowed values: %s, Using default %s\n", value, kdp_corefile_path);
-		return;
-	}
-
-	IOLog("corefile path selection in device-tree was set to: %s (value: %s)\n", kdp_corefile_path, value);
-}
-STARTUP(EARLY_BOOT, STARTUP_RANK_MIDDLE, IOResolveCoreFilePath);
-
-static void
 IOCoreFileGetSize(uint64_t *ideal_size, uint64_t *fallback_size, uint64_t *free_space_to_leave, IOPolledCoreFileMode_t mode)
 {
 	unsigned int requested_corefile_size = 0;
@@ -1242,7 +1165,7 @@
 	    sizeof(requested_corefile_size))) {
 		IOLog("Boot-args specify %d MB kernel corefile\n", requested_corefile_size);
 
-		*ideal_size = *fallback_size = (requested_corefile_size * ONE_MB);
+		*ideal_size = *fallback_size = (requested_corefile_size * 1024ULL * 1024ULL);
 		return;
 	}
 
@@ -1266,7 +1189,7 @@
 #pragma unused(mode)
 	*ideal_size = *fallback_size = kIOCoreDumpMinSize;
 
-	if (max_mem > (3 * 1024ULL * ONE_MB)) {
+	if (max_mem > (3 * 1024ULL * 1024ULL * 1024ULL)) {
 		*ideal_size = kIOCoreDumpLargeSize;
 	}
 
@@ -1274,18 +1197,14 @@
 #else /* defined(XNU_TARGET_OS_BRIDGE) */
 	if (mode == kIOPolledCoreFileModeCoredump) {
 		*ideal_size = *fallback_size = kIOCoreDumpMinSize;
-		if (kIOCoreDumpIncrementalSize != 0 && max_mem > (32 * 1024ULL * ONE_MB)) {
-			*ideal_size = ((ROUNDUP(max_mem, (32 * 1024ULL * ONE_MB)) / (32 * 1024ULL * ONE_MB)) * kIOCoreDumpIncrementalSize);
+		if (kIOCoreDumpIncrementalSize != 0 && max_mem > (32 * 1024ULL * 1024ULL * 1024ULL)) {
+			*ideal_size = ((ROUNDUP(max_mem, (32 * 1024ULL * 1024ULL * 1024ULL)) / (32 * 1024ULL * 1024ULL * 1024ULL)) * kIOCoreDumpIncrementalSize);
 		}
 		*free_space_to_leave = kIOCoreDumpFreeSize;
 	} else if (mode == kIOPolledCoreFileModeStackshot) {
 		*ideal_size = *fallback_size = *free_space_to_leave = kIOStackshotFileSize;
 	}
 #endif /* defined(XNU_TARGET_OS_BRIDGE) */
-
-#if EXCLAVES_COREDUMP
-	*ideal_size += sk_core_size();
-#endif /* EXCLAVES_COREDUMP */
 
 	return;
 }
@@ -1347,13 +1266,12 @@
 	}
 
 	do {
-		// This file reference remains open long-term in case we need to write a core-dump
-		err = IOPolledFileOpen(filename, kIOPolledFileCreate, 0 /*setFileSizeMin*/, corefile_size_bytes, free_space_to_leave_bytes,
+		err = IOPolledFileOpen(filename, kIOPolledFileCreate, corefile_size_bytes, free_space_to_leave_bytes,
 		    NULL, 0, &gIOPolledCoreFileVars, NULL, NULL, NULL);
 		if (kIOReturnSuccess == err) {
 			break;
 		} else if (kIOReturnNoSpace == err) {
-			IOLog("Failed to open corefile of size %llu MB (low disk space)\n",
+			IOLog("Failed to open corefile of size %llu MB (low disk space)",
 			    (corefile_size_bytes / (1024ULL * 1024ULL)));
 			if (corefile_size_bytes == corefile_fallback_size_bytes) {
 				gIOPolledCoreFileOpenRet = err;
@@ -1366,7 +1284,7 @@
 			return;
 		}
 
-		err = IOPolledFileOpen(filename, kIOPolledFileCreate, 0 /*setFileSizeMin*/, corefile_fallback_size_bytes, free_space_to_leave_bytes,
+		err = IOPolledFileOpen(filename, kIOPolledFileCreate, corefile_fallback_size_bytes, free_space_to_leave_bytes,
 		    NULL, 0, &gIOPolledCoreFileVars, NULL, NULL, NULL);
 		if (kIOReturnSuccess != err) {
 			IOLog("Failed to open corefile of size %llu MB (returned error 0x%x)\n",
@@ -1409,7 +1327,7 @@
 
 	// Open the kernel corefile
 	vfs_context = vfs_context_kernel();
-	vnode_error = vnode_open(kdp_corefile_path, (FREAD | FWRITE | O_NOFOLLOW), 0600, 0, &vnode_ptr, vfs_context);
+	vnode_error = vnode_open(kIOCoreDumpPath, (FREAD | FWRITE | O_NOFOLLOW), 0600, 0, &vnode_ptr, vfs_context);
 	if (vnode_error) {
 		IOLog("Failed to open the corefile. Error %d\n", vnode_error);
 		return kIOReturnError;
@@ -1498,12 +1416,11 @@
 			break;
 		}
 #endif
-		// Does this mount point include the kernel core-file?
-		if (0 != strncmp(path, kdp_corefile_path, pathLen - 1)) {
+		if (0 != strncmp(path, kIOCoreDumpPath, pathLen - 1)) {
 			break;
 		}
 
-		thread_call_enter1(corefile_open_call, (void *) kdp_corefile_path);
+		thread_call_enter1(corefile_open_call, (void *) kIOCoreDumpPath);
 		break;
 
 	case kIOMountChangeUnmount:
@@ -1534,28 +1451,9 @@
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-static char*
-copyOSStringAsCString(OSString *string)
-{
-	size_t string_length = 0;
-	char *c_string = NULL;
-
-	if (string == NULL) {
-		return NULL;
-	}
-	string_length = string->getLength() + 1;
-
-	/* Allocate kernel data memory for the string */
-	c_string = (char*)kalloc_data(string_length, (zalloc_flags_t)(Z_ZERO | Z_WAITOK | Z_NOFAIL));
-	assert(c_string != NULL);
-
-	/* Copy in the string */
-	strlcpy(c_string, string->getCStringNoCopy(), string_length);
-
-	return c_string;
-}
-
-extern "C" OS_ALWAYS_INLINE boolean_t
+extern "C"
+OS_ALWAYS_INLINE
+boolean_t
 IOCurrentTaskHasStringEntitlement(const char *entitlement, const char *value)
 {
 	return IOTaskHasStringEntitlement(NULL, entitlement, value);
@@ -1564,208 +1462,162 @@
 extern "C" boolean_t
 IOTaskHasStringEntitlement(task_t task, const char *entitlement, const char *value)
 {
+	if (task == kernel_task) {
+		return false;
+	} else if (!entitlement || !value) {
+		return false;
+	}
+
+	size_t name_length = strnlen(entitlement, CE_MAX_KEY_SIZE);
+	if (name_length >= CE_MAX_KEY_SIZE) {
+		printf("entitlement name length exceeds maximum allowed\n");
+		return false;
+	}
+
+	size_t value_length = strnlen(value, CE_MAX_KEY_SIZE);
+	if (value_length >= CE_MAX_KEY_SIZE) {
+		printf("entitlement value length exceeds maximum allowed\n");
+		return false;
+	}
+
+	CEQuery_t query = {
+		CESelectDictValueDynamic((const uint8_t*)entitlement, name_length),
+		CEIsDynamicStringAllowed((const uint8_t*)value, value_length)
+	};
+
+#if PMAP_CS_ENABLE && !CONFIG_X86_64_COMPAT
+
+	/*
+	 * If we have PMAP_CS available and code signing is enabled, then we perform
+	 * the entitlement check in the PPL.
+	 *
+	 * Note that the security benefits of doing so are questionable. The PPL has
+	 * already locked down the entitlements blob, so we could simply have XNU go
+	 * through the locked entitlements blob instead of switching into the PPL to
+	 * perform the check. Afterall, the entitlement will be enforced by XNU and
+	 * not the PPL, so trapping into the PPL for the check means little.
+	 *
+	 * Nevertheless, this is kept around to be consistent with how some of the
+	 * other interfaces perform their entitlement checks.
+	 */
+
+	if (pmap_cs_enabled()) {
+		if (task == NULL || task == current_task()) {
+			/* NULL task implies current_task */
+			return pmap_query_entitlements(NULL, query, 2, NULL);
+		}
+
+		vm_map_t task_map = get_task_map_reference(task);
+		if (task_map) {
+			pmap_t pmap = vm_map_get_pmap(task_map);
+			if (pmap && pmap_query_entitlements(pmap, query, 2, NULL)) {
+				vm_map_deallocate(task_map);
+				return true;
+			}
+			vm_map_deallocate(task_map);
+		}
+		return false;
+	}
+
+#endif
+
+	/* AMFI interface needs to be available */
+	if (amfi == NULL) {
+		panic("CoreEntitlements: (IOTask): AMFI interface not available");
+	}
+
+	if (task == NULL) {
+		/* NULL task implies current_task */
+		task = current_task();
+	}
+
+	proc_t p = (proc_t)get_bsdtask_info(task);
+	if (p == NULL) {
+		/* Cannot proceed if we don't have a proc structure */
+		return false;
+	}
+
+	struct cs_blob* csblob = csproc_get_blob(p);
+	if (csblob == NULL) {
+		/* Cannot proceed if process doesn't have a code signature */
+		return false;
+	}
+
+	void* osents = csblob_os_entitlements_get(csblob);
+	if (osents == NULL) {
+		return false;
+	}
+
+	CEError_t ce_err = amfi->CoreEntitlements.kQueryCannotBeSatisfied;
+	ce_err = amfi->OSEntitlements_query(osents, (uint8_t*)csblob_get_cdhash(csblob), query, 2);
+
+	return ce_err == amfi->CoreEntitlements.kNoError;
+}
+
+extern "C"
+OS_ALWAYS_INLINE
+boolean_t
+IOCurrentTaskHasEntitlement(const char * entitlement)
+{
+	return IOTaskHasEntitlement(NULL, entitlement);
+}
+
+extern "C" boolean_t
+IOTaskHasEntitlement(task_t task, const char * entitlement)
+{
+	// Don't do this
+	if (task == kernel_task || entitlement == NULL) {
+		return false;
+	}
+	size_t entlen = strlen(entitlement);
+	CEQuery_t query = {
+		CESelectDictValueDynamic((const uint8_t*)entitlement, entlen),
+		CEMatchBool(true)
+	};
+
+#if PMAP_CS_ENABLE && !CONFIG_X86_64_COMPAT
+	if (pmap_cs_enabled()) {
+		if (task == NULL || task == current_task()) {
+			// NULL task means current task, which translated to the current pmap
+			return pmap_query_entitlements(NULL, query, 2, NULL);
+		}
+		vm_map_t task_map = get_task_map_reference(task);
+		if (task_map) {
+			pmap_t pmap = vm_map_get_pmap(task_map);
+			if (pmap && pmap_query_entitlements(pmap, query, 2, NULL)) {
+				vm_map_deallocate(task_map);
+				return true;
+			}
+			vm_map_deallocate(task_map);
+		}
+		return false;
+	}
+#endif
 	if (task == NULL) {
 		task = current_task();
 	}
 
-	/* Validate input arguments */
-	if (task == kernel_task || entitlement == NULL || value == NULL) {
+	proc_t p = (proc_t)get_bsdtask_info(task);
+
+	if (p == NULL) {
 		return false;
 	}
-	proc_t proc = (proc_t)get_bsdtask_info(task);
-
-	if (proc == NULL) {
+
+	struct cs_blob* csblob = csproc_get_blob(p);
+	if (csblob == NULL) {
 		return false;
 	}
 
-	kern_return_t ret = amfi->OSEntitlements.queryEntitlementStringWithProc(
-		proc,
-		entitlement,
-		value);
-
-	if (ret == KERN_SUCCESS) {
-		return true;
-	}
-
-	return false;
-}
-
-extern "C" OS_ALWAYS_INLINE boolean_t
-IOCurrentTaskHasEntitlement(const char *entitlement)
-{
-	return IOTaskHasEntitlement(NULL, entitlement);
-}
-
-/*
- * Reminder to reader: This only returns `true` if:
- *  - The entitlement is boolean-valued
- *  - The value is `true`
- * If you are looking to check whether an entitlement is present,
- * you likely want `IOVnodeIsEntitlementPresentWithAnyValue`
- * or `IOTaskHasEntitlementAsBooleanOrObject` (caveat emptor).
- */
-extern "C" boolean_t
-IOTaskHasEntitlement(task_t task, const char *entitlement)
-{
-	if (task == NULL) {
-		task = current_task();
-	}
-
-	/* Validate input arguments */
-	if (task == kernel_task || entitlement == NULL) {
+	void* osents = csblob_os_entitlements_get(csblob);
+	if (osents == NULL) {
 		return false;
 	}
-	proc_t proc = (proc_t)get_bsdtask_info(task);
-
-	if (proc == NULL) {
-		return false;
-	}
-
-	kern_return_t ret = amfi->OSEntitlements.queryEntitlementBooleanWithProc(
-		proc,
-		entitlement);
-
-	if (ret == KERN_SUCCESS) {
-		return true;
-	}
-
-	return false;
-}
-
-extern "C" boolean_t
-IOTaskGetIntegerEntitlement(task_t task, const char *entitlement, uint64_t *value)
-{
-	void *entitlement_object = NULL;
-
-	if (task == NULL) {
-		task = current_task();
-	}
-
-	/* Validate input arguments */
-	if (task == kernel_task || entitlement == NULL || value == NULL) {
-		return false;
-	}
-	proc_t proc = (proc_t)get_bsdtask_info(task);
-
-	if (proc == NULL) {
-		return false;
-	}
-
-	kern_return_t ret = amfi->OSEntitlements.copyEntitlementAsOSObjectWithProc(
-		proc,
-		entitlement,
-		&entitlement_object);
-
-	if (ret != KERN_SUCCESS) {
-		return false;
-	}
-	assert(entitlement_object != NULL);
-
-	OSObject *os_object = (OSObject*)entitlement_object;
-	OSNumber *os_number = OSDynamicCast(OSNumber, os_object);
-
-	boolean_t has_entitlement = os_number != NULL;
-	if (has_entitlement) {
-		*value = os_number->unsigned64BitValue();
-	}
-
-	/* Free the OSObject which was given to us */
-	OSSafeReleaseNULL(os_object);
-
-	return has_entitlement;
-}
-
-extern "C" OS_ALWAYS_INLINE char*
-IOCurrentTaskGetEntitlement(const char *entitlement)
-{
-	return IOTaskGetEntitlement(NULL, entitlement);
-}
-
-extern "C" char*
-IOTaskGetEntitlement(task_t task, const char *entitlement)
-{
-	void *entitlement_object = NULL;
-	char *return_value = NULL;
-
-	if (task == NULL) {
-		task = current_task();
-	}
-
-	/* Validate input arguments */
-	if (task == kernel_task || entitlement == NULL) {
-		return NULL;
-	}
-	proc_t proc = (proc_t)get_bsdtask_info(task);
-
-	if (proc == NULL) {
-		return NULL;
-	}
-
-	kern_return_t ret = amfi->OSEntitlements.copyEntitlementAsOSObjectWithProc(
-		proc,
-		entitlement,
-		&entitlement_object);
-
-	if (ret != KERN_SUCCESS) {
-		return NULL;
-	}
-	assert(entitlement_object != NULL);
-
-	OSObject *os_object = (OSObject*)entitlement_object;
-	OSString *os_string = OSDynamicCast(OSString, os_object);
-
-	/* Get a C string version of the OSString */
-	return_value = copyOSStringAsCString(os_string);
-
-	/* Free the OSObject which was given to us */
-	OSSafeReleaseNULL(os_object);
-
-	return return_value;
-}
-
-extern "C" boolean_t
-IOTaskHasEntitlementAsBooleanOrObject(task_t task, const char *entitlement)
-{
-	if (task == NULL) {
-		task = current_task();
-	}
-
-	/* Validate input arguments */
-	if (task == kernel_task || entitlement == NULL) {
-		return false;
-	}
-	proc_t proc = (proc_t)get_bsdtask_info(task);
-
-	if (proc == NULL) {
-		return false;
-	}
-
-	kern_return_t ret = amfi->OSEntitlements.queryEntitlementBooleanWithProc(
-		proc,
-		entitlement);
-	if (ret == KERN_SUCCESS) {
-		return true;
-	}
-
-	/* Check for the presence of an object */
-	void *entitlement_object = NULL;
-	ret = amfi->OSEntitlements.copyEntitlementAsOSObjectWithProc(
-		proc,
-		entitlement,
-		&entitlement_object);
-	if (ret != KERN_SUCCESS) {
-		return false;
-	}
-	assert(entitlement_object != NULL);
-
-	OSObject *os_object = (OSObject*)entitlement_object;
-
-	bool not_false_entitlement = (os_object != kOSBooleanFalse);
-
-	/* Free the OSObject which was given to us */
-	OSSafeReleaseNULL(os_object);
-
-	return not_false_entitlement;
+
+	if (!amfi) {
+		panic("CoreEntitlements: (IOTask): No AMFI\n");
+	}
+
+	return amfi->OSEntitlements_query(osents, (uint8_t*)csblob_get_cdhash(csblob), query, 2) == amfi->CoreEntitlements.kNoError;
 }
 
 extern "C" boolean_t
@@ -1780,83 +1632,6 @@
 	}
 	obj->release();
 	return obj != kOSBooleanFalse;
-}
-
-extern "C" boolean_t
-IOVnodeIsEntitlementPresentWithAnyValue(vnode_t vnode, int64_t off, const char *entitlement)
-{
-	OSObject * obj;
-	off_t offset = (off_t)off;
-
-	obj = IOUserClient::copyClientEntitlementVnode(vnode, offset, entitlement);
-	if (!obj) {
-		return false;
-	}
-	obj->release();
-	return true;
-}
-
-/*
- * Support querying an OSBoolean entitlement value,
- * while distinguishing between the following cases:
- *     - the entitlement does not exist.
- *     - the entitlement exists with a value of false.
- *     - the entitlement exists with a value of true.
- *
- * Return value:
- *     - false if the entitlement does not exist.
- *     - true if the entitlement exists.
- *
- * If the return value is true, the `value` argument will
- * hold the entitlement value, which has to be Boolean.
- */
-extern "C" boolean_t
-IOVnodeGetBooleanEntitlement(
-	vnode_t vnode,
-	int64_t off,
-	const char *entitlement,
-	bool *value)
-{
-	OSObject * obj;
-	off_t offset = (off_t)off;
-
-	obj = IOUserClient::copyClientEntitlementVnode(vnode, offset, entitlement);
-	if (!obj) {
-		return false;
-	}
-
-	if (obj == kOSBooleanTrue) {
-		*value = true;
-	} else if (obj == kOSBooleanFalse) {
-		*value = false;
-	} else {
-		panic("%s: entitlement is not OSBoolean", __func__);
-	}
-
-	obj->release();
-	return true;
-}
-
-extern boolean_t
-IOVnodeGetIntegerEntitlement(struct vnode *vnode, int64_t off, const char *entitlement, uint64_t *value)
-{
-	OSObject *obj;
-	boolean_t ret = false;
-	off_t offset = (off_t)off;
-
-	obj = IOUserClient::copyClientEntitlementVnode(vnode, offset, entitlement);
-	if (!obj) {
-		return ret;
-	}
-
-	OSNumber *num = OSDynamicCast(OSNumber, obj);
-	if (num) {
-		*value = num->unsigned64BitValue();
-		ret = true;
-	}
-
-	obj->release();
-	return ret;
 }
 
 extern "C" char *
@@ -1880,3 +1655,43 @@
 	}
 	return value;
 }
+
+extern "C"
+OS_ALWAYS_INLINE
+char *
+IOCurrentTaskGetEntitlement(const char * entitlement)
+{
+	return IOTaskGetEntitlement(current_task(), entitlement);
+}
+
+extern "C" char *
+IOTaskGetEntitlement(task_t task, const char * entitlement)
+{
+	OSObject * obj = NULL;
+	OSDictionary * entitlements = NULL;
+	OSString * str = NULL;
+	size_t len = 0;
+	char * value = NULL;
+
+	if (task == kernel_task || task == NULL || entitlement == NULL) {
+		goto finish;
+	}
+
+	entitlements = IOUserClient::copyClientEntitlements(task);
+	if (entitlements == NULL) {
+		goto finish;
+	}
+
+	obj = entitlements->getObject(entitlement);
+	str = OSDynamicCast(OSString, obj);
+	if (str != NULL) {
+		len = str->getLength() + 1;
+		value = (char *)kalloc_data(len, (zalloc_flags_t)(Z_ZERO | Z_WAITOK | Z_NOFAIL));
+		strlcpy(value, str->getCStringNoCopy(), len);
+	}
+
+finish:
+	OSSafeReleaseNULL(entitlements);
+
+	return value;
+}