X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/2d21ac55c334faf3a56e5634905ed6987fc787d4..5ba3f43ea354af8ad55bea84372a2bc834d8757c:/iokit/Kernel/RootDomainUserClient.cpp diff --git a/iokit/Kernel/RootDomainUserClient.cpp b/iokit/Kernel/RootDomainUserClient.cpp index 170ab0eae..7a909d998 100644 --- a/iokit/Kernel/RootDomainUserClient.cpp +++ b/iokit/Kernel/RootDomainUserClient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1998-2012 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -36,6 +36,8 @@ #include #include "RootDomainUserClient.h" #include +#include +#include #define super IOUserClient @@ -45,17 +47,17 @@ OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -bool RootDomainUserClient::initWithTask(task_t owningTask, void *security_id, - UInt32 type, OSDictionary * properties) +bool RootDomainUserClient::initWithTask(task_t owningTask, void *security_id, + UInt32 type, OSDictionary * properties) { if (properties) - properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); + properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); if (!super::initWithTask(owningTask, security_id, type, properties)) - return false; + return false; fOwningTask = owningTask; - task_reference (fOwningTask); + task_reference (fOwningTask); return true; } @@ -73,23 +75,14 @@ bool RootDomainUserClient::start( IOService * provider ) IOReturn RootDomainUserClient::secureSleepSystem( uint32_t *return_code ) { - IOByteCount return_code_size = 1; - - return secureSleepSystemOptions( NULL, // inOptions - (void *)return_code, // returnCode - (void *)0, // inSize - (void *)&return_code_size, // returnSize - NULL, NULL); + return secureSleepSystemOptions(NULL, 0, return_code); } -IOReturn RootDomainUserClient::secureSleepSystemOptions( - void * p1, void * p2, void * p3, - void * p4, void * p5, void * p6 ) +IOReturn RootDomainUserClient::secureSleepSystemOptions( + const void *inOptions, + IOByteCount inOptionsSize, + uint32_t *returnCode) { - void *inOptions = (void *)p1; - uint32_t *returnCode = (uint32_t *)p2; - IOByteCount inOptionsSize = (IOByteCount)p3; - IOByteCount *returnCodeSize = (IOByteCount *)p4; int local_priv = 0; int admin_priv = 0; @@ -99,40 +92,44 @@ IOReturn RootDomainUserClient::secureSleepSystemOptions( ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); local_priv = (kIOReturnSuccess == ret); - + ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); admin_priv = (kIOReturnSuccess == ret); - - *returnCodeSize = sizeof(uint32_t); - + + if (inOptions) { unserializedOptions = OSDynamicCast( OSDictionary, - OSUnserializeXML((const char *)inOptions, &unserializeErrorString)); - + OSUnserializeXML((const char *)inOptions, inOptionsSize, &unserializeErrorString)); + if (!unserializedOptions) { - IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n", + IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n", unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown"); } } - if ( (local_priv || admin_priv) - && fOwner ) + if ( (local_priv || admin_priv) && fOwner ) { - if (unserializedOptions) + proc_t p; + p = (proc_t)get_bsdtask_info(fOwningTask); + if (p) { + fOwner->setProperty("SleepRequestedByPID", proc_pid(p), 32); + } + + if (unserializedOptions) { // Publish Sleep Options in registry under root_domain - fOwner->setProperty( kRootDomainSleepOptionsKey, unserializedOptions); + fOwner->setProperty( kRootDomainSleepOptionsKey, unserializedOptions); *returnCode = fOwner->sleepSystemOptions( unserializedOptions ); - unserializedOptions->release(); + unserializedOptions->release(); } else { // No options // Clear any pre-existing options fOwner->removeProperty( kRootDomainSleepOptionsKey ); - *returnCode = fOwner->sleepSystemOptions( NULL ); + *returnCode = fOwner->sleepSystemOptions( NULL ); } } else { @@ -142,7 +139,7 @@ IOReturn RootDomainUserClient::secureSleepSystemOptions( return kIOReturnSuccess; } -IOReturn RootDomainUserClient::secureSetAggressiveness( +IOReturn RootDomainUserClient::secureSetAggressiveness( unsigned long type, unsigned long newLevel, int *return_code ) @@ -153,122 +150,244 @@ IOReturn RootDomainUserClient::secureSetAggressiveness( ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); local_priv = (kIOReturnSuccess == ret); - + ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); admin_priv = (kIOReturnSuccess == ret); if((local_priv || admin_priv) && fOwner) { *return_code = fOwner->setAggressiveness(type, newLevel); - return kIOReturnSuccess; } else { *return_code = kIOReturnNotPrivileged; - return kIOReturnSuccess; } + return kIOReturnSuccess; +} + +IOReturn RootDomainUserClient::secureSetMaintenanceWakeCalendar( + IOPMCalendarStruct *inCalendar, + uint32_t *returnCode) +{ + int admin_priv = 0; + IOReturn ret = kIOReturnNotPrivileged; + + ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); + admin_priv = (kIOReturnSuccess == ret); + if (admin_priv && fOwner) { + *returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar); + } else { + *returnCode = kIOReturnNotPrivileged; + } + return kIOReturnSuccess; } +IOReturn RootDomainUserClient::secureSetUserAssertionLevels( + uint32_t assertionBitfield) +{ + int admin_priv = 0; + IOReturn ret = kIOReturnNotPrivileged; + + ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); + admin_priv = (kIOReturnSuccess == ret); + + if (admin_priv && fOwner) { + ret = fOwner->setPMAssertionUserLevels(assertionBitfield); + } else { + ret = kIOReturnNotPrivileged; + } + return kIOReturnSuccess; +} + +IOReturn RootDomainUserClient::secureGetSystemSleepType( + uint32_t *outSleepType, uint32_t *sleepTimer) +{ + int admin_priv = 0; + IOReturn ret; + + ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); + admin_priv = (kIOReturnSuccess == ret); + + if (admin_priv && fOwner) { + ret = fOwner->getSystemSleepType(outSleepType, sleepTimer); + } else { + ret = kIOReturnNotPrivileged; + } + return ret; +} IOReturn RootDomainUserClient::clientClose( void ) { - detach(fOwner); - - if(fOwningTask) { - task_deallocate(fOwningTask); - fOwningTask = 0; - } - + terminate(); + return kIOReturnSuccess; } -IOExternalMethod * -RootDomainUserClient::getTargetAndMethodForIndex( IOService ** targetP, UInt32 index ) +void RootDomainUserClient::stop( IOService *provider) { - static const IOExternalMethod sMethods[] = { - { // kPMSetAggressiveness, 0 - (IOService *)1, (IOMethod)&RootDomainUserClient::secureSetAggressiveness, kIOUCScalarIScalarO, 2, 1 - }, - { // kPMGetAggressiveness, 1 - 0, (IOMethod)&IOPMrootDomain::getAggressiveness, kIOUCScalarIScalarO, 1, 1 - }, - { // kPMSleepSystem, 2 - (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystem, kIOUCScalarIScalarO, 0, 1 - }, - { // kPMAllowPowerChange, 3 - 0, (IOMethod)&IOPMrootDomain::allowPowerChange, kIOUCScalarIScalarO, 1, 0 - }, - { // kPMCancelPowerChange, 4 - 0, (IOMethod)&IOPMrootDomain::cancelPowerChange, kIOUCScalarIScalarO, 1, 0 - }, - { // kPMShutdownSystem, 5 - 0, (IOMethod)&IOPMrootDomain::shutdownSystem, kIOUCScalarIScalarO, 0, 0 - }, - { // kPMRestartSystem, 6 - 0, (IOMethod)&IOPMrootDomain::restartSystem, kIOUCScalarIScalarO, 0, 0 - }, - { // kPMSleepSystemOptions, 7 - (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystemOptions, - kIOUCStructIStructO, kIOUCVariableStructureSize, sizeof(uint32_t) - } - }; - - if(index >= kNumPMMethods) - return NULL; - else { - if (sMethods[index].object) - *targetP = this; - else - *targetP = fOwner; - - return (IOExternalMethod *)&sMethods[index]; + if(fOwningTask) { + task_deallocate(fOwningTask); + fOwningTask = 0; } + + super::stop(provider); } -#if 0 -IOReturn RootDomainUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args, - IOExternalMethodDispatch * dispatch, OSObject * target, void * reference ) +IOReturn RootDomainUserClient::externalMethod( + uint32_t selector, + IOExternalMethodArguments * arguments, + IOExternalMethodDispatch * dispatch __unused, + OSObject * target __unused, + void * reference __unused ) { - static const IOExternalMethodDispatch sMethods[] = { - { // kPMSetAggressiveness, 0 - (IOService *)1, (IOMethod)&RootDomainUserClient::secureSetAggressiveness, kIOUCScalarIScalarO, 2, 1 - }, - { // kPMGetAggressiveness, 1 - 0, (IOMethod)&IOPMrootDomain::getAggressiveness, kIOUCScalarIScalarO, 1, 1 - }, - { // kPMSleepSystem, 2 - (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystem, kIOUCScalarIScalarO, 0, 1 - }, - { // kPMAllowPowerChange, 3 - 0, (IOMethod)&IOPMrootDomain::allowPowerChange, kIOUCScalarIScalarO, 1, 0 - }, - { // kPMCancelPowerChange, 4 - 0, (IOMethod)&IOPMrootDomain::cancelPowerChange, kIOUCScalarIScalarO, 1, 0 - }, - { // kPMShutdownSystem, 5 - 0, (IOMethod)&IOPMrootDomain::shutdownSystem, kIOUCScalarIScalarO, 0, 0 - }, - { // kPMRestartSystem, 6 - 0, (IOMethod)&IOPMrootDomain::restartSystem, kIOUCScalarIScalarO, 0, 0 - }, - { // kPMSetPreventative, 7 - (IOService *)1, (IOMethod)&RootDomainUserClient::setPreventative, kIOUCScalarIScalarO, 2, 0 - }, - }; - - if (selector > (sizeof(sMethods) / sizeof(sMethods[0]))) - return (kIOReturnBadArgument); - - if ((1 << selector) & ((1 << 0) | (1 << 7)) - target = this; - else - target = fOwner; - - return (super::externalMethod(selector, args, &sMethods[selector], target, 0)); -} + IOReturn ret = kIOReturnBadArgument; + + switch (selector) + { + case kPMSetAggressiveness: + if ((2 == arguments->scalarInputCount) + && (1 == arguments->scalarOutputCount)) + { + ret = this->secureSetAggressiveness( + (unsigned long)arguments->scalarInput[0], + (unsigned long)arguments->scalarInput[1], + (int *)&arguments->scalarOutput[0]); + } + break; + + case kPMGetAggressiveness: + if ((1 == arguments->scalarInputCount) + && (1 == arguments->scalarOutputCount)) + { + ret = fOwner->getAggressiveness( + (unsigned long)arguments->scalarInput[0], + (unsigned long *)&arguments->scalarOutput[0]); + } + break; + + case kPMSleepSystem: + if (1 == arguments->scalarOutputCount) + { + ret = this->secureSleepSystem( + (uint32_t *)&arguments->scalarOutput[0]); + } + break; + + case kPMAllowPowerChange: + if (1 == arguments->scalarInputCount) + { + ret = fOwner->allowPowerChange( + arguments->scalarInput[0]); + } + break; + + case kPMCancelPowerChange: + if (1 == arguments->scalarInputCount) + { + ret = fOwner->cancelPowerChange( + arguments->scalarInput[0]); + } + break; + + case kPMShutdownSystem: + // deperecated interface + ret = kIOReturnUnsupported; + break; + + case kPMRestartSystem: + // deperecated interface + ret = kIOReturnUnsupported; + break; + + case kPMSleepSystemOptions: + ret = this->secureSleepSystemOptions( + arguments->structureInput, + arguments->structureInputSize, + (uint32_t *)&arguments->scalarOutput[0]); + break; + case kPMSetMaintenanceWakeCalendar: + if ((arguments->structureInputSize >= sizeof(IOPMCalendarStruct)) && + (arguments->structureOutputSize >= sizeof(uint32_t) )) { + ret = this->secureSetMaintenanceWakeCalendar( + (IOPMCalendarStruct *)arguments->structureInput, + (uint32_t *)&arguments->structureOutput); + arguments->structureOutputSize = sizeof(uint32_t); + } + break; + + case kPMSetUserAssertionLevels: + ret = this->secureSetUserAssertionLevels( + (uint32_t)arguments->scalarInput[0]); + break; + + case kPMActivityTickle: + if ( fOwner->checkSystemCanSustainFullWake() ) + { + fOwner->reportUserInput( ); + fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion"); + } + ret = kIOReturnSuccess; + break; + + case kPMSetClamshellSleepState: + fOwner->setDisableClamShellSleep(arguments->scalarInput[0] ? true : false); + ret = kIOReturnSuccess; + break; + + case kPMGetSystemSleepType: + if (2 == arguments->scalarOutputCount) + { + ret = this->secureGetSystemSleepType( + (uint32_t *) &arguments->scalarOutput[0], + (uint32_t *) &arguments->scalarOutput[1]); + } + break; + +#if defined(__i386__) || defined(__x86_64__) + case kPMSleepWakeWatchdogEnable: + ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); + if (ret == kIOReturnSuccess) + fOwner->sleepWakeDebugEnableWdog(); + break; + + + case kPMSleepWakeDebugTrig: + ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); + if (ret == kIOReturnSuccess) + fOwner->sleepWakeDebugTrig(false); + break; #endif -void -RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) + case kPMSetDisplayPowerOn: + if (1 == arguments->scalarInputCount) + { + ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); + if (ret == kIOReturnSuccess) + fOwner->setDisplayPowerOn((uint32_t)arguments->scalarInput[0]); + } + break; + + default: + // bad selector + return kIOReturnBadArgument; + } + + return ret; +} + +/* getTargetAndMethodForIndex + * Not used. We prefer to use externalMethod() for user client invocations. + * We maintain getTargetAndExternalMethod since it's an exported symbol, + * and only for that reason. + */ +IOExternalMethod * RootDomainUserClient::getTargetAndMethodForIndex( + IOService ** targetP, UInt32 index ) { - return; + // DO NOT EDIT + return super::getTargetAndMethodForIndex(targetP, index); } +/* setPreventative + * Does nothing. Exists only for exported symbol compatibility. + */ +void +RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) +{ return; } // DO NOT EDIT