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 IOUserClient2022 43 44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 45 46 OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient2022) 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 setProperty(kIOUserClientDefaultLockingKey, kOSBooleanTrue); 78 setProperty(kIOUserClientDefaultLockingSetPropertiesKey, kOSBooleanTrue); 79 setProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey, kOSBooleanFalse); 80 81 setProperty(kIOUserClientEntitlementsKey, kOSBooleanFalse); 82 83 return true; 84 } 85 86 IOReturn 87 RootDomainUserClient::secureSleepSystem( uint32_t *return_code ) 88 { 89 return secureSleepSystemOptions(NULL, 0, return_code); 90 } 91 92 IOReturn 93 RootDomainUserClient::secureSleepSystemOptions( 94 const void *inOptions, 95 IOByteCount inOptionsSize, 96 uint32_t *returnCode) 97 { 98 int local_priv = 0; 99 int admin_priv = 0; 100 IOReturn ret = kIOReturnNotPrivileged; 101 102 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 103 local_priv = (kIOReturnSuccess == ret); 104 105 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 106 admin_priv = (kIOReturnSuccess == ret); 107 108 if ((local_priv || admin_priv) && fOwner) { 109 OSString *unserializeErrorString = NULL; 110 OSObject *unserializedObject = NULL; 111 OSDictionary *sleepOptionsDict = NULL; // do not release 112 113 proc_t p; 114 p = (proc_t)get_bsdtask_info(fOwningTask); 115 if (p) { 116 fOwner->setProperty("SleepRequestedByPID", proc_pid(p), 32); 117 } 118 119 if (inOptions) { 120 unserializedObject = OSUnserializeXML((const char *)inOptions, inOptionsSize, &unserializeErrorString); 121 sleepOptionsDict = OSDynamicCast( OSDictionary, unserializedObject); 122 if (!sleepOptionsDict) { 123 IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n", 124 unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown"); 125 } 126 } 127 128 if (sleepOptionsDict) { 129 // Publish Sleep Options in registry under root_domain 130 fOwner->setProperty( kRootDomainSleepOptionsKey, sleepOptionsDict); 131 } else { 132 // No options 133 // Clear any pre-existing options 134 fOwner->removeProperty( kRootDomainSleepOptionsKey ); 135 } 136 137 *returnCode = fOwner->sleepSystemOptions( sleepOptionsDict ); 138 OSSafeReleaseNULL(unserializedObject); 139 OSSafeReleaseNULL(unserializeErrorString); 140 } else { 141 *returnCode = kIOReturnNotPrivileged; 142 } 143 144 return kIOReturnSuccess; 145 } 146 147 IOReturn 148 RootDomainUserClient::secureSetAggressiveness( 149 unsigned long type, 150 unsigned long newLevel, 151 int *return_code ) 152 { 153 int local_priv = 0; 154 int admin_priv = 0; 155 IOReturn ret = kIOReturnNotPrivileged; 156 157 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 158 local_priv = (kIOReturnSuccess == ret); 159 160 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 161 admin_priv = (kIOReturnSuccess == ret); 162 163 if ((local_priv || admin_priv) && fOwner) { 164 *return_code = fOwner->setAggressiveness(type, newLevel); 165 } else { 166 *return_code = kIOReturnNotPrivileged; 167 } 168 return kIOReturnSuccess; 169 } 170 171 IOReturn 172 RootDomainUserClient::secureSetMaintenanceWakeCalendar( 173 IOPMCalendarStruct *inCalendar, 174 uint32_t *returnCode) 175 { 176 int admin_priv = 0; 177 IOReturn ret = kIOReturnNotPrivileged; 178 179 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 180 admin_priv = (kIOReturnSuccess == ret); 181 182 if (admin_priv && fOwner) { 183 *returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar); 184 } else { 185 *returnCode = kIOReturnNotPrivileged; 186 } 187 return kIOReturnSuccess; 188 } 189 190 IOReturn 191 RootDomainUserClient::secureSetUserAssertionLevels( 192 uint32_t assertionBitfield) 193 { 194 int admin_priv = 0; 195 IOReturn ret = kIOReturnNotPrivileged; 196 197 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 198 admin_priv = (kIOReturnSuccess == ret); 199 200 if (admin_priv && fOwner) { 201 ret = fOwner->setPMAssertionUserLevels(assertionBitfield); 202 } else { 203 ret = kIOReturnNotPrivileged; 204 } 205 return kIOReturnSuccess; 206 } 207 208 IOReturn 209 RootDomainUserClient::secureGetSystemSleepType( 210 uint32_t *outSleepType, uint32_t *sleepTimer) 211 { 212 int admin_priv = 0; 213 IOReturn ret; 214 215 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 216 admin_priv = (kIOReturnSuccess == ret); 217 218 if (admin_priv && fOwner) { 219 ret = fOwner->getSystemSleepType(outSleepType, sleepTimer); 220 } else { 221 ret = kIOReturnNotPrivileged; 222 } 223 return ret; 224 } 225 226 IOReturn 227 RootDomainUserClient::secureAttemptIdleSleepAbort( 228 uint32_t *outReverted) 229 { 230 int admin_priv = 0; 231 IOReturn ret; 232 233 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 234 admin_priv = (kIOReturnSuccess == ret); 235 236 if (admin_priv && fOwner) { 237 *outReverted = (uint32_t) fOwner->attemptIdleSleepAbort(); 238 } else { 239 ret = kIOReturnNotPrivileged; 240 } 241 return ret; 242 } 243 244 IOReturn 245 RootDomainUserClient::clientClose( void ) 246 { 247 terminate(); 248 249 return kIOReturnSuccess; 250 } 251 252 void 253 RootDomainUserClient::stop( IOService *provider) 254 { 255 if (fOwningTask) { 256 task_deallocate(fOwningTask); 257 fOwningTask = NULL; 258 } 259 260 super::stop(provider); 261 } 262 263 IOReturn 264 RootDomainUserClient::externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * args ) 265 { 266 static const IOExternalMethodDispatch2022 dispatchArray[] = { 267 [kPMSetAggressiveness] = { 268 .function = &RootDomainUserClient::externalMethodDispatched, 269 .checkScalarInputCount = 2, 270 .checkStructureInputSize = 0, 271 .checkScalarOutputCount = 1, 272 .checkStructureOutputSize = 0, 273 .allowAsync = false, 274 .checkEntitlement = NULL, 275 }, 276 [kPMGetAggressiveness] = { 277 .function = &RootDomainUserClient::externalMethodDispatched, 278 .checkScalarInputCount = 1, 279 .checkStructureInputSize = 0, 280 .checkScalarOutputCount = 1, 281 .checkStructureOutputSize = 0, 282 .allowAsync = false, 283 .checkEntitlement = NULL, 284 }, 285 [kPMSleepSystem] = { 286 .function = &RootDomainUserClient::externalMethodDispatched, 287 .checkScalarInputCount = 0, 288 .checkStructureInputSize = 0, 289 .checkScalarOutputCount = 1, 290 .checkStructureOutputSize = 0, 291 .allowAsync = false, 292 .checkEntitlement = NULL, 293 }, 294 [kPMAllowPowerChange] = { 295 .function = &RootDomainUserClient::externalMethodDispatched, 296 .checkScalarInputCount = 1, 297 .checkStructureInputSize = 0, 298 .checkScalarOutputCount = 0, 299 .checkStructureOutputSize = 0, 300 .allowAsync = false, 301 .checkEntitlement = NULL, 302 }, 303 [kPMCancelPowerChange] = { 304 .function = &RootDomainUserClient::externalMethodDispatched, 305 .checkScalarInputCount = 1, 306 .checkStructureInputSize = 0, 307 .checkScalarOutputCount = 0, 308 .checkStructureOutputSize = 0, 309 .allowAsync = false, 310 .checkEntitlement = NULL, 311 }, 312 [kPMShutdownSystem] = { 313 .function = &RootDomainUserClient::externalMethodDispatched, 314 .checkScalarInputCount = 0, 315 .checkStructureInputSize = 0, 316 .checkScalarOutputCount = 0, 317 .checkStructureOutputSize = 0, 318 .allowAsync = false, 319 .checkEntitlement = NULL, 320 }, 321 [kPMRestartSystem] = { 322 .function = &RootDomainUserClient::externalMethodDispatched, 323 .checkScalarInputCount = 0, 324 .checkStructureInputSize = 0, 325 .checkScalarOutputCount = 0, 326 .checkStructureOutputSize = 0, 327 .allowAsync = false, 328 .checkEntitlement = NULL, 329 }, 330 [kPMSleepSystemOptions] = { 331 .function = &RootDomainUserClient::externalMethodDispatched, 332 .checkScalarInputCount = 0, 333 .checkStructureInputSize = kIOUCVariableStructureSize, 334 .checkScalarOutputCount = 0, 335 .checkStructureOutputSize = sizeof(uint32_t), 336 .allowAsync = false, 337 .checkEntitlement = NULL, 338 }, 339 [kPMSetMaintenanceWakeCalendar] = { 340 .function = &RootDomainUserClient::externalMethodDispatched, 341 .checkScalarInputCount = 0, 342 .checkStructureInputSize = sizeof(IOPMCalendarStruct), 343 .checkScalarOutputCount = 0, 344 .checkStructureOutputSize = sizeof(uint32_t), 345 .allowAsync = false, 346 .checkEntitlement = NULL, 347 }, 348 [kPMSetUserAssertionLevels] = { 349 .function = &RootDomainUserClient::externalMethodDispatched, 350 .checkScalarInputCount = 1, 351 .checkStructureInputSize = 0, 352 .checkScalarOutputCount = 0, 353 .checkStructureOutputSize = 0, 354 .allowAsync = false, 355 .checkEntitlement = NULL, 356 }, 357 [kPMActivityTickle] = { 358 .function = &RootDomainUserClient::externalMethodDispatched, 359 .checkScalarInputCount = 0, 360 .checkStructureInputSize = 0, 361 .checkScalarOutputCount = 0, 362 .checkStructureOutputSize = 0, 363 .allowAsync = false, 364 .checkEntitlement = NULL, 365 }, 366 [kPMSetClamshellSleepState] = { 367 .function = &RootDomainUserClient::externalMethodDispatched, 368 .checkScalarInputCount = 1, 369 .checkStructureInputSize = 0, 370 .checkScalarOutputCount = 0, 371 .checkStructureOutputSize = 0, 372 .allowAsync = false, 373 .checkEntitlement = NULL, 374 }, 375 [kPMGetSystemSleepType] = { 376 .function = &RootDomainUserClient::externalMethodDispatched, 377 .checkScalarInputCount = 0, 378 .checkStructureInputSize = 0, 379 .checkScalarOutputCount = 2, 380 .checkStructureOutputSize = 0, 381 .allowAsync = false, 382 .checkEntitlement = NULL, 383 }, 384 [kPMSleepWakeWatchdogEnable] = { 385 .function = &RootDomainUserClient::externalMethodDispatched, 386 .checkScalarInputCount = 0, 387 .checkStructureInputSize = 0, 388 .checkScalarOutputCount = 0, 389 .checkStructureOutputSize = 0, 390 .allowAsync = false, 391 .checkEntitlement = NULL, 392 }, 393 [kPMSleepWakeDebugTrig] = { 394 .function = &RootDomainUserClient::externalMethodDispatched, 395 .checkScalarInputCount = 0, 396 .checkStructureInputSize = 0, 397 .checkScalarOutputCount = 0, 398 .checkStructureOutputSize = 0, 399 .allowAsync = false, 400 .checkEntitlement = NULL, 401 }, 402 [kPMSetDisplayPowerOn] = { 403 .function = &RootDomainUserClient::externalMethodDispatched, 404 .checkScalarInputCount = 1, 405 .checkStructureInputSize = 0, 406 .checkScalarOutputCount = 0, 407 .checkStructureOutputSize = 0, 408 .allowAsync = false, 409 .checkEntitlement = NULL, 410 }, 411 [kPMRequestIdleSleepRevert] = { 412 .function = &RootDomainUserClient::externalMethodDispatched, 413 .checkScalarInputCount = 0, 414 .checkStructureInputSize = 0, 415 .checkScalarOutputCount = 1, 416 .checkStructureOutputSize = 0, 417 .allowAsync = false, 418 .checkEntitlement = NULL, 419 }, 420 }; 421 422 return dispatchExternalMethod(selector, args, dispatchArray, sizeof(dispatchArray) / sizeof(dispatchArray[0]), this, NULL); 423 } 424 IOReturn 425 RootDomainUserClient::externalMethodDispatched(OSObject * target, void * reference, IOExternalMethodArguments * arguments) 426 { 427 IOReturn ret = kIOReturnBadArgument; 428 RootDomainUserClient * me = (typeof(me))target; 429 switch (arguments->selector) { 430 case kPMSetAggressiveness: 431 ret = me->secureSetAggressiveness( 432 (unsigned long)arguments->scalarInput[0], 433 (unsigned long)arguments->scalarInput[1], 434 (int *)&arguments->scalarOutput[0]); 435 break; 436 437 case kPMGetAggressiveness: 438 ret = me->fOwner->getAggressiveness( 439 (unsigned long)arguments->scalarInput[0], 440 (unsigned long *)&arguments->scalarOutput[0]); 441 break; 442 443 case kPMSleepSystem: 444 ret = me->secureSleepSystem( 445 (uint32_t *)&arguments->scalarOutput[0]); 446 break; 447 448 case kPMAllowPowerChange: 449 ret = me->fOwner->allowPowerChange( 450 arguments->scalarInput[0]); 451 break; 452 453 case kPMCancelPowerChange: 454 ret = me->fOwner->cancelPowerChange( 455 arguments->scalarInput[0]); 456 break; 457 458 case kPMShutdownSystem: 459 // deprecated interface 460 ret = kIOReturnUnsupported; 461 break; 462 463 case kPMRestartSystem: 464 // deprecated interface 465 ret = kIOReturnUnsupported; 466 break; 467 468 case kPMSleepSystemOptions: 469 ret = me->secureSleepSystemOptions( 470 arguments->structureInput, 471 arguments->structureInputSize, 472 (uint32_t *)&arguments->structureOutput); 473 break; 474 case kPMSetMaintenanceWakeCalendar: 475 ret = me->secureSetMaintenanceWakeCalendar( 476 (IOPMCalendarStruct *)arguments->structureInput, 477 (uint32_t *)&arguments->structureOutput); 478 arguments->structureOutputSize = sizeof(uint32_t); 479 break; 480 481 case kPMSetUserAssertionLevels: 482 ret = me->secureSetUserAssertionLevels( 483 (uint32_t)arguments->scalarInput[0]); 484 break; 485 486 case kPMActivityTickle: 487 if (me->fOwner->checkSystemCanSustainFullWake()) { 488 me->fOwner->reportUserInput(); 489 me->fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion"); 490 } 491 ret = kIOReturnSuccess; 492 break; 493 494 case kPMSetClamshellSleepState: 495 me->fOwner->setClamShellSleepDisable(arguments->scalarInput[0] ? true : false, 496 IOPMrootDomain::kClamshellSleepDisablePowerd); 497 ret = kIOReturnSuccess; 498 break; 499 500 case kPMGetSystemSleepType: 501 ret = me->secureGetSystemSleepType( 502 (uint32_t *) &arguments->scalarOutput[0], 503 (uint32_t *) &arguments->scalarOutput[1]); 504 break; 505 506 #if defined(__i386__) || defined(__x86_64__) 507 case kPMSleepWakeWatchdogEnable: 508 ret = clientHasPrivilege(me->fOwningTask, kIOClientPrivilegeAdministrator); 509 if (ret == kIOReturnSuccess) { 510 me->fOwner->sleepWakeDebugEnableWdog(); 511 } 512 break; 513 514 case kPMSleepWakeDebugTrig: 515 ret = clientHasPrivilege(me->fOwningTask, kIOClientPrivilegeAdministrator); 516 if (ret == kIOReturnSuccess) { 517 me->fOwner->sleepWakeDebugTrig(false); 518 } 519 break; 520 #endif 521 522 case kPMSetDisplayPowerOn: 523 ret = clientHasPrivilege(me->fOwningTask, kIOClientPrivilegeAdministrator); 524 if (ret == kIOReturnSuccess) { 525 me->fOwner->setDisplayPowerOn((uint32_t)arguments->scalarInput[0]); 526 } 527 break; 528 529 case kPMRequestIdleSleepRevert: 530 ret = me->secureAttemptIdleSleepAbort( 531 (uint32_t *) &arguments->scalarOutput[0]); 532 break; 533 534 535 default: 536 // bad selector 537 return kIOReturnBadArgument; 538 } 539 540 return ret; 541 } 542 543 /* getTargetAndMethodForIndex 544 * Not used. We prefer to use externalMethod() for user client invocations. 545 * We maintain getTargetAndExternalMethod since it's an exported symbol, 546 * and only for that reason. 547 */ 548 IOExternalMethod * 549 RootDomainUserClient::getTargetAndMethodForIndex( 550 IOService ** targetP, UInt32 index ) 551 { 552 // DO NOT EDIT 553 return super::getTargetAndMethodForIndex(targetP, index); 554 } 555 556 /* setPreventative 557 * Does nothing. Exists only for exported symbol compatibility. 558 */ 559 void 560 RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) 561 { 562 return; 563 } // DO NOT EDIT 564