Loading...
--- xnu/xnu-10063.141.1/iokit/Kernel/RootDomainUserClient.cpp
+++ xnu/xnu-12377.121.6/iokit/Kernel/RootDomainUserClient.cpp
@@ -34,6 +34,8 @@
#include <IOKit/IOLib.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
+#include <IOKit/IOSubMemoryDescriptor.h>
+#include <AssertMacros.h>
#include "RootDomainUserClient.h"
#include <IOKit/pwr_mgt/IOPMLibDefs.h>
#include <IOKit/pwr_mgt/IOPMPrivate.h>
@@ -224,9 +226,92 @@
}
IOReturn
+RootDomainUserClient::secureAttemptIdleSleepAbort(
+ uint32_t *outReverted)
+{
+ int admin_priv = 0;
+ IOReturn ret;
+
+ ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
+ admin_priv = (kIOReturnSuccess == ret);
+
+ if (admin_priv && fOwner) {
+ *outReverted = (uint32_t) fOwner->attemptIdleSleepAbort();
+ } else {
+ ret = kIOReturnNotPrivileged;
+ }
+ return ret;
+}
+
+IOReturn
+RootDomainUserClient::secureSetLockdownModeHibernation(
+ uint32_t status)
+{
+#if HIBERNATION
+ int admin_priv = 0;
+ IOReturn ret;
+
+ ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
+ admin_priv = (kIOReturnSuccess == ret);
+
+ if (admin_priv && fOwner) {
+ fOwner->setLockdownModeHibernation(status);
+ } else {
+ ret = kIOReturnNotPrivileged;
+ }
+ return kIOReturnSuccess;
+#else
+ return kIOReturnError;
+#endif
+}
+
+IOReturn
+RootDomainUserClient::secureGetAssertionLog(
+ IOPMAssertionLogData *outLog)
+{
+ if (!fOwner) {
+ return kIOReturnError;
+ }
+
+ return fOwner->getAssertionLog(outLog);
+}
+
+IOReturn
+RootDomainUserClient::secureSetAssertionLogNotificationThreshold(
+ uint64_t threshold)
+{
+ if (!fOwner) {
+ return kIOReturnError;
+ }
+
+ return fOwner->setAssertionLogNotificationThreshold(threshold);
+}
+
+IOReturn
+RootDomainUserClient::secureSetAssertionLogNotificationPort(
+ mach_port_t port)
+{
+ if (!fOwner) {
+ return kIOReturnError;
+ }
+
+ IOReturn ret = fOwner->setAssertionLogNotificationPort(port);
+
+ if (ret == kIOReturnSuccess) {
+ fAssertionLogNotificationPortRegistered = (port != MACH_PORT_NULL);
+ }
+
+ return ret;
+}
+
+IOReturn
RootDomainUserClient::clientClose( void )
{
terminate();
+
+ if (fAssertionLogNotificationPortRegistered) {
+ secureSetAssertionLogNotificationPort(MACH_PORT_NULL);
+ }
return kIOReturnSuccess;
}
@@ -243,6 +328,17 @@
}
IOReturn
+RootDomainUserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon)
+{
+ switch ((IOPMUserClientNotificationType)type) {
+ case IOPMUserClientNotificationType_AssertionLog:
+ return secureSetAssertionLogNotificationPort(port);
+ }
+
+ return kIOReturnSuccess;
+}
+
+IOReturn
RootDomainUserClient::externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * args )
{
static const IOExternalMethodDispatch2022 dispatchArray[] = {
@@ -390,6 +486,42 @@
.allowAsync = false,
.checkEntitlement = NULL,
},
+ [kPMRequestIdleSleepRevert] = {
+ .function = &RootDomainUserClient::externalMethodDispatched,
+ .checkScalarInputCount = 0,
+ .checkStructureInputSize = 0,
+ .checkScalarOutputCount = 1,
+ .checkStructureOutputSize = 0,
+ .allowAsync = false,
+ .checkEntitlement = NULL,
+ },
+ [kPMSetLDMHibernationDisable] = {
+ .function = &RootDomainUserClient::externalMethodDispatched,
+ .checkScalarInputCount = 1,
+ .checkStructureInputSize = 0,
+ .checkScalarOutputCount = 0,
+ .checkStructureOutputSize = 0,
+ .allowAsync = false,
+ .checkEntitlement = NULL,
+ },
+ [kPMGetAssertionLog] = {
+ .function = &RootDomainUserClient::externalMethodDispatched,
+ .checkScalarInputCount = 0,
+ .checkStructureInputSize = 0,
+ .checkScalarOutputCount = 0,
+ .checkStructureOutputSize = sizeof(IOPMAssertionLogData),
+ .allowAsync = false,
+ .checkEntitlement = NULL,
+ },
+ [kPMSetAssertionLogThreshold] = {
+ .function = &RootDomainUserClient::externalMethodDispatched,
+ .checkScalarInputCount = 1,
+ .checkStructureInputSize = 0,
+ .checkScalarOutputCount = 0,
+ .checkStructureOutputSize = 0,
+ .allowAsync = false,
+ .checkEntitlement = NULL,
+ },
};
return dispatchExternalMethod(selector, args, dispatchArray, sizeof(dispatchArray) / sizeof(dispatchArray[0]), this, NULL);
@@ -397,8 +529,24 @@
IOReturn
RootDomainUserClient::externalMethodDispatched(OSObject * target, void * reference, IOExternalMethodArguments * arguments)
{
- IOReturn ret = kIOReturnBadArgument;
- RootDomainUserClient * me = (typeof(me))target;
+ IOReturn ret = kIOReturnBadArgument;
+ RootDomainUserClient *me = (typeof(me))target;
+ IOMemoryDescriptor *outMD = nullptr;
+ IOMemoryMap *outMap = nullptr;
+
+ if (arguments->structureOutputSize > 0 || arguments->structureOutputDescriptorSize > 0) {
+ if (arguments->structureOutputDescriptor) {
+ outMD = arguments->structureOutputDescriptor;
+ outMD->retain();
+ } else {
+ outMD = IOMemoryDescriptor::withAddressRange((mach_vm_address_t)arguments->structureOutput, arguments->structureOutputSize, kIODirectionIn, kernel_task);
+ }
+
+ require_action(outMD != nullptr, out, ret = kIOReturnError);
+ outMap = outMD->map();
+ require_action(outMap != nullptr, out, ret = kIOReturnError);
+ }
+
switch (arguments->selector) {
case kPMSetAggressiveness:
ret = me->secureSetAggressiveness(
@@ -484,7 +632,6 @@
}
break;
-
case kPMSleepWakeDebugTrig:
ret = clientHasPrivilege(me->fOwningTask, kIOClientPrivilegeAdministrator);
if (ret == kIOReturnSuccess) {
@@ -500,10 +647,37 @@
}
break;
+ case kPMRequestIdleSleepRevert:
+ ret = me->secureAttemptIdleSleepAbort(
+ (uint32_t *) &arguments->scalarOutput[0]);
+ break;
+
+ case kPMSetLDMHibernationDisable:
+ ret = me->secureSetLockdownModeHibernation((uint32_t)arguments->scalarInput[0]);
+ break;
+
+ case kPMGetAssertionLog:
+ require_action(outMap != nullptr, out, ret = kIOReturnBadArgument);
+ ret = me->secureGetAssertionLog((IOPMAssertionLogData *)outMap->getAddress());
+ break;
+
+ case kPMSetAssertionLogThreshold:
+ ret = me->secureSetAssertionLogNotificationThreshold(arguments->scalarInput[0]);
+ break;
+
default:
// bad selector
- return kIOReturnBadArgument;
- }
+ ret = kIOReturnBadArgument;
+ break;
+ }
+
+out:
+ if (outMap) {
+ outMap->unmap();
+ }
+
+ OSSafeReleaseNULL(outMap);
+ OSSafeReleaseNULL(outMD);
return ret;
}