1 /* 2 * Copyright (c) 1998-2020 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* 29 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 30 * 31 */ 32 33 #include <IOKit/assert.h> 34 #include <IOKit/IOLib.h> 35 #include <IOKit/IOKitKeys.h> 36 #include <IOKit/IOBufferMemoryDescriptor.h> 37 #include "RootDomainUserClient.h" 38 #include <IOKit/pwr_mgt/IOPMLibDefs.h> 39 #include <IOKit/pwr_mgt/IOPMPrivate.h> 40 #include <sys/proc.h> 41 42 #define super IOUserClient 43 44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 45 46 OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient) 47 48 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 49 50 bool 51 RootDomainUserClient::initWithTask(task_t owningTask, void *security_id, 52 UInt32 type, OSDictionary * properties) 53 { 54 if (properties) { 55 properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); 56 } 57 58 if (!super::initWithTask(owningTask, security_id, type, properties)) { 59 return false; 60 } 61 62 fOwningTask = owningTask; 63 task_reference(fOwningTask); 64 return true; 65 } 66 67 68 bool 69 RootDomainUserClient::start( IOService * provider ) 70 { 71 assert(OSDynamicCast(IOPMrootDomain, provider)); 72 if (!super::start(provider)) { 73 return false; 74 } 75 fOwner = (IOPMrootDomain *)provider; 76 77 78 return true; 79 } 80 81 IOReturn 82 RootDomainUserClient::secureSleepSystem( uint32_t *return_code ) 83 { 84 return secureSleepSystemOptions(NULL, 0, return_code); 85 } 86 87 IOReturn 88 RootDomainUserClient::secureSleepSystemOptions( 89 const void *inOptions, 90 IOByteCount inOptionsSize, 91 uint32_t *returnCode) 92 { 93 int local_priv = 0; 94 int admin_priv = 0; 95 IOReturn ret = kIOReturnNotPrivileged; 96 97 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 98 local_priv = (kIOReturnSuccess == ret); 99 100 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 101 admin_priv = (kIOReturnSuccess == ret); 102 103 if ((local_priv || admin_priv) && fOwner) { 104 OSString *unserializeErrorString = NULL; 105 OSObject *unserializedObject = NULL; 106 OSDictionary *sleepOptionsDict = NULL; // do not release 107 108 proc_t p; 109 p = (proc_t)get_bsdtask_info(fOwningTask); 110 if (p) { 111 fOwner->setProperty("SleepRequestedByPID", proc_pid(p), 32); 112 } 113 114 if (inOptions) { 115 unserializedObject = OSUnserializeXML((const char *)inOptions, inOptionsSize, &unserializeErrorString); 116 sleepOptionsDict = OSDynamicCast( OSDictionary, unserializedObject); 117 if (!sleepOptionsDict) { 118 IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n", 119 unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown"); 120 } 121 } 122 123 if (sleepOptionsDict) { 124 // Publish Sleep Options in registry under root_domain 125 fOwner->setProperty( kRootDomainSleepOptionsKey, sleepOptionsDict); 126 } else { 127 // No options 128 // Clear any pre-existing options 129 fOwner->removeProperty( kRootDomainSleepOptionsKey ); 130 } 131 132 *returnCode = fOwner->sleepSystemOptions( sleepOptionsDict ); 133 OSSafeReleaseNULL(unserializedObject); 134 OSSafeReleaseNULL(unserializeErrorString); 135 } else { 136 *returnCode = kIOReturnNotPrivileged; 137 } 138 139 return kIOReturnSuccess; 140 } 141 142 IOReturn 143 RootDomainUserClient::secureSetAggressiveness( 144 unsigned long type, 145 unsigned long newLevel, 146 int *return_code ) 147 { 148 int local_priv = 0; 149 int admin_priv = 0; 150 IOReturn ret = kIOReturnNotPrivileged; 151 152 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 153 local_priv = (kIOReturnSuccess == ret); 154 155 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 156 admin_priv = (kIOReturnSuccess == ret); 157 158 if ((local_priv || admin_priv) && fOwner) { 159 *return_code = fOwner->setAggressiveness(type, newLevel); 160 } else { 161 *return_code = kIOReturnNotPrivileged; 162 } 163 return kIOReturnSuccess; 164 } 165 166 IOReturn 167 RootDomainUserClient::secureSetMaintenanceWakeCalendar( 168 IOPMCalendarStruct *inCalendar, 169 uint32_t *returnCode) 170 { 171 int admin_priv = 0; 172 IOReturn ret = kIOReturnNotPrivileged; 173 174 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 175 admin_priv = (kIOReturnSuccess == ret); 176 177 if (admin_priv && fOwner) { 178 *returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar); 179 } else { 180 *returnCode = kIOReturnNotPrivileged; 181 } 182 return kIOReturnSuccess; 183 } 184 185 IOReturn 186 RootDomainUserClient::secureSetUserAssertionLevels( 187 uint32_t assertionBitfield) 188 { 189 int admin_priv = 0; 190 IOReturn ret = kIOReturnNotPrivileged; 191 192 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 193 admin_priv = (kIOReturnSuccess == ret); 194 195 if (admin_priv && fOwner) { 196 ret = fOwner->setPMAssertionUserLevels(assertionBitfield); 197 } else { 198 ret = kIOReturnNotPrivileged; 199 } 200 return kIOReturnSuccess; 201 } 202 203 IOReturn 204 RootDomainUserClient::secureGetSystemSleepType( 205 uint32_t *outSleepType, uint32_t *sleepTimer) 206 { 207 int admin_priv = 0; 208 IOReturn ret; 209 210 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 211 admin_priv = (kIOReturnSuccess == ret); 212 213 if (admin_priv && fOwner) { 214 ret = fOwner->getSystemSleepType(outSleepType, sleepTimer); 215 } else { 216 ret = kIOReturnNotPrivileged; 217 } 218 return ret; 219 } 220 221 IOReturn 222 RootDomainUserClient::clientClose( void ) 223 { 224 terminate(); 225 226 return kIOReturnSuccess; 227 } 228 229 void 230 RootDomainUserClient::stop( IOService *provider) 231 { 232 if (fOwningTask) { 233 task_deallocate(fOwningTask); 234 fOwningTask = NULL; 235 } 236 237 super::stop(provider); 238 } 239 240 IOReturn 241 RootDomainUserClient::externalMethod( 242 uint32_t selector, 243 IOExternalMethodArguments * arguments, 244 IOExternalMethodDispatch * dispatch __unused, 245 OSObject * target __unused, 246 void * reference __unused ) 247 { 248 IOReturn ret = kIOReturnBadArgument; 249 250 switch (selector) { 251 case kPMSetAggressiveness: 252 if ((2 == arguments->scalarInputCount) 253 && (1 == arguments->scalarOutputCount)) { 254 ret = this->secureSetAggressiveness( 255 (unsigned long)arguments->scalarInput[0], 256 (unsigned long)arguments->scalarInput[1], 257 (int *)&arguments->scalarOutput[0]); 258 } 259 break; 260 261 case kPMGetAggressiveness: 262 if ((1 == arguments->scalarInputCount) 263 && (1 == arguments->scalarOutputCount)) { 264 ret = fOwner->getAggressiveness( 265 (unsigned long)arguments->scalarInput[0], 266 (unsigned long *)&arguments->scalarOutput[0]); 267 } 268 break; 269 270 case kPMSleepSystem: 271 if (1 == arguments->scalarOutputCount) { 272 ret = this->secureSleepSystem( 273 (uint32_t *)&arguments->scalarOutput[0]); 274 } 275 break; 276 277 case kPMAllowPowerChange: 278 if (1 == arguments->scalarInputCount) { 279 ret = fOwner->allowPowerChange( 280 arguments->scalarInput[0]); 281 } 282 break; 283 284 case kPMCancelPowerChange: 285 if (1 == arguments->scalarInputCount) { 286 ret = fOwner->cancelPowerChange( 287 arguments->scalarInput[0]); 288 } 289 break; 290 291 case kPMShutdownSystem: 292 // deperecated interface 293 ret = kIOReturnUnsupported; 294 break; 295 296 case kPMRestartSystem: 297 // deperecated interface 298 ret = kIOReturnUnsupported; 299 break; 300 301 case kPMSleepSystemOptions: 302 ret = this->secureSleepSystemOptions( 303 arguments->structureInput, 304 arguments->structureInputSize, 305 (uint32_t *)&arguments->scalarOutput[0]); 306 break; 307 case kPMSetMaintenanceWakeCalendar: 308 if ((arguments->structureInputSize >= sizeof(IOPMCalendarStruct)) && 309 (arguments->structureOutputSize >= sizeof(uint32_t))) { 310 ret = this->secureSetMaintenanceWakeCalendar( 311 (IOPMCalendarStruct *)arguments->structureInput, 312 (uint32_t *)&arguments->structureOutput); 313 arguments->structureOutputSize = sizeof(uint32_t); 314 } 315 break; 316 317 case kPMSetUserAssertionLevels: 318 ret = this->secureSetUserAssertionLevels( 319 (uint32_t)arguments->scalarInput[0]); 320 break; 321 322 case kPMActivityTickle: 323 if (fOwner->checkSystemCanSustainFullWake()) { 324 fOwner->reportUserInput(); 325 fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion"); 326 } 327 ret = kIOReturnSuccess; 328 break; 329 330 case kPMSetClamshellSleepState: 331 fOwner->setClamShellSleepDisable(arguments->scalarInput[0] ? true : false, 332 IOPMrootDomain::kClamshellSleepDisablePowerd); 333 ret = kIOReturnSuccess; 334 break; 335 336 case kPMGetSystemSleepType: 337 if (2 == arguments->scalarOutputCount) { 338 ret = this->secureGetSystemSleepType( 339 (uint32_t *) &arguments->scalarOutput[0], 340 (uint32_t *) &arguments->scalarOutput[1]); 341 } 342 break; 343 344 #if defined(__i386__) || defined(__x86_64__) 345 case kPMSleepWakeWatchdogEnable: 346 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 347 if (ret == kIOReturnSuccess) { 348 fOwner->sleepWakeDebugEnableWdog(); 349 } 350 break; 351 352 353 case kPMSleepWakeDebugTrig: 354 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 355 if (ret == kIOReturnSuccess) { 356 fOwner->sleepWakeDebugTrig(false); 357 } 358 break; 359 #endif 360 361 case kPMSetDisplayPowerOn: 362 if (1 == arguments->scalarInputCount) { 363 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 364 if (ret == kIOReturnSuccess) { 365 fOwner->setDisplayPowerOn((uint32_t)arguments->scalarInput[0]); 366 } 367 } 368 break; 369 370 default: 371 // bad selector 372 return kIOReturnBadArgument; 373 } 374 375 return ret; 376 } 377 378 /* getTargetAndMethodForIndex 379 * Not used. We prefer to use externalMethod() for user client invocations. 380 * We maintain getTargetAndExternalMethod since it's an exported symbol, 381 * and only for that reason. 382 */ 383 IOExternalMethod * 384 RootDomainUserClient::getTargetAndMethodForIndex( 385 IOService ** targetP, UInt32 index ) 386 { 387 // DO NOT EDIT 388 return super::getTargetAndMethodForIndex(targetP, index); 389 } 390 391 /* setPreventative 392 * Does nothing. Exists only for exported symbol compatibility. 393 */ 394 void 395 RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) 396 { 397 return; 398 } // DO NOT EDIT 399