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::clientClose( void ) 228 { 229 terminate(); 230 231 return kIOReturnSuccess; 232 } 233 234 void 235 RootDomainUserClient::stop( IOService *provider) 236 { 237 if (fOwningTask) { 238 task_deallocate(fOwningTask); 239 fOwningTask = NULL; 240 } 241 242 super::stop(provider); 243 } 244 245 IOReturn 246 RootDomainUserClient::externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * args ) 247 { 248 static const IOExternalMethodDispatch2022 dispatchArray[] = { 249 [kPMSetAggressiveness] = { 250 .function = &RootDomainUserClient::externalMethodDispatched, 251 .checkScalarInputCount = 2, 252 .checkStructureInputSize = 0, 253 .checkScalarOutputCount = 1, 254 .checkStructureOutputSize = 0, 255 .allowAsync = false, 256 .checkEntitlement = NULL, 257 }, 258 [kPMGetAggressiveness] = { 259 .function = &RootDomainUserClient::externalMethodDispatched, 260 .checkScalarInputCount = 1, 261 .checkStructureInputSize = 0, 262 .checkScalarOutputCount = 1, 263 .checkStructureOutputSize = 0, 264 .allowAsync = false, 265 .checkEntitlement = NULL, 266 }, 267 [kPMSleepSystem] = { 268 .function = &RootDomainUserClient::externalMethodDispatched, 269 .checkScalarInputCount = 0, 270 .checkStructureInputSize = 0, 271 .checkScalarOutputCount = 1, 272 .checkStructureOutputSize = 0, 273 .allowAsync = false, 274 .checkEntitlement = NULL, 275 }, 276 [kPMAllowPowerChange] = { 277 .function = &RootDomainUserClient::externalMethodDispatched, 278 .checkScalarInputCount = 1, 279 .checkStructureInputSize = 0, 280 .checkScalarOutputCount = 0, 281 .checkStructureOutputSize = 0, 282 .allowAsync = false, 283 .checkEntitlement = NULL, 284 }, 285 [kPMCancelPowerChange] = { 286 .function = &RootDomainUserClient::externalMethodDispatched, 287 .checkScalarInputCount = 1, 288 .checkStructureInputSize = 0, 289 .checkScalarOutputCount = 0, 290 .checkStructureOutputSize = 0, 291 .allowAsync = false, 292 .checkEntitlement = NULL, 293 }, 294 [kPMShutdownSystem] = { 295 .function = &RootDomainUserClient::externalMethodDispatched, 296 .checkScalarInputCount = 0, 297 .checkStructureInputSize = 0, 298 .checkScalarOutputCount = 0, 299 .checkStructureOutputSize = 0, 300 .allowAsync = false, 301 .checkEntitlement = NULL, 302 }, 303 [kPMRestartSystem] = { 304 .function = &RootDomainUserClient::externalMethodDispatched, 305 .checkScalarInputCount = 0, 306 .checkStructureInputSize = 0, 307 .checkScalarOutputCount = 0, 308 .checkStructureOutputSize = 0, 309 .allowAsync = false, 310 .checkEntitlement = NULL, 311 }, 312 [kPMSleepSystemOptions] = { 313 .function = &RootDomainUserClient::externalMethodDispatched, 314 .checkScalarInputCount = 0, 315 .checkStructureInputSize = kIOUCVariableStructureSize, 316 .checkScalarOutputCount = 0, 317 .checkStructureOutputSize = sizeof(uint32_t), 318 .allowAsync = false, 319 .checkEntitlement = NULL, 320 }, 321 [kPMSetMaintenanceWakeCalendar] = { 322 .function = &RootDomainUserClient::externalMethodDispatched, 323 .checkScalarInputCount = 0, 324 .checkStructureInputSize = sizeof(IOPMCalendarStruct), 325 .checkScalarOutputCount = 0, 326 .checkStructureOutputSize = sizeof(uint32_t), 327 .allowAsync = false, 328 .checkEntitlement = NULL, 329 }, 330 [kPMSetUserAssertionLevels] = { 331 .function = &RootDomainUserClient::externalMethodDispatched, 332 .checkScalarInputCount = 1, 333 .checkStructureInputSize = 0, 334 .checkScalarOutputCount = 0, 335 .checkStructureOutputSize = 0, 336 .allowAsync = false, 337 .checkEntitlement = NULL, 338 }, 339 [kPMActivityTickle] = { 340 .function = &RootDomainUserClient::externalMethodDispatched, 341 .checkScalarInputCount = 0, 342 .checkStructureInputSize = 0, 343 .checkScalarOutputCount = 0, 344 .checkStructureOutputSize = 0, 345 .allowAsync = false, 346 .checkEntitlement = NULL, 347 }, 348 [kPMSetClamshellSleepState] = { 349 .function = &RootDomainUserClient::externalMethodDispatched, 350 .checkScalarInputCount = 1, 351 .checkStructureInputSize = 0, 352 .checkScalarOutputCount = 0, 353 .checkStructureOutputSize = 0, 354 .allowAsync = false, 355 .checkEntitlement = NULL, 356 }, 357 [kPMGetSystemSleepType] = { 358 .function = &RootDomainUserClient::externalMethodDispatched, 359 .checkScalarInputCount = 0, 360 .checkStructureInputSize = 0, 361 .checkScalarOutputCount = 2, 362 .checkStructureOutputSize = 0, 363 .allowAsync = false, 364 .checkEntitlement = NULL, 365 }, 366 [kPMSleepWakeWatchdogEnable] = { 367 .function = &RootDomainUserClient::externalMethodDispatched, 368 .checkScalarInputCount = 0, 369 .checkStructureInputSize = 0, 370 .checkScalarOutputCount = 0, 371 .checkStructureOutputSize = 0, 372 .allowAsync = false, 373 .checkEntitlement = NULL, 374 }, 375 [kPMSleepWakeDebugTrig] = { 376 .function = &RootDomainUserClient::externalMethodDispatched, 377 .checkScalarInputCount = 0, 378 .checkStructureInputSize = 0, 379 .checkScalarOutputCount = 0, 380 .checkStructureOutputSize = 0, 381 .allowAsync = false, 382 .checkEntitlement = NULL, 383 }, 384 [kPMSetDisplayPowerOn] = { 385 .function = &RootDomainUserClient::externalMethodDispatched, 386 .checkScalarInputCount = 1, 387 .checkStructureInputSize = 0, 388 .checkScalarOutputCount = 0, 389 .checkStructureOutputSize = 0, 390 .allowAsync = false, 391 .checkEntitlement = NULL, 392 }, 393 }; 394 395 return dispatchExternalMethod(selector, args, dispatchArray, sizeof(dispatchArray) / sizeof(dispatchArray[0]), this, NULL); 396 } 397 IOReturn 398 RootDomainUserClient::externalMethodDispatched(OSObject * target, void * reference, IOExternalMethodArguments * arguments) 399 { 400 IOReturn ret = kIOReturnBadArgument; 401 RootDomainUserClient * me = (typeof(me))target; 402 switch (arguments->selector) { 403 case kPMSetAggressiveness: 404 ret = me->secureSetAggressiveness( 405 (unsigned long)arguments->scalarInput[0], 406 (unsigned long)arguments->scalarInput[1], 407 (int *)&arguments->scalarOutput[0]); 408 break; 409 410 case kPMGetAggressiveness: 411 ret = me->fOwner->getAggressiveness( 412 (unsigned long)arguments->scalarInput[0], 413 (unsigned long *)&arguments->scalarOutput[0]); 414 break; 415 416 case kPMSleepSystem: 417 ret = me->secureSleepSystem( 418 (uint32_t *)&arguments->scalarOutput[0]); 419 break; 420 421 case kPMAllowPowerChange: 422 ret = me->fOwner->allowPowerChange( 423 arguments->scalarInput[0]); 424 break; 425 426 case kPMCancelPowerChange: 427 ret = me->fOwner->cancelPowerChange( 428 arguments->scalarInput[0]); 429 break; 430 431 case kPMShutdownSystem: 432 // deprecated interface 433 ret = kIOReturnUnsupported; 434 break; 435 436 case kPMRestartSystem: 437 // deprecated interface 438 ret = kIOReturnUnsupported; 439 break; 440 441 case kPMSleepSystemOptions: 442 ret = me->secureSleepSystemOptions( 443 arguments->structureInput, 444 arguments->structureInputSize, 445 (uint32_t *)&arguments->structureOutput); 446 break; 447 case kPMSetMaintenanceWakeCalendar: 448 ret = me->secureSetMaintenanceWakeCalendar( 449 (IOPMCalendarStruct *)arguments->structureInput, 450 (uint32_t *)&arguments->structureOutput); 451 arguments->structureOutputSize = sizeof(uint32_t); 452 break; 453 454 case kPMSetUserAssertionLevels: 455 ret = me->secureSetUserAssertionLevels( 456 (uint32_t)arguments->scalarInput[0]); 457 break; 458 459 case kPMActivityTickle: 460 if (me->fOwner->checkSystemCanSustainFullWake()) { 461 me->fOwner->reportUserInput(); 462 me->fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion"); 463 } 464 ret = kIOReturnSuccess; 465 break; 466 467 case kPMSetClamshellSleepState: 468 me->fOwner->setClamShellSleepDisable(arguments->scalarInput[0] ? true : false, 469 IOPMrootDomain::kClamshellSleepDisablePowerd); 470 ret = kIOReturnSuccess; 471 break; 472 473 case kPMGetSystemSleepType: 474 ret = me->secureGetSystemSleepType( 475 (uint32_t *) &arguments->scalarOutput[0], 476 (uint32_t *) &arguments->scalarOutput[1]); 477 break; 478 479 #if defined(__i386__) || defined(__x86_64__) 480 case kPMSleepWakeWatchdogEnable: 481 ret = clientHasPrivilege(me->fOwningTask, kIOClientPrivilegeAdministrator); 482 if (ret == kIOReturnSuccess) { 483 me->fOwner->sleepWakeDebugEnableWdog(); 484 } 485 break; 486 487 488 case kPMSleepWakeDebugTrig: 489 ret = clientHasPrivilege(me->fOwningTask, kIOClientPrivilegeAdministrator); 490 if (ret == kIOReturnSuccess) { 491 me->fOwner->sleepWakeDebugTrig(false); 492 } 493 break; 494 #endif 495 496 case kPMSetDisplayPowerOn: 497 ret = clientHasPrivilege(me->fOwningTask, kIOClientPrivilegeAdministrator); 498 if (ret == kIOReturnSuccess) { 499 me->fOwner->setDisplayPowerOn((uint32_t)arguments->scalarInput[0]); 500 } 501 break; 502 503 default: 504 // bad selector 505 return kIOReturnBadArgument; 506 } 507 508 return ret; 509 } 510 511 /* getTargetAndMethodForIndex 512 * Not used. We prefer to use externalMethod() for user client invocations. 513 * We maintain getTargetAndExternalMethod since it's an exported symbol, 514 * and only for that reason. 515 */ 516 IOExternalMethod * 517 RootDomainUserClient::getTargetAndMethodForIndex( 518 IOService ** targetP, UInt32 index ) 519 { 520 // DO NOT EDIT 521 return super::getTargetAndMethodForIndex(targetP, index); 522 } 523 524 /* setPreventative 525 * Does nothing. Exists only for exported symbol compatibility. 526 */ 527 void 528 RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) 529 { 530 return; 531 } // DO NOT EDIT 532