Loading...
--- xnu/xnu-12377.121.6/iokit/Kernel/IOUserServer.cpp
+++ xnu/xnu-8019.80.24/iokit/Kernel/IOUserServer.cpp
@@ -43,28 +43,18 @@
#include <IOKit/IOHibernatePrivate.h>
#include <IOKit/IOBSD.h>
#include <IOKit/system.h>
-#include "IOServicePrivate.h"
#include <IOKit/IOUserServer.h>
#include <IOKit/IOInterruptEventSource.h>
#include <IOKit/IOTimerEventSource.h>
-#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/pwr_mgt/RootDomain.h>
-#include <IOKit/pwr_mgt/IOPowerConnection.h>
#include <libkern/c++/OSAllocation.h>
#include <libkern/c++/OSKext.h>
#include <libkern/c++/OSSharedPtr.h>
#include <libkern/OSDebug.h>
#include <libkern/Block.h>
-#include <kern/cs_blobs.h>
-#include <kern/thread_call.h>
-#include <os/atomic_private.h>
#include <sys/proc.h>
#include <sys/reboot.h>
-#include <sys/codesign.h>
-#include <vm/vm_iokit.h>
-#include <mach_debug/mach_debug_types.h>
#include "IOKitKernelInternal.h"
-#include "IOServicePMPrivate.h"
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -90,41 +80,17 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-enum{
- kIOUserServerCheckInTimeoutMSecs = 120000ULL,
- kIOUserServerCheckInMaxRetry = 3,
-};
-
TUNABLE(SInt64, gIODKDebug, "dk", kIODKEnable);
-
-#if DEBUG || DEVELOPMENT
-uint64_t driverkit_checkin_timed_out = 0;
-TUNABLE(bool, disable_dext_crash_reboot, "disable_dext_crash_reboot", 0);
-extern "C" kern_return_t kern_register_userspace_coredump(task_t task, const char * name, boolean_t emergency);
-#endif /* DEBUG || DEVELOPMENT */
-
-extern bool restore_boot;
static OSString * gIOSystemStateSleepDescriptionKey;
static const OSSymbol * gIOSystemStateSleepDescriptionReasonKey;
static const OSSymbol * gIOSystemStateSleepDescriptionHibernateStateKey;
-static OSString * gIOSystemStateWakeDescriptionKey;
-static const OSSymbol * gIOSystemStateWakeDescriptionWakeReasonKey;
-static const OSSymbol * gIOSystemStateWakeDescriptionContinuousTimeOffsetKey;
-
static OSString * gIOSystemStateHaltDescriptionKey;
static const OSSymbol * gIOSystemStateHaltDescriptionHaltStateKey;
static OSString * gIOSystemStatePowerSourceDescriptionKey;
static const OSSymbol * gIOSystemStatePowerSourceDescriptionACAttachedKey;
-
-extern bool gInUserspaceReboot;
-
-extern void iokit_clear_registered_ports(task_t task);
-
-static IORPCMessage *
-IORPCMessageFromMachReply(IORPCMessageMach * msg);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -165,6 +131,32 @@
OSDefineMetaClassAndStructors(IOUserService, IOService)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+class IOUserUserClient : public IOUserClient
+{
+ OSDeclareDefaultStructors(IOUserUserClient);
+public:
+ task_t fTask;
+ OSDictionary * fWorkGroups;
+ OSDictionary * fEventLinks;
+ IOLock * fLock;
+
+ IOReturn setTask(task_t task);
+ IOReturn eventlinkConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6);
+ IOReturn workgroupConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6);
+
+ virtual bool init( OSDictionary * dictionary ) APPLE_KEXT_OVERRIDE;
+ virtual void free() APPLE_KEXT_OVERRIDE;
+ virtual void stop(IOService * provider) APPLE_KEXT_OVERRIDE;
+ virtual IOReturn clientClose(void) APPLE_KEXT_OVERRIDE;
+ virtual IOReturn setProperties(OSObject * properties) APPLE_KEXT_OVERRIDE;
+ virtual IOReturn externalMethod(uint32_t selector, IOExternalMethodArguments * args,
+ IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) APPLE_KEXT_OVERRIDE;
+ virtual IOReturn clientMemoryForType(UInt32 type,
+ IOOptionBits * options,
+ IOMemoryDescriptor ** memory) APPLE_KEXT_OVERRIDE;
+ virtual IOExternalTrap * getTargetAndTrapForIndex( IOService **targetP, UInt32 index ) APPLE_KEXT_OVERRIDE;
+};
OSDefineMetaClassAndStructors(IOUserServerCheckInToken, OSObject);
OSDefineMetaClassAndStructors(_IOUserServerCheckInCancellationHandler, OSObject);
@@ -210,7 +202,6 @@
OSString * typeName;
void * reference;
size_t referenceSize;
- bool aborted;
};
struct IOWorkGroup_IVars {
@@ -368,22 +359,8 @@
IOService::RegisterService_Impl()
{
IOReturn ret = kIOReturnSuccess;
- bool started;
-
- IOUserServer *us = (typeof(us))thread_iokit_tls_get(0);
- if (reserved != NULL && reserved->uvars != NULL && reserved->uvars->userServer == us) {
- started = reserved->uvars->started;
- } else {
- // assume started
- started = true;
- }
-
- if (OSDynamicCast(IOUserServer, this) != NULL || started) {
- registerService(kIOServiceAsynchronous);
- } else {
- assert(reserved != NULL && reserved->uvars != NULL);
- reserved->uvars->deferredRegisterService = true;
- }
+
+ registerService(kIOServiceAsynchronous);
return ret;
}
@@ -399,11 +376,6 @@
uint32_t index;
if (!reserved->uvars) {
- return kIOReturnError;
- }
-
- if (!reserved->uvars->queueArray) {
- // CopyDispatchQueue should not be called after the service has stopped
return kIOReturnError;
}
@@ -591,7 +563,7 @@
}
kern_return_t
-IOService::CopyProperties_Local(
+IOService::CopyProperties_Impl(
OSDictionary ** properties)
{
OSDictionary * props;
@@ -610,13 +582,6 @@
}
kern_return_t
-IOService::CopyProperties_Impl(
- OSDictionary ** properties)
-{
- return CopyProperties_Local(properties);
-}
-
-kern_return_t
IOService::RequireMaxBusStall_Impl(
uint64_t u64ns)
{
@@ -628,7 +593,7 @@
}
ret = requireMaxBusStall(ns);
- return ret;
+ return kIOReturnSuccess;
}
#if PRIVATE_WIFI_ONLY
@@ -637,12 +602,6 @@
OSContainer * properties)
{
return kIOReturnUnsupported;
-}
-
-kern_return_t
-IOService::SendIOMessageServicePropertyChange_Impl(void)
-{
- return messageClients(kIOMessageServicePropertyChange);
}
#endif /* PRIVATE_WIFI_ONLY */
@@ -729,9 +688,6 @@
case kIOMemoryMapCacheModeWriteThrough:
koptions |= kIOMapWriteThruCache;
break;
- case kIOMemoryMapCacheModeRealTime:
- koptions |= kIOMapRealTimeCache;
- break;
default:
ret = kIOReturnBadArgument;
}
@@ -860,7 +816,7 @@
return kIOReturnNotReady;
}
- mdOptions = kIOMemoryThreadSafe;
+ mdOptions = 0;
if (kIOMemoryDirectionOut & memoryDescriptorCreateOptions) {
mdOptions |= kIODirectionOut;
}
@@ -925,7 +881,7 @@
// no other options currently defined
return kIOReturnBadArgument;
}
- bmdOptions = (options & kIOMemoryDirectionOutIn) | kIOMemoryKernelUserShared | kIOMemoryThreadSafe;
+ bmdOptions = (options & kIOMemoryDirectionOutIn) | kIOMemoryKernelUserShared;
bmd = IOBufferMemoryDescriptor::inTaskWithOptions(
kernel_task, bmdOptions, capacity, alignment);
@@ -987,7 +943,6 @@
dma = IODMACommand::withSpecification(
kIODMACommandOutputHost64,
&segmentOptions,
- kIODMAMapOptionDextOwner |
kIODMAMapOptionMapped,
mapper,
NULL);
@@ -1002,8 +957,6 @@
return ret;
}
-
-#define fInternalState reserved
kern_return_t
IODMACommand::PrepareForDMA_Impl(
@@ -1025,30 +978,23 @@
return kIOReturnBadArgument;
}
- if (memory == NULL) {
- return kIOReturnBadArgument;
- }
-
- assert(fInternalState->fDextLock);
- IOLockLock(fInternalState->fDextLock);
-
// uses IOMD direction
ret = memory->prepare();
if (kIOReturnSuccess != ret) {
- goto exit;
+ return ret;
}
ret = setMemoryDescriptor(memory, false);
if (kIOReturnSuccess != ret) {
memory->complete();
- goto exit;
+ return ret;
}
ret = prepare(offset, length);
if (kIOReturnSuccess != ret) {
clearMemoryDescriptor(false);
memory->complete();
- goto exit;
+ return ret;
}
static_assert(sizeof(IODMACommand::Segment64) == sizeof(IOAddressSegment));
@@ -1057,25 +1003,18 @@
genOffset = 0;
ret = genIOVMSegments(&genOffset, segments, &numSegments);
- if (kIOReturnSuccess != ret) {
- clearMemoryDescriptor(true);
- memory->complete();
- goto exit;
- }
-
- mdFlags = fMemory->getFlags();
- lflags = 0;
- if (kIODirectionOut & mdFlags) {
- lflags |= kIOMemoryDirectionOut;
- }
- if (kIODirectionIn & mdFlags) {
- lflags |= kIOMemoryDirectionIn;
- }
- *flags = lflags;
- *segmentsCount = numSegments;
-
-exit:
- IOLockUnlock(fInternalState->fDextLock);
+ if (kIOReturnSuccess == ret) {
+ mdFlags = fMemory->getFlags();
+ lflags = 0;
+ if (kIODirectionOut & mdFlags) {
+ lflags |= kIOMemoryDirectionOut;
+ }
+ if (kIODirectionIn & mdFlags) {
+ lflags |= kIOMemoryDirectionIn;
+ }
+ *flags = lflags;
+ *segmentsCount = numSegments;
+ }
return ret;
}
@@ -1091,13 +1030,8 @@
// no other options currently defined
return kIOReturnBadArgument;
}
-
- assert(fInternalState->fDextLock);
- IOLockLock(fInternalState->fDextLock);
-
- if (!fInternalState->fPrepared) {
- ret = kIOReturnNotReady;
- goto exit;
+ if (!fActive) {
+ return kIOReturnNotReady;
}
md = __DECONST(IOMemoryDescriptor *, fMemory);
@@ -1114,8 +1048,6 @@
ret = completeRet;
}
}
-exit:
- IOLockUnlock(fInternalState->fDextLock);
return ret;
}
@@ -1405,10 +1337,6 @@
void
OSAction::Aborted_Impl(void)
{
- if (!os_atomic_cmpxchg(&ivars->aborted, false, true, relaxed)) {
- // already aborted
- return;
- }
if (ivars->abortedHandler) {
ivars->abortedHandler();
}
@@ -1465,14 +1393,9 @@
uint64_t time;
OSAction * action;
bool enable;
- bool canceled;
};
-void
-IOInterruptDispatchSourceInterrupt(OSObject * target, void * refCon,
- IOService * nub, int source );
-
-void
+static void
IOInterruptDispatchSourceInterrupt(OSObject * target, void * refCon,
IOService * nub, int source )
{
@@ -1564,8 +1487,11 @@
void
IOInterruptDispatchSource::free()
{
+ IOReturn ret;
+
if (ivars && ivars->provider) {
- (void) ivars->provider->unregisterInterrupt(ivars->intIndex);
+ ret = ivars->provider->unregisterInterrupt(ivars->intIndex);
+ assert(kIOReturnSuccess == ret);
ivars->provider->release();
}
@@ -1608,11 +1534,6 @@
if (enable == ivars->enable) {
return kIOReturnSuccess;
}
-
- if (ivars->canceled) {
- return kIOReturnUnsupported;
- }
- assert(ivars->provider != NULL);
if (enable) {
is = IOSimpleLockLockDisableInterrupt(ivars->lock);
@@ -1633,27 +1554,7 @@
IOInterruptDispatchSource::Cancel_Impl(
IODispatchSourceCancelHandler handler)
{
- IOInterruptState is;
- IOService * provider;
-
- is = IOSimpleLockLockDisableInterrupt(ivars->lock);
- ivars->canceled = true;
- if (ivars->waiter) {
- thread_wakeup_thread((event_t) ivars, ivars->waiter);
- ivars->waiter = NULL;
- }
- provider = ivars->provider;
- if (provider) {
- ivars->provider = NULL;
- }
- IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-
- if (provider) {
- (void) provider->unregisterInterrupt(ivars->intIndex);
- provider->release();
- }
-
- return kIOReturnSuccess;
+ return kIOReturnUnsupported;
}
kern_return_t
@@ -1664,7 +1565,6 @@
IOReturn ret = kIOReturnNotReady;
IOInterruptState is;
bool willWait;
- bool canceled;
wait_result_t waitResult;
uint64_t icount;
uint64_t itime;
@@ -1673,40 +1573,31 @@
self = current_thread();
icount = 0;
do {
- willWait = false;
is = IOSimpleLockLockDisableInterrupt(ivars->lock);
- canceled = ivars->canceled;
- if (!canceled) {
- if ((icount = ivars->count)) {
- itime = ivars->time;
- ivars->count = 0;
- waitResult = THREAD_AWAKENED;
- } else if (synchronous) {
- assert(NULL == ivars->waiter);
- ivars->waiter = self;
- waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
- }
- willWait = (synchronous && (waitResult == THREAD_WAITING));
- if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) {
- IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
- ivars->provider->enableInterrupt(ivars->intIndex);
- } else {
- IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
- }
- } else {
- IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
- }
+ if ((icount = ivars->count)) {
+ itime = ivars->time;
+ ivars->count = 0;
+ waitResult = THREAD_AWAKENED;
+ } else if (synchronous) {
+ assert(NULL == ivars->waiter);
+ ivars->waiter = self;
+ waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
+ }
+ willWait = (synchronous && (waitResult == THREAD_WAITING));
+ if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) {
+ ivars->provider->enableInterrupt(ivars->intIndex);
+ }
+ IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
if (willWait) {
waitResult = thread_block(THREAD_CONTINUE_NULL);
if (THREAD_INTERRUPTED == waitResult) {
is = IOSimpleLockLockDisableInterrupt(ivars->lock);
ivars->waiter = NULL;
IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
- canceled = true;
break;
}
}
- } while (synchronous && !icount && !canceled);
+ } while (synchronous && !icount);
if (icount && ivars->action) {
ret = InterruptOccurred(rpc, ivars->action, icount, itime);
@@ -1721,28 +1612,6 @@
uint64_t count,
uint64_t time)
{
-}
-
-kern_return_t
-IOInterruptDispatchSource::GetLastInterrupt_Impl(
- uint64_t * pCount,
- uint64_t * pTime)
-{
- IOInterruptState is;
- uint64_t count, time;
-
- is = IOSimpleLockLockDisableInterrupt(ivars->lock);
- count = ivars->count;
- time = ivars->time;
- IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-
- if (pCount) {
- *pCount = count;
- }
- if (pTime) {
- *pTime = time;
- }
- return kIOReturnSuccess;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -1757,7 +1626,7 @@
IOLock * lock;
IONotifier * notifier;
OSDictionary * interestNotifiers;
- OSBoundedArray<OSArray *, kIOServiceNotificationTypeCount> pending;
+ OSArray * pending[kIOServiceNotificationTypeCount];
bool enable;
};
@@ -1811,7 +1680,7 @@
inst->ivars->notifier = IOService::addMatchingNotification(gIOMatchedNotification, matching, 0 /*priority*/,
^bool (IOService * newService, IONotifier * notifier) {
bool notifyReady = false;
- IONotifier * interest = NULL;
+ IONotifier * interest;
OSObject * serverName;
bool okToUse;
@@ -1819,78 +1688,39 @@
okToUse = (serverName && inst->ivars->serverName->isEqualTo(serverName));
OSSafeReleaseNULL(serverName);
if (!okToUse) {
- OSObject * prop;
- OSObject * str;
-
- if (!newService->reserved->uvars || !newService->reserved->uvars->userServer) {
- return false;
- }
- str = OSString::withCStringNoCopy(kIODriverKitAllowsPublishEntitlementsKey);
- if (!str) {
- return false;
- }
- okToUse = newService->reserved->uvars->userServer->checkEntitlements(str, NULL, NULL);
- if (!okToUse) {
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS ": publisher entitlements check failed\n", DKN(newService));
- }
- return false;
- }
- prop = newService->copyProperty(kIODriverKitPublishEntitlementsKey);
- if (!prop) {
- return false;
- }
- okToUse = us->checkEntitlements(prop, NULL, NULL);
- if (!okToUse) {
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS ": subscriber entitlements check failed\n", DKN(newService));
- }
- return false;
- }
+ return false;
}
IOLockLock(inst->ivars->lock);
notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeMatched]->getCount());
inst->ivars->pending[kIOServiceNotificationTypeMatched]->setObject(newService);
- bool needInterest = (NULL == inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService));
IOLockUnlock(inst->ivars->lock);
- if (needInterest) {
- interest = newService->registerInterest(gIOGeneralInterest,
- ^IOReturn (uint32_t messageType, IOService * provider,
- void * messageArgument, size_t argSize) {
- IONotifier * interest;
- bool notifyReady = false;
-
- // after the notifier remove, IOServiceNotificationDispatchSource::free
- // will not wait for this code to complete
- if (!inst->taggedTryRetain(NULL)) {
- return kIOReturnSuccess;
- }
-
- switch (messageType) {
- case kIOMessageServiceIsTerminated:
- IOLockLock(inst->ivars->lock);
- notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeTerminated]->getCount());
- inst->ivars->pending[kIOServiceNotificationTypeTerminated]->setObject(provider);
- if (inst->ivars->interestNotifiers != NULL) {
- interest = (typeof(interest))inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService);
- assert(interest);
- interest->remove();
- inst->ivars->interestNotifiers->removeObject((const OSSymbol *) newService);
- }
- IOLockUnlock(inst->ivars->lock);
- break;
- default:
- break;
- }
- if (notifyReady && inst->ivars->action) {
- inst->ServiceNotificationReady(inst->ivars->action);
- }
- inst->release();
- return kIOReturnSuccess;
- });
- }
+ interest = newService->registerInterest(gIOGeneralInterest,
+ ^IOReturn (uint32_t messageType, IOService * provider,
+ void * messageArgument, size_t argSize) {
+ IONotifier * interest;
+ bool notifyReady = false;
+
+ switch (messageType) {
+ case kIOMessageServiceIsTerminated:
+ IOLockLock(inst->ivars->lock);
+ notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeTerminated]->getCount());
+ inst->ivars->pending[kIOServiceNotificationTypeTerminated]->setObject(provider);
+ interest = (typeof(interest))inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService);
+ assert(interest);
+ interest->remove();
+ inst->ivars->interestNotifiers->removeObject((const OSSymbol *) newService);
+ IOLockUnlock(inst->ivars->lock);
+ break;
+ default:
+ break;
+ }
+ if (notifyReady && inst->ivars->action) {
+ inst->ServiceNotificationReady(inst->ivars->action);
+ }
+ return kIOReturnSuccess;
+ });
if (interest) {
IOLockLock(inst->ivars->lock);
inst->ivars->interestNotifiers->setObject((const OSSymbol *) newService, interest);
@@ -1960,39 +1790,26 @@
IOServiceNotificationDispatchSource::free()
{
if (ivars) {
- if (ivars->notifier) {
- ivars->notifier->remove();
- ivars->notifier = NULL;
- }
+ OSSafeReleaseNULL(ivars->serverName);
if (ivars->interestNotifiers) {
- OSDictionary * savedInterestNotifiers = NULL;
-
- // the lock is always initialized first, so it should exist
- assert(ivars->lock);
-
- // Prevent additional changes to interestNotifiers
- IOLockLock(ivars->lock);
- savedInterestNotifiers = ivars->interestNotifiers;
- ivars->interestNotifiers = NULL;
- IOLockUnlock(ivars->lock);
-
- // Remove all interest notifiers
- savedInterestNotifiers->iterateObjects(^bool (const OSSymbol * key, OSObject * object) {
+ ivars->interestNotifiers->iterateObjects(^bool (const OSSymbol * key, OSObject * object) {
IONotifier * interest = (typeof(interest))object;
interest->remove();
return false;
});
- OSSafeReleaseNULL(savedInterestNotifiers);
+ OSSafeReleaseNULL(ivars->interestNotifiers);
}
for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) {
OSSafeReleaseNULL(ivars->pending[idx]);
}
- OSSafeReleaseNULL(ivars->action);
if (ivars->lock) {
IOLockFree(ivars->lock);
ivars->lock = NULL;
}
- OSSafeReleaseNULL(ivars->serverName);
+ if (ivars->notifier) {
+ ivars->notifier->remove();
+ ivars->notifier = NULL;
+ }
IOFreeType(ivars, IOServiceNotificationDispatchSource_IVars);
}
@@ -2182,7 +1999,6 @@
IOInterruptDispatchSourcePayload payload;
bool willWait;
- bool canceled;
wait_result_t waitResult;
thread_t self;
@@ -2200,40 +2016,31 @@
ivars = interrupt->ivars;
payload.count = 0;
do {
- willWait = false;
is = IOSimpleLockLockDisableInterrupt(ivars->lock);
- canceled = ivars->canceled;
- if (!canceled) {
- if ((payload.count = ivars->count)) {
- payload.time = ivars->time;
- ivars->count = 0;
- waitResult = THREAD_AWAKENED;
- } else {
- assert(NULL == ivars->waiter);
- ivars->waiter = self;
- waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
- }
- willWait = (waitResult == THREAD_WAITING);
- if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) {
- IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
- ivars->provider->enableInterrupt(ivars->intIndex);
- } else {
- IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
- }
+ if ((payload.count = ivars->count)) {
+ payload.time = ivars->time;
+ ivars->count = 0;
+ waitResult = THREAD_AWAKENED;
} else {
- IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
- }
+ assert(NULL == ivars->waiter);
+ ivars->waiter = self;
+ waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
+ }
+ willWait = (waitResult == THREAD_WAITING);
+ if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) {
+ ivars->provider->enableInterrupt(ivars->intIndex);
+ }
+ IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
if (willWait) {
waitResult = thread_block(THREAD_CONTINUE_NULL);
if (THREAD_INTERRUPTED == waitResult) {
is = IOSimpleLockLockDisableInterrupt(ivars->lock);
ivars->waiter = NULL;
IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
- canceled = true;
break;
}
}
- } while (!payload.count && !canceled);
+ } while (!payload.count);
ret = (payload.count ? kIOReturnSuccess : kIOReturnAborted);
}
@@ -2280,7 +2087,6 @@
if (kext) {
us->setTaskLoadTag(kext);
us->setDriverKitUUID(kext);
- us->setDriverKitStatistics(kext);
OSKext::OSKextLogDriverKitInfoLoad(kext);
OSSafeReleaseNULL(kext);
} else {
@@ -2308,21 +2114,6 @@
ret = kIOReturnSuccess;
return ret;
-}
-
-kern_return_t
-IOUserServer::Panic_Impl(const char * reason)
-{
- if (isPlatformDriver()) {
- if (strnlen(reason, kIOUserServrMaxPanicReasonLength) == kIOUserServrMaxPanicReasonLength) {
- // Invalid panic message, panic anyways
- panic("%s: dext requested panic", getName());
- } else {
- panic("%s: dext requested panic: \"%s\"", getName(), reason);
- }
- return kIOReturnSuccess;
- }
- return kIOReturnNotPermitted;
}
kern_return_t
@@ -2391,10 +2182,8 @@
if (MACH_PORT_NULL != ivars->serverPort) {
return kIOReturnNotReady;
}
- ivars->serverPort = ipc_port_copy_send_mqueue(port);
- if (ivars->serverPort == MACH_PORT_NULL) {
- return kIOReturnBadArgument;
- }
+
+ ivars->serverPort = port;
return kIOReturnSuccess;
}
@@ -2444,7 +2233,7 @@
IORPCMessage * message;
assert(rpc.sendSize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage)));
- message = rpc.kernelContent;
+ message = IORPCMessageFromMach(rpc.message, false);
if (!message) {
return kIOReturnIPCError;
}
@@ -2600,33 +2389,19 @@
}
uuid_unparse(p_uuid, uuid_string);
- new_uuid = OSData::withValue(p_uuid);
+ new_uuid = OSData::withBytes(p_uuid, sizeof(p_uuid));
kext->setDriverKitUUID(new_uuid);
}
void
-IOUserServer::setDriverKitStatistics(OSKext *kext)
-{
- OSDextStatistics * statistics = kext->copyDextStatistics();
- if (statistics == NULL) {
- panic("Kext %s was not a DriverKit OSKext", kext->getIdentifierCString());
- }
- fStatistics = statistics;
-}
-
-IOReturn
IOUserServer::setCheckInToken(IOUserServerCheckInToken *token)
{
- IOReturn ret = kIOReturnError;
if (token != NULL && fCheckInToken == NULL) {
token->retain();
fCheckInToken = token;
- ret = fCheckInToken->complete();
- iokit_clear_registered_ports(fOwningTask);
} else {
printf("%s: failed to set check in token. token=%p, fCheckInToken=%p\n", __FUNCTION__, token, fCheckInToken);
}
- return ret;
}
bool
@@ -2634,6 +2409,9 @@
{
if (token != NULL) {
bool result = token == fCheckInToken;
+ if (result) {
+ fCheckInToken->complete();
+ }
return result;
} else {
printf("%s: null check in token\n", __FUNCTION__);
@@ -2671,7 +2449,7 @@
}
}
- bool allPresent __block = false;
+ bool allPresent __block;
prop->iterateObjects(^bool (OSObject * object) {
allPresent = false;
object->iterateObjects(^bool (OSObject * object) {
@@ -2701,12 +2479,6 @@
}
bool
-IOUserServer::checkEntitlements(OSObject * prop, IOService * provider, IOService * dext)
-{
- return checkEntitlements(fEntitlements, prop, provider, dext);
-}
-
-bool
IOUserServer::checkEntitlements(IOService * provider, IOService * dext)
{
OSObject * prop;
@@ -2735,40 +2507,9 @@
IOReturn
IOUserServer::exit(const char * reason)
{
- DKLOG(DKS "::exit(%s)\n", DKN(this), reason);
+ DKLOG("%s::exit(%s)\n", getName(), reason);
Exit(reason);
return kIOReturnSuccess;
-}
-
-IOReturn
-IOUserServer::kill(const char * reason)
-{
- IOReturn ret = kIOReturnError;
- if (fOwningTask != NULL) {
- DKLOG(DKS"::kill(%s)\n", DKN(this), reason);
- proc_t unsafe_proc = (proc_t)get_bsdtask_info(fOwningTask);
- proc_t p = proc_ref_nowait(unsafe_proc);
- if (p) {
- taskbsd_kill_and_release(p);
- }
- ret = kIOReturnSuccess;
- }
- return ret;
-}
-
-void
-IOUserServer::emergencyPanicCoreDumpEnable()
-{
-#if DEVELOPMENT || DEBUG
- if (isPlatformDriver()) {
- // Enable coredump for the first party dext that is causing an imminent panic
- // This is enabled on non-release without requiring an entitlement,
- // so this coredump has only a generic name
- char core_name[MACH_CORE_FILEHEADER_NAMELEN];
- snprintf(core_name, sizeof(core_name), "dext-%d", pid_from_task(fOwningTask));
- kern_register_userspace_coredump(fOwningTask, core_name, TRUE);
- }
-#endif /* DEVELOPMENT || DEBUG */
}
OSObjectUserVars *
@@ -2789,8 +2530,8 @@
IOPStrings * array;
vm_size_t alloc;
size_t len;
+ const char * cstr;
const char * end;
- OSBoundedPtr<const char> cstr;
if (userSize <= 1) {
return NULL;
@@ -2812,8 +2553,8 @@
bcopy(string, (void *) &array->strings[0], userSize);
array->count = 0;
+ cstr = &array->strings[0];
end = &array->strings[array->dataSize];
- cstr = OSBoundedPtr<const char>(&array->strings[0], &array->strings[0], end);
while ((len = (unsigned char)cstr[0])) {
cstr++;
if ((cstr + len) >= end) {
@@ -2835,20 +2576,19 @@
{
uint32_t idx;
size_t len, llen;
- OSBoundedPtr<const char> cstr;
+ const char * cstr;
const char * end;
idx = 0;
+ cstr = &array->strings[0];
end = &array->strings[array->dataSize];
- cstr = OSBoundedPtr<const char>(&array->strings[0], &array->strings[0], end);
-
llen = strlen(look);
while ((len = (unsigned char)cstr[0])) {
cstr++;
if ((cstr + len) >= end) {
break;
}
- if ((len == llen) && !strncmp(cstr.discard_bounds(), look, len)) {
+ if ((len == llen) && !strncmp(cstr, look, len)) {
return idx;
}
cstr += len;
@@ -2925,10 +2665,9 @@
OSObjectUserVars * uvars;
uint32_t idx;
ipc_port_t sendPort;
- bool serviceInactive;
OSObject_Instantiate_Rpl_Content * reply;
- IODispatchQueue ** unboundedQueueArray = NULL;
+
queueCount = 0;
methodCount = 0;
methods = NULL;
@@ -2946,14 +2685,7 @@
resultFlags |= kOSObjectRPCKernel;
resultFlags |= kOSObjectRPCRemote;
} else {
- serviceInactive = false;
- if (service->lockForArbitration()) {
- if (service->isInactive() && (service->__state[1] & kIOServiceStartState) == 0) {
- serviceInactive = true;
- }
- service->unlockForArbitration();
- }
- if (serviceInactive) {
+ if (service->isInactive()) {
DKLOG(DKS "::instantiate inactive\n", DKN(service));
return kIOReturnOffline;
}
@@ -2973,7 +2705,6 @@
return kIOReturnError;
}
IOLockLock(service->reserved->uvars->userServer->fLock);
- service->reserved->uvars->instantiated = true;
userMeta = (typeof(userMeta))service->reserved->uvars->userServer->fClasses->getObject(str);
IOLockUnlock(service->reserved->uvars->userServer->fLock);
}
@@ -3024,9 +2755,8 @@
if (userMeta->queueNames) {
queueAlloc += userMeta->queueNames->count;
}
- unboundedQueueArray = IONewZero(IODispatchQueue *, queueAlloc);
service->reserved->uvars->queueArray =
- OSBoundedArrayRef<IODispatchQueue *>(unboundedQueueArray, queueAlloc);
+ IONewZero(IODispatchQueue *, queueAlloc);
resultClassName = str->getCStringNoCopy();
ret = kIOReturnSuccess;
}
@@ -3062,7 +2792,7 @@
idx = 0;
sendPort = NULL;
if (queue && (kIODispatchQueueStopped != queue)) {
- sendPort = ipc_port_copy_send_mqueue(queue->ivars->serverPort);
+ sendPort = ipc_port_copy_send(queue->ivars->serverPort);
}
replySize = sizeof(OSObject_Instantiate_Rpl)
+ queueCount * sizeof(machReply->objects[0])
@@ -3098,7 +2828,7 @@
queue = uvars->queueArray[idx];
sendPort = NULL;
if (queue) {
- sendPort = ipc_port_copy_send_mqueue(queue->ivars->serverPort);
+ sendPort = ipc_port_copy_send(queue->ivars->serverPort);
}
machReply->objects[idx].type = MACH_MSG_PORT_DESCRIPTOR;
machReply->objects[idx].disposition = MACH_MSG_TYPE_MOVE_SEND;
@@ -3123,7 +2853,7 @@
machReply->msgh.msgh_size = replySize;
machReply->msgh_body.msgh_descriptor_count = queueCount;
- reply = (typeof(reply))IORPCMessageFromMachReply(machReply);
+ reply = (typeof(reply))IORPCMessageFromMach(machReply, true);
if (!reply) {
return kIOReturnIPCError;
}
@@ -3151,7 +2881,7 @@
IOReturn ret;
IORPCMessage * message;
- message = rpc.kernelContent;
+ message = IORPCMessageFromMach(rpc.message, false);
if (!message) {
return kIOReturnIPCError;
}
@@ -3159,15 +2889,15 @@
if (OSObject_Instantiate_ID == message->msgid) {
ret = objectInstantiate(obj, rpc, message);
if (kIOReturnSuccess != ret) {
- DKLOG(DKS ": %s: instantiate failed 0x%x\n", DKN(this), obj->getMetaClass()->getClassName(), ret);
+ DKLOG("%s: instantiate failed 0x%x\n", obj->getMetaClass()->getClassName(), ret);
}
} else {
if (kIODKLogIPC & gIODKDebug) {
- DKLOG(DKS ": %s::Dispatch kernel 0x%qx\n", DKN(this), obj->getMetaClass()->getClassName(), message->msgid);
+ DKLOG("%s::Dispatch kernel 0x%qx\n", obj->getMetaClass()->getClassName(), message->msgid);
}
ret = obj->Dispatch(rpc);
if (kIODKLogIPC & gIODKDebug) {
- DKLOG(DKS ": %s::Dispatch kernel 0x%qx result 0x%x\n", DKN(this), obj->getMetaClass()->getClassName(), message->msgid, ret);
+ DKLOG("%s::Dispatch kernel 0x%qx result 0x%x\n", obj->getMetaClass()->getClassName(), message->msgid, ret);
}
}
@@ -3214,8 +2944,11 @@
uext_server(ipc_port_t receiver, ipc_kmsg_t requestkmsg, ipc_kmsg_t * pReply)
{
kern_return_t ret;
+ IORPCMessageMach * msgin;
OSObject * object;
IOUserServer * server;
+
+ msgin = (typeof(msgin))ipc_kmsg_msg_header(requestkmsg);
object = IOUserServer::copyObjectForSendRight(receiver, IKOT_UEXT_OBJECT);
server = OSDynamicCast(IOUserServer, object);
@@ -3223,10 +2956,7 @@
OSSafeReleaseNULL(object);
return KERN_INVALID_NAME;
}
-
- IORPCMessage * message = (typeof(message))ikm_udata_from_header(requestkmsg);
-
- ret = server->server(requestkmsg, message, pReply);
+ ret = server->server(requestkmsg, pReply);
object->release();
return ret;
@@ -3240,12 +2970,13 @@
static_assert(MAX_UEXT_REPLY_SIZE + MAX_TRAILER_SIZE <= KALLOC_SAFE_ALLOC_SIZE);
kern_return_t
-IOUserServer::server(ipc_kmsg_t requestkmsg, IORPCMessage * message, ipc_kmsg_t * pReply)
+IOUserServer::server(ipc_kmsg_t requestkmsg, ipc_kmsg_t * pReply)
{
kern_return_t ret;
mach_msg_size_t replyAlloc;
ipc_kmsg_t replykmsg;
IORPCMessageMach * msgin;
+ IORPCMessage * message;
IORPCMessageMach * msgout;
IORPCMessage * reply;
uint32_t replySize;
@@ -3254,7 +2985,7 @@
bool oneway;
uint64_t msgid;
- msgin = (typeof(msgin))ikm_header(requestkmsg);
+ msgin = (typeof(msgin))ipc_kmsg_msg_header(requestkmsg);
replyAlloc = 0;
msgout = NULL;
replykmsg = NULL;
@@ -3269,6 +3000,7 @@
if (!(MACH_MSGH_BITS_COMPLEX & msgin->msgh.msgh_bits)) {
msgin->msgh_body.msgh_descriptor_count = 0;
}
+ message = IORPCMessageFromMach(msgin, false);
if (!message) {
return kIOReturnIPCError;
}
@@ -3280,9 +3012,6 @@
if (kIODKLogIPC & gIODKDebug) {
DKLOG("UEXT copyin(0x%x) %x\n", ret, msgin->msgh.msgh_id);
}
- // release objects and ports
- consumeObjects(msgin, message, msgin->msgh.msgh_size);
- copyInObjects(msgin, message, msgin->msgh.msgh_size, false, true);
return KERN_NOT_SUPPORTED;
}
@@ -3303,22 +3032,18 @@
assert(oneway || (MACH_PORT_NULL != msgin->msgh.msgh_local_port));
replyAlloc = oneway ? 0 : MAX_UEXT_REPLY_SIZE;
-
-
-
-
if (replyAlloc) {
/*
* Same as:
- * ipc_kmsg_alloc(MAX_UEXT_REPLY_SIZE_MACH, MAX_UEXT_REPLY_SIZE_MESSAGE,
- * IPC_KMSG_ALLOC_KERNEL | IPC_KMSG_ALLOC_ZERO | IPC_KMSG_ALLOC_LINEAR |
+ * ipc_kmsg_alloc(replyAlloc, 0,
+ * IPC_KMSG_ALLOC_KERNEL | IPC_KMSG_ALLOC_ZERO |
* IPC_KMSG_ALLOC_NOFAIL);
*/
- replykmsg = ipc_kmsg_alloc_uext_reply(MAX_UEXT_REPLY_SIZE);
- msgout = (typeof(msgout))ikm_header(replykmsg);
- }
-
- IORPC rpc = { .message = msgin, .reply = msgout, .sendSize = msgin->msgh.msgh_size, .replySize = replyAlloc, .kernelContent = message };
+ replykmsg = ipc_kmsg_alloc_uext_reply(replyAlloc);
+ msgout = (typeof(msgout))ipc_kmsg_msg_header(replykmsg);
+ }
+
+ IORPC rpc = { .message = msgin, .reply = msgout, .sendSize = msgin->msgh.msgh_size, .replySize = replyAlloc };
if (object) {
kern_allocation_name_t prior;
@@ -3339,7 +3064,7 @@
}
// release objects
- consumeObjects(msgin, message, msgin->msgh.msgh_size);
+ consumeObjects(message, msgin->msgh.msgh_size);
// release ports
copyInObjects(msgin, message, msgin->msgh.msgh_size, false, true);
@@ -3347,7 +3072,7 @@
if (!oneway) {
if (kIOReturnSuccess == ret) {
replySize = msgout->msgh.msgh_size;
- reply = IORPCMessageFromMachReply(msgout);
+ reply = IORPCMessageFromMach(msgout, true);
if (!reply) {
ret = kIOReturnIPCError;
} else {
@@ -3359,7 +3084,7 @@
msgout->msgh_body.msgh_descriptor_count = 0;
msgout->msgh.msgh_id = kIORPCVersionCurrentReply;
- errorMsg = (typeof(errorMsg))IORPCMessageFromMachReply(msgout);
+ errorMsg = (typeof(errorMsg))IORPCMessageFromMach(msgout, true);
errorMsg->hdr.msgid = message->msgid;
errorMsg->hdr.flags = kIORPCMessageOneway | kIORPCMessageError;
errorMsg->hdr.objectRefs = 0;
@@ -3384,31 +3109,8 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-static inline uint32_t
-MAX_OBJECT_COUNT(IORPCMessageMach *mach, size_t size, IORPCMessage *message __unused)
-{
- assert(mach->msgh.msgh_size == size);
- size_t used_size;
- size_t remaining_size;
- if (os_mul_and_add_overflow(
- mach->msgh_body.msgh_descriptor_count,
- sizeof(mach_msg_port_descriptor_t),
- sizeof(mach->msgh) + sizeof(mach->msgh_body) + offsetof(IORPCMessage, objects[0]),
- &used_size)) {
- return 0;
- }
- if (os_sub_overflow(size, used_size, &remaining_size)) {
- return 0;
- }
- return (uint32_t)(remaining_size / sizeof(OSObjectRef));
-}
-
-#pragma pack(push, 4)
-struct UEXTTrapReply {
- uint64_t replySize;
- IORPCMessage replyMessage;
-};
-#pragma pack(pop)
+#define MAX_OBJECT_COUNT(mach, size, message) \
+ ((uint32_t)(((((size) + ((uintptr_t) (mach))) - ((uintptr_t) (&message->objects[0]))) / sizeof(OSObjectRef))))
kern_return_t
IOUserServerUEXTTrap(OSObject * object, void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
@@ -3442,7 +3144,7 @@
uint64_t refs;
uint32_t maxObjectCount;
size_t copySize;
- UEXTTrapReply * replyHdr;
+ uint64_t * replyHdr;
uintptr_t p;
bzero(&buffer, sizeof(buffer));
@@ -3470,7 +3172,6 @@
if (!(kIORPCMessageSimpleReply & message->flags)) {
return kIOReturnUnsupported;
}
- message->flags &= ~(kIORPCMessageKernel | kIORPCMessageRemote);
descs = (typeof(descs))(p - refs * sizeof(*descs));
mach = (typeof(mach))(p - refs * sizeof(*descs) - sizeof(*mach));
@@ -3483,16 +3184,11 @@
rpc.sendSize = mach->msgh.msgh_size;
rpc.reply = (IORPCMessageMach *) (p + inSize);
rpc.replySize = ((uint32_t) (sizeof(buffer.buffer) - inSize)); // inSize was checked
- rpc.kernelContent = message;
message->objects[0] = 0;
if ((action = OSDynamicCast(OSAction, object))) {
maxObjectCount = MAX_OBJECT_COUNT(rpc.message, rpc.sendSize, message);
if (refs > maxObjectCount) {
- return kIOReturnBadArgument;
- }
- if (refs < 2) {
- DKLOG("invalid refs count %qd in message id 0x%qx\n", refs, message->msgid);
return kIOReturnBadArgument;
}
object = IOUserServer::target(action, message);
@@ -3525,7 +3221,7 @@
if (rpc.reply->msgh_body.msgh_descriptor_count) {
return kIOReturnIPCError;
}
- reply = IORPCMessageFromMachReply(rpc.reply);
+ reply = IORPCMessageFromMach(rpc.reply, rpc.reply->msgh.msgh_size);
if (!reply) {
return kIOReturnIPCError;
}
@@ -3533,8 +3229,9 @@
if (copySize > outSize) {
return kIOReturnIPCError;
}
- replyHdr = (UEXTTrapReply *) ((uintptr_t)reply - sizeof(uint64_t));
- replyHdr->replySize = copySize;
+ replyHdr = (uint64_t *) reply;
+ replyHdr--;
+ replyHdr[0] = copySize;
copyerr = copyout(replyHdr, out, copySize);
if (copyerr) {
return kIOReturnVMError;
@@ -3576,7 +3273,7 @@
assert(sendSize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage)));
- message = rpc.kernelContent;
+ message = IORPCMessageFromMach(mach, false);
if (!message) {
return kIOReturnIPCError;
}
@@ -3598,7 +3295,7 @@
port = queue->ivars->serverPort;
}
if (port) {
- sendPort = ipc_port_copy_send_mqueue(port);
+ sendPort = ipc_port_copy_send(port);
}
IOLockUnlock(gIOUserServerLock);
if (!sendPort) {
@@ -3620,7 +3317,8 @@
if (oneway) {
ret = kernel_mach_msg_send(&mach->msgh, sendSize,
- MACH_SEND_KERNEL_DEFAULT, 0, &message_moved);
+ MACH_SEND_MSG | MACH_SEND_ALWAYS | MACH_SEND_NOIMPORTANCE,
+ 0, &message_moved);
} else {
assert(replySize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage)));
ret = kernel_mach_msg_rpc(&mach->msgh, sendSize, replySize, FALSE, &message_moved);
@@ -3648,7 +3346,7 @@
if (!(MACH_MSGH_BITS_COMPLEX & mach->msgh.msgh_bits)) {
mach->msgh_body.msgh_descriptor_count = 0;
}
- message = IORPCMessageFromMachReply(mach);
+ message = IORPCMessageFromMach(mach, true);
if (!message) {
ret = kIOReturnIPCError;
} else if (message->msgid != msgid) {
@@ -3661,10 +3359,6 @@
if (kIODKLogIPC & gIODKDebug) {
DKLOG("rpc copyin(0x%x) %x\n", ret, mach->msgh.msgh_id);
}
- if (!isError) {
- consumeObjects(mach, message, replySize);
- copyInObjects(mach, message, replySize, false, true);
- }
return KERN_NOT_SUPPORTED;
}
if (isError) {
@@ -3680,15 +3374,14 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-static IORPCMessage *
-IORPCMessageFromMachReply(IORPCMessageMach * msg)
+IORPCMessage *
+IORPCMessageFromMach(IORPCMessageMach * msg, bool reply)
{
mach_msg_size_t idx, count;
mach_msg_port_descriptor_t * desc;
mach_msg_port_descriptor_t * maxDesc;
size_t size, msgsize;
bool upgrade;
- bool reply = true;
msgsize = msg->msgh.msgh_size;
count = msg->msgh_body.msgh_descriptor_count;
@@ -3723,13 +3416,24 @@
ipc_port_t
IOUserServer::copySendRightForObject(OSObject * object, ipc_kobject_type_t type)
{
- return iokit_port_make_send_for_object(object, type);
+ ipc_port_t port;
+ ipc_port_t sendPort = NULL;
+
+ port = iokit_port_for_object(object, type);
+ if (port) {
+ sendPort = ipc_port_make_send(port);
+ iokit_release_port(port);
+ }
+
+ return sendPort;
}
OSObject *
IOUserServer::copyObjectForSendRight(ipc_port_t port, ipc_kobject_type_t type)
{
- return iokit_lookup_io_object(port, type);
+ OSObject * object;
+ object = iokit_lookup_io_object(port, type);
+ return object;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -3793,15 +3497,6 @@
descsize = sizeof(mach_msg_port_descriptor_t);
port = NULL;
if (object) {
-#if DEVELOPMENT || DEBUG
- if (kIODKLogIPC & gIODKDebug) {
- IOMemoryDescriptor * iomd = OSDynamicCast(IOMemoryDescriptor, object);
- if (iomd != NULL && (iomd->getFlags() & kIOMemoryThreadSafe) == 0) {
- OSReportWithBacktrace("IOMemoryDescriptor %p was created without kIOMemoryThreadSafe flag", iomd);
- }
- }
-#endif /* DEVELOPMENT || DEBUG */
-
port = copySendRightForObject(object, IKOT_UEXT_OBJECT);
if (!port) {
break;
@@ -3929,14 +3624,8 @@
return kIOReturnBadArgument;
}
+ desc = &mach->objects[0];
for (idx = 0; idx < refs; idx++) {
- message->objects[idx] = (OSObjectRef) NULL;
- }
-
- desc = &mach->objects[0];
- for (idx = 0; idx < mach->msgh_body.msgh_descriptor_count; idx++) {
- bool isObjectPort = idx < refs;
-
switch (desc->type) {
case MACH_MSG_PORT_DESCRIPTOR:
descsize = sizeof(mach_msg_port_descriptor_t);
@@ -3944,7 +3633,7 @@
object = NULL;
port = desc->name;
if (port) {
- if (isObjectPort && copyObjects) {
+ if (copyObjects) {
object = copyObjectForSendRight(port, IKOT_UEXT_OBJECT);
if (!object) {
descsize = -1UL;
@@ -3953,7 +3642,6 @@
}
if (consumePorts) {
ipc_port_release_send(port);
- desc->name = MACH_PORT_NULL;
}
}
break;
@@ -3963,7 +3651,7 @@
ool = (typeof(ool))desc;
object = NULL;
- if (isObjectPort && copyObjects && ool->size && ool->address) {
+ if (copyObjects && ool->size && ool->address) {
kr = vm_map_copyout(kernel_map, ©outdata, (vm_map_copy_t) ool->address);
if (KERN_SUCCESS == kr) {
object = OSUnserializeXML((const char *) copyoutdata, ool->size);
@@ -3987,7 +3675,7 @@
if (-1UL == descsize) {
break;
}
- if (isObjectPort && copyObjects) {
+ if (copyObjects) {
message->objects[idx] = (OSObjectRef) object;
}
desc = (typeof(desc))(((uintptr_t) desc) + descsize);
@@ -3999,7 +3687,7 @@
while (idx--) {
object = (OSObject *) message->objects[idx];
- OSSafeReleaseNULL(object);
+ object->release();
message->objects[idx] = 0;
}
@@ -4007,20 +3695,12 @@
}
IOReturn
-IOUserServer::consumeObjects(IORPCMessageMach *mach, IORPCMessage * message, size_t messageSize)
+IOUserServer::consumeObjects(IORPCMessage * message, size_t messageSize)
{
uint64_t refs, idx;
OSObject * object;
refs = message->objectRefs;
- uint32_t maxObjectCount = MAX_OBJECT_COUNT(mach, messageSize, message);
- if (refs > mach->msgh_body.msgh_descriptor_count) {
- return kIOReturnBadArgument;
- }
- if (refs > maxObjectCount) {
- return kIOReturnBadArgument;
- }
-
for (idx = 0; idx < refs; idx++) {
object = (OSObject *) message->objects[idx];
if (object) {
@@ -4034,16 +3714,13 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-static kern_return_t
-acknowledgeSetPowerState(IOService * service);
-
bool
IOUserServer::finalize(IOOptionBits options)
{
OSArray * services;
if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::finalize(%p)\n", DKN(this), this);
+ DKLOG("%s::finalize(%p)\n", getName(), this);
}
IOLockLock(gIOUserServerLock);
@@ -4056,19 +3733,6 @@
services = OSArray::withArray(fServices);
}
IOLockUnlock(fLock);
-
- IOOptionBits terminateFlags = kIOServiceTerminateNeedWillTerminate | kIOServiceTerminateWithRematch;
- if (fCheckInToken) {
- bool can_rematch = fCheckInToken->dextTerminate();
- if (can_rematch) {
- terminateFlags |= kIOServiceTerminateWithRematchCurrentDext;
- } else {
- DKLOG(DKS "::finalize(%p) dext was replaced, do not rematch current dext\n", DKN(this), this);
- }
- } else {
- terminateFlags |= kIOServiceTerminateWithRematchCurrentDext;
- DKLOG(DKS "::finalize(%p) could not find fCheckInToken\n", DKN(this), this);
- }
if (services) {
services->iterateObjects(^bool (OSObject * obj) {
@@ -4076,44 +3740,24 @@
IOService * nextService;
IOService * provider;
bool started = false;
- bool instantiated = false;
nextService = (IOService *) obj;
if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::terminate(" DKS ")\n", DKN(this), DKN(nextService));
+ DKLOG("%s::terminate(" DKS ")\n", getName(), DKN(nextService));
}
if (nextService->reserved->uvars) {
- IOUserClient * nextUserClient = OSDynamicCast(IOUserClient, nextService);
- provider = nextService->getProvider();
- if (nextUserClient) {
- nextUserClient->setTerminateDefer(provider, false);
+ started = nextService->reserved->uvars->started;
+ nextService->reserved->uvars->serverDied = true;
+ if (started) {
+ provider = nextService->getProvider();
+ serviceDidStop(nextService, provider);
+ nextService->terminate(kIOServiceTerminateNeedWillTerminate
+ | kIOServiceTerminateWithRematch
+ | kIOServiceTerminateWithRematchCurrentDext);
}
- (void)::acknowledgeSetPowerState(nextService);
- started = nextService->reserved->uvars->started;
- instantiated = nextService->reserved->uvars->instantiated;
- nextService->reserved->uvars->serverDied = true;
-
- serviceDidStop(nextService, provider);
- if (provider != NULL && (terminateFlags & kIOServiceTerminateWithRematchCurrentDext) == 0) {
- provider->resetRematchProperties();
- }
- if (started) {
- IOService * provider = nextService;
- while ((provider = provider->getProvider())) {
- if (-1U != services->getNextIndexOfObject(provider, 0)) {
- break;
- }
- }
- if (!provider) {
- // this service is the root of the set, so only terminate it
- nextService->terminate(terminateFlags);
- }
- }
- }
- if (!started || !instantiated) {
- DKLOG(DKS "::terminate(" DKS ") server exit before start() instantiated %d\n", DKN(this), DKN(nextService), instantiated);
- // Override started since we are forcing serviceStop to happen
- nextService->reserved->uvars->started = true;
+ }
+ if (!started) {
+ DKLOG("%s::terminate(" DKS ") server exit before start()\n", getName(), DKN(nextService));
serviceStop(nextService, NULL);
}
return false;
@@ -4127,9 +3771,9 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#undef super
-#define super IOUserClient2022
-
-OSDefineMetaClassAndStructors(IOUserServer, IOUserClient2022)
+#define super IOUserClient
+
+OSDefineMetaClassAndStructors(IOUserServer, IOUserClient)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -4149,43 +3793,21 @@
inst = NULL;
return inst;
}
- OS_ANALYZER_SUPPRESS("82033761") inst->PMinit();
+ inst->PMinit();
inst->fOwningTask = current_task();
- task_reference(inst->fOwningTask);
-
inst->fEntitlements = IOUserClient::copyClientEntitlements(inst->fOwningTask);
if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
- proc_t p;
- pid_t pid;
- const char * name;
- p = (proc_t)get_bsdtask_info(inst->fOwningTask);
- if (p) {
- name = proc_best_name(p);
- pid = proc_pid(p);
- } else {
- name = "unknown";
- pid = 0;
- }
-
- if (inst->fEntitlements == NULL) {
-#if DEVELOPMENT || DEBUG
- panic("entitlements are missing for %s[%d]\n", name, pid);
-#else
- DKLOG("entitlements are missing for %s[%d]\n", name, pid);
-#endif /* DEVELOPMENT || DEBUG */
- }
-
-
- const char * dextTeamID = csproc_get_teamid(p);
- if (dextTeamID != NULL) {
- inst->fTeamIdentifier = OSString::withCString(dextTeamID);
- DKLOG("%s[%d] has team identifier %s\n", name, pid, dextTeamID);
- }
-
if (!IOCurrentTaskHasEntitlement(gIODriverKitEntitlementKey->getCStringNoCopy())) {
- IOLog(kIODriverKitEntitlementKey " entitlement check failed for %s[%d]\n", name, pid);
+ proc_t p;
+ pid_t pid;
+
+ p = (proc_t)get_bsdtask_info(inst->fOwningTask);
+ if (p) {
+ pid = proc_pid(p);
+ IOLog(kIODriverKitEntitlementKey " entitlement check failed for %s[%d]\n", proc_best_name(p), pid);
+ }
inst->release();
inst = NULL;
return inst;
@@ -4199,89 +3821,19 @@
inst->fServices = OSArray::withCapacity(4);
inst->fClasses = OSDictionary::withCapacity(16);
inst->fClasses->setOptions(OSCollection::kSort, OSCollection::kSort);
- inst->fPlatformDriver = task_get_platform_binary(inst->fOwningTask);
- if (csproc_get_validation_category(current_proc(), &inst->fCSValidationCategory) != KERN_SUCCESS) {
- inst->fCSValidationCategory = CS_VALIDATION_CATEGORY_INVALID;
- }
- inst->fWorkLoop = IOWorkLoop::workLoop();
-
- inst->setProperty(kIOUserClientDefaultLockingKey, kOSBooleanTrue);
- inst->setProperty(kIOUserClientDefaultLockingSetPropertiesKey, kOSBooleanTrue);
- inst->setProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey, kOSBooleanTrue);
- //requirement for gIODriverKitEntitlementKey is enforced elsewhere conditionally
- inst->setProperty(kIOUserClientEntitlementsKey, kOSBooleanFalse);
return inst;
-}
-
-static bool gIOUserServerLeakObjects = false;
-
-bool
-IOUserServer::shouldLeakObjects()
-{
- return gIOUserServerLeakObjects;
-}
-
-void
-IOUserServer::beginLeakingObjects()
-{
- gIOUserServerLeakObjects = true;
-}
-
-bool
-IOUserServer::isPlatformDriver()
-{
- return fPlatformDriver;
-}
-
-int
-IOUserServer::getCSValidationCategory()
-{
- return fCSValidationCategory;
-}
-
-
-struct IOUserServerRecordExitReasonContext {
- task_t task;
- os_reason_t reason;
-};
-
-static bool
-IOUserServerRecordExitReasonMatch(const OSObject *obj, void * context)
-{
- IOUserServerRecordExitReasonContext * ctx = (IOUserServerRecordExitReasonContext *)context;
- IOUserServer * us = OSDynamicCast(IOUserServer, obj);
- if (us == NULL) {
- return false;
- }
-
- if (us->fOwningTask == ctx->task) {
- assert(us->fTaskCrashReason == OS_REASON_NULL);
- assert(ctx->reason != OS_REASON_NULL);
- os_reason_ref(ctx->reason);
- us->fTaskCrashReason = ctx->reason;
- return true;
- }
-
- return false;
-}
-
-extern "C" void
-IOUserServerRecordExitReason(task_t task, os_reason_t reason)
-{
- IOUserServerRecordExitReasonContext ctx { task, reason };
- IOUserServer::gMetaClass.applyToInstances(IOUserServerRecordExitReasonMatch, &ctx);
}
IOReturn
IOUserServer::clientClose(void)
{
OSArray * services;
- bool __block unexpectedExit = false;
if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::clientClose(%p)\n", DKN(this), this);
- }
+ DKLOG("%s::clientClose(%p)\n", getName(), this);
+ }
+
services = NULL;
IOLockLock(fLock);
if (fServices) {
@@ -4302,18 +3854,12 @@
if (nextService->isInactive()) {
return false;
}
- if (nextService->reserved && nextService->reserved->uvars && nextService->reserved->uvars->started) {
- unexpectedExit = true;
- }
provider = nextService->getProvider();
if (provider
&& (!provider->reserved->uvars || (provider->reserved->uvars->userServer != this))) {
if (kIODKLogSetup & gIODKDebug) {
DKLOG(DKS "::ClientCrashed(" DKS ")\n", DKN(provider), DKN(nextService));
}
- if (unexpectedExit) {
- provider->unregisterAllInterrupts();
- }
provider->ClientCrashed(nextService, 0);
}
return false;
@@ -4321,30 +3867,6 @@
services->release();
}
- if (unexpectedExit &&
- !gInUserspaceReboot &&
- (fTaskCrashReason != OS_REASON_NULL && fTaskCrashReason->osr_namespace != OS_REASON_JETSAM && fTaskCrashReason->osr_namespace != OS_REASON_RUNNINGBOARD) &&
- fStatistics != NULL) {
- OSDextCrashPolicy policy = fStatistics->recordCrash();
- bool allowPanic;
-#if DEVELOPMENT || DEBUG
- allowPanic = !restore_boot && fPlatformDriver && fEntitlements->getObject(gIODriverKitTestDriverEntitlementKey) != kOSBooleanTrue && !disable_dext_crash_reboot;
-#else
- allowPanic = !restore_boot && fPlatformDriver;
-#endif /* DEVELOPMENT || DEBUG */
-
- if (policy == kOSDextCrashPolicyReboot && allowPanic) {
- emergencyPanicCoreDumpEnable();
- panic("Driver %s has crashed too many times (reason %u:%llu)\n",
- getName(), fTaskCrashReason->osr_namespace, fTaskCrashReason->osr_code);
- }
-
- IOPMrootDomain *rootDomain = IOService::getPMRootDomain();
- if (rootDomain) {
- rootDomain->requestRunMode(kIOPMRunModeFullWake);
- }
- }
-
terminate();
return kIOReturnSuccess;
}
@@ -4359,10 +3881,7 @@
void
IOUserServer::stop(IOService * provider)
{
- if (fOwningTask) {
- task_deallocate(fOwningTask);
- fOwningTask = TASK_NULL;
- }
+ fOwningTask = TASK_NULL;
PMstop();
@@ -4375,36 +3894,20 @@
}
}
-IOWorkLoop *
-IOUserServer::getWorkLoop() const
-{
- return fWorkLoop;
-}
-
void
IOUserServer::free()
{
OSSafeReleaseNULL(fEntitlements);
OSSafeReleaseNULL(fClasses);
- if (fOwningTask) {
- task_deallocate(fOwningTask);
- fOwningTask = TASK_NULL;
- }
if (fLock) {
IOLockFree(fLock);
}
OSSafeReleaseNULL(fServices);
OSSafeReleaseNULL(fCheckInToken);
- OSSafeReleaseNULL(fStatistics);
- OSSafeReleaseNULL(fTeamIdentifier);
if (fAllocationName) {
kern_allocation_name_release(fAllocationName);
fAllocationName = NULL;
}
- if (fTaskCrashReason != OS_REASON_NULL) {
- os_reason_free(fTaskCrashReason);
- }
- OSSafeReleaseNULL(fWorkLoop);
IOUserClient::free();
}
@@ -4424,7 +3927,7 @@
}
if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::registerClass %s, %d, %d\n", DKN(this), desc->name, desc->queueNamesSize, desc->methodNamesSize);
+ DKLOG("%s::registerClass %s, %d, %d\n", getName(), desc->name, desc->queueNamesSize, desc->methodNamesSize);
}
if (desc->descriptionSize != size) {
@@ -4551,91 +4054,72 @@
return kIOReturnSuccess;
}
-
IOReturn
-IOUserServer::externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * args)
-{
- static const IOExternalMethodDispatch2022 dispatchArray[] = {
- [kIOUserServerMethodRegisterClass] = {
- .function = &IOUserServer::externalMethodRegisterClass,
- .checkScalarInputCount = 0,
- .checkStructureInputSize = kIOUCVariableStructureSize,
- .checkScalarOutputCount = 2,
- .checkStructureOutputSize = 0,
- .allowAsync = false,
- .checkEntitlement = NULL,
- },
- [kIOUserServerMethodStart] = {
- .function = &IOUserServer::externalMethodStart,
- .checkScalarInputCount = 1,
- .checkStructureInputSize = 0,
- .checkScalarOutputCount = 1,
- .checkStructureOutputSize = 0,
- .allowAsync = false,
- .checkEntitlement = NULL,
- },
- };
-
- return dispatchExternalMethod(selector, args, dispatchArray, sizeof(dispatchArray) / sizeof(dispatchArray[0]), this, NULL);
-}
-
-IOReturn
-IOUserServer::externalMethodRegisterClass(OSObject * target, void * reference, IOExternalMethodArguments * args)
+IOUserServer::externalMethod(uint32_t selector, IOExternalMethodArguments * args,
+ IOExternalMethodDispatch * dispatch, OSObject * target, void * reference)
{
IOReturn ret = kIOReturnBadArgument;
mach_port_name_t portname;
- IOUserServer * me = (typeof(me))target;
-
- OSUserMetaClass * cls;
- if (!args->structureInputSize) {
- return kIOReturnBadArgument;
- }
-
- ret = me->registerClass((OSClassDescription *) args->structureInput, args->structureInputSize, &cls);
- if (kIOReturnSuccess == ret) {
- portname = iokit_make_send_right(me->fOwningTask, cls, IKOT_UEXT_OBJECT);
+ switch (selector) {
+ case kIOUserServerMethodRegisterClass:
+ {
+ OSUserMetaClass * cls;
+ if (!args->structureInputSize) {
+ return kIOReturnBadArgument;
+ }
+ if (args->scalarOutputCount != 2) {
+ return kIOReturnBadArgument;
+ }
+ ret = registerClass((OSClassDescription *) args->structureInput, args->structureInputSize, &cls);
+ if (kIOReturnSuccess == ret) {
+ portname = iokit_make_send_right(fOwningTask, cls, IKOT_UEXT_OBJECT);
+ assert(portname);
+ args->scalarOutput[0] = portname;
+ args->scalarOutput[1] = kOSObjectRPCRemote;
+ }
+ break;
+ }
+ case kIOUserServerMethodStart:
+ {
+ if (args->scalarOutputCount != 1) {
+ return kIOReturnBadArgument;
+ }
+ if (!(kIODKDisableCheckInTokenVerification & gIODKDebug)) {
+ if (args->scalarInputCount != 1) {
+ return kIOReturnBadArgument;
+ }
+ mach_port_name_t checkInPortName = ((typeof(checkInPortName))args->scalarInput[0]);
+ OSObject * obj = iokit_lookup_object_with_port_name(checkInPortName, IKOT_IOKIT_IDENT, fOwningTask);
+ IOUserServerCheckInToken * retrievedToken = OSDynamicCast(IOUserServerCheckInToken, obj);
+ if (retrievedToken != NULL) {
+ setCheckInToken(retrievedToken);
+ } else {
+ OSSafeReleaseNULL(obj);
+ return kIOReturnBadArgument;
+ }
+ OSSafeReleaseNULL(obj);
+ }
+ portname = iokit_make_send_right(fOwningTask, this, IKOT_UEXT_OBJECT);
assert(portname);
args->scalarOutput[0] = portname;
- args->scalarOutput[1] = kOSObjectRPCRemote;
+ ret = kIOReturnSuccess;
+ break;
+ }
+ default:
+ break;
}
return ret;
}
-IOReturn
-IOUserServer::externalMethodStart(OSObject * target, void * reference, IOExternalMethodArguments * args)
-{
- mach_port_name_t portname = 0;
- IOReturn ret = kIOReturnSuccess;
-
- IOUserServer * me = (typeof(me))target;
-
- if (!(kIODKDisableCheckInTokenVerification & gIODKDebug)) {
- mach_port_name_t checkInPortName = ((typeof(checkInPortName))args->scalarInput[0]);
- OSObject * obj = iokit_lookup_object_with_port_name(checkInPortName, IKOT_IOKIT_IDENT, me->fOwningTask);
- IOUserServerCheckInToken * retrievedToken = OSDynamicCast(IOUserServerCheckInToken, obj);
- if (retrievedToken != NULL) {
- ret = me->setCheckInToken(retrievedToken);
- } else {
- ret = kIOReturnBadArgument;
- }
- OSSafeReleaseNULL(obj);
- }
- if (ret == kIOReturnSuccess) {
- portname = iokit_make_send_right(me->fOwningTask, me, IKOT_UEXT_OBJECT);
- assert(portname);
- }
- args->scalarOutput[0] = portname;
- return ret;
-}
IOExternalTrap *
IOUserServer::getTargetAndTrapForIndex( IOService **targetP, UInt32 index )
{
- static const OSBoundedArray<IOExternalTrap, 1> trapTemplate = {{
- { NULL, (IOTrap) & IOUserServer::waitInterruptTrap},
- }};
- if (index >= trapTemplate.size()) {
+ static const IOExternalTrap trapTemplate[] = {
+ { NULL, (IOTrap) & IOUserServer::waitInterruptTrap},
+ };
+ if (index >= (sizeof(trapTemplate) / sizeof(IOExternalTrap))) {
return NULL;
}
*targetP = this;
@@ -4643,12 +4127,6 @@
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-void
-IOUserServer::pageout()
-{
- fPageout = 1;
-}
IOReturn
IOUserServer::serviceAttach(IOService * service, IOService * provider)
@@ -4666,7 +4144,6 @@
vars->userServer = this;
vars->userServer->retain();
vars->uvarsLock = IOLockAlloc();
- vars->originalProperties = service->dictionaryWithProperties();
IOLockLock(fLock);
if (-1U == fServices->getNextIndexOfObject(service, 0)) {
fServices->setObject(service);
@@ -4687,27 +4164,6 @@
OSSafeReleaseNULL(registryEntryNumber);
OSSafeReleaseNULL(serviceArray);
OSSafeReleaseNULL(serviceArrayObj);
-
- // populate kIOUserClassesKey
-
- OSUserMetaClass * userMeta;
- OSArray * classesArray;
- const OSString * str2;
-
- classesArray = OSArray::withCapacity(4);
- prop = service->copyProperty(gIOUserClassKey);
- str2 = OSDynamicCast(OSString, prop);
- userMeta = (typeof(userMeta))service->reserved->uvars->userServer->fClasses->getObject(str2);
- while (str2 && userMeta) {
- classesArray->setObject(str2);
- userMeta = userMeta->superMeta;
- if (userMeta) {
- str2 = userMeta->name;
- }
- }
- service->setProperty(gIOUserClassesKey, classesArray);
- OSSafeReleaseNULL(classesArray);
- OSSafeReleaseNULL(prop);
}
IOLockUnlock(fLock);
@@ -4726,21 +4182,20 @@
if (ok) {
ret = LoadModule(execPath);
if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::LoadModule 0x%x %s\n", DKN(this), ret, execPath);
+ DKLOG("%s::LoadModule 0x%x %s\n", getName(), ret, execPath);
}
}
}
OSSafeReleaseNULL(prop);
ret = kIOReturnSuccess;
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::serviceAttach(" DKS ", " DKS ")\n", DKN(this), DKN(service), DKN(provider));
- }
return ret;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define kDriverKitUCPrefix "com.apple.developer.driverkit.userclient-access."
IOReturn
IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void * securityID,
@@ -4752,126 +4207,66 @@
OSDictionary * entitlements;
OSObject * prop;
OSObject * bundleID;
- bool ok = false;
+ bool ok;
entitlements = IOUserClient::copyClientEntitlements(owningTask);
if (!entitlements) {
entitlements = OSDictionary::withCapacity(8);
}
- if (entitlements) {
- if (kIOReturnSuccess == clientHasPrivilege((void *) owningTask, kIOClientPrivilegeAdministrator)) {
- entitlements->setObject(kIODriverKitUserClientEntitlementAdministratorKey, kOSBooleanTrue);
- }
- OSString * creatorName = IOCopyLogNameForPID(proc_selfpid());
- if (creatorName) {
- entitlements->setObject(kIOUserClientCreatorKey, creatorName);
- OSSafeReleaseNULL(creatorName);
- }
+ if (entitlements && (kIOReturnSuccess == clientHasPrivilege((void *) owningTask, kIOClientPrivilegeAdministrator))) {
+ entitlements->setObject(kIODriverKitUserClientEntitlementAdministratorKey, kOSBooleanTrue);
}
*handler = NULL;
ret = service->_NewUserClient(type, entitlements, &uc);
- if (kIOReturnSuccess != ret || uc == NULL) {
+ if (kIOReturnSuccess != ret) {
+ OSSafeReleaseNULL(entitlements);
+ return ret;
+ }
+ userUC = OSDynamicCast(IOUserUserClient, uc);
+ if (!userUC) {
+ uc->terminate();
OSSafeReleaseNULL(uc);
OSSafeReleaseNULL(entitlements);
- return ret;
- }
- userUC = OSDynamicCast(IOUserUserClient, uc);
- if (!userUC) {
- if (uc) {
- uc->terminate(kIOServiceTerminateNeedWillTerminate);
- uc->setTerminateDefer(service, false);
- OSSafeReleaseNULL(uc);
- }
- OSSafeReleaseNULL(entitlements);
return kIOReturnUnsupported;
}
userUC->setTask(owningTask);
if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
- do {
- bool checkiOS3pEntitlements;
-
- // check if client has com.apple.private.driverkit.driver-access and the required entitlements match the driver's entitlements
- if (entitlements && (prop = entitlements->getObject(gIODriverKitRequiredEntitlementsKey))) {
- prop->retain();
- ok = checkEntitlements(fEntitlements, prop, NULL, NULL);
- if (ok) {
- break;
- } else {
- DKLOG(DKS ":UC failed required entitlement check\n", DKN(userUC));
- }
- }
-
-#if XNU_TARGET_OS_IOS
- checkiOS3pEntitlements = !fPlatformDriver;
- if (checkiOS3pEntitlements && fTeamIdentifier == NULL) {
- DKLOG("warning: " DKS " does not have a team identifier\n", DKN(this));
- }
-#else
- checkiOS3pEntitlements = false;
-#endif
- if (checkiOS3pEntitlements) {
- // App must have com.apple.developer.driverkit.communicates-with-drivers
- ok = entitlements && entitlements->getObject(gIODriverKitUserClientEntitlementCommunicatesWithDriversKey) == kOSBooleanTrue;
- if (ok) {
- // check team ID
- const char * clientTeamID = csproc_get_teamid(current_proc());
- bool sameTeam = fTeamIdentifier != NULL && clientTeamID != NULL && strncmp(fTeamIdentifier->getCStringNoCopy(), clientTeamID, CS_MAX_TEAMID_LEN) == 0;
-
- if (sameTeam) {
- ok = true;
- } else {
- // different team IDs, dext must have com.apple.developer.driverkit.allow-third-party-userclients
- ok = fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowThirdPartyUserClientsKey) == kOSBooleanTrue;
- }
- if (!ok) {
- DKLOG(DKS ":UC failed team ID check. client team=%s, driver team=%s\n", DKN(userUC), clientTeamID ? clientTeamID : "(null)", fTeamIdentifier ? fTeamIdentifier->getCStringNoCopy() : "(null)");
- }
- } else {
- DKLOG(DKS ":UC entitlement check failed, app does not have %s entitlement\n", DKN(userUC), gIODriverKitUserClientEntitlementCommunicatesWithDriversKey->getCStringNoCopy());
- }
-
- // When checking iOS 3rd party entitlements, do not fall through to other entitlement checks
- break;
- }
-
- // first party dexts and third party macOS dexts
-
- // check if driver has com.apple.developer.driverkit.allow-any-userclient-access
+ if (entitlements && (prop = entitlements->getObject(gIODriverKitRequiredEntitlementsKey))) {
+ prop->retain();
+ ok = checkEntitlements(fEntitlements, prop, NULL, NULL);
+ if (!ok && fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowAnyKey)) {
+ ok = true;
+ }
+ } else {
+ bundleID = NULL;
if (fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowAnyKey)) {
ok = true;
- break;
- }
-
- // check if client has com.apple.developer.driverkit.userclient-access and its value matches the bundle ID of the service
- bundleID = service->copyProperty(gIOModuleIdentifierKey);
- ok = (entitlements
- && bundleID
- && (prop = entitlements->getObject(gIODriverKitUserClientEntitlementsKey)));
+ } else {
+ bundleID = service->copyProperty(gIOModuleIdentifierKey);
+ ok = (entitlements
+ && bundleID
+ && (prop = entitlements->getObject(gIODriverKitUserClientEntitlementsKey)));
+ if (ok) {
+ bool found __block = false;
+ ok = prop->iterateObjects(^bool (OSObject * object) {
+ found = object->isEqualTo(bundleID);
+ return found;
+ });
+ ok = found;
+ }
+ OSSafeReleaseNULL(bundleID);
+ }
if (ok) {
- bool found __block = false;
- ok = prop->iterateObjects(^bool (OSObject * object) {
- found = object->isEqualTo(bundleID);
- return found;
- });
- ok = found;
- } else {
- OSString * bundleIDStr = OSDynamicCast(OSString, bundleID);
- DKLOG(DKS ":UC failed userclient-access check, needed bundle ID %s\n", DKN(userUC), bundleIDStr ? bundleIDStr->getCStringNoCopy() : "(null)");
- }
- OSSafeReleaseNULL(bundleID);
- } while (false);
-
- if (ok) {
- prop = userUC->copyProperty(gIOServiceDEXTEntitlementsKey);
- ok = checkEntitlements(entitlements, prop, NULL, NULL);
+ prop = userUC->copyProperty(gIOServiceDEXTEntitlementsKey);
+ ok = checkEntitlements(entitlements, prop, NULL, NULL);
+ }
}
if (!ok) {
DKLOG(DKS ":UC entitlements check failed\n", DKN(userUC));
- uc->terminate(kIOServiceTerminateNeedWillTerminate);
- uc->setTerminateDefer(service, false);
+ uc->terminate();
OSSafeReleaseNULL(uc);
OSSafeReleaseNULL(entitlements);
return kIOReturnNotPermitted;
@@ -4907,106 +4302,11 @@
.outputPowerCharacter = kIOPMLowPower,
.inputPowerRequirement = kIOPMLowPower},
{ .version = kIOPMPowerStateVersion1,
- .capabilityFlags = kIOPMAOTPower,
- .outputPowerCharacter = kIOPMAOTPower,
- .inputPowerRequirement = kIOPMAOTPower},
- { .version = kIOPMPowerStateVersion1,
.capabilityFlags = kIOPMPowerOn,
.outputPowerCharacter = kIOPMPowerOn,
.inputPowerRequirement = kIOPMPowerOn},
};
-enum {
- kUserServerMaxPowerState = 3
-};
-
-IOReturn
-IOUserServer::serviceJoinPMTree(IOService * service)
-{
- IOReturn ret;
- IOService * pmProvider;
- bool joinTree;
-
- if (service->reserved->uvars->userServerPM) {
- return kIOReturnSuccess;
- }
-
- if (!fRootNotifier) {
- ret = registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
- assert(kIOReturnSuccess == ret);
- IOServicePH::serverAdd(this);
- fRootNotifier = true;
- }
-
- joinTree = false;
- if (!(kIODKDisablePM & gIODKDebug) && !service->pm_vars) {
- kern_return_t kr;
- OSDictionary * props;
- kr = service->CopyProperties_Local(&props);
- if (kIOReturnSuccess == kr) {
- if (props->getObject(kIOPMResetPowerStateOnWakeKey) == kOSBooleanTrue) {
- service->setProperty(kIOPMResetPowerStateOnWakeKey, kOSBooleanTrue);
- }
- fAOTAllow |= (NULL != props->getObject(kIOPMAOTAllowKey));
- if (!(kIODKDisableIOPMSystemOffPhase2Allow & gIODKDebug)) {
- fSystemOffPhase2Allow |= (NULL != props->getObject(kIOPMSystemOffPhase2AllowKey));
- }
- OSSafeReleaseNULL(props);
- }
- service->PMinit();
- ret = service->registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
- assert(kIOReturnSuccess == ret);
- joinTree = true;
- }
-
- pmProvider = service;
- while (pmProvider && !pmProvider->inPlane(gIOPowerPlane)) {
- pmProvider = pmProvider->getProvider();
- }
- if (!pmProvider) {
- pmProvider = getPMRootDomain();
- }
- if (pmProvider) {
- IOService * entry;
- OSObject * prop;
- OSObject * nextProp;
- OSString * str;
-
- entry = pmProvider;
- prop = NULL;
- do {
- nextProp = entry->copyProperty("non-removable");
- if (nextProp) {
- OSSafeReleaseNULL(prop);
- prop = nextProp;
- }
- entry = entry->getProvider();
- } while (entry);
- if (prop) {
- str = OSDynamicCast(OSString, prop);
- if (str && str->isEqualTo("yes")) {
- pmProvider = NULL;
- }
- prop->release();
- }
- }
-
- if (!(kIODKDisablePM & gIODKDebug) && pmProvider) {
- IOLockLock(fLock);
- service->reserved->uvars->powerState = true;
- IOLockUnlock(fLock);
-
- if (joinTree) {
- pmProvider->joinPMtree(service);
- service->reserved->uvars->userServerPM = true;
- service->reserved->uvars->resetPowerOnWake = service->propertyExists(kIOPMResetPowerStateOnWakeKey);
- }
- }
-
- service->registerInterestedDriver(this);
- return kIOReturnSuccess;
-}
-
IOReturn
IOUserServer::setPowerState(unsigned long state, IOService * service)
{
@@ -5015,7 +4315,6 @@
}
return kIOPMAckImplied;
}
-
IOReturn
IOUserServer::serviceSetPowerState(IOService * controllingDriver, IOService * service, IOPMPowerFlags flags, unsigned long state)
@@ -5037,31 +4336,10 @@
IOLockUnlock(fLock);
if (sendIt) {
- uint32_t driverFlags = (uint32_t) flags;
if (kIODKLogPM & gIODKDebug) {
- DKLOG(DKS "::serviceSetPowerState(%ld, 0x%x) %d\n", DKN(service), state, driverFlags, fSystemPowerAck);
- }
-#if DEBUG || DEVELOPMENT
- bool pageout = false;
- uint64_t pageincount = 0;
- if (gLPWFlags) {
- pageout = fPageout;
- if (pageout) {
- fPageout = false;
- DKLOG(DKS " pageout\n", DKN(service));
- pageincount = vm_task_evict_shared_cache(fOwningTask);
- }
- }
-#endif /* DEBUG || DEVELOPMENT */
-
- ret = service->SetPowerState(driverFlags);
-
-#if DEBUG || DEVELOPMENT
- if (pageout) {
- DKLOG(DKS " state %ld pageins %qd\n", DKN(service), state, vm_task_pageins(fOwningTask) - pageincount);
- }
-#endif /* DEBUG || DEVELOPMENT */
-
+ DKLOG(DKS "::serviceSetPowerState(%ld) %d\n", DKN(service), state, fSystemPowerAck);
+ }
+ ret = service->SetPowerState((uint32_t) flags);
if (kIOReturnSuccess == ret) {
return 20 * 1000 * 1000;
} else {
@@ -5095,8 +4373,8 @@
}
service->reserved->uvars->powerState = (0 != state);
- bool allPowerStates __block = service->reserved->uvars->powerState;
- if (!allPowerStates) {
+ bool allPowerStates __block = 0;
+ if (!state) {
// any service on?
fServices->iterateObjects(^bool (OSObject * obj) {
int service __unused; // hide outer defn
@@ -5117,161 +4395,10 @@
IOLockUnlock(fLock);
if (pmAck) {
- serverAck();
+ IOServicePH::serverAck(this);
}
return kIOPMAckImplied;
-}
-
-bool
-IOUserServer::checkPMReady()
-{
- bool __block ready = true;
-
- IOLockLock(fLock);
- // Check if any services have not completely joined the PM tree (i.e.
- // addPowerChild has not compeleted).
- fServices->iterateObjects(^bool (OSObject * obj) {
- IOPowerConnection *conn;
- IOService *service = (IOService *) obj;
- IORegistryEntry *parent = service->getParentEntry(gIOPowerPlane);
- if ((conn = OSDynamicCast(IOPowerConnection, parent))) {
- if (!conn->getReadyFlag()) {
- ready = false;
- return true;
- }
- }
- return false;
- });
- IOLockUnlock(fLock);
-
- return ready;
-}
-
-IOReturn
-IOUserServer::serviceCreatePMAssertion(IOService * service, uint32_t assertionBits, uint64_t * assertionID, bool synced)
-{
- IOReturn ret = kIOReturnSuccess;
-
- *assertionID = kIOPMUndefinedDriverAssertionID;
-
- if (!service->reserved->uvars || service->reserved->uvars->userServer != this) {
- return kIOReturnError;
- }
-
- if (!service->reserved->uvars->userServerPM) {
- // Cannot create PM assertion unless joined PM tree
- return kIOReturnNotReady;
- }
-
- // Check to make sure the bits are allowed
- uint32_t userAllowedBits = kIOPMDriverAssertionCPUBit |
- kIOPMDriverAssertionForceFullWakeupBit;
- if (synced) {
- userAllowedBits = kIOPMDriverAssertionCPUBit;
- }
- if (0 == (assertionBits & ~userAllowedBits)) {
- if (synced) {
- ret = getPMRootDomain()->acquireDriverKitSyncedAssertion(service, assertionID);
- assert(ret != kIOReturnSuccess || *assertionID != kIOPMUndefinedDriverAssertionID);
- } else {
- *assertionID = getPMRootDomain()->createPMAssertion(assertionBits,
- kIOPMDriverAssertionLevelOn,
- getPMRootDomain(),
- service->getName());
- if (!*assertionID) {
- ret = kIOReturnInternalError;
- }
- }
- } else {
- ret = kIOReturnBadArgument;
- }
- if (*assertionID != kIOPMUndefinedDriverAssertionID) {
- IOLockLock(fLock);
- OSNumber * assertionIDNumber = OSNumber::withNumber(*assertionID, 64);
- OSArray ** pmAssertions = (synced ? &service->reserved->uvars->pmAssertionsSynced : &service->reserved->uvars->pmAssertions);
- if (!*pmAssertions) {
- *pmAssertions = OSArray::withCapacity(1);
- }
- (*pmAssertions)->setObject(assertionIDNumber);
- assertionIDNumber->release();
- IOLockUnlock(fLock);
- }
-
- return ret;
-}
-
-IOReturn
-IOUserServer::serviceReleasePMAssertion(IOService * service, IOPMDriverAssertionID assertionID)
-{
- kern_return_t ret = kIOReturnSuccess;
- bool synced = false;
-
- bool (^findAndRemoveAssertionID)(OSArray *) = ^(OSArray * assertions) {
- unsigned index;
- if (!assertions) {
- return false;
- }
- for (index = 0; index < assertions->getCount(); index++) {
- OSNumber * theID = (OSNumber *)assertions->getObject(index);
- if (theID->unsigned64BitValue() == assertionID) {
- break;
- }
- }
- if (index == assertions->getCount()) {
- return false;
- }
- assertions->removeObject(index);
- return true;
- };
-
- if (!service->reserved->uvars || !service->reserved->uvars->userServer) {
- return kIOReturnError;
- }
-
- IOLockLock(fLock);
- if (findAndRemoveAssertionID(service->reserved->uvars->pmAssertionsSynced)) {
- synced = true;
- } else if (!findAndRemoveAssertionID(service->reserved->uvars->pmAssertions)) {
- ret = kIOReturnNotFound;
- }
- IOLockUnlock(fLock);
-
- if (ret == kIOReturnSuccess) {
- if (synced) {
- getPMRootDomain()->releaseDriverKitSyncedAssertion(assertionID);
- } else {
- getPMRootDomain()->releasePMAssertion(assertionID);
- }
- }
-
- return ret;
-}
-
-kern_return_t
-IOService::JoinPMTree_Impl(void)
-{
- if (!reserved->uvars || !reserved->uvars->userServer) {
- return kIOReturnNotReady;
- }
- return reserved->uvars->userServer->serviceJoinPMTree(this);
-}
-
-static kern_return_t
-acknowledgeSetPowerState(IOService * service)
-{
- if (service->reserved->uvars
- && service->reserved->uvars->userServer
- && service->reserved->uvars->willPower) {
- IOReturn ret;
- service->reserved->uvars->willPower = false;
- ret = service->reserved->uvars->controllingDriver->setPowerState(service->reserved->uvars->willPowerState, service);
- if (kIOPMAckImplied == ret) {
- service->acknowledgeSetPowerState();
- }
- return kIOReturnSuccess;
- }
- return kIOReturnNotReady;
}
kern_return_t
@@ -5281,7 +4408,18 @@
if (kIODKLogPM & gIODKDebug) {
DKLOG(DKS "::SetPowerState(%d), %d\n", DKN(this), powerFlags, reserved->uvars->willPower);
}
- return ::acknowledgeSetPowerState(this);
+ if (reserved->uvars
+ && reserved->uvars->userServer
+ && reserved->uvars->willPower) {
+ IOReturn ret;
+ reserved->uvars->willPower = false;
+ ret = reserved->uvars->controllingDriver->setPowerState(reserved->uvars->willPowerState, this);
+ if (kIOPMAckImplied == ret) {
+ acknowledgeSetPowerState();
+ }
+ return kIOReturnSuccess;
+ }
+ return kIOReturnNotReady;
}
kern_return_t
@@ -5296,28 +4434,13 @@
changePowerStateToPriv(1);
break;
case kIOServicePowerCapabilityOn:
- changePowerStateToPriv(kUserServerMaxPowerState);
+ changePowerStateToPriv(2);
break;
default:
return kIOReturnBadArgument;
}
return kIOReturnSuccess;
-}
-
-kern_return_t
-IOService::SetPowerOverride_Impl(
- bool enable)
-{
- kern_return_t ret;
-
- if (enable) {
- ret = powerOverrideOnPriv();
- } else {
- ret = powerOverrideOffPriv();
- }
-
- return ret == IOPMNoErr ? kIOReturnSuccess : kIOReturnError;
}
kern_return_t
@@ -5352,17 +4475,11 @@
IOService * service;
OSString * str;
const OSSymbol * sym;
- OSObject * prop = NULL;
- OSObject * moduleIdentifier = NULL;
- OSObject * userServerName = NULL;
- OSDictionary * properties = NULL;
- OSDictionary * copyProperties = NULL;
+ OSObject * prop;
+ OSDictionary * properties;
kern_return_t ret;
if (provider != this) {
- return kIOReturnUnsupported;
- }
- if (reserved == NULL || reserved->uvars == NULL) {
return kIOReturnUnsupported;
}
@@ -5370,53 +4487,27 @@
inst = NULL;
service = NULL;
- prop = reserved->uvars->originalProperties->getObject(propertiesKey);
- if (!prop) {
- return kIOReturnBadArgument;
- }
- prop->retain();
+ prop = copyProperty(propertiesKey);
properties = OSDynamicCast(OSDictionary, prop);
- if (!properties) {
- ret = kIOReturnBadArgument;
- goto finish;
- }
- copyProperties = OSDynamicCast(OSDictionary, properties->copyCollection());
- if (!copyProperties) {
- ret = kIOReturnNoMemory;
- goto finish;
- }
- moduleIdentifier = copyProperty(gIOModuleIdentifierKey);
- if (moduleIdentifier) {
- copyProperties->setObject(gIOModuleIdentifierKey, moduleIdentifier);
- }
- userServerName = reserved->uvars->userServer->copyProperty(gIOUserServerNameKey);
- if (userServerName) {
- copyProperties->setObject(gIOUserServerNameKey, userServerName);
- }
-
- str = OSDynamicCast(OSString, copyProperties->getObject(gIOClassKey));
- if (!str) {
- ret = kIOReturnBadArgument;
- goto finish;
- }
- sym = OSSymbol::withString(str);
- if (sym) {
- inst = OSMetaClass::allocClassWithName(sym);
- service = OSDynamicCast(IOService, inst);
- if (service && service->init(copyProperties) && service->attach(this)) {
- reserved->uvars->userServer->serviceAttach(service, this);
- service->reserved->uvars->started = true;
- ret = kIOReturnSuccess;
- *result = service;
- }
- OSSafeReleaseNULL(sym);
- }
-
-finish:
+ assert(properties);
+ if (properties) {
+ str = OSDynamicCast(OSString, properties->getObject(gIOClassKey));
+ assert(str);
+ sym = OSSymbol::withString(str);
+ if (sym) {
+ inst = OSMetaClass::allocClassWithName(sym);
+ service = OSDynamicCast(IOService, inst);
+ if (service && service->init(properties) && service->attach(this)) {
+ reserved->uvars->userServer->serviceAttach(service, this);
+ service->reserved->uvars->started = true;
+ ret = kIOReturnSuccess;
+ *result = service;
+ }
+ OSSafeReleaseNULL(sym);
+ }
+ }
+
OSSafeReleaseNULL(prop);
- OSSafeReleaseNULL(copyProperties);
- OSSafeReleaseNULL(moduleIdentifier);
- OSSafeReleaseNULL(userServerName);
if (kIOReturnSuccess != ret) {
OSSafeReleaseNULL(inst);
}
@@ -5435,8 +4526,8 @@
}
us = (typeof(us))thread_iokit_tls_get(0);
- if (us && (!reserved->uvars
- || (reserved->uvars->userServer != us))) {
+ if (!reserved->uvars
+ || (reserved->uvars->userServer != us)) {
return kIOReturnNotPermitted;
}
terminate(kIOServiceTerminateNeedWillTerminate);
@@ -5494,7 +4585,7 @@
}
return kIOReturnSuccess;
});
- if (object || !(kIORegistryIterateParents & regOptions)) {
+ if (object || !(kIORegistryIterateParents & options)) {
break;
}
}
@@ -5514,15 +4605,6 @@
*str = obj;
return obj ? kIOReturnSuccess : kIOReturnError;
}
-
-#if PRIVATE_WIFI_ONLY
-const char *
-IOService::StringFromReturn(
- IOReturn retval)
-{
- return stringFromReturn(retval);
-}
-#endif /* PRIVATE_WIFI_ONLY */
kern_return_t
IOService::CopyProviderProperties_Impl(
@@ -5617,77 +4699,15 @@
return kIOReturnSuccess;
}
-kern_return_t
-IOService::CreatePMAssertion_Impl(uint32_t assertionBits, uint64_t * assertionID, bool synced)
-{
- *assertionID = kIOPMUndefinedDriverAssertionID;
-
- if (!reserved->uvars || !reserved->uvars->userServer) {
- return kIOReturnError;
- }
-
- return reserved->uvars->userServer->serviceCreatePMAssertion(this, assertionBits, assertionID, synced);
-}
-
-kern_return_t
-IOService::ReleasePMAssertion_Impl(uint64_t assertionID)
-{
- if (!reserved->uvars || !reserved->uvars->userServer) {
- return kIOReturnError;
- }
-
- return reserved->uvars->userServer->serviceReleasePMAssertion(this, assertionID);
-}
-
void
-IOUserServer::serverAck(void)
-{
- IOServicePH::serverAck(this);
-}
-
-OSArray *
-IOUserServer::servicesWithPowerState(bool state)
-{
- OSArray * result = OSArray::withCapacity(1);
- if (!result) {
- return NULL;
- }
- IOLockLock(fLock);
- fServices->iterateObjects(^(OSObject * object) {
- IOService * service = OSDynamicCast(IOService, object);
- if (service && service->reserved->uvars->powerState == state) {
- result->setObject(service);
- }
- return false;
- });
- IOLockUnlock(fLock);
- if (!result->getCount()) {
- OSSafeReleaseNULL(result);
- }
- return result;
-}
-
-void
-IOUserServer::systemSuspend()
-{
- if (fSystemOff && !fSuspended) {
- KDBG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SUSPEND_DRIVERKIT_USERSPACE) | DBG_FUNC_START,
- task_pid(fOwningTask));
- task_suspend_internal(fOwningTask);
- DKLOG(DKS " did task_suspend_internal\n", DKN(this));
- fSuspended = true;
- }
-}
-
-void
-IOUserServer::systemPower(uint8_t systemState, bool hibernate)
+IOUserServer::systemPower(bool powerOff)
{
OSArray * services;
{
OSDictionary * sleepDescription;
OSObject * prop;
- sleepDescription = OSDictionary::withCapacity(3);
+ sleepDescription = OSDictionary::withCapacity(4);
if (sleepDescription) {
prop = getPMRootDomain()->copyProperty(kRootDomainSleepReasonKey);
if (prop) {
@@ -5699,44 +4719,12 @@
sleepDescription->setObject(gIOSystemStateSleepDescriptionHibernateStateKey, prop);
OSSafeReleaseNULL(prop);
}
- if (hibernate) {
- uint32_t correctHibernateState = kIOSystemStateSleepDescriptionHibernateStateHibernating;
- OSData *correctHibernateStateData = OSData::withValue(correctHibernateState);
- assert(correctHibernateStateData != NULL);
- sleepDescription->setObject(gIOSystemStateSleepDescriptionHibernateStateKey, correctHibernateStateData);
- OSSafeReleaseNULL(correctHibernateStateData);
- }
getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateSleepDescriptionKey, sleepDescription);
OSSafeReleaseNULL(sleepDescription);
}
}
- if (!IsIOServiceSystemStateOff(systemState)) {
- OSDictionary * wakeDescription;
- OSObject * prop;
- char wakeReasonString[128];
-
- wakeDescription = OSDictionary::withCapacity(2);
- if (wakeDescription) {
- wakeReasonString[0] = 0;
- getPMRootDomain()->copyWakeReasonString(wakeReasonString, sizeof(wakeReasonString));
-
- if (wakeReasonString[0]) {
- prop = OSString::withCString(&wakeReasonString[0]);
- wakeDescription->setObject(gIOSystemStateWakeDescriptionWakeReasonKey, prop);
- OSSafeReleaseNULL(prop);
- }
-#if defined(__arm__) || defined(__arm64__)
- prop = OSNumber::withNumber(ml_get_conttime_offset(), sizeof(uint64_t) * CHAR_BIT);
- wakeDescription->setObject(gIOSystemStateWakeDescriptionContinuousTimeOffsetKey, prop);
- OSSafeReleaseNULL(prop);
-#endif /* defined(__arm__) || defined(__arm64__) */
- getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateWakeDescriptionKey, wakeDescription);
- OSSafeReleaseNULL(wakeDescription);
- }
- }
IOLockLock(fLock);
-
services = OSArray::withArray(fServices);
bool allPowerStates __block = 0;
@@ -5750,17 +4738,11 @@
return allPowerStates;
});
- // figure what phase this DK server process will be suspended in,
- // and make sure its power changes complete before suspension
-
- bool effectiveOff = IsIOServiceSystemStateOff(systemState) && !allPowerStates;
- effectiveOff |= ((kIOServiceSystemStateOffPhase1 == systemState) && !fSystemOffPhase2Allow);
- effectiveOff |= (kIOServiceSystemStateOffPhase2 == systemState);
- effectiveOff |= ((kIOServiceSystemStateAOT == systemState) && !fAOTAllow);
-
- DKLOG(DKS "::systemPower(0x%x) effective %d current %d\n", DKN(this), systemState, !effectiveOff, allPowerStates != 0);
-
- if (effectiveOff) {
+ if (kIODKLogPM & gIODKDebug) {
+ DKLOG("%s::powerOff(%d) %d\n", getName(), powerOff, allPowerStates);
+ }
+
+ if (powerOff) {
fSystemPowerAck = allPowerStates;
if (!fSystemPowerAck) {
fSystemOff = true;
@@ -5768,7 +4750,7 @@
IOLockUnlock(fLock);
if (!fSystemPowerAck) {
- serverAck();
+ IOServicePH::serverAck(this);
} else {
if (services) {
services->iterateObjects(^bool (OSObject * obj) {
@@ -5778,23 +4760,14 @@
if (kIODKLogPM & gIODKDebug) {
DKLOG("changePowerStateWithOverrideTo(" DKS ", %d)\n", DKN(nextService), 0);
}
- nextService->reserved->uvars->powerOverride = nextService->reserved->uvars->userServerPM ? kUserServerMaxPowerState : nextService->getPowerState();
+ nextService->reserved->uvars->powerOverride = nextService->getPowerState();
nextService->changePowerStateWithOverrideTo(0, 0);
return false;
});
}
}
- } else if (fSystemOff) {
+ } else {
fSystemOff = false;
-
- if (fSuspended) {
- KDBG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SUSPEND_DRIVERKIT_USERSPACE) | DBG_FUNC_END,
- task_pid(fOwningTask));
- task_resume_internal(fOwningTask);
- DKLOG(DKS " did task_resume_internal\n", DKN(this));
- fSuspended = false;
- }
-
IOLockUnlock(fLock);
if (services) {
services->iterateObjects(^bool (OSObject * obj) {
@@ -5803,22 +4776,18 @@
nextService = (IOService *) obj;
if (-1U != nextService->reserved->uvars->powerOverride) {
if (kIODKLogPM & gIODKDebug) {
- DKLOG("%schangePowerStateWithOverrideTo(" DKS ", %d)\n", nextService->reserved->uvars->resetPowerOnWake ? "!" : "", DKN(nextService), nextService->reserved->uvars->powerOverride);
+ DKLOG("changePowerStateWithOverrideTo(" DKS ", %d)\n", DKN(nextService), nextService->reserved->uvars->powerOverride);
}
- if (!nextService->reserved->uvars->resetPowerOnWake) {
- nextService->changePowerStateWithOverrideTo(nextService->reserved->uvars->powerOverride, 0);
- }
+ nextService->changePowerStateWithOverrideTo(nextService->reserved->uvars->powerOverride, 0);
nextService->reserved->uvars->powerOverride = -1U;
}
return false;
});
}
- } else {
- IOLockUnlock(fLock);
- serverAck();
}
OSSafeReleaseNULL(services);
}
+
void
IOUserServer::systemHalt(int howto)
@@ -5826,7 +4795,7 @@
OSArray * services;
if (true || (kIODKLogPM & gIODKDebug)) {
- DKLOG(DKS "::systemHalt()\n", DKN(this));
+ DKLOG("%s::systemHalt()\n", getName());
}
{
@@ -5876,15 +4845,9 @@
if (!root) {
return false;
}
- if (nextService->reserved && nextService->reserved->uvars) {
- if (nextService->reserved->uvars->started) {
- terminateOptions = kIOServiceRequired | kIOServiceTerminateNeedWillTerminate;
- if (!nextService->terminate(terminateOptions)) {
- IOLog("failed to terminate service %s-0x%llx\n", nextService->getName(), nextService->getRegistryEntryID());
- }
- } else {
- IOLog("service %s-0x%llx not started, skipped termination\n", nextService->getName(), nextService->getRegistryEntryID());
- }
+ terminateOptions = kIOServiceRequired | kIOServiceTerminateNeedWillTerminate;
+ if (!nextService->terminate(terminateOptions)) {
+ IOLog("failed to terminate service %s-0x%llx\n", nextService->getName(), nextService->getRegistryEntryID());
}
return false;
});
@@ -5911,44 +4874,73 @@
IOUserServer::serviceStarted(IOService * service, IOService * provider, bool result)
{
IOReturn ret;
- bool needStop = false;
+ IOService * pmProvider;
+ bool joinTree;
DKLOG(DKS "::start(" DKS ") %s\n", DKN(service), DKN(provider), result ? "ok" : "fail");
if (!result) {
- if (!service->reserved->uvars->instantiated && provider) {
- // Object instantiation did not happen. This can happen if,
- // 1. Dext crashed, in which case the user server has been terminated when the task is marked as corpse
- // 2. Kernel IOService failed start, and it did not attempt Start
- // A rematch should be attempted for 1, not 2
- bool shouldReRegister = true;
- if (lockForArbitration()) {
- shouldReRegister = (__state[0] & kIOServiceInactiveState);
- unlockForArbitration();
- }
- if (shouldReRegister) {
- provider->registerService(kIOServiceAsynchronous);
- }
- }
ret = kIOReturnSuccess;
return ret;
}
- ret = serviceJoinPMTree(service);
-
- IOLockLock(service->reserved->uvars->uvarsLock);
+ if (!fRootNotifier) {
+ ret = registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
+ assert(kIOReturnSuccess == ret);
+ IOServicePH::serverAdd(this);
+ fRootNotifier = true;
+ }
+
+ joinTree = false;
+ if (!(kIODKDisablePM & gIODKDebug) && !service->pm_vars) {
+ service->PMinit();
+ ret = service->registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
+ assert(kIOReturnSuccess == ret);
+ joinTree = true;
+ }
+
+ pmProvider = service;
+ while (pmProvider && !pmProvider->inPlane(gIOPowerPlane)) {
+ pmProvider = pmProvider->getProvider();
+ }
+ if (pmProvider) {
+ IOService * entry;
+ OSObject * prop;
+ OSObject * nextProp;
+ OSString * str;
+
+ entry = pmProvider;
+ prop = NULL;
+ do {
+ nextProp = entry->copyProperty("non-removable");
+ if (nextProp) {
+ OSSafeReleaseNULL(prop);
+ prop = nextProp;
+ }
+ entry = entry->getProvider();
+ } while (entry);
+ if (prop) {
+ str = OSDynamicCast(OSString, prop);
+ if (str && str->isEqualTo("yes")) {
+ pmProvider = NULL;
+ }
+ prop->release();
+ }
+ }
+
+ if (!(kIODKDisablePM & gIODKDebug) && pmProvider) {
+ IOLockLock(fLock);
+ service->reserved->uvars->powerState = true;
+ IOLockUnlock(fLock);
+
+ if (joinTree) {
+ pmProvider->joinPMtree(service);
+ service->reserved->uvars->userServerPM = true;
+ }
+ }
+
+ service->registerInterestedDriver(this);
service->reserved->uvars->started = true;
- needStop = service->reserved->uvars->needStop;
- IOLockUnlock(service->reserved->uvars->uvarsLock);
- if (needStop) {
- serviceStop(service, provider);
- return kIOReturnSuccess;
- }
-
- if (service->reserved->uvars->deferredRegisterService) {
- service->registerService(kIOServiceAsynchronous | kIOServiceDextRequirePowerForMatching);
- service->reserved->uvars->deferredRegisterService = false;
- }
return kIOReturnSuccess;
}
@@ -5958,25 +4950,17 @@
IOUserServer::serviceOpen(IOService * provider, IOService * client)
{
OSObjectUserVars * uvars;
- IOReturn ret;
IOLockLock(client->reserved->uvars->uvarsLock);
uvars = client->reserved->uvars;
- if (uvars->willTerminate || uvars->stopped) {
- DKLOG(DKS "- " DKS " blocked attempt to open " DKS "\n", DKN(this), DKN(client), DKN(provider));
- ret = kIOReturnBadArgument;
- } else {
- if (!uvars->openProviders) {
- uvars->openProviders = OSArray::withObjects((const OSObject **) &provider, 1);
- } else if (-1U == uvars->openProviders->getNextIndexOfObject(provider, 0)) {
- uvars->openProviders->setObject(provider);
- }
- ret = kIOReturnSuccess;
- }
-
+ if (!uvars->openProviders) {
+ uvars->openProviders = OSArray::withObjects((const OSObject **) &provider, 1);
+ } else if (-1U == uvars->openProviders->getNextIndexOfObject(provider, 0)) {
+ uvars->openProviders->setObject(provider);
+ }
IOLockUnlock(client->reserved->uvars->uvarsLock);
- return ret;
+ return kIOReturnSuccess;
}
IOReturn
@@ -6006,33 +4990,18 @@
finish:
IOLockUnlock(client->reserved->uvars->uvarsLock);
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::serviceClose(" DKS ", " DKS ") -> %x\n", DKN(this), DKN(provider), DKN(client), ret);
- }
return ret;
}
IOReturn
-IOUserServer::serviceStop(IOService * service, IOService *provider)
+IOUserServer::serviceStop(IOService * service, IOService *)
{
IOReturn ret;
- uint32_t idx;
+ uint32_t idx, queueAlloc;
bool pmAck;
- bool deferred = false;
- OSObjectUserVars * uvars = service->reserved->uvars;
-
- IOLockLock(uvars->uvarsLock);
- if (!uvars->started) {
- // started will be set, at a later point
- uvars->needStop = true;
- deferred = true;
- }
- IOLockUnlock(uvars->uvarsLock);
- if (deferred) {
- return kIOReturnSuccess;
- }
+ OSObjectUserVars * uvars;
pmAck = false;
IOLockLock(fLock);
@@ -6060,6 +5029,7 @@
OSSafeReleaseNULL(serviceArray);
OSSafeReleaseNULL(serviceArrayObj);
+ uvars = service->reserved->uvars;
uvars->stopped = true;
uvars->powerState = 0;
@@ -6081,55 +5051,13 @@
}
IOLockUnlock(fLock);
if (pmAck) {
- serverAck();
+ IOServicePH::serverAck(this);
}
if (-1U == idx) {
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::serviceStop(" DKS ", " DKS "): could not find service\n", DKN(this), DKN(service), DKN(provider));
- }
return kIOReturnSuccess;
}
- (void) service->deRegisterInterestedDriver(this);
- if (uvars->userServerPM) {
- IOPMrootDomain * rootDomain = getPMRootDomain();
- service->PMstop();
- service->acknowledgeSetPowerState();
- if (uvars->pmAssertions) {
- uvars->pmAssertions->iterateObjects(^(OSObject * obj) {
- rootDomain->releasePMAssertion(((OSNumber *)obj)->unsigned64BitValue());
- return false;
- });
- OSSafeReleaseNULL(uvars->pmAssertions);
- }
- if (uvars->pmAssertionsSynced) {
- uvars->pmAssertionsSynced->iterateObjects(^(OSObject * obj) {
- rootDomain->releaseDriverKitSyncedAssertion(((OSNumber *)obj)->unsigned64BitValue());
- return false;
- });
- OSSafeReleaseNULL(uvars->pmAssertionsSynced);
- }
- }
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::serviceStop(" DKS ", " DKS ")\n", DKN(this), DKN(service), DKN(provider));
- }
-
- ret = kIOReturnSuccess;
- return ret;
-}
-
-void
-IOUserServer::serviceFree(IOService * service)
-{
- OSObjectUserVars * uvars;
- uint32_t idx, queueAlloc;
- IODispatchQueue ** unboundedQueueArray = NULL;
-
- uvars = service->reserved->uvars;
- if (!uvars) {
- return;
- }
if (uvars->queueArray && uvars->userMeta) {
queueAlloc = 1;
if (uvars->userMeta->queueNames) {
@@ -6138,13 +5066,29 @@
for (idx = 0; idx < queueAlloc; idx++) {
OSSafeReleaseNULL(uvars->queueArray[idx]);
}
- unboundedQueueArray = uvars->queueArray.data();
- IOSafeDeleteNULL(unboundedQueueArray, IODispatchQueue *, queueAlloc);
- uvars->queueArray = OSBoundedArrayRef<IODispatchQueue *>();
+ IOSafeDeleteNULL(uvars->queueArray, IODispatchQueue *, queueAlloc);
+ }
+
+ (void) service->deRegisterInterestedDriver(this);
+ if (uvars->userServerPM) {
+ service->PMstop();
+ }
+
+ ret = kIOReturnSuccess;
+ return ret;
+}
+
+void
+IOUserServer::serviceFree(IOService * service)
+{
+ OSObjectUserVars * uvars;
+
+ uvars = service->reserved->uvars;
+ if (!uvars) {
+ return;
}
OSSafeReleaseNULL(uvars->userServer);
IOLockFree(uvars->uvarsLock);
- OSSafeReleaseNULL(service->reserved->uvars->originalProperties);
IOFreeType(service->reserved->uvars, OSObjectUserVars);
}
@@ -6162,25 +5106,13 @@
willTerminate = true;
}
IOLockUnlock(client->reserved->uvars->uvarsLock);
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG("serviceWillTerminate(" DKS ", " DKS ")\n", DKN(client), DKN(provider));
- }
if (willTerminate) {
if (provider->isInactive() || IOServicePH::serverSlept()) {
- if (kIODKLogIPC & gIODKDebug) {
- DKLOG(DKS "->Stop_async(" DKS ")\n", DKN(client), DKN(provider));
- }
client->Stop_async(provider);
ret = kIOReturnOffline;
} else {
- if (kIODKLogIPC & gIODKDebug) {
- DKLOG(DKS "->Stop(" DKS ")\n", DKN(client), DKN(provider));
- }
ret = client->Stop(provider);
- if (kIODKLogIPC & gIODKDebug) {
- DKLOG(DKS "->Stop(" DKS ") returned %x\n", DKN(client), DKN(provider), ret);
- }
}
if (kIOReturnSuccess != ret) {
IOUserServer::serviceDidStop(client, provider);
@@ -6199,9 +5131,6 @@
*defer = true;
}
IOLockUnlock(client->reserved->uvars->uvarsLock);
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG("serviceDidTerminate(" DKS ", " DKS ") -> defer %d\n", DKN(client), DKN(provider), *defer);
- }
}
void
@@ -6226,10 +5155,6 @@
client->reserved->uvars->openProviders = NULL;
}
IOLockUnlock(client->reserved->uvars->uvarsLock);
-
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG("serviceDidStop(" DKS ", " DKS ") -> complete %d\n", DKN(client), DKN(provider), complete);
- }
if (closeArray) {
closeArray->iterateObjects(^bool (OSObject * obj) {
@@ -6359,6 +5284,7 @@
user_addr_t userObjectName = (user_addr_t)p1;
mach_port_name_t portName = (mach_port_name_t)(uintptr_t)p3;
mach_port_t port = MACH_PORT_NULL;
+ ipc_kobject_type_t portType;
char eventlinkName[kIOEventLinkMaxNameLength + 1] = {0};
size_t eventLinkNameLen;
OSString * eventlinkNameStr = NULL; // must release
@@ -6384,9 +5310,6 @@
IOLockLock(fLock);
eventLink = OSDynamicCast(IOEventLink, fEventLinks->getObject(eventlinkNameStr));
- if (eventLink) {
- eventLink->retain();
- }
IOLockUnlock(fLock);
if (eventLink == NULL) {
@@ -6394,8 +5317,15 @@
goto finish;
}
- ret = iokit_lookup_raw_current_task(portName, IKOT_EVENTLINK, &port);
- if (ret != kIOReturnSuccess) {
+ port = iokit_lookup_raw_current_task(portName, &portType);
+
+ if (port == NULL) {
+ ret = kIOReturnNotFound;
+ goto finish;
+ }
+
+ if (portType != IKOT_EVENTLINK) {
+ ret = kIOReturnBadArgument;
goto finish;
}
@@ -6413,7 +5343,6 @@
}
OSSafeReleaseNULL(eventlinkNameStr);
- OSSafeReleaseNULL(eventLink);
return ret;
}
@@ -6424,6 +5353,7 @@
user_addr_t userObjectName = (user_addr_t)p1;
mach_port_name_t portName = (mach_port_name_t)(uintptr_t)p3;
mach_port_t port = MACH_PORT_NULL;
+ ipc_kobject_type_t portType;
char workgroupName[kIOWorkGroupMaxNameLength + 1] = {0};
size_t workgroupNameLen;
OSString * workgroupNameStr = NULL; // must release
@@ -6449,9 +5379,6 @@
IOLockLock(fLock);
workgroup = OSDynamicCast(IOWorkGroup, fWorkGroups->getObject(workgroupNameStr));
- if (workgroup) {
- workgroup->retain();
- }
IOLockUnlock(fLock);
if (workgroup == NULL) {
@@ -6459,8 +5386,15 @@
goto finish;
}
- ret = iokit_lookup_raw_current_task(portName, IKOT_WORK_INTERVAL, &port);
- if (ret != kIOReturnSuccess) {
+ port = iokit_lookup_raw_current_task(portName, &portType);
+
+ if (port == NULL) {
+ ret = kIOReturnNotFound;
+ goto finish;
+ }
+
+ if (portType != IKOT_WORK_INTERVAL) {
+ ret = kIOReturnBadArgument;
goto finish;
}
@@ -6479,7 +5413,6 @@
}
OSSafeReleaseNULL(workgroupNameStr);
- OSSafeReleaseNULL(workgroup);
return ret;
}
@@ -6487,11 +5420,11 @@
IOExternalTrap *
IOUserUserClient::getTargetAndTrapForIndex( IOService **targetP, UInt32 index )
{
- static const OSBoundedArray<IOExternalTrap, 2> trapTemplate = {{
- { NULL, (IOTrap) & IOUserUserClient::eventlinkConfigurationTrap},
- { NULL, (IOTrap) & IOUserUserClient::workgroupConfigurationTrap},
- }};
- if (index >= trapTemplate.size()) {
+ static const IOExternalTrap trapTemplate[] = {
+ { NULL, (IOTrap) & IOUserUserClient::eventlinkConfigurationTrap},
+ { NULL, (IOTrap) & IOUserUserClient::workgroupConfigurationTrap},
+ };
+ if (index >= (sizeof(trapTemplate) / sizeof(IOExternalTrap))) {
return NULL;
}
*targetP = this;
@@ -6588,7 +5521,7 @@
if (MACH_PORT_NULL != args->asyncWakePort) {
// this retain is for the OSAction to release
- wake_port = ipc_port_make_send_mqueue(args->asyncWakePort);
+ wake_port = ipc_port_make_send(args->asyncWakePort);
kr = CreateActionKernelCompletion(sizeof(IOUserUserClientActionRef), &action);
assert(KERN_SUCCESS == kr);
ref = (typeof(ref))action->GetReference();
@@ -6622,7 +5555,16 @@
OSSafeReleaseNULL(structureInput);
OSSafeReleaseNULL(action);
- if (kr == kIOReturnSuccess && structureOutput) {
+ if (kIOReturnSuccess != kr) {
+ // mig will destroy any async port
+ return kr;
+ }
+ if (MACH_PORT_NULL != wake_port) {
+ // this release is for the mig created send right
+ iokit_release_port_send(wake_port);
+ }
+
+ if (structureOutput) {
if (args->structureVariableOutputData) {
*args->structureVariableOutputData = structureOutput;
} else {
@@ -6637,42 +5579,10 @@
}
}
- if (kIOReturnSuccess != kr) {
- // mig will destroy any async port
- return kr;
- }
-
- // We must never return error after this point in order to preserve MIG ownership semantics
- assert(kr == kIOReturnSuccess);
- if (MACH_PORT_NULL != wake_port) {
- // this release is for the mig created send right
- iokit_release_port_send(wake_port);
- }
-
return kr;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/*
- * IOUserServerCheckInToken state machine
- *
- * token
- * creation
- * |
- * |
- * v dext
- * +-----------+ check-in +-----------+
- * | Pending +--------------->| Complete |
- * +-----+-----+ +-----+-----+
- * | |
- * dext crash | | dext crash
- * before | | before server
- * check-in | | registration
- * | +-----------+ |
- * +----->| Canceled |<--------+
- * +-----------+
- */
extern IORecursiveLock * gDriverKitLaunchLock;
extern OSSet * gDriverKitLaunches;
@@ -6687,6 +5597,8 @@
}
IORecursiveLockLock(gDriverKitLaunchLock);
+
+ assert(fState != kIOUserServerCheckInComplete);
if (fState == kIOUserServerCheckInCanceled) {
// Send cancel notification if we set the handler after this was canceled
@@ -6716,12 +5628,8 @@
{
IORecursiveLockLock(gDriverKitLaunchLock);
- if (fState != kIOUserServerCheckInCanceled) {
- // Move the state to canceled even if the token has completed
- // This is to cover the gap between dext check-in and the registration of user server
- // Cancellation listeners must be informed of a crash in between
+ if (fState == kIOUserServerCheckInPending) {
fState = kIOUserServerCheckInCanceled;
-
if (gDriverKitLaunches != NULL) {
// Remove pending launch from list, if we have not shut down yet.
gDriverKitLaunches->removeObject(this);
@@ -6740,34 +5648,27 @@
IORecursiveLockUnlock(gDriverKitLaunchLock);
}
-IOReturn
+void
IOUserServerCheckInToken::complete()
{
- IOReturn ret;
IORecursiveLockLock(gDriverKitLaunchLock);
- if (fState == kIOUserServerCheckInCanceled) {
- ret = kIOReturnError;
- } else {
- ret = kIOReturnSuccess;
- }
-
- if (fState == kIOUserServerCheckInPending) {
+ if (fState == kIOUserServerCheckInPending && --fPendingCount == 0) {
fState = kIOUserServerCheckInComplete;
if (gDriverKitLaunches != NULL) {
// Remove pending launch from list, if we have not shut down yet.
gDriverKitLaunches->removeObject(this);
}
- // Do not flush the cancellation handlers, as we might still trigger them
+ // No need to hold on to the cancellation handlers
+ fHandlers->flushCollection();
}
IORecursiveLockUnlock(gDriverKitLaunchLock);
- return ret;
}
bool
-IOUserServerCheckInToken::init(const OSSymbol * serverName, OSNumber * serverTag, OSKext *driverKext, OSData *serverDUI)
+IOUserServerCheckInToken::init(const OSSymbol * serverName, OSNumber * serverTag)
{
if (!OSObject::init()) {
return false;
@@ -6791,67 +5692,9 @@
}
fState = kIOUserServerCheckInPending;
-
- fKextBundleID = NULL;
- fNeedDextDec = false;
-
- fExecutableName = NULL;
-
- if (driverKext) {
- fExecutableName = OSDynamicCast(OSSymbol, driverKext->getBundleExecutable());
-
- if (fExecutableName) {
- fExecutableName->retain();
- }
-
- /*
- * We need to keep track of how many dexts we have started.
- * For every new dext we are going to create a new token, and
- * we consider the token creation as the initial step to
- * create a dext as it is the data structure that will back up
- * the userspace dance to start a dext.
- * We later have to decrement only once per token.
- * If no error occurs we consider the finalize() call on IOUserServer
- * as the moment in which we do not consider the dext "alive" anymore;
- * however in case of errors we will still need to decrement the count
- * otherwise upgrades of the dext will never make progress.
- */
- if (OSKext::incrementDextLaunchCount(driverKext, serverDUI)) {
- /*
- * If fKext holds a pointer,
- * it is the indication that a decrements needs
- * to be called.
- */
- fNeedDextDec = true;
- fKextBundleID = OSDynamicCast(OSString, driverKext->getIdentifier());
- fKextBundleID->retain();
- } else {
- return false;
- }
- }
+ fPendingCount = 1;
return true;
-}
-
-/*
- * Returns if the dext can be re-used
- * for matching.
- */
-bool
-IOUserServerCheckInToken::dextTerminate(void)
-{
- bool ret = true;
-
- if (fNeedDextDec == true) {
- /*
- * We can decrement DextLaunchCount only
- * once per token.
- */
- ret = !(OSKext::decrementDextLaunchCount(fKextBundleID));
- fNeedDextDec = false;
- }
-
- return ret;
}
void
@@ -6859,12 +5702,7 @@
{
OSSafeReleaseNULL(fServerName);
OSSafeReleaseNULL(fServerTag);
- OSSafeReleaseNULL(fExecutableName);
OSSafeReleaseNULL(fHandlers);
- if (fKextBundleID != NULL) {
- dextTerminate();
- OSSafeReleaseNULL(fKextBundleID);
- }
OSObject::free();
}
@@ -6883,82 +5721,18 @@
return fServerTag;
}
-/*
- * Wait for a IOUserServer to check in
- */
-
-static
-__attribute__((noinline, not_tail_called))
IOUserServer *
-__WAITING_FOR_USER_SERVER__(IOUserServerCheckInToken * token, uint64_t * timeoutMS)
-{
- IOUserServer * result = NULL;
- IOService * server = NULL;
- const OSSymbol * serverName = token->copyServerName();
- OSNumber * serverTag = token->copyServerTag();
- OSDictionary * matching = IOService::serviceMatching(gIOUserServerClassKey);
- uint64_t startTime = 0, endTime = 0;
-
- if (!matching || !serverName || !serverTag) {
- goto finish;
- }
- IOService::propertyMatching(gIOUserServerNameKey, serverName, matching);
- if (!(kIODKDisableDextTag & gIODKDebug)) {
- IOService::propertyMatching(gIOUserServerTagKey, serverTag, matching);
- }
-
- absolutetime_to_nanoseconds(mach_absolute_time(), &startTime);
- startTime /= NSEC_PER_MSEC;
- server = IOService::waitForMatchingServiceWithToken(matching, (*timeoutMS) * NSEC_PER_MSEC, token);
- result = OSDynamicCast(IOUserServer, server);
- if (!result) {
- // Calculate the remaining timeout if the server isn't registered
- OSSafeReleaseNULL(server);
- token->cancel();
- absolutetime_to_nanoseconds(mach_absolute_time(), &endTime);
- endTime /= NSEC_PER_MSEC;
- if (endTime > startTime) {
- if (os_sub_overflow(*timeoutMS, endTime - startTime, timeoutMS)) {
- *timeoutMS = 0;
- }
- }
- }
-
-finish:
- OSSafeReleaseNULL(matching);
- OSSafeReleaseNULL(serverName);
- OSSafeReleaseNULL(serverTag);
-
- return result;
-}
-
-IOUserServer *
-IOUserServer::launchUserServer(IOService * provider, IOService * service, OSString * bundleID, const OSSymbol * serverName, OSNumber * serverTag, bool reuseIfExists, OSData *serverDUI)
-{
- IOUserServer *me = NULL, *providerServer = NULL;
+IOUserServer::launchUserServer(OSString * bundleID, const OSSymbol * serverName, OSNumber * serverTag, bool reuseIfExists, IOUserServerCheckInToken ** resultToken)
+{
+ IOUserServer *me = NULL;
IOUserServerCheckInToken * token = NULL;
OSDictionary * matching = NULL; // must release
- OSKext * driverKext = NULL; // must release
- OSDextStatistics * driverStatistics = NULL; // must release
- bool reslide = false;
- uint32_t retries = kIOUserServerCheckInMaxRetry;
- uint64_t timeRemainingMS = kIOUserServerCheckInTimeoutMSecs;
-
- /* TODO: Check we are looking for same dextID
- * and if it is not the same
- * restart the matching process.
- */
- driverKext = OSKext::lookupDextWithIdentifier(bundleID, serverDUI);
- if (driverKext != NULL) {
- driverStatistics = driverKext->copyDextStatistics();
- if (driverStatistics == NULL) {
- panic("Kext %s was not a DriverKit OSKext", bundleID->getCStringNoCopy());
- }
- IOLog("Driver %s has crashed %zu time(s)\n", bundleID->getCStringNoCopy(), driverStatistics->getCrashCount());
- reslide = driverStatistics->getCrashCount() > 0;
- } else {
- DKLOG("Could not find OSKext for %s\n", bundleID->getCStringNoCopy());
- return NULL;
+
+ IORecursiveLockLock(gDriverKitLaunchLock);
+
+ if (gDriverKitLaunches == NULL) {
+ // About to shut down, don't launch anything
+ goto finish;
}
if (reuseIfExists) {
@@ -6975,136 +5749,53 @@
}
}
+ // Find existing server
if (reuseIfExists) {
- // Check provider's user server, if exists
- if (provider->reserved && provider->reserved->uvars && (providerServer = provider->reserved->uvars->userServer) != NULL) {
- OSString * providerServerName = OSDynamicCast(OSString, providerServer->getProperty(gIOUserServerNameKey));
- if (providerServerName && providerServerName->isEqualTo(serverName)) {
- // Reuse is required
-
- DKLOG("using existing server " DKS " from provider " DKS "\n", DKN(providerServer), DKN(provider));
-
- // If provider has the user server that we are supposed to reuse, and it has become inactive
- // start of this service should simply fail
- // If the user server become inactive after this check, start should fail at a later stage
- if (!providerServer->isInactive()) {
- providerServer->retain();
- me = providerServer;
- } else {
- DKLOG(DKS " cannot reuse inactive server\n", DKN(service));
- // Must not create a token as reuse is required
- }
+ token = IOUserServerCheckInToken::findExistingToken(serverName);
+ if (token) {
+ // Launch in progress, return token
+ goto finish;
+ } else {
+ // Check if launch completed
+ matching = IOService::serviceMatching(gIOUserServerClassKey);
+ if (!matching) {
goto finish;
}
- }
- }
-
- do {
- const OSSymbol * tokenServerName;
- OSNumber * tokenServerTag;
-
- IORecursiveLockLock(gDriverKitLaunchLock);
-
- if (gDriverKitLaunches == NULL) {
- // About to shut down, don't launch anything
- IORecursiveLockUnlock(gDriverKitLaunchLock);
- goto finish;
- }
-
- // Find existing server
- if (reuseIfExists) {
- token = IOUserServerCheckInToken::findExistingToken(serverName);
- if (!token) {
- // Check if launch completed
-
- matching = IOService::serviceMatching(gIOUserServerClassKey);
- if (!matching) {
- IORecursiveLockUnlock(gDriverKitLaunchLock);
- goto finish;
- }
- IOService::propertyMatching(gIOUserServerNameKey, serverName, matching);
- IOService * service = IOService::copyMatchingService(matching);
- IOUserServer * userServer = OSDynamicCast(IOUserServer, service);
- if (userServer) {
- // found existing user server
- me = userServer;
- IORecursiveLockUnlock(gDriverKitLaunchLock);
- goto finish;
- } else {
- OSSafeReleaseNULL(service);
- }
- }
- }
-
- if (!token) {
- // No existing server, request launch
- token = new IOUserServerCheckInToken;
- if (!token) {
- IORecursiveLockUnlock(gDriverKitLaunchLock);
+ IOService::propertyMatching(gIOUserServerNameKey, serverName, matching);
+ IOService * service = IOService::copyMatchingService(matching);
+ IOUserServer * userServer = OSDynamicCast(IOUserServer, service);
+ if (userServer) {
+ // found existing user server
+ me = userServer;
goto finish;
- }
-
- /*
- * TODO: If the init fails because the personalities are not up to date
- * restart the whole matching process.
- */
- if (token && !token->init(serverName, serverTag, driverKext, serverDUI)) {
- DKLOG(DKS " could not initialize token\n", DKN(service));
- IORecursiveLockUnlock(gDriverKitLaunchLock);
- OSSafeReleaseNULL(token);
- goto finish;
- }
-
- /*
- * If the launch fails at any point terminate() will
- * be called on this IOUserServer.
- */
- gDriverKitLaunches->setObject(token);
- OSKext::requestDaemonLaunch(bundleID, (OSString *)serverName, serverTag, reslide ? kOSBooleanTrue : kOSBooleanFalse, token, serverDUI);
- }
-
- IORecursiveLockUnlock(gDriverKitLaunchLock);
-
- tokenServerName = token->copyServerName();
- tokenServerTag = token->copyServerTag();
- assert(tokenServerName && tokenServerTag);
- DKLOG(DKS " waiting for server %s-%llx\n", DKN(service), tokenServerName->getCStringNoCopy(), tokenServerTag->unsigned64BitValue());
-
- me = __WAITING_FOR_USER_SERVER__(token, &timeRemainingMS);
- if (me) {
- OSSafeReleaseNULL(tokenServerName);
- OSSafeReleaseNULL(tokenServerTag);
- break;
- }
- DKLOG(DKS " failed to find server %s-%llx, remaining %llums, retries %u\n", DKN(service),
- tokenServerName->getCStringNoCopy(), tokenServerTag->unsigned64BitValue(), timeRemainingMS, retries - 1);
- OSSafeReleaseNULL(tokenServerName);
- OSSafeReleaseNULL(tokenServerTag);
+ } else {
+ OSSafeReleaseNULL(service);
+ }
+ }
+ }
+
+ // No existing server, request launch
+ token = new IOUserServerCheckInToken;
+ if (!token) {
+ goto finish;
+ }
+ if (token && !token->init(serverName, serverTag)) {
OSSafeReleaseNULL(token);
- // If the loop continues it means the dext has been killed
- // We don't record a crash since start never happened. No client code has run
- } while (--retries && timeRemainingMS && !gInUserspaceReboot);
-
- if (me) {
- DKLOG(DKS " server launched, validating\n", DKN(service));
- if (token && !(kIODKDisableCheckInTokenVerification & gIODKDebug)) {
- if (!me->serviceMatchesCheckInToken(token)) {
- DKLOG(DKS " server does not match token\n", DKN(service));
- me->exit("Check In Token verification failed");
- OSSafeReleaseNULL(me);
- }
- }
+ goto finish;
+ }
+
+ gDriverKitLaunches->setObject(token);
+ OSKext::requestDaemonLaunch(bundleID, (OSString *)serverName, serverTag, token);
+
+finish:
+ IORecursiveLockUnlock(gDriverKitLaunchLock);
+ OSSafeReleaseNULL(matching);
+
+ if (resultToken) {
+ *resultToken = token;
} else {
-#if DEVELOPMENT || DEBUG
- driverkit_checkin_timed_out = mach_absolute_time();
-#endif
- }
-
-finish:
- OSSafeReleaseNULL(matching);
- OSSafeReleaseNULL(driverStatistics);
- OSSafeReleaseNULL(driverKext);
- OSSafeReleaseNULL(token);
+ OSSafeReleaseNULL(token);
+ }
return me;
}
@@ -7149,6 +5840,7 @@
const OSSymbol * tokenServerName = token->fServerName;
if (tokenServerName->isEqualTo(serverName)) {
assert(token->fState == kIOUserServerCheckInPending);
+ token->fPendingCount++;
result = token;
result->retain();
}
@@ -7457,6 +6149,7 @@
public:
virtual bool init() override;
+ OSDictionary * fSchema;
OSDictionary * fValue;
OSSet * fListeners;
};
@@ -7525,24 +6218,6 @@
ret = me->StateNotificationItemCreate(gIOSystemStateSleepDescriptionKey, NULL);
assert(kIOReturnSuccess == ret);
- gIOSystemStateWakeDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionKey);
- gIOSystemStateWakeDescriptionWakeReasonKey = OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionWakeReasonKey);
- gIOSystemStateWakeDescriptionContinuousTimeOffsetKey = OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionContinuousTimeOffsetKey);
-
-#if defined(__arm__) || defined(__arm64__)
- // Make ml_get_conttime_offset available before systemPower
- OSDictionary * wakeDescription = OSDictionary::withCapacity(1);
- OSObject * prop = OSNumber::withNumber(ml_get_conttime_offset(), sizeof(uint64_t) * CHAR_BIT);
- wakeDescription->setObject(gIOSystemStateWakeDescriptionContinuousTimeOffsetKey, prop);
- ret = me->StateNotificationItemCreate(gIOSystemStateWakeDescriptionKey, wakeDescription);
- OSSafeReleaseNULL(prop);
- OSSafeReleaseNULL(wakeDescription);
- assert(kIOReturnSuccess == ret);
-#else /* !defined(__arm__) && !defined(__arm64__) */
- ret = me->StateNotificationItemCreate(gIOSystemStateWakeDescriptionKey, NULL);
- assert(kIOReturnSuccess == ret);
-#endif /* defined(__arm__) || defined(__arm64__) */
-
gIOSystemStateHaltDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateHaltDescriptionKey);
gIOSystemStateHaltDescriptionHaltStateKey = OSSymbol::withCStringNoCopy(kIOSystemStateHaltDescriptionHaltStateKey);
@@ -7593,6 +6268,7 @@
{
kern_return_t kr;
OSDictionary * dict;
+ OSDictionary * schema;
OSDictionary * value;
OSString * itemName;
@@ -7601,16 +6277,9 @@
return kIOReturnBadArgument;
}
- if (!IOCurrentTaskHasEntitlement(kIOSystemStateEntitlement)) {
- return kIOReturnNotPermitted;
- }
-
- if ((value = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemCreateKey)))) {
- itemName = OSDynamicCast(OSString, value->getObject(kIOStateNotificationNameKey));
- itemName->retain();
- value->removeObject(kIOStateNotificationNameKey);
- kr = StateNotificationItemCreate(itemName, value);
- itemName->release();
+ if ((schema = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemCreateKey)))) {
+ itemName = OSDynamicCast(OSString, schema->getObject(kIOStateNotificationNameKey));
+ kr = StateNotificationItemCreate(itemName, schema);
} else if ((value = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemSetKey)))) {
itemName = OSDynamicCast(OSString, value->getObject(kIOStateNotificationNameKey));
itemName->retain();
@@ -7637,7 +6306,7 @@
}
IOStateNotificationItem *
-IOService::stateNotificationItemCopy(OSString * itemName, OSDictionary * initialValue)
+IOService::stateNotificationItemCopy(OSString * itemName, OSDictionary * schema)
{
IOServiceStateChangeVars * ivars = reserved->svars;
@@ -7654,10 +6323,13 @@
item->init();
item->fListeners = OSSet::withCapacity(16);
- if (initialValue) {
- initialValue->retain();
- item->fValue = initialValue;
- }
+ if (schema) {
+ schema->retain();
+ } else {
+ schema = OSDictionary::withCapacity(8);
+ }
+ schema->setObject(kIOStateNotificationNameKey, name);
+ item->fSchema = schema;
ivars->fItems->setObject(name, item);
}
IOLockUnlock(ivars->fLock);
@@ -7668,11 +6340,11 @@
}
kern_return_t
-IOService::StateNotificationItemCreate_Impl(OSString * itemName, OSDictionary * value)
+IOService::StateNotificationItemCreate_Impl(OSString * itemName, OSDictionary * schema)
{
IOStateNotificationItem * item;
- item = stateNotificationItemCopy(itemName, value);
+ item = stateNotificationItemCopy(itemName, schema);
if (!item) {
return kIOReturnNoMemory;
}
@@ -7684,27 +6356,20 @@
kern_return_t
IOService::StateNotificationItemSet_Impl(OSString * itemName, OSDictionary * value)
{
- kern_return_t ret = kIOReturnSuccess;
IOServiceStateChangeVars * ivars = reserved->svars;
- OSSet * listeners = NULL;
- IOStateNotificationItem * item;
+ OSSet * listeners;
+ IOStateNotificationItem * item;
value->retain();
IOLockLock(ivars->fLock);
- do {
- item = (typeof(item))ivars->fItems->getObject(itemName);
- if (!item) {
- ret = kIOReturnNotFound;
- value->release();
- break;
- }
- OSSafeReleaseNULL(item->fValue);
- item->fValue = value;
- if (item->fListeners->getCount()) {
- listeners = OSSet::withSet(item->fListeners);
- }
- } while (false);
+ item = (typeof(item))ivars->fItems->getObject(itemName);
+ OSSafeReleaseNULL(item->fValue);
+ item->fValue = value;
+ listeners = NULL;
+ if (item->fListeners->getCount()) {
+ listeners = OSSet::withSet(item->fListeners);
+ }
IOLockUnlock(ivars->fLock);
if (listeners) {
@@ -7718,7 +6383,7 @@
OSSafeReleaseNULL(listeners);
}
- return ret;
+ return kIOReturnSuccess;
}
kern_return_t