Loading...
--- xnu/xnu-12377.121.6/iokit/Kernel/IOUserClient.cpp
+++ xnu/xnu-6153.121.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, ©);
+ kr = vm_map_copyin(kernel_map, (vm_map_address_t)data,
+ (vm_map_size_t)size, true, ©);
*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);