Loading...
iokit/Kernel/IOUserClient.cpp xnu-12377.121.6 xnu-6153.141.1
--- xnu/xnu-12377.121.6/iokit/Kernel/IOUserClient.cpp
+++ xnu/xnu-6153.141.1/iokit/Kernel/IOUserClient.cpp
@@ -26,8 +26,8 @@
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
+
 #include <libkern/c++/OSKext.h>
-#include <libkern/c++/OSSharedPtr.h>
 #include <IOKit/IOKitServer.h>
 #include <IOKit/IOKitKeysPrivate.h>
 #include <IOKit/IOUserClient.h>
@@ -48,13 +48,9 @@
 #include <sys/proc.h>
 #include <sys/kauth.h>
 #include <sys/codesign.h>
-#include <sys/code_signing.h>
-#include <vm/vm_kern_xnu.h>
 
 #include <mach/sdt.h>
 #include <os/hash.h>
-
-#include <libkern/amfi/amfi.h>
 
 #if CONFIG_MACF
 
@@ -136,101 +132,76 @@
 
 extern "C" {
 #include <mach/mach_traps.h>
-#include <vm/vm_map_xnu.h>
+#include <vm/vm_map.h>
 } /* extern "C" */
 
 struct IOMachPortHashList;
 
+static_assert(IKOT_MAX_TYPE <= 255);
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
-class IOMachPort final : public OSObject
+class IOMachPort : public OSObject
 {
 	OSDeclareDefaultStructors(IOMachPort);
 public:
-	bool        hashed;
 	SLIST_ENTRY(IOMachPort) link;
 	ipc_port_t  port;
-	OSObject*   XNU_PTRAUTH_SIGNED_PTR("IOMachPort.object") object;
-
-	static IOMachPort* withObject(OSObject *obj);
-
-	static IOMachPortHashList* bucketForObject(OSObject *obj);
-
-	static LIBKERN_RETURNS_NOT_RETAINED IOMachPort* portForObjectInBucket(IOMachPortHashList *bucket, OSObject *obj, ipc_kobject_type_t type);
-
-	static IOMachPort *noMoreSenders( ipc_port_t port,
-	    ipc_kobject_type_t type, mach_port_mscount_t mscount );
+	OSObject*   object;
+	UInt32      mscount;
+	UInt8       holdDestroy;
+	UInt8       type;
+
+	static IOMachPort* withObjectAndType(OSObject *obj, ipc_kobject_type_t type);
+
+	static IOMachPortHashList* bucketForObject(OSObject *obj,
+	    ipc_kobject_type_t type);
+
+	static IOMachPort* portForObjectInBucket(IOMachPortHashList *bucket, OSObject *obj, ipc_kobject_type_t type);
+
+	static bool noMoreSendersForObject( OSObject * obj,
+	    ipc_kobject_type_t type, mach_port_mscount_t * mscount );
 	static void releasePortForObject( OSObject * obj,
 	    ipc_kobject_type_t type );
+	static void setHoldDestroy( OSObject * obj, ipc_kobject_type_t type );
 
 	static mach_port_name_t makeSendRightForTask( task_t task,
 	    io_object_t obj, ipc_kobject_type_t type );
 
 	virtual void free() APPLE_KEXT_OVERRIDE;
-
-	void
-	makePort(ipc_kobject_type_t type)
-	{
-		port = iokit_alloc_object_port(this, type);
-	}
-
-	void
-	adoptPort(IOMachPort *other, ipc_kobject_type_t type)
-	{
-		port = other->port;
-		ipc_kobject_enable(port, this, IKOT_IOKIT_CONNECT);
-		other->port = NULL;
-	}
-
-	void
-	disablePort(ipc_kobject_type_t type)
-	{
-		__assert_only ipc_kobject_t kobj;
-		kobj = ipc_kobject_disable(port, type);
-		assert(kobj == this);
-	}
-
-	template<typename T>
-	inline T *
-	getAs() const
-	{
-		return OSDynamicCast(T, object);
-	}
 };
 
 #define super OSObject
-OSDefineMetaClassAndStructorsWithZone(IOMachPort, OSObject, ZC_ZFREE_CLEARMEM)
+OSDefineMetaClassAndStructors(IOMachPort, OSObject)
 
 static IOLock *         gIOObjectPortLock;
 IOLock *                gIOUserServerLock;
 
-SECURITY_READ_ONLY_LATE(const struct io_filter_callbacks *) gIOUCFilterCallbacks;
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 SLIST_HEAD(IOMachPortHashList, IOMachPort);
 
-#if defined(XNU_TARGET_OS_OSX)
+#if CONFIG_EMBEDDED
+#define PORT_HASH_SIZE 256
+#else
 #define PORT_HASH_SIZE 4096
-#else /* defined(!XNU_TARGET_OS_OSX) */
-#define PORT_HASH_SIZE 256
-#endif /* !defined(!XNU_TARGET_OS_OSX) */
-
-IOMachPortHashList gIOMachPortHash[PORT_HASH_SIZE];
+#endif /* CONFIG_EMBEDDED */
+
+IOMachPortHashList ports[PORT_HASH_SIZE];
 
 void
 IOMachPortInitialize(void)
 {
 	for (size_t i = 0; i < PORT_HASH_SIZE; i++) {
-		SLIST_INIT(&gIOMachPortHash[i]);
+		SLIST_INIT(&ports[i]);
 	}
 }
 
 IOMachPortHashList*
-IOMachPort::bucketForObject(OSObject *obj)
-{
-	return &gIOMachPortHash[os_hash_kernel_pointer(obj) % PORT_HASH_SIZE];
+IOMachPort::bucketForObject(OSObject *obj, ipc_kobject_type_t type )
+{
+	return &ports[os_hash_kernel_pointer(obj) % PORT_HASH_SIZE];
 }
 
 IOMachPort*
@@ -239,7 +210,7 @@
 	IOMachPort *machPort;
 
 	SLIST_FOREACH(machPort, bucket, link) {
-		if (machPort->object == obj && iokit_port_type(machPort->port) == type) {
+		if (machPort->object == obj && machPort->type == type) {
 			return machPort;
 		}
 	}
@@ -247,150 +218,177 @@
 }
 
 IOMachPort*
-IOMachPort::withObject(OSObject *obj)
+IOMachPort::withObjectAndType(OSObject *obj, ipc_kobject_type_t type)
 {
 	IOMachPort *machPort = NULL;
 
 	machPort = new IOMachPort;
-	release_assert(machPort->init());
+	if (__improbable(machPort && !machPort->init())) {
+		return NULL;
+	}
+
 	machPort->object = obj;
+	machPort->type = (typeof(machPort->type))type;
+	machPort->port = iokit_alloc_object_port(obj, type);
 
 	obj->taggedRetain(OSTypeID(OSCollection));
+	machPort->mscount++;
 
 	return machPort;
 }
 
-IOMachPort *
-IOMachPort::noMoreSenders( ipc_port_t port, ipc_kobject_type_t type,
-    mach_port_mscount_t mscount )
-{
-	IOUserClient *uc = NULL;
-	IOMachPort   *machPort;
-	bool          destroyed;
+bool
+IOMachPort::noMoreSendersForObject( OSObject * obj,
+    ipc_kobject_type_t type, mach_port_mscount_t * mscount )
+{
+	IOMachPort *machPort = NULL;
+	IOUserClient *uc;
+	OSAction *action;
+	bool destroyed = true;
+
+	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj, type);
+
+	obj->retain();
 
 	lck_mtx_lock(gIOObjectPortLock);
 
-	iokit_lock_port(port);
-	machPort  = (IOMachPort *)ipc_kobject_get_locked(port, type);
-	destroyed = ipc_kobject_is_mscount_current_locked(port, mscount);
-	iokit_unlock_port(port);
+	machPort = IOMachPort::portForObjectInBucket(bucket, obj, type);
+
+	if (machPort) {
+		destroyed = (machPort->mscount <= *mscount);
+		if (!destroyed) {
+			*mscount = machPort->mscount;
+			lck_mtx_unlock(gIOObjectPortLock);
+		} else {
+			if ((IKOT_IOKIT_CONNECT == type) && (uc = OSDynamicCast(IOUserClient, obj))) {
+				uc->noMoreSenders();
+			}
+			SLIST_REMOVE(bucket, machPort, IOMachPort, link);
+
+			lck_mtx_unlock(gIOObjectPortLock);
+
+			machPort->release();
+			obj->taggedRelease(OSTypeID(OSCollection));
+		}
+	} else {
+		lck_mtx_unlock(gIOObjectPortLock);
+	}
+
+	if ((IKOT_UEXT_OBJECT == type) && (action = OSDynamicCast(OSAction, obj))) {
+		action->Aborted();
+	}
+
+	obj->release();
+
+	return destroyed;
+}
+
+void
+IOMachPort::releasePortForObject( OSObject * obj,
+    ipc_kobject_type_t type )
+{
+	IOMachPort *machPort;
+	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj, type);
+
+	assert(IKOT_IOKIT_CONNECT != type);
+
+	lck_mtx_lock(gIOObjectPortLock);
+
+	machPort = IOMachPort::portForObjectInBucket(bucket, obj, type);
+
+	if (machPort && !machPort->holdDestroy) {
+		obj->retain();
+		SLIST_REMOVE(bucket, machPort, IOMachPort, link);
+
+		lck_mtx_unlock(gIOObjectPortLock);
+
+		machPort->release();
+		obj->taggedRelease(OSTypeID(OSCollection));
+		obj->release();
+	} else {
+		lck_mtx_unlock(gIOObjectPortLock);
+	}
+}
+
+void
+IOMachPort::setHoldDestroy( OSObject * obj, ipc_kobject_type_t type )
+{
+	IOMachPort *        machPort;
+
+	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj, type);
+	lck_mtx_lock(gIOObjectPortLock);
+
+	machPort = IOMachPort::portForObjectInBucket(bucket, obj, type);
+
+	if (machPort) {
+		machPort->holdDestroy = true;
+	}
+
+	lck_mtx_unlock(gIOObjectPortLock);
+}
+
+void
+IOMachPortDestroyUserReferences(OSObject * obj, natural_t type)
+{
+	IOMachPort::releasePortForObject(obj, type);
+}
+
+void
+IOUserClient::destroyUserReferences( OSObject * obj )
+{
+	IOMachPort *machPort;
+
+	IOMachPort::releasePortForObject( obj, IKOT_IOKIT_OBJECT );
+
+	// panther, 3160200
+	// IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
+
+	obj->retain();
+	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj, IKOT_IOKIT_CONNECT);
+	IOMachPortHashList *mappingBucket = NULL;
+
+	lck_mtx_lock(gIOObjectPortLock);
+
+	IOUserClient * uc = OSDynamicCast(IOUserClient, obj);
+	if (uc && uc->mappings) {
+		mappingBucket = IOMachPort::bucketForObject(uc->mappings, IKOT_IOKIT_CONNECT);
+	}
+
+	machPort = IOMachPort::portForObjectInBucket(bucket, obj, IKOT_IOKIT_CONNECT);
 
 	if (machPort == NULL) {
 		lck_mtx_unlock(gIOObjectPortLock);
-		return NULL;
-	}
-
-	assert(machPort->port == port);
-
-	if (destroyed) {
-		if (machPort->hashed) {
-			IOMachPortHashList *bucket;
-
-			bucket = IOMachPort::bucketForObject(machPort->object);
-			machPort->hashed = false;
-			SLIST_REMOVE(bucket, machPort, IOMachPort, link);
-		}
-
-		machPort->disablePort(type);
-
-		if (IKOT_IOKIT_CONNECT == type) {
-			uc = machPort->getAs<IOUserClient>();
-		}
-	}
+		goto end;
+	}
+
+	SLIST_REMOVE(bucket, machPort, IOMachPort, link);
+	obj->taggedRelease(OSTypeID(OSCollection));
 
 	if (uc) {
 		uc->noMoreSenders();
-	}
-
-	lck_mtx_unlock(gIOObjectPortLock);
-
-	if (IKOT_UEXT_OBJECT == type) {
-		if (OSAction *action = machPort->getAs<OSAction>()) {
-			action->Aborted();
-		}
-
-		if (IOUserServer::shouldLeakObjects()) {
-			// Leak object
-			machPort->object->retain();
-		}
-	}
-
-	return destroyed ? machPort : NULL;
-}
-
-void
-IOMachPort::releasePortForObject( OSObject * obj, ipc_kobject_type_t type )
-{
-	bool destroyed = false;
-	IOMachPort *machPort;
-	IOService  *service;
-	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj);
-
-	assert(IKOT_IOKIT_CONNECT != type);
-
-	lck_mtx_lock(gIOObjectPortLock);
-
-	machPort = IOMachPort::portForObjectInBucket(bucket, obj, type);
-
-	if (machPort
-	    && ((type != IKOT_IOKIT_OBJECT)
-	    || !(service = OSDynamicCast(IOService, obj))
-	    || !service->machPortHoldDestroy())) {
-		machPort->hashed = false;
-		SLIST_REMOVE(bucket, machPort, IOMachPort, link);
-		machPort->disablePort(type);
-		destroyed = true;
-	}
-
-	lck_mtx_unlock(gIOObjectPortLock);
-
-	if (destroyed) {
+		if (uc->mappings) {
+			uc->mappings->taggedRetain(OSTypeID(OSCollection));
+			machPort->object = uc->mappings;
+			SLIST_INSERT_HEAD(mappingBucket, machPort, link);
+			iokit_switch_object_port(machPort->port, uc->mappings, IKOT_IOKIT_CONNECT);
+
+			lck_mtx_unlock(gIOObjectPortLock);
+
+			uc->mappings->release();
+			uc->mappings = NULL;
+		} else {
+			lck_mtx_unlock(gIOObjectPortLock);
+			machPort->release();
+		}
+	} else {
+		lck_mtx_unlock(gIOObjectPortLock);
 		machPort->release();
 	}
-}
-
-void
-IOUserClient::destroyUserReferences( OSObject * obj )
-{
-	IOMachPort   *machPort = NULL;
-	OSObject     *mappings = NULL;
-
-	IOMachPort::releasePortForObject( obj, IKOT_IOKIT_OBJECT );
-
-	IOUserClient * uc = OSDynamicCast(IOUserClient, obj);
-	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj);
-
-	lck_mtx_lock(gIOObjectPortLock);
-
-	machPort = IOMachPort::portForObjectInBucket(bucket, obj, IKOT_IOKIT_CONNECT);
-
-	if (machPort == NULL) {
-		lck_mtx_unlock(gIOObjectPortLock);
-		return;
-	}
-
-	machPort->hashed = false;
-	SLIST_REMOVE(bucket, machPort, IOMachPort, link);
-	machPort->disablePort(IKOT_IOKIT_CONNECT);
-
-	if (uc) {
-		mappings = uc->mappings;
-		uc->mappings = NULL;
-
-		uc->noMoreSenders();
-
-		if (mappings) {
-			IOMachPort *newPort;
-
-			newPort = IOMachPort::withObject(mappings);
-			newPort->adoptPort(machPort, IKOT_IOKIT_CONNECT);
-		}
-	}
-
-	lck_mtx_unlock(gIOObjectPortLock);
-
-	OSSafeReleaseNULL(mappings);
-	machPort->release();
+
+
+end:
+
+	obj->release();
 }
 
 mach_port_name_t
@@ -404,30 +402,47 @@
 IOMachPort::free( void )
 {
 	if (port) {
-		iokit_destroy_object_port(port, iokit_port_type(port));
-	}
-	object->taggedRelease(OSTypeID(OSCollection));
+		iokit_destroy_object_port( port );
+	}
 	super::free();
 }
 
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-static bool
-IOTaskRegistryCompatibility(task_t task)
-{
-	return false;
-}
-
-static void
-IOTaskRegistryCompatibilityMatching(task_t task, OSDictionary * matching)
-{
-	matching->setObject(gIOServiceNotificationUserKey, kOSBooleanTrue);
-	if (!IOTaskRegistryCompatibility(task)) {
-		return;
-	}
-	matching->setObject(gIOCompatibilityMatchKey, kOSBooleanTrue);
-}
+class IOUserIterator : public OSIterator
+{
+	OSDeclareDefaultStructors(IOUserIterator);
+public:
+	OSObject    *       userIteratorObject;
+	IOLock      *       lock;
+
+	static IOUserIterator * withIterator(LIBKERN_CONSUMED OSIterator * iter);
+	virtual bool init( void ) APPLE_KEXT_OVERRIDE;
+	virtual void free() APPLE_KEXT_OVERRIDE;
+
+	virtual void reset() APPLE_KEXT_OVERRIDE;
+	virtual bool isValid() APPLE_KEXT_OVERRIDE;
+	virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
+	virtual OSObject * copyNextObject();
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+class IOUserNotification : public IOUserIterator
+{
+	OSDeclareDefaultStructors(IOUserNotification);
+
+#define holdNotify      userIteratorObject
+
+public:
+
+	virtual void free() APPLE_KEXT_OVERRIDE;
+
+	virtual void setNotification( IONotifier * obj );
+
+	virtual void reset() APPLE_KEXT_OVERRIDE;
+	virtual bool isValid() APPLE_KEXT_OVERRIDE;
+};
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -448,7 +463,6 @@
 		me = NULL;
 	}
 	if (!me) {
-		iter->release();
 		return me;
 	}
 	me->userIteratorObject = iter;
@@ -463,7 +477,11 @@
 		return false;
 	}
 
-	IOLockInlineInit(&lock);
+	lock = IOLockAlloc();
+	if (!lock) {
+		return false;
+	}
+
 	return true;
 }
 
@@ -473,17 +491,19 @@
 	if (userIteratorObject) {
 		userIteratorObject->release();
 	}
-	IOLockInlineDestroy(&lock);
+	if (lock) {
+		IOLockFree(lock);
+	}
 	OSObject::free();
 }
 
 void
 IOUserIterator::reset()
 {
-	IOLockLock(&lock);
+	IOLockLock(lock);
 	assert(OSDynamicCast(OSIterator, userIteratorObject));
 	((OSIterator *)userIteratorObject)->reset();
-	IOLockUnlock(&lock);
+	IOLockUnlock(lock);
 }
 
 bool
@@ -491,10 +511,10 @@
 {
 	bool ret;
 
-	IOLockLock(&lock);
+	IOLockLock(lock);
 	assert(OSDynamicCast(OSIterator, userIteratorObject));
 	ret = ((OSIterator *)userIteratorObject)->isValid();
-	IOLockUnlock(&lock);
+	IOLockUnlock(lock);
 
 	return ret;
 }
@@ -511,14 +531,14 @@
 {
 	OSObject * ret = NULL;
 
-	IOLockLock(&lock);
+	IOLockLock(lock);
 	if (userIteratorObject) {
 		ret = ((OSIterator *)userIteratorObject)->getNextObject();
 		if (ret) {
 			ret->retain();
 		}
 	}
-	IOLockUnlock(&lock);
+	IOLockUnlock(lock);
 
 	return ret;
 }
@@ -534,44 +554,37 @@
 	IOUserNotification * __unused noti;
 	_IOServiceNotifier * __unused serviceNoti;
 	OSSerialize        * __unused s;
-	OSDictionary       * __unused matching = NULL;
 
 	if ((regEntry = OSDynamicCast(IORegistryEntry, obj))) {
 		snprintf(desc, KOBJECT_DESCRIPTION_LENGTH, "%s(0x%qx)", obj->getMetaClass()->getClassName(), regEntry->getRegistryEntryID());
 #if DEVELOPMENT || DEBUG
-	} else if ((noti = OSDynamicCast(IOUserNotification, obj))) {
-		// serviceNoti->matching may become NULL if the port gets a no-senders notification, so we have to lock gIOObjectPortLock
-		IOLockLock(gIOObjectPortLock);
-		serviceNoti = OSDynamicCast(_IOServiceNotifier, noti->userIteratorObject);
-		if (serviceNoti && (matching = serviceNoti->matching)) {
-			matching->retain();
-		}
-		IOLockUnlock(gIOObjectPortLock);
-
-		if (matching) {
-			s = OSSerialize::withCapacity((unsigned int) page_size);
-			if (s && matching->serialize(s)) {
-				snprintf(desc, KOBJECT_DESCRIPTION_LENGTH, "%s(%s)", obj->getMetaClass()->getClassName(), s->text());
-			}
-			OSSafeReleaseNULL(s);
-			OSSafeReleaseNULL(matching);
-		}
+	} else if ((noti = OSDynamicCast(IOUserNotification, obj))
+	    && ((serviceNoti = OSDynamicCast(_IOServiceNotifier, noti->holdNotify)))) {
+		s = OSSerialize::withCapacity(page_size);
+		if (s && serviceNoti->matching->serialize(s)) {
+			snprintf(desc, KOBJECT_DESCRIPTION_LENGTH, "%s(%s)", obj->getMetaClass()->getClassName(), s->text());
+		}
+		OSSafeReleaseNULL(s);
 #endif /* DEVELOPMENT || DEBUG */
 	} else {
 		snprintf(desc, KOBJECT_DESCRIPTION_LENGTH, "%s", obj->getMetaClass()->getClassName());
 	}
 }
 
-// FIXME: Implementation of these functions are hidden from the static analyzer.
-// As for now, the analyzer doesn't consistently support wrapper functions
-// for retain and release.
-#ifndef __clang_analyzer__
 void
-iokit_add_reference( io_object_t obj )
-{
+iokit_add_reference( io_object_t obj, natural_t type )
+{
+	IOUserClient * uc;
+
 	if (!obj) {
 		return;
 	}
+
+	if ((IKOT_IOKIT_CONNECT == type)
+	    && (uc = OSDynamicCast(IOUserClient, obj))) {
+		OSIncrementAtomic(&uc->__ipc);
+	}
+
 	obj->retain();
 }
 
@@ -582,92 +595,31 @@
 		obj->release();
 	}
 }
-#endif // __clang_analyzer__
 
 void
-iokit_remove_connect_reference(LIBKERN_CONSUMED io_object_t obj )
-{
+iokit_remove_connect_reference( io_object_t obj )
+{
+	IOUserClient * uc;
+	bool           finalize = false;
+
 	if (!obj) {
 		return;
 	}
+
+	if ((uc = OSDynamicCast(IOUserClient, obj))) {
+		if (1 == OSDecrementAtomic(&uc->__ipc) && uc->isInactive()) {
+			IOLockLock(gIOObjectPortLock);
+			if ((finalize = uc->__ipcFinal)) {
+				uc->__ipcFinal = false;
+			}
+			IOLockUnlock(gIOObjectPortLock);
+		}
+		if (finalize) {
+			uc->scheduleFinalize(true);
+		}
+	}
+
 	obj->release();
-}
-
-enum {
-	kIPCLockNone  = 0,
-	kIPCLockRead  = 1,
-	kIPCLockWrite = 2
-};
-
-void
-IOUserClient::ipcEnter(int locking)
-{
-	switch (locking) {
-	case kIPCLockWrite:
-		IORWLockWrite(&lock);
-		break;
-	case kIPCLockRead:
-		IORWLockRead(&lock);
-		break;
-	case kIPCLockNone:
-		break;
-	default:
-		panic("ipcEnter");
-	}
-
-	OSIncrementAtomic(&__ipc);
-}
-
-void
-IOUserClient::ipcExit(int locking)
-{
-	bool finalize = false;
-
-	assert(__ipc);
-	if (1 == OSDecrementAtomic(&__ipc) && isInactive()) {
-		IOLockLock(gIOObjectPortLock);
-		if ((finalize = __ipcFinal)) {
-			__ipcFinal = false;
-		}
-		IOLockUnlock(gIOObjectPortLock);
-		if (finalize) {
-			scheduleFinalize(true);
-		}
-	}
-	switch (locking) {
-	case kIPCLockWrite:
-	case kIPCLockRead:
-		IORWLockUnlock(&lock);
-		break;
-	case kIPCLockNone:
-		break;
-	default:
-		panic("ipcExit");
-	}
-}
-
-void
-iokit_kobject_retain(io_kobject_t machPort)
-{
-	assert(OSDynamicCast(IOMachPort, machPort));
-	machPort->retain();
-}
-
-io_object_t
-iokit_copy_object_for_consumed_kobject(LIBKERN_CONSUMED io_kobject_t machPort)
-{
-	io_object_t result;
-
-	assert(OSDynamicCast(IOMachPort, machPort));
-
-	/*
-	 * IOMachPort::object is never nil-ed, so this just borrows its port
-	 * reference to make new rights.
-	 */
-	result = machPort->object;
-	iokit_add_reference(result);
-	machPort->release();
-	return result;
 }
 
 bool
@@ -687,110 +639,64 @@
 }
 
 ipc_port_t
-iokit_port_make_send_for_object( io_object_t obj, ipc_kobject_type_t type )
+iokit_port_for_object( io_object_t obj, ipc_kobject_type_t type )
 {
 	IOMachPort *machPort = NULL;
-	ipc_port_t  port = NULL;
-
-	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj);
+	ipc_port_t   port = NULL;
+
+	IOMachPortHashList *bucket = IOMachPort::bucketForObject(obj, type);
 
 	lck_mtx_lock(gIOObjectPortLock);
 
 	machPort = IOMachPort::portForObjectInBucket(bucket, obj, type);
 
 	if (__improbable(machPort == NULL)) {
-		machPort = IOMachPort::withObject(obj);
-		machPort->makePort(type);
-		machPort->hashed = true;
+		machPort = IOMachPort::withObjectAndType(obj, type);
+		if (__improbable(machPort == NULL)) {
+			goto end;
+		}
 		SLIST_INSERT_HEAD(bucket, machPort, link);
-	}
-
-	port = ipc_kobject_make_send( machPort->port, machPort, type );
-
+	} else {
+		machPort->mscount++;
+	}
+
+	iokit_retain_port(machPort->port);
+	port = machPort->port;
+
+end:
 	lck_mtx_unlock(gIOObjectPortLock);
 
 	return port;
 }
 
-/*
- * Handle the No-More_Senders notification generated from a device port destroy.
- * Since there are no longer any tasks which hold a send right to this device
- * port a NMS notification has been generated.
- */
-
-void
-iokit_ident_no_senders( ipc_port_t port, mach_port_mscount_t mscount )
-{
-	IOMachPort *machPort;
-
-	machPort = IOMachPort::noMoreSenders(port, IKOT_IOKIT_IDENT, mscount);
-
-	if (machPort) {
-		if (IOUserServerCheckInToken *token =
-		    machPort->getAs<IOUserServerCheckInToken>()) {
-			token->cancel();
-		}
-		machPort->release();
-	}
-}
-
-void
-iokit_object_no_senders( ipc_port_t port, mach_port_mscount_t mscount )
-{
-	IOMachPort *machPort;
-
-	machPort = IOMachPort::noMoreSenders(port, IKOT_IOKIT_OBJECT, mscount);
-
-	if (machPort) {
-		if (IOMemoryMap *map = machPort->getAs<IOMemoryMap>()) {
+kern_return_t
+iokit_client_died( io_object_t obj, ipc_port_t /* port */,
+    ipc_kobject_type_t type, mach_port_mscount_t * mscount )
+{
+	IOUserClient *      client;
+	IOMemoryMap *       map;
+	IOUserNotification * notify;
+
+	if (!IOMachPort::noMoreSendersForObject( obj, type, mscount )) {
+		return kIOReturnNotReady;
+	}
+
+	if (IKOT_IOKIT_CONNECT == type) {
+		if ((client = OSDynamicCast( IOUserClient, obj ))) {
+			IOStatisticsClientCall();
+			IOLockLock(client->lock);
+			client->clientDied();
+			IOLockUnlock(client->lock);
+		}
+	} else if (IKOT_IOKIT_OBJECT == type) {
+		if ((map = OSDynamicCast( IOMemoryMap, obj ))) {
 			map->taskDied();
-		} else if (IOUserNotification *notify =
-		    machPort->getAs<IOUserNotification>()) {
+		} else if ((notify = OSDynamicCast( IOUserNotification, obj ))) {
 			notify->setNotification( NULL );
 		}
-		machPort->release();
-	}
-}
-
-void
-iokit_connect_no_senders( ipc_port_t port, mach_port_mscount_t mscount )
-{
-	IOMachPort *machPort;
-
-	machPort = IOMachPort::noMoreSenders(port, IKOT_IOKIT_CONNECT, mscount);
-
-	if (machPort) {
-		if (IOUserClient *client = machPort->getAs<IOUserClient>()) {
-			IOStatisticsClientCall();
-			IORWLockWrite(&client->lock);
-			client->clientDied();
-			IORWLockUnlock(&client->lock);
-		}
-		machPort->release();
-	}
-}
-
-void
-iokit_uext_no_senders( ipc_port_t port, mach_port_mscount_t mscount )
-{
-	IOMachPort *machPort;
-
-	machPort = IOMachPort::noMoreSenders(port, IKOT_UEXT_OBJECT, mscount);
-
-	if (machPort) {
-		if (IOUserClient *uc = machPort->getAs<IOUserUserClient>()) {
-			IOService *provider = NULL;
-			uc->lockForArbitration();
-			provider = uc->getProvider();
-			if (provider) {
-				provider->retain();
-			}
-			uc->unlockForArbitration();
-			uc->setTerminateDefer(provider, false);
-			OSSafeReleaseNULL(provider);
-		}
-		machPort->release();
-	}
+	}
+
+	return kIOReturnSuccess;
 }
 };      /* extern "C" */
 
@@ -800,19 +706,15 @@
 {
 	OSDeclareDefaultStructors(IOServiceUserNotification);
 
-	struct PingMsgKdata {
+	struct PingMsg {
 		mach_msg_header_t               msgHdr;
-	};
-	struct PingMsgUdata {
 		OSNotificationHeader64          notifyHeader;
 	};
 
 	enum { kMaxOutstanding = 1024 };
 
-	ipc_port_t          remotePort;
-	void                *msgReference;
-	mach_msg_size_t     msgReferenceSize;
-	natural_t           msgType;
+	PingMsg     *       pingMsg;
+	vm_size_t           msgSize;
 	OSArray     *       newSet;
 	bool                armed;
 	bool                ipcLogged;
@@ -837,20 +739,15 @@
 {
 	OSDeclareDefaultStructors(IOServiceMessageUserNotification);
 
-	struct PingMsgKdata {
+	struct PingMsg {
 		mach_msg_header_t               msgHdr;
 		mach_msg_body_t                 msgBody;
 		mach_msg_port_descriptor_t      ports[1];
-	};
-	struct PingMsgUdata {
 		OSNotificationHeader64          notifyHeader __attribute__ ((packed));
 	};
 
-	ipc_port_t          remotePort;
-	void                *msgReference;
-	mach_msg_size_t     msgReferenceSize;
-	mach_msg_size_t     msgExtraSize;
-	natural_t           msgType;
+	PingMsg *           pingMsg;
+	vm_size_t           msgSize;
 	uint8_t             clientIs64;
 	int                 owningPID;
 	bool                ipcLogged;
@@ -859,6 +756,7 @@
 
 	virtual bool init( mach_port_t port, natural_t type,
 	    void * reference, vm_size_t referenceSize,
+	    vm_size_t extraSize,
 	    bool clientIs64 );
 
 	virtual void free() APPLE_KEXT_OVERRIDE;
@@ -887,13 +785,12 @@
 void
 IOUserNotification::free( void )
 {
-#if DEVELOPMENT || DEBUG
-	IOLockLock( gIOObjectPortLock);
-
-	assert(userIteratorObject == NULL);
-
-	IOLockUnlock( gIOObjectPortLock);
-#endif /* DEVELOPMENT || DEBUG */
+	if (holdNotify) {
+		assert(OSDynamicCast(IONotifier, holdNotify));
+		((IONotifier *)holdNotify)->remove();
+		holdNotify = NULL;
+	}
+	// can't be in handler now
 
 	super::free();
 }
@@ -904,36 +801,17 @@
 {
 	OSObject * previousNotify;
 
-	/*
-	 * We must retain this object here before proceeding.
-	 * Two threads may race in setNotification(). If one thread sets a new notifier while the
-	 * other thread sets the notifier to NULL, it is possible for the second thread to call release()
-	 * before the first thread calls retain(). Without the retain here, this thread interleaving
-	 * would cause the object to get released and freed before it is retained by the first thread,
-	 * which is a UaF.
-	 */
-	retain();
-
 	IOLockLock( gIOObjectPortLock);
 
-	previousNotify = userIteratorObject;
-	userIteratorObject = notify;
+	previousNotify = holdNotify;
+	holdNotify = notify;
 
 	IOLockUnlock( gIOObjectPortLock);
 
 	if (previousNotify) {
 		assert(OSDynamicCast(IONotifier, previousNotify));
 		((IONotifier *)previousNotify)->remove();
-
-		if (notify == NULL) {
-			release();
-		}
-	} else if (notify) {
-		// new IONotifier, retain the object. release() will happen in setNotification(NULL)
-		retain();
-	}
-
-	release(); // paired with retain() at beginning of this method
+	}
 }
 
 void
@@ -974,15 +852,24 @@
 		return false;
 	}
 
-	msgReferenceSize = mach_round_msg((mach_msg_size_t)referenceSize);
-	msgReference = IOMallocZeroData(msgReferenceSize);
-	if (!msgReference) {
+	msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize;
+	pingMsg = (PingMsg *) IOMalloc( msgSize);
+	if (!pingMsg) {
 		return false;
 	}
 
-	remotePort = port;
-	msgType = type;
-	bcopy( reference, msgReference, referenceSize );
+	bzero( pingMsg, msgSize);
+
+	pingMsg->msgHdr.msgh_remote_port    = port;
+	pingMsg->msgHdr.msgh_bits           = MACH_MSGH_BITS(
+		MACH_MSG_TYPE_COPY_SEND /*remote*/,
+		MACH_MSG_TYPE_MAKE_SEND /*local*/);
+	pingMsg->msgHdr.msgh_size           = msgSize;
+	pingMsg->msgHdr.msgh_id             = kOSNotificationMessageID;
+
+	pingMsg->notifyHeader.size = 0;
+	pingMsg->notifyHeader.type = type;
+	bcopy( reference, pingMsg->notifyHeader.reference, referenceSize );
 
 	return true;
 }
@@ -990,32 +877,41 @@
 void
 IOServiceUserNotification::invalidatePort(void)
 {
-	remotePort = MACH_PORT_NULL;
+	if (pingMsg) {
+		pingMsg->msgHdr.msgh_remote_port = MACH_PORT_NULL;
+	}
 }
 
 void
 IOServiceUserNotification::free( void )
 {
-	if (remotePort) {
-		iokit_release_port_send(remotePort);
-	}
-	IOFreeData(msgReference, msgReferenceSize);
-	OSSafeReleaseNULL(newSet);
+	PingMsg   * _pingMsg;
+	vm_size_t   _msgSize;
+	OSArray   * _newSet;
+
+	_pingMsg   = pingMsg;
+	_msgSize   = msgSize;
+	_newSet    = newSet;
 
 	super::free();
+
+	if (_pingMsg && _msgSize) {
+		if (_pingMsg->msgHdr.msgh_remote_port) {
+			iokit_release_port_send(_pingMsg->msgHdr.msgh_remote_port);
+		}
+		IOFree(_pingMsg, _msgSize);
+	}
+
+	if (_newSet) {
+		_newSet->release();
+	}
 }
 
 bool
 IOServiceUserNotification::_handler( void * target,
     void * ref, IOService * newService, IONotifier * notifier )
 {
-	IOServiceUserNotification * targetObj = (IOServiceUserNotification *)target;
-	bool ret;
-
-	targetObj->retain();
-	ret = targetObj->handler( ref, newService );
-	targetObj->release();
-	return ret;
+	return ((IOServiceUserNotification *) target)->handler( ref, newService );
 }
 
 bool
@@ -1026,9 +922,8 @@
 	kern_return_t       kr;
 	ipc_port_t          port = NULL;
 	bool                sendPing = false;
-	mach_msg_size_t     msgSize, payloadSize;
-
-	IOTakeLock( &lock );
+
+	IOTakeLock( lock );
 
 	count = newSet->getCount();
 	if (count < kMaxOutstanding) {
@@ -1038,51 +933,30 @@
 		}
 	}
 
-	IOUnlock( &lock );
-
-	if (kIOServiceTerminatedNotificationType == msgType) {
-		lck_mtx_lock(gIOObjectPortLock);
-		newService->setMachPortHoldDestroy(true);
-		lck_mtx_unlock(gIOObjectPortLock);
+	IOUnlock( lock );
+
+	if (kIOServiceTerminatedNotificationType == pingMsg->notifyHeader.type) {
+		IOMachPort::setHoldDestroy( newService, IKOT_IOKIT_OBJECT );
 	}
 
 	if (sendPing) {
-		/*
-		 * This right will be consumed when the message we form below
-		 * is sent by kernel_mach_msg_send_with_builder_internal(),
-		 * because we make the disposition for the right move-send.
-		 */
-		port = iokit_port_make_send_for_object( this, IKOT_IOKIT_OBJECT );
-
-		payloadSize = sizeof(PingMsgUdata) - sizeof(OSAsyncReference64) + msgReferenceSize;
-		msgSize = (mach_msg_size_t)(sizeof(PingMsgKdata) + payloadSize);
-
-		kr = kernel_mach_msg_send_with_builder_internal(0, payloadSize,
-		    MACH_SEND_KERNEL_IMPORTANCE, MACH_MSG_TIMEOUT_NONE, NULL,
-		    ^(mach_msg_header_t *hdr, __assert_only mach_msg_descriptor_t *descs, void *payload){
-			PingMsgUdata *udata = (PingMsgUdata *)payload;
-
-			hdr->msgh_remote_port    = remotePort;
-			hdr->msgh_local_port     = port;
-			hdr->msgh_bits           = MACH_MSGH_BITS(
-				MACH_MSG_TYPE_COPY_SEND /*remote*/,
-				MACH_MSG_TYPE_MOVE_SEND /*local*/);
-			hdr->msgh_size           = msgSize;
-			hdr->msgh_id             = kOSNotificationMessageID;
-
-			assert(descs == NULL);
-			/* End of kernel processed data */
-
-			udata->notifyHeader.size          = 0;
-			udata->notifyHeader.type          = msgType;
-
-			assert((char *)udata->notifyHeader.reference + msgReferenceSize <= (char *)payload + payloadSize);
-			bcopy( msgReference, udata->notifyHeader.reference, msgReferenceSize );
-		});
+		if ((port = iokit_port_for_object( this, IKOT_IOKIT_OBJECT ))) {
+			pingMsg->msgHdr.msgh_local_port = port;
+		} else {
+			pingMsg->msgHdr.msgh_local_port = NULL;
+		}
+
+		kr = mach_msg_send_from_kernel_with_options( &pingMsg->msgHdr,
+		    pingMsg->msgHdr.msgh_size,
+		    (MACH_SEND_MSG | MACH_SEND_ALWAYS | MACH_SEND_IMPORTANCE),
+		    0);
+		if (port) {
+			iokit_release_port( port );
+		}
 
 		if ((KERN_SUCCESS != kr) && !ipcLogged) {
 			ipcLogged = true;
-			IOLog("%s: kernel_mach_msg_send (0x%x)\n", __PRETTY_FUNCTION__, kr );
+			IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__, kr );
 		}
 	}
 
@@ -1101,7 +975,7 @@
 	unsigned int        count;
 	OSObject *          result;
 
-	IOLockLock(&lock);
+	IOLockLock(lock);
 
 	count = newSet->getCount();
 	if (count) {
@@ -1113,7 +987,7 @@
 		armed = true;
 	}
 
-	IOLockUnlock(&lock);
+	IOLockUnlock(lock);
 
 	return result;
 }
@@ -1126,7 +1000,8 @@
 
 bool
 IOServiceMessageUserNotification::init( mach_port_t port, natural_t type,
-    void * reference, vm_size_t referenceSize, bool client64 )
+    void * reference, vm_size_t referenceSize, vm_size_t extraSize,
+    bool client64 )
 {
 	if (!super::init()) {
 		return false;
@@ -1140,15 +1015,32 @@
 
 	owningPID = proc_selfpid();
 
-	msgReferenceSize = mach_round_msg((mach_msg_size_t)referenceSize);
-	msgReference = IOMallocZeroData(msgReferenceSize);
-	if (!msgReference) {
+	extraSize += sizeof(IOServiceInterestContent64);
+	msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize;
+	pingMsg = (PingMsg *) IOMalloc( msgSize);
+	if (!pingMsg) {
 		return false;
 	}
 
-	remotePort = port;
-	msgType = type;
-	bcopy( reference, msgReference, referenceSize );
+	bzero( pingMsg, msgSize);
+
+	pingMsg->msgHdr.msgh_remote_port    = port;
+	pingMsg->msgHdr.msgh_bits           = MACH_MSGH_BITS_COMPLEX
+	    |  MACH_MSGH_BITS(
+		MACH_MSG_TYPE_COPY_SEND /*remote*/,
+		MACH_MSG_TYPE_MAKE_SEND /*local*/);
+	pingMsg->msgHdr.msgh_size           = msgSize;
+	pingMsg->msgHdr.msgh_id             = kOSNotificationMessageID;
+
+	pingMsg->msgBody.msgh_descriptor_count = 1;
+
+	pingMsg->ports[0].name              = NULL;
+	pingMsg->ports[0].disposition       = MACH_MSG_TYPE_MAKE_SEND;
+	pingMsg->ports[0].type              = MACH_MSG_PORT_DESCRIPTOR;
+
+	pingMsg->notifyHeader.size          = extraSize;
+	pingMsg->notifyHeader.type          = type;
+	bcopy( reference, pingMsg->notifyHeader.reference, referenceSize );
 
 	return true;
 }
@@ -1156,18 +1048,28 @@
 void
 IOServiceMessageUserNotification::invalidatePort(void)
 {
-	remotePort = MACH_PORT_NULL;
+	if (pingMsg) {
+		pingMsg->msgHdr.msgh_remote_port = MACH_PORT_NULL;
+	}
 }
 
 void
 IOServiceMessageUserNotification::free( void )
 {
-	if (remotePort) {
-		iokit_release_port_send(remotePort);
-	}
-	IOFreeData(msgReference, msgReferenceSize);
+	PingMsg *   _pingMsg;
+	vm_size_t   _msgSize;
+
+	_pingMsg   = pingMsg;
+	_msgSize   = msgSize;
 
 	super::free();
+
+	if (_pingMsg && _msgSize) {
+		if (_pingMsg->msgHdr.msgh_remote_port) {
+			iokit_release_port_send(_pingMsg->msgHdr.msgh_remote_port);
+		}
+		IOFree( _pingMsg, _msgSize);
+	}
 }
 
 IOReturn
@@ -1175,14 +1077,8 @@
     UInt32 messageType, IOService * provider,
     void * argument, vm_size_t argSize )
 {
-	IOServiceMessageUserNotification * targetObj = (IOServiceMessageUserNotification *)target;
-	IOReturn ret;
-
-	targetObj->retain();
-	ret = targetObj->handler(
+	return ((IOServiceMessageUserNotification *) target)->handler(
 		ref, messageType, provider, argument, argSize);
-	targetObj->release();
-	return ret;
 }
 
 IOReturn
@@ -1190,10 +1086,15 @@
     UInt32 messageType, IOService * provider,
     void * messageArgument, vm_size_t callerArgSize )
 {
+	enum                         { kLocalMsgSize = 0x100 };
+	uint64_t                     stackMsg[kLocalMsgSize / sizeof(uint64_t)];
+	void *                       allocMsg;
 	kern_return_t                kr;
 	vm_size_t                    argSize;
-	mach_msg_size_t              thisMsgSize;
+	vm_size_t                    thisMsgSize;
 	ipc_port_t                   thisPort, providerPort;
+	struct PingMsg *             thisMsg;
+	IOServiceInterestContent64 * data;
 
 	if (kIOMessageCopyClientID == messageType) {
 		*((void **) messageArgument) = OSNumber::withNumber(owningPID, 32);
@@ -1202,7 +1103,7 @@
 
 	if (callerArgSize == 0) {
 		if (clientIs64) {
-			argSize = sizeof(io_user_reference_t);
+			argSize = sizeof(data->messageArgument[0]);
 		} else {
 			argSize = sizeof(uint32_t);
 		}
@@ -1214,81 +1115,70 @@
 	}
 
 	// adjust message size for ipc restrictions
-	natural_t type = msgType;
+	natural_t type;
+	type = pingMsg->notifyHeader.type;
 	type &= ~(kIOKitNoticationMsgSizeMask << kIOKitNoticationTypeSizeAdjShift);
 	type |= ((argSize & kIOKitNoticationMsgSizeMask) << kIOKitNoticationTypeSizeAdjShift);
 	argSize = (argSize + kIOKitNoticationMsgSizeMask) & ~kIOKitNoticationMsgSizeMask;
 
-	mach_msg_size_t extraSize = kIOUserNotifyMaxMessageSize + sizeof(IOServiceInterestContent64);
-	mach_msg_size_t msgSize = (mach_msg_size_t) (sizeof(PingMsgKdata) +
-	    sizeof(PingMsgUdata) - sizeof(OSAsyncReference64) + msgReferenceSize);
-
-	if (os_add3_overflow(msgSize, offsetof(IOServiceInterestContent64, messageArgument), argSize, &thisMsgSize)) {
-		return kIOReturnBadArgument;
-	}
-	mach_msg_size_t payloadSize = thisMsgSize - sizeof(PingMsgKdata);
-
-	/*
-	 * These rights will be consumed when the message we form below
-	 * is sent by kernel_mach_msg_send_with_builder_internal(),
-	 * because we make the disposition for the rights move-send.
-	 */
-	providerPort = iokit_port_make_send_for_object( provider, IKOT_IOKIT_OBJECT );
-	thisPort = iokit_port_make_send_for_object( this, IKOT_IOKIT_OBJECT );
-
-	kr = kernel_mach_msg_send_with_builder_internal(1, payloadSize,
-	    MACH_SEND_KERNEL_IMPORTANCE, MACH_MSG_TIMEOUT_NONE, NULL,
-	    ^(mach_msg_header_t *hdr, mach_msg_descriptor_t *descs, void *payload){
-		mach_msg_port_descriptor_t *port_desc = (mach_msg_port_descriptor_t *)descs;
-		PingMsgUdata *udata = (PingMsgUdata *)payload;
-		IOServiceInterestContent64 * data;
-		mach_msg_size_t dataOffset;
-
-		hdr->msgh_remote_port    = remotePort;
-		hdr->msgh_local_port     = thisPort;
-		hdr->msgh_bits           = MACH_MSGH_BITS_SET(
-			MACH_MSG_TYPE_COPY_SEND /*remote*/,
-			MACH_MSG_TYPE_MOVE_SEND /*local*/,
-			MACH_MSG_TYPE_NONE /*voucher*/,
-			MACH_MSGH_BITS_COMPLEX);
-		hdr->msgh_size           = thisMsgSize;
-		hdr->msgh_id             = kOSNotificationMessageID;
-
-		/* body.msgh_descriptor_count is set automatically after the closure */
-
-		port_desc[0].name              = providerPort;
-		port_desc[0].disposition       = MACH_MSG_TYPE_MOVE_SEND;
-		port_desc[0].type              = MACH_MSG_PORT_DESCRIPTOR;
-		/* End of kernel processed data */
-
-		udata->notifyHeader.size          = extraSize;
-		udata->notifyHeader.type          = type;
-		bcopy( msgReference, udata->notifyHeader.reference, msgReferenceSize );
-
-		/* data is after msgReference */
-		dataOffset = sizeof(PingMsgUdata) - sizeof(OSAsyncReference64) + msgReferenceSize;
-		data = (IOServiceInterestContent64 *) (((uint8_t *) udata) + dataOffset);
-		data->messageType = messageType;
-
-		if (callerArgSize == 0) {
-		        assert((char *)data->messageArgument + argSize <= (char *)payload + payloadSize);
-		        data->messageArgument[0] = (io_user_reference_t) messageArgument;
-		        if (!clientIs64) {
-		                data->messageArgument[0] |= (data->messageArgument[0] << 32);
-			}
-		} else {
-		        assert((char *)data->messageArgument + callerArgSize <= (char *)payload + payloadSize);
-		        bcopy(messageArgument, data->messageArgument, callerArgSize);
-		}
-	});
-
-	if (kr == MACH_SEND_NO_BUFFER) {
-		return kIOReturnNoMemory;
+	thisMsgSize = msgSize
+	    + sizeof(IOServiceInterestContent64)
+	    - sizeof(data->messageArgument)
+	    + argSize;
+
+	if (thisMsgSize > sizeof(stackMsg)) {
+		allocMsg = IOMalloc(thisMsgSize);
+		if (!allocMsg) {
+			return kIOReturnNoMemory;
+		}
+		thisMsg = (typeof(thisMsg))allocMsg;
+	} else {
+		allocMsg = NULL;
+		thisMsg  = (typeof(thisMsg))stackMsg;
+	}
+
+	bcopy(pingMsg, thisMsg, msgSize);
+	thisMsg->notifyHeader.type = type;
+	data = (IOServiceInterestContent64 *) (((uint8_t *) thisMsg) + msgSize);
+	// == pingMsg->notifyHeader.content;
+	data->messageType = messageType;
+
+	if (callerArgSize == 0) {
+		data->messageArgument[0] = (io_user_reference_t) messageArgument;
+		if (!clientIs64) {
+			data->messageArgument[0] |= (data->messageArgument[0] << 32);
+		}
+	} else {
+		bcopy( messageArgument, data->messageArgument, callerArgSize );
+		bzero((void *)(((uintptr_t) &data->messageArgument[0]) + callerArgSize), argSize - callerArgSize);
+	}
+
+	thisMsg->notifyHeader.type = type;
+	thisMsg->msgHdr.msgh_size  = thisMsgSize;
+
+	providerPort = iokit_port_for_object( provider, IKOT_IOKIT_OBJECT );
+	thisMsg->ports[0].name = providerPort;
+	thisPort = iokit_port_for_object( this, IKOT_IOKIT_OBJECT );
+	thisMsg->msgHdr.msgh_local_port = thisPort;
+
+	kr = mach_msg_send_from_kernel_with_options( &thisMsg->msgHdr,
+	    thisMsg->msgHdr.msgh_size,
+	    (MACH_SEND_MSG | MACH_SEND_ALWAYS | MACH_SEND_IMPORTANCE),
+	    0);
+	if (thisPort) {
+		iokit_release_port( thisPort );
+	}
+	if (providerPort) {
+		iokit_release_port( providerPort );
+	}
+
+	if (allocMsg) {
+		IOFree(allocMsg, thisMsgSize);
 	}
 
 	if ((KERN_SUCCESS != kr) && !ipcLogged) {
 		ipcLogged = true;
-		IOLog("%s: kernel_mach_msg_send (0x%x)\n", __PRETTY_FUNCTION__, kr );
+		IOLog("%s: mach_msg_send_from_kernel_proper (0x%x)\n", __PRETTY_FUNCTION__, kr );
 	}
 
 	return kIOReturnSuccess;
@@ -1313,12 +1203,6 @@
 OSDefineMetaClassAndAbstractStructors( IOUserClient, IOService )
 
 IOLock       * gIOUserClientOwnersLock;
-
-static TUNABLE(bool, gEnforcePowerEntitlement, "enforce-power-entitlement", false);
-
-static_assert(offsetof(IOUserClient, __opaque_end) -
-    offsetof(IOUserClient, __opaque_start) == sizeof(void *) * 9,
-    "ABI check: Opaque ivars for IOUserClient must be 9 void * big");
 
 void
 IOUserClient::initialize( void )
@@ -1327,31 +1211,17 @@
 	gIOUserClientOwnersLock = IOLockAlloc();
 	gIOUserServerLock       = IOLockAlloc();
 	assert(gIOObjectPortLock && gIOUserClientOwnersLock);
-
-#if IOTRACKING
-	IOTrackingQueueCollectUser(IOUserIterator::gMetaClass.getTracking());
-	IOTrackingQueueCollectUser(IOServiceMessageUserNotification::gMetaClass.getTracking());
-	IOTrackingQueueCollectUser(IOServiceUserNotification::gMetaClass.getTracking());
-	IOTrackingQueueCollectUser(IOUserClient::gMetaClass.getTracking());
-#endif /* IOTRACKING */
 }
 
 void
-#if __LP64__
-__attribute__((__noreturn__))
-#endif
 IOUserClient::setAsyncReference(OSAsyncReference asyncRef,
     mach_port_t wakePort,
     void *callback, void *refcon)
 {
-#if __LP64__
-	panic("setAsyncReference not valid for 64b");
-#else
 	asyncRef[kIOAsyncReservedIndex]      = ((uintptr_t) wakePort)
 	    | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]);
 	asyncRef[kIOAsyncCalloutFuncIndex]   = (uintptr_t) callback;
 	asyncRef[kIOAsyncCalloutRefconIndex] = (uintptr_t) refcon;
-#endif
 }
 
 void
@@ -1382,8 +1252,8 @@
 	OSArray * array;
 	OSDictionary * user = NULL;
 
-	OSObject * ioProperty = IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey);
-	if ((array = OSDynamicCast(OSArray, ioProperty))) {
+	if ((array = OSDynamicCast(OSArray,
+	    IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey)))) {
 		for (unsigned int idx = 0;
 		    (user = OSDynamicCast(OSDictionary, array->getObject(idx)));
 		    idx++) {
@@ -1395,8 +1265,8 @@
 				break;
 			}
 		}
-	}
-	OSSafeReleaseNULL(ioProperty);
+		array->release();
+	}
 	return user;
 }
 
@@ -1406,8 +1276,8 @@
 	OSArray * array;
 	OSDictionary * user = NULL;
 
-	OSObject * ioProperty = IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey);
-	if ((array = OSDynamicCast(OSArray, ioProperty))) {
+	if ((array = OSDynamicCast(OSArray,
+	    IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey)))) {
 		for (unsigned int idx = 0;
 		    (user = OSDynamicCast(OSDictionary, array->getObject(idx)));
 		    idx++) {
@@ -1416,8 +1286,8 @@
 				break;
 			}
 		}
-	}
-	OSSafeReleaseNULL(ioProperty);
+		array->release();
+	}
 	return user;
 }
 
@@ -1540,13 +1410,20 @@
 OSDictionary *
 IOUserClient::copyClientEntitlements(task_t task)
 {
+#define MAX_ENTITLEMENTS_LEN    (128 * 1024)
+
 	proc_t p = NULL;
 	pid_t pid = 0;
+	size_t len = 0;
+	void *entitlements_blob = NULL;
+	char *entitlements_data = NULL;
+	OSObject *entitlements_obj = NULL;
 	OSDictionary *entitlements = NULL;
+	OSString *errorString = NULL;
 
 	p = (proc_t)get_bsdtask_info(task);
 	if (p == NULL) {
-		return NULL;
+		goto fail;
 	}
 	pid = proc_pid(p);
 
@@ -1556,17 +1433,62 @@
 		}
 	}
 
-	// If the above fails, thats it
-	return NULL;
-}
-
-OSDictionary *
-IOUserClient::copyClientEntitlementsVnode(vnode_t vnode, off_t offset)
-{
-	OSDictionary *entitlements = NULL;
-
-	if (cs_entitlements_dictionary_copy_vnode(vnode, offset, (void**)&entitlements) != 0) {
-		return NULL;
+	if (cs_entitlements_blob_get(p, &entitlements_blob, &len) != 0) {
+		goto fail;
+	}
+
+	if (len <= offsetof(CS_GenericBlob, data)) {
+		goto fail;
+	}
+
+	/*
+	 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
+	 * we'll try to parse in the kernel.
+	 */
+	len -= offsetof(CS_GenericBlob, data);
+	if (len > MAX_ENTITLEMENTS_LEN) {
+		IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n",
+		    proc_best_name(p), pid, len, MAX_ENTITLEMENTS_LEN);
+		goto fail;
+	}
+
+	/*
+	 * OSUnserializeXML() expects a nul-terminated string, but that isn't
+	 * what is stored in the entitlements blob.  Copy the string and
+	 * terminate it.
+	 */
+	entitlements_data = (char *)IOMalloc(len + 1);
+	if (entitlements_data == NULL) {
+		goto fail;
+	}
+	memcpy(entitlements_data, ((CS_GenericBlob *)entitlements_blob)->data, len);
+	entitlements_data[len] = '\0';
+
+	entitlements_obj = OSUnserializeXML(entitlements_data, len + 1, &errorString);
+	if (errorString != NULL) {
+		IOLog("failed to parse entitlements for %s[%u]: %s\n",
+		    proc_best_name(p), pid, errorString->getCStringNoCopy());
+		goto fail;
+	}
+	if (entitlements_obj == NULL) {
+		goto fail;
+	}
+
+	entitlements = OSDynamicCast(OSDictionary, entitlements_obj);
+	if (entitlements == NULL) {
+		goto fail;
+	}
+	entitlements_obj = NULL;
+
+fail:
+	if (entitlements_data != NULL) {
+		IOFree(entitlements_data, len + 1);
+	}
+	if (entitlements_obj != NULL) {
+		entitlements_obj->release();
+	}
+	if (errorString != NULL) {
+		errorString->release();
 	}
 	return entitlements;
 }
@@ -1575,45 +1497,10 @@
 IOUserClient::copyClientEntitlement( task_t task,
     const char * entitlement )
 {
-	void *entitlement_object = 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);
-
-	return (OSObject*)entitlement_object;
-}
-
-OSObject *
-IOUserClient::copyClientEntitlementVnode(
-	struct vnode *vnode,
-	off_t offset,
-	const char *entitlement)
-{
 	OSDictionary *entitlements;
 	OSObject *value;
 
-	entitlements = copyClientEntitlementsVnode(vnode, offset);
+	entitlements = copyClientEntitlements(task);
 	if (entitlements == NULL) {
 		return NULL;
 	}
@@ -1678,12 +1565,13 @@
 IOUserClient::reserve()
 {
 	if (!reserved) {
-		reserved = IOMallocType(ExpansionData);
+		reserved = IONew(ExpansionData, 1);
+		if (!reserved) {
+			return false;
+		}
 	}
 	setTerminateDefer(NULL, true);
 	IOStatisticsRegisterCounter();
-	IORWLockInlineInit(&lock);
-	IOLockInlineInit(&filterLock);
 
 	return true;
 }
@@ -1720,14 +1608,17 @@
 		}
 	}
 	if (newOwner) {
-		owner = IOMallocType(IOUserClientOwner);
-
-		owner->task = task;
-		owner->uc   = this;
-		queue_enter_first(&owners, owner, IOUserClientOwner *, ucLink);
-		queue_enter_first(task_io_user_clients(task), owner, IOUserClientOwner *, taskLink);
-		if (messageAppSuspended) {
-			task_set_message_app_suspended(task, true);
+		owner = IONew(IOUserClientOwner, 1);
+		if (!owner) {
+			ret = kIOReturnNoMemory;
+		} else {
+			owner->task = task;
+			owner->uc   = this;
+			queue_enter_first(&owners, owner, IOUserClientOwner *, ucLink);
+			queue_enter_first(task_io_user_clients(task), owner, IOUserClientOwner *, taskLink);
+			if (messageAppSuspended) {
+				task_set_message_app_suspended(task, true);
+			}
 		}
 	}
 
@@ -1760,7 +1651,7 @@
 			}
 			task_set_message_app_suspended(owner->task, hasMessageAppSuspended);
 			queue_remove(&owners, owner, IOUserClientOwner *, ucLink);
-			IOFreeType(owner, IOUserClientOwner);
+			IODelete(owner, IOUserClientOwner, 1);
 		}
 		owners.next = owners.prev = NULL;
 	}
@@ -1817,46 +1708,16 @@
 	}
 }
 
-static kern_return_t
-iokit_task_terminate_phase1(task_t task)
-{
-	queue_head_t      * taskque;
-	IOUserClientOwner * iter;
-	OSSet             * userServers = NULL;
-
-	if (!task_is_driver(task)) {
-		return KERN_SUCCESS;
-	}
-	userServers = OSSet::withCapacity(1);
-
-	IOLockLock(gIOUserClientOwnersLock);
-
-	taskque = task_io_user_clients(task);
-	queue_iterate(taskque, iter, IOUserClientOwner *, taskLink) {
-		userServers->setObject(iter->uc);
-	}
-	IOLockUnlock(gIOUserClientOwnersLock);
-
-	if (userServers) {
-		IOUserServer * userServer;
-		while ((userServer = OSRequiredCast(IOUserServer, userServers->getAnyObject()))) {
-			userServer->clientDied();
-			userServers->removeObject(userServer);
-		}
-		userServers->release();
-	}
-	return KERN_SUCCESS;
-}
-
-static kern_return_t
-iokit_task_terminate_phase2(task_t task)
-{
-	queue_head_t      * taskque;
+extern "C" kern_return_t
+iokit_task_terminate(task_t task)
+{
 	IOUserClientOwner * owner;
 	IOUserClient      * dead;
 	IOUserClient      * uc;
+	queue_head_t      * taskque;
 
 	IOLockLock(gIOUserClientOwnersLock);
+
 	taskque = task_io_user_clients(task);
 	dead = NULL;
 	while (!queue_empty(taskque)) {
@@ -1873,8 +1734,9 @@
 			uc->owners.prev = (queue_entry_t) dead;
 			dead = uc;
 		}
-		IOFreeType(owner, IOUserClientOwner);
-	}
+		IODelete(owner, IOUserClientOwner, 1);
+	}
+
 	IOLockUnlock(gIOUserClientOwnersLock);
 
 	while (dead) {
@@ -1890,61 +1752,15 @@
 	return KERN_SUCCESS;
 }
 
-extern "C" kern_return_t
-iokit_task_terminate(task_t task, int phase)
-{
-	switch (phase) {
-	case 1:
-		return iokit_task_terminate_phase1(task);
-	case 2:
-		return iokit_task_terminate_phase2(task);
-	default:
-		panic("iokit_task_terminate phase %d", phase);
-	}
-}
-
-struct IOUCFilterPolicy {
-	task_t             task;
-	io_filter_policy_t filterPolicy;
-	IOUCFilterPolicy * next;
-};
-
-io_filter_policy_t
-IOUserClient::filterForTask(task_t task, io_filter_policy_t addFilterPolicy)
-{
-	IOUCFilterPolicy * elem;
-	io_filter_policy_t filterPolicy;
-
-	filterPolicy = 0;
-	IOLockLock(&filterLock);
-
-	for (elem = reserved->filterPolicies; elem && (elem->task != task); elem = elem->next) {
-	}
-
-	if (elem) {
-		if (addFilterPolicy) {
-			assert(addFilterPolicy == elem->filterPolicy);
-		}
-		filterPolicy = elem->filterPolicy;
-	} else if (addFilterPolicy) {
-		elem = IOMallocType(IOUCFilterPolicy);
-		elem->task               = task;
-		elem->filterPolicy       = addFilterPolicy;
-		elem->next               = reserved->filterPolicies;
-		reserved->filterPolicies = elem;
-		filterPolicy = addFilterPolicy;
-	}
-
-	IOLockUnlock(&filterLock);
-	return filterPolicy;
-}
-
 void
 IOUserClient::free()
 {
 	if (mappings) {
 		mappings->release();
 	}
+	if (lock) {
+		IOLockFree(lock);
+	}
 
 	IOStatisticsUnregisterCounter();
 
@@ -1952,29 +1768,11 @@
 	assert(!owners.prev);
 
 	if (reserved) {
-		IOUCFilterPolicy * elem;
-		IOUCFilterPolicy * nextElem;
-		for (elem = reserved->filterPolicies; elem; elem = nextElem) {
-			nextElem = elem->next;
-			if (elem->filterPolicy && gIOUCFilterCallbacks->io_filter_release) {
-				gIOUCFilterCallbacks->io_filter_release(elem->filterPolicy);
-			}
-			IOFreeType(elem, IOUCFilterPolicy);
-		}
-		IOFreeType(reserved, ExpansionData);
-		IORWLockInlineDestroy(&lock);
-		IOLockInlineDestroy(&filterLock);
+		IODelete(reserved, ExpansionData, 1);
 	}
 
 	super::free();
 }
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-OSDefineMetaClassAndAbstractStructors( IOUserClient2022, IOUserClient )
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 IOReturn
 IOUserClient::clientDied( void )
@@ -2037,17 +1835,6 @@
     IOMemoryDescriptor ** memory )
 {
 	return kIOReturnUnsupported;
-}
-
-IOReturn
-IOUserClient::clientMemoryForType( UInt32 type,
-    IOOptionBits * options,
-    OSSharedPtr<IOMemoryDescriptor>& memory )
-{
-	IOMemoryDescriptor* memoryRaw = nullptr;
-	IOReturn result = clientMemoryForType(type, options, &memoryRaw);
-	memory.reset(memoryRaw, OSNoRetain);
-	return result;
 }
 
 #if !__LP64__
@@ -2076,7 +1863,7 @@
 
 	err = clientMemoryForType((UInt32) type, &options, &memory );
 
-	if ((kIOReturnSuccess == err) && memory && !memory->hasSharingContext()) {
+	if (memory && (kIOReturnSuccess == err)) {
 		FAKE_STACK_FRAME(getMetaClass());
 
 		options = (options & ~kIOMapUserOptionsMask)
@@ -2131,16 +1918,6 @@
 	*obj = object;
 
 	return object ? kIOReturnSuccess : kIOReturnIPCError;
-}
-
-IOReturn
-IOUserClient::copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name,
-    OSSharedPtr<OSObject>& obj)
-{
-	OSObject* objRaw = NULL;
-	IOReturn result = copyObjectForPortNameInTask(task, port_name, &objRaw);
-	obj.reset(objRaw, OSNoRetain);
-	return result;
 }
 
 IOReturn
@@ -2186,16 +1963,6 @@
 	return method;
 }
 
-IOExternalMethod *
-IOUserClient::
-getTargetAndMethodForIndex(OSSharedPtr<IOService>& targetP, UInt32 index)
-{
-	IOService* targetPRaw = NULL;
-	IOExternalMethod* result = getTargetAndMethodForIndex(&targetPRaw, index);
-	targetP.reset(targetPRaw, OSRetain);
-	return result;
-}
-
 IOExternalAsyncMethod *
 IOUserClient::
 getAsyncTargetAndMethodForIndex(IOService ** targetP, UInt32 index)
@@ -2209,16 +1976,6 @@
 	return method;
 }
 
-IOExternalAsyncMethod *
-IOUserClient::
-getAsyncTargetAndMethodForIndex(OSSharedPtr<IOService>& targetP, UInt32 index)
-{
-	IOService* targetPRaw = NULL;
-	IOExternalAsyncMethod* result = getAsyncTargetAndMethodForIndex(&targetPRaw, index);
-	targetP.reset(targetPRaw, OSRetain);
-	return result;
-}
-
 IOExternalTrap *
 IOUserClient::
 getTargetAndTrapForIndex(IOService ** targetP, UInt32 index)
@@ -2261,7 +2018,7 @@
     IOReturn result, void *args[], UInt32 numArgs)
 {
 	OSAsyncReference64  reference64;
-	OSBoundedArray<io_user_reference_t, kMaxAsyncArgs> args64;
+	io_user_reference_t args64[kMaxAsyncArgs];
 	unsigned int        idx;
 
 	if (numArgs > kMaxAsyncArgs) {
@@ -2276,7 +2033,7 @@
 		args64[idx] = REF64(args[idx]);
 	}
 
-	return sendAsyncResult64(reference64, result, args64.data(), numArgs);
+	return sendAsyncResult64(reference64, result, args64, numArgs);
 }
 
 IOReturn
@@ -2371,15 +2128,15 @@
 
 	if ((options & kIOUserNotifyOptionCanDrop) != 0) {
 		kr = mach_msg_send_from_kernel_with_options( &replyMsg.msgHdr,
-		    replyMsg.msgHdr.msgh_size, MACH64_SEND_TIMEOUT, MACH_MSG_TIMEOUT_NONE);
+		    replyMsg.msgHdr.msgh_size, MACH_SEND_TIMEOUT, MACH_MSG_TIMEOUT_NONE);
 	} else {
 		/* Fail on full queue. */
-		kr = mach_msg_send_from_kernel(&replyMsg.msgHdr,
+		kr = mach_msg_send_from_kernel_proper( &replyMsg.msgHdr,
 		    replyMsg.msgHdr.msgh_size);
 	}
 	if ((KERN_SUCCESS != kr) && (MACH_SEND_TIMED_OUT != kr) && !(kIOUCAsyncErrorLoggedFlag & reference[0])) {
 		reference[0] |= kIOUCAsyncErrorLoggedFlag;
-		IOLog("%s: mach_msg_send_from_kernel(0x%x)\n", __PRETTY_FUNCTION__, kr );
+		IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__, kr );
 	}
 	return kr;
 }
@@ -2429,7 +2186,7 @@
 /* Routine io_server_version */
 kern_return_t
 is_io_server_version(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	uint64_t *version)
 {
 	*version = IOKIT_SERVER_VERSION;
@@ -2461,7 +2218,7 @@
 /* Routine io_object_get_superclass */
 kern_return_t
 is_io_object_get_superclass(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t obj_name,
 	io_name_t class_name)
 {
@@ -2474,7 +2231,7 @@
 	if (!obj_name || !class_name) {
 		return kIOReturnBadArgument;
 	}
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -2512,7 +2269,7 @@
 /* Routine io_object_get_bundle_identifier */
 kern_return_t
 is_io_object_get_bundle_identifier(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t obj_name,
 	io_name_t bundle_name)
 {
@@ -2525,7 +2282,7 @@
 	if (!obj_name || !bundle_name) {
 		return kIOReturnBadArgument;
 	}
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -2647,6 +2404,7 @@
 	return kIOReturnSuccess;
 }
 
+
 static kern_return_t
 internal_io_service_match_property_table(
 	io_service_t _service,
@@ -2661,12 +2419,9 @@
 	OSDictionary *      dict;
 
 	assert(matching_size);
-
-
 	obj = OSUnserializeXML(matching, matching_size);
 
 	if ((dict = OSDynamicCast( OSDictionary, obj))) {
-		IOTaskRegistryCompatibilityMatching(current_task(), dict);
 		*matches = service->passiveMatch( dict );
 		kr = kIOReturnSuccess;
 	} else {
@@ -2730,7 +2485,7 @@
 
 static kern_return_t
 internal_io_service_get_matching_services(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	const char * matching,
 	mach_msg_type_number_t matching_size,
 	io_iterator_t *existing )
@@ -2739,7 +2494,7 @@
 	OSObject *          obj;
 	OSDictionary *      dict;
 
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -2747,7 +2502,6 @@
 	obj = OSUnserializeXML(matching, matching_size);
 
 	if ((dict = OSDynamicCast( OSDictionary, obj))) {
-		IOTaskRegistryCompatibilityMatching(current_task(), dict);
 		*existing = IOUserIterator::withIterator(IOService::getMatchingServices( dict ));
 		kr = kIOReturnSuccess;
 	} else {
@@ -2764,7 +2518,7 @@
 /* Routine io_service_get_matching_services */
 kern_return_t
 is_io_service_get_matching_services(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_string_t matching,
 	io_iterator_t *existing )
 {
@@ -2774,7 +2528,7 @@
 /* Routine io_service_get_matching_services_ool */
 kern_return_t
 is_io_service_get_matching_services_ool(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_buf_ptr_t matching,
 	mach_msg_type_number_t matchingCnt,
 	kern_return_t *result,
@@ -2791,7 +2545,7 @@
 		// must return success after vm_map_copyout() succeeds
 		// and mig will copy out objects on success
 		*existing = NULL;
-		*result = internal_io_service_get_matching_services(main_port,
+		*result = internal_io_service_get_matching_services(master_port,
 		    (const char *) data, matchingCnt, existing);
 		vm_deallocate( kernel_map, data, matchingCnt );
 	}
@@ -2802,18 +2556,18 @@
 /* Routine io_service_get_matching_services_bin */
 kern_return_t
 is_io_service_get_matching_services_bin(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_struct_inband_t matching,
 	mach_msg_type_number_t matchingCnt,
 	io_object_t *existing)
 {
-	return internal_io_service_get_matching_services(main_port, matching, matchingCnt, existing);
+	return internal_io_service_get_matching_services(master_port, matching, matchingCnt, existing);
 }
 
 
 static kern_return_t
 internal_io_service_get_matching_service(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	const char * matching,
 	mach_msg_type_number_t matching_size,
 	io_service_t *service )
@@ -2822,7 +2576,7 @@
 	OSObject *          obj;
 	OSDictionary *      dict;
 
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -2830,7 +2584,6 @@
 	obj = OSUnserializeXML(matching, matching_size);
 
 	if ((dict = OSDynamicCast( OSDictionary, obj))) {
-		IOTaskRegistryCompatibilityMatching(current_task(), dict);
 		*service = IOService::copyMatchingService( dict );
 		kr = *service ? kIOReturnSuccess : kIOReturnNotFound;
 	} else {
@@ -2847,7 +2600,7 @@
 /* Routine io_service_get_matching_service */
 kern_return_t
 is_io_service_get_matching_service(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_string_t matching,
 	io_service_t *service )
 {
@@ -2857,7 +2610,7 @@
 /* Routine io_service_get_matching_services_ool */
 kern_return_t
 is_io_service_get_matching_service_ool(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_buf_ptr_t matching,
 	mach_msg_type_number_t matchingCnt,
 	kern_return_t *result,
@@ -2874,7 +2627,7 @@
 		// must return success after vm_map_copyout() succeeds
 		// and mig will copy out objects on success
 		*service = NULL;
-		*result = internal_io_service_get_matching_service(main_port,
+		*result = internal_io_service_get_matching_service(master_port,
 		    (const char *) data, matchingCnt, service );
 		vm_deallocate( kernel_map, data, matchingCnt );
 	}
@@ -2885,17 +2638,17 @@
 /* Routine io_service_get_matching_service_bin */
 kern_return_t
 is_io_service_get_matching_service_bin(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_struct_inband_t matching,
 	mach_msg_type_number_t matchingCnt,
 	io_object_t *service)
 {
-	return internal_io_service_get_matching_service(main_port, matching, matchingCnt, service);
+	return internal_io_service_get_matching_service(master_port, matching, matchingCnt, service);
 }
 
 static kern_return_t
 internal_io_service_add_notification(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t notification_type,
 	const char * matching,
 	size_t matching_size,
@@ -2908,12 +2661,11 @@
 	IOServiceUserNotification * userNotify = NULL;
 	IONotifier *                notify = NULL;
 	const OSSymbol *            sym;
-	OSObject *                  obj;
 	OSDictionary *              dict;
 	IOReturn                    err;
-	natural_t                   userMsgType;
-
-	if (main_port != main_device_port) {
+	unsigned long int           userMsgType;
+
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -2929,13 +2681,11 @@
 		}
 
 		assert(matching_size);
-		obj = OSUnserializeXML(matching, matching_size);
-		dict = OSDynamicCast(OSDictionary, obj);
+		dict = OSDynamicCast(OSDictionary, OSUnserializeXML(matching, matching_size));
 		if (!dict) {
 			err = kIOReturnBadArgument;
 			continue;
 		}
-		IOTaskRegistryCompatibilityMatching(current_task(), dict);
 
 		if ((sym == gIOPublishNotification)
 		    || (sym == gIOFirstPublishNotification)) {
@@ -2973,7 +2723,6 @@
 	} while (false);
 
 	if ((kIOReturnSuccess != err) && userNotify) {
-		userNotify->setNotification(NULL);
 		userNotify->invalidatePort();
 		userNotify->release();
 		userNotify = NULL;
@@ -2982,8 +2731,8 @@
 	if (sym) {
 		sym->release();
 	}
-	if (obj) {
-		obj->release();
+	if (dict) {
+		dict->release();
 	}
 
 	return err;
@@ -2993,7 +2742,7 @@
 /* Routine io_service_add_notification */
 kern_return_t
 is_io_service_add_notification(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t notification_type,
 	io_string_t matching,
 	mach_port_t port,
@@ -3007,7 +2756,7 @@
 /* Routine io_service_add_notification_64 */
 kern_return_t
 is_io_service_add_notification_64(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t notification_type,
 	io_string_t matching,
 	mach_port_t wake_port,
@@ -3022,7 +2771,7 @@
 kern_return_t
 is_io_service_add_notification_bin
 (
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t notification_type,
 	io_struct_inband_t matching,
 	mach_msg_type_number_t matchingCnt,
@@ -3039,7 +2788,7 @@
 	bcopy(&reference[0], &zreference[0], referenceCnt * sizeof(zreference[0]));
 	bzero(&zreference[referenceCnt], (ASYNC_REF_COUNT - referenceCnt) * sizeof(zreference[0]));
 
-	return internal_io_service_add_notification(main_port, notification_type,
+	return internal_io_service_add_notification(master_port, notification_type,
 	           matching, matchingCnt, wake_port, &zreference[0], sizeof(io_async_ref_t),
 	           false, notification);
 }
@@ -3048,7 +2797,7 @@
 kern_return_t
 is_io_service_add_notification_bin_64
 (
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t notification_type,
 	io_struct_inband_t matching,
 	mach_msg_type_number_t matchingCnt,
@@ -3065,14 +2814,14 @@
 	bcopy(&reference[0], &zreference[0], referenceCnt * sizeof(zreference[0]));
 	bzero(&zreference[referenceCnt], (ASYNC_REF64_COUNT - referenceCnt) * sizeof(zreference[0]));
 
-	return internal_io_service_add_notification(main_port, notification_type,
+	return internal_io_service_add_notification(master_port, notification_type,
 	           matching, matchingCnt, wake_port, &zreference[0], sizeof(io_async_ref64_t),
 	           true, notification);
 }
 
 static kern_return_t
 internal_io_service_add_notification_ool(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t notification_type,
 	io_buf_ptr_t matching,
 	mach_msg_type_number_t matchingCnt,
@@ -3094,7 +2843,7 @@
 		// must return success after vm_map_copyout() succeeds
 		// and mig will copy out objects on success
 		*notification = NULL;
-		*result = internal_io_service_add_notification( main_port, notification_type,
+		*result = internal_io_service_add_notification( master_port, notification_type,
 		    (char *) data, matchingCnt, wake_port, reference, referenceSize, client64, notification );
 		vm_deallocate( kernel_map, data, matchingCnt );
 	}
@@ -3105,7 +2854,7 @@
 /* Routine io_service_add_notification_ool */
 kern_return_t
 is_io_service_add_notification_ool(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t notification_type,
 	io_buf_ptr_t matching,
 	mach_msg_type_number_t matchingCnt,
@@ -3123,7 +2872,7 @@
 	bcopy(&reference[0], &zreference[0], referenceCnt * sizeof(zreference[0]));
 	bzero(&zreference[referenceCnt], (ASYNC_REF_COUNT - referenceCnt) * sizeof(zreference[0]));
 
-	return internal_io_service_add_notification_ool(main_port, notification_type,
+	return internal_io_service_add_notification_ool(master_port, notification_type,
 	           matching, matchingCnt, wake_port, &zreference[0], sizeof(io_async_ref_t),
 	           false, result, notification);
 }
@@ -3131,7 +2880,7 @@
 /* Routine io_service_add_notification_ool_64 */
 kern_return_t
 is_io_service_add_notification_ool_64(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t notification_type,
 	io_buf_ptr_t matching,
 	mach_msg_type_number_t matchingCnt,
@@ -3149,7 +2898,7 @@
 	bcopy(&reference[0], &zreference[0], referenceCnt * sizeof(zreference[0]));
 	bzero(&zreference[referenceCnt], (ASYNC_REF64_COUNT - referenceCnt) * sizeof(zreference[0]));
 
-	return internal_io_service_add_notification_ool(main_port, notification_type,
+	return internal_io_service_add_notification_ool(master_port, notification_type,
 	           matching, matchingCnt, wake_port, &zreference[0], sizeof(io_async_ref64_t),
 	           true, result, notification);
 }
@@ -3157,7 +2906,7 @@
 /* Routine io_service_add_notification_old */
 kern_return_t
 is_io_service_add_notification_old(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t notification_type,
 	io_string_t matching,
 	mach_port_t port,
@@ -3165,9 +2914,10 @@
 	natural_t ref,
 	io_object_t * notification )
 {
-	return is_io_service_add_notification( main_port, notification_type,
+	return is_io_service_add_notification( master_port, notification_type,
 	           matching, port, &ref, 1, notification );
 }
+
 
 static kern_return_t
 internal_io_service_add_interest_notification(
@@ -3189,25 +2939,12 @@
 	err = kIOReturnNoResources;
 	if ((sym = OSSymbol::withCString( type_of_interest ))) {
 		do {
-#if XNU_PLATFORM_WatchOS
-			if (sym == gIOAppPowerStateInterest &&
-			    !(IOCurrentTaskHasEntitlement("com.apple.private.power.notifications") || IOCurrentTaskHasEntitlement("com.apple.private.power.notifications-temp"))) {
-				OSString * taskName = IOCopyLogNameForPID(proc_selfpid());
-				IOLog("IORegisterForSystemPower called by %s without \"com.apple.private.power.notifications\" entitlement\n",
-				    taskName ? taskName->getCStringNoCopy() : "???");
-				OSSafeReleaseNULL(taskName);
-
-				if (gEnforcePowerEntitlement) {
-					err = kIOReturnNotPermitted;
-					continue;
-				}
-			}
-#endif // XNU_PLATFORM_WatchOS
-
 			userNotify = new IOServiceMessageUserNotification;
 
 			if (userNotify && !userNotify->init( port, kIOServiceMessageNotificationType,
-			    reference, referenceSize, client64 )) {
+			    reference, referenceSize,
+			    kIOUserNotifyMaxMessageSize,
+			    client64 )) {
 				userNotify->release();
 				userNotify = NULL;
 			}
@@ -3224,13 +2961,12 @@
 			} else {
 				err = kIOReturnUnsupported;
 			}
+
+			sym->release();
 		} while (false);
-
-		sym->release();
 	}
 
 	if ((kIOReturnSuccess != err) && userNotify) {
-		userNotify->setNotification(NULL);
 		userNotify->invalidatePort();
 		userNotify->release();
 		userNotify = NULL;
@@ -3304,27 +3040,22 @@
 	natural_t notification_type,
 	semaphore_t *semaphore )
 {
-	IOReturn ret;
 	CHECK( IOUserClient, connection, client );
 
 	IOStatisticsClientCall();
-	client->ipcEnter(kIPCLockWrite);
-	ret = client->getNotificationSemaphore((UInt32) notification_type,
-	    semaphore );
-	client->ipcExit(kIPCLockWrite);
-
-	return ret;
+	return client->getNotificationSemaphore((UInt32) notification_type,
+	           semaphore );
 }
 
 /* Routine io_registry_get_root_entry */
 kern_return_t
 is_io_registry_get_root_entry(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_object_t *root )
 {
 	IORegistryEntry *   entry;
 
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -3340,12 +3071,12 @@
 /* Routine io_registry_create_iterator */
 kern_return_t
 is_io_registry_create_iterator(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t plane,
 	uint32_t options,
 	io_object_t *iterator )
 {
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -3380,9 +3111,9 @@
 {
 	CHECKLOCKED( IORegistryIterator, iterator, iter );
 
-	IOLockLock(&oIter->lock);
+	IOLockLock(oIter->lock);
 	iter->enterEntry();
-	IOLockUnlock(&oIter->lock);
+	IOLockUnlock(oIter->lock);
 
 	return kIOReturnSuccess;
 }
@@ -3396,9 +3127,9 @@
 
 	CHECKLOCKED( IORegistryIterator, iterator, iter );
 
-	IOLockLock(&oIter->lock);
+	IOLockLock(oIter->lock);
 	didIt = iter->exitEntry();
-	IOLockUnlock(&oIter->lock);
+	IOLockUnlock(oIter->lock);
 
 	return didIt ? kIOReturnSuccess : kIOReturnNoDevice;
 }
@@ -3406,32 +3137,18 @@
 /* Routine io_registry_entry_from_path */
 kern_return_t
 is_io_registry_entry_from_path(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_string_t path,
 	io_object_t *registry_entry )
 {
 	IORegistryEntry *   entry;
 
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
 	entry = IORegistryEntry::fromPath( path );
 
-	if (!entry && IOTaskRegistryCompatibility(current_task())) {
-		OSDictionary * matching;
-		const OSObject * objects[2] = { kOSBooleanTrue, NULL };
-		const OSSymbol * keys[2]    = { gIOCompatibilityMatchKey, gIOPathMatchKey };
-
-		objects[1] = OSString::withCStringNoCopy(path);
-		matching = OSDictionary::withObjects(objects, keys, 2, 2);
-		if (matching) {
-			entry = IOService::copyMatchingService(matching);
-		}
-		OSSafeReleaseNULL(matching);
-		OSSafeReleaseNULL(objects[1]);
-	}
-
 	*registry_entry = entry;
 
 	return kIOReturnSuccess;
@@ -3441,7 +3158,7 @@
 /* Routine io_registry_entry_from_path */
 kern_return_t
 is_io_registry_entry_from_path_ool(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_string_inband_t path,
 	io_buf_ptr_t path_ool,
 	mach_msg_type_number_t path_oolCnt,
@@ -3454,7 +3171,7 @@
 	IOReturn            res;
 	kern_return_t       err;
 
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -3556,7 +3273,7 @@
 		err = kIOReturnSuccess;
 	} else {
 		length = kMaxPath;
-		buf = IONewData(char, length);
+		buf = IONew(char, length);
 		if (!buf) {
 			err = kIOReturnNoMemory;
 		} else if (!entry->getPath(buf, &length, IORegistryEntry::getPlane(plane))) {
@@ -3566,7 +3283,7 @@
 			err = copyoutkdata(buf, length, path_ool);
 		}
 		if (buf) {
-			IODeleteData(buf, char, kMaxPath);
+			IODelete(buf, char, kMaxPath);
 		}
 	}
 
@@ -3645,38 +3362,6 @@
 	*entry_id = entry->getRegistryEntryID();
 
 	return kIOReturnSuccess;
-}
-
-
-static OSObject *
-IOCopyPropertyCompatible(IORegistryEntry * regEntry, const char * name)
-{
-	OSObject     * obj;
-	OSObject     * compatProperties;
-	OSDictionary * props;
-
-	obj = regEntry->copyProperty(name);
-	if (obj) {
-		return obj;
-	}
-
-	compatProperties = regEntry->copyProperty(gIOUserServicePropertiesKey);
-	if (!compatProperties
-	    && IOTaskRegistryCompatibility(current_task())) {
-		compatProperties = regEntry->copyProperty(gIOCompatibilityPropertiesKey);
-	}
-	if (compatProperties) {
-		props = OSDynamicCast(OSDictionary, compatProperties);
-		if (props) {
-			obj = props->getObject(name);
-			if (obj) {
-				obj->retain();
-			}
-		}
-		compatProperties->release();
-	}
-
-	return obj;
 }
 
 /* Routine io_registry_entry_get_property */
@@ -3705,7 +3390,7 @@
 	}
 #endif
 
-	obj = IOCopyPropertyCompatible(entry, property_name);
+	obj = entry->copyProperty(property_name);
 	if (!obj) {
 		return kIOReturnNoResources;
 	}
@@ -3762,7 +3447,7 @@
 	mach_msg_type_number_t *propertiesCnt )
 {
 	kern_return_t       err;
-	unsigned int        len;
+	vm_size_t           len;
 	OSObject *          obj;
 
 	CHECK( IORegistryEntry, registry_entry, entry );
@@ -3773,7 +3458,7 @@
 	}
 #endif
 
-	obj = IOCopyPropertyCompatible(entry, property_name);
+	obj = entry->copyProperty(property_name);
 	if (!obj) {
 		return kIOReturnNotFound;
 	}
@@ -3809,7 +3494,7 @@
 	mach_msg_type_number_t *propertiesCnt )
 {
 	kern_return_t       err;
-	unsigned int        len;
+	vm_size_t           len;
 	OSObject *          obj;
 
 	CHECK( IORegistryEntry, registry_entry, entry );
@@ -3864,7 +3549,7 @@
 	OSCollection    * root;
 };
 
-static const LIBKERN_RETURNS_RETAINED OSMetaClassBase *
+static const OSMetaClassBase *
 GetPropertiesEditor(void                  * reference,
     OSSerialize           * s,
     OSCollection          * container,
@@ -3898,9 +3583,8 @@
 	io_buf_ptr_t *properties,
 	mach_msg_type_number_t *propertiesCnt)
 {
-	kern_return_t          err = kIOReturnSuccess;
-	unsigned int           len;
-	OSObject             * compatProperties;
+	kern_return_t              err = kIOReturnSuccess;
+	vm_size_t                  len;
 	OSSerialize          * s;
 	OSSerialize::Editor    editor = NULL;
 	void                 * editRef = NULL;
@@ -3923,30 +3607,7 @@
 		return kIOReturnNoMemory;
 	}
 
-
-	compatProperties = entry->copyProperty(gIOUserServicePropertiesKey);
-	if (!compatProperties
-	    && IOTaskRegistryCompatibility(current_task())) {
-		compatProperties = entry->copyProperty(gIOCompatibilityPropertiesKey);
-	}
-
-	if (compatProperties) {
-		OSDictionary * dict;
-
-		dict = entry->dictionaryWithProperties();
-		if (!dict) {
-			err = kIOReturnNoMemory;
-		} else {
-			dict->removeObject(gIOUserServicePropertiesKey);
-			dict->removeObject(gIOCompatibilityPropertiesKey);
-			dict->merge(OSDynamicCast(OSDictionary, compatProperties));
-			if (!dict->serialize(s)) {
-				err = kIOReturnUnsupported;
-			}
-			dict->release();
-		}
-		compatProperties->release();
-	} else if (!entry->serializeProperties(s)) {
+	if (!entry->serializeProperties(s)) {
 		err = kIOReturnUnsupported;
 	}
 
@@ -3998,7 +3659,7 @@
 	mach_msg_type_number_t *propertiesCnt )
 {
 	kern_return_t       err;
-	unsigned int        len;
+	vm_size_t           len;
 	OSObject *          obj;
 	const OSSymbol *    sym;
 
@@ -4015,32 +3676,14 @@
 		return kIOReturnNoMemory;
 	}
 
-	err = kIOReturnNotFound;
 	if (gIORegistryEntryPropertyKeysKey == sym) {
 		obj = entry->copyPropertyKeys();
 	} else {
 		if ((kIORegistryIterateRecursively & options) && plane[0]) {
-			obj = IOCopyPropertyCompatible(entry, property_name);
-			if (obj == NULL) {
-				IORegistryIterator * iter = IORegistryIterator::iterateOver(entry, IORegistryEntry::getPlane(plane), options);
-				if (iter) {
-					while ((NULL == obj) && (entry = iter->getNextObject())) {
-						OSObject * currentObj = IOCopyPropertyCompatible(entry, property_name);
-#if CONFIG_MACF
-						if (currentObj != NULL && 0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) {
-							// Record that MAC hook blocked this entry and property, and continue to next entry
-							err = kIOReturnNotPermitted;
-							OSSafeReleaseNULL(currentObj);
-							continue;
-						}
-#endif
-						obj = currentObj;
-					}
-					iter->release();
-				}
-			}
+			obj = entry->copyProperty(property_name,
+			    IORegistryEntry::getPlane(plane), options );
 		} else {
-			obj = IOCopyPropertyCompatible(entry, property_name);
+			obj = entry->copyProperty(property_name);
 		}
 		if (obj && gIORemoveOnReadProperties->containsObject(sym)) {
 			entry->removeProperty(sym);
@@ -4049,7 +3692,7 @@
 
 	sym->release();
 	if (!obj) {
-		return err;
+		return kIOReturnNotFound;
 	}
 
 	OSSerialize * s = OSSerialize::binaryWithCapacity(4096);
@@ -4142,66 +3785,9 @@
 		}
 #endif
 		else {
-			IOService    * service = OSDynamicCast(IOService, entry);
-			OSDictionary * props = OSDynamicCast(OSDictionary, obj);
-			OSObject     * allowable = entry->copyProperty(gIORegistryEntryAllowableSetPropertiesKey);
-			OSArray      * allowableArray;
-
-			if (!allowable) {
-				res = kIOReturnSuccess;
-			} else {
-				if (!props) {
-					res = kIOReturnNotPermitted;
-				} else if (!(allowableArray = OSDynamicCast(OSArray, allowable))) {
-					res = kIOReturnNotPermitted;
-				} else {
-					bool allFound __block, found __block;
-
-					allFound = true;
-					props->iterateObjects(^(const OSSymbol * key, OSObject * value) {
-							found = false;
-							for (unsigned int idx = 0; !found; idx++) {
-							        OSObject * next = allowableArray->getObject(idx);
-							        if (!next) {
-							                break;
-								}
-							        found = next->isEqualTo(key);
-							}
-							allFound &= found;
-							if (!found) {
-							        IOLog("IORegistryEntrySetProperties(%s, %s) disallowed due to " kIORegistryEntryAllowableSetPropertiesKey "\n",
-							        entry->getName(), key->getCStringNoCopy());
-							}
-							return !allFound;
-						});
-					res =  allFound ? kIOReturnSuccess : kIOReturnBadArgument;
-				}
-			}
-			if (kIOReturnSuccess == res) {
-				IOUserClient *
-				    client = OSDynamicCast(IOUserClient, entry);
-
-				if (client && client->defaultLockingSetProperties) {
-					IORWLockWrite(&client->lock);
-				}
-
-				if (!client && (kOSBooleanTrue == entry->getProperty(gIORegistryEntryDefaultLockingSetPropertiesKey))) {
-					res = entry->runPropertyActionBlock(^IOReturn (void) {
-							return entry->setProperties( obj );
-						});
-				} else {
-					res = entry->setProperties( obj );
-				}
-
-				if (client && client->defaultLockingSetProperties) {
-					IORWLockUnlock(&client->lock);
-				}
-				if (service && props && service->hasUserServer()) {
-					res = service->UserSetProperties(props);
-				}
-			}
-			OSSafeReleaseNULL(allowable);
-		}
+			res = entry->setProperties( obj );
+		}
+
 		if (obj) {
 			obj->release();
 		}
@@ -4292,34 +3878,6 @@
 	return service->waitQuiet(timeoutNS);
 }
 
-/* Routine io_service_wait_quiet_with_options */
-kern_return_t
-is_io_service_wait_quiet_with_options(
-	io_object_t _service,
-	mach_timespec_t wait_time,
-	uint32_t options )
-{
-	uint64_t    timeoutNS;
-
-	CHECK( IOService, _service, service );
-
-	timeoutNS = wait_time.tv_sec;
-	timeoutNS *= kSecondScale;
-	timeoutNS += wait_time.tv_nsec;
-
-	if ((options & kIOWaitQuietPanicOnFailure) && !IOCurrentTaskHasEntitlement(kIOWaitQuietPanicsEntitlement)) {
-		OSString * taskName = IOCopyLogNameForPID(proc_selfpid());
-		IOLog("IOServiceWaitQuietWithOptions(%s): Not entitled\n", taskName ? taskName->getCStringNoCopy() : "");
-		OSSafeReleaseNULL(taskName);
-
-		/* strip this option from the options before calling waitQuietWithOptions */
-		options &= ~kIOWaitQuietPanicOnFailure;
-	}
-
-	return service->waitQuietWithOptions(timeoutNS, options);
-}
-
-
 /* Routine io_service_request_probe */
 kern_return_t
 is_io_service_request_probe(
@@ -4347,12 +3905,7 @@
 		return kr;
 	}
 
-#if defined(XNU_TARGET_OS_OSX)
 	*authorization_id = service->getAuthorizationID();
-#else /* defined(XNU_TARGET_OS_OSX) */
-	*authorization_id = 0;
-	kr = kIOReturnUnsupported;
-#endif /* defined(XNU_TARGET_OS_OSX) */
 
 	return kr;
 }
@@ -4365,11 +3918,7 @@
 {
 	CHECK( IOService, _service, service );
 
-#if defined(XNU_TARGET_OS_OSX)
 	return service->setAuthorizationID( authorization_id );
-#else /* defined(XNU_TARGET_OS_OSX) */
-	return kIOReturnUnsupported;
-#endif /* defined(XNU_TARGET_OS_OSX) */
 }
 
 /* Routine io_service_open_ndr */
@@ -4388,7 +3937,8 @@
 	kern_return_t  err = KERN_SUCCESS;
 	IOReturn       res = kIOReturnSuccess;
 	OSDictionary * propertiesDict = NULL;
-	bool           disallowAccess = false;
+	bool           crossEndian;
+	bool           disallowAccess;
 
 	CHECK( IOService, _service, service );
 
@@ -4400,11 +3950,6 @@
 		return kIOReturnBadArgument;
 	}
 
-#if CONFIG_MACF
-	if (mac_iokit_check_open_service(kauth_cred_get(), service, connect_type) != 0) {
-		return kIOReturnNotPermitted;
-	}
-#endif
 	do{
 		if (properties) {
 			return kIOReturnUnsupported;
@@ -4439,6 +3984,20 @@
 			}
 		}
 #endif
+		crossEndian = (ndr.int_rep != NDR_record.int_rep);
+		if (crossEndian) {
+			if (!propertiesDict) {
+				propertiesDict = OSDictionary::withCapacity(4);
+			}
+			OSData * data = OSData::withBytes(&ndr, sizeof(ndr));
+			if (data) {
+				if (propertiesDict) {
+					propertiesDict->setObject(kIOUserClientCrossEndianKey, data);
+				}
+				data->release();
+			}
+		}
+
 		res = service->newUserClient( owningTask, (void *) owningTask,
 		    connect_type, propertiesDict, &client );
 
@@ -4446,158 +4005,42 @@
 			propertiesDict->release();
 		}
 
-		if (res == kIOReturnSuccess && OSDynamicCast(IOUserClient, client) == NULL) {
-			// client should always be a IOUserClient
-			res = kIOReturnError;
-		}
-
 		if (res == kIOReturnSuccess) {
-			if (!client->reserved) {
-				if (!client->reserve()) {
-					client->clientClose();
-					OSSafeReleaseNULL(client);
-					res = kIOReturnNoMemory;
-				}
-			}
-		}
-
-		if (res == kIOReturnSuccess) {
-			OSString * creatorName = IOCopyLogNameForPID(proc_selfpid());
-			if (creatorName) {
-				client->setProperty(kIOUserClientCreatorKey, creatorName);
-			}
-			const char * creatorNameCStr = creatorName ? creatorName->getCStringNoCopy() : "<unknown>";
+			assert( OSDynamicCast(IOUserClient, client));
+
 			client->sharedInstance = (NULL != client->getProperty(kIOUserClientSharedInstanceKey));
-			if (client->sharedInstance) {
-				IOLockLock(gIOUserClientOwnersLock);
-			}
-			if (!client->opened) {
-				client->opened = true;
-
-				client->messageAppSuspended = (NULL != client->getProperty(kIOUserClientMessageAppSuspendedKey));
-				{
-					OSObject * obj;
-					extern const OSSymbol * gIOSurfaceIdentifier;
-					obj = client->getProperty(kIOUserClientDefaultLockingKey);
-					bool hasProps = false;
-
-					client->uc2022 = (NULL != OSDynamicCast(IOUserClient2022, client));
-					if (obj) {
-						hasProps = true;
-						client->defaultLocking = (kOSBooleanFalse != client->getProperty(kIOUserClientDefaultLockingKey));
-					} else if (client->uc2022) {
-						res = kIOReturnError;
-					}
-					obj = client->getProperty(kIOUserClientDefaultLockingSetPropertiesKey);
-					if (obj) {
-						hasProps = true;
-						client->defaultLockingSetProperties = (kOSBooleanFalse != client->getProperty(kIOUserClientDefaultLockingSetPropertiesKey));
-					} else if (client->uc2022) {
-						res = kIOReturnError;
-					}
-					obj = client->getProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey);
-					if (obj) {
-						hasProps = true;
-						client->defaultLockingSingleThreadExternalMethod = (kOSBooleanFalse != client->getProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey));
-					} else if (client->uc2022) {
-						res = kIOReturnError;
-					}
-					if (kIOReturnSuccess != res) {
-						IOLog("IOUC %s requires kIOUserClientDefaultLockingKey, kIOUserClientDefaultLockingSetPropertiesKey, kIOUserClientDefaultLockingSingleThreadExternalMethodKey\n",
-						    client->getMetaClass()->getClassName());
-					}
-					if (!hasProps) {
-						const OSMetaClass * meta;
-						OSKext            * kext;
-						meta = client->getMetaClass();
-						kext = meta->getKext();
-						if (!kext || !kext->hasDependency(gIOSurfaceIdentifier)) {
-							client->defaultLocking = true;
-							client->defaultLockingSetProperties = false;
-							client->defaultLockingSingleThreadExternalMethod = false;
-							client->setProperty(kIOUserClientDefaultLockingKey, kOSBooleanTrue);
-						}
-					}
-				}
-			}
-			if (client->sharedInstance) {
-				IOLockUnlock(gIOUserClientOwnersLock);
-			}
-
-			OSObject     * requiredEntitlement = client->copyProperty(gIOUserClientEntitlementsKey);
-			OSString * requiredEntitlementString = OSDynamicCast(OSString, requiredEntitlement);
-			//If this is an IOUserClient2022, having kIOUserClientEntitlementsKey is mandatory.
-			//If it has kIOUserClientEntitlementsKey, the value must be either kOSBooleanFalse or an OSString
-			//If the value is kOSBooleanFalse, we allow access.
-			//If the value is an OSString, we allow access if the task has the named entitlement
-			if (client->uc2022) {
-				if (!requiredEntitlement) {
-					IOLog("IOUC %s missing " kIOUserClientEntitlementsKey " property\n",
-					    client->getMetaClass()->getClassName());
-					disallowAccess = true;
-				} else if (!requiredEntitlementString && requiredEntitlement != kOSBooleanFalse) {
-					IOLog("IOUC %s had " kIOUserClientEntitlementsKey "with value not boolean false or string\n", client->getMetaClass()->getClassName());
-					disallowAccess = true;
-				}
-			}
-
-			if (requiredEntitlement && disallowAccess == false) {
-				if (kOSBooleanFalse == requiredEntitlement) {
-					// allow
-					disallowAccess = false;
-				} else {
-					disallowAccess = !IOTaskHasEntitlement(owningTask, requiredEntitlementString->getCStringNoCopy());
-					if (disallowAccess) {
-						IOLog("IOUC %s missing entitlement in process %s\n",
-						    client->getMetaClass()->getClassName(), creatorNameCStr);
-					}
-				}
-			}
-
-			OSSafeReleaseNULL(requiredEntitlement);
-
+			client->messageAppSuspended = (NULL != client->getProperty(kIOUserClientMessageAppSuspendedKey));
+			client->closed = false;
+			client->lock = IOLockAlloc();
+
+			disallowAccess = (crossEndian
+			    && (kOSBooleanTrue != service->getProperty(kIOUserClientCrossEndianCompatibleKey))
+			    && (kOSBooleanTrue != client->getProperty(kIOUserClientCrossEndianCompatibleKey)));
 			if (disallowAccess) {
-				res = kIOReturnNotPrivileged;
+				res = kIOReturnUnsupported;
 			}
 #if CONFIG_MACF
 			else if (0 != mac_iokit_check_open(kauth_cred_get(), client, connect_type)) {
-				IOLog("IOUC %s failed MACF in process %s\n",
-				    client->getMetaClass()->getClassName(), creatorNameCStr);
 				res = kIOReturnNotPermitted;
 			}
 #endif
 
-			if ((kIOReturnSuccess == res)
-			    && gIOUCFilterCallbacks
-			    && gIOUCFilterCallbacks->io_filter_resolver) {
-				io_filter_policy_t filterPolicy;
-				filterPolicy = client->filterForTask(owningTask, 0);
-				if (!filterPolicy) {
-					res = gIOUCFilterCallbacks->io_filter_resolver(owningTask, client, connect_type, &filterPolicy);
-					if (kIOReturnUnsupported == res) {
-						res = kIOReturnSuccess;
-					} else if (kIOReturnSuccess == res) {
-						client->filterForTask(owningTask, filterPolicy);
-					} else {
-						IOLog("IOUC %s failed sandbox in process %s\n",
-						    client->getMetaClass()->getClassName(), creatorNameCStr);
-					}
-				}
-			}
-
 			if (kIOReturnSuccess == res) {
 				res = client->registerOwner(owningTask);
 			}
-			OSSafeReleaseNULL(creatorName);
 
 			if (kIOReturnSuccess != res) {
 				IOStatisticsClientCall();
 				client->clientClose();
-				client->setTerminateDefer(service, false);
 				client->release();
 				client = NULL;
 				break;
 			}
+			OSString * creatorName = IOCopyLogNameForPID(proc_selfpid());
+			if (creatorName) {
+				client->setProperty(kIOUserClientCreatorKey, creatorName);
+				creatorName->release();
+			}
 			client->setTerminateDefer(service, false);
 		}
 	}while (false);
@@ -4611,7 +4054,7 @@
 /* Routine io_service_close */
 kern_return_t
 is_io_service_close(
-	io_connect_t connection )
+	io_object_t connection )
 {
 	OSSet * mappings;
 	if ((mappings = OSDynamicCast(OSSet, connection))) {
@@ -4623,9 +4066,9 @@
 	IOStatisticsClientCall();
 
 	if (client->sharedInstance || OSCompareAndSwap8(0, 1, &client->closed)) {
-		client->ipcEnter(kIPCLockWrite);
+		IOLockLock(client->lock);
 		client->clientClose();
-		client->ipcExit(kIPCLockWrite);
+		IOLockUnlock(client->lock);
 	} else {
 		IOLog("ignored is_io_service_close(0x%qx,%s)\n",
 		    client->getRegistryEntryID(), client->getName());
@@ -4637,22 +4080,18 @@
 /* Routine io_connect_get_service */
 kern_return_t
 is_io_connect_get_service(
-	io_connect_t connection,
+	io_object_t connection,
 	io_object_t *service )
 {
 	IOService * theService;
 
 	CHECK( IOUserClient, connection, client );
-
-	client->ipcEnter(kIPCLockNone);
 
 	theService = client->getService();
 	if (theService) {
 		theService->retain();
 	}
 
-	client->ipcExit(kIPCLockNone);
-
 	*service = theService;
 
 	return theService ? kIOReturnSuccess : kIOReturnUnsupported;
@@ -4661,7 +4100,7 @@
 /* Routine io_connect_set_notification_port */
 kern_return_t
 is_io_connect_set_notification_port(
-	io_connect_t connection,
+	io_object_t connection,
 	uint32_t notification_type,
 	mach_port_t port,
 	uint32_t reference)
@@ -4670,19 +4109,17 @@
 	CHECK( IOUserClient, connection, client );
 
 	IOStatisticsClientCall();
-
-	client->ipcEnter(kIPCLockWrite);
+	IOLockLock(client->lock);
 	ret = client->registerNotificationPort( port, notification_type,
 	    (io_user_reference_t) reference );
-	client->ipcExit(kIPCLockWrite);
-
+	IOLockUnlock(client->lock);
 	return ret;
 }
 
 /* Routine io_connect_set_notification_port */
 kern_return_t
 is_io_connect_set_notification_port_64(
-	io_connect_t connection,
+	io_object_t connection,
 	uint32_t notification_type,
 	mach_port_t port,
 	io_user_reference_t reference)
@@ -4691,107 +4128,13 @@
 	CHECK( IOUserClient, connection, client );
 
 	IOStatisticsClientCall();
-
-	client->ipcEnter(kIPCLockWrite);
+	IOLockLock(client->lock);
 	ret = client->registerNotificationPort( port, notification_type,
 	    reference );
-	client->ipcExit(kIPCLockWrite);
-
+	IOLockUnlock(client->lock);
 	return ret;
 }
 
-
-/* Routine io_connect_map_shared_memory */
-kern_return_t
-is_io_connect_map_shared_memory
-(
-	io_connect_t connection,
-	uint32_t memory_type,
-	task_t into_task,
-	mach_vm_address_t *address,
-	mach_vm_size_t *size,
-	uint32_t map_flags,
-	io_name_t property_name,
-	io_struct_inband_t inband_output,
-	mach_msg_type_number_t *inband_outputCnt
-)
-{
-	IOReturn            err;
-	IOMemoryMap *       map = NULL;
-	IOOptionBits        options = 0;
-	IOMemoryDescriptor * memory = NULL;
-
-	CHECK( IOUserClient, connection, client );
-
-	if (!into_task) {
-		return kIOReturnBadArgument;
-	}
-	if (client->sharedInstance
-	    || (into_task != current_task())) {
-		return kIOReturnUnsupported;
-	}
-
-	IOStatisticsClientCall();
-
-	client->ipcEnter(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
-
-	err = client->clientMemoryForType(memory_type, &options, &memory );
-
-	if (memory && (kIOReturnSuccess == err)) {
-		OSObject * context = memory->copySharingContext(property_name);
-		OSData   * desc;
-		if (!(desc = OSDynamicCast(OSData, context))) {
-			err = kIOReturnNotReady;
-		} else {
-			if (!(kIOMapReadOnly & options)
-			    && !IOCurrentTaskHasEntitlement(kIOMapSharedMemoryWritableEntitlement)) {
-				err = kIOReturnNotPermitted;
-			} else if (desc->getLength() > *inband_outputCnt) {
-				err = kIOReturnOverrun;
-			} else {
-				memcpy(inband_output, desc->getBytesNoCopy(), desc->getLength());
-				*inband_outputCnt = desc->getLength();
-			}
-			OSSafeReleaseNULL(context);
-		}
-		if (kIOReturnSuccess == err) {
-			FAKE_STACK_FRAME(client->getMetaClass());
-
-			options = (options & ~kIOMapUserOptionsMask)
-			    | (map_flags & kIOMapUserOptionsMask)
-			    | kIOMapAnywhere;
-			map = memory->createMappingInTask( into_task, 0, options );
-
-			FAKE_STACK_FRAME_END();
-			if (!map) {
-				err = kIOReturnNotReadable;
-			}
-		}
-		memory->release();
-	}
-
-	if (map) {
-		*address = map->getAddress();
-		if (size) {
-			*size = map->getSize();
-		}
-		// keep it with the user client
-		IOLockLock( gIOObjectPortLock);
-		if (NULL == client->mappings) {
-			client->mappings = OSSet::withCapacity(2);
-		}
-		if (client->mappings) {
-			client->mappings->setObject( map);
-		}
-		IOLockUnlock( gIOObjectPortLock);
-		map->release();
-		err = kIOReturnSuccess;
-	}
-
-	client->ipcExit(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
-
-	return err;
-}
 /* Routine io_connect_map_memory_into_task */
 kern_return_t
 is_io_connect_map_memory_into_task
@@ -4814,8 +4157,6 @@
 	}
 
 	IOStatisticsClientCall();
-
-	client->ipcEnter(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
 	map = client->mapClientMemory64( memory_type, into_task, flags, *address );
 
 	if (map) {
@@ -4849,8 +4190,6 @@
 		err = kIOReturnBadArgument;
 	}
 
-	client->ipcExit(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
-
 	return err;
 }
 
@@ -4927,8 +4266,6 @@
 	}
 
 	IOStatisticsClientCall();
-
-	client->ipcEnter(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
 	err = client->clientMemoryForType((UInt32) memory_type, &options, &memory );
 
 	if (memory && (kIOReturnSuccess == err)) {
@@ -4945,8 +4282,7 @@
 			IOLockUnlock( gIOObjectPortLock);
 
 			mach_port_name_t name = 0;
-			bool is_shared_instance_or_from_current_task = from_task != current_task() || client->sharedInstance;
-			if (is_shared_instance_or_from_current_task) {
+			if (from_task != current_task()) {
 				name = IOMachPort::makeSendRightForTask( from_task, map, IKOT_IOKIT_OBJECT );
 				map->release();
 			}
@@ -4958,15 +4294,13 @@
 			} else {
 				IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT );
 			}
-			if (!is_shared_instance_or_from_current_task) {
+			if (from_task == current_task()) {
 				map->release();
 			}
 		} else {
 			err = kIOReturnBadArgument;
 		}
 	}
-
-	client->ipcExit(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
 
 	return err;
 }
@@ -4992,28 +4326,21 @@
 /* Routine io_connect_add_client */
 kern_return_t
 is_io_connect_add_client(
-	io_connect_t connection,
+	io_object_t connection,
 	io_object_t connect_to)
 {
 	CHECK( IOUserClient, connection, client );
 	CHECK( IOUserClient, connect_to, to );
 
-	IOReturn ret;
-
 	IOStatisticsClientCall();
-
-	client->ipcEnter(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
-	ret = client->connectClient( to );
-	client->ipcExit(client->defaultLocking ? kIPCLockWrite : kIPCLockNone);
-
-	return ret;
+	return client->connectClient( to );
 }
 
 
 /* Routine io_connect_set_properties */
 kern_return_t
 is_io_connect_set_properties(
-	io_connect_t connection,
+	io_object_t connection,
 	io_buf_ptr_t properties,
 	mach_msg_type_number_t propertiesCnt,
 	kern_return_t * result)
@@ -5085,16 +4412,7 @@
 	args.structureOutputDescriptorSize = 0;
 
 	IOStatisticsClientCall();
-	ret = kIOReturnSuccess;
-
-	io_filter_policy_t filterPolicy = client->filterForTask(current_task(), 0);
-	if (filterPolicy && gIOUCFilterCallbacks->io_filter_applier) {
-		ret = gIOUCFilterCallbacks->io_filter_applier(client, filterPolicy, io_filter_type_external_method, selector);
-	}
-
-	if (kIOReturnSuccess == ret) {
-		ret = client->callExternalMethod(selector, &args);
-	}
+	ret = client->externalMethod( selector, &args );
 
 	*scalar_outputCnt = args.scalarOutputCount;
 	*inband_outputCnt = args.structureOutputSize;
@@ -5102,14 +4420,13 @@
 	if (var_outputCnt && var_output && (kIOReturnSuccess == ret)) {
 		OSSerialize * serialize;
 		OSData      * data;
-		unsigned int  len;
+		vm_size_t     len;
 
 		if ((serialize = OSDynamicCast(OSSerialize, structureVariableOutputData))) {
 			len = serialize->getLength();
 			*var_outputCnt = len;
 			ret = copyoutkdata(serialize->text(), len, var_output);
 		} else if ((data = OSDynamicCast(OSData, structureVariableOutputData))) {
-			data->clipForCopyout();
 			len = data->getLength();
 			*var_outputCnt = len;
 			ret = copyoutkdata(data->getBytesNoCopy(), len, var_output);
@@ -5174,13 +4491,8 @@
 	if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t))) {
 		return kIOReturnIPCError;
 	}
-	if (ool_output) {
-		if (*ool_output_size <= sizeof(io_struct_inband_t)) {
-			return kIOReturnIPCError;
-		}
-		if (*ool_output_size > UINT_MAX) {
-			return kIOReturnIPCError;
-		}
+	if (ool_output && (*ool_output_size <= sizeof(io_struct_inband_t))) {
+		return kIOReturnIPCError;
 	}
 
 	if (ool_input) {
@@ -5203,19 +4515,10 @@
 	}
 
 	args.structureOutputDescriptor = outputMD;
-	args.structureOutputDescriptorSize = ool_output_size
-	    ? ((typeof(args.structureOutputDescriptorSize)) * ool_output_size)
-	    : 0;
+	args.structureOutputDescriptorSize = ool_output_size ? *ool_output_size : 0;
 
 	IOStatisticsClientCall();
-	ret = kIOReturnSuccess;
-	io_filter_policy_t filterPolicy = client->filterForTask(current_task(), 0);
-	if (filterPolicy && gIOUCFilterCallbacks->io_filter_applier) {
-		ret = gIOUCFilterCallbacks->io_filter_applier(client, filterPolicy, io_filter_type_external_method, selector);
-	}
-	if (kIOReturnSuccess == ret) {
-		ret = client->callExternalMethod( selector, &args );
-	}
+	ret = client->externalMethod( selector, &args );
 
 	*scalar_outputCnt = args.scalarOutputCount;
 	*inband_outputCnt = args.structureOutputSize;
@@ -5261,10 +4564,6 @@
 	IOMemoryDescriptor * inputMD  = NULL;
 	IOMemoryDescriptor * outputMD = NULL;
 
-	if (referenceCnt < 1) {
-		return kIOReturnBadArgument;
-	}
-
 	bzero(&args.__reserved[0], sizeof(args.__reserved));
 	args.__reservedA = 0;
 	args.version = kIOExternalMethodArgumentsCurrentVersion;
@@ -5290,13 +4589,8 @@
 	if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t))) {
 		return kIOReturnIPCError;
 	}
-	if (ool_output) {
-		if (*ool_output_size <= sizeof(io_struct_inband_t)) {
-			return kIOReturnIPCError;
-		}
-		if (*ool_output_size > UINT_MAX) {
-			return kIOReturnIPCError;
-		}
+	if (ool_output && (*ool_output_size <= sizeof(io_struct_inband_t))) {
+		return kIOReturnIPCError;
 	}
 
 	if (ool_input) {
@@ -5319,17 +4613,10 @@
 	}
 
 	args.structureOutputDescriptor = outputMD;
-	args.structureOutputDescriptorSize = ((typeof(args.structureOutputDescriptorSize)) * ool_output_size);
+	args.structureOutputDescriptorSize = *ool_output_size;
 
 	IOStatisticsClientCall();
-	ret = kIOReturnSuccess;
-	io_filter_policy_t filterPolicy = client->filterForTask(current_task(), 0);
-	if (filterPolicy && gIOUCFilterCallbacks->io_filter_applier) {
-		ret = gIOUCFilterCallbacks->io_filter_applier(client, filterPolicy, io_filter_type_external_async_method, selector);
-	}
-	if (kIOReturnSuccess == ret) {
-		ret = client->callExternalMethod( selector, &args );
-	}
+	ret = client->externalMethod( selector, &args );
 
 	*scalar_outputCnt = args.scalarOutputCount;
 	*inband_outputCnt = args.structureOutputSize;
@@ -6200,26 +5487,29 @@
 	return err;
 }
 
+#if !NO_KEXTD
+bool gIOKextdClearedBusy = false;
+#endif
+
 /* Routine io_catalog_send_data */
 kern_return_t
 is_io_catalog_send_data(
-	mach_port_t             main_port,
+	mach_port_t             master_port,
 	uint32_t                flag,
 	io_buf_ptr_t            inData,
 	mach_msg_type_number_t  inDataCount,
 	kern_return_t *         result)
 {
-	// Allow sending catalog data if there is no kextd and the kernel is DEVELOPMENT || DEBUG
-#if NO_KEXTD && !(DEVELOPMENT || DEBUG)
+#if NO_KEXTD
 	return kIOReturnNotPrivileged;
-#else /* NO_KEXTD && !(DEVELOPMENT || DEBUG) */
+#else /* NO_KEXTD */
 	OSObject * obj = NULL;
 	vm_offset_t data;
 	kern_return_t kr = kIOReturnError;
 
 	//printf("io_catalog_send_data called. flag: %d\n", flag);
 
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -6230,7 +5520,7 @@
 		return kIOReturnBadArgument;
 	}
 
-	if (!IOCurrentTaskHasEntitlement(kIOCatalogManagementEntitlement)) {
+	if (!IOTaskHasEntitlement(current_task(), kOSKextManagementEntitlement)) {
 		OSString * taskName = IOCopyLogNameForPID(proc_selfpid());
 		IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName ? taskName->getCStringNoCopy() : "");
 		OSSafeReleaseNULL(taskName);
@@ -6316,10 +5606,32 @@
 
 	case kIOCatalogStartMatching__Removed:
 	case kIOCatalogRemoveKernelLinker__Removed:
-	case kIOCatalogKextdActive:
-	case kIOCatalogKextdFinishedLaunching:
 		kr = KERN_NOT_SUPPORTED;
 		break;
+
+	case kIOCatalogKextdActive:
+#if !NO_KEXTD
+		IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
+		OSKext::setKextdActive();
+
+		/* Dump all nonloaded startup extensions; kextd will now send them
+		 * down on request.
+		 */
+		OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
+#endif
+		kr = kIOReturnSuccess;
+		break;
+
+	case kIOCatalogKextdFinishedLaunching: {
+#if !NO_KEXTD
+		if (!gIOKextdClearedBusy) {
+			IOService::kextdLaunched();
+			gIOKextdClearedBusy = true;
+		}
+#endif
+		kr = kIOReturnSuccess;
+	}
+	break;
 
 	default:
 		kr = kIOReturnBadArgument;
@@ -6332,19 +5644,19 @@
 
 	*result = kr;
 	return KERN_SUCCESS;
-#endif /* NO_KEXTD && !(DEVELOPMENT || DEBUG) */
+#endif /* NO_KEXTD */
 }
 
 /* Routine io_catalog_terminate */
 kern_return_t
 is_io_catalog_terminate(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	uint32_t flag,
 	io_name_t name )
 {
 	kern_return_t          kr;
 
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -6357,7 +5669,7 @@
 	switch (flag) {
 #if !defined(SECURE_KERNEL)
 	case kIOCatalogServiceTerminate:
-		kr = gIOCatalogue->terminateDrivers(NULL, name, false);
+		kr = gIOCatalogue->terminateDrivers(NULL, name);
 		break;
 
 	case kIOCatalogModuleUnload:
@@ -6378,7 +5690,7 @@
 /* Routine io_catalog_get_data */
 kern_return_t
 is_io_catalog_get_data(
-	mach_port_t             main_port,
+	mach_port_t             master_port,
 	uint32_t                flag,
 	io_buf_ptr_t            *outData,
 	mach_msg_type_number_t  *outDataCount)
@@ -6386,7 +5698,7 @@
 	kern_return_t kr = kIOReturnSuccess;
 	OSSerialize * s;
 
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -6400,16 +5712,16 @@
 	kr = gIOCatalogue->serializeData(flag, s);
 
 	if (kr == kIOReturnSuccess) {
-		mach_vm_address_t data;
+		vm_offset_t data;
 		vm_map_copy_t copy;
-		unsigned int size;
+		vm_size_t size;
 
 		size = s->getLength();
-		kr = mach_vm_allocate_kernel(kernel_map, &data, size,
-		    VM_MAP_KERNEL_FLAGS_ANYWHERE(.vm_tag = VM_KERN_MEMORY_IOKIT));
+		kr = vm_allocate_kernel(kernel_map, &data, size, VM_FLAGS_ANYWHERE, VM_KERN_MEMORY_IOKIT);
 		if (kr == kIOReturnSuccess) {
 			bcopy(s->text(), (void *)data, size);
-			kr = vm_map_copyin(kernel_map, data, size, true, &copy);
+			kr = vm_map_copyin(kernel_map, (vm_map_address_t)data,
+			    (vm_map_size_t)size, true, &copy);
 			*outData = (char *)copy;
 			*outDataCount = size;
 		}
@@ -6423,10 +5735,10 @@
 /* Routine io_catalog_get_gen_count */
 kern_return_t
 is_io_catalog_get_gen_count(
-	mach_port_t             main_port,
+	mach_port_t             master_port,
 	uint32_t                *genCount)
 {
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -6446,10 +5758,10 @@
  */
 kern_return_t
 is_io_catalog_module_loaded(
-	mach_port_t             main_port,
+	mach_port_t             master_port,
 	io_name_t               name)
 {
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -6466,10 +5778,10 @@
 
 kern_return_t
 is_io_catalog_reset(
-	mach_port_t             main_port,
+	mach_port_t             master_port,
 	uint32_t                flag)
 {
-	if (main_port != main_device_port) {
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
@@ -6488,55 +5800,35 @@
 kern_return_t
 iokit_user_client_trap(struct iokit_user_client_trap_args *args)
 {
-	kern_return_t    result = kIOReturnBadArgument;
-	IOUserClient   * userClient;
-	OSObject       * object;
-	uintptr_t        ref;
-	mach_port_name_t portName;
-
-	ref     = (uintptr_t) args->userClientRef;
-
-	if ((ref == MACH_PORT_DEAD) || (ref == (uintptr_t) MACH_PORT_NULL)) {
-		return kIOReturnBadArgument;
-	}
-	// kobject port names always have b0-1 set, so we use these bits as flags to
-	// iokit_user_client_trap()
-	// keep this up to date with ipc_entry_name_mask();
-	portName = (mach_port_name_t) (ref | 3);
-	if (((1ULL << 32) & ref) || !(1 & ref)) {
-		object = iokit_lookup_uext_ref_current_task(portName);
+	kern_return_t  result = kIOReturnBadArgument;
+	IOUserClient * userClient;
+	OSObject     * object;
+	uintptr_t      ref;
+
+	ref = (uintptr_t) args->userClientRef;
+	if ((1ULL << 32) & ref) {
+		object = iokit_lookup_uext_ref_current_task((mach_port_name_t) ref);
 		if (object) {
 			result = IOUserServerUEXTTrap(object, args->p1, args->p2, args->p3, args->p4, args->p5, args->p6);
 		}
 		OSSafeReleaseNULL(object);
-	} else {
-		io_object_t ref_current_task = iokit_lookup_connect_ref_current_task((mach_port_name_t) ref);
-		if ((userClient = OSDynamicCast(IOUserClient, ref_current_task))) {
-			IOExternalTrap *trap = NULL;
-			IOService *target = NULL;
-
-			result = kIOReturnSuccess;
-			io_filter_policy_t filterPolicy = userClient->filterForTask(current_task(), 0);
-			if (filterPolicy && gIOUCFilterCallbacks->io_filter_applier) {
-				result = gIOUCFilterCallbacks->io_filter_applier(userClient, filterPolicy, io_filter_type_trap, args->index);
+	} else if ((userClient = OSDynamicCast(IOUserClient, iokit_lookup_connect_ref_current_task((mach_port_name_t) ref)))) {
+		IOExternalTrap *trap;
+		IOService *target = NULL;
+
+		trap = userClient->getTargetAndTrapForIndex(&target, args->index);
+
+		if (trap && target) {
+			IOTrap func;
+
+			func = trap->func;
+
+			if (func) {
+				result = (target->*func)(args->p1, args->p2, args->p3, args->p4, args->p5, args->p6);
 			}
-			if (kIOReturnSuccess == result) {
-				trap = userClient->getTargetAndTrapForIndex(&target, args->index);
-			}
-			if (trap && target) {
-				IOTrap func;
-
-				func = trap->func;
-
-				if (func) {
-					result = (target->*func)(args->p1, args->p2, args->p3, args->p4, args->p5, args->p6);
-				}
-			}
-
-			iokit_remove_connect_reference(userClient);
-		} else {
-			OSSafeReleaseNULL(ref_current_task);
-		}
+		}
+
+		iokit_remove_connect_reference(userClient);
 	}
 
 	return result;
@@ -6545,123 +5837,23 @@
 /* Routine io_device_tree_entry_exists_with_name */
 kern_return_t
 is_io_device_tree_entry_exists_with_name(
-	mach_port_t main_port,
+	mach_port_t master_port,
 	io_name_t name,
 	boolean_t *exists )
 {
 	OSCollectionIterator *iter;
-	IORegistryEntry *entry;
-	io_name_t namebuf;
-	const char *entryname;
-	const char *propname;
-
-	if (main_port != main_device_port) {
+
+	if (master_port != master_device_port) {
 		return kIOReturnNotPrivileged;
 	}
 
-	if ((propname = strchr(name, ':'))) {
-		propname++;
-		strlcpy(namebuf, name, propname - name);
-		entryname = namebuf;
-	} else {
-		entryname = name;
-	}
-
-	iter = IODTFindMatchingEntries(IORegistryEntry::getRegistryRoot(), kIODTRecursive, entryname);
-	if (iter && (entry = (IORegistryEntry *) iter->getNextObject())) {
-		*exists = !propname || entry->propertyExists(propname);
-	} else {
-		*exists = FALSE;
-	}
+	iter = IODTFindMatchingEntries(IORegistryEntry::getRegistryRoot(), kIODTRecursive, name);
+	*exists = iter && iter->getNextObject();
 	OSSafeReleaseNULL(iter);
 
 	return kIOReturnSuccess;
 }
 } /* extern "C" */
-
-IOReturn
-IOUserClient::callExternalMethod(uint32_t selector, IOExternalMethodArguments * args)
-{
-	IOReturn ret;
-
-	ipcEnter(defaultLocking ? (defaultLockingSingleThreadExternalMethod ? kIPCLockWrite : kIPCLockRead) : kIPCLockNone);
-	if (uc2022) {
-		ret = ((IOUserClient2022 *) this)->externalMethod(selector, (IOExternalMethodArgumentsOpaque *) args);
-	} else {
-		ret = externalMethod(selector, args);
-	}
-	ipcExit(defaultLocking ? (defaultLockingSingleThreadExternalMethod ? kIPCLockWrite : kIPCLockRead) : kIPCLockNone);
-
-	return ret;
-}
-
-MIG_SERVER_ROUTINE IOReturn
-IOUserClient2022::externalMethod(uint32_t selector, IOExternalMethodArguments * arguments,
-    IOExternalMethodDispatch *dispatch,
-    OSObject *target, void *reference)
-{
-	panic("wrong externalMethod for IOUserClient2022");
-}
-
-IOReturn
-IOUserClient2022::dispatchExternalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque *arguments,
-    const IOExternalMethodDispatch2022 dispatchArray[], size_t dispatchArrayCount,
-    OSObject * target, void * reference)
-{
-	IOReturn    err;
-	IOExternalMethodArguments * args = (typeof(args))arguments;
-	const IOExternalMethodDispatch2022 * dispatch;
-
-	if (!dispatchArray) {
-		return kIOReturnError;
-	}
-	if (selector >= dispatchArrayCount) {
-		return kIOReturnBadArgument;
-	}
-	dispatch = &dispatchArray[selector];
-
-	uint32_t count;
-	count = dispatch->checkScalarInputCount;
-	if ((kIOUCVariableStructureSize != count) && (count != args->scalarInputCount)) {
-		return kIOReturnBadArgument;
-	}
-
-	count = dispatch->checkStructureInputSize;
-	if ((kIOUCVariableStructureSize != count)
-	    && (count != ((args->structureInputDescriptor)
-	    ? args->structureInputDescriptor->getLength() : args->structureInputSize))) {
-		return kIOReturnBadArgument;
-	}
-
-	count = dispatch->checkScalarOutputCount;
-	if ((kIOUCVariableStructureSize != count) && (count != args->scalarOutputCount)) {
-		return kIOReturnBadArgument;
-	}
-
-	count = dispatch->checkStructureOutputSize;
-	if ((kIOUCVariableStructureSize != count)
-	    && (count != ((args->structureOutputDescriptor)
-	    ? args->structureOutputDescriptor->getLength() : args->structureOutputSize))) {
-		return kIOReturnBadArgument;
-	}
-
-	if (args->asyncWakePort && !dispatch->allowAsync) {
-		return kIOReturnBadArgument;
-	}
-
-	if (dispatch->checkEntitlement) {
-		if (!IOCurrentTaskHasEntitlement(dispatch->checkEntitlement)) {
-			return kIOReturnNotPrivileged;
-		}
-	}
-
-	if (dispatch->function) {
-		err = (*dispatch->function)(target, reference, args);
-	} else {
-		err = kIOReturnNoCompletion; /* implementer can dispatch */
-	}
-	return err;
-}
 
 IOReturn
 IOUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args,
@@ -6700,7 +5892,7 @@
 		if (dispatch->function) {
 			err = (*dispatch->function)(target, reference, args);
 		} else {
-			err = kIOReturnNoCompletion; /* implementer can dispatch */
+			err = kIOReturnNoCompletion; /* implementator can dispatch */
 		}
 		return err;
 	}
@@ -6806,31 +5998,18 @@
 		}
 	}
 
-	if (structureOutputSize > UINT_MAX) {
-		structureOutputSize = 0;
-		err = kIOReturnBadArgument;
-	}
-
-	args->structureOutputSize = ((typeof(args->structureOutputSize))structureOutputSize);
+	args->structureOutputSize = structureOutputSize;
 
 	return err;
 }
 
-IOReturn
-IOUserClient::registerFilterCallbacks(const struct io_filter_callbacks *callbacks, size_t size)
-{
-	if (size < sizeof(*callbacks)) {
-		return kIOReturnBadArgument;
-	}
-	if (!OSCompareAndSwapPtr(NULL, __DECONST(void *, callbacks), &gIOUCFilterCallbacks)) {
-		return kIOReturnBusy;
-	}
-	return kIOReturnSuccess;
-}
-
-
+#if __LP64__
 OSMetaClassDefineReservedUnused(IOUserClient, 0);
 OSMetaClassDefineReservedUnused(IOUserClient, 1);
+#else
+OSMetaClassDefineReservedUsed(IOUserClient, 0);
+OSMetaClassDefineReservedUsed(IOUserClient, 1);
+#endif
 OSMetaClassDefineReservedUnused(IOUserClient, 2);
 OSMetaClassDefineReservedUnused(IOUserClient, 3);
 OSMetaClassDefineReservedUnused(IOUserClient, 4);
@@ -6845,8 +6024,3 @@
 OSMetaClassDefineReservedUnused(IOUserClient, 13);
 OSMetaClassDefineReservedUnused(IOUserClient, 14);
 OSMetaClassDefineReservedUnused(IOUserClient, 15);
-
-OSMetaClassDefineReservedUnused(IOUserClient2022, 0);
-OSMetaClassDefineReservedUnused(IOUserClient2022, 1);
-OSMetaClassDefineReservedUnused(IOUserClient2022, 2);
-OSMetaClassDefineReservedUnused(IOUserClient2022, 3);