RootDomainUserClient.cpp [plain text]
#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include "RootDomainUserClient.h"
#include <IOKit/pwr_mgt/IOPMLibDefs.h>
#include <IOKit/pwr_mgt/IOPMPrivate.h>
#include <sys/proc.h>
#define super IOUserClient
OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient)
bool
RootDomainUserClient::initWithTask(task_t owningTask, void *security_id,
UInt32 type, OSDictionary * properties)
{
if (properties) {
properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue);
}
if (!super::initWithTask(owningTask, security_id, type, properties)) {
return false;
}
fOwningTask = owningTask;
task_reference(fOwningTask);
return true;
}
bool
RootDomainUserClient::start( IOService * provider )
{
assert(OSDynamicCast(IOPMrootDomain, provider));
if (!super::start(provider)) {
return false;
}
fOwner = (IOPMrootDomain *)provider;
return true;
}
IOReturn
RootDomainUserClient::secureSleepSystem( uint32_t *return_code )
{
return secureSleepSystemOptions(NULL, 0, return_code);
}
IOReturn
RootDomainUserClient::secureSleepSystemOptions(
const void *inOptions,
IOByteCount inOptionsSize,
uint32_t *returnCode)
{
int local_priv = 0;
int admin_priv = 0;
IOReturn ret = kIOReturnNotPrivileged;
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser);
local_priv = (kIOReturnSuccess == ret);
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
admin_priv = (kIOReturnSuccess == ret);
if ((local_priv || admin_priv) && fOwner) {
OSString *unserializeErrorString = NULL;
OSObject *unserializedObject = NULL;
OSDictionary *sleepOptionsDict = NULL;
proc_t p;
p = (proc_t)get_bsdtask_info(fOwningTask);
if (p) {
fOwner->setProperty("SleepRequestedByPID", proc_pid(p), 32);
}
if (inOptions) {
unserializedObject = OSUnserializeXML((const char *)inOptions, inOptionsSize, &unserializeErrorString);
sleepOptionsDict = OSDynamicCast( OSDictionary, unserializedObject);
if (!sleepOptionsDict) {
IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n",
unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown");
}
}
if (sleepOptionsDict) {
fOwner->setProperty( kRootDomainSleepOptionsKey, sleepOptionsDict);
} else {
fOwner->removeProperty( kRootDomainSleepOptionsKey );
}
*returnCode = fOwner->sleepSystemOptions( sleepOptionsDict );
OSSafeReleaseNULL(unserializedObject);
OSSafeReleaseNULL(unserializeErrorString);
} else {
*returnCode = kIOReturnNotPrivileged;
}
return kIOReturnSuccess;
}
IOReturn
RootDomainUserClient::secureSetAggressiveness(
unsigned long type,
unsigned long newLevel,
int *return_code )
{
int local_priv = 0;
int admin_priv = 0;
IOReturn ret = kIOReturnNotPrivileged;
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);
} else {
*return_code = kIOReturnNotPrivileged;
}
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 )
{
terminate();
return kIOReturnSuccess;
}
void
RootDomainUserClient::stop( IOService *provider)
{
if (fOwningTask) {
task_deallocate(fOwningTask);
fOwningTask = NULL;
}
super::stop(provider);
}
IOReturn
RootDomainUserClient::externalMethod(
uint32_t selector,
IOExternalMethodArguments * arguments,
IOExternalMethodDispatch * dispatch __unused,
OSObject * target __unused,
void * reference __unused )
{
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:
ret = kIOReturnUnsupported;
break;
case kPMRestartSystem:
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
case kPMSetDisplayPowerOn:
if (1 == arguments->scalarInputCount) {
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
if (ret == kIOReturnSuccess) {
fOwner->setDisplayPowerOn((uint32_t)arguments->scalarInput[0]);
}
}
break;
default:
return kIOReturnBadArgument;
}
return ret;
}
IOExternalMethod *
RootDomainUserClient::getTargetAndMethodForIndex(
IOService ** targetP, UInt32 index )
{
return super::getTargetAndMethodForIndex(targetP, index);
}
void
RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep)
{
return;
}