1 /* 2 * Copyright (c) 1998-2021 Apple 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 #include <IOKit/IORPC.h> 30 #include <IOKit/IOKitServer.h> 31 #include <IOKit/IOKitKeysPrivate.h> 32 #include <IOKit/IOKernelReportStructs.h> 33 #include <IOKit/IOUserClient.h> 34 #include <IOKit/IOService.h> 35 #include <IOKit/IORegistryEntry.h> 36 #include <IOKit/IOCatalogue.h> 37 #include <IOKit/IOMemoryDescriptor.h> 38 #include <IOKit/IOBufferMemoryDescriptor.h> 39 #include <IOKit/IOSubMemoryDescriptor.h> 40 #include <IOKit/IOMultiMemoryDescriptor.h> 41 #include <IOKit/IOMapper.h> 42 #include <IOKit/IOLib.h> 43 #include <IOKit/IOHibernatePrivate.h> 44 #include <IOKit/IOBSD.h> 45 #include <IOKit/system.h> 46 #include "IOServicePrivate.h" 47 #include <IOKit/IOUserServer.h> 48 #include <IOKit/IOInterruptEventSource.h> 49 #include <IOKit/IOTimerEventSource.h> 50 #include <IOKit/pwr_mgt/RootDomain.h> 51 #include <IOKit/pwr_mgt/IOPowerConnection.h> 52 #include <libkern/c++/OSAllocation.h> 53 #include <libkern/c++/OSKext.h> 54 #include <libkern/c++/OSSharedPtr.h> 55 #include <libkern/OSDebug.h> 56 #include <libkern/Block.h> 57 #include <kern/cs_blobs.h> 58 #include <kern/thread_call.h> 59 #include <os/atomic_private.h> 60 #include <sys/proc.h> 61 #include <sys/reboot.h> 62 #include <sys/codesign.h> 63 #include "IOKitKernelInternal.h" 64 65 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 66 67 #include <DriverKit/IODispatchQueue.h> 68 #include <DriverKit/OSObject.h> 69 #include <DriverKit/OSAction.h> 70 #include <DriverKit/IODispatchSource.h> 71 #include <DriverKit/IOInterruptDispatchSource.h> 72 #include <DriverKit/IOService.h> 73 #include <DriverKit/IOMemoryDescriptor.h> 74 #include <DriverKit/IOBufferMemoryDescriptor.h> 75 #include <DriverKit/IOMemoryMap.h> 76 #include <DriverKit/IODataQueueDispatchSource.h> 77 #include <DriverKit/IOServiceNotificationDispatchSource.h> 78 #include <DriverKit/IOServiceStateNotificationDispatchSource.h> 79 #include <DriverKit/IOEventLink.h> 80 #include <DriverKit/IOWorkGroup.h> 81 #include <DriverKit/IOUserServer.h> 82 83 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 84 85 #include <System/IODataQueueDispatchSourceShared.h> 86 87 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 88 89 TUNABLE(SInt64, gIODKDebug, "dk", kIODKEnable); 90 91 #if DEBUG || DEVELOPMENT 92 TUNABLE(bool, disable_dext_crash_reboot, "disable_dext_crash_reboot", 0); 93 #endif /* DEBUG || DEVELOPMENT */ 94 95 extern bool restore_boot; 96 97 static OSString * gIOSystemStateSleepDescriptionKey; 98 static const OSSymbol * gIOSystemStateSleepDescriptionReasonKey; 99 static const OSSymbol * gIOSystemStateSleepDescriptionHibernateStateKey; 100 101 static OSString * gIOSystemStateWakeDescriptionKey; 102 static const OSSymbol * gIOSystemStateWakeDescriptionWakeReasonKey; 103 static const OSSymbol * gIOSystemStateWakeDescriptionContinuousTimeOffsetKey; 104 105 static OSString * gIOSystemStateHaltDescriptionKey; 106 static const OSSymbol * gIOSystemStateHaltDescriptionHaltStateKey; 107 108 static OSString * gIOSystemStatePowerSourceDescriptionKey; 109 static const OSSymbol * gIOSystemStatePowerSourceDescriptionACAttachedKey; 110 111 extern bool gInUserspaceReboot; 112 113 extern void iokit_clear_registered_ports(task_t task); 114 115 static IORPCMessage * 116 IORPCMessageFromMachReply(IORPCMessageMach * msg); 117 118 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 119 120 struct IOPStrings; 121 122 class OSUserMetaClass : public OSObject 123 { 124 OSDeclareDefaultStructors(OSUserMetaClass); 125 public: 126 const OSSymbol * name; 127 const OSMetaClass * meta; 128 OSUserMetaClass * superMeta; 129 130 queue_chain_t link; 131 132 OSClassDescription * description; 133 IOPStrings * queueNames; 134 uint32_t methodCount; 135 uint64_t * methods; 136 137 virtual void free() override; 138 virtual kern_return_t Dispatch(const IORPC rpc) APPLE_KEXT_OVERRIDE; 139 }; 140 OSDefineMetaClassAndStructors(OSUserMetaClass, OSObject); 141 142 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 143 144 class IOUserService : public IOService 145 { 146 friend class IOService; 147 148 OSDeclareDefaultStructors(IOUserService) 149 150 virtual bool 151 start(IOService * provider) APPLE_KEXT_OVERRIDE; 152 }; 153 154 OSDefineMetaClassAndStructors(IOUserService, IOService) 155 156 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 157 158 class IOUserUserClient : public IOUserClient 159 { 160 OSDeclareDefaultStructors(IOUserUserClient); 161 public: 162 task_t fTask; 163 OSDictionary * fWorkGroups; 164 OSDictionary * fEventLinks; 165 IOLock * fLock; 166 167 IOReturn setTask(task_t task); 168 IOReturn eventlinkConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6); 169 IOReturn workgroupConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6); 170 171 virtual bool init( OSDictionary * dictionary ) APPLE_KEXT_OVERRIDE; 172 virtual void free() APPLE_KEXT_OVERRIDE; 173 virtual void stop(IOService * provider) APPLE_KEXT_OVERRIDE; 174 virtual IOReturn clientClose(void) APPLE_KEXT_OVERRIDE; 175 virtual IOReturn setProperties(OSObject * properties) APPLE_KEXT_OVERRIDE; 176 virtual IOReturn externalMethod(uint32_t selector, IOExternalMethodArguments * args, 177 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) APPLE_KEXT_OVERRIDE; 178 virtual IOReturn clientMemoryForType(UInt32 type, 179 IOOptionBits * options, 180 IOMemoryDescriptor ** memory) APPLE_KEXT_OVERRIDE; 181 virtual IOExternalTrap * getTargetAndTrapForIndex( IOService **targetP, UInt32 index ) APPLE_KEXT_OVERRIDE; 182 }; 183 184 OSDefineMetaClassAndStructors(IOUserServerCheckInToken, OSObject); 185 OSDefineMetaClassAndStructors(_IOUserServerCheckInCancellationHandler, OSObject); 186 187 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 188 189 190 bool 191 IOUserService::start(IOService * provider) 192 { 193 bool ok = true; 194 IOReturn ret; 195 196 ret = Start(provider); 197 if (kIOReturnSuccess != ret) { 198 return false; 199 } 200 201 return ok; 202 } 203 204 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 205 206 #undef super 207 208 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 209 210 struct IODispatchQueue_IVars { 211 IOUserServer * userServer; 212 IODispatchQueue * queue; 213 queue_chain_t link; 214 uint64_t tid; 215 216 mach_port_t serverPort; 217 }; 218 219 struct OSAction_IVars { 220 OSObject * target; 221 uint64_t targetmsgid; 222 uint64_t msgid; 223 IOUserServer * userServer; 224 OSActionAbortedHandler abortedHandler; 225 OSString * typeName; 226 void * reference; 227 size_t referenceSize; 228 bool aborted; 229 }; 230 231 struct IOWorkGroup_IVars { 232 IOUserServer * userServer; 233 OSString * name; 234 IOUserUserClient * userClient; 235 }; 236 237 struct IOEventLink_IVars { 238 IOUserServer * userServer; 239 OSString * name; 240 IOUserUserClient * userClient; 241 }; 242 243 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 244 245 kern_return_t 246 IOService::GetRegistryEntryID_Impl( 247 uint64_t * registryEntryID) 248 { 249 IOReturn ret = kIOReturnSuccess; 250 251 *registryEntryID = getRegistryEntryID(); 252 253 return ret; 254 } 255 256 kern_return_t 257 IOService::SetName_Impl( 258 const char * name) 259 { 260 IOReturn ret = kIOReturnSuccess; 261 262 setName(name); 263 264 return ret; 265 } 266 267 kern_return_t 268 IOService::CopyName_Impl( 269 OSString ** name) 270 { 271 const OSString * str = copyName(); 272 *name = __DECONST(OSString *, str); 273 return str ? kIOReturnSuccess : kIOReturnError; 274 } 275 276 277 kern_return_t 278 IOService::Start_Impl( 279 IOService * provider) 280 { 281 IOReturn ret = kIOReturnSuccess; 282 return ret; 283 } 284 285 286 IOReturn 287 IOService::UpdateReport_Impl(OSData *channels, uint32_t action, 288 uint32_t *outElementCount, 289 uint64_t offset, uint64_t capacity, 290 IOMemoryDescriptor *buffer) 291 { 292 return kIOReturnUnsupported; 293 } 294 295 IOReturn 296 IOService::ConfigureReport_Impl(OSData *channels, uint32_t action, uint32_t *outCount) 297 { 298 return kIOReturnUnsupported; 299 } 300 301 // adapt old signature of configureReport to the iig-friendly signature of ConfigureReport 302 IOReturn 303 IOService::_ConfigureReport(IOReportChannelList *channelList, 304 IOReportConfigureAction action, 305 void *result, 306 void *destination) 307 { 308 if (action != kIOReportEnable && action != kIOReportGetDimensions && action != kIOReportDisable) { 309 return kIOReturnUnsupported; 310 } 311 static_assert(sizeof(IOReportChannelList) == 8); 312 static_assert(sizeof(IOReportChannel) == 16); 313 unsigned int size_of_channels; 314 bool overflow = os_mul_and_add_overflow(channelList->nchannels, sizeof(IOReportChannel), sizeof(IOReportChannelList), &size_of_channels); 315 if (overflow) { 316 return kIOReturnOverrun; 317 } 318 OSSharedPtr<OSData> sp_channels(OSData::withBytesNoCopy(channelList, size_of_channels), libkern::no_retain); 319 if (!sp_channels) { 320 return kIOReturnNoMemory; 321 } 322 int *resultp = (int*) result; 323 uint32_t count = 0; 324 IOReturn r = ConfigureReport(sp_channels.get(), action, &count); 325 int new_result; 326 overflow = os_add_overflow(*resultp, count, &new_result); 327 if (overflow) { 328 return kIOReturnOverrun; 329 } 330 *resultp = new_result; 331 return r; 332 } 333 334 // adapt old signature of updateReport to the iig-friendly signature of UpdateReport 335 IOReturn 336 IOService::_UpdateReport(IOReportChannelList *channelList, 337 IOReportUpdateAction action, 338 void *result, 339 void *destination) 340 { 341 if (action != kIOReportCopyChannelData) { 342 return kIOReturnUnsupported; 343 } 344 unsigned int size_of_channels; 345 bool overflow = os_mul_and_add_overflow(channelList->nchannels, sizeof(IOReportChannel), sizeof(IOReportChannelList), &size_of_channels); 346 if (overflow) { 347 return kIOReturnOverrun; 348 } 349 OSSharedPtr<OSData> sp_channels(OSData::withBytesNoCopy(channelList, size_of_channels), libkern::no_retain); 350 if (!sp_channels) { 351 return kIOReturnNoMemory; 352 } 353 int *resultp = (int*) result; 354 uint32_t count = 0; 355 auto buffer = (IOBufferMemoryDescriptor*) destination; 356 uint64_t length = buffer->getLength(); 357 buffer->setLength(buffer->getCapacity()); 358 IOReturn r = UpdateReport(sp_channels.get(), action, &count, length, buffer->getCapacity() - length, buffer); 359 int new_result; 360 overflow = os_add_overflow(*resultp, count, &new_result); 361 size_t new_length; 362 overflow = overflow || os_mul_and_add_overflow(count, sizeof(IOReportElement), length, &new_length); 363 if (overflow || new_length > buffer->getCapacity()) { 364 buffer->setLength(length); 365 return kIOReturnOverrun; 366 } 367 *resultp = new_result; 368 buffer->setLength(new_length); 369 return r; 370 } 371 372 373 IOReturn 374 IOService::SetLegend_Impl(OSArray *legend, bool is_public) 375 { 376 bool ok = setProperty(kIOReportLegendKey, legend); 377 ok = ok && setProperty(kIOReportLegendPublicKey, is_public); 378 return ok ? kIOReturnSuccess : kIOReturnError; 379 } 380 381 382 kern_return_t 383 IOService::RegisterService_Impl() 384 { 385 IOReturn ret = kIOReturnSuccess; 386 bool started; 387 388 IOUserServer *us = (typeof(us))thread_iokit_tls_get(0); 389 if (reserved != NULL && reserved->uvars != NULL && reserved->uvars->userServer == us) { 390 started = reserved->uvars->started; 391 } else { 392 // assume started 393 started = true; 394 } 395 396 if (OSDynamicCast(IOUserServer, this) != NULL || started) { 397 registerService(kIOServiceAsynchronous); 398 } else { 399 assert(reserved != NULL && reserved->uvars != NULL); 400 reserved->uvars->deferredRegisterService = true; 401 } 402 403 return ret; 404 } 405 406 kern_return_t 407 IOService::CopyDispatchQueue_Impl( 408 const char * name, 409 IODispatchQueue ** queue) 410 { 411 IODispatchQueue * result; 412 IOService * service; 413 IOReturn ret; 414 uint32_t index; 415 416 if (!reserved->uvars) { 417 return kIOReturnError; 418 } 419 420 if (!reserved->uvars->queueArray) { 421 // CopyDispatchQueue should not be called after the service has stopped 422 return kIOReturnError; 423 } 424 425 ret = kIOReturnNotFound; 426 index = -1U; 427 if (!strcmp("Default", name)) { 428 index = 0; 429 } else if (reserved->uvars->userMeta 430 && reserved->uvars->userMeta->queueNames) { 431 index = reserved->uvars->userServer->stringArrayIndex(reserved->uvars->userMeta->queueNames, name); 432 if (index != -1U) { 433 index++; 434 } 435 } 436 if (index == -1U) { 437 if ((service = getProvider())) { 438 ret = service->CopyDispatchQueue(name, queue); 439 } 440 } else { 441 result = reserved->uvars->queueArray[index]; 442 if (result) { 443 result->retain(); 444 *queue = result; 445 ret = kIOReturnSuccess; 446 } 447 } 448 449 return ret; 450 } 451 452 kern_return_t 453 IOService::CreateDefaultDispatchQueue_Impl( 454 IODispatchQueue ** queue) 455 { 456 return kIOReturnError; 457 } 458 459 kern_return_t 460 IOService::CoreAnalyticsSendEvent_Impl( 461 uint64_t options, 462 OSString * eventName, 463 OSDictionary * eventPayload) 464 { 465 kern_return_t ret; 466 467 if (NULL == gIOCoreAnalyticsSendEventProc) { 468 // perhaps save for later? 469 return kIOReturnNotReady; 470 } 471 472 ret = (*gIOCoreAnalyticsSendEventProc)(options, eventName, eventPayload); 473 474 return ret; 475 } 476 477 kern_return_t 478 IOService::SetDispatchQueue_Impl( 479 const char * name, 480 IODispatchQueue * queue) 481 { 482 IOReturn ret = kIOReturnSuccess; 483 uint32_t index; 484 485 if (!reserved->uvars) { 486 return kIOReturnError; 487 } 488 489 if (kIODKLogSetup & gIODKDebug) { 490 DKLOG(DKS "::SetDispatchQueue(%s)\n", DKN(this), name); 491 } 492 queue->ivars->userServer = reserved->uvars->userServer; 493 index = -1U; 494 if (!strcmp("Default", name)) { 495 index = 0; 496 } else if (reserved->uvars->userMeta 497 && reserved->uvars->userMeta->queueNames) { 498 index = reserved->uvars->userServer->stringArrayIndex(reserved->uvars->userMeta->queueNames, name); 499 if (index != -1U) { 500 index++; 501 } 502 } 503 if (index == -1U) { 504 ret = kIOReturnBadArgument; 505 } else { 506 reserved->uvars->queueArray[index] = queue; 507 queue->retain(); 508 } 509 510 return ret; 511 } 512 513 IOService * 514 IOService::GetProvider() const 515 { 516 return getProvider(); 517 } 518 519 kern_return_t 520 IOService::SetProperties_Impl( 521 OSDictionary * properties) 522 { 523 IOUserServer * us; 524 OSDictionary * dict; 525 IOReturn ret; 526 527 us = (typeof(us))thread_iokit_tls_get(0); 528 dict = OSDynamicCast(OSDictionary, properties); 529 if (NULL == us) { 530 if (!dict) { 531 return kIOReturnBadArgument; 532 } 533 bool ok __block = true; 534 dict->iterateObjects(^bool (const OSSymbol * key, OSObject * value) { 535 ok = setProperty(key, value); 536 return !ok; 537 }); 538 ret = ok ? kIOReturnSuccess : kIOReturnNotWritable; 539 return ret; 540 } 541 542 ret = setProperties(properties); 543 544 if (kIOReturnUnsupported == ret) { 545 if (dict && reserved->uvars && (reserved->uvars->userServer == us)) { 546 ret = runPropertyActionBlock(^IOReturn (void) { 547 OSDictionary * userProps; 548 IOReturn ret; 549 550 userProps = OSDynamicCast(OSDictionary, getProperty(gIOUserServicePropertiesKey)); 551 if (userProps) { 552 userProps = (typeof(userProps))userProps->copyCollection(); 553 } else { 554 userProps = OSDictionary::withCapacity(4); 555 } 556 if (!userProps) { 557 ret = kIOReturnNoMemory; 558 } else { 559 bool ok = userProps->merge(dict); 560 if (ok) { 561 ok = setProperty(gIOUserServicePropertiesKey, userProps); 562 } 563 OSSafeReleaseNULL(userProps); 564 ret = ok ? kIOReturnSuccess : kIOReturnNotWritable; 565 } 566 return ret; 567 }); 568 } 569 } 570 571 return ret; 572 } 573 574 kern_return_t 575 IOService::RemoveProperty_Impl(OSString * propertyName) 576 { 577 IOUserServer * us = (IOUserServer *)thread_iokit_tls_get(0); 578 IOReturn ret = kIOReturnUnsupported; 579 580 if (NULL == propertyName) { 581 return kIOReturnUnsupported; 582 } 583 if (NULL == us) { 584 removeProperty(propertyName); 585 return kIOReturnSuccess; 586 } 587 if (reserved && reserved->uvars && reserved->uvars->userServer == us) { 588 ret = runPropertyActionBlock(^IOReturn (void) { 589 OSDictionary * userProps; 590 userProps = OSDynamicCast(OSDictionary, getProperty(gIOUserServicePropertiesKey)); 591 if (userProps) { 592 userProps = (OSDictionary *)userProps->copyCollection(); 593 if (!userProps) { 594 return kIOReturnNoMemory; 595 } 596 userProps->removeObject(propertyName); 597 bool ok = setProperty(gIOUserServicePropertiesKey, userProps); 598 OSSafeReleaseNULL(userProps); 599 return ok ? kIOReturnSuccess : kIOReturnNotWritable; 600 } else { 601 return kIOReturnNotFound; 602 } 603 }); 604 } 605 return ret; 606 } 607 608 kern_return_t 609 IOService::CopyProperties_Local( 610 OSDictionary ** properties) 611 { 612 OSDictionary * props; 613 OSDictionary * userProps; 614 615 props = dictionaryWithProperties(); 616 userProps = OSDynamicCast(OSDictionary, props->getObject(gIOUserServicePropertiesKey)); 617 if (userProps) { 618 props->merge(userProps); 619 props->removeObject(gIOUserServicePropertiesKey); 620 } 621 622 *properties = props; 623 624 return props ? kIOReturnSuccess : kIOReturnNoMemory; 625 } 626 627 kern_return_t 628 IOService::CopyProperties_Impl( 629 OSDictionary ** properties) 630 { 631 return CopyProperties_Local(properties); 632 } 633 634 kern_return_t 635 IOService::RequireMaxBusStall_Impl( 636 uint64_t u64ns) 637 { 638 IOReturn ret; 639 UInt32 ns; 640 641 if (os_convert_overflow(u64ns, &ns)) { 642 return kIOReturnBadArgument; 643 } 644 ret = requireMaxBusStall(ns); 645 646 return ret; 647 } 648 649 #if PRIVATE_WIFI_ONLY 650 kern_return_t 651 IOService::UserSetProperties_Impl( 652 OSContainer * properties) 653 { 654 return kIOReturnUnsupported; 655 } 656 657 kern_return_t 658 IOService::SendIOMessageServicePropertyChange_Impl(void) 659 { 660 return messageClients(kIOMessageServicePropertyChange); 661 } 662 #endif /* PRIVATE_WIFI_ONLY */ 663 664 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 665 666 kern_return_t 667 IOMemoryDescriptor::_CopyState_Impl( 668 _IOMDPrivateState * state) 669 { 670 IOReturn ret; 671 672 state->length = _length; 673 state->options = _flags; 674 675 ret = kIOReturnSuccess; 676 677 return ret; 678 } 679 680 kern_return_t 681 IOMemoryDescriptor::GetLength(uint64_t * returnLength) 682 { 683 *returnLength = getLength(); 684 685 return kIOReturnSuccess; 686 } 687 688 kern_return_t 689 IOMemoryDescriptor::CreateMapping_Impl( 690 uint64_t options, 691 uint64_t address, 692 uint64_t offset, 693 uint64_t length, 694 uint64_t alignment, 695 IOMemoryMap ** map) 696 { 697 IOReturn ret; 698 IOMemoryMap * resultMap; 699 IOOptionBits koptions; 700 mach_vm_address_t atAddress; 701 702 ret = kIOReturnSuccess; 703 koptions = 0; 704 resultMap = NULL; 705 706 if (kIOMemoryMapFixedAddress & options) { 707 atAddress = address; 708 koptions = 0; 709 } else { 710 switch (kIOMemoryMapGuardedMask & options) { 711 default: 712 case kIOMemoryMapGuardedDefault: 713 koptions |= kIOMapGuardedSmall; 714 break; 715 case kIOMemoryMapGuardedNone: 716 break; 717 case kIOMemoryMapGuardedSmall: 718 koptions |= kIOMapGuardedSmall; 719 break; 720 case kIOMemoryMapGuardedLarge: 721 koptions |= kIOMapGuardedLarge; 722 break; 723 } 724 atAddress = 0; 725 koptions |= kIOMapAnywhere; 726 } 727 728 if ((kIOMemoryMapReadOnly & options) || (kIODirectionOut == getDirection())) { 729 if (!reserved || (current_task() != reserved->creator)) { 730 koptions |= kIOMapReadOnly; 731 } 732 } 733 734 switch (0xFF00 & options) { 735 case kIOMemoryMapCacheModeDefault: 736 koptions |= kIOMapDefaultCache; 737 break; 738 case kIOMemoryMapCacheModeInhibit: 739 koptions |= kIOMapInhibitCache; 740 break; 741 case kIOMemoryMapCacheModeCopyback: 742 koptions |= kIOMapCopybackCache; 743 break; 744 case kIOMemoryMapCacheModeWriteThrough: 745 koptions |= kIOMapWriteThruCache; 746 break; 747 case kIOMemoryMapCacheModeRealTime: 748 koptions |= kIOMapRealTimeCache; 749 break; 750 default: 751 ret = kIOReturnBadArgument; 752 } 753 754 if (kIOReturnSuccess == ret) { 755 resultMap = createMappingInTask(current_task(), atAddress, koptions, offset, length); 756 if (!resultMap) { 757 ret = kIOReturnError; 758 } 759 } 760 761 *map = resultMap; 762 763 return ret; 764 } 765 766 kern_return_t 767 IOMemoryDescriptor::CreateSubMemoryDescriptor_Impl( 768 uint64_t memoryDescriptorCreateOptions, 769 uint64_t offset, 770 uint64_t length, 771 IOMemoryDescriptor * ofDescriptor, 772 IOMemoryDescriptor ** memory) 773 { 774 IOReturn ret; 775 IOMemoryDescriptor * iomd; 776 IOByteCount mdOffset; 777 IOByteCount mdLength; 778 IOByteCount mdEnd; 779 780 if (!ofDescriptor) { 781 return kIOReturnBadArgument; 782 } 783 if (memoryDescriptorCreateOptions & ~kIOMemoryDirectionOutIn) { 784 return kIOReturnBadArgument; 785 } 786 if (os_convert_overflow(offset, &mdOffset)) { 787 return kIOReturnBadArgument; 788 } 789 if (os_convert_overflow(length, &mdLength)) { 790 return kIOReturnBadArgument; 791 } 792 if (os_add_overflow(mdOffset, mdLength, &mdEnd)) { 793 return kIOReturnBadArgument; 794 } 795 if (mdEnd > ofDescriptor->getLength()) { 796 return kIOReturnBadArgument; 797 } 798 799 iomd = IOSubMemoryDescriptor::withSubRange( 800 ofDescriptor, mdOffset, mdLength, (IOOptionBits) memoryDescriptorCreateOptions); 801 802 if (iomd) { 803 ret = kIOReturnSuccess; 804 *memory = iomd; 805 } else { 806 ret = kIOReturnNoMemory; 807 *memory = NULL; 808 } 809 810 return ret; 811 } 812 813 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 814 815 kern_return_t 816 IOMemoryDescriptor::CreateWithMemoryDescriptors_Impl( 817 uint64_t memoryDescriptorCreateOptions, 818 uint32_t withDescriptorsCount, 819 IOMemoryDescriptor ** const withDescriptors, 820 IOMemoryDescriptor ** memory) 821 { 822 IOReturn ret; 823 IOMemoryDescriptor * iomd; 824 825 if (!withDescriptors) { 826 return kIOReturnBadArgument; 827 } 828 if (!withDescriptorsCount) { 829 return kIOReturnBadArgument; 830 } 831 if (memoryDescriptorCreateOptions & ~kIOMemoryDirectionOutIn) { 832 return kIOReturnBadArgument; 833 } 834 835 for (unsigned int idx = 0; idx < withDescriptorsCount; idx++) { 836 if (NULL == withDescriptors[idx]) { 837 return kIOReturnBadArgument; 838 } 839 } 840 841 iomd = IOMultiMemoryDescriptor::withDescriptors(withDescriptors, withDescriptorsCount, 842 (IODirection) memoryDescriptorCreateOptions, false); 843 844 if (iomd) { 845 ret = kIOReturnSuccess; 846 *memory = iomd; 847 } else { 848 ret = kIOReturnNoMemory; 849 *memory = NULL; 850 } 851 852 return ret; 853 } 854 855 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 856 857 kern_return_t 858 IOUserClient::CreateMemoryDescriptorFromClient_Impl( 859 uint64_t memoryDescriptorCreateOptions, 860 uint32_t segmentsCount, 861 const IOAddressSegment segments[32], 862 IOMemoryDescriptor ** memory) 863 { 864 IOReturn ret; 865 IOMemoryDescriptor * iomd; 866 IOOptionBits mdOptions; 867 IOUserUserClient * me; 868 IOAddressRange * ranges; 869 870 me = OSDynamicCast(IOUserUserClient, this); 871 if (!me) { 872 return kIOReturnBadArgument; 873 } 874 if (!me->fTask) { 875 return kIOReturnNotReady; 876 } 877 878 mdOptions = kIOMemoryThreadSafe; 879 if (kIOMemoryDirectionOut & memoryDescriptorCreateOptions) { 880 mdOptions |= kIODirectionOut; 881 } 882 if (kIOMemoryDirectionIn & memoryDescriptorCreateOptions) { 883 mdOptions |= kIODirectionIn; 884 } 885 if (!(kIOMemoryDisableCopyOnWrite & memoryDescriptorCreateOptions)) { 886 mdOptions |= kIOMemoryMapCopyOnWrite; 887 } 888 889 static_assert(sizeof(IOAddressRange) == sizeof(IOAddressSegment)); 890 ranges = __DECONST(IOAddressRange *, &segments[0]); 891 892 iomd = IOMemoryDescriptor::withAddressRanges( 893 ranges, segmentsCount, 894 mdOptions, me->fTask); 895 896 if (iomd) { 897 ret = kIOReturnSuccess; 898 *memory = iomd; 899 } else { 900 ret = kIOReturnNoMemory; 901 *memory = NULL; 902 } 903 904 return ret; 905 } 906 907 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 908 909 kern_return_t 910 IOMemoryMap::_CopyState_Impl( 911 _IOMemoryMapPrivateState * state) 912 { 913 IOReturn ret; 914 915 state->offset = fOffset; 916 state->length = getLength(); 917 state->address = getAddress(); 918 state->options = getMapOptions(); 919 920 ret = kIOReturnSuccess; 921 922 return ret; 923 } 924 925 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 926 927 kern_return_t 928 IOBufferMemoryDescriptor::Create_Impl( 929 uint64_t options, 930 uint64_t capacity, 931 uint64_t alignment, 932 IOBufferMemoryDescriptor ** memory) 933 { 934 IOReturn ret; 935 IOOptionBits bmdOptions; 936 IOBufferMemoryDescriptor * bmd; 937 IOMemoryDescriptorReserved * reserved; 938 939 if (options & ~((uint64_t) kIOMemoryDirectionOutIn)) { 940 // no other options currently defined 941 return kIOReturnBadArgument; 942 } 943 bmdOptions = (options & kIOMemoryDirectionOutIn) | kIOMemoryKernelUserShared | kIOMemoryThreadSafe; 944 bmd = IOBufferMemoryDescriptor::inTaskWithOptions( 945 kernel_task, bmdOptions, capacity, alignment); 946 947 *memory = bmd; 948 949 if (!bmd) { 950 return kIOReturnNoMemory; 951 } 952 953 reserved = bmd->getKernelReserved(); 954 reserved->creator = current_task(); 955 task_reference(reserved->creator); 956 957 ret = kIOReturnSuccess; 958 959 return ret; 960 } 961 962 kern_return_t 963 IOBufferMemoryDescriptor::SetLength_Impl( 964 uint64_t length) 965 { 966 setLength(length); 967 return kIOReturnSuccess; 968 } 969 970 971 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 972 973 kern_return_t 974 IODMACommand::Create_Impl( 975 IOService * device, 976 uint64_t options, 977 const IODMACommandSpecification * specification, 978 IODMACommand ** command) 979 { 980 IOReturn ret; 981 IODMACommand * dma; 982 IODMACommand::SegmentOptions segmentOptions; 983 IOMapper * mapper; 984 985 if (options & ~((uint64_t) kIODMACommandCreateNoOptions)) { 986 // no other options currently defined 987 return kIOReturnBadArgument; 988 } 989 990 if (os_convert_overflow(specification->maxAddressBits, &segmentOptions.fNumAddressBits)) { 991 return kIOReturnBadArgument; 992 } 993 segmentOptions.fMaxSegmentSize = 0; 994 segmentOptions.fMaxTransferSize = 0; 995 segmentOptions.fAlignment = 1; 996 segmentOptions.fAlignmentLength = 1; 997 segmentOptions.fAlignmentInternalSegments = 1; 998 segmentOptions.fStructSize = sizeof(segmentOptions); 999 1000 mapper = IOMapper::copyMapperForDevice(device); 1001 1002 dma = IODMACommand::withSpecification( 1003 kIODMACommandOutputHost64, 1004 &segmentOptions, 1005 kIODMAMapOptionDextOwner | 1006 kIODMAMapOptionMapped, 1007 mapper, 1008 NULL); 1009 1010 OSSafeReleaseNULL(mapper); 1011 *command = dma; 1012 1013 if (!dma) { 1014 return kIOReturnNoMemory; 1015 } 1016 ret = kIOReturnSuccess; 1017 1018 return ret; 1019 } 1020 1021 #define fInternalState reserved 1022 1023 kern_return_t 1024 IODMACommand::PrepareForDMA_Impl( 1025 uint64_t options, 1026 IOMemoryDescriptor * memory, 1027 uint64_t offset, 1028 uint64_t length, 1029 uint64_t * flags, 1030 uint32_t * segmentsCount, 1031 IOAddressSegment * segments) 1032 { 1033 IOReturn ret; 1034 uint64_t lflags, mdFlags; 1035 UInt32 numSegments; 1036 UInt64 genOffset; 1037 1038 if (options & ~((uint64_t) kIODMACommandPrepareForDMANoOptions)) { 1039 // no other options currently defined 1040 return kIOReturnBadArgument; 1041 } 1042 1043 if (memory == NULL) { 1044 return kIOReturnBadArgument; 1045 } 1046 1047 assert(fInternalState->fDextLock); 1048 IOLockLock(fInternalState->fDextLock); 1049 1050 // uses IOMD direction 1051 ret = memory->prepare(); 1052 if (kIOReturnSuccess != ret) { 1053 goto exit; 1054 } 1055 1056 ret = setMemoryDescriptor(memory, false); 1057 if (kIOReturnSuccess != ret) { 1058 memory->complete(); 1059 goto exit; 1060 } 1061 1062 ret = prepare(offset, length); 1063 if (kIOReturnSuccess != ret) { 1064 clearMemoryDescriptor(false); 1065 memory->complete(); 1066 goto exit; 1067 } 1068 1069 static_assert(sizeof(IODMACommand::Segment64) == sizeof(IOAddressSegment)); 1070 1071 numSegments = *segmentsCount; 1072 genOffset = 0; 1073 ret = genIOVMSegments(&genOffset, segments, &numSegments); 1074 1075 if (kIOReturnSuccess != ret) { 1076 clearMemoryDescriptor(true); 1077 memory->complete(); 1078 goto exit; 1079 } 1080 1081 mdFlags = fMemory->getFlags(); 1082 lflags = 0; 1083 if (kIODirectionOut & mdFlags) { 1084 lflags |= kIOMemoryDirectionOut; 1085 } 1086 if (kIODirectionIn & mdFlags) { 1087 lflags |= kIOMemoryDirectionIn; 1088 } 1089 *flags = lflags; 1090 *segmentsCount = numSegments; 1091 1092 exit: 1093 IOLockUnlock(fInternalState->fDextLock); 1094 1095 return ret; 1096 } 1097 1098 kern_return_t 1099 IODMACommand::CompleteDMA_Impl( 1100 uint64_t options) 1101 { 1102 IOReturn ret, completeRet; 1103 IOMemoryDescriptor * md; 1104 1105 if (options & ~((uint64_t) kIODMACommandCompleteDMANoOptions)) { 1106 // no other options currently defined 1107 return kIOReturnBadArgument; 1108 } 1109 1110 assert(fInternalState->fDextLock); 1111 IOLockLock(fInternalState->fDextLock); 1112 1113 if (!fInternalState->fPrepared) { 1114 ret = kIOReturnNotReady; 1115 goto exit; 1116 } 1117 1118 md = __DECONST(IOMemoryDescriptor *, fMemory); 1119 if (md) { 1120 md->retain(); 1121 } 1122 1123 ret = clearMemoryDescriptor(true); 1124 1125 if (md) { 1126 completeRet = md->complete(); 1127 OSSafeReleaseNULL(md); 1128 if (kIOReturnSuccess == ret) { 1129 ret = completeRet; 1130 } 1131 } 1132 exit: 1133 IOLockUnlock(fInternalState->fDextLock); 1134 1135 return ret; 1136 } 1137 1138 kern_return_t 1139 IODMACommand::GetPreparation_Impl( 1140 uint64_t * offset, 1141 uint64_t * length, 1142 IOMemoryDescriptor ** memory) 1143 { 1144 IOReturn ret; 1145 IOMemoryDescriptor * md; 1146 1147 if (!fActive) { 1148 return kIOReturnNotReady; 1149 } 1150 1151 ret = getPreparedOffsetAndLength(offset, length); 1152 if (kIOReturnSuccess != ret) { 1153 return ret; 1154 } 1155 1156 if (memory) { 1157 md = __DECONST(IOMemoryDescriptor *, fMemory); 1158 *memory = md; 1159 if (!md) { 1160 ret = kIOReturnNotReady; 1161 } else { 1162 md->retain(); 1163 } 1164 } 1165 return ret; 1166 } 1167 1168 kern_return_t 1169 IODMACommand::PerformOperation_Impl( 1170 uint64_t options, 1171 uint64_t dmaOffset, 1172 uint64_t length, 1173 uint64_t dataOffset, 1174 IOMemoryDescriptor * data) 1175 { 1176 IOReturn ret; 1177 OSDataAllocation<uint8_t> buffer; 1178 UInt64 copiedDMA; 1179 IOByteCount mdOffset, mdLength, copied; 1180 1181 if (options & ~((uint64_t) 1182 (kIODMACommandPerformOperationOptionRead 1183 | kIODMACommandPerformOperationOptionWrite 1184 | kIODMACommandPerformOperationOptionZero))) { 1185 // no other options currently defined 1186 return kIOReturnBadArgument; 1187 } 1188 1189 if (!fActive) { 1190 return kIOReturnNotReady; 1191 } 1192 if (os_convert_overflow(dataOffset, &mdOffset)) { 1193 return kIOReturnBadArgument; 1194 } 1195 if (os_convert_overflow(length, &mdLength)) { 1196 return kIOReturnBadArgument; 1197 } 1198 if (length > fMemory->getLength()) { 1199 return kIOReturnBadArgument; 1200 } 1201 buffer = OSDataAllocation<uint8_t>(length, OSAllocateMemory); 1202 if (!buffer) { 1203 return kIOReturnNoMemory; 1204 } 1205 1206 switch (options) { 1207 case kIODMACommandPerformOperationOptionZero: 1208 bzero(buffer.data(), length); 1209 copiedDMA = writeBytes(dmaOffset, buffer.data(), length); 1210 if (copiedDMA != length) { 1211 ret = kIOReturnUnderrun; 1212 break; 1213 } 1214 ret = kIOReturnSuccess; 1215 break; 1216 1217 case kIODMACommandPerformOperationOptionRead: 1218 case kIODMACommandPerformOperationOptionWrite: 1219 1220 if (!data) { 1221 ret = kIOReturnBadArgument; 1222 break; 1223 } 1224 if (length > data->getLength()) { 1225 ret = kIOReturnBadArgument; 1226 break; 1227 } 1228 if (kIODMACommandPerformOperationOptionWrite == options) { 1229 copied = data->readBytes(mdOffset, buffer.data(), mdLength); 1230 if (copied != mdLength) { 1231 ret = kIOReturnUnderrun; 1232 break; 1233 } 1234 copiedDMA = writeBytes(dmaOffset, buffer.data(), length); 1235 if (copiedDMA != length) { 1236 ret = kIOReturnUnderrun; 1237 break; 1238 } 1239 } else { /* kIODMACommandPerformOperationOptionRead */ 1240 copiedDMA = readBytes(dmaOffset, buffer.data(), length); 1241 if (copiedDMA != length) { 1242 ret = kIOReturnUnderrun; 1243 break; 1244 } 1245 copied = data->writeBytes(mdOffset, buffer.data(), mdLength); 1246 if (copied != mdLength) { 1247 ret = kIOReturnUnderrun; 1248 break; 1249 } 1250 } 1251 ret = kIOReturnSuccess; 1252 break; 1253 default: 1254 ret = kIOReturnBadArgument; 1255 break; 1256 } 1257 1258 return ret; 1259 } 1260 1261 1262 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1263 1264 static kern_return_t 1265 OSActionCreateWithTypeNameInternal(OSObject * target, uint64_t targetmsgid, uint64_t msgid, size_t referenceSize, OSString * typeName, bool fromKernel, OSAction ** action) 1266 { 1267 OSAction * inst = NULL; 1268 void * reference = NULL; // must release 1269 const OSSymbol *sym = NULL; // must release 1270 OSObject *obj = NULL; // must release 1271 const OSMetaClass *actionMetaClass = NULL; // do not release 1272 kern_return_t ret; 1273 1274 if (fromKernel && typeName) { 1275 /* The action is being constructed in the kernel with a type name */ 1276 sym = OSSymbol::withString(typeName); 1277 actionMetaClass = OSMetaClass::getMetaClassWithName(sym); 1278 if (actionMetaClass && actionMetaClass->getSuperClass() == OSTypeID(OSAction)) { 1279 obj = actionMetaClass->alloc(); 1280 if (!obj) { 1281 ret = kIOReturnNoMemory; 1282 goto finish; 1283 } 1284 inst = OSDynamicCast(OSAction, obj); 1285 obj = NULL; // prevent release 1286 assert(inst); // obj is a subclass of OSAction so the dynamic cast should always work 1287 } else { 1288 DKLOG("Attempted to create action object with type \"%s\" which does not inherit from OSAction\n", typeName->getCStringNoCopy()); 1289 ret = kIOReturnBadArgument; 1290 goto finish; 1291 } 1292 } else { 1293 inst = OSTypeAlloc(OSAction); 1294 if (!inst) { 1295 ret = kIOReturnNoMemory; 1296 goto finish; 1297 } 1298 } 1299 1300 if (referenceSize != 0) { 1301 reference = IONewZeroData(uint8_t, referenceSize); 1302 if (reference == NULL) { 1303 ret = kIOReturnNoMemory; 1304 goto finish; 1305 } 1306 } 1307 1308 inst->ivars = IONewZero(OSAction_IVars, 1); 1309 if (!inst->ivars) { 1310 ret = kIOReturnNoMemory; 1311 goto finish; 1312 } 1313 if (target) { 1314 target->retain(); 1315 if (!fromKernel && !OSDynamicCast(IOService, target)) { 1316 IOUserServer * us; 1317 us = (typeof(us))thread_iokit_tls_get(0); 1318 inst->ivars->userServer = OSDynamicCast(IOUserServer, us); 1319 assert(inst->ivars->userServer); 1320 inst->ivars->userServer->retain(); 1321 } 1322 } 1323 inst->ivars->target = target; 1324 inst->ivars->targetmsgid = targetmsgid; 1325 inst->ivars->msgid = msgid; 1326 1327 inst->ivars->reference = reference; 1328 inst->ivars->referenceSize = referenceSize; 1329 reference = NULL; // prevent release 1330 1331 if (typeName) { 1332 typeName->retain(); 1333 } 1334 inst->ivars->typeName = typeName; 1335 1336 *action = inst; 1337 inst = NULL; // prevent release 1338 ret = kIOReturnSuccess; 1339 1340 finish: 1341 OSSafeReleaseNULL(obj); 1342 OSSafeReleaseNULL(sym); 1343 OSSafeReleaseNULL(inst); 1344 if (reference) { 1345 IODeleteData(reference, uint8_t, referenceSize); 1346 } 1347 1348 return ret; 1349 } 1350 1351 kern_return_t 1352 OSAction::Create(OSAction_Create_Args) 1353 { 1354 return OSAction::CreateWithTypeName(target, targetmsgid, msgid, referenceSize, NULL, action); 1355 } 1356 1357 kern_return_t 1358 OSAction::CreateWithTypeName(OSAction_CreateWithTypeName_Args) 1359 { 1360 return OSActionCreateWithTypeNameInternal(target, targetmsgid, msgid, referenceSize, typeName, true, action); 1361 } 1362 1363 kern_return_t 1364 OSAction::Create_Impl( 1365 OSObject * target, 1366 uint64_t targetmsgid, 1367 uint64_t msgid, 1368 size_t referenceSize, 1369 OSAction ** action) 1370 { 1371 return OSAction::CreateWithTypeName_Impl(target, targetmsgid, msgid, referenceSize, NULL, action); 1372 } 1373 1374 kern_return_t 1375 OSAction::CreateWithTypeName_Impl( 1376 OSObject * target, 1377 uint64_t targetmsgid, 1378 uint64_t msgid, 1379 size_t referenceSize, 1380 OSString * typeName, 1381 OSAction ** action) 1382 { 1383 return OSActionCreateWithTypeNameInternal(target, targetmsgid, msgid, referenceSize, typeName, false, action); 1384 } 1385 1386 void 1387 OSAction::free() 1388 { 1389 if (ivars) { 1390 if (ivars->abortedHandler) { 1391 Block_release(ivars->abortedHandler); 1392 ivars->abortedHandler = NULL; 1393 } 1394 OSSafeReleaseNULL(ivars->target); 1395 OSSafeReleaseNULL(ivars->typeName); 1396 OSSafeReleaseNULL(ivars->userServer); 1397 if (ivars->reference) { 1398 assert(ivars->referenceSize > 0); 1399 IODeleteData(ivars->reference, uint8_t, ivars->referenceSize); 1400 } 1401 IOSafeDeleteNULL(ivars, OSAction_IVars, 1); 1402 } 1403 return super::free(); 1404 } 1405 1406 void * 1407 OSAction::GetReference() 1408 { 1409 assert(ivars && ivars->referenceSize && ivars->reference); 1410 return ivars->reference; 1411 } 1412 1413 kern_return_t 1414 OSAction::SetAbortedHandler(OSActionAbortedHandler handler) 1415 { 1416 ivars->abortedHandler = Block_copy(handler); 1417 return kIOReturnSuccess; 1418 } 1419 1420 void 1421 OSAction::Aborted_Impl(void) 1422 { 1423 if (!os_atomic_cmpxchg(&ivars->aborted, false, true, relaxed)) { 1424 // already aborted 1425 return; 1426 } 1427 if (ivars->abortedHandler) { 1428 ivars->abortedHandler(); 1429 } 1430 } 1431 1432 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1433 1434 struct IODispatchSource_IVars { 1435 queue_chain_t link; 1436 IODispatchSource * source; 1437 IOUserServer * server; 1438 IODispatchQueue_IVars * queue; 1439 bool enabled; 1440 }; 1441 1442 bool 1443 IODispatchSource::init() 1444 { 1445 if (!super::init()) { 1446 return false; 1447 } 1448 1449 ivars = IOMallocType(IODispatchSource_IVars); 1450 1451 ivars->source = this; 1452 1453 return true; 1454 } 1455 1456 void 1457 IODispatchSource::free() 1458 { 1459 IOFreeType(ivars, IODispatchSource_IVars); 1460 super::free(); 1461 } 1462 1463 kern_return_t 1464 IODispatchSource::SetEnable_Impl( 1465 bool enable) 1466 { 1467 return SetEnableWithCompletion(enable, NULL); 1468 } 1469 1470 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1471 1472 struct IOInterruptDispatchSource_IVars { 1473 IOService * provider; 1474 uint32_t intIndex; 1475 uint32_t flags; 1476 int interruptType; 1477 IOSimpleLock * lock; 1478 thread_t waiter; 1479 uint64_t count; 1480 uint64_t time; 1481 OSAction * action; 1482 bool enable; 1483 bool canceled; 1484 }; 1485 1486 static void 1487 IOInterruptDispatchSourceInterrupt(OSObject * target, void * refCon, 1488 IOService * nub, int source ) 1489 { 1490 IOInterruptDispatchSource_IVars * ivars = (typeof(ivars))refCon; 1491 IOInterruptState is; 1492 1493 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1494 ivars->count++; 1495 ivars->time = (kIOInterruptSourceContinuousTime & ivars->flags) 1496 ? mach_continuous_time() : mach_absolute_time(); 1497 if (ivars->waiter) { 1498 thread_wakeup_thread((event_t) ivars, ivars->waiter); 1499 ivars->waiter = NULL; 1500 } 1501 if (kIOInterruptTypeLevel & ivars->interruptType) { 1502 ivars->provider->disableInterrupt(ivars->intIndex); 1503 } 1504 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1505 } 1506 1507 kern_return_t 1508 IOInterruptDispatchSource::Create_Impl( 1509 IOService * provider, 1510 uint32_t indexAndFlags, 1511 IODispatchQueue * queue, 1512 IOInterruptDispatchSource ** source) 1513 { 1514 IOReturn ret; 1515 IOInterruptDispatchSource * inst; 1516 uint32_t index; 1517 uint32_t flags; 1518 1519 index = indexAndFlags & kIOInterruptSourceIndexMask; 1520 flags = indexAndFlags & ~kIOInterruptSourceIndexMask; 1521 1522 inst = OSTypeAlloc(IOInterruptDispatchSource); 1523 if (!inst->init()) { 1524 inst->free(); 1525 return kIOReturnNoMemory; 1526 } 1527 1528 inst->ivars->lock = IOSimpleLockAlloc(); 1529 1530 ret = provider->getInterruptType(index, &inst->ivars->interruptType); 1531 if (kIOReturnSuccess != ret) { 1532 OSSafeReleaseNULL(inst); 1533 return ret; 1534 } 1535 ret = provider->registerInterrupt(index, inst, IOInterruptDispatchSourceInterrupt, inst->ivars); 1536 if (kIOReturnSuccess == ret) { 1537 inst->ivars->intIndex = index; 1538 inst->ivars->flags = flags; 1539 inst->ivars->provider = provider; 1540 inst->ivars->provider->retain(); 1541 *source = inst; 1542 } 1543 return ret; 1544 } 1545 1546 kern_return_t 1547 IOInterruptDispatchSource::GetInterruptType_Impl( 1548 IOService * provider, 1549 uint32_t index, 1550 uint64_t * interruptType) 1551 { 1552 IOReturn ret; 1553 int type; 1554 1555 *interruptType = 0; 1556 ret = provider->getInterruptType(index, &type); 1557 if (kIOReturnSuccess == ret) { 1558 *interruptType = type; 1559 } 1560 1561 return ret; 1562 } 1563 1564 bool 1565 IOInterruptDispatchSource::init() 1566 { 1567 if (!super::init()) { 1568 return false; 1569 } 1570 ivars = IOMallocType(IOInterruptDispatchSource_IVars); 1571 1572 return true; 1573 } 1574 1575 void 1576 IOInterruptDispatchSource::free() 1577 { 1578 if (ivars && ivars->provider) { 1579 (void) ivars->provider->unregisterInterrupt(ivars->intIndex); 1580 ivars->provider->release(); 1581 } 1582 1583 if (ivars && ivars->lock) { 1584 IOSimpleLockFree(ivars->lock); 1585 } 1586 1587 IOFreeType(ivars, IOInterruptDispatchSource_IVars); 1588 1589 super::free(); 1590 } 1591 1592 kern_return_t 1593 IOInterruptDispatchSource::SetHandler_Impl( 1594 OSAction * action) 1595 { 1596 IOReturn ret; 1597 OSAction * oldAction; 1598 1599 oldAction = (typeof(oldAction))ivars->action; 1600 if (oldAction && OSCompareAndSwapPtr(oldAction, NULL, &ivars->action)) { 1601 oldAction->release(); 1602 } 1603 action->retain(); 1604 ivars->action = action; 1605 1606 ret = kIOReturnSuccess; 1607 1608 return ret; 1609 } 1610 1611 kern_return_t 1612 IOInterruptDispatchSource::SetEnableWithCompletion_Impl( 1613 bool enable, 1614 IODispatchSourceCancelHandler handler) 1615 { 1616 IOReturn ret; 1617 IOInterruptState is; 1618 1619 if (enable == ivars->enable) { 1620 return kIOReturnSuccess; 1621 } 1622 1623 if (enable) { 1624 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1625 ivars->enable = enable; 1626 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1627 ret = ivars->provider->enableInterrupt(ivars->intIndex); 1628 } else { 1629 ret = ivars->provider->disableInterrupt(ivars->intIndex); 1630 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1631 ivars->enable = enable; 1632 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1633 } 1634 1635 return ret; 1636 } 1637 1638 kern_return_t 1639 IOInterruptDispatchSource::Cancel_Impl( 1640 IODispatchSourceCancelHandler handler) 1641 { 1642 IOInterruptState is; 1643 IOService * provider; 1644 1645 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1646 ivars->canceled = true; 1647 if (ivars->waiter) { 1648 thread_wakeup_thread((event_t) ivars, ivars->waiter); 1649 ivars->waiter = NULL; 1650 } 1651 provider = ivars->provider; 1652 if (provider) { 1653 ivars->provider = NULL; 1654 } 1655 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1656 1657 if (provider) { 1658 (void) provider->unregisterInterrupt(ivars->intIndex); 1659 provider->release(); 1660 } 1661 1662 return kIOReturnSuccess; 1663 } 1664 1665 kern_return_t 1666 IOInterruptDispatchSource::CheckForWork_Impl( 1667 const IORPC rpc, 1668 bool synchronous) 1669 { 1670 IOReturn ret = kIOReturnNotReady; 1671 IOInterruptState is; 1672 bool willWait; 1673 bool canceled; 1674 wait_result_t waitResult; 1675 uint64_t icount; 1676 uint64_t itime; 1677 thread_t self; 1678 1679 self = current_thread(); 1680 icount = 0; 1681 do { 1682 willWait = false; 1683 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1684 canceled = ivars->canceled; 1685 if (!canceled) { 1686 if ((icount = ivars->count)) { 1687 itime = ivars->time; 1688 ivars->count = 0; 1689 waitResult = THREAD_AWAKENED; 1690 } else if (synchronous) { 1691 assert(NULL == ivars->waiter); 1692 ivars->waiter = self; 1693 waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE); 1694 } 1695 willWait = (synchronous && (waitResult == THREAD_WAITING)); 1696 if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) { 1697 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1698 ivars->provider->enableInterrupt(ivars->intIndex); 1699 } else { 1700 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1701 } 1702 } else { 1703 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1704 } 1705 if (willWait) { 1706 waitResult = thread_block(THREAD_CONTINUE_NULL); 1707 if (THREAD_INTERRUPTED == waitResult) { 1708 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1709 ivars->waiter = NULL; 1710 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1711 canceled = true; 1712 break; 1713 } 1714 } 1715 } while (synchronous && !icount && !canceled); 1716 1717 if (icount && ivars->action) { 1718 ret = InterruptOccurred(rpc, ivars->action, icount, itime); 1719 } 1720 1721 return ret; 1722 } 1723 1724 void 1725 IOInterruptDispatchSource::InterruptOccurred_Impl( 1726 OSAction * action, 1727 uint64_t count, 1728 uint64_t time) 1729 { 1730 } 1731 1732 kern_return_t 1733 IOInterruptDispatchSource::GetLastInterrupt_Impl( 1734 uint64_t * pCount, 1735 uint64_t * pTime) 1736 { 1737 IOInterruptState is; 1738 uint64_t count, time; 1739 1740 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1741 count = ivars->count; 1742 time = ivars->time; 1743 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1744 1745 if (pCount) { 1746 *pCount = count; 1747 } 1748 if (pTime) { 1749 *pTime = time; 1750 } 1751 return kIOReturnSuccess; 1752 } 1753 1754 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1755 1756 enum { 1757 kIOServiceNotificationTypeCount = kIOServiceNotificationTypeLast + 1, 1758 }; 1759 1760 struct IOServiceNotificationDispatchSource_IVars { 1761 OSObject * serverName; 1762 OSAction * action; 1763 IOLock * lock; 1764 IONotifier * notifier; 1765 OSDictionary * interestNotifiers; 1766 OSBoundedArray<OSArray *, kIOServiceNotificationTypeCount> pending; 1767 bool enable; 1768 }; 1769 1770 kern_return_t 1771 IOServiceNotificationDispatchSource::Create_Impl( 1772 OSDictionary * matching, 1773 uint64_t options, 1774 IODispatchQueue * queue, 1775 IOServiceNotificationDispatchSource ** notification) 1776 { 1777 IOUserServer * us; 1778 IOReturn ret; 1779 IOServiceNotificationDispatchSource * inst; 1780 1781 inst = OSTypeAlloc(IOServiceNotificationDispatchSource); 1782 if (!inst->init()) { 1783 OSSafeReleaseNULL(inst); 1784 return kIOReturnNoMemory; 1785 } 1786 1787 us = (typeof(us))thread_iokit_tls_get(0); 1788 assert(OSDynamicCast(IOUserServer, us)); 1789 if (!us) { 1790 OSSafeReleaseNULL(inst); 1791 return kIOReturnError; 1792 } 1793 inst->ivars->serverName = us->copyProperty(gIOUserServerNameKey); 1794 if (!inst->ivars->serverName) { 1795 OSSafeReleaseNULL(inst); 1796 return kIOReturnNoMemory; 1797 } 1798 1799 inst->ivars->lock = IOLockAlloc(); 1800 if (!inst->ivars->lock) { 1801 OSSafeReleaseNULL(inst); 1802 return kIOReturnNoMemory; 1803 } 1804 for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) { 1805 inst->ivars->pending[idx] = OSArray::withCapacity(4); 1806 if (!inst->ivars->pending[idx]) { 1807 OSSafeReleaseNULL(inst); 1808 return kIOReturnNoMemory; 1809 } 1810 } 1811 inst->ivars->interestNotifiers = OSDictionary::withCapacity(4); 1812 if (!inst->ivars->interestNotifiers) { 1813 OSSafeReleaseNULL(inst); 1814 return kIOReturnNoMemory; 1815 } 1816 1817 inst->ivars->notifier = IOService::addMatchingNotification(gIOMatchedNotification, matching, 0 /*priority*/, 1818 ^bool (IOService * newService, IONotifier * notifier) { 1819 bool notifyReady = false; 1820 IONotifier * interest; 1821 OSObject * serverName; 1822 bool okToUse; 1823 1824 serverName = newService->copyProperty(gIOUserServerNameKey); 1825 okToUse = (serverName && inst->ivars->serverName->isEqualTo(serverName)); 1826 OSSafeReleaseNULL(serverName); 1827 if (!okToUse) { 1828 OSObject * prop; 1829 OSObject * str; 1830 1831 if (!newService->reserved->uvars || !newService->reserved->uvars->userServer) { 1832 return false; 1833 } 1834 str = OSString::withCStringNoCopy(kIODriverKitAllowsPublishEntitlementsKey); 1835 if (!str) { 1836 return false; 1837 } 1838 okToUse = newService->reserved->uvars->userServer->checkEntitlements(str, NULL, NULL); 1839 if (!okToUse) { 1840 if (kIODKLogSetup & gIODKDebug) { 1841 DKLOG(DKS ": publisher entitlements check failed\n", DKN(newService)); 1842 } 1843 return false; 1844 } 1845 prop = newService->copyProperty(kIODriverKitPublishEntitlementsKey); 1846 if (!prop) { 1847 return false; 1848 } 1849 okToUse = us->checkEntitlements(prop, NULL, NULL); 1850 if (!okToUse) { 1851 if (kIODKLogSetup & gIODKDebug) { 1852 DKLOG(DKS ": subscriber entitlements check failed\n", DKN(newService)); 1853 } 1854 return false; 1855 } 1856 } 1857 1858 IOLockLock(inst->ivars->lock); 1859 notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeMatched]->getCount()); 1860 inst->ivars->pending[kIOServiceNotificationTypeMatched]->setObject(newService); 1861 IOLockUnlock(inst->ivars->lock); 1862 1863 interest = newService->registerInterest(gIOGeneralInterest, 1864 ^IOReturn (uint32_t messageType, IOService * provider, 1865 void * messageArgument, size_t argSize) { 1866 IONotifier * interest; 1867 bool notifyReady = false; 1868 1869 switch (messageType) { 1870 case kIOMessageServiceIsTerminated: 1871 IOLockLock(inst->ivars->lock); 1872 notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeTerminated]->getCount()); 1873 inst->ivars->pending[kIOServiceNotificationTypeTerminated]->setObject(provider); 1874 if (inst->ivars->interestNotifiers != NULL) { 1875 interest = (typeof(interest))inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService); 1876 assert(interest); 1877 interest->remove(); 1878 inst->ivars->interestNotifiers->removeObject((const OSSymbol *) newService); 1879 } 1880 IOLockUnlock(inst->ivars->lock); 1881 break; 1882 default: 1883 break; 1884 } 1885 if (notifyReady && inst->ivars->action) { 1886 inst->ServiceNotificationReady(inst->ivars->action); 1887 } 1888 return kIOReturnSuccess; 1889 }); 1890 if (interest) { 1891 IOLockLock(inst->ivars->lock); 1892 inst->ivars->interestNotifiers->setObject((const OSSymbol *) newService, interest); 1893 IOLockUnlock(inst->ivars->lock); 1894 } 1895 if (notifyReady) { 1896 if (inst->ivars->action) { 1897 inst->ServiceNotificationReady(inst->ivars->action); 1898 } 1899 } 1900 return false; 1901 }); 1902 1903 if (!inst->ivars->notifier) { 1904 OSSafeReleaseNULL(inst); 1905 ret = kIOReturnError; 1906 } 1907 1908 *notification = inst; 1909 ret = kIOReturnSuccess; 1910 1911 return ret; 1912 } 1913 1914 kern_return_t 1915 IOServiceNotificationDispatchSource::CopyNextNotification_Impl( 1916 uint64_t * type, 1917 IOService ** service, 1918 uint64_t * options) 1919 { 1920 IOService * next; 1921 uint32_t idx; 1922 1923 IOLockLock(ivars->lock); 1924 for (idx = 0; idx < kIOServiceNotificationTypeCount; idx++) { 1925 next = (IOService *) ivars->pending[idx]->getObject(0); 1926 if (next) { 1927 next->retain(); 1928 ivars->pending[idx]->removeObject(0); 1929 break; 1930 } 1931 } 1932 IOLockUnlock(ivars->lock); 1933 1934 if (idx == kIOServiceNotificationTypeCount) { 1935 idx = kIOServiceNotificationTypeNone; 1936 } 1937 *type = idx; 1938 *service = next; 1939 *options = 0; 1940 1941 return kIOReturnSuccess; 1942 } 1943 1944 bool 1945 IOServiceNotificationDispatchSource::init() 1946 { 1947 if (!super::init()) { 1948 return false; 1949 } 1950 ivars = IOMallocType(IOServiceNotificationDispatchSource_IVars); 1951 1952 return true; 1953 } 1954 1955 void 1956 IOServiceNotificationDispatchSource::free() 1957 { 1958 if (ivars) { 1959 if (ivars->notifier) { 1960 ivars->notifier->remove(); 1961 ivars->notifier = NULL; 1962 } 1963 if (ivars->interestNotifiers) { 1964 OSDictionary * savedInterestNotifiers = NULL; 1965 1966 // the lock is always initialized first, so it should exist 1967 assert(ivars->lock); 1968 1969 // Prevent additional changes to interestNotifiers 1970 IOLockLock(ivars->lock); 1971 savedInterestNotifiers = ivars->interestNotifiers; 1972 ivars->interestNotifiers = NULL; 1973 IOLockUnlock(ivars->lock); 1974 1975 // Remove all interest notifiers 1976 savedInterestNotifiers->iterateObjects(^bool (const OSSymbol * key, OSObject * object) { 1977 IONotifier * interest = (typeof(interest))object; 1978 interest->remove(); 1979 return false; 1980 }); 1981 OSSafeReleaseNULL(savedInterestNotifiers); 1982 } 1983 for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) { 1984 OSSafeReleaseNULL(ivars->pending[idx]); 1985 } 1986 if (ivars->lock) { 1987 IOLockFree(ivars->lock); 1988 ivars->lock = NULL; 1989 } 1990 OSSafeReleaseNULL(ivars->serverName); 1991 IOFreeType(ivars, IOServiceNotificationDispatchSource_IVars); 1992 } 1993 1994 super::free(); 1995 } 1996 1997 kern_return_t 1998 IOServiceNotificationDispatchSource::SetHandler_Impl( 1999 OSAction * action) 2000 { 2001 IOReturn ret; 2002 bool notifyReady; 2003 2004 notifyReady = false; 2005 2006 IOLockLock(ivars->lock); 2007 OSSafeReleaseNULL(ivars->action); 2008 action->retain(); 2009 ivars->action = action; 2010 if (action) { 2011 for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) { 2012 notifyReady = (ivars->pending[idx]->getCount()); 2013 if (notifyReady) { 2014 break; 2015 } 2016 } 2017 } 2018 IOLockUnlock(ivars->lock); 2019 2020 if (notifyReady) { 2021 ServiceNotificationReady(action); 2022 } 2023 ret = kIOReturnSuccess; 2024 2025 return ret; 2026 } 2027 2028 kern_return_t 2029 IOServiceNotificationDispatchSource::SetEnableWithCompletion_Impl( 2030 bool enable, 2031 IODispatchSourceCancelHandler handler) 2032 { 2033 if (enable == ivars->enable) { 2034 return kIOReturnSuccess; 2035 } 2036 2037 IOLockLock(ivars->lock); 2038 ivars->enable = enable; 2039 IOLockUnlock(ivars->lock); 2040 2041 return kIOReturnSuccess; 2042 } 2043 2044 kern_return_t 2045 IOServiceNotificationDispatchSource::Cancel_Impl( 2046 IODispatchSourceCancelHandler handler) 2047 { 2048 return kIOReturnUnsupported; 2049 } 2050 2051 kern_return_t 2052 IOServiceNotificationDispatchSource::CheckForWork_Impl( 2053 const IORPC rpc, 2054 bool synchronous) 2055 { 2056 return kIOReturnNotReady; 2057 } 2058 2059 kern_return_t 2060 IOServiceNotificationDispatchSource::DeliverNotifications(IOServiceNotificationBlock block) 2061 { 2062 return kIOReturnUnsupported; 2063 } 2064 2065 2066 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2067 2068 OSDictionary * 2069 IOService::CreatePropertyMatchingDictionary(const char * key, OSObjectPtr value, OSDictionary * matching) 2070 { 2071 OSDictionary * result; 2072 const OSSymbol * keySym; 2073 2074 keySym = OSSymbol::withCString(key); 2075 result = propertyMatching(keySym, (const OSObject *) value, matching); 2076 OSSafeReleaseNULL(keySym); 2077 2078 return result; 2079 } 2080 2081 OSDictionary * 2082 IOService::CreatePropertyMatchingDictionary(const char * key, const char * stringValue, OSDictionary * matching) 2083 { 2084 OSDictionary * result; 2085 OSString * value; 2086 2087 value = OSString::withCString(stringValue); 2088 result = CreatePropertyMatchingDictionary(key, value, matching); 2089 OSSafeReleaseNULL(value); 2090 2091 return result; 2092 } 2093 2094 OSDictionary * 2095 IOService::CreateKernelClassMatchingDictionary(OSString * className, OSDictionary * matching) 2096 { 2097 if (!className) { 2098 return NULL; 2099 } 2100 if (!matching) { 2101 matching = OSDictionary::withCapacity(2); 2102 if (!matching) { 2103 return NULL; 2104 } 2105 } 2106 matching->setObject(kIOProviderClassKey, className); 2107 2108 return matching; 2109 } 2110 2111 OSDictionary * 2112 IOService::CreateKernelClassMatchingDictionary(const char * className, OSDictionary * matching) 2113 { 2114 OSDictionary * result; 2115 OSString * string; 2116 2117 string = OSString::withCString(className); 2118 result = CreateKernelClassMatchingDictionary(string, matching); 2119 OSSafeReleaseNULL(string); 2120 2121 return result; 2122 } 2123 2124 OSDictionary * 2125 IOService::CreateUserClassMatchingDictionary(OSString * className, OSDictionary * matching) 2126 { 2127 return CreatePropertyMatchingDictionary(kIOUserClassKey, className, matching); 2128 } 2129 2130 OSDictionary * 2131 IOService::CreateUserClassMatchingDictionary(const char * className, OSDictionary * matching) 2132 { 2133 return CreatePropertyMatchingDictionary(kIOUserClassKey, className, matching); 2134 } 2135 2136 OSDictionary * 2137 IOService::CreateNameMatchingDictionary(OSString * serviceName, OSDictionary * matching) 2138 { 2139 if (!serviceName) { 2140 return NULL; 2141 } 2142 if (!matching) { 2143 matching = OSDictionary::withCapacity(2); 2144 if (!matching) { 2145 return NULL; 2146 } 2147 } 2148 matching->setObject(kIONameMatchKey, serviceName); 2149 2150 return matching; 2151 } 2152 2153 OSDictionary * 2154 IOService::CreateNameMatchingDictionary(const char * serviceName, OSDictionary * matching) 2155 { 2156 OSDictionary * result; 2157 OSString * string; 2158 2159 string = OSString::withCString(serviceName); 2160 result = CreateNameMatchingDictionary(string, matching); 2161 OSSafeReleaseNULL(string); 2162 2163 return result; 2164 } 2165 2166 2167 2168 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2169 2170 kern_return_t 2171 IOUserServer::waitInterruptTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6) 2172 { 2173 IOReturn ret = kIOReturnBadArgument; 2174 IOInterruptState is; 2175 IOInterruptDispatchSource * interrupt; 2176 IOInterruptDispatchSource_IVars * ivars; 2177 IOInterruptDispatchSourcePayload payload; 2178 2179 bool willWait; 2180 bool canceled; 2181 wait_result_t waitResult; 2182 thread_t self; 2183 2184 OSObject * object; 2185 2186 object = iokit_lookup_object_with_port_name((mach_port_name_t)(uintptr_t)p1, IKOT_UEXT_OBJECT, current_task()); 2187 2188 if (!object) { 2189 return kIOReturnBadArgument; 2190 } 2191 if (!(interrupt = OSDynamicCast(IOInterruptDispatchSource, object))) { 2192 ret = kIOReturnBadArgument; 2193 } else { 2194 self = current_thread(); 2195 ivars = interrupt->ivars; 2196 payload.count = 0; 2197 do { 2198 willWait = false; 2199 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 2200 canceled = ivars->canceled; 2201 if (!canceled) { 2202 if ((payload.count = ivars->count)) { 2203 payload.time = ivars->time; 2204 ivars->count = 0; 2205 waitResult = THREAD_AWAKENED; 2206 } else { 2207 assert(NULL == ivars->waiter); 2208 ivars->waiter = self; 2209 waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE); 2210 } 2211 willWait = (waitResult == THREAD_WAITING); 2212 if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) { 2213 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 2214 ivars->provider->enableInterrupt(ivars->intIndex); 2215 } else { 2216 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 2217 } 2218 } else { 2219 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 2220 } 2221 if (willWait) { 2222 waitResult = thread_block(THREAD_CONTINUE_NULL); 2223 if (THREAD_INTERRUPTED == waitResult) { 2224 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 2225 ivars->waiter = NULL; 2226 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 2227 canceled = true; 2228 break; 2229 } 2230 } 2231 } while (!payload.count && !canceled); 2232 ret = (payload.count ? kIOReturnSuccess : kIOReturnAborted); 2233 } 2234 2235 if (kIOReturnSuccess == ret) { 2236 int copyerr = copyout(&payload, (user_addr_t) p2, sizeof(payload)); 2237 if (copyerr) { 2238 ret = kIOReturnVMError; 2239 } 2240 } 2241 2242 object->release(); 2243 2244 return ret; 2245 } 2246 2247 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2248 2249 kern_return_t 2250 IOUserServer::Create_Impl( 2251 const char * name, 2252 uint64_t tag, 2253 uint64_t options, 2254 OSString * bundleID, 2255 IOUserServer ** server) 2256 { 2257 IOReturn ret; 2258 IOUserServer * us; 2259 const OSSymbol * sym; 2260 OSNumber * serverTag; 2261 io_name_t rname; 2262 OSKext * kext; 2263 2264 us = (typeof(us))thread_iokit_tls_get(0); 2265 assert(OSDynamicCast(IOUserServer, us)); 2266 if (kIODKLogSetup & gIODKDebug) { 2267 DKLOG(DKS "::Create(" DKS ") %p\n", DKN(us), name, tag, us); 2268 } 2269 if (!us) { 2270 return kIOReturnError; 2271 } 2272 2273 if (bundleID) { 2274 kext = OSKext::lookupKextWithIdentifier(bundleID->getCStringNoCopy()); 2275 if (kext) { 2276 us->setTaskLoadTag(kext); 2277 us->setDriverKitUUID(kext); 2278 us->setDriverKitStatistics(kext); 2279 OSKext::OSKextLogDriverKitInfoLoad(kext); 2280 OSSafeReleaseNULL(kext); 2281 } else { 2282 DKLOG(DKS "::Create(" DKS "): could not find OSKext for %s\n", DKN(us), name, tag, bundleID->getCStringNoCopy()); 2283 } 2284 2285 us->fAllocationName = kern_allocation_name_allocate(bundleID->getCStringNoCopy(), 0); 2286 assert(us->fAllocationName); 2287 } 2288 2289 sym = OSSymbol::withCString(name); 2290 serverTag = OSNumber::withNumber(tag, 64); 2291 2292 us->setProperty(gIOUserServerNameKey, (OSObject *) sym); 2293 us->setProperty(gIOUserServerTagKey, serverTag); 2294 2295 serverTag->release(); 2296 OSSafeReleaseNULL(sym); 2297 2298 snprintf(rname, sizeof(rname), "IOUserServer(%s-0x%qx)", name, tag); 2299 us->setName(rname); 2300 2301 us->retain(); 2302 *server = us; 2303 ret = kIOReturnSuccess; 2304 2305 return ret; 2306 } 2307 2308 kern_return_t 2309 IOUserServer::RegisterService_Impl() 2310 { 2311 kern_return_t ret = IOService::RegisterService_Impl(); 2312 2313 return ret; 2314 } 2315 2316 kern_return_t 2317 IOUserServer::Exit_Impl( 2318 const char * reason) 2319 { 2320 return kIOReturnUnsupported; 2321 } 2322 2323 kern_return_t 2324 IOUserServer::LoadModule_Impl( 2325 const char * path) 2326 { 2327 return kIOReturnUnsupported; 2328 } 2329 2330 2331 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2332 2333 kern_return_t 2334 IODispatchQueue::Create_Impl( 2335 const char * name, 2336 uint64_t options, 2337 uint64_t priority, 2338 IODispatchQueue ** queue) 2339 { 2340 IODispatchQueue * result; 2341 IOUserServer * us; 2342 2343 result = OSTypeAlloc(IODispatchQueue); 2344 if (!result) { 2345 return kIOReturnNoMemory; 2346 } 2347 if (!result->init()) { 2348 OSSafeReleaseNULL(result); 2349 return kIOReturnNoMemory; 2350 } 2351 2352 *queue = result; 2353 2354 if (!strcmp("Root", name)) { 2355 us = (typeof(us))thread_iokit_tls_get(0); 2356 assert(OSDynamicCast(IOUserServer, us)); 2357 us->setRootQueue(result); 2358 } 2359 2360 if (kIODKLogSetup & gIODKDebug) { 2361 DKLOG("IODispatchQueue::Create %s %p\n", name, result); 2362 } 2363 2364 return kIOReturnSuccess; 2365 } 2366 2367 kern_return_t 2368 IODispatchQueue::SetPort_Impl( 2369 mach_port_t port) 2370 { 2371 if (MACH_PORT_NULL != ivars->serverPort) { 2372 return kIOReturnNotReady; 2373 } 2374 ivars->serverPort = ipc_port_copy_send_mqueue(port); 2375 if (ivars->serverPort == MACH_PORT_NULL) { 2376 return kIOReturnBadArgument; 2377 } 2378 return kIOReturnSuccess; 2379 } 2380 2381 bool 2382 IODispatchQueue::init() 2383 { 2384 ivars = IOMallocType(IODispatchQueue_IVars); 2385 ivars->queue = this; 2386 2387 return true; 2388 } 2389 2390 void 2391 IODispatchQueue::free() 2392 { 2393 if (ivars && ivars->serverPort) { 2394 ipc_port_release_send(ivars->serverPort); 2395 ivars->serverPort = MACH_PORT_NULL; 2396 } 2397 IOFreeType(ivars, IODispatchQueue_IVars); 2398 super::free(); 2399 } 2400 2401 bool 2402 IODispatchQueue::OnQueue() 2403 { 2404 return false; 2405 } 2406 2407 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2408 2409 2410 kern_return_t 2411 OSMetaClassBase::Dispatch(IORPC rpc) 2412 { 2413 return kIOReturnUnsupported; 2414 } 2415 2416 kern_return_t 2417 OSMetaClassBase::Invoke(IORPC rpc) 2418 { 2419 IOReturn ret = kIOReturnUnsupported; 2420 OSMetaClassBase * object; 2421 OSAction * action; 2422 IOService * service; 2423 IOUserServer * us; 2424 IORPCMessage * message; 2425 2426 assert(rpc.sendSize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))); 2427 message = rpc.kernelContent; 2428 if (!message) { 2429 return kIOReturnIPCError; 2430 } 2431 message->flags |= kIORPCMessageKernel; 2432 2433 us = NULL; 2434 if (!(kIORPCMessageLocalHost & message->flags)) { 2435 us = OSDynamicCast(IOUserServer, this); 2436 if (!us) { 2437 IOEventLink * eventLink = NULL; 2438 IOWorkGroup * workgroup = NULL; 2439 2440 if ((action = OSDynamicCast(OSAction, this))) { 2441 object = IOUserServer::target(action, message); 2442 } else { 2443 object = this; 2444 } 2445 if ((service = OSDynamicCast(IOService, object)) 2446 && service->reserved->uvars) { 2447 // xxx other classes 2448 us = service->reserved->uvars->userServer; 2449 } else if (action) { 2450 us = action->ivars->userServer; 2451 } else if ((eventLink = OSDynamicCast(IOEventLink, object))) { 2452 us = eventLink->ivars->userServer; 2453 } else if ((workgroup = OSDynamicCast(IOWorkGroup, object))) { 2454 us = workgroup->ivars->userServer; 2455 } 2456 } 2457 } 2458 if (us) { 2459 message->flags |= kIORPCMessageRemote; 2460 ret = us->rpc(rpc); 2461 if (kIOReturnSuccess != ret) { 2462 if (kIODKLogIPC & gIODKDebug) { 2463 DKLOG("OSMetaClassBase::Invoke user 0x%x\n", ret); 2464 } 2465 } 2466 } else { 2467 if (kIODKLogIPC & gIODKDebug) { 2468 DKLOG("OSMetaClassBase::Invoke kernel %s 0x%qx\n", getMetaClass()->getClassName(), message->msgid); 2469 } 2470 void * prior = thread_iokit_tls_get(0); 2471 thread_iokit_tls_set(0, NULL); 2472 ret = Dispatch(rpc); 2473 thread_iokit_tls_set(0, prior); 2474 } 2475 2476 return ret; 2477 } 2478 2479 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2480 2481 struct IOPStrings { 2482 uint32_t dataSize; 2483 uint32_t count; 2484 const char strings[0]; 2485 }; 2486 2487 kern_return_t 2488 OSUserMetaClass::Dispatch(IORPC rpc) 2489 { 2490 if (meta) { 2491 return const_cast<OSMetaClass *>(meta)->Dispatch(rpc); 2492 } else { 2493 return kIOReturnUnsupported; 2494 } 2495 } 2496 2497 void 2498 OSUserMetaClass::free() 2499 { 2500 if (queueNames) { 2501 IOFreeData(queueNames, sizeof(IOPStrings) + queueNames->dataSize * sizeof(char)); 2502 queueNames = NULL; 2503 } 2504 if (description) { 2505 IOFreeData(description, description->descriptionSize); 2506 description = NULL; 2507 } 2508 IODeleteData(methods, uint64_t, 2 * methodCount); 2509 if (meta) { 2510 meta->releaseMetaClass(); 2511 } 2512 if (name) { 2513 name->release(); 2514 } 2515 OSObject::free(); 2516 } 2517 2518 /* 2519 * Sets the loadTag of the associated OSKext 2520 * in the dext task. 2521 * NOTE: different instances of the same OSKext 2522 * (so same BounleID but different tasks) 2523 * will have the same loadTag. 2524 */ 2525 void 2526 IOUserServer::setTaskLoadTag(OSKext *kext) 2527 { 2528 task_t owningTask; 2529 uint32_t loadTag, prev_taskloadTag; 2530 2531 owningTask = this->fOwningTask; 2532 if (!owningTask) { 2533 printf("%s: fOwningTask not found\n", __FUNCTION__); 2534 return; 2535 } 2536 2537 loadTag = kext->getLoadTag(); 2538 prev_taskloadTag = set_task_loadTag(owningTask, loadTag); 2539 if (prev_taskloadTag) { 2540 printf("%s: found the task loadTag already set to %u (set to %u)\n", 2541 __FUNCTION__, prev_taskloadTag, loadTag); 2542 } 2543 } 2544 2545 /* 2546 * Sets the OSKext uuid as the uuid of the userspace 2547 * dext executable. 2548 */ 2549 void 2550 IOUserServer::setDriverKitUUID(OSKext *kext) 2551 { 2552 task_t task; 2553 proc_t p; 2554 uuid_t p_uuid, k_uuid; 2555 OSData *k_data_uuid; 2556 OSData *new_uuid; 2557 uuid_string_t uuid_string = ""; 2558 2559 task = this->fOwningTask; 2560 if (!task) { 2561 printf("%s: fOwningTask not found\n", __FUNCTION__); 2562 return; 2563 } 2564 2565 p = (proc_t)(get_bsdtask_info(task)); 2566 if (!p) { 2567 printf("%s: proc not found\n", __FUNCTION__); 2568 return; 2569 } 2570 proc_getexecutableuuid(p, p_uuid, sizeof(p_uuid)); 2571 2572 k_data_uuid = kext->copyUUID(); 2573 if (k_data_uuid) { 2574 memcpy(&k_uuid, k_data_uuid->getBytesNoCopy(), sizeof(k_uuid)); 2575 OSSafeReleaseNULL(k_data_uuid); 2576 if (uuid_compare(k_uuid, p_uuid) != 0) { 2577 printf("%s: uuid not matching\n", __FUNCTION__); 2578 } 2579 return; 2580 } 2581 2582 uuid_unparse(p_uuid, uuid_string); 2583 new_uuid = OSData::withValue(p_uuid); 2584 kext->setDriverKitUUID(new_uuid); 2585 } 2586 2587 void 2588 IOUserServer::setDriverKitStatistics(OSKext *kext) 2589 { 2590 OSDextStatistics * statistics = kext->copyDextStatistics(); 2591 if (statistics == NULL) { 2592 panic("Kext %s was not a DriverKit OSKext", kext->getIdentifierCString()); 2593 } 2594 fStatistics = statistics; 2595 } 2596 2597 IOReturn 2598 IOUserServer::setCheckInToken(IOUserServerCheckInToken *token) 2599 { 2600 IOReturn ret = kIOReturnError; 2601 if (token != NULL && fCheckInToken == NULL) { 2602 token->retain(); 2603 fCheckInToken = token; 2604 ret = fCheckInToken->complete(); 2605 iokit_clear_registered_ports(fOwningTask); 2606 } else { 2607 printf("%s: failed to set check in token. token=%p, fCheckInToken=%p\n", __FUNCTION__, token, fCheckInToken); 2608 } 2609 return ret; 2610 } 2611 2612 bool 2613 IOUserServer::serviceMatchesCheckInToken(IOUserServerCheckInToken *token) 2614 { 2615 if (token != NULL) { 2616 bool result = token == fCheckInToken; 2617 return result; 2618 } else { 2619 printf("%s: null check in token\n", __FUNCTION__); 2620 return false; 2621 } 2622 } 2623 2624 // entitlements - dict of entitlements to check 2625 // prop - string - if present return true 2626 // - array of strings - if any present return true 2627 // - array of arrays of strings - in each leaf array all must be present 2628 // - if any top level array succeeds return true 2629 // consumes one reference of prop 2630 bool 2631 IOUserServer::checkEntitlements( 2632 OSDictionary * entitlements, OSObject * prop, 2633 IOService * provider, IOService * dext) 2634 { 2635 OSDictionary * matching; 2636 2637 if (!prop) { 2638 return true; 2639 } 2640 if (!entitlements) { 2641 OSSafeReleaseNULL(prop); 2642 return false; 2643 } 2644 2645 matching = NULL; 2646 if (dext) { 2647 matching = dext->dictionaryWithProperties(); 2648 if (!matching) { 2649 OSSafeReleaseNULL(prop); 2650 return false; 2651 } 2652 } 2653 2654 bool allPresent __block = false; 2655 prop->iterateObjects(^bool (OSObject * object) { 2656 allPresent = false; 2657 object->iterateObjects(^bool (OSObject * object) { 2658 OSString * string; 2659 OSObject * value; 2660 string = OSDynamicCast(OSString, object); 2661 value = entitlements->getObject(string); 2662 if (matching && value) { 2663 matching->setObject(string, value); 2664 } 2665 allPresent = (NULL != value); 2666 // early terminate if not found 2667 return !allPresent; 2668 }); 2669 // early terminate if found 2670 return allPresent; 2671 }); 2672 2673 if (allPresent && matching && provider) { 2674 allPresent = provider->matchPropertyTable(matching); 2675 } 2676 2677 OSSafeReleaseNULL(matching); 2678 OSSafeReleaseNULL(prop); 2679 2680 return allPresent; 2681 } 2682 2683 bool 2684 IOUserServer::checkEntitlements(OSObject * prop, IOService * provider, IOService * dext) 2685 { 2686 return checkEntitlements(fEntitlements, prop, provider, dext); 2687 } 2688 2689 bool 2690 IOUserServer::checkEntitlements(IOService * provider, IOService * dext) 2691 { 2692 OSObject * prop; 2693 bool ok; 2694 2695 if (!fOwningTask) { 2696 return false; 2697 } 2698 2699 prop = provider->copyProperty(gIOServiceDEXTEntitlementsKey); 2700 ok = checkEntitlements(fEntitlements, prop, provider, dext); 2701 if (!ok) { 2702 DKLOG(DKS ": provider entitlements check failed\n", DKN(dext)); 2703 } 2704 if (ok) { 2705 prop = dext->copyProperty(gIOServiceDEXTEntitlementsKey); 2706 ok = checkEntitlements(fEntitlements, prop, NULL, NULL); 2707 if (!ok) { 2708 DKLOG(DKS ": family entitlements check failed\n", DKN(dext)); 2709 } 2710 } 2711 2712 return ok; 2713 } 2714 2715 IOReturn 2716 IOUserServer::exit(const char * reason) 2717 { 2718 DKLOG("%s::exit(%s)\n", getName(), reason); 2719 Exit(reason); 2720 return kIOReturnSuccess; 2721 } 2722 2723 IOReturn 2724 IOUserServer::kill(const char * reason) 2725 { 2726 IOReturn ret = kIOReturnError; 2727 if (fOwningTask != NULL) { 2728 DKLOG("%s::kill(%s)\n", getName(), reason); 2729 task_bsdtask_kill(fOwningTask); 2730 ret = kIOReturnSuccess; 2731 } 2732 return ret; 2733 } 2734 2735 OSObjectUserVars * 2736 IOUserServer::varsForObject(OSObject * obj) 2737 { 2738 IOService * service; 2739 2740 if ((service = OSDynamicCast(IOService, obj))) { 2741 return service->reserved->uvars; 2742 } 2743 2744 return NULL; 2745 } 2746 2747 IOPStrings * 2748 IOUserServer::copyInStringArray(const char * string, uint32_t userSize) 2749 { 2750 IOPStrings * array; 2751 vm_size_t alloc; 2752 size_t len; 2753 const char * end; 2754 OSBoundedPtr<const char> cstr; 2755 2756 if (userSize <= 1) { 2757 return NULL; 2758 } 2759 2760 if (os_add_overflow(sizeof(IOPStrings), userSize, &alloc)) { 2761 assert(false); 2762 return NULL; 2763 } 2764 if (alloc > 16384) { 2765 assert(false); 2766 return NULL; 2767 } 2768 array = (typeof(array))IOMallocData(alloc); 2769 if (!array) { 2770 return NULL; 2771 } 2772 array->dataSize = userSize; 2773 bcopy(string, (void *) &array->strings[0], userSize); 2774 2775 array->count = 0; 2776 end = &array->strings[array->dataSize]; 2777 cstr = OSBoundedPtr<const char>(&array->strings[0], &array->strings[0], end); 2778 while ((len = (unsigned char)cstr[0])) { 2779 cstr++; 2780 if ((cstr + len) >= end) { 2781 break; 2782 } 2783 cstr += len; 2784 array->count++; 2785 } 2786 if (len) { 2787 IOFreeData(array, alloc); 2788 array = NULL; 2789 } 2790 2791 return array; 2792 } 2793 2794 uint32_t 2795 IOUserServer::stringArrayIndex(IOPStrings * array, const char * look) 2796 { 2797 uint32_t idx; 2798 size_t len, llen; 2799 OSBoundedPtr<const char> cstr; 2800 const char * end; 2801 2802 idx = 0; 2803 end = &array->strings[array->dataSize]; 2804 cstr = OSBoundedPtr<const char>(&array->strings[0], &array->strings[0], end); 2805 2806 llen = strlen(look); 2807 while ((len = (unsigned char)cstr[0])) { 2808 cstr++; 2809 if ((cstr + len) >= end) { 2810 break; 2811 } 2812 if ((len == llen) && !strncmp(cstr.discard_bounds(), look, len)) { 2813 return idx; 2814 } 2815 cstr += len; 2816 idx++; 2817 } 2818 2819 return -1U; 2820 } 2821 #define kIODispatchQueueStopped ((IODispatchQueue *) -1L) 2822 2823 IODispatchQueue * 2824 IOUserServer::queueForObject(OSObject * obj, uint64_t msgid) 2825 { 2826 IODispatchQueue * queue; 2827 OSObjectUserVars * uvars; 2828 uint64_t option; 2829 2830 uvars = varsForObject(obj); 2831 if (!uvars) { 2832 return NULL; 2833 } 2834 if (!uvars->queueArray) { 2835 if (uvars->stopped) { 2836 return kIODispatchQueueStopped; 2837 } 2838 return NULL; 2839 } 2840 queue = uvars->queueArray[0]; 2841 2842 if (uvars->userMeta 2843 && uvars->userMeta->methods) { 2844 uint32_t idx, baseIdx; 2845 uint32_t lim; 2846 // bsearch 2847 for (baseIdx = 0, lim = uvars->userMeta->methodCount; lim; lim >>= 1) { 2848 idx = baseIdx + (lim >> 1); 2849 if (msgid == uvars->userMeta->methods[idx]) { 2850 option = uvars->userMeta->methods[uvars->userMeta->methodCount + idx]; 2851 option &= 0xFF; 2852 if (option < uvars->userMeta->queueNames->count) { 2853 queue = uvars->queueArray[option + 1]; 2854 } 2855 break; 2856 } else if (msgid > uvars->userMeta->methods[idx]) { 2857 // move right 2858 baseIdx += (lim >> 1) + 1; 2859 lim--; 2860 } 2861 // else move left 2862 } 2863 } 2864 return queue; 2865 } 2866 2867 IOReturn 2868 IOUserServer::objectInstantiate(OSObject * obj, IORPC rpc, IORPCMessage * message) 2869 { 2870 IOReturn ret; 2871 OSString * str; 2872 OSObject * prop; 2873 IOService * service; 2874 2875 OSAction * action; 2876 OSObject * target; 2877 uint32_t queueCount, queueAlloc; 2878 const char * resultClassName; 2879 uint64_t resultFlags; 2880 2881 mach_msg_size_t replySize; 2882 uint32_t methodCount; 2883 const uint64_t * methods; 2884 IODispatchQueue * queue; 2885 OSUserMetaClass * userMeta; 2886 OSObjectUserVars * uvars; 2887 uint32_t idx; 2888 ipc_port_t sendPort; 2889 bool serviceInactive; 2890 2891 OSObject_Instantiate_Rpl_Content * reply; 2892 IODispatchQueue ** unboundedQueueArray = NULL; 2893 queueCount = 0; 2894 methodCount = 0; 2895 methods = NULL; 2896 str = NULL; 2897 prop = NULL; 2898 userMeta = NULL; 2899 resultClassName = NULL; 2900 resultFlags = 0; 2901 ret = kIOReturnUnsupportedMode; 2902 2903 service = OSDynamicCast(IOService, obj); 2904 action = OSDynamicCast(OSAction, obj); 2905 if (!service) { 2906 // xxx other classes hosted 2907 resultFlags |= kOSObjectRPCKernel; 2908 resultFlags |= kOSObjectRPCRemote; 2909 } else { 2910 serviceInactive = false; 2911 if (service->lockForArbitration()) { 2912 if (service->isInactive() && (service->__state[1] & kIOServiceStartState) == 0) { 2913 serviceInactive = true; 2914 } 2915 service->unlockForArbitration(); 2916 } 2917 if (serviceInactive) { 2918 DKLOG(DKS "::instantiate inactive\n", DKN(service)); 2919 return kIOReturnOffline; 2920 } 2921 prop = service->copyProperty(gIOUserClassKey); 2922 str = OSDynamicCast(OSString, prop); 2923 if (!service->reserved->uvars) { 2924 resultFlags |= kOSObjectRPCRemote; 2925 resultFlags |= kOSObjectRPCKernel; 2926 } else if (this != service->reserved->uvars->userServer) { 2927 // remote, use base class 2928 resultFlags |= kOSObjectRPCRemote; 2929 } 2930 if (service->reserved->uvars && service->reserved->uvars->userServer) { 2931 if (!str) { 2932 DKLOG("no IOUserClass defined for " DKS "\n", DKN(service)); 2933 OSSafeReleaseNULL(prop); 2934 return kIOReturnError; 2935 } 2936 IOLockLock(service->reserved->uvars->userServer->fLock); 2937 userMeta = (typeof(userMeta))service->reserved->uvars->userServer->fClasses->getObject(str); 2938 IOLockUnlock(service->reserved->uvars->userServer->fLock); 2939 } 2940 } 2941 if (!str && !userMeta) { 2942 const OSMetaClass * meta; 2943 meta = obj->getMetaClass(); 2944 IOLockLock(fLock); 2945 if (action) { 2946 str = action->ivars->typeName; 2947 if (str) { 2948 userMeta = (typeof(userMeta))fClasses->getObject(str); 2949 } 2950 } 2951 while (meta && !userMeta) { 2952 str = (OSString *) meta->getClassNameSymbol(); 2953 userMeta = (typeof(userMeta))fClasses->getObject(str); 2954 if (!userMeta) { 2955 meta = meta->getSuperClass(); 2956 } 2957 } 2958 IOLockUnlock(fLock); 2959 } 2960 if (str) { 2961 if (!userMeta) { 2962 IOLockLock(fLock); 2963 userMeta = (typeof(userMeta))fClasses->getObject(str); 2964 IOLockUnlock(fLock); 2965 } 2966 if (kIODKLogSetup & gIODKDebug) { 2967 DKLOG("userMeta %s %p\n", str->getCStringNoCopy(), userMeta); 2968 } 2969 if (userMeta) { 2970 if (kOSObjectRPCRemote & resultFlags) { 2971 if (!action) { 2972 /* Special case: For OSAction subclasses, do not use the superclass */ 2973 while (userMeta && !(kOSClassCanRemote & userMeta->description->flags)) { 2974 userMeta = userMeta->superMeta; 2975 } 2976 } 2977 if (userMeta) { 2978 resultClassName = userMeta->description->name; 2979 ret = kIOReturnSuccess; 2980 } 2981 } else { 2982 service->reserved->uvars->userMeta = userMeta; 2983 queueAlloc = 1; 2984 if (userMeta->queueNames) { 2985 queueAlloc += userMeta->queueNames->count; 2986 } 2987 unboundedQueueArray = IONewZero(IODispatchQueue *, queueAlloc); 2988 service->reserved->uvars->queueArray = 2989 OSBoundedArrayRef<IODispatchQueue *>(unboundedQueueArray, queueAlloc); 2990 resultClassName = str->getCStringNoCopy(); 2991 ret = kIOReturnSuccess; 2992 } 2993 } else if (kIODKLogSetup & gIODKDebug) { 2994 DKLOG("userMeta %s was not found in fClasses\n", str->getCStringNoCopy()); 2995 IOLockLock(fLock); 2996 fClasses->iterateObjects(^bool (const OSSymbol * key, OSObject * val) { 2997 DKLOG(" fClasses[\"%s\"] => %p\n", key->getCStringNoCopy(), val); 2998 return false; 2999 }); 3000 IOLockUnlock(fLock); 3001 } 3002 } 3003 OSSafeReleaseNULL(prop); 3004 3005 IORPCMessageMach * machReply = rpc.reply; 3006 replySize = sizeof(OSObject_Instantiate_Rpl); 3007 3008 if ((kIOReturnSuccess == ret) && (kOSObjectRPCRemote & resultFlags)) { 3009 target = obj; 3010 if (action) { 3011 if (action->ivars->referenceSize) { 3012 resultFlags |= kOSObjectRPCKernel; 3013 } else { 3014 resultFlags &= ~kOSObjectRPCKernel; 3015 if (action->ivars->target) { 3016 target = action->ivars->target; 3017 queueCount = 1; 3018 queue = queueForObject(target, action->ivars->targetmsgid); 3019 if (!queue && action->ivars->userServer) { 3020 queue = action->ivars->userServer->fRootQueue; 3021 } 3022 idx = 0; 3023 sendPort = NULL; 3024 if (queue && (kIODispatchQueueStopped != queue)) { 3025 sendPort = ipc_port_copy_send_mqueue(queue->ivars->serverPort); 3026 } 3027 replySize = sizeof(OSObject_Instantiate_Rpl) 3028 + queueCount * sizeof(machReply->objects[0]) 3029 + 2 * methodCount * sizeof(reply->methods[0]); 3030 if (replySize > rpc.replySize) { 3031 assert(false); 3032 return kIOReturnIPCError; 3033 } 3034 machReply->objects[idx].type = MACH_MSG_PORT_DESCRIPTOR; 3035 machReply->objects[idx].disposition = MACH_MSG_TYPE_MOVE_SEND; 3036 machReply->objects[idx].name = sendPort; 3037 machReply->objects[idx].pad2 = 0; 3038 machReply->objects[idx].pad_end = 0; 3039 } 3040 } 3041 } else { 3042 uvars = varsForObject(target); 3043 if (uvars && uvars->userMeta) { 3044 queueCount = 1; 3045 if (uvars->userMeta->queueNames) { 3046 queueCount += uvars->userMeta->queueNames->count; 3047 } 3048 methods = &uvars->userMeta->methods[0]; 3049 methodCount = uvars->userMeta->methodCount; 3050 replySize = sizeof(OSObject_Instantiate_Rpl) 3051 + queueCount * sizeof(machReply->objects[0]) 3052 + 2 * methodCount * sizeof(reply->methods[0]); 3053 if (replySize > rpc.replySize) { 3054 assert(false); 3055 return kIOReturnIPCError; 3056 } 3057 for (idx = 0; idx < queueCount; idx++) { 3058 queue = uvars->queueArray[idx]; 3059 sendPort = NULL; 3060 if (queue) { 3061 sendPort = ipc_port_copy_send_mqueue(queue->ivars->serverPort); 3062 } 3063 machReply->objects[idx].type = MACH_MSG_PORT_DESCRIPTOR; 3064 machReply->objects[idx].disposition = MACH_MSG_TYPE_MOVE_SEND; 3065 machReply->objects[idx].name = sendPort; 3066 machReply->objects[idx].pad2 = 0; 3067 machReply->objects[idx].pad_end = 0; 3068 } 3069 } 3070 } 3071 } 3072 3073 if (kIODKLogIPC & gIODKDebug) { 3074 DKLOG("instantiate object %s with user class %s\n", obj->getMetaClass()->getClassName(), str ? str->getCStringNoCopy() : "(null)"); 3075 } 3076 3077 if (kIOReturnSuccess != ret) { 3078 DKLOG("%s: no user class found\n", str ? str->getCStringNoCopy() : obj->getMetaClass()->getClassName()); 3079 resultClassName = "unknown"; 3080 } 3081 3082 machReply->msgh.msgh_id = kIORPCVersionCurrentReply; 3083 machReply->msgh.msgh_size = replySize; 3084 machReply->msgh_body.msgh_descriptor_count = queueCount; 3085 3086 reply = (typeof(reply))IORPCMessageFromMachReply(machReply); 3087 if (!reply) { 3088 return kIOReturnIPCError; 3089 } 3090 if (methodCount) { 3091 bcopy(methods, &reply->methods[0], methodCount * 2 * sizeof(reply->methods[0])); 3092 } 3093 reply->__hdr.msgid = OSObject_Instantiate_ID; 3094 reply->__hdr.flags = kIORPCMessageOneway; 3095 reply->__hdr.objectRefs = 0; 3096 reply->__pad = 0; 3097 reply->flags = resultFlags; 3098 strlcpy(reply->classname, resultClassName, sizeof(reply->classname)); 3099 reply->__result = ret; 3100 3101 ret = kIOReturnSuccess; 3102 3103 return ret; 3104 } 3105 3106 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3107 3108 IOReturn 3109 IOUserServer::kernelDispatch(OSObject * obj, IORPC rpc) 3110 { 3111 IOReturn ret; 3112 IORPCMessage * message; 3113 3114 message = rpc.kernelContent; 3115 if (!message) { 3116 return kIOReturnIPCError; 3117 } 3118 3119 if (OSObject_Instantiate_ID == message->msgid) { 3120 ret = objectInstantiate(obj, rpc, message); 3121 if (kIOReturnSuccess != ret) { 3122 DKLOG("%s: instantiate failed 0x%x\n", obj->getMetaClass()->getClassName(), ret); 3123 } 3124 } else { 3125 if (kIODKLogIPC & gIODKDebug) { 3126 DKLOG("%s::Dispatch kernel 0x%qx\n", obj->getMetaClass()->getClassName(), message->msgid); 3127 } 3128 ret = obj->Dispatch(rpc); 3129 if (kIODKLogIPC & gIODKDebug) { 3130 DKLOG("%s::Dispatch kernel 0x%qx result 0x%x\n", obj->getMetaClass()->getClassName(), message->msgid, ret); 3131 } 3132 } 3133 3134 return ret; 3135 } 3136 3137 3138 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3139 3140 OSObject * 3141 IOUserServer::target(OSAction * action, IORPCMessage * message) 3142 { 3143 OSObject * object; 3144 3145 if (message->msgid != action->ivars->msgid) { 3146 return action; 3147 } 3148 object = action->ivars->target; 3149 if (!object) { 3150 return action; 3151 } 3152 message->msgid = action->ivars->targetmsgid; 3153 message->objects[0] = (OSObjectRef) object; 3154 if (kIORPCMessageRemote & message->flags) { 3155 object->retain(); 3156 #ifndef __clang_analyzer__ 3157 // Hide the release of 'action' from the clang static analyzer to suppress 3158 // an overrelease diagnostic. The analyzer doesn't have a way to express the 3159 // non-standard contract of this method, which is that it releases 'action' when 3160 // the message flags have kIORPCMessageRemote set. 3161 action->release(); 3162 #endif 3163 } 3164 if (kIODKLogIPC & gIODKDebug) { 3165 DKLOG("TARGET %s msg 0x%qx from 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid, action->ivars->msgid); 3166 } 3167 3168 return object; 3169 } 3170 3171 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3172 3173 kern_return_t 3174 uext_server(ipc_port_t receiver, ipc_kmsg_t requestkmsg, ipc_kmsg_t * pReply) 3175 { 3176 kern_return_t ret; 3177 OSObject * object; 3178 IOUserServer * server; 3179 3180 object = IOUserServer::copyObjectForSendRight(receiver, IKOT_UEXT_OBJECT); 3181 server = OSDynamicCast(IOUserServer, object); 3182 if (!server) { 3183 OSSafeReleaseNULL(object); 3184 return KERN_INVALID_NAME; 3185 } 3186 3187 IORPCMessage * message = (typeof(message))ikm_udata_from_header(requestkmsg); 3188 3189 ret = server->server(requestkmsg, message, pReply); 3190 object->release(); 3191 3192 return ret; 3193 } 3194 3195 /* 3196 * Chosen to hit kalloc zones (as opposed to the VM). 3197 * doesn't include the trailer size which ipc_kmsg_alloc() will add 3198 */ 3199 #define MAX_UEXT_REPLY_SIZE 0x17c0 3200 static_assert(MAX_UEXT_REPLY_SIZE + MAX_TRAILER_SIZE <= KALLOC_SAFE_ALLOC_SIZE); 3201 3202 kern_return_t 3203 IOUserServer::server(ipc_kmsg_t requestkmsg, IORPCMessage * message, ipc_kmsg_t * pReply) 3204 { 3205 kern_return_t ret; 3206 mach_msg_size_t replyAlloc; 3207 ipc_kmsg_t replykmsg; 3208 IORPCMessageMach * msgin; 3209 IORPCMessageMach * msgout; 3210 IORPCMessage * reply; 3211 uint32_t replySize; 3212 OSObject * object; 3213 OSAction * action; 3214 bool oneway; 3215 uint64_t msgid; 3216 3217 msgin = (typeof(msgin))ikm_header(requestkmsg); 3218 replyAlloc = 0; 3219 msgout = NULL; 3220 replykmsg = NULL; 3221 3222 if (msgin->msgh.msgh_size < (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))) { 3223 if (kIODKLogIPC & gIODKDebug) { 3224 DKLOG("UEXT notify %o\n", msgin->msgh.msgh_id); 3225 } 3226 return KERN_NOT_SUPPORTED; 3227 } 3228 3229 if (!(MACH_MSGH_BITS_COMPLEX & msgin->msgh.msgh_bits)) { 3230 msgin->msgh_body.msgh_descriptor_count = 0; 3231 } 3232 if (!message) { 3233 return kIOReturnIPCError; 3234 } 3235 if (message->objectRefs == 0) { 3236 return kIOReturnIPCError; 3237 } 3238 ret = copyInObjects(msgin, message, msgin->msgh.msgh_size, true, false); 3239 if (kIOReturnSuccess != ret) { 3240 if (kIODKLogIPC & gIODKDebug) { 3241 DKLOG("UEXT copyin(0x%x) %x\n", ret, msgin->msgh.msgh_id); 3242 } 3243 // release objects and ports 3244 consumeObjects(msgin, message, msgin->msgh.msgh_size); 3245 copyInObjects(msgin, message, msgin->msgh.msgh_size, false, true); 3246 return KERN_NOT_SUPPORTED; 3247 } 3248 3249 if (msgin->msgh_body.msgh_descriptor_count < 1) { 3250 return KERN_NOT_SUPPORTED; 3251 } 3252 object = (OSObject *) message->objects[0]; 3253 msgid = message->msgid; 3254 message->flags &= ~kIORPCMessageKernel; 3255 message->flags |= kIORPCMessageRemote; 3256 3257 if ((action = OSDynamicCast(OSAction, object))) { 3258 object = target(action, message); 3259 msgid = message->msgid; 3260 } 3261 3262 oneway = (0 != (kIORPCMessageOneway & message->flags)); 3263 assert(oneway || (MACH_PORT_NULL != msgin->msgh.msgh_local_port)); 3264 3265 replyAlloc = oneway ? 0 : MAX_UEXT_REPLY_SIZE; 3266 3267 3268 3269 3270 if (replyAlloc) { 3271 /* 3272 * Same as: 3273 * ipc_kmsg_alloc(MAX_UEXT_REPLY_SIZE_MACH, MAX_UEXT_REPLY_SIZE_MESSAGE, 3274 * IPC_KMSG_ALLOC_KERNEL | IPC_KMSG_ALLOC_ZERO | IPC_KMSG_ALLOC_LINEAR | 3275 * IPC_KMSG_ALLOC_NOFAIL); 3276 */ 3277 replykmsg = ipc_kmsg_alloc_uext_reply(MAX_UEXT_REPLY_SIZE); 3278 msgout = (typeof(msgout))ikm_header(replykmsg); 3279 } 3280 3281 IORPC rpc = { .message = msgin, .reply = msgout, .sendSize = msgin->msgh.msgh_size, .replySize = replyAlloc, .kernelContent = message }; 3282 3283 if (object) { 3284 kern_allocation_name_t prior; 3285 bool setAllocationName; 3286 3287 setAllocationName = (NULL != fAllocationName); 3288 if (setAllocationName) { 3289 prior = thread_set_allocation_name(fAllocationName); 3290 } 3291 thread_iokit_tls_set(0, this); 3292 ret = kernelDispatch(object, rpc); 3293 thread_iokit_tls_set(0, NULL); 3294 if (setAllocationName) { 3295 thread_set_allocation_name(prior); 3296 } 3297 } else { 3298 ret = kIOReturnBadArgument; 3299 } 3300 3301 // release objects 3302 consumeObjects(msgin, message, msgin->msgh.msgh_size); 3303 3304 // release ports 3305 copyInObjects(msgin, message, msgin->msgh.msgh_size, false, true); 3306 3307 if (!oneway) { 3308 if (kIOReturnSuccess == ret) { 3309 replySize = msgout->msgh.msgh_size; 3310 reply = IORPCMessageFromMachReply(msgout); 3311 if (!reply) { 3312 ret = kIOReturnIPCError; 3313 } else { 3314 ret = copyOutObjects(msgout, reply, replySize, (kIORPCVersionCurrentReply == msgout->msgh.msgh_id) /* =>!InvokeReply */); 3315 } 3316 } 3317 if (kIOReturnSuccess != ret) { 3318 IORPCMessageErrorReturnContent * errorMsg; 3319 3320 msgout->msgh_body.msgh_descriptor_count = 0; 3321 msgout->msgh.msgh_id = kIORPCVersionCurrentReply; 3322 errorMsg = (typeof(errorMsg))IORPCMessageFromMachReply(msgout); 3323 errorMsg->hdr.msgid = message->msgid; 3324 errorMsg->hdr.flags = kIORPCMessageOneway | kIORPCMessageError; 3325 errorMsg->hdr.objectRefs = 0; 3326 errorMsg->result = ret; 3327 errorMsg->pad = 0; 3328 replySize = sizeof(IORPCMessageErrorReturn); 3329 } 3330 3331 msgout->msgh.msgh_bits = MACH_MSGH_BITS_COMPLEX | 3332 MACH_MSGH_BITS_SET(MACH_MSGH_BITS_LOCAL(msgin->msgh.msgh_bits) /*remote*/, 0 /*local*/, 0, 0); 3333 3334 msgout->msgh.msgh_remote_port = msgin->msgh.msgh_local_port; 3335 msgout->msgh.msgh_local_port = MACH_PORT_NULL; 3336 msgout->msgh.msgh_voucher_port = (mach_port_name_t) 0; 3337 msgout->msgh.msgh_reserved = 0; 3338 msgout->msgh.msgh_size = replySize; 3339 } 3340 3341 *pReply = replykmsg; 3342 return KERN_SUCCESS; 3343 } 3344 3345 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3346 3347 static inline uint32_t 3348 MAX_OBJECT_COUNT(IORPCMessageMach *mach, size_t size, IORPCMessage *message __unused) 3349 { 3350 assert(mach->msgh.msgh_size == size); 3351 size_t used_size; 3352 size_t remaining_size; 3353 if (os_mul_and_add_overflow( 3354 mach->msgh_body.msgh_descriptor_count, 3355 sizeof(mach_msg_port_descriptor_t), 3356 sizeof(mach->msgh) + sizeof(mach->msgh_body) + offsetof(IORPCMessage, objects[0]), 3357 &used_size)) { 3358 return 0; 3359 } 3360 if (os_sub_overflow(size, used_size, &remaining_size)) { 3361 return 0; 3362 } 3363 return (uint32_t)(remaining_size / sizeof(OSObjectRef)); 3364 } 3365 3366 #pragma pack(push, 4) 3367 struct UEXTTrapReply { 3368 uint64_t replySize; 3369 IORPCMessage replyMessage; 3370 }; 3371 #pragma pack(pop) 3372 3373 kern_return_t 3374 IOUserServerUEXTTrap(OSObject * object, void * p1, void * p2, void * p3, void * p4, void * p5, void * p6) 3375 { 3376 const user_addr_t msg = (uintptr_t) p1; 3377 size_t inSize = (uintptr_t) p2; 3378 user_addr_t out = (uintptr_t) p3; 3379 size_t outSize = (uintptr_t) p4; 3380 mach_port_name_t objectName1 = (mach_port_name_t)(uintptr_t) p5; 3381 size_t totalSize; 3382 OSObject * objectArg1; 3383 3384 IORPCMessageMach * mach; 3385 mach_msg_port_descriptor_t * descs; 3386 3387 #pragma pack(4) 3388 struct { 3389 uint32_t pad; 3390 IORPCMessageMach mach; 3391 mach_msg_port_descriptor_t objects[2]; 3392 IOTrapMessageBuffer buffer; 3393 } buffer; 3394 #pragma pack() 3395 3396 IOReturn ret; 3397 OSAction * action; 3398 int copyerr; 3399 IORPCMessage * message; 3400 IORPCMessage * reply; 3401 IORPC rpc; 3402 uint64_t refs; 3403 uint32_t maxObjectCount; 3404 size_t copySize; 3405 UEXTTrapReply * replyHdr; 3406 uintptr_t p; 3407 3408 bzero(&buffer, sizeof(buffer)); 3409 3410 p = (typeof(p)) & buffer.buffer[0]; 3411 if (os_add_overflow(inSize, outSize, &totalSize)) { 3412 return kIOReturnMessageTooLarge; 3413 } 3414 if (totalSize > sizeof(buffer.buffer)) { 3415 return kIOReturnMessageTooLarge; 3416 } 3417 if (inSize < sizeof(IORPCMessage)) { 3418 return kIOReturnIPCError; 3419 } 3420 copyerr = copyin(msg, &buffer.buffer[0], inSize); 3421 if (copyerr) { 3422 return kIOReturnVMError; 3423 } 3424 3425 message = (typeof(message))p; 3426 refs = message->objectRefs; 3427 if ((refs > 2) || !refs) { 3428 return kIOReturnUnsupported; 3429 } 3430 if (!(kIORPCMessageSimpleReply & message->flags)) { 3431 return kIOReturnUnsupported; 3432 } 3433 message->flags &= ~(kIORPCMessageKernel | kIORPCMessageRemote); 3434 3435 descs = (typeof(descs))(p - refs * sizeof(*descs)); 3436 mach = (typeof(mach))(p - refs * sizeof(*descs) - sizeof(*mach)); 3437 3438 mach->msgh.msgh_id = kIORPCVersionCurrent; 3439 mach->msgh.msgh_size = (mach_msg_size_t) (sizeof(IORPCMessageMach) + refs * sizeof(*descs) + inSize); // totalSize was checked 3440 mach->msgh_body.msgh_descriptor_count = ((mach_msg_size_t) refs); 3441 3442 rpc.message = mach; 3443 rpc.sendSize = mach->msgh.msgh_size; 3444 rpc.reply = (IORPCMessageMach *) (p + inSize); 3445 rpc.replySize = ((uint32_t) (sizeof(buffer.buffer) - inSize)); // inSize was checked 3446 rpc.kernelContent = message; 3447 3448 message->objects[0] = 0; 3449 if ((action = OSDynamicCast(OSAction, object))) { 3450 maxObjectCount = MAX_OBJECT_COUNT(rpc.message, rpc.sendSize, message); 3451 if (refs > maxObjectCount) { 3452 return kIOReturnBadArgument; 3453 } 3454 if (refs < 2) { 3455 DKLOG("invalid refs count %qd in message id 0x%qx\n", refs, message->msgid); 3456 return kIOReturnBadArgument; 3457 } 3458 object = IOUserServer::target(action, message); 3459 message->objects[1] = (OSObjectRef) action; 3460 if (kIODKLogIPC & gIODKDebug) { 3461 DKLOG("%s::Dispatch(trap) kernel 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid); 3462 } 3463 ret = object->Dispatch(rpc); 3464 } else { 3465 objectArg1 = NULL; 3466 if (refs > 1) { 3467 if (objectName1) { 3468 objectArg1 = iokit_lookup_uext_ref_current_task(objectName1); 3469 if (!objectArg1) { 3470 return kIOReturnIPCError; 3471 } 3472 } 3473 message->objects[1] = (OSObjectRef) objectArg1; 3474 } 3475 if (kIODKLogIPC & gIODKDebug) { 3476 DKLOG("%s::Dispatch(trap) kernel 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid); 3477 } 3478 ret = object->Dispatch(rpc); 3479 if (kIODKLogIPC & gIODKDebug) { 3480 DKLOG("%s::Dispatch(trap) kernel 0x%qx 0x%x\n", object->getMetaClass()->getClassName(), message->msgid, ret); 3481 } 3482 OSSafeReleaseNULL(objectArg1); 3483 3484 if (kIOReturnSuccess == ret) { 3485 if (rpc.reply->msgh_body.msgh_descriptor_count) { 3486 return kIOReturnIPCError; 3487 } 3488 reply = IORPCMessageFromMachReply(rpc.reply); 3489 if (!reply) { 3490 return kIOReturnIPCError; 3491 } 3492 copySize = rpc.reply->msgh.msgh_size - (((uintptr_t) reply) - ((uintptr_t) rpc.reply)) + sizeof(uint64_t); 3493 if (copySize > outSize) { 3494 return kIOReturnIPCError; 3495 } 3496 replyHdr = (UEXTTrapReply *) ((uintptr_t)reply - sizeof(uint64_t)); 3497 replyHdr->replySize = copySize; 3498 copyerr = copyout(replyHdr, out, copySize); 3499 if (copyerr) { 3500 return kIOReturnVMError; 3501 } 3502 } 3503 } 3504 3505 return ret; 3506 } 3507 3508 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3509 3510 IOReturn 3511 IOUserServer::rpc(IORPC rpc) 3512 { 3513 if (isInactive() && !fRootQueue) { 3514 return kIOReturnOffline; 3515 } 3516 3517 IOReturn ret; 3518 IORPCMessage * message; 3519 IORPCMessageMach * mach; 3520 mach_msg_id_t machid; 3521 uint32_t sendSize, replySize; 3522 bool oneway; 3523 uint64_t msgid; 3524 IODispatchQueue * queue; 3525 IOService * service; 3526 ipc_port_t port; 3527 ipc_port_t sendPort; 3528 3529 queue = NULL; 3530 port = NULL; 3531 sendPort = NULL; 3532 3533 mach = rpc.message; 3534 sendSize = rpc.sendSize; 3535 replySize = rpc.replySize; 3536 3537 assert(sendSize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))); 3538 3539 message = rpc.kernelContent; 3540 if (!message) { 3541 return kIOReturnIPCError; 3542 } 3543 msgid = message->msgid; 3544 machid = (msgid >> 32); 3545 3546 if (mach->msgh_body.msgh_descriptor_count < 1) { 3547 return kIOReturnNoMedia; 3548 } 3549 3550 IOLockLock(gIOUserServerLock); 3551 if ((service = OSDynamicCast(IOService, (OSObject *) message->objects[0]))) { 3552 queue = queueForObject(service, msgid); 3553 } 3554 if (!queue) { 3555 queue = fRootQueue; 3556 } 3557 if (queue && (kIODispatchQueueStopped != queue)) { 3558 port = queue->ivars->serverPort; 3559 } 3560 if (port) { 3561 sendPort = ipc_port_copy_send_mqueue(port); 3562 } 3563 IOLockUnlock(gIOUserServerLock); 3564 if (!sendPort) { 3565 return kIOReturnNotReady; 3566 } 3567 3568 oneway = (0 != (kIORPCMessageOneway & message->flags)); 3569 3570 ret = copyOutObjects(mach, message, sendSize, false); 3571 3572 mach->msgh.msgh_bits = MACH_MSGH_BITS_COMPLEX | 3573 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, (oneway ? 0 : MACH_MSG_TYPE_MAKE_SEND_ONCE)); 3574 mach->msgh.msgh_remote_port = sendPort; 3575 mach->msgh.msgh_local_port = (oneway ? MACH_PORT_NULL : mig_get_reply_port()); 3576 mach->msgh.msgh_id = kIORPCVersionCurrent; 3577 mach->msgh.msgh_reserved = 0; 3578 3579 boolean_t message_moved; 3580 3581 if (oneway) { 3582 ret = kernel_mach_msg_send(&mach->msgh, sendSize, 3583 MACH_SEND_KERNEL_DEFAULT, 0, &message_moved); 3584 } else { 3585 assert(replySize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))); 3586 ret = kernel_mach_msg_rpc(&mach->msgh, sendSize, replySize, FALSE, &message_moved); 3587 } 3588 3589 ipc_port_release_send(sendPort); 3590 3591 if (MACH_MSG_SUCCESS != ret) { 3592 if (kIODKLogIPC & gIODKDebug) { 3593 DKLOG("mach_msg() failed 0x%x\n", ret); 3594 } 3595 if (!message_moved) { 3596 // release ports 3597 copyInObjects(mach, message, sendSize, false, true); 3598 } 3599 } 3600 3601 if ((KERN_SUCCESS == ret) && !oneway) { 3602 if (kIORPCVersionCurrentReply != mach->msgh.msgh_id) { 3603 ret = (MACH_NOTIFY_SEND_ONCE == mach->msgh.msgh_id) ? MIG_SERVER_DIED : MIG_REPLY_MISMATCH; 3604 } else if ((replySize = mach->msgh.msgh_size) < (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))) { 3605 // printf("BAD REPLY SIZE\n"); 3606 ret = MIG_BAD_ARGUMENTS; 3607 } else { 3608 if (!(MACH_MSGH_BITS_COMPLEX & mach->msgh.msgh_bits)) { 3609 mach->msgh_body.msgh_descriptor_count = 0; 3610 } 3611 message = IORPCMessageFromMachReply(mach); 3612 if (!message) { 3613 ret = kIOReturnIPCError; 3614 } else if (message->msgid != msgid) { 3615 // printf("BAD REPLY ID\n"); 3616 ret = MIG_BAD_ARGUMENTS; 3617 } else { 3618 bool isError = (0 != (kIORPCMessageError & message->flags)); 3619 ret = copyInObjects(mach, message, replySize, !isError, true); 3620 if (kIOReturnSuccess != ret) { 3621 if (kIODKLogIPC & gIODKDebug) { 3622 DKLOG("rpc copyin(0x%x) %x\n", ret, mach->msgh.msgh_id); 3623 } 3624 if (!isError) { 3625 consumeObjects(mach, message, replySize); 3626 copyInObjects(mach, message, replySize, false, true); 3627 } 3628 return KERN_NOT_SUPPORTED; 3629 } 3630 if (isError) { 3631 IORPCMessageErrorReturnContent * errorMsg = (typeof(errorMsg))message; 3632 ret = errorMsg->result; 3633 } 3634 } 3635 } 3636 } 3637 3638 return ret; 3639 } 3640 3641 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3642 3643 static IORPCMessage * 3644 IORPCMessageFromMachReply(IORPCMessageMach * msg) 3645 { 3646 mach_msg_size_t idx, count; 3647 mach_msg_port_descriptor_t * desc; 3648 mach_msg_port_descriptor_t * maxDesc; 3649 size_t size, msgsize; 3650 bool upgrade; 3651 bool reply = true; 3652 3653 msgsize = msg->msgh.msgh_size; 3654 count = msg->msgh_body.msgh_descriptor_count; 3655 desc = &msg->objects[0]; 3656 maxDesc = (typeof(maxDesc))(((uintptr_t) msg) + msgsize); 3657 upgrade = (msg->msgh.msgh_id != (reply ? kIORPCVersionCurrentReply : kIORPCVersionCurrent)); 3658 3659 if (upgrade) { 3660 OSReportWithBacktrace("obsolete message"); 3661 return NULL; 3662 } 3663 3664 for (idx = 0; idx < count; idx++) { 3665 if (desc >= maxDesc) { 3666 return NULL; 3667 } 3668 switch (desc->type) { 3669 case MACH_MSG_PORT_DESCRIPTOR: 3670 size = sizeof(mach_msg_port_descriptor_t); 3671 break; 3672 case MACH_MSG_OOL_DESCRIPTOR: 3673 size = sizeof(mach_msg_ool_descriptor_t); 3674 break; 3675 default: 3676 return NULL; 3677 } 3678 desc = (typeof(desc))(((uintptr_t) desc) + size); 3679 } 3680 return (IORPCMessage *)(uintptr_t) desc; 3681 } 3682 3683 ipc_port_t 3684 IOUserServer::copySendRightForObject(OSObject * object, ipc_kobject_type_t type) 3685 { 3686 ipc_port_t port; 3687 ipc_port_t sendPort = NULL; 3688 ipc_kobject_t kobj; 3689 3690 port = iokit_port_for_object(object, type, &kobj); 3691 if (port) { 3692 sendPort = ipc_kobject_make_send(port, kobj, type); 3693 iokit_release_port(port); 3694 } 3695 3696 return sendPort; 3697 } 3698 3699 OSObject * 3700 IOUserServer::copyObjectForSendRight(ipc_port_t port, ipc_kobject_type_t type) 3701 { 3702 OSObject * object; 3703 object = iokit_lookup_io_object(port, type); 3704 return object; 3705 } 3706 3707 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3708 3709 // Create a vm_map_copy_t or kalloc'ed data for memory 3710 // to be copied out. ipc will free after the copyout. 3711 3712 static kern_return_t 3713 copyoutkdata(const void * data, vm_size_t len, void ** buf) 3714 { 3715 kern_return_t err; 3716 vm_map_copy_t copy; 3717 3718 err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len, 3719 false /* src_destroy */, ©); 3720 3721 assert( err == KERN_SUCCESS ); 3722 if (err == KERN_SUCCESS) { 3723 *buf = (char *) copy; 3724 } 3725 3726 return err; 3727 } 3728 3729 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3730 3731 IOReturn 3732 IOUserServer::copyOutObjects(IORPCMessageMach * mach, IORPCMessage * message, 3733 size_t size, bool consume) 3734 { 3735 uint64_t refs; 3736 uint32_t idx, maxObjectCount; 3737 ipc_port_t port; 3738 OSObject * object; 3739 size_t descsize; 3740 mach_msg_port_descriptor_t * desc; 3741 mach_msg_ool_descriptor_t * ool; 3742 vm_map_copy_t copy; 3743 void * address; 3744 mach_msg_size_t length; 3745 kern_return_t kr; 3746 OSSerialize * s; 3747 3748 refs = message->objectRefs; 3749 maxObjectCount = MAX_OBJECT_COUNT(mach, size, message); 3750 // assert(refs <= mach->msgh_body.msgh_descriptor_count); 3751 // assert(refs <= maxObjectCount); 3752 if (refs > mach->msgh_body.msgh_descriptor_count) { 3753 return kIOReturnBadArgument; 3754 } 3755 if (refs > maxObjectCount) { 3756 return kIOReturnBadArgument; 3757 } 3758 3759 desc = &mach->objects[0]; 3760 for (idx = 0; idx < refs; idx++) { 3761 object = (OSObject *) message->objects[idx]; 3762 3763 switch (desc->type) { 3764 case MACH_MSG_PORT_DESCRIPTOR: 3765 descsize = sizeof(mach_msg_port_descriptor_t); 3766 port = NULL; 3767 if (object) { 3768 #if DEVELOPMENT || DEBUG 3769 if (kIODKLogIPC & gIODKDebug) { 3770 IOMemoryDescriptor * iomd = OSDynamicCast(IOMemoryDescriptor, object); 3771 if (iomd != NULL && (iomd->getFlags() & kIOMemoryThreadSafe) == 0) { 3772 OSReportWithBacktrace("IOMemoryDescriptor %p was created without kIOMemoryThreadSafe flag", iomd); 3773 } 3774 } 3775 #endif /* DEVELOPMENT || DEBUG */ 3776 3777 port = copySendRightForObject(object, IKOT_UEXT_OBJECT); 3778 if (!port) { 3779 break; 3780 } 3781 if (consume) { 3782 object->release(); 3783 } 3784 message->objects[idx] = 0; 3785 } 3786 // desc->type = MACH_MSG_PORT_DESCRIPTOR; 3787 desc->disposition = MACH_MSG_TYPE_MOVE_SEND; 3788 desc->name = port; 3789 desc->pad2 = 0; 3790 desc->pad_end = 0; 3791 break; 3792 3793 case MACH_MSG_OOL_DESCRIPTOR: 3794 descsize = sizeof(mach_msg_ool_descriptor_t); 3795 3796 length = 0; 3797 address = NULL; 3798 if (object) { 3799 s = OSSerialize::binaryWithCapacity(4096); 3800 assert(s); 3801 if (!s) { 3802 break; 3803 } 3804 s->setIndexed(true); 3805 if (!object->serialize(s)) { 3806 assert(false); 3807 descsize = -1UL; 3808 s->release(); 3809 break; 3810 } 3811 length = s->getLength(); 3812 kr = copyoutkdata(s->text(), length, &address); 3813 s->release(); 3814 if (KERN_SUCCESS != kr) { 3815 descsize = -1UL; 3816 address = NULL; 3817 length = 0; 3818 } 3819 if (consume) { 3820 object->release(); 3821 } 3822 message->objects[idx] = 0; 3823 } 3824 ool = (typeof(ool))desc; 3825 // ool->type = MACH_MSG_OOL_DESCRIPTOR; 3826 ool->deallocate = false; 3827 ool->copy = MACH_MSG_PHYSICAL_COPY; 3828 ool->size = length; 3829 ool->address = address; 3830 break; 3831 3832 default: 3833 descsize = -1UL; 3834 break; 3835 } 3836 if (-1UL == descsize) { 3837 break; 3838 } 3839 desc = (typeof(desc))(((uintptr_t) desc) + descsize); 3840 } 3841 3842 if (idx >= refs) { 3843 return kIOReturnSuccess; 3844 } 3845 3846 desc = &mach->objects[0]; 3847 while (idx--) { 3848 switch (desc->type) { 3849 case MACH_MSG_PORT_DESCRIPTOR: 3850 descsize = sizeof(mach_msg_port_descriptor_t); 3851 port = desc->name; 3852 if (port) { 3853 ipc_port_release_send(port); 3854 } 3855 break; 3856 3857 case MACH_MSG_OOL_DESCRIPTOR: 3858 descsize = sizeof(mach_msg_ool_descriptor_t); 3859 ool = (typeof(ool))desc; 3860 copy = (vm_map_copy_t) ool->address; 3861 if (copy) { 3862 vm_map_copy_discard(copy); 3863 } 3864 break; 3865 3866 default: 3867 descsize = -1UL; 3868 break; 3869 } 3870 if (-1UL == descsize) { 3871 break; 3872 } 3873 desc = (typeof(desc))(((uintptr_t) desc) + descsize); 3874 } 3875 3876 return kIOReturnBadArgument; 3877 } 3878 3879 IOReturn 3880 IOUserServer::copyInObjects(IORPCMessageMach * mach, IORPCMessage * message, 3881 size_t size, bool copyObjects, bool consumePorts) 3882 { 3883 uint64_t refs; 3884 uint32_t idx, maxObjectCount; 3885 ipc_port_t port; 3886 OSObject * object; 3887 size_t descsize; 3888 mach_msg_port_descriptor_t * desc; 3889 mach_msg_ool_descriptor_t * ool; 3890 vm_map_address_t copyoutdata; 3891 kern_return_t kr; 3892 3893 refs = message->objectRefs; 3894 maxObjectCount = MAX_OBJECT_COUNT(mach, size, message); 3895 // assert(refs <= mach->msgh_body.msgh_descriptor_count); 3896 // assert(refs <= maxObjectCount); 3897 if (refs > mach->msgh_body.msgh_descriptor_count) { 3898 return kIOReturnBadArgument; 3899 } 3900 if (refs > maxObjectCount) { 3901 return kIOReturnBadArgument; 3902 } 3903 3904 for (idx = 0; idx < refs; idx++) { 3905 message->objects[idx] = (OSObjectRef) NULL; 3906 } 3907 3908 desc = &mach->objects[0]; 3909 for (idx = 0; idx < mach->msgh_body.msgh_descriptor_count; idx++) { 3910 bool isObjectPort = idx < refs; 3911 3912 switch (desc->type) { 3913 case MACH_MSG_PORT_DESCRIPTOR: 3914 descsize = sizeof(mach_msg_port_descriptor_t); 3915 3916 object = NULL; 3917 port = desc->name; 3918 if (port) { 3919 if (isObjectPort && copyObjects) { 3920 object = copyObjectForSendRight(port, IKOT_UEXT_OBJECT); 3921 if (!object) { 3922 descsize = -1UL; 3923 break; 3924 } 3925 } 3926 if (consumePorts) { 3927 ipc_port_release_send(port); 3928 desc->name = MACH_PORT_NULL; 3929 } 3930 } 3931 break; 3932 3933 case MACH_MSG_OOL_DESCRIPTOR: 3934 descsize = sizeof(mach_msg_ool_descriptor_t); 3935 ool = (typeof(ool))desc; 3936 3937 object = NULL; 3938 if (isObjectPort && copyObjects && ool->size && ool->address) { 3939 kr = vm_map_copyout(kernel_map, ©outdata, (vm_map_copy_t) ool->address); 3940 if (KERN_SUCCESS == kr) { 3941 object = OSUnserializeXML((const char *) copyoutdata, ool->size); 3942 kr = vm_deallocate(kernel_map, copyoutdata, ool->size); 3943 assert(KERN_SUCCESS == kr); 3944 // vm_map_copyout() has consumed the vm_map_copy_t in the message 3945 ool->size = 0; 3946 ool->address = NULL; 3947 } 3948 if (!object) { 3949 descsize = -1UL; 3950 break; 3951 } 3952 } 3953 break; 3954 3955 default: 3956 descsize = -1UL; 3957 break; 3958 } 3959 if (-1UL == descsize) { 3960 break; 3961 } 3962 if (isObjectPort && copyObjects) { 3963 message->objects[idx] = (OSObjectRef) object; 3964 } 3965 desc = (typeof(desc))(((uintptr_t) desc) + descsize); 3966 } 3967 3968 if (idx >= refs) { 3969 return kIOReturnSuccess; 3970 } 3971 3972 while (idx--) { 3973 object = (OSObject *) message->objects[idx]; 3974 OSSafeReleaseNULL(object); 3975 message->objects[idx] = 0; 3976 } 3977 3978 return kIOReturnBadArgument; 3979 } 3980 3981 IOReturn 3982 IOUserServer::consumeObjects(IORPCMessageMach *mach, IORPCMessage * message, size_t messageSize) 3983 { 3984 uint64_t refs, idx; 3985 OSObject * object; 3986 3987 refs = message->objectRefs; 3988 uint32_t maxObjectCount = MAX_OBJECT_COUNT(mach, messageSize, message); 3989 if (refs > mach->msgh_body.msgh_descriptor_count) { 3990 return kIOReturnBadArgument; 3991 } 3992 if (refs > maxObjectCount) { 3993 return kIOReturnBadArgument; 3994 } 3995 3996 for (idx = 0; idx < refs; idx++) { 3997 object = (OSObject *) message->objects[idx]; 3998 if (object) { 3999 object->release(); 4000 message->objects[idx] = 0; 4001 } 4002 } 4003 4004 return kIOReturnSuccess; 4005 } 4006 4007 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4008 4009 bool 4010 IOUserServer::finalize(IOOptionBits options) 4011 { 4012 OSArray * services; 4013 4014 if (kIODKLogSetup & gIODKDebug) { 4015 DKLOG("%s::finalize(%p)\n", getName(), this); 4016 } 4017 4018 IOLockLock(gIOUserServerLock); 4019 OSSafeReleaseNULL(fRootQueue); 4020 IOLockUnlock(gIOUserServerLock); 4021 4022 services = NULL; 4023 IOLockLock(fLock); 4024 if (fServices) { 4025 services = OSArray::withArray(fServices); 4026 } 4027 IOLockUnlock(fLock); 4028 4029 IOOptionBits terminateFlags = kIOServiceTerminateNeedWillTerminate | kIOServiceTerminateWithRematch; 4030 if (fCheckInToken) { 4031 bool can_rematch = fCheckInToken->dextTerminate(); 4032 if (can_rematch) { 4033 terminateFlags |= kIOServiceTerminateWithRematchCurrentDext; 4034 } else { 4035 DKLOG("%s::finalize(%p) dext was replaced, do not rematch current dext\n", getName(), this); 4036 } 4037 } else { 4038 terminateFlags |= kIOServiceTerminateWithRematchCurrentDext; 4039 DKLOG("%s::finalize(%p) could not find fCheckInToken\n", getName(), this); 4040 } 4041 4042 if (services) { 4043 services->iterateObjects(^bool (OSObject * obj) { 4044 int service __unused; // hide outer defn 4045 IOService * nextService; 4046 IOService * provider; 4047 bool started = false; 4048 4049 nextService = (IOService *) obj; 4050 if (kIODKLogSetup & gIODKDebug) { 4051 DKLOG("%s::terminate(" DKS ")\n", getName(), DKN(nextService)); 4052 } 4053 if (nextService->reserved->uvars) { 4054 IOUserClient * nextUserClient = OSDynamicCast(IOUserClient, nextService); 4055 provider = nextService->getProvider(); 4056 if (nextUserClient) { 4057 nextUserClient->setTerminateDefer(provider, false); 4058 } 4059 started = nextService->reserved->uvars->started; 4060 nextService->reserved->uvars->serverDied = true; 4061 4062 serviceDidStop(nextService, provider); 4063 if (provider != NULL && (terminateFlags & kIOServiceTerminateWithRematchCurrentDext) == 0) { 4064 provider->resetRematchProperties(); 4065 } 4066 if (started) { 4067 nextService->terminate(terminateFlags); 4068 } 4069 } 4070 if (!started) { 4071 DKLOG("%s::terminate(" DKS ") server exit before start()\n", getName(), DKN(nextService)); 4072 serviceStop(nextService, NULL); 4073 } 4074 return false; 4075 }); 4076 services->release(); 4077 } 4078 4079 return IOUserClient::finalize(options); 4080 } 4081 4082 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4083 4084 #undef super 4085 #define super IOUserClient2022 4086 4087 OSDefineMetaClassAndStructors(IOUserServer, IOUserClient2022) 4088 4089 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4090 4091 IOUserClient * IOUserServer::withTask(task_t owningTask) 4092 { 4093 IOUserServer * inst; 4094 4095 assert(owningTask == current_task()); 4096 if (!task_is_driver(owningTask)) { 4097 DKLOG("IOUserServer may only be created with driver tasks\n"); 4098 return NULL; 4099 } 4100 4101 inst = new IOUserServer; 4102 if (inst && !inst->init()) { 4103 inst->release(); 4104 inst = NULL; 4105 return inst; 4106 } 4107 OS_ANALYZER_SUPPRESS("82033761") inst->PMinit(); 4108 4109 inst->fOwningTask = current_task(); 4110 task_reference(inst->fOwningTask); 4111 4112 inst->fEntitlements = IOUserClient::copyClientEntitlements(inst->fOwningTask); 4113 4114 if (!(kIODKDisableEntitlementChecking & gIODKDebug)) { 4115 proc_t p; 4116 pid_t pid; 4117 const char * name; 4118 p = (proc_t)get_bsdtask_info(inst->fOwningTask); 4119 if (p) { 4120 name = proc_best_name(p); 4121 pid = proc_pid(p); 4122 } else { 4123 name = "unknown"; 4124 pid = 0; 4125 } 4126 4127 if (inst->fEntitlements == NULL) { 4128 #if DEVELOPMENT || DEBUG 4129 panic("entitlements are missing for %s[%d]\n", name, pid); 4130 #else 4131 DKLOG("entitlements are missing for %s[%d]\n", name, pid); 4132 #endif /* DEVELOPMENT || DEBUG */ 4133 } 4134 4135 4136 const char * dextTeamID = csproc_get_teamid(p); 4137 if (dextTeamID != NULL) { 4138 inst->fTeamIdentifier = OSString::withCString(dextTeamID); 4139 DKLOG("%s[%d] has team identifier %s\n", name, pid, dextTeamID); 4140 } 4141 4142 if (!IOCurrentTaskHasEntitlement(gIODriverKitEntitlementKey->getCStringNoCopy())) { 4143 IOLog(kIODriverKitEntitlementKey " entitlement check failed for %s[%d]\n", name, pid); 4144 inst->release(); 4145 inst = NULL; 4146 return inst; 4147 } 4148 } 4149 4150 /* Mark the current task's space as eligible for uext object ports */ 4151 iokit_label_dext_task(inst->fOwningTask); 4152 4153 inst->fLock = IOLockAlloc(); 4154 inst->fServices = OSArray::withCapacity(4); 4155 inst->fClasses = OSDictionary::withCapacity(16); 4156 inst->fClasses->setOptions(OSCollection::kSort, OSCollection::kSort); 4157 inst->fPlatformDriver = task_get_platform_binary(inst->fOwningTask); 4158 if (csproc_get_validation_category(current_proc(), &inst->fCSValidationCategory) != KERN_SUCCESS) { 4159 inst->fCSValidationCategory = CS_VALIDATION_CATEGORY_INVALID; 4160 } 4161 4162 inst->setProperty(kIOUserClientDefaultLockingKey, kOSBooleanTrue); 4163 inst->setProperty(kIOUserClientDefaultLockingSetPropertiesKey, kOSBooleanTrue); 4164 inst->setProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey, kOSBooleanTrue); 4165 //requirement for gIODriverKitEntitlementKey is enforced elsewhere conditionally 4166 inst->setProperty(kIOUserClientEntitlementsKey, kOSBooleanFalse); 4167 4168 return inst; 4169 } 4170 4171 static bool gIOUserServerLeakObjects = false; 4172 4173 bool 4174 IOUserServer::shouldLeakObjects() 4175 { 4176 return gIOUserServerLeakObjects; 4177 } 4178 4179 void 4180 IOUserServer::beginLeakingObjects() 4181 { 4182 gIOUserServerLeakObjects = true; 4183 } 4184 4185 bool 4186 IOUserServer::isPlatformDriver() 4187 { 4188 return fPlatformDriver; 4189 } 4190 4191 int 4192 IOUserServer::getCSValidationCategory() 4193 { 4194 return fCSValidationCategory; 4195 } 4196 4197 4198 struct IOUserServerRecordExitReasonContext { 4199 task_t task; 4200 os_reason_t reason; 4201 }; 4202 4203 static bool 4204 IOUserServerRecordExitReasonMatch(const OSObject *obj, void * context) 4205 { 4206 IOUserServerRecordExitReasonContext * ctx = (IOUserServerRecordExitReasonContext *)context; 4207 IOUserServer * us = OSDynamicCast(IOUserServer, obj); 4208 if (us == NULL) { 4209 return false; 4210 } 4211 4212 if (us->fOwningTask == ctx->task) { 4213 assert(us->fTaskCrashReason == OS_REASON_NULL); 4214 assert(ctx->reason != OS_REASON_NULL); 4215 os_reason_ref(ctx->reason); 4216 us->fTaskCrashReason = ctx->reason; 4217 return true; 4218 } 4219 4220 return false; 4221 } 4222 4223 extern "C" void 4224 IOUserServerRecordExitReason(task_t task, os_reason_t reason) 4225 { 4226 IOUserServerRecordExitReasonContext ctx { task, reason }; 4227 IOUserServer::gMetaClass.applyToInstances(IOUserServerRecordExitReasonMatch, &ctx); 4228 } 4229 4230 IOReturn 4231 IOUserServer::clientClose(void) 4232 { 4233 OSArray * services; 4234 bool __block unexpectedExit = false; 4235 4236 if (kIODKLogSetup & gIODKDebug) { 4237 DKLOG("%s::clientClose(%p)\n", getName(), this); 4238 } 4239 services = NULL; 4240 IOLockLock(fLock); 4241 if (fServices) { 4242 services = OSArray::withArray(fServices); 4243 } 4244 IOLockUnlock(fLock); 4245 4246 // if this was a an expected exit, termination and stop should have detached at this 4247 // point, so send any provider still attached and not owned by this user server 4248 // the ClientCrashed() notification 4249 if (services) { 4250 services->iterateObjects(^bool (OSObject * obj) { 4251 int service __unused; // hide outer defn 4252 IOService * nextService; 4253 IOService * provider; 4254 4255 nextService = (IOService *) obj; 4256 if (nextService->isInactive()) { 4257 return false; 4258 } 4259 if (nextService->reserved && nextService->reserved->uvars && nextService->reserved->uvars->started) { 4260 unexpectedExit = true; 4261 } 4262 provider = nextService->getProvider(); 4263 if (provider 4264 && (!provider->reserved->uvars || (provider->reserved->uvars->userServer != this))) { 4265 if (kIODKLogSetup & gIODKDebug) { 4266 DKLOG(DKS "::ClientCrashed(" DKS ")\n", DKN(provider), DKN(nextService)); 4267 } 4268 if (unexpectedExit) { 4269 provider->unregisterAllInterrupts(); 4270 } 4271 provider->ClientCrashed(nextService, 0); 4272 } 4273 return false; 4274 }); 4275 services->release(); 4276 } 4277 4278 if (unexpectedExit && 4279 !gInUserspaceReboot && 4280 (fTaskCrashReason != OS_REASON_NULL && fTaskCrashReason->osr_namespace != OS_REASON_JETSAM && fTaskCrashReason->osr_namespace != OS_REASON_RUNNINGBOARD) && 4281 fStatistics != NULL) { 4282 OSDextCrashPolicy policy = fStatistics->recordCrash(); 4283 bool allowPanic; 4284 #if DEVELOPMENT || DEBUG 4285 allowPanic = !restore_boot && fPlatformDriver && fEntitlements->getObject(gIODriverKitTestDriverEntitlementKey) != kOSBooleanTrue && !disable_dext_crash_reboot; 4286 #else 4287 allowPanic = !restore_boot && fPlatformDriver; 4288 #endif /* DEVELOPMENT || DEBUG */ 4289 4290 if (policy == kOSDextCrashPolicyReboot && allowPanic) { 4291 panic("Driver %s has crashed too many times\n", getName()); 4292 } 4293 } 4294 4295 terminate(); 4296 return kIOReturnSuccess; 4297 } 4298 4299 IOReturn 4300 IOUserServer::setProperties(OSObject * properties) 4301 { 4302 IOReturn kr = kIOReturnUnsupported; 4303 return kr; 4304 } 4305 4306 void 4307 IOUserServer::stop(IOService * provider) 4308 { 4309 if (fOwningTask) { 4310 task_deallocate(fOwningTask); 4311 fOwningTask = TASK_NULL; 4312 } 4313 4314 PMstop(); 4315 4316 IOServicePH::serverRemove(this); 4317 4318 OSSafeReleaseNULL(fRootQueue); 4319 4320 if (fInterruptLock) { 4321 IOSimpleLockFree(fInterruptLock); 4322 } 4323 } 4324 4325 void 4326 IOUserServer::free() 4327 { 4328 OSSafeReleaseNULL(fEntitlements); 4329 OSSafeReleaseNULL(fClasses); 4330 if (fOwningTask) { 4331 task_deallocate(fOwningTask); 4332 fOwningTask = TASK_NULL; 4333 } 4334 if (fLock) { 4335 IOLockFree(fLock); 4336 } 4337 OSSafeReleaseNULL(fServices); 4338 OSSafeReleaseNULL(fCheckInToken); 4339 OSSafeReleaseNULL(fStatistics); 4340 OSSafeReleaseNULL(fTeamIdentifier); 4341 if (fAllocationName) { 4342 kern_allocation_name_release(fAllocationName); 4343 fAllocationName = NULL; 4344 } 4345 if (fTaskCrashReason != OS_REASON_NULL) { 4346 os_reason_free(fTaskCrashReason); 4347 } 4348 IOUserClient::free(); 4349 } 4350 4351 IOReturn 4352 IOUserServer::registerClass(OSClassDescription * desc, uint32_t size, OSUserMetaClass ** pCls) 4353 { 4354 OSUserMetaClass * cls; 4355 const OSSymbol * sym; 4356 uint64_t * methodOptions; 4357 const char * queueNames; 4358 uint32_t methodOptionsEnd, queueNamesEnd; 4359 IOReturn ret = kIOReturnSuccess; 4360 4361 if (size < sizeof(OSClassDescription)) { 4362 assert(false); 4363 return kIOReturnBadArgument; 4364 } 4365 4366 if (kIODKLogSetup & gIODKDebug) { 4367 DKLOG("%s::registerClass %s, %d, %d\n", getName(), desc->name, desc->queueNamesSize, desc->methodNamesSize); 4368 } 4369 4370 if (desc->descriptionSize != size) { 4371 assert(false); 4372 return kIOReturnBadArgument; 4373 } 4374 if (os_add_overflow(desc->queueNamesOffset, desc->queueNamesSize, &queueNamesEnd)) { 4375 assert(false); 4376 return kIOReturnBadArgument; 4377 } 4378 if (queueNamesEnd > size) { 4379 assert(false); 4380 return kIOReturnBadArgument; 4381 } 4382 if (os_add_overflow(desc->methodOptionsOffset, desc->methodOptionsSize, &methodOptionsEnd)) { 4383 assert(false); 4384 return kIOReturnBadArgument; 4385 } 4386 if (methodOptionsEnd > size) { 4387 assert(false); 4388 return kIOReturnBadArgument; 4389 } 4390 // overlaps? 4391 if ((desc->queueNamesOffset >= desc->methodOptionsOffset) && (desc->queueNamesOffset < methodOptionsEnd)) { 4392 assert(false); 4393 return kIOReturnBadArgument; 4394 } 4395 if ((queueNamesEnd >= desc->methodOptionsOffset) && (queueNamesEnd < methodOptionsEnd)) { 4396 assert(false); 4397 return kIOReturnBadArgument; 4398 } 4399 4400 if (desc->methodOptionsSize & ((2 * sizeof(uint64_t)) - 1)) { 4401 assert(false); 4402 return kIOReturnBadArgument; 4403 } 4404 if (sizeof(desc->name) == strnlen(desc->name, sizeof(desc->name))) { 4405 assert(false); 4406 return kIOReturnBadArgument; 4407 } 4408 if (sizeof(desc->superName) == strnlen(desc->superName, sizeof(desc->superName))) { 4409 assert(false); 4410 return kIOReturnBadArgument; 4411 } 4412 4413 cls = OSTypeAlloc(OSUserMetaClass); 4414 assert(cls); 4415 if (!cls) { 4416 return kIOReturnNoMemory; 4417 } 4418 4419 cls->description = (typeof(cls->description))IOMallocData(size); 4420 assert(cls->description); 4421 if (!cls->description) { 4422 assert(false); 4423 cls->release(); 4424 return kIOReturnNoMemory; 4425 } 4426 bcopy(desc, cls->description, size); 4427 4428 cls->methodCount = desc->methodOptionsSize / (2 * sizeof(uint64_t)); 4429 cls->methods = IONewData(uint64_t, 2 * cls->methodCount); 4430 if (!cls->methods) { 4431 assert(false); 4432 cls->release(); 4433 return kIOReturnNoMemory; 4434 } 4435 4436 methodOptions = (typeof(methodOptions))(((uintptr_t) desc) + desc->methodOptionsOffset); 4437 bcopy(methodOptions, cls->methods, 2 * cls->methodCount * sizeof(uint64_t)); 4438 4439 queueNames = (typeof(queueNames))(((uintptr_t) desc) + desc->queueNamesOffset); 4440 cls->queueNames = copyInStringArray(queueNames, desc->queueNamesSize); 4441 4442 sym = OSSymbol::withCString(desc->name); 4443 assert(sym); 4444 if (!sym) { 4445 assert(false); 4446 cls->release(); 4447 return kIOReturnNoMemory; 4448 } 4449 4450 cls->name = sym; 4451 cls->meta = OSMetaClass::copyMetaClassWithName(sym); 4452 IOLockLock(fLock); 4453 cls->superMeta = OSDynamicCast(OSUserMetaClass, fClasses->getObject(desc->superName)); 4454 if (fClasses->getObject(sym) != NULL) { 4455 /* class with this name exists */ 4456 ret = kIOReturnBadArgument; 4457 } else { 4458 if (fClasses->setObject(sym, cls)) { 4459 *pCls = cls; 4460 } else { 4461 /* could not add class to fClasses */ 4462 ret = kIOReturnNoMemory; 4463 } 4464 } 4465 IOLockUnlock(fLock); 4466 cls->release(); 4467 return ret; 4468 } 4469 4470 IOReturn 4471 IOUserServer::registerClass(OSClassDescription * desc, uint32_t size, OSSharedPtr<OSUserMetaClass>& pCls) 4472 { 4473 OSUserMetaClass* pClsRaw = NULL; 4474 IOReturn result = registerClass(desc, size, &pClsRaw); 4475 if (result == kIOReturnSuccess) { 4476 pCls.reset(pClsRaw, OSRetain); 4477 } 4478 return result; 4479 } 4480 4481 IOReturn 4482 IOUserServer::setRootQueue(IODispatchQueue * queue) 4483 { 4484 assert(!fRootQueue); 4485 if (fRootQueue) { 4486 return kIOReturnStillOpen; 4487 } 4488 queue->retain(); 4489 fRootQueue = queue; 4490 4491 return kIOReturnSuccess; 4492 } 4493 4494 4495 IOReturn 4496 IOUserServer::externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * args) 4497 { 4498 static const IOExternalMethodDispatch2022 dispatchArray[] = { 4499 [kIOUserServerMethodRegisterClass] = { 4500 .function = &IOUserServer::externalMethodRegisterClass, 4501 .checkScalarInputCount = 0, 4502 .checkStructureInputSize = kIOUCVariableStructureSize, 4503 .checkScalarOutputCount = 2, 4504 .checkStructureOutputSize = 0, 4505 .allowAsync = false, 4506 .checkEntitlement = NULL, 4507 }, 4508 [kIOUserServerMethodStart] = { 4509 .function = &IOUserServer::externalMethodStart, 4510 .checkScalarInputCount = 1, 4511 .checkStructureInputSize = 0, 4512 .checkScalarOutputCount = 1, 4513 .checkStructureOutputSize = 0, 4514 .allowAsync = false, 4515 .checkEntitlement = NULL, 4516 }, 4517 }; 4518 4519 return dispatchExternalMethod(selector, args, dispatchArray, sizeof(dispatchArray) / sizeof(dispatchArray[0]), this, NULL); 4520 } 4521 4522 IOReturn 4523 IOUserServer::externalMethodRegisterClass(OSObject * target, void * reference, IOExternalMethodArguments * args) 4524 { 4525 IOReturn ret = kIOReturnBadArgument; 4526 mach_port_name_t portname; 4527 4528 IOUserServer * me = (typeof(me))target; 4529 4530 OSUserMetaClass * cls; 4531 if (!args->structureInputSize) { 4532 return kIOReturnBadArgument; 4533 } 4534 4535 ret = me->registerClass((OSClassDescription *) args->structureInput, args->structureInputSize, &cls); 4536 if (kIOReturnSuccess == ret) { 4537 portname = iokit_make_send_right(me->fOwningTask, cls, IKOT_UEXT_OBJECT); 4538 assert(portname); 4539 args->scalarOutput[0] = portname; 4540 args->scalarOutput[1] = kOSObjectRPCRemote; 4541 } 4542 4543 return ret; 4544 } 4545 4546 IOReturn 4547 IOUserServer::externalMethodStart(OSObject * target, void * reference, IOExternalMethodArguments * args) 4548 { 4549 mach_port_name_t portname = 0; 4550 IOReturn ret = kIOReturnSuccess; 4551 4552 IOUserServer * me = (typeof(me))target; 4553 4554 if (!(kIODKDisableCheckInTokenVerification & gIODKDebug)) { 4555 mach_port_name_t checkInPortName = ((typeof(checkInPortName))args->scalarInput[0]); 4556 OSObject * obj = iokit_lookup_object_with_port_name(checkInPortName, IKOT_IOKIT_IDENT, me->fOwningTask); 4557 IOUserServerCheckInToken * retrievedToken = OSDynamicCast(IOUserServerCheckInToken, obj); 4558 if (retrievedToken != NULL) { 4559 ret = me->setCheckInToken(retrievedToken); 4560 } else { 4561 ret = kIOReturnBadArgument; 4562 } 4563 OSSafeReleaseNULL(obj); 4564 } 4565 if (ret == kIOReturnSuccess) { 4566 portname = iokit_make_send_right(me->fOwningTask, me, IKOT_UEXT_OBJECT); 4567 assert(portname); 4568 } 4569 args->scalarOutput[0] = portname; 4570 return ret; 4571 } 4572 IOExternalTrap * 4573 IOUserServer::getTargetAndTrapForIndex( IOService **targetP, UInt32 index ) 4574 { 4575 static const OSBoundedArray<IOExternalTrap, 1> trapTemplate = {{ 4576 { NULL, (IOTrap) & IOUserServer::waitInterruptTrap}, 4577 }}; 4578 if (index >= trapTemplate.size()) { 4579 return NULL; 4580 } 4581 *targetP = this; 4582 return (IOExternalTrap *)&trapTemplate[index]; 4583 } 4584 4585 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4586 4587 IOReturn 4588 IOUserServer::serviceAttach(IOService * service, IOService * provider) 4589 { 4590 IOReturn ret; 4591 OSObjectUserVars * vars; 4592 OSObject * prop; 4593 OSString * str; 4594 OSSymbol const* bundleID; 4595 char execPath[1024]; 4596 4597 vars = IOMallocType(OSObjectUserVars); 4598 service->reserved->uvars = vars; 4599 4600 vars->userServer = this; 4601 vars->userServer->retain(); 4602 vars->uvarsLock = IOLockAlloc(); 4603 IOLockLock(fLock); 4604 if (-1U == fServices->getNextIndexOfObject(service, 0)) { 4605 fServices->setObject(service); 4606 4607 // Add to IOAssociatedServices 4608 OSObject * serviceArrayObj = copyProperty(gIOAssociatedServicesKey); 4609 OSArray * serviceArray = OSDynamicCast(OSArray, serviceArrayObj); 4610 if (!serviceArray) { 4611 serviceArray = OSArray::withCapacity(0); 4612 } else { 4613 serviceArray = OSDynamicCast(OSArray, serviceArray->copyCollection()); 4614 assert(serviceArray != NULL); 4615 } 4616 4617 OSNumber * registryEntryNumber = OSNumber::withNumber(service->getRegistryEntryID(), 64); 4618 serviceArray->setObject(registryEntryNumber); 4619 setProperty(gIOAssociatedServicesKey, serviceArray); 4620 OSSafeReleaseNULL(registryEntryNumber); 4621 OSSafeReleaseNULL(serviceArray); 4622 OSSafeReleaseNULL(serviceArrayObj); 4623 4624 // populate kIOUserClassesKey 4625 4626 OSUserMetaClass * userMeta; 4627 OSArray * classesArray; 4628 const OSString * str2; 4629 4630 classesArray = OSArray::withCapacity(4); 4631 prop = service->copyProperty(gIOUserClassKey); 4632 str2 = OSDynamicCast(OSString, prop); 4633 userMeta = (typeof(userMeta))service->reserved->uvars->userServer->fClasses->getObject(str2); 4634 while (str2 && userMeta) { 4635 classesArray->setObject(str2); 4636 userMeta = userMeta->superMeta; 4637 if (userMeta) { 4638 str2 = userMeta->name; 4639 } 4640 } 4641 service->setProperty(gIOUserClassesKey, classesArray); 4642 OSSafeReleaseNULL(classesArray); 4643 OSSafeReleaseNULL(prop); 4644 } 4645 IOLockUnlock(fLock); 4646 4647 prop = service->copyProperty(gIOUserClassKey); 4648 str = OSDynamicCast(OSString, prop); 4649 if (str) { 4650 service->setName(str); 4651 } 4652 OSSafeReleaseNULL(prop); 4653 4654 prop = service->copyProperty(gIOModuleIdentifierKey); 4655 bundleID = OSDynamicCast(OSSymbol, prop); 4656 if (bundleID) { 4657 execPath[0] = 0; 4658 bool ok = OSKext::copyUserExecutablePath(bundleID, execPath, sizeof(execPath)); 4659 if (ok) { 4660 ret = LoadModule(execPath); 4661 if (kIODKLogSetup & gIODKDebug) { 4662 DKLOG("%s::LoadModule 0x%x %s\n", getName(), ret, execPath); 4663 } 4664 } 4665 } 4666 OSSafeReleaseNULL(prop); 4667 4668 ret = kIOReturnSuccess; 4669 4670 return ret; 4671 } 4672 4673 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4674 4675 IOReturn 4676 IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void * securityID, 4677 uint32_t type, OSDictionary * properties, IOUserClient ** handler) 4678 { 4679 IOReturn ret; 4680 IOUserClient * uc; 4681 IOUserUserClient * userUC; 4682 OSDictionary * entitlements; 4683 OSObject * prop; 4684 OSObject * bundleID; 4685 bool ok = false; 4686 4687 entitlements = IOUserClient::copyClientEntitlements(owningTask); 4688 if (!entitlements) { 4689 entitlements = OSDictionary::withCapacity(8); 4690 } 4691 if (entitlements) { 4692 if (kIOReturnSuccess == clientHasPrivilege((void *) owningTask, kIOClientPrivilegeAdministrator)) { 4693 entitlements->setObject(kIODriverKitUserClientEntitlementAdministratorKey, kOSBooleanTrue); 4694 } 4695 OSString * creatorName = IOCopyLogNameForPID(proc_selfpid()); 4696 if (creatorName) { 4697 entitlements->setObject(kIOUserClientCreatorKey, creatorName); 4698 OSSafeReleaseNULL(creatorName); 4699 } 4700 } 4701 4702 *handler = NULL; 4703 ret = service->_NewUserClient(type, entitlements, &uc); 4704 if (kIOReturnSuccess != ret) { 4705 OSSafeReleaseNULL(entitlements); 4706 return ret; 4707 } 4708 userUC = OSDynamicCast(IOUserUserClient, uc); 4709 if (!userUC) { 4710 uc->terminate(kIOServiceTerminateNeedWillTerminate); 4711 uc->setTerminateDefer(service, false); 4712 OSSafeReleaseNULL(uc); 4713 OSSafeReleaseNULL(entitlements); 4714 return kIOReturnUnsupported; 4715 } 4716 userUC->setTask(owningTask); 4717 4718 if (!(kIODKDisableEntitlementChecking & gIODKDebug)) { 4719 do { 4720 bool checkiOS3pEntitlements; 4721 4722 // check if client has com.apple.private.driverkit.driver-access and the required entitlements match the driver's entitlements 4723 if (entitlements && (prop = entitlements->getObject(gIODriverKitRequiredEntitlementsKey))) { 4724 prop->retain(); 4725 ok = checkEntitlements(fEntitlements, prop, NULL, NULL); 4726 if (ok) { 4727 break; 4728 } else { 4729 DKLOG(DKS ":UC failed required entitlement check\n", DKN(userUC)); 4730 } 4731 } 4732 4733 #if XNU_TARGET_OS_IOS 4734 checkiOS3pEntitlements = !fPlatformDriver; 4735 if (checkiOS3pEntitlements && fTeamIdentifier == NULL) { 4736 DKLOG("warning: " DKS " does not have a team identifier\n", DKN(this)); 4737 } 4738 #else 4739 checkiOS3pEntitlements = false; 4740 #endif 4741 if (checkiOS3pEntitlements) { 4742 // App must have com.apple.developer.driverkit.communicates-with-drivers 4743 ok = entitlements && entitlements->getObject(gIODriverKitUserClientEntitlementCommunicatesWithDriversKey) == kOSBooleanTrue; 4744 if (ok) { 4745 // check team ID 4746 const char * clientTeamID = csproc_get_teamid(current_proc()); 4747 bool sameTeam = fTeamIdentifier != NULL && clientTeamID != NULL && strncmp(fTeamIdentifier->getCStringNoCopy(), clientTeamID, CS_MAX_TEAMID_LEN) == 0; 4748 4749 if (sameTeam) { 4750 ok = true; 4751 } else { 4752 // different team IDs, dext must have com.apple.developer.driverkit.allow-third-party-userclients 4753 ok = fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowThirdPartyUserClientsKey) == kOSBooleanTrue; 4754 } 4755 if (!ok) { 4756 DKLOG(DKS ":UC failed team ID check. client team=%s, driver team=%s\n", DKN(userUC), clientTeamID ? clientTeamID : "(null)", fTeamIdentifier ? fTeamIdentifier->getCStringNoCopy() : "(null)"); 4757 } 4758 } else { 4759 DKLOG(DKS ":UC entitlement check failed, app does not have %s entitlement\n", DKN(userUC), gIODriverKitUserClientEntitlementCommunicatesWithDriversKey->getCStringNoCopy()); 4760 } 4761 4762 // When checking iOS 3rd party entitlements, do not fall through to other entitlement checks 4763 break; 4764 } 4765 4766 // first party dexts and third party macOS dexts 4767 4768 // check if driver has com.apple.developer.driverkit.allow-any-userclient-access 4769 if (fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowAnyKey)) { 4770 ok = true; 4771 break; 4772 } 4773 4774 // check if client has com.apple.developer.driverkit.userclient-access and its value matches the bundle ID of the service 4775 bundleID = service->copyProperty(gIOModuleIdentifierKey); 4776 ok = (entitlements 4777 && bundleID 4778 && (prop = entitlements->getObject(gIODriverKitUserClientEntitlementsKey))); 4779 if (ok) { 4780 bool found __block = false; 4781 ok = prop->iterateObjects(^bool (OSObject * object) { 4782 found = object->isEqualTo(bundleID); 4783 return found; 4784 }); 4785 ok = found; 4786 } else { 4787 OSString * bundleIDStr = OSDynamicCast(OSString, bundleID); 4788 DKLOG(DKS ":UC failed userclient-access check, needed bundle ID %s\n", DKN(userUC), bundleIDStr ? bundleIDStr->getCStringNoCopy() : "(null)"); 4789 } 4790 OSSafeReleaseNULL(bundleID); 4791 } while (false); 4792 4793 if (ok) { 4794 prop = userUC->copyProperty(gIOServiceDEXTEntitlementsKey); 4795 ok = checkEntitlements(entitlements, prop, NULL, NULL); 4796 } 4797 4798 if (!ok) { 4799 DKLOG(DKS ":UC entitlements check failed\n", DKN(userUC)); 4800 uc->terminate(kIOServiceTerminateNeedWillTerminate); 4801 uc->setTerminateDefer(service, false); 4802 OSSafeReleaseNULL(uc); 4803 OSSafeReleaseNULL(entitlements); 4804 return kIOReturnNotPermitted; 4805 } 4806 } 4807 4808 OSSafeReleaseNULL(entitlements); 4809 *handler = userUC; 4810 4811 return ret; 4812 } 4813 4814 IOReturn 4815 IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void * securityID, 4816 uint32_t type, OSDictionary * properties, OSSharedPtr<IOUserClient>& handler) 4817 { 4818 IOUserClient* handlerRaw = NULL; 4819 IOReturn result = serviceNewUserClient(service, owningTask, securityID, type, properties, &handlerRaw); 4820 handler.reset(handlerRaw, OSNoRetain); 4821 return result; 4822 } 4823 4824 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4825 4826 static IOPMPowerState 4827 sPowerStates[] = { 4828 { .version = kIOPMPowerStateVersion1, 4829 .capabilityFlags = 0, 4830 .outputPowerCharacter = 0, 4831 .inputPowerRequirement = 0}, 4832 { .version = kIOPMPowerStateVersion1, 4833 .capabilityFlags = kIOPMLowPower, 4834 .outputPowerCharacter = kIOPMLowPower, 4835 .inputPowerRequirement = kIOPMLowPower}, 4836 { .version = kIOPMPowerStateVersion1, 4837 .capabilityFlags = kIOPMPowerOn, 4838 .outputPowerCharacter = kIOPMPowerOn, 4839 .inputPowerRequirement = kIOPMPowerOn}, 4840 }; 4841 4842 enum { 4843 kUserServerMaxPowerState = 2 4844 }; 4845 4846 IOReturn 4847 IOUserServer::serviceJoinPMTree(IOService * service) 4848 { 4849 IOReturn ret; 4850 IOService * pmProvider; 4851 bool joinTree; 4852 4853 if (service->reserved->uvars->userServerPM) { 4854 return kIOReturnSuccess; 4855 } 4856 4857 if (!fRootNotifier) { 4858 ret = registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0])); 4859 assert(kIOReturnSuccess == ret); 4860 IOServicePH::serverAdd(this); 4861 fRootNotifier = true; 4862 } 4863 4864 joinTree = false; 4865 if (!(kIODKDisablePM & gIODKDebug) && !service->pm_vars) { 4866 kern_return_t kr; 4867 OSDictionary * props; 4868 kr = service->CopyProperties_Local(&props); 4869 if (kIOReturnSuccess == kr) { 4870 if (props->getObject(kIOPMResetPowerStateOnWakeKey) == kOSBooleanTrue) { 4871 service->setProperty(kIOPMResetPowerStateOnWakeKey, kOSBooleanTrue); 4872 } 4873 OSSafeReleaseNULL(props); 4874 } 4875 service->PMinit(); 4876 ret = service->registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0])); 4877 assert(kIOReturnSuccess == ret); 4878 joinTree = true; 4879 } 4880 4881 pmProvider = service; 4882 while (pmProvider && !pmProvider->inPlane(gIOPowerPlane)) { 4883 pmProvider = pmProvider->getProvider(); 4884 } 4885 if (!pmProvider) { 4886 pmProvider = getPMRootDomain(); 4887 } 4888 if (pmProvider) { 4889 IOService * entry; 4890 OSObject * prop; 4891 OSObject * nextProp; 4892 OSString * str; 4893 4894 entry = pmProvider; 4895 prop = NULL; 4896 do { 4897 nextProp = entry->copyProperty("non-removable"); 4898 if (nextProp) { 4899 OSSafeReleaseNULL(prop); 4900 prop = nextProp; 4901 } 4902 entry = entry->getProvider(); 4903 } while (entry); 4904 if (prop) { 4905 str = OSDynamicCast(OSString, prop); 4906 if (str && str->isEqualTo("yes")) { 4907 pmProvider = NULL; 4908 } 4909 prop->release(); 4910 } 4911 } 4912 4913 if (!(kIODKDisablePM & gIODKDebug) && pmProvider) { 4914 IOLockLock(fLock); 4915 service->reserved->uvars->powerState = true; 4916 IOLockUnlock(fLock); 4917 4918 if (joinTree) { 4919 pmProvider->joinPMtree(service); 4920 service->reserved->uvars->userServerPM = true; 4921 service->reserved->uvars->resetPowerOnWake = service->propertyExists(kIOPMResetPowerStateOnWakeKey); 4922 } 4923 } 4924 4925 service->registerInterestedDriver(this); 4926 return kIOReturnSuccess; 4927 } 4928 4929 IOReturn 4930 IOUserServer::setPowerState(unsigned long state, IOService * service) 4931 { 4932 if (kIODKLogPM & gIODKDebug) { 4933 DKLOG(DKS "::setPowerState(%ld) %d\n", DKN(service), state, fSystemPowerAck); 4934 } 4935 return kIOPMAckImplied; 4936 } 4937 4938 4939 IOReturn 4940 IOUserServer::serviceSetPowerState(IOService * controllingDriver, IOService * service, IOPMPowerFlags flags, unsigned long state) 4941 { 4942 IOReturn ret; 4943 bool sendIt = false; 4944 4945 IOLockLock(fLock); 4946 if (service->reserved->uvars) { 4947 if (!fSystemOff && !(kIODKDisablePM & gIODKDebug)) { 4948 OSDictionary * wakeDescription; 4949 OSObject * prop; 4950 char wakeReasonString[128]; 4951 4952 wakeDescription = OSDictionary::withCapacity(4); 4953 if (wakeDescription) { 4954 wakeReasonString[0] = 0; 4955 getPMRootDomain()->copyWakeReasonString(wakeReasonString, sizeof(wakeReasonString)); 4956 4957 if (wakeReasonString[0]) { 4958 prop = OSString::withCString(&wakeReasonString[0]); 4959 wakeDescription->setObject(gIOSystemStateWakeDescriptionWakeReasonKey, prop); 4960 OSSafeReleaseNULL(prop); 4961 } 4962 #if defined(__arm__) || defined(__arm64__) 4963 prop = OSNumber::withNumber(ml_get_conttime_offset(), sizeof(uint64_t) * CHAR_BIT); 4964 wakeDescription->setObject(gIOSystemStateWakeDescriptionContinuousTimeOffsetKey, prop); 4965 OSSafeReleaseNULL(prop); 4966 #endif /* defined(__arm__) || defined(__arm64__) */ 4967 getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateWakeDescriptionKey, wakeDescription); 4968 OSSafeReleaseNULL(wakeDescription); 4969 } 4970 4971 service->reserved->uvars->willPower = true; 4972 service->reserved->uvars->willPowerState = state; 4973 service->reserved->uvars->controllingDriver = controllingDriver; 4974 sendIt = true; 4975 } else { 4976 service->reserved->uvars->willPower = false; 4977 } 4978 } 4979 IOLockUnlock(fLock); 4980 4981 if (sendIt) { 4982 if (kIODKLogPM & gIODKDebug) { 4983 DKLOG(DKS "::serviceSetPowerState(%ld) %d\n", DKN(service), state, fSystemPowerAck); 4984 } 4985 ret = service->SetPowerState((uint32_t) flags); 4986 if (kIOReturnSuccess == ret) { 4987 return 20 * 1000 * 1000; 4988 } else { 4989 IOLockLock(fLock); 4990 service->reserved->uvars->willPower = false; 4991 IOLockUnlock(fLock); 4992 } 4993 } 4994 4995 return kIOPMAckImplied; 4996 } 4997 4998 IOReturn 4999 IOUserServer::powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service) 5000 { 5001 return kIOPMAckImplied; 5002 } 5003 5004 IOReturn 5005 IOUserServer::powerStateDidChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service) 5006 { 5007 unsigned int idx; 5008 bool pmAck; 5009 5010 pmAck = false; 5011 IOLockLock(fLock); 5012 idx = fServices->getNextIndexOfObject(service, 0); 5013 if (-1U == idx) { 5014 IOLockUnlock(fLock); 5015 return kIOPMAckImplied; 5016 } 5017 5018 service->reserved->uvars->powerState = (0 != state); 5019 bool allPowerStates __block = service->reserved->uvars->powerState; 5020 if (!allPowerStates) { 5021 // any service on? 5022 fServices->iterateObjects(^bool (OSObject * obj) { 5023 int service __unused; // hide outer defn 5024 IOService * nextService; 5025 nextService = (IOService *) obj; 5026 allPowerStates = nextService->reserved->uvars->powerState; 5027 // early terminate if true 5028 return allPowerStates; 5029 }); 5030 } 5031 if (kIODKLogPM & gIODKDebug) { 5032 DKLOG(DKS "::powerStateDidChangeTo(%ld) %d, %d\n", DKN(service), state, allPowerStates, fSystemPowerAck); 5033 } 5034 if (!allPowerStates && (pmAck = fSystemPowerAck)) { 5035 fSystemPowerAck = false; 5036 fSystemOff = true; 5037 } 5038 IOLockUnlock(fLock); 5039 5040 if (pmAck) { 5041 IOServicePH::serverAck(this); 5042 } 5043 5044 return kIOPMAckImplied; 5045 } 5046 5047 bool 5048 IOUserServer::checkPMReady() 5049 { 5050 bool __block ready = true; 5051 5052 IOLockLock(fLock); 5053 // Check if any services have not completely joined the PM tree (i.e. 5054 // addPowerChild has not compeleted). 5055 fServices->iterateObjects(^bool (OSObject * obj) { 5056 IOPowerConnection *conn; 5057 IOService *service = (IOService *) obj; 5058 IORegistryEntry *parent = service->getParentEntry(gIOPowerPlane); 5059 if ((conn = OSDynamicCast(IOPowerConnection, parent))) { 5060 if (!conn->getReadyFlag()) { 5061 ready = false; 5062 return true; 5063 } 5064 } 5065 return false; 5066 }); 5067 IOLockUnlock(fLock); 5068 5069 return ready; 5070 } 5071 5072 kern_return_t 5073 IOService::JoinPMTree_Impl(void) 5074 { 5075 if (!reserved->uvars || !reserved->uvars->userServer) { 5076 return kIOReturnNotReady; 5077 } 5078 return reserved->uvars->userServer->serviceJoinPMTree(this); 5079 } 5080 5081 kern_return_t 5082 IOService::SetPowerState_Impl( 5083 uint32_t powerFlags) 5084 { 5085 if (kIODKLogPM & gIODKDebug) { 5086 DKLOG(DKS "::SetPowerState(%d), %d\n", DKN(this), powerFlags, reserved->uvars->willPower); 5087 } 5088 if (reserved->uvars 5089 && reserved->uvars->userServer 5090 && reserved->uvars->willPower) { 5091 IOReturn ret; 5092 reserved->uvars->willPower = false; 5093 ret = reserved->uvars->controllingDriver->setPowerState(reserved->uvars->willPowerState, this); 5094 if (kIOPMAckImplied == ret) { 5095 acknowledgeSetPowerState(); 5096 } 5097 return kIOReturnSuccess; 5098 } 5099 return kIOReturnNotReady; 5100 } 5101 5102 kern_return_t 5103 IOService::ChangePowerState_Impl( 5104 uint32_t powerFlags) 5105 { 5106 switch (powerFlags) { 5107 case kIOServicePowerCapabilityOff: 5108 changePowerStateToPriv(0); 5109 break; 5110 case kIOServicePowerCapabilityLow: 5111 changePowerStateToPriv(1); 5112 break; 5113 case kIOServicePowerCapabilityOn: 5114 changePowerStateToPriv(2); 5115 break; 5116 default: 5117 return kIOReturnBadArgument; 5118 } 5119 5120 return kIOReturnSuccess; 5121 } 5122 5123 kern_return_t 5124 IOService::_ClaimSystemWakeEvent_Impl( 5125 IOService * device, 5126 uint64_t flags, 5127 const char * reason, 5128 OSContainer * details) 5129 { 5130 IOPMrootDomain * rootDomain; 5131 IOOptionBits pmFlags; 5132 5133 rootDomain = getPMRootDomain(); 5134 if (!rootDomain) { 5135 return kIOReturnNotReady; 5136 } 5137 if (os_convert_overflow(flags, &pmFlags)) { 5138 return kIOReturnBadArgument; 5139 } 5140 rootDomain->claimSystemWakeEvent(device, pmFlags, reason, details); 5141 5142 return kIOReturnSuccess; 5143 } 5144 5145 kern_return_t 5146 IOService::Create_Impl( 5147 IOService * provider, 5148 const char * propertiesKey, 5149 IOService ** result) 5150 { 5151 OSObject * inst; 5152 IOService * service; 5153 OSString * str; 5154 const OSSymbol * sym; 5155 OSObject * prop = NULL; 5156 OSObject * moduleIdentifier = NULL; 5157 OSObject * userServerName = NULL; 5158 OSDictionary * properties = NULL; 5159 OSDictionary * copyProperties = NULL; 5160 kern_return_t ret; 5161 5162 if (provider != this) { 5163 return kIOReturnUnsupported; 5164 } 5165 5166 ret = kIOReturnUnsupported; 5167 inst = NULL; 5168 service = NULL; 5169 5170 prop = copyProperty(propertiesKey); 5171 properties = OSDynamicCast(OSDictionary, prop); 5172 if (!properties) { 5173 ret = kIOReturnBadArgument; 5174 goto finish; 5175 } 5176 copyProperties = OSDynamicCast(OSDictionary, properties->copyCollection()); 5177 if (!copyProperties) { 5178 ret = kIOReturnNoMemory; 5179 goto finish; 5180 } 5181 moduleIdentifier = copyProperty(gIOModuleIdentifierKey); 5182 if (moduleIdentifier) { 5183 copyProperties->setObject(gIOModuleIdentifierKey, moduleIdentifier); 5184 } 5185 userServerName = reserved->uvars->userServer->copyProperty(gIOUserServerNameKey); 5186 if (userServerName) { 5187 copyProperties->setObject(gIOUserServerNameKey, userServerName); 5188 } 5189 5190 str = OSDynamicCast(OSString, copyProperties->getObject(gIOClassKey)); 5191 if (!str) { 5192 ret = kIOReturnBadArgument; 5193 goto finish; 5194 } 5195 sym = OSSymbol::withString(str); 5196 if (sym) { 5197 inst = OSMetaClass::allocClassWithName(sym); 5198 service = OSDynamicCast(IOService, inst); 5199 if (service && service->init(copyProperties) && service->attach(this)) { 5200 reserved->uvars->userServer->serviceAttach(service, this); 5201 service->reserved->uvars->started = true; 5202 ret = kIOReturnSuccess; 5203 *result = service; 5204 } 5205 OSSafeReleaseNULL(sym); 5206 } 5207 5208 finish: 5209 OSSafeReleaseNULL(prop); 5210 OSSafeReleaseNULL(copyProperties); 5211 OSSafeReleaseNULL(moduleIdentifier); 5212 OSSafeReleaseNULL(userServerName); 5213 if (kIOReturnSuccess != ret) { 5214 OSSafeReleaseNULL(inst); 5215 } 5216 5217 return ret; 5218 } 5219 5220 kern_return_t 5221 IOService::Terminate_Impl( 5222 uint64_t options) 5223 { 5224 IOUserServer * us; 5225 5226 if (options) { 5227 return kIOReturnUnsupported; 5228 } 5229 5230 us = (typeof(us))thread_iokit_tls_get(0); 5231 if (us && (!reserved->uvars 5232 || (reserved->uvars->userServer != us))) { 5233 return kIOReturnNotPermitted; 5234 } 5235 terminate(kIOServiceTerminateNeedWillTerminate); 5236 5237 return kIOReturnSuccess; 5238 } 5239 5240 kern_return_t 5241 IOService::NewUserClient_Impl( 5242 uint32_t type, 5243 IOUserClient ** userClient) 5244 { 5245 return kIOReturnError; 5246 } 5247 5248 kern_return_t 5249 IOService::_NewUserClient_Impl( 5250 uint32_t type, 5251 OSDictionary * entitlements, 5252 IOUserClient ** userClient) 5253 { 5254 return kIOReturnError; 5255 } 5256 5257 kern_return_t 5258 IOService::SearchProperty_Impl( 5259 const char * name, 5260 const char * plane, 5261 uint64_t options, 5262 OSContainer ** property) 5263 { 5264 OSObject * object __block; 5265 IOService * provider; 5266 IOOptionBits regOptions; 5267 5268 if (kIOServiceSearchPropertyParents & options) { 5269 regOptions = kIORegistryIterateParents | kIORegistryIterateRecursively; 5270 } else { 5271 regOptions = 0; 5272 } 5273 5274 object = copyProperty(name, IORegistryEntry::getPlane(plane), regOptions); 5275 5276 if (NULL == object) { 5277 for (provider = this; provider; provider = provider->getProvider()) { 5278 provider->runPropertyActionBlock(^IOReturn (void) { 5279 OSDictionary * userProps; 5280 object = provider->getProperty(name); 5281 if (!object 5282 && (userProps = OSDynamicCast(OSDictionary, provider->getProperty(gIOUserServicePropertiesKey)))) { 5283 object = userProps->getObject(name); 5284 } 5285 if (object) { 5286 object->retain(); 5287 } 5288 return kIOReturnSuccess; 5289 }); 5290 if (object || !(kIORegistryIterateParents & options)) { 5291 break; 5292 } 5293 } 5294 } 5295 5296 *property = object; 5297 5298 return object ? kIOReturnSuccess : kIOReturnNotFound; 5299 } 5300 5301 kern_return_t 5302 IOService::StringFromReturn_Impl( 5303 IOReturn retval, 5304 OSString ** str) 5305 { 5306 OSString *obj = OSString::withCString(stringFromReturn(retval)); 5307 *str = obj; 5308 return obj ? kIOReturnSuccess : kIOReturnError; 5309 } 5310 5311 #if PRIVATE_WIFI_ONLY 5312 const char * 5313 IOService::StringFromReturn( 5314 IOReturn retval) 5315 { 5316 return stringFromReturn(retval); 5317 } 5318 #endif /* PRIVATE_WIFI_ONLY */ 5319 5320 kern_return_t 5321 IOService::CopyProviderProperties_Impl( 5322 OSArray * propertyKeys, 5323 OSArray ** properties) 5324 { 5325 IOReturn ret; 5326 OSArray * result; 5327 IOService * provider; 5328 5329 result = OSArray::withCapacity(8); 5330 if (!result) { 5331 return kIOReturnNoMemory; 5332 } 5333 5334 ret = kIOReturnSuccess; 5335 for (provider = this; provider; provider = provider->getProvider()) { 5336 OSObject * obj; 5337 OSDictionary * props; 5338 5339 obj = provider->copyProperty(gIOSupportedPropertiesKey); 5340 props = OSDynamicCast(OSDictionary, obj); 5341 if (!props) { 5342 OSSafeReleaseNULL(obj); 5343 props = provider->dictionaryWithProperties(); 5344 } 5345 if (!props) { 5346 ret = kIOReturnNoMemory; 5347 break; 5348 } 5349 5350 bool __block addClass = true; 5351 if (propertyKeys) { 5352 OSDictionary * retProps; 5353 retProps = OSDictionary::withCapacity(4); 5354 addClass = false; 5355 if (!retProps) { 5356 ret = kIOReturnNoMemory; 5357 OSSafeReleaseNULL(props); 5358 break; 5359 } 5360 propertyKeys->iterateObjects(^bool (OSObject * _key) { 5361 OSString * key = OSDynamicCast(OSString, _key); 5362 if (gIOClassKey->isEqualTo(key)) { 5363 addClass = true; 5364 return false; 5365 } 5366 retProps->setObject(key, props->getObject(key)); 5367 return false; 5368 }); 5369 OSSafeReleaseNULL(props); 5370 props = retProps; 5371 } 5372 if (addClass) { 5373 OSArray * classes = OSArray::withCapacity(8); 5374 if (!classes) { 5375 OSSafeReleaseNULL(props); 5376 ret = kIOReturnNoMemory; 5377 break; 5378 } 5379 for (const OSMetaClass * meta = provider->getMetaClass(); meta; meta = meta->getSuperClass()) { 5380 classes->setObject(meta->getClassNameSymbol()); 5381 } 5382 props->setObject(gIOClassKey, classes); 5383 OSSafeReleaseNULL(classes); 5384 } 5385 bool ok = result->setObject(props); 5386 props->release(); 5387 if (!ok) { 5388 ret = kIOReturnNoMemory; 5389 break; 5390 } 5391 } 5392 if (kIOReturnSuccess != ret) { 5393 OSSafeReleaseNULL(result); 5394 } 5395 *properties = result; 5396 return ret; 5397 } 5398 5399 IOReturn 5400 IOService::AdjustBusy_Impl(int32_t delta) 5401 { 5402 adjustBusy(delta); 5403 return kIOReturnSuccess; 5404 } 5405 5406 IOReturn 5407 IOService::GetBusyState_Impl(uint32_t *busyState) 5408 { 5409 *busyState = getBusyState(); 5410 return kIOReturnSuccess; 5411 } 5412 5413 void 5414 IOUserServer::systemPower(bool powerOff, bool hibernate) 5415 { 5416 OSArray * services; 5417 { 5418 OSDictionary * sleepDescription; 5419 OSObject * prop; 5420 5421 sleepDescription = OSDictionary::withCapacity(4); 5422 if (sleepDescription) { 5423 prop = getPMRootDomain()->copyProperty(kRootDomainSleepReasonKey); 5424 if (prop) { 5425 sleepDescription->setObject(gIOSystemStateSleepDescriptionReasonKey, prop); 5426 OSSafeReleaseNULL(prop); 5427 } 5428 prop = getPMRootDomain()->copyProperty(kIOHibernateStateKey); 5429 if (prop) { 5430 sleepDescription->setObject(gIOSystemStateSleepDescriptionHibernateStateKey, prop); 5431 OSSafeReleaseNULL(prop); 5432 } 5433 if (hibernate) { 5434 uint32_t correctHibernateState = kIOSystemStateSleepDescriptionHibernateStateHibernating; 5435 OSData *correctHibernateStateData = OSData::withValue(correctHibernateState); 5436 assert(correctHibernateStateData != NULL); 5437 sleepDescription->setObject(gIOSystemStateSleepDescriptionHibernateStateKey, correctHibernateStateData); 5438 OSSafeReleaseNULL(correctHibernateStateData); 5439 } 5440 getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateSleepDescriptionKey, sleepDescription); 5441 OSSafeReleaseNULL(sleepDescription); 5442 } 5443 } 5444 5445 IOLockLock(fLock); 5446 5447 services = OSArray::withArray(fServices); 5448 5449 bool allPowerStates __block = 0; 5450 // any service on? 5451 fServices->iterateObjects(^bool (OSObject * obj) { 5452 int service __unused; // hide outer defn 5453 IOService * nextService; 5454 nextService = (IOService *) obj; 5455 allPowerStates = nextService->reserved->uvars->powerState; 5456 // early terminate if true 5457 return allPowerStates; 5458 }); 5459 5460 if (kIODKLogPM & gIODKDebug) { 5461 DKLOG("%s::powerOff(%d) %d\n", getName(), powerOff, allPowerStates); 5462 } 5463 5464 if (powerOff) { 5465 fSystemPowerAck = allPowerStates; 5466 if (!fSystemPowerAck) { 5467 fSystemOff = true; 5468 } 5469 IOLockUnlock(fLock); 5470 5471 if (!fSystemPowerAck) { 5472 IOServicePH::serverAck(this); 5473 } else { 5474 if (services) { 5475 services->iterateObjects(^bool (OSObject * obj) { 5476 int service __unused; // hide outer defn 5477 IOService * nextService; 5478 nextService = (IOService *) obj; 5479 if (kIODKLogPM & gIODKDebug) { 5480 DKLOG("changePowerStateWithOverrideTo(" DKS ", %d)\n", DKN(nextService), 0); 5481 } 5482 nextService->reserved->uvars->powerOverride = nextService->reserved->uvars->userServerPM ? kUserServerMaxPowerState : nextService->getPowerState(); 5483 nextService->changePowerStateWithOverrideTo(0, 0); 5484 return false; 5485 }); 5486 } 5487 } 5488 } else { 5489 fSystemOff = false; 5490 IOLockUnlock(fLock); 5491 if (services) { 5492 services->iterateObjects(^bool (OSObject * obj) { 5493 int service __unused; // hide outer defn 5494 IOService * nextService; 5495 nextService = (IOService *) obj; 5496 if (-1U != nextService->reserved->uvars->powerOverride) { 5497 if (kIODKLogPM & gIODKDebug) { 5498 DKLOG("%schangePowerStateWithOverrideTo(" DKS ", %d)\n", nextService->reserved->uvars->resetPowerOnWake ? "!" : "", DKN(nextService), nextService->reserved->uvars->powerOverride); 5499 } 5500 if (!nextService->reserved->uvars->resetPowerOnWake) { 5501 nextService->changePowerStateWithOverrideTo(nextService->reserved->uvars->powerOverride, 0); 5502 } 5503 nextService->reserved->uvars->powerOverride = -1U; 5504 } 5505 return false; 5506 }); 5507 } 5508 } 5509 OSSafeReleaseNULL(services); 5510 } 5511 5512 5513 void 5514 IOUserServer::systemHalt(int howto) 5515 { 5516 OSArray * services; 5517 5518 if (true || (kIODKLogPM & gIODKDebug)) { 5519 DKLOG("%s::systemHalt()\n", getName()); 5520 } 5521 5522 { 5523 OSDictionary * haltDescription; 5524 OSNumber * state; 5525 uint64_t haltStateFlags; 5526 5527 haltDescription = OSDictionary::withCapacity(4); 5528 if (haltDescription) { 5529 haltStateFlags = 0; 5530 if (RB_HALT & howto) { 5531 haltStateFlags |= kIOServiceHaltStatePowerOff; 5532 } else { 5533 haltStateFlags |= kIOServiceHaltStateRestart; 5534 } 5535 state = OSNumber::withNumber(haltStateFlags, 64); 5536 haltDescription->setObject(gIOSystemStateHaltDescriptionHaltStateKey, state); 5537 getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateHaltDescriptionKey, haltDescription); 5538 5539 OSSafeReleaseNULL(state); 5540 OSSafeReleaseNULL(haltDescription); 5541 } 5542 } 5543 5544 IOLockLock(fLock); 5545 services = OSArray::withArray(fServices); 5546 IOLockUnlock(fLock); 5547 5548 if (services) { 5549 services->iterateObjects(^bool (OSObject * obj) { 5550 int service __unused; // hide outer defn 5551 IOService * nextService; 5552 IOService * provider; 5553 IOOptionBits terminateOptions; 5554 bool root; 5555 5556 nextService = (IOService *) obj; 5557 provider = nextService->getProvider(); 5558 if (!provider) { 5559 DKLOG("stale service " DKS " found, skipping termination\n", DKN(nextService)); 5560 return false; 5561 } 5562 root = (NULL == provider->getProperty(gIOUserServerNameKey, gIOServicePlane)); 5563 if (true || (kIODKLogPM & gIODKDebug)) { 5564 DKLOG("%d: terminate(" DKS ")\n", root, DKN(nextService)); 5565 } 5566 if (!root) { 5567 return false; 5568 } 5569 terminateOptions = kIOServiceRequired | kIOServiceTerminateNeedWillTerminate; 5570 if (!nextService->terminate(terminateOptions)) { 5571 IOLog("failed to terminate service %s-0x%llx\n", nextService->getName(), nextService->getRegistryEntryID()); 5572 } 5573 return false; 5574 }); 5575 } 5576 OSSafeReleaseNULL(services); 5577 } 5578 5579 void 5580 IOUserServer::powerSourceChanged(bool acAttached) 5581 { 5582 OSDictionary * powerSourceDescription; 5583 5584 powerSourceDescription = OSDictionary::withCapacity(4); 5585 if (!powerSourceDescription) { 5586 return; 5587 } 5588 powerSourceDescription->setObject(gIOSystemStatePowerSourceDescriptionACAttachedKey, acAttached ? kOSBooleanTrue : kOSBooleanFalse); 5589 getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStatePowerSourceDescriptionKey, powerSourceDescription); 5590 5591 OSSafeReleaseNULL(powerSourceDescription); 5592 } 5593 5594 IOReturn 5595 IOUserServer::serviceStarted(IOService * service, IOService * provider, bool result) 5596 { 5597 IOReturn ret; 5598 5599 DKLOG(DKS "::start(" DKS ") %s\n", DKN(service), DKN(provider), result ? "ok" : "fail"); 5600 5601 if (!result) { 5602 ret = kIOReturnSuccess; 5603 return ret; 5604 } 5605 5606 ret = serviceJoinPMTree(service); 5607 5608 service->reserved->uvars->started = true; 5609 5610 if (service->reserved->uvars->deferredRegisterService) { 5611 service->registerService(kIOServiceAsynchronous | kIOServiceDextRequirePowerForMatching); 5612 service->reserved->uvars->deferredRegisterService = false; 5613 } 5614 5615 return kIOReturnSuccess; 5616 } 5617 5618 5619 IOReturn 5620 IOUserServer::serviceOpen(IOService * provider, IOService * client) 5621 { 5622 OSObjectUserVars * uvars; 5623 IOReturn ret; 5624 5625 IOLockLock(client->reserved->uvars->uvarsLock); 5626 uvars = client->reserved->uvars; 5627 if (uvars->willTerminate || uvars->stopped) { 5628 DKLOG(DKS "- " DKS " blocked attempt to open " DKS "\n", DKN(this), DKN(client), DKN(provider)); 5629 ret = kIOReturnBadArgument; 5630 } else { 5631 if (!uvars->openProviders) { 5632 uvars->openProviders = OSArray::withObjects((const OSObject **) &provider, 1); 5633 } else if (-1U == uvars->openProviders->getNextIndexOfObject(provider, 0)) { 5634 uvars->openProviders->setObject(provider); 5635 } 5636 ret = kIOReturnSuccess; 5637 } 5638 5639 IOLockUnlock(client->reserved->uvars->uvarsLock); 5640 5641 return ret; 5642 } 5643 5644 IOReturn 5645 IOUserServer::serviceClose(IOService * provider, IOService * client) 5646 { 5647 OSObjectUserVars * uvars; 5648 unsigned int idx; 5649 IOReturn ret; 5650 5651 IOLockLock(client->reserved->uvars->uvarsLock); 5652 uvars = client->reserved->uvars; 5653 if (!uvars->openProviders) { 5654 ret = kIOReturnNotOpen; 5655 goto finish; 5656 } 5657 idx = uvars->openProviders->getNextIndexOfObject(provider, 0); 5658 if (-1U == idx) { 5659 ret = kIOReturnNotOpen; 5660 goto finish; 5661 } 5662 uvars->openProviders->removeObject(idx); 5663 if (!uvars->openProviders->getCount()) { 5664 OSSafeReleaseNULL(uvars->openProviders); 5665 } 5666 5667 ret = kIOReturnSuccess; 5668 5669 finish: 5670 IOLockUnlock(client->reserved->uvars->uvarsLock); 5671 5672 return ret; 5673 } 5674 5675 5676 IOReturn 5677 IOUserServer::serviceStop(IOService * service, IOService *) 5678 { 5679 IOReturn ret; 5680 uint32_t idx; 5681 bool pmAck; 5682 OSObjectUserVars * uvars; 5683 pmAck = false; 5684 IOLockLock(fLock); 5685 idx = fServices->getNextIndexOfObject(service, 0); 5686 if (-1U != idx) { 5687 fServices->removeObject(idx); 5688 5689 // Remove the service from IOAssociatedServices 5690 OSObject * serviceArrayObj = copyProperty(gIOAssociatedServicesKey); 5691 OSArray * serviceArray = OSDynamicCast(OSArray, serviceArrayObj); 5692 assert(serviceArray != NULL); 5693 5694 serviceArray = OSDynamicCast(OSArray, serviceArray->copyCollection()); 5695 assert(serviceArray != NULL); 5696 5697 // Index should be the same as it was in fServices 5698 OSNumber * __assert_only registryEntryID = OSDynamicCast(OSNumber, serviceArray->getObject(idx)); 5699 assert(registryEntryID); 5700 5701 // ensure it is the right service 5702 assert(registryEntryID->unsigned64BitValue() == service->getRegistryEntryID()); 5703 serviceArray->removeObject(idx); 5704 5705 setProperty(gIOAssociatedServicesKey, serviceArray); 5706 OSSafeReleaseNULL(serviceArray); 5707 OSSafeReleaseNULL(serviceArrayObj); 5708 5709 uvars = service->reserved->uvars; 5710 uvars->stopped = true; 5711 uvars->powerState = 0; 5712 5713 bool allPowerStates __block = 0; 5714 // any service on? 5715 fServices->iterateObjects(^bool (OSObject * obj) { 5716 int service __unused; // hide outer defn 5717 IOService * nextService; 5718 nextService = (IOService *) obj; 5719 allPowerStates = nextService->reserved->uvars->powerState; 5720 // early terminate if true 5721 return allPowerStates; 5722 }); 5723 5724 if (!allPowerStates && (pmAck = fSystemPowerAck)) { 5725 fSystemPowerAck = false; 5726 fSystemOff = true; 5727 } 5728 } 5729 IOLockUnlock(fLock); 5730 if (pmAck) { 5731 IOServicePH::serverAck(this); 5732 } 5733 5734 if (-1U == idx) { 5735 return kIOReturnSuccess; 5736 } 5737 5738 (void) service->deRegisterInterestedDriver(this); 5739 if (uvars->userServerPM) { 5740 service->PMstop(); 5741 } 5742 5743 ret = kIOReturnSuccess; 5744 return ret; 5745 } 5746 5747 void 5748 IOUserServer::serviceFree(IOService * service) 5749 { 5750 OSObjectUserVars * uvars; 5751 uint32_t idx, queueAlloc; 5752 IODispatchQueue ** unboundedQueueArray = NULL; 5753 5754 uvars = service->reserved->uvars; 5755 if (!uvars) { 5756 return; 5757 } 5758 if (uvars->queueArray && uvars->userMeta) { 5759 queueAlloc = 1; 5760 if (uvars->userMeta->queueNames) { 5761 queueAlloc += uvars->userMeta->queueNames->count; 5762 } 5763 for (idx = 0; idx < queueAlloc; idx++) { 5764 OSSafeReleaseNULL(uvars->queueArray[idx]); 5765 } 5766 unboundedQueueArray = uvars->queueArray.data(); 5767 IOSafeDeleteNULL(unboundedQueueArray, IODispatchQueue *, queueAlloc); 5768 uvars->queueArray = OSBoundedArrayRef<IODispatchQueue *>(); 5769 } 5770 OSSafeReleaseNULL(uvars->userServer); 5771 IOLockFree(uvars->uvarsLock); 5772 IOFreeType(service->reserved->uvars, OSObjectUserVars); 5773 } 5774 5775 void 5776 IOUserServer::serviceWillTerminate(IOService * client, IOService * provider, IOOptionBits options) 5777 { 5778 IOReturn ret; 5779 bool willTerminate; 5780 5781 willTerminate = false; 5782 IOLockLock(client->reserved->uvars->uvarsLock); 5783 if (!client->reserved->uvars->serverDied 5784 && !client->reserved->uvars->willTerminate) { 5785 client->reserved->uvars->willTerminate = true; 5786 willTerminate = true; 5787 } 5788 IOLockUnlock(client->reserved->uvars->uvarsLock); 5789 5790 if (willTerminate) { 5791 if (provider->isInactive() || IOServicePH::serverSlept()) { 5792 client->Stop_async(provider); 5793 ret = kIOReturnOffline; 5794 } else { 5795 ret = client->Stop(provider); 5796 } 5797 if (kIOReturnSuccess != ret) { 5798 IOUserServer::serviceDidStop(client, provider); 5799 ret = kIOReturnSuccess; 5800 } 5801 } 5802 } 5803 5804 void 5805 IOUserServer::serviceDidTerminate(IOService * client, IOService * provider, IOOptionBits options, bool * defer) 5806 { 5807 IOLockLock(client->reserved->uvars->uvarsLock); 5808 client->reserved->uvars->didTerminate = true; 5809 if (!client->reserved->uvars->serverDied 5810 && !client->reserved->uvars->stopped) { 5811 *defer = true; 5812 } 5813 IOLockUnlock(client->reserved->uvars->uvarsLock); 5814 } 5815 5816 void 5817 IOUserServer::serviceDidStop(IOService * client, IOService * provider) 5818 { 5819 bool complete; 5820 OSArray * closeArray; 5821 5822 complete = false; 5823 closeArray = NULL; 5824 5825 IOLockLock(client->reserved->uvars->uvarsLock); 5826 if (client->reserved->uvars 5827 && client->reserved->uvars->willTerminate 5828 && !client->reserved->uvars->stopped) { 5829 client->reserved->uvars->stopped = true; 5830 complete = client->reserved->uvars->didTerminate; 5831 } 5832 5833 if (client->reserved->uvars) { 5834 closeArray = client->reserved->uvars->openProviders; 5835 client->reserved->uvars->openProviders = NULL; 5836 } 5837 IOLockUnlock(client->reserved->uvars->uvarsLock); 5838 5839 if (closeArray) { 5840 closeArray->iterateObjects(^bool (OSObject * obj) { 5841 IOService * toClose; 5842 toClose = OSDynamicCast(IOService, obj); 5843 if (toClose) { 5844 DKLOG(DKS ":force close (" DKS ")\n", DKN(client), DKN(toClose)); 5845 toClose->close(client); 5846 } 5847 return false; 5848 }); 5849 closeArray->release(); 5850 } 5851 5852 if (complete) { 5853 bool defer = false; 5854 client->didTerminate(provider, 0, &defer); 5855 } 5856 } 5857 5858 kern_return_t 5859 IOService::ClientCrashed_Impl( 5860 IOService * client, 5861 uint64_t options) 5862 { 5863 return kIOReturnUnsupported; 5864 } 5865 5866 kern_return_t 5867 IOService::Stop_Impl( 5868 IOService * provider) 5869 { 5870 IOUserServer::serviceDidStop(this, provider); 5871 5872 return kIOReturnSuccess; 5873 } 5874 5875 void 5876 IOService::Stop_async_Impl( 5877 IOService * provider) 5878 { 5879 } 5880 5881 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 5882 5883 #undef super 5884 #define super IOUserClient 5885 5886 OSDefineMetaClassAndStructors(IOUserUserClient, IOUserClient) 5887 5888 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 5889 5890 bool 5891 IOUserUserClient::init(OSDictionary * properties) 5892 { 5893 if (!super::init(properties)) { 5894 return false; 5895 } 5896 5897 fWorkGroups = OSDictionary::withCapacity(0); 5898 if (fWorkGroups == NULL) { 5899 return false; 5900 } 5901 5902 fEventLinks = OSDictionary::withCapacity(0); 5903 if (fEventLinks == NULL) { 5904 return false; 5905 } 5906 5907 fLock = IOLockAlloc(); 5908 5909 return true; 5910 } 5911 5912 void 5913 IOUserUserClient::free() 5914 { 5915 OSSafeReleaseNULL(fWorkGroups); 5916 OSSafeReleaseNULL(fEventLinks); 5917 if (fLock) { 5918 IOLockFree(fLock); 5919 } 5920 5921 super::free(); 5922 } 5923 5924 IOReturn 5925 IOUserUserClient::setTask(task_t task) 5926 { 5927 task_reference(task); 5928 fTask = task; 5929 5930 return kIOReturnSuccess; 5931 } 5932 5933 void 5934 IOUserUserClient::stop(IOService * provider) 5935 { 5936 if (fTask) { 5937 task_deallocate(fTask); 5938 fTask = NULL; 5939 } 5940 super::stop(provider); 5941 } 5942 5943 IOReturn 5944 IOUserUserClient::clientClose(void) 5945 { 5946 terminate(kIOServiceTerminateNeedWillTerminate); 5947 return kIOReturnSuccess; 5948 } 5949 5950 IOReturn 5951 IOUserUserClient::setProperties(OSObject * properties) 5952 { 5953 IOReturn ret = kIOReturnUnsupported; 5954 return ret; 5955 } 5956 5957 // p1 - name of object 5958 // p2 - length of object name 5959 // p3 - mach port name 5960 5961 kern_return_t 5962 IOUserUserClient::eventlinkConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6) 5963 { 5964 user_addr_t userObjectName = (user_addr_t)p1; 5965 mach_port_name_t portName = (mach_port_name_t)(uintptr_t)p3; 5966 mach_port_t port = MACH_PORT_NULL; 5967 ipc_kobject_type_t portType; 5968 char eventlinkName[kIOEventLinkMaxNameLength + 1] = {0}; 5969 size_t eventLinkNameLen; 5970 OSString * eventlinkNameStr = NULL; // must release 5971 IOEventLink * eventLink = NULL; // do not release 5972 kern_return_t ret; 5973 5974 ret = copyinstr(userObjectName, &eventlinkName[0], sizeof(eventlinkName), &eventLinkNameLen); 5975 if (ret != kIOReturnSuccess) { 5976 goto finish; 5977 } 5978 5979 // ensure string length matches trap argument 5980 if (eventLinkNameLen != (size_t)p2 + 1) { 5981 ret = kIOReturnBadArgument; 5982 goto finish; 5983 } 5984 5985 eventlinkNameStr = OSString::withCStringNoCopy(eventlinkName); 5986 if (eventlinkNameStr == NULL) { 5987 ret = kIOReturnNoMemory; 5988 goto finish; 5989 } 5990 5991 IOLockLock(fLock); 5992 eventLink = OSDynamicCast(IOEventLink, fEventLinks->getObject(eventlinkNameStr)); 5993 if (eventLink) { 5994 eventLink->retain(); 5995 } 5996 IOLockUnlock(fLock); 5997 5998 if (eventLink == NULL) { 5999 ret = kIOReturnNotFound; 6000 goto finish; 6001 } 6002 6003 port = iokit_lookup_raw_current_task(portName, &portType); 6004 6005 if (port == NULL) { 6006 ret = kIOReturnNotFound; 6007 goto finish; 6008 } 6009 6010 if (portType != IKOT_EVENTLINK) { 6011 ret = kIOReturnBadArgument; 6012 goto finish; 6013 } 6014 6015 ret = eventLink->SetEventlinkPort(port); 6016 if (ret != kIOReturnSuccess) { 6017 if (kIODKLogSetup & gIODKDebug) { 6018 DKLOG(DKS " %s SetEventlinkPort() returned %x\n", DKN(this), eventlinkNameStr->getCStringNoCopy(), ret); 6019 } 6020 goto finish; 6021 } 6022 6023 finish: 6024 if (port != NULL) { 6025 iokit_release_port_send(port); 6026 } 6027 6028 OSSafeReleaseNULL(eventlinkNameStr); 6029 OSSafeReleaseNULL(eventLink); 6030 6031 return ret; 6032 } 6033 6034 kern_return_t 6035 IOUserUserClient::workgroupConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6) 6036 { 6037 user_addr_t userObjectName = (user_addr_t)p1; 6038 mach_port_name_t portName = (mach_port_name_t)(uintptr_t)p3; 6039 mach_port_t port = MACH_PORT_NULL; 6040 ipc_kobject_type_t portType; 6041 char workgroupName[kIOWorkGroupMaxNameLength + 1] = {0}; 6042 size_t workgroupNameLen; 6043 OSString * workgroupNameStr = NULL; // must release 6044 IOWorkGroup * workgroup = NULL; // do not release 6045 kern_return_t ret; 6046 6047 ret = copyinstr(userObjectName, &workgroupName[0], sizeof(workgroupName), &workgroupNameLen); 6048 if (ret != kIOReturnSuccess) { 6049 goto finish; 6050 } 6051 6052 // ensure string length matches trap argument 6053 if (workgroupNameLen != (size_t)p2 + 1) { 6054 ret = kIOReturnBadArgument; 6055 goto finish; 6056 } 6057 6058 workgroupNameStr = OSString::withCStringNoCopy(workgroupName); 6059 if (workgroupNameStr == NULL) { 6060 ret = kIOReturnNoMemory; 6061 goto finish; 6062 } 6063 6064 IOLockLock(fLock); 6065 workgroup = OSDynamicCast(IOWorkGroup, fWorkGroups->getObject(workgroupNameStr)); 6066 if (workgroup) { 6067 workgroup->retain(); 6068 } 6069 IOLockUnlock(fLock); 6070 6071 if (workgroup == NULL) { 6072 ret = kIOReturnNotFound; 6073 goto finish; 6074 } 6075 6076 port = iokit_lookup_raw_current_task(portName, &portType); 6077 6078 if (port == NULL) { 6079 ret = kIOReturnNotFound; 6080 goto finish; 6081 } 6082 6083 if (portType != IKOT_WORK_INTERVAL) { 6084 ret = kIOReturnBadArgument; 6085 goto finish; 6086 } 6087 6088 ret = workgroup->SetWorkGroupPort(port); 6089 if (ret != kIOReturnSuccess) { 6090 if (kIODKLogSetup & gIODKDebug) { 6091 DKLOG(DKS " %s SetWorkGroupPort() returned %x\n", DKN(this), workgroupNameStr->getCStringNoCopy(), ret); 6092 } 6093 goto finish; 6094 } 6095 6096 finish: 6097 6098 if (port != NULL) { 6099 iokit_release_port_send(port); 6100 } 6101 6102 OSSafeReleaseNULL(workgroupNameStr); 6103 OSSafeReleaseNULL(workgroup); 6104 6105 return ret; 6106 } 6107 6108 IOExternalTrap * 6109 IOUserUserClient::getTargetAndTrapForIndex( IOService **targetP, UInt32 index ) 6110 { 6111 static const OSBoundedArray<IOExternalTrap, 2> trapTemplate = {{ 6112 { NULL, (IOTrap) & IOUserUserClient::eventlinkConfigurationTrap}, 6113 { NULL, (IOTrap) & IOUserUserClient::workgroupConfigurationTrap}, 6114 }}; 6115 if (index >= trapTemplate.size()) { 6116 return NULL; 6117 } 6118 *targetP = this; 6119 return (IOExternalTrap *)&trapTemplate[index]; 6120 } 6121 6122 kern_return_t 6123 IOUserClient::CopyClientEntitlements_Impl(OSDictionary ** entitlements) 6124 { 6125 return kIOReturnUnsupported; 6126 }; 6127 6128 struct IOUserUserClientActionRef { 6129 OSAsyncReference64 asyncRef; 6130 }; 6131 6132 void 6133 IOUserClient::KernelCompletion_Impl( 6134 OSAction * action, 6135 IOReturn status, 6136 const unsigned long long * asyncData, 6137 uint32_t asyncDataCount) 6138 { 6139 IOUserUserClientActionRef * ref; 6140 6141 ref = (typeof(ref))action->GetReference(); 6142 6143 IOUserClient::sendAsyncResult64(ref->asyncRef, status, (io_user_reference_t *) asyncData, asyncDataCount); 6144 } 6145 6146 kern_return_t 6147 IOUserClient::_ExternalMethod_Impl( 6148 uint64_t selector, 6149 const unsigned long long * scalarInput, 6150 uint32_t scalarInputCount, 6151 OSData * structureInput, 6152 IOMemoryDescriptor * structureInputDescriptor, 6153 unsigned long long * scalarOutput, 6154 uint32_t * scalarOutputCount, 6155 uint64_t structureOutputMaximumSize, 6156 OSData ** structureOutput, 6157 IOMemoryDescriptor * structureOutputDescriptor, 6158 OSAction * completion) 6159 { 6160 return kIOReturnUnsupported; 6161 } 6162 6163 IOReturn 6164 IOUserUserClient::clientMemoryForType(UInt32 type, 6165 IOOptionBits * koptions, 6166 IOMemoryDescriptor ** kmemory) 6167 { 6168 IOReturn kr; 6169 uint64_t options; 6170 IOMemoryDescriptor * memory; 6171 6172 kr = CopyClientMemoryForType(type, &options, &memory); 6173 6174 *koptions = 0; 6175 *kmemory = NULL; 6176 if (kIOReturnSuccess != kr) { 6177 return kr; 6178 } 6179 6180 if (kIOUserClientMemoryReadOnly & options) { 6181 *koptions |= kIOMapReadOnly; 6182 } 6183 *kmemory = memory; 6184 6185 return kr; 6186 } 6187 6188 IOReturn 6189 IOUserUserClient::externalMethod(uint32_t selector, IOExternalMethodArguments * args, 6190 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) 6191 { 6192 IOReturn kr; 6193 OSData * structureInput; 6194 OSData * structureOutput; 6195 size_t copylen; 6196 uint64_t structureOutputSize; 6197 OSAction * action; 6198 IOUserUserClientActionRef * ref; 6199 mach_port_t wake_port = MACH_PORT_NULL; 6200 6201 kr = kIOReturnUnsupported; 6202 structureInput = NULL; 6203 action = NULL; 6204 ref = NULL; 6205 6206 if (args->structureInputSize) { 6207 structureInput = OSData::withBytesNoCopy((void *) args->structureInput, args->structureInputSize); 6208 } 6209 6210 if (MACH_PORT_NULL != args->asyncWakePort) { 6211 // this retain is for the OSAction to release 6212 wake_port = ipc_port_make_send_mqueue(args->asyncWakePort); 6213 kr = CreateActionKernelCompletion(sizeof(IOUserUserClientActionRef), &action); 6214 assert(KERN_SUCCESS == kr); 6215 ref = (typeof(ref))action->GetReference(); 6216 bcopy(args->asyncReference, &ref->asyncRef[0], args->asyncReferenceCount * sizeof(ref->asyncRef[0])); 6217 kr = action->SetAbortedHandler(^(void) { 6218 IOUserUserClientActionRef * ref; 6219 IOReturn ret; 6220 6221 ref = (typeof(ref))action->GetReference(); 6222 ret = releaseAsyncReference64(ref->asyncRef); 6223 assert(kIOReturnSuccess == ret); 6224 bzero(&ref->asyncRef[0], sizeof(ref->asyncRef)); 6225 }); 6226 assert(KERN_SUCCESS == kr); 6227 } 6228 6229 if (args->structureVariableOutputData) { 6230 structureOutputSize = kIOUserClientVariableStructureSize; 6231 } else if (args->structureOutputDescriptor) { 6232 structureOutputSize = args->structureOutputDescriptor->getLength(); 6233 } else { 6234 structureOutputSize = args->structureOutputSize; 6235 } 6236 6237 kr = _ExternalMethod(selector, &args->scalarInput[0], args->scalarInputCount, 6238 structureInput, args->structureInputDescriptor, 6239 args->scalarOutput, &args->scalarOutputCount, 6240 structureOutputSize, &structureOutput, args->structureOutputDescriptor, 6241 action); 6242 6243 OSSafeReleaseNULL(structureInput); 6244 OSSafeReleaseNULL(action); 6245 6246 if (kr == kIOReturnSuccess && structureOutput) { 6247 if (args->structureVariableOutputData) { 6248 *args->structureVariableOutputData = structureOutput; 6249 } else { 6250 copylen = structureOutput->getLength(); 6251 if (copylen > args->structureOutputSize) { 6252 kr = kIOReturnBadArgument; 6253 } else { 6254 bcopy((const void *) structureOutput->getBytesNoCopy(), args->structureOutput, copylen); 6255 args->structureOutputSize = (uint32_t) copylen; 6256 } 6257 OSSafeReleaseNULL(structureOutput); 6258 } 6259 } 6260 6261 if (kIOReturnSuccess != kr) { 6262 // mig will destroy any async port 6263 return kr; 6264 } 6265 6266 // We must never return error after this point in order to preserve MIG ownership semantics 6267 assert(kr == kIOReturnSuccess); 6268 if (MACH_PORT_NULL != wake_port) { 6269 // this release is for the mig created send right 6270 iokit_release_port_send(wake_port); 6271 } 6272 6273 return kr; 6274 } 6275 6276 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 6277 6278 extern IORecursiveLock * gDriverKitLaunchLock; 6279 extern OSSet * gDriverKitLaunches; 6280 6281 _IOUserServerCheckInCancellationHandler * 6282 IOUserServerCheckInToken::setCancellationHandler(IOUserServerCheckInCancellationHandler handler, 6283 void* handlerArgs) 6284 { 6285 _IOUserServerCheckInCancellationHandler * handlerObj = _IOUserServerCheckInCancellationHandler::withHandler(handler, handlerArgs); 6286 if (!handlerObj) { 6287 goto finish; 6288 } 6289 6290 IORecursiveLockLock(gDriverKitLaunchLock); 6291 6292 if (fState == kIOUserServerCheckInCanceled) { 6293 // Send cancel notification if we set the handler after this was canceled 6294 handlerObj->call(this); 6295 } else if (fState == kIOUserServerCheckInPending) { 6296 fHandlers->setObject(handlerObj); 6297 } 6298 6299 IORecursiveLockUnlock(gDriverKitLaunchLock); 6300 6301 finish: 6302 return handlerObj; 6303 } 6304 6305 void 6306 IOUserServerCheckInToken::removeCancellationHandler(_IOUserServerCheckInCancellationHandler * handler) 6307 { 6308 IORecursiveLockLock(gDriverKitLaunchLock); 6309 6310 fHandlers->removeObject(handler); 6311 6312 IORecursiveLockUnlock(gDriverKitLaunchLock); 6313 } 6314 6315 void 6316 IOUserServerCheckInToken::cancel() 6317 { 6318 IORecursiveLockLock(gDriverKitLaunchLock); 6319 6320 if (fState == kIOUserServerCheckInPending) { 6321 fState = kIOUserServerCheckInCanceled; 6322 if (gDriverKitLaunches != NULL) { 6323 // Remove pending launch from list, if we have not shut down yet. 6324 gDriverKitLaunches->removeObject(this); 6325 } 6326 6327 fHandlers->iterateObjects(^bool (OSObject * obj){ 6328 _IOUserServerCheckInCancellationHandler * handlerObj = OSDynamicCast(_IOUserServerCheckInCancellationHandler, obj); 6329 if (handlerObj) { 6330 handlerObj->call(this); 6331 } 6332 return false; 6333 }); 6334 fHandlers->flushCollection(); 6335 } 6336 6337 IORecursiveLockUnlock(gDriverKitLaunchLock); 6338 } 6339 6340 IOReturn 6341 IOUserServerCheckInToken::complete() 6342 { 6343 IOReturn ret; 6344 IORecursiveLockLock(gDriverKitLaunchLock); 6345 6346 if (fState == kIOUserServerCheckInCanceled) { 6347 ret = kIOReturnError; 6348 } else { 6349 ret = kIOReturnSuccess; 6350 } 6351 6352 if (fState == kIOUserServerCheckInPending && --fPendingCount == 0) { 6353 fState = kIOUserServerCheckInComplete; 6354 if (gDriverKitLaunches != NULL) { 6355 // Remove pending launch from list, if we have not shut down yet. 6356 gDriverKitLaunches->removeObject(this); 6357 } 6358 6359 // No need to hold on to the cancellation handlers 6360 fHandlers->flushCollection(); 6361 } 6362 6363 IORecursiveLockUnlock(gDriverKitLaunchLock); 6364 return ret; 6365 } 6366 6367 bool 6368 IOUserServerCheckInToken::init(const OSSymbol * serverName, OSNumber * serverTag, OSKext *driverKext, OSData *serverDUI) 6369 { 6370 if (!OSObject::init()) { 6371 return false; 6372 } 6373 6374 if (!serverName) { 6375 return false; 6376 } 6377 fServerName = serverName; 6378 fServerName->retain(); 6379 6380 if (!serverTag) { 6381 return false; 6382 } 6383 fServerTag = serverTag; 6384 fServerTag->retain(); 6385 6386 fHandlers = OSSet::withCapacity(0); 6387 if (!fHandlers) { 6388 return false; 6389 } 6390 6391 fState = kIOUserServerCheckInPending; 6392 fPendingCount = 1; 6393 6394 fKextBundleID = NULL; 6395 fNeedDextDec = false; 6396 6397 fExecutableName = NULL; 6398 6399 if (driverKext) { 6400 fExecutableName = OSDynamicCast(OSSymbol, driverKext->getBundleExecutable()); 6401 6402 if (fExecutableName) { 6403 fExecutableName->retain(); 6404 } 6405 6406 /* 6407 * We need to keep track of how many dexts we have started. 6408 * For every new dext we are going to create a new token, and 6409 * we consider the token creation as the initial step to 6410 * create a dext as it is the data structure that will back up 6411 * the userspace dance to start a dext. 6412 * We later have to decrement only once per token. 6413 * If no error occurs we consider the finalize() call on IOUserServer 6414 * as the moment in which we do not consider the dext "alive" anymore; 6415 * however in case of errors we will still need to decrement the count 6416 * otherwise upgrades of the dext will never make progress. 6417 */ 6418 if (OSKext::incrementDextLaunchCount(driverKext, serverDUI)) { 6419 /* 6420 * If fKext holds a pointer, 6421 * it is the indication that a decrements needs 6422 * to be called. 6423 */ 6424 fNeedDextDec = true; 6425 fKextBundleID = OSDynamicCast(OSString, driverKext->getIdentifier()); 6426 fKextBundleID->retain(); 6427 } else { 6428 return false; 6429 } 6430 } 6431 6432 return true; 6433 } 6434 6435 /* 6436 * Returns if the dext can be re-used 6437 * for matching. 6438 */ 6439 bool 6440 IOUserServerCheckInToken::dextTerminate(void) 6441 { 6442 bool ret = true; 6443 6444 if (fNeedDextDec == true) { 6445 /* 6446 * We can decrement DextLaunchCount only 6447 * once per token. 6448 */ 6449 ret = !(OSKext::decrementDextLaunchCount(fKextBundleID)); 6450 fNeedDextDec = false; 6451 } 6452 6453 return ret; 6454 } 6455 6456 void 6457 IOUserServerCheckInToken::free() 6458 { 6459 OSSafeReleaseNULL(fServerName); 6460 OSSafeReleaseNULL(fServerTag); 6461 OSSafeReleaseNULL(fExecutableName); 6462 OSSafeReleaseNULL(fHandlers); 6463 if (fKextBundleID != NULL) { 6464 dextTerminate(); 6465 OSSafeReleaseNULL(fKextBundleID); 6466 } 6467 6468 OSObject::free(); 6469 } 6470 6471 const OSSymbol * 6472 IOUserServerCheckInToken::copyServerName() const 6473 { 6474 fServerName->retain(); 6475 return fServerName; 6476 } 6477 6478 OSNumber * 6479 IOUserServerCheckInToken::copyServerTag() const 6480 { 6481 fServerTag->retain(); 6482 return fServerTag; 6483 } 6484 6485 IOUserServer * 6486 IOUserServer::launchUserServer(OSString * bundleID, const OSSymbol * serverName, OSNumber * serverTag, bool reuseIfExists, IOUserServerCheckInToken ** resultToken, OSData *serverDUI) 6487 { 6488 IOUserServer *me = NULL; 6489 IOUserServerCheckInToken * token = NULL; 6490 OSDictionary * matching = NULL; // must release 6491 OSKext * driverKext = NULL; // must release 6492 OSDextStatistics * driverStatistics = NULL; // must release 6493 bool reslide = false; 6494 6495 /* TODO: Check we are looking for same dextID 6496 * and if it is not the same 6497 * restart the matching process. 6498 */ 6499 driverKext = OSKext::lookupDextWithIdentifier(bundleID, serverDUI); 6500 if (driverKext != NULL) { 6501 driverStatistics = driverKext->copyDextStatistics(); 6502 if (driverStatistics == NULL) { 6503 panic("Kext %s was not a DriverKit OSKext", bundleID->getCStringNoCopy()); 6504 } 6505 IOLog("Driver %s has crashed %zu time(s)\n", bundleID->getCStringNoCopy(), driverStatistics->getCrashCount()); 6506 reslide = driverStatistics->getCrashCount() > 0; 6507 } else { 6508 DKLOG("Could not find OSKext for %s\n", bundleID->getCStringNoCopy()); 6509 *resultToken = NULL; 6510 return NULL; 6511 } 6512 6513 IORecursiveLockLock(gDriverKitLaunchLock); 6514 6515 if (gDriverKitLaunches == NULL) { 6516 // About to shut down, don't launch anything 6517 goto finish; 6518 } 6519 6520 if (reuseIfExists) { 6521 const char * serverNameCStr; 6522 const char * bundleIDCStr; 6523 const char * endOrgCStr; 6524 6525 serverNameCStr = serverName->getCStringNoCopy(); 6526 bundleIDCStr = bundleID->getCStringNoCopy(); 6527 (endOrgCStr = strchr(bundleIDCStr, '.')) && (endOrgCStr = strchr(endOrgCStr + 1, '.')); 6528 reuseIfExists = endOrgCStr && (0 == strncmp(bundleIDCStr, serverNameCStr, endOrgCStr + 1 - bundleIDCStr)); 6529 if (!reuseIfExists) { 6530 IOLog(kIOUserServerNameKey " \"%s\" not correct organization for bundleID \"%s\"\n", serverNameCStr, bundleIDCStr); 6531 } 6532 } 6533 6534 // Find existing server 6535 if (reuseIfExists) { 6536 token = IOUserServerCheckInToken::findExistingToken(serverName); 6537 if (token) { 6538 // Launch in progress, return token 6539 goto finish; 6540 } else { 6541 // Check if launch completed 6542 matching = IOService::serviceMatching(gIOUserServerClassKey); 6543 if (!matching) { 6544 goto finish; 6545 } 6546 IOService::propertyMatching(gIOUserServerNameKey, serverName, matching); 6547 IOService * service = IOService::copyMatchingService(matching); 6548 IOUserServer * userServer = OSDynamicCast(IOUserServer, service); 6549 if (userServer) { 6550 // found existing user server 6551 me = userServer; 6552 goto finish; 6553 } else { 6554 OSSafeReleaseNULL(service); 6555 } 6556 } 6557 } 6558 6559 // No existing server, request launch 6560 token = new IOUserServerCheckInToken; 6561 if (!token) { 6562 goto finish; 6563 } 6564 6565 /* 6566 * TODO: If the init fails because the personalities are not up to date 6567 * restart the whole matching process. 6568 */ 6569 if (token && !token->init(serverName, serverTag, driverKext, serverDUI)) { 6570 IOLog("Could not initialize token\n"); 6571 OSSafeReleaseNULL(token); 6572 goto finish; 6573 } 6574 6575 /* 6576 * If the launch fails at any point terminate() will 6577 * be called on this IOUserServer. 6578 */ 6579 gDriverKitLaunches->setObject(token); 6580 OSKext::requestDaemonLaunch(bundleID, (OSString *)serverName, serverTag, reslide ? kOSBooleanTrue : kOSBooleanFalse, token, serverDUI); 6581 6582 finish: 6583 IORecursiveLockUnlock(gDriverKitLaunchLock); 6584 OSSafeReleaseNULL(matching); 6585 OSSafeReleaseNULL(driverStatistics); 6586 OSSafeReleaseNULL(driverKext); 6587 6588 if (resultToken) { 6589 *resultToken = token; 6590 } else { 6591 OSSafeReleaseNULL(token); 6592 } 6593 6594 return me; 6595 } 6596 6597 /* 6598 * IOUserServerCheckInTokens are used to track dext launches. They have three possible states: 6599 * 6600 * - Pending: A dext launch is pending 6601 * - Canceled: Dext launch failed 6602 * - Complete: Dext launch is complete 6603 * 6604 * A token can be shared among multiple IOServices that are waiting for dexts if the IOUserServerName 6605 * is the same. This allows dexts to be reused and host multiple services. All pending tokens are stored 6606 * in gDriverKitLaunches and we check here before creating a new token when launching a dext. 6607 * 6608 * A token starts in the pending state with a pending count of 1. When we reuse a token, we increase the 6609 * pending count of the token. 6610 * 6611 * The token is sent to userspace as a mach port through kernelmanagerd/driverkitd to the dext. The dext then 6612 * uses that token to check in to the kernel. If any part of the dext launch failed (dext crashed, kmd crashed, etc.) 6613 * we get a no-senders notification for the token in the kernel and the token goes into the Canceled state. 6614 * 6615 * Once the dext checks in to the kernel, we decrement the pending count for the token. When the pending count reaches 6616 * 0, the token goes into the Complete state. So if the token is in the Complete state, there are no kernel matching threads 6617 * waiting on the dext to check in. 6618 */ 6619 6620 IOUserServerCheckInToken * 6621 IOUserServerCheckInToken::findExistingToken(const OSSymbol * serverName) 6622 { 6623 IOUserServerCheckInToken * __block result = NULL; 6624 6625 IORecursiveLockLock(gDriverKitLaunchLock); 6626 if (gDriverKitLaunches == NULL) { 6627 goto finish; 6628 } 6629 6630 gDriverKitLaunches->iterateObjects(^(OSObject * obj) { 6631 IOUserServerCheckInToken * token = OSDynamicCast(IOUserServerCheckInToken, obj); 6632 if (token) { 6633 // Check if server name matches 6634 const OSSymbol * tokenServerName = token->fServerName; 6635 if (tokenServerName->isEqualTo(serverName)) { 6636 assert(token->fState == kIOUserServerCheckInPending); 6637 token->fPendingCount++; 6638 result = token; 6639 result->retain(); 6640 } 6641 } 6642 return result != NULL; 6643 }); 6644 6645 finish: 6646 IORecursiveLockUnlock(gDriverKitLaunchLock); 6647 return result; 6648 } 6649 6650 void 6651 IOUserServerCheckInToken::cancelAll() 6652 { 6653 OSSet * tokensToCancel; 6654 6655 IORecursiveLockLock(gDriverKitLaunchLock); 6656 tokensToCancel = gDriverKitLaunches; 6657 gDriverKitLaunches = NULL; 6658 6659 6660 tokensToCancel->iterateObjects(^(OSObject *obj) { 6661 IOUserServerCheckInToken * token = OSDynamicCast(IOUserServerCheckInToken, obj); 6662 if (token) { 6663 token->cancel(); 6664 } 6665 return false; 6666 }); 6667 6668 IORecursiveLockUnlock(gDriverKitLaunchLock); 6669 6670 OSSafeReleaseNULL(tokensToCancel); 6671 } 6672 6673 void 6674 _IOUserServerCheckInCancellationHandler::call(IOUserServerCheckInToken * token) 6675 { 6676 fHandler(token, fHandlerArgs); 6677 } 6678 6679 _IOUserServerCheckInCancellationHandler * 6680 _IOUserServerCheckInCancellationHandler::withHandler(IOUserServerCheckInCancellationHandler handler, void * args) 6681 { 6682 _IOUserServerCheckInCancellationHandler * handlerObj = NULL; 6683 if (!handler) { 6684 goto finish; 6685 } 6686 6687 handlerObj = new _IOUserServerCheckInCancellationHandler; 6688 if (!handlerObj) { 6689 goto finish; 6690 } 6691 6692 handlerObj->fHandler = handler; 6693 handlerObj->fHandlerArgs = args; 6694 6695 finish: 6696 return handlerObj; 6697 } 6698 6699 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 6700 6701 struct IOServiceStateNotificationDispatchSource_IVars { 6702 IOLock * fLock; 6703 IOService * fStateNotification; 6704 IOStateNotificationListenerRef fListener; 6705 OSAction * fAction; 6706 bool fEnable; 6707 bool fArmed; 6708 }; 6709 6710 kern_return_t 6711 IOServiceStateNotificationDispatchSource::Create_Impl(IOService * service, OSArray * items, 6712 IODispatchQueue * queue, IOServiceStateNotificationDispatchSource ** outSource) 6713 { 6714 kern_return_t kr; 6715 IOServiceStateNotificationDispatchSource * source; 6716 6717 source = OSTypeAlloc(IOServiceStateNotificationDispatchSource); 6718 source->init(); 6719 6720 source->ivars->fStateNotification = service; 6721 kr = service->stateNotificationListenerAdd(items, &source->ivars->fListener, ^kern_return_t () { 6722 OSAction * action; 6723 6724 action = NULL; 6725 IOLockLock(source->ivars->fLock); 6726 if (source->ivars->fArmed && source->ivars->fAction) { 6727 source->ivars->fArmed = false; 6728 action = source->ivars->fAction; 6729 action->retain(); 6730 } 6731 IOLockUnlock(source->ivars->fLock); 6732 if (action) { 6733 source->StateNotificationReady(action); 6734 OSSafeReleaseNULL(action); 6735 } 6736 return kIOReturnSuccess; 6737 }); 6738 6739 if (kIOReturnSuccess != kr) { 6740 OSSafeReleaseNULL(source); 6741 } 6742 *outSource = source; 6743 6744 return kr; 6745 } 6746 6747 6748 bool 6749 IOServiceStateNotificationDispatchSource::init() 6750 { 6751 if (!IODispatchSource::init()) { 6752 return false; 6753 } 6754 ivars = IOMallocType(IOServiceStateNotificationDispatchSource_IVars); 6755 if (!ivars) { 6756 return false; 6757 } 6758 ivars->fLock = IOLockAlloc(); 6759 if (!ivars->fLock) { 6760 return false; 6761 } 6762 ivars->fArmed = true; 6763 6764 return true; 6765 } 6766 6767 void 6768 IOServiceStateNotificationDispatchSource::free() 6769 { 6770 if (ivars) { 6771 if (ivars->fListener) { 6772 ivars->fStateNotification->stateNotificationListenerRemove(ivars->fListener); 6773 } 6774 if (ivars->fLock) { 6775 IOLockFree(ivars->fLock); 6776 } 6777 IOFreeType(ivars, IOServiceStateNotificationDispatchSource_IVars); 6778 } 6779 IODispatchSource::free(); 6780 } 6781 6782 kern_return_t 6783 IOServiceStateNotificationDispatchSource::SetHandler_Impl(OSAction * action) 6784 { 6785 IOReturn ret; 6786 bool notifyReady; 6787 6788 notifyReady = false; 6789 6790 IOLockLock(ivars->fLock); 6791 action->retain(); 6792 OSSafeReleaseNULL(ivars->fAction); 6793 ivars->fAction = action; 6794 if (action) { 6795 notifyReady = true; 6796 } 6797 IOLockUnlock(ivars->fLock); 6798 6799 if (notifyReady) { 6800 StateNotificationReady(action); 6801 } 6802 ret = kIOReturnSuccess; 6803 6804 return ret; 6805 } 6806 6807 kern_return_t 6808 IOServiceStateNotificationDispatchSource::SetEnableWithCompletion_Impl( 6809 bool enable, 6810 IODispatchSourceCancelHandler handler) 6811 { 6812 if (enable == ivars->fEnable) { 6813 return kIOReturnSuccess; 6814 } 6815 6816 IOLockLock(ivars->fLock); 6817 ivars->fEnable = enable; 6818 IOLockUnlock(ivars->fLock); 6819 6820 return kIOReturnSuccess; 6821 } 6822 6823 kern_return_t 6824 IOServiceStateNotificationDispatchSource::Cancel_Impl( 6825 IODispatchSourceCancelHandler handler) 6826 { 6827 return kIOReturnUnsupported; 6828 } 6829 6830 kern_return_t 6831 IOServiceStateNotificationDispatchSource::StateNotificationBegin_Impl(void) 6832 { 6833 IOLockLock(ivars->fLock); 6834 ivars->fArmed = true; 6835 IOLockUnlock(ivars->fLock); 6836 6837 return kIOReturnSuccess; 6838 } 6839 6840 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 6841 6842 #include <IOKit/IOServiceStateNotificationEventSource.h> 6843 6844 OSDefineMetaClassAndStructors(IOServiceStateNotificationEventSource, IOEventSource) 6845 OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 0); 6846 OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 1); 6847 OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 2); 6848 OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 3); 6849 OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 4); 6850 OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 5); 6851 OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 6); 6852 OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 7); 6853 6854 OSPtr<IOServiceStateNotificationEventSource> 6855 IOServiceStateNotificationEventSource::serviceStateNotificationEventSource(IOService *service, 6856 OSArray * items, 6857 ActionBlock inAction) 6858 { 6859 kern_return_t kr; 6860 IOServiceStateNotificationEventSource * source; 6861 6862 source = OSTypeAlloc(IOServiceStateNotificationEventSource); 6863 if (source && !source->init(service, NULL)) { 6864 OSSafeReleaseNULL(source); 6865 } 6866 6867 if (!source) { 6868 return nullptr; 6869 } 6870 6871 source->fStateNotification = service; 6872 kr = service->stateNotificationListenerAdd(items, &source->fListener, ^kern_return_t () { 6873 if (!source->workLoop) { 6874 return kIOReturnSuccess; 6875 } 6876 source->workLoop->runActionBlock(^IOReturn (void) { 6877 source->fArmed = true; 6878 return kIOReturnSuccess; 6879 }); 6880 source->signalWorkAvailable(); 6881 return kIOReturnSuccess; 6882 }); 6883 6884 if (kIOReturnSuccess != kr) { 6885 OSSafeReleaseNULL(source); 6886 } 6887 6888 if (source) { 6889 source->setActionBlock((IOEventSource::ActionBlock) inAction); 6890 } 6891 6892 return source; 6893 } 6894 6895 void 6896 IOServiceStateNotificationEventSource::free() 6897 { 6898 if (fListener) { 6899 fStateNotification->stateNotificationListenerRemove(fListener); 6900 } 6901 IOEventSource::free(); 6902 } 6903 6904 void 6905 IOServiceStateNotificationEventSource::enable() 6906 { 6907 fEnable = true; 6908 } 6909 6910 void 6911 IOServiceStateNotificationEventSource::disable() 6912 { 6913 fEnable = false; 6914 } 6915 6916 void 6917 IOServiceStateNotificationEventSource::setWorkLoop(IOWorkLoop *inWorkLoop) 6918 { 6919 IOEventSource::setWorkLoop(inWorkLoop); 6920 } 6921 6922 bool 6923 IOServiceStateNotificationEventSource::checkForWork() 6924 { 6925 ActionBlock intActionBlock = (ActionBlock) actionBlock; 6926 6927 if (fArmed) { 6928 fArmed = false; 6929 (intActionBlock)(); 6930 } 6931 6932 return false; 6933 } 6934 6935 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 6936 6937 OSDefineMetaClassAndStructors(IOSystemStateNotification, IOService); 6938 6939 class IOStateNotificationItem : public OSObject 6940 { 6941 OSDeclareDefaultStructors(IOStateNotificationItem); 6942 6943 public: 6944 virtual bool init() override; 6945 6946 OSDictionary * fSchema; 6947 OSDictionary * fValue; 6948 OSSet * fListeners; 6949 }; 6950 OSDefineMetaClassAndStructors(IOStateNotificationItem, OSObject); 6951 6952 6953 class IOStateNotificationListener : public OSObject 6954 { 6955 OSDeclareDefaultStructors(IOStateNotificationListener); 6956 6957 public: 6958 virtual bool init() override; 6959 virtual void free() override; 6960 6961 IOStateNotificationHandler fHandler; 6962 }; 6963 OSDefineMetaClassAndStructors(IOStateNotificationListener, OSObject); 6964 6965 6966 bool 6967 IOStateNotificationItem::init() 6968 { 6969 return OSObject::init(); 6970 } 6971 6972 bool 6973 IOStateNotificationListener::init() 6974 { 6975 return OSObject::init(); 6976 } 6977 6978 void 6979 IOStateNotificationListener::free() 6980 { 6981 if (fHandler) { 6982 Block_release(fHandler); 6983 } 6984 OSObject::free(); 6985 } 6986 6987 6988 struct IOServiceStateChangeVars { 6989 IOLock * fLock; 6990 OSDictionary * fItems; 6991 }; 6992 6993 IOService * 6994 IOSystemStateNotification::initialize(void) 6995 { 6996 IOSystemStateNotification * me; 6997 IOServiceStateChangeVars * vars; 6998 6999 me = OSTypeAlloc(IOSystemStateNotification); 7000 me->init(); 7001 vars = IOMallocType(IOServiceStateChangeVars); 7002 me->reserved->svars = vars; 7003 vars->fLock = IOLockAlloc(); 7004 vars->fItems = OSDictionary::withCapacity(16); 7005 { 7006 kern_return_t ret; 7007 7008 gIOSystemStateSleepDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateSleepDescriptionKey); 7009 gIOSystemStateSleepDescriptionHibernateStateKey = OSSymbol::withCStringNoCopy(kIOSystemStateSleepDescriptionHibernateStateKey); 7010 gIOSystemStateSleepDescriptionReasonKey = OSSymbol::withCStringNoCopy(kIOSystemStateSleepDescriptionReasonKey); 7011 7012 ret = me->StateNotificationItemCreate(gIOSystemStateSleepDescriptionKey, NULL); 7013 assert(kIOReturnSuccess == ret); 7014 7015 gIOSystemStateWakeDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionKey); 7016 gIOSystemStateWakeDescriptionWakeReasonKey = OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionWakeReasonKey); 7017 gIOSystemStateWakeDescriptionContinuousTimeOffsetKey = OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionContinuousTimeOffsetKey); 7018 7019 ret = me->StateNotificationItemCreate(gIOSystemStateWakeDescriptionKey, NULL); 7020 assert(kIOReturnSuccess == ret); 7021 7022 gIOSystemStateHaltDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateHaltDescriptionKey); 7023 gIOSystemStateHaltDescriptionHaltStateKey = OSSymbol::withCStringNoCopy(kIOSystemStateHaltDescriptionHaltStateKey); 7024 7025 ret = me->StateNotificationItemCreate(gIOSystemStateHaltDescriptionKey, NULL); 7026 assert(kIOReturnSuccess == ret); 7027 7028 gIOSystemStatePowerSourceDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStatePowerSourceDescriptionKey); 7029 gIOSystemStatePowerSourceDescriptionACAttachedKey = OSSymbol::withCStringNoCopy(kIOSystemStatePowerSourceDescriptionACAttachedKey); 7030 7031 ret = me->StateNotificationItemCreate(gIOSystemStatePowerSourceDescriptionKey, NULL); 7032 assert(kIOReturnSuccess == ret); 7033 } 7034 7035 return me; 7036 } 7037 7038 bool 7039 IOSystemStateNotification::serializeProperties(OSSerialize * s) const 7040 { 7041 IOServiceStateChangeVars * ivars = reserved->svars; 7042 7043 bool ok; 7044 OSDictionary * result; 7045 7046 result = OSDictionary::withCapacity(16); 7047 7048 IOLockLock(ivars->fLock); 7049 ivars->fItems->iterateObjects(^bool (const OSSymbol * key, OSObject * object) { 7050 IOStateNotificationItem * item; 7051 7052 item = (typeof(item))object; 7053 if (!item->fValue) { 7054 return false; 7055 } 7056 result->setObject(key, item->fValue); 7057 return false; 7058 }); 7059 IOLockUnlock(ivars->fLock); 7060 7061 ok = result->serialize(s); 7062 OSSafeReleaseNULL(result); 7063 7064 return ok; 7065 } 7066 7067 kern_return_t 7068 IOSystemStateNotification::setProperties(OSObject * properties) 7069 { 7070 kern_return_t kr; 7071 OSDictionary * dict; 7072 OSDictionary * schema; 7073 OSDictionary * value; 7074 OSString * itemName; 7075 7076 dict = OSDynamicCast(OSDictionary, properties); 7077 if (!dict) { 7078 return kIOReturnBadArgument; 7079 } 7080 7081 if (!IOCurrentTaskHasEntitlement(kIOSystemStateEntitlement)) { 7082 return kIOReturnNotPermitted; 7083 } 7084 7085 if ((schema = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemCreateKey)))) { 7086 itemName = OSDynamicCast(OSString, schema->getObject(kIOStateNotificationNameKey)); 7087 kr = StateNotificationItemCreate(itemName, schema); 7088 } else if ((value = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemSetKey)))) { 7089 itemName = OSDynamicCast(OSString, value->getObject(kIOStateNotificationNameKey)); 7090 itemName->retain(); 7091 value->removeObject(kIOStateNotificationNameKey); 7092 kr = StateNotificationItemSet(itemName, value); 7093 itemName->release(); 7094 } else { 7095 kr = kIOReturnError; 7096 } 7097 7098 return kr; 7099 } 7100 7101 kern_return_t 7102 IOService::CopySystemStateNotificationService_Impl(IOService ** outService) 7103 { 7104 IOService * service; 7105 7106 service = getSystemStateNotificationService(); 7107 service->retain(); 7108 *outService = service; 7109 7110 return kIOReturnSuccess; 7111 } 7112 7113 IOStateNotificationItem * 7114 IOService::stateNotificationItemCopy(OSString * itemName, OSDictionary * schema) 7115 { 7116 IOServiceStateChangeVars * ivars = reserved->svars; 7117 7118 const OSSymbol * name; 7119 IOStateNotificationItem * item; 7120 7121 name = OSSymbol::withString(itemName); 7122 7123 IOLockLock(ivars->fLock); 7124 if ((item = (typeof(item))ivars->fItems->getObject(name))) { 7125 item->retain(); 7126 } else { 7127 item = OSTypeAlloc(IOStateNotificationItem); 7128 item->init(); 7129 item->fListeners = OSSet::withCapacity(16); 7130 7131 if (schema) { 7132 schema->retain(); 7133 } else { 7134 schema = OSDictionary::withCapacity(8); 7135 } 7136 schema->setObject(kIOStateNotificationNameKey, name); 7137 item->fSchema = schema; 7138 ivars->fItems->setObject(name, item); 7139 } 7140 IOLockUnlock(ivars->fLock); 7141 7142 OSSafeReleaseNULL(name); 7143 7144 return item; 7145 } 7146 7147 kern_return_t 7148 IOService::StateNotificationItemCreate_Impl(OSString * itemName, OSDictionary * schema) 7149 { 7150 IOStateNotificationItem * item; 7151 7152 item = stateNotificationItemCopy(itemName, schema); 7153 if (!item) { 7154 return kIOReturnNoMemory; 7155 } 7156 item->release(); 7157 7158 return kIOReturnSuccess; 7159 } 7160 7161 kern_return_t 7162 IOService::StateNotificationItemSet_Impl(OSString * itemName, OSDictionary * value) 7163 { 7164 IOServiceStateChangeVars * ivars = reserved->svars; 7165 7166 OSSet * listeners; 7167 IOStateNotificationItem * item; 7168 7169 value->retain(); 7170 IOLockLock(ivars->fLock); 7171 item = (typeof(item))ivars->fItems->getObject(itemName); 7172 OSSafeReleaseNULL(item->fValue); 7173 item->fValue = value; 7174 listeners = NULL; 7175 if (item->fListeners->getCount()) { 7176 listeners = OSSet::withSet(item->fListeners); 7177 } 7178 IOLockUnlock(ivars->fLock); 7179 7180 if (listeners) { 7181 listeners->iterateObjects(^bool (OSObject * object) { 7182 IOStateNotificationListener * listener; 7183 7184 listener = (typeof(listener))object; 7185 listener->fHandler(); 7186 return false; 7187 }); 7188 OSSafeReleaseNULL(listeners); 7189 } 7190 7191 return kIOReturnSuccess; 7192 } 7193 7194 kern_return_t 7195 IOService::StateNotificationItemCopy_Impl(OSString * itemName, OSDictionary ** outValue) 7196 { 7197 IOServiceStateChangeVars * ivars = reserved->svars; 7198 7199 kern_return_t ret; 7200 IOStateNotificationItem * item; 7201 OSDictionary * value; 7202 7203 IOLockLock(ivars->fLock); 7204 item = (typeof(item))ivars->fItems->getObject(itemName); 7205 if (item) { 7206 value = item->fValue; 7207 } else { 7208 value = NULL; 7209 } 7210 if (!value) { 7211 ret = kIOReturnNotFound; 7212 } else { 7213 value->retain(); 7214 ret = kIOReturnSuccess; 7215 } 7216 IOLockUnlock(ivars->fLock); 7217 7218 *outValue = value; 7219 7220 return ret; 7221 } 7222 7223 kern_return_t 7224 IOService::stateNotificationListenerAdd(OSArray * items, 7225 IOStateNotificationListenerRef * outRef, 7226 IOStateNotificationHandler handler) 7227 { 7228 IOServiceStateChangeVars * ivars = reserved->svars; 7229 7230 kern_return_t kr __block; 7231 IOStateNotificationListener * listener; 7232 7233 listener = OSTypeAlloc(IOStateNotificationListener); 7234 listener->init(); 7235 listener->fHandler = Block_copy(handler); 7236 7237 kr = kIOReturnSuccess; 7238 items->iterateObjects(^bool (OSObject * object) { 7239 OSString * itemName; 7240 IOStateNotificationItem * item; 7241 7242 itemName = OSDynamicCast(OSString, object); 7243 if (!itemName) { 7244 kr = kIOReturnBadArgument; 7245 return true; 7246 } 7247 item = stateNotificationItemCopy(itemName, NULL); 7248 if (!item) { 7249 kr = kIOReturnNoMemory; 7250 return true; 7251 } 7252 IOLockLock(ivars->fLock); 7253 item->fListeners->setObject(listener); 7254 IOLockUnlock(ivars->fLock); 7255 item->release(); 7256 return false; 7257 }); 7258 7259 if (kIOReturnSuccess != kr) { 7260 stateNotificationListenerRemove(listener); 7261 OSSafeReleaseNULL(listener); 7262 } 7263 *outRef = listener; 7264 7265 return kr; 7266 } 7267 7268 7269 kern_return_t 7270 IOService::stateNotificationListenerRemove(IOStateNotificationListenerRef ref) 7271 { 7272 IOServiceStateChangeVars * ivars = reserved->svars; 7273 7274 IOStateNotificationListener * listener; 7275 kern_return_t kr; 7276 7277 kr = kIOReturnSuccess; 7278 listener = (typeof(listener))ref; 7279 7280 IOLockLock(ivars->fLock); 7281 ivars->fItems->iterateObjects(^bool (const OSSymbol * key, OSObject * object) { 7282 IOStateNotificationItem * item; 7283 7284 item = (typeof(item))object; 7285 item->fListeners->removeObject(listener); 7286 return false; 7287 }); 7288 IOLockUnlock(ivars->fLock); 7289 7290 return kr; 7291 } 7292 7293 7294 7295 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 7296 7297 kern_return_t 7298 IOWorkGroup::Create_Impl(OSString * name, IOUserClient * userClient, IOWorkGroup ** workgroup) 7299 { 7300 IOWorkGroup * inst = NULL; 7301 IOUserUserClient * uc = NULL; 7302 kern_return_t ret = kIOReturnError; 7303 IOUserServer * us; 7304 7305 if (name == NULL) { 7306 ret = kIOReturnBadArgument; 7307 goto finish; 7308 } 7309 7310 if (name->getLength() > kIOWorkGroupMaxNameLength) { 7311 ret = kIOReturnBadArgument; 7312 goto finish; 7313 } 7314 7315 uc = OSDynamicCast(IOUserUserClient, userClient); 7316 if (uc == NULL) { 7317 ret = kIOReturnBadArgument; 7318 goto finish; 7319 } 7320 7321 inst = OSTypeAlloc(IOWorkGroup); 7322 if (!inst->init()) { 7323 inst->free(); 7324 inst = NULL; 7325 ret = kIOReturnNoMemory; 7326 goto finish; 7327 } 7328 7329 us = (typeof(us))thread_iokit_tls_get(0); 7330 inst->ivars->userServer = OSDynamicCast(IOUserServer, us); 7331 7332 if (inst->ivars->userServer == NULL) { 7333 ret = kIOReturnBadArgument; 7334 goto finish; 7335 } 7336 inst->ivars->userServer->retain(); 7337 7338 inst->ivars->name = name; 7339 inst->ivars->name->retain(); 7340 7341 inst->ivars->userClient = uc; // no retain 7342 7343 IOLockLock(uc->fLock); 7344 uc->fWorkGroups->setObject(name, inst); 7345 IOLockUnlock(uc->fLock); 7346 ret = kIOReturnSuccess; 7347 7348 finish: 7349 if (ret != kIOReturnSuccess) { 7350 OSSafeReleaseNULL(inst); 7351 } else { 7352 *workgroup = inst; 7353 } 7354 7355 return ret; 7356 } 7357 7358 kern_return_t 7359 IOWorkGroup::InvalidateKernel_Impl(IOUserClient * client) 7360 { 7361 IOUserUserClient * uc = OSDynamicCast(IOUserUserClient, client); 7362 7363 if (uc == NULL) { 7364 return kIOReturnBadArgument; 7365 } 7366 7367 if (uc != ivars->userClient) { 7368 return kIOReturnBadArgument; 7369 } 7370 7371 IOLockLock(uc->fLock); 7372 uc->fWorkGroups->removeObject(ivars->name); 7373 IOLockUnlock(uc->fLock); 7374 7375 return kIOReturnSuccess; 7376 } 7377 7378 kern_return_t 7379 IOWorkGroup::SetWorkGroupPort_Impl(mach_port_t port) 7380 { 7381 return kIOReturnUnsupported; 7382 } 7383 7384 bool 7385 IOWorkGroup::init() 7386 { 7387 if (!OSObject::init()) { 7388 return false; 7389 } 7390 ivars = IOMallocType(IOWorkGroup_IVars); 7391 7392 return true; 7393 } 7394 7395 void 7396 IOWorkGroup::free() 7397 { 7398 if (ivars) { 7399 OSSafeReleaseNULL(ivars->userServer); 7400 OSSafeReleaseNULL(ivars->name); 7401 IOFreeType(ivars, IOWorkGroup_IVars); 7402 } 7403 7404 OSObject::free(); 7405 } 7406 7407 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 7408 7409 kern_return_t 7410 IOEventLink::Create_Impl(OSString * name, IOUserClient * userClient, IOEventLink ** eventlink) 7411 { 7412 IOEventLink * inst = NULL; 7413 IOUserUserClient * uc = NULL; 7414 IOUserServer * us; 7415 kern_return_t ret = kIOReturnError; 7416 7417 if (name == NULL) { 7418 ret = kIOReturnBadArgument; 7419 goto finish; 7420 } 7421 7422 if (name->getLength() > kIOEventLinkMaxNameLength) { 7423 ret = kIOReturnBadArgument; 7424 goto finish; 7425 } 7426 7427 uc = OSDynamicCast(IOUserUserClient, userClient); 7428 if (uc == NULL) { 7429 ret = kIOReturnBadArgument; 7430 goto finish; 7431 } 7432 7433 inst = OSTypeAlloc(IOEventLink); 7434 if (!inst->init()) { 7435 inst->free(); 7436 inst = NULL; 7437 ret = kIOReturnNoMemory; 7438 goto finish; 7439 } 7440 7441 us = (typeof(us))thread_iokit_tls_get(0); 7442 inst->ivars->userServer = OSDynamicCast(IOUserServer, us); 7443 7444 if (inst->ivars->userServer == NULL) { 7445 ret = kIOReturnBadArgument; 7446 goto finish; 7447 } 7448 inst->ivars->userServer->retain(); 7449 7450 inst->ivars->name = name; 7451 inst->ivars->name->retain(); 7452 7453 inst->ivars->userClient = uc; // no retain 7454 7455 IOLockLock(uc->fLock); 7456 uc->fEventLinks->setObject(name, inst); 7457 IOLockUnlock(uc->fLock); 7458 7459 ret = kIOReturnSuccess; 7460 7461 finish: 7462 if (ret != kIOReturnSuccess) { 7463 OSSafeReleaseNULL(inst); 7464 } else { 7465 *eventlink = inst; 7466 } 7467 7468 return ret; 7469 } 7470 7471 kern_return_t 7472 IOEventLink::InvalidateKernel_Impl(IOUserClient * client) 7473 { 7474 IOUserUserClient * uc = OSDynamicCast(IOUserUserClient, client); 7475 7476 if (uc == NULL) { 7477 return kIOReturnBadArgument; 7478 } 7479 7480 if (uc != ivars->userClient) { 7481 return kIOReturnBadArgument; 7482 } 7483 7484 IOLockLock(uc->fLock); 7485 uc->fEventLinks->removeObject(ivars->name); 7486 IOLockUnlock(uc->fLock); 7487 7488 return kIOReturnSuccess; 7489 } 7490 7491 bool 7492 IOEventLink::init() 7493 { 7494 if (!OSObject::init()) { 7495 return false; 7496 } 7497 ivars = IOMallocType(IOEventLink_IVars); 7498 7499 return true; 7500 } 7501 7502 void 7503 IOEventLink::free() 7504 { 7505 if (ivars) { 7506 OSSafeReleaseNULL(ivars->userServer); 7507 OSSafeReleaseNULL(ivars->name); 7508 IOFreeType(ivars, IOEventLink_IVars); 7509 } 7510 7511 OSObject::free(); 7512 } 7513 7514 kern_return_t 7515 IOEventLink::SetEventlinkPort_Impl(mach_port_t port __unused) 7516 { 7517 return kIOReturnUnsupported; 7518 } 7519