1 /* 2 * Copyright (c) 1998-2014 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/IOUserClient.h> 33 #include <IOKit/IOService.h> 34 #include <IOKit/IORegistryEntry.h> 35 #include <IOKit/IOCatalogue.h> 36 #include <IOKit/IOMemoryDescriptor.h> 37 #include <IOKit/IOBufferMemoryDescriptor.h> 38 #include <IOKit/IOSubMemoryDescriptor.h> 39 #include <IOKit/IOMultiMemoryDescriptor.h> 40 #include <IOKit/IOMapper.h> 41 #include <IOKit/IOLib.h> 42 #include <IOKit/IOBSD.h> 43 #include <IOKit/system.h> 44 #include <IOKit/IOUserServer.h> 45 #include <IOKit/IOInterruptEventSource.h> 46 #include <IOKit/IOTimerEventSource.h> 47 #include <IOKit/pwr_mgt/RootDomain.h> 48 #include <libkern/c++/OSKext.h> 49 #include <libkern/c++/OSSharedPtr.h> 50 #include <libkern/OSDebug.h> 51 #include <libkern/Block.h> 52 #include <sys/proc.h> 53 #include "IOKitKernelInternal.h" 54 55 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 56 57 #include <DriverKit/IODispatchQueue.h> 58 #include <DriverKit/OSObject.h> 59 #include <DriverKit/OSAction.h> 60 #include <DriverKit/IODispatchSource.h> 61 #include <DriverKit/IOInterruptDispatchSource.h> 62 #include <DriverKit/IOService.h> 63 #include <DriverKit/IOMemoryDescriptor.h> 64 #include <DriverKit/IOBufferMemoryDescriptor.h> 65 #include <DriverKit/IOMemoryMap.h> 66 #include <DriverKit/IODataQueueDispatchSource.h> 67 #include <DriverKit/IOServiceNotificationDispatchSource.h> 68 #include <DriverKit/IOUserServer.h> 69 70 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 71 72 #include <System/IODataQueueDispatchSourceShared.h> 73 74 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 75 76 SECURITY_READ_ONLY_LATE(SInt64) gIODKDebug = kIODKEnable; 77 78 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 79 80 struct IOPStrings; 81 82 class OSUserMetaClass : public OSObject 83 { 84 OSDeclareDefaultStructors(OSUserMetaClass); 85 public: 86 const OSSymbol * name; 87 const OSMetaClass * meta; 88 OSUserMetaClass * superMeta; 89 90 queue_chain_t link; 91 92 OSClassDescription * description; 93 IOPStrings * queueNames; 94 uint32_t methodCount; 95 uint64_t * methods; 96 97 virtual void free() override; 98 virtual kern_return_t Dispatch(const IORPC rpc) APPLE_KEXT_OVERRIDE; 99 }; 100 OSDefineMetaClassAndStructors(OSUserMetaClass, OSObject); 101 102 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 103 104 class IOUserService : public IOService 105 { 106 friend class IOService; 107 108 OSDeclareDefaultStructors(IOUserService) 109 110 virtual bool 111 start(IOService * provider) APPLE_KEXT_OVERRIDE; 112 }; 113 114 OSDefineMetaClassAndStructors(IOUserService, IOService) 115 116 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 117 118 class IOUserUserClient : public IOUserClient 119 { 120 OSDeclareDefaultStructors(IOUserUserClient); 121 public: 122 task_t fTask; 123 124 IOReturn setTask(task_t task); 125 virtual void stop(IOService * provider) APPLE_KEXT_OVERRIDE; 126 virtual IOReturn clientClose(void) APPLE_KEXT_OVERRIDE; 127 virtual IOReturn setProperties(OSObject * properties) APPLE_KEXT_OVERRIDE; 128 virtual IOReturn externalMethod(uint32_t selector, IOExternalMethodArguments * args, 129 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) APPLE_KEXT_OVERRIDE; 130 virtual IOReturn clientMemoryForType(UInt32 type, 131 IOOptionBits * options, 132 IOMemoryDescriptor ** memory) APPLE_KEXT_OVERRIDE; 133 }; 134 135 OSDefineMetaClassAndStructors(IOUserServerCheckInToken, OSObject); 136 137 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 138 139 140 bool 141 IOUserService::start(IOService * provider) 142 { 143 bool ok = true; 144 IOReturn ret; 145 146 ret = Start(provider); 147 if (kIOReturnSuccess != ret) { 148 return false; 149 } 150 151 return ok; 152 } 153 154 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 155 156 #undef super 157 158 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 159 160 struct IODispatchQueue_IVars { 161 IOUserServer * userServer; 162 IODispatchQueue * queue; 163 queue_chain_t link; 164 uint64_t tid; 165 166 mach_port_t serverPort; 167 }; 168 169 struct OSAction_IVars { 170 OSObject * target; 171 uint64_t targetmsgid; 172 uint64_t msgid; 173 OSActionAbortedHandler abortedHandler; 174 size_t referenceSize; 175 OSString * typeName; 176 void * reference[0]; 177 }; 178 179 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 180 181 kern_return_t 182 IOService::GetRegistryEntryID_Impl( 183 uint64_t * registryEntryID) 184 { 185 IOReturn ret = kIOReturnSuccess; 186 187 *registryEntryID = getRegistryEntryID(); 188 189 return ret; 190 } 191 192 kern_return_t 193 IOService::SetName_Impl( 194 const char * name) 195 { 196 IOReturn ret = kIOReturnSuccess; 197 198 setName(name); 199 200 return ret; 201 } 202 203 kern_return_t 204 IOService::Start_Impl( 205 IOService * provider) 206 { 207 IOReturn ret = kIOReturnSuccess; 208 return ret; 209 } 210 211 kern_return_t 212 IOService::RegisterService_Impl() 213 { 214 IOReturn ret = kIOReturnSuccess; 215 216 registerService(); 217 218 return ret; 219 } 220 221 kern_return_t 222 IOService::CopyDispatchQueue_Impl( 223 const char * name, 224 IODispatchQueue ** queue) 225 { 226 IODispatchQueue * result; 227 IOService * service; 228 IOReturn ret; 229 uint32_t index; 230 231 if (!reserved->uvars) { 232 return kIOReturnError; 233 } 234 235 ret = kIOReturnNotFound; 236 index = -1U; 237 if (!strcmp("Default", name)) { 238 index = 0; 239 } else if (reserved->uvars->userMeta 240 && reserved->uvars->userMeta->queueNames) { 241 index = reserved->uvars->userServer->stringArrayIndex(reserved->uvars->userMeta->queueNames, name); 242 if (index != -1U) { 243 index++; 244 } 245 } 246 if (index == -1U) { 247 if ((service = getProvider())) { 248 ret = service->CopyDispatchQueue(name, queue); 249 } 250 } else { 251 result = reserved->uvars->queueArray[index]; 252 if (result) { 253 result->retain(); 254 *queue = result; 255 ret = kIOReturnSuccess; 256 } 257 } 258 259 return ret; 260 } 261 262 kern_return_t 263 IOService::SetDispatchQueue_Impl( 264 const char * name, 265 IODispatchQueue * queue) 266 { 267 IOReturn ret = kIOReturnSuccess; 268 uint32_t index; 269 270 if (!reserved->uvars) { 271 return kIOReturnError; 272 } 273 274 if (kIODKLogSetup & gIODKDebug) { 275 DKLOG(DKS "::SetDispatchQueue(%s)\n", DKN(this), name); 276 } 277 queue->ivars->userServer = reserved->uvars->userServer; 278 index = -1U; 279 if (!strcmp("Default", name)) { 280 index = 0; 281 } else if (reserved->uvars->userMeta 282 && reserved->uvars->userMeta->queueNames) { 283 index = reserved->uvars->userServer->stringArrayIndex(reserved->uvars->userMeta->queueNames, name); 284 if (index != -1U) { 285 index++; 286 } 287 } 288 if (index == -1U) { 289 ret = kIOReturnBadArgument; 290 } else { 291 reserved->uvars->queueArray[index] = queue; 292 queue->retain(); 293 } 294 295 return ret; 296 } 297 298 kern_return_t 299 IOService::SetProperties_Impl( 300 OSDictionary * properties) 301 { 302 IOUserServer * us; 303 OSDictionary * dict; 304 IOReturn ret; 305 306 ret = setProperties(properties); 307 308 if (kIOReturnUnsupported == ret) { 309 dict = OSDynamicCast(OSDictionary, properties); 310 us = (typeof(us))thread_iokit_tls_get(0); 311 if (dict && reserved->uvars && (reserved->uvars->userServer == us)) { 312 ret = runPropertyActionBlock(^IOReturn (void) { 313 OSDictionary * userProps; 314 IOReturn ret; 315 316 userProps = OSDynamicCast(OSDictionary, getProperty(gIOUserServicePropertiesKey)); 317 if (userProps) { 318 userProps = (typeof(userProps))userProps->copyCollection(); 319 } else { 320 userProps = OSDictionary::withCapacity(4); 321 } 322 if (!userProps) { 323 ret = kIOReturnNoMemory; 324 } else { 325 bool ok = userProps->merge(dict); 326 if (ok) { 327 ok = setProperty(gIOUserServicePropertiesKey, userProps); 328 } 329 OSSafeReleaseNULL(userProps); 330 ret = ok ? kIOReturnSuccess : kIOReturnNotWritable; 331 } 332 return ret; 333 }); 334 } 335 } 336 337 return ret; 338 } 339 340 kern_return_t 341 IOService::CopyProperties_Impl( 342 OSDictionary ** properties) 343 { 344 IOReturn ret = kIOReturnSuccess; 345 *properties = dictionaryWithProperties(); 346 return ret; 347 } 348 349 kern_return_t 350 IOService::RequireMaxBusStall_Impl( 351 uint64_t u64ns) 352 { 353 IOReturn ret; 354 UInt32 ns; 355 356 if (os_convert_overflow(u64ns, &ns)) { 357 return kIOReturnBadArgument; 358 } 359 ret = requireMaxBusStall(ns); 360 361 return kIOReturnSuccess; 362 } 363 364 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 365 366 kern_return_t 367 IOMemoryDescriptor::_CopyState_Impl( 368 _IOMDPrivateState * state) 369 { 370 IOReturn ret; 371 372 state->length = _length; 373 state->options = _flags; 374 375 ret = kIOReturnSuccess; 376 377 return ret; 378 } 379 380 kern_return_t 381 IOMemoryDescriptor::GetLength(uint64_t * returnLength) 382 { 383 *returnLength = getLength(); 384 385 return kIOReturnSuccess; 386 } 387 388 kern_return_t 389 IOMemoryDescriptor::CreateMapping_Impl( 390 uint64_t options, 391 uint64_t address, 392 uint64_t offset, 393 uint64_t length, 394 uint64_t alignment, 395 IOMemoryMap ** map) 396 { 397 IOReturn ret; 398 IOMemoryMap * resultMap; 399 IOOptionBits koptions; 400 mach_vm_address_t atAddress; 401 402 ret = kIOReturnSuccess; 403 koptions = 0; 404 resultMap = NULL; 405 406 if (kIOMemoryMapFixedAddress & options) { 407 atAddress = address; 408 koptions = 0; 409 } else { 410 atAddress = 0; 411 koptions |= kIOMapAnywhere; 412 } 413 414 if (kIOMemoryMapReadOnly & options || (kIODirectionOut == getDirection())) { 415 if (!reserved || (current_task() != reserved->creator)) { 416 koptions |= kIOMapReadOnly; 417 } 418 } 419 420 switch (0xFF00 & options) { 421 case kIOMemoryMapCacheModeDefault: 422 koptions |= kIOMapDefaultCache; 423 break; 424 case kIOMemoryMapCacheModeInhibit: 425 koptions |= kIOMapInhibitCache; 426 break; 427 case kIOMemoryMapCacheModeCopyback: 428 koptions |= kIOMapCopybackCache; 429 break; 430 case kIOMemoryMapCacheModeWriteThrough: 431 koptions |= kIOMapWriteThruCache; 432 break; 433 default: 434 ret = kIOReturnBadArgument; 435 } 436 437 if (kIOReturnSuccess == ret) { 438 resultMap = createMappingInTask(current_task(), atAddress, koptions, offset, length); 439 if (!resultMap) { 440 ret = kIOReturnError; 441 } 442 } 443 444 *map = resultMap; 445 446 return ret; 447 } 448 449 kern_return_t 450 IOMemoryDescriptor::CreateSubMemoryDescriptor_Impl( 451 uint64_t memoryDescriptorCreateOptions, 452 uint64_t offset, 453 uint64_t length, 454 IOMemoryDescriptor * ofDescriptor, 455 IOMemoryDescriptor ** memory) 456 { 457 IOReturn ret; 458 IOMemoryDescriptor * iomd; 459 IOByteCount mdOffset; 460 IOByteCount mdLength; 461 IOByteCount mdEnd; 462 463 if (!ofDescriptor) { 464 return kIOReturnBadArgument; 465 } 466 if (memoryDescriptorCreateOptions & ~kIOMemoryDirectionOutIn) { 467 return kIOReturnBadArgument; 468 } 469 if (os_convert_overflow(offset, &mdOffset)) { 470 return kIOReturnBadArgument; 471 } 472 if (os_convert_overflow(length, &mdLength)) { 473 return kIOReturnBadArgument; 474 } 475 if (os_add_overflow(mdOffset, mdLength, &mdEnd)) { 476 return kIOReturnBadArgument; 477 } 478 if (mdEnd > ofDescriptor->getLength()) { 479 return kIOReturnBadArgument; 480 } 481 482 iomd = IOSubMemoryDescriptor::withSubRange( 483 ofDescriptor, mdOffset, mdLength, (IOOptionBits) memoryDescriptorCreateOptions); 484 485 if (iomd) { 486 ret = kIOReturnSuccess; 487 *memory = iomd; 488 } else { 489 ret = kIOReturnNoMemory; 490 *memory = NULL; 491 } 492 493 return ret; 494 } 495 496 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 497 498 kern_return_t 499 IOMemoryDescriptor::CreateWithMemoryDescriptors_Impl( 500 uint64_t memoryDescriptorCreateOptions, 501 uint32_t withDescriptorsCount, 502 IOMemoryDescriptor ** const withDescriptors, 503 IOMemoryDescriptor ** memory) 504 { 505 IOReturn ret; 506 IOMemoryDescriptor * iomd; 507 508 if (!withDescriptors) { 509 return kIOReturnBadArgument; 510 } 511 if (!withDescriptorsCount) { 512 return kIOReturnBadArgument; 513 } 514 if (memoryDescriptorCreateOptions & ~kIOMemoryDirectionOutIn) { 515 return kIOReturnBadArgument; 516 } 517 518 for (unsigned int idx = 0; idx < withDescriptorsCount; idx++) { 519 if (NULL == withDescriptors[idx]) { 520 return kIOReturnBadArgument; 521 } 522 } 523 524 iomd = IOMultiMemoryDescriptor::withDescriptors(withDescriptors, withDescriptorsCount, 525 (IODirection) memoryDescriptorCreateOptions, false); 526 527 if (iomd) { 528 ret = kIOReturnSuccess; 529 *memory = iomd; 530 } else { 531 ret = kIOReturnNoMemory; 532 *memory = NULL; 533 } 534 535 return ret; 536 } 537 538 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 539 540 kern_return_t 541 IOUserClient::CreateMemoryDescriptorFromClient_Impl( 542 uint64_t memoryDescriptorCreateOptions, 543 uint32_t segmentsCount, 544 const IOAddressSegment segments[32], 545 IOMemoryDescriptor ** memory) 546 { 547 IOReturn ret; 548 IOMemoryDescriptor * iomd; 549 IOOptionBits mdOptions; 550 IOUserUserClient * me; 551 IOAddressRange * ranges; 552 553 me = OSDynamicCast(IOUserUserClient, this); 554 if (!me) { 555 return kIOReturnBadArgument; 556 } 557 558 mdOptions = 0; 559 if (kIOMemoryDirectionOut & memoryDescriptorCreateOptions) { 560 mdOptions |= kIODirectionOut; 561 } 562 if (kIOMemoryDirectionIn & memoryDescriptorCreateOptions) { 563 mdOptions |= kIODirectionIn; 564 } 565 if (!(kIOMemoryDisableCopyOnWrite & memoryDescriptorCreateOptions)) { 566 mdOptions |= kIOMemoryMapCopyOnWrite; 567 } 568 569 static_assert(sizeof(IOAddressRange) == sizeof(IOAddressSegment)); 570 ranges = __DECONST(IOAddressRange *, &segments[0]); 571 572 iomd = IOMemoryDescriptor::withAddressRanges( 573 ranges, segmentsCount, 574 mdOptions, me->fTask); 575 576 if (iomd) { 577 ret = kIOReturnSuccess; 578 *memory = iomd; 579 } else { 580 ret = kIOReturnNoMemory; 581 *memory = NULL; 582 } 583 584 return ret; 585 } 586 587 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 588 589 kern_return_t 590 IOMemoryMap::_CopyState_Impl( 591 _IOMemoryMapPrivateState * state) 592 { 593 IOReturn ret; 594 595 state->offset = fOffset; 596 state->length = getLength(); 597 state->address = getAddress(); 598 state->options = getMapOptions(); 599 600 ret = kIOReturnSuccess; 601 602 return ret; 603 } 604 605 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 606 607 kern_return_t 608 IOBufferMemoryDescriptor::Create_Impl( 609 uint64_t options, 610 uint64_t capacity, 611 uint64_t alignment, 612 IOBufferMemoryDescriptor ** memory) 613 { 614 IOReturn ret; 615 IOOptionBits bmdOptions; 616 IOBufferMemoryDescriptor * bmd; 617 IOMemoryDescriptorReserved * reserved; 618 619 if (options & ~((uint64_t) kIOMemoryDirectionOutIn)) { 620 // no other options currently defined 621 return kIOReturnBadArgument; 622 } 623 bmdOptions = (options & kIOMemoryDirectionOutIn) | kIOMemoryKernelUserShared; 624 bmd = IOBufferMemoryDescriptor::inTaskWithOptions( 625 kernel_task, bmdOptions, capacity, alignment); 626 627 *memory = bmd; 628 629 if (!bmd) { 630 return kIOReturnNoMemory; 631 } 632 633 reserved = bmd->getKernelReserved(); 634 reserved->creator = current_task(); 635 task_reference(reserved->creator); 636 637 ret = kIOReturnSuccess; 638 639 return ret; 640 } 641 642 kern_return_t 643 IOBufferMemoryDescriptor::SetLength_Impl( 644 uint64_t length) 645 { 646 setLength(length); 647 return kIOReturnSuccess; 648 } 649 650 651 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 652 653 kern_return_t 654 IODMACommand::Create_Impl( 655 IOService * device, 656 uint64_t options, 657 const IODMACommandSpecification * specification, 658 IODMACommand ** command) 659 { 660 IOReturn ret; 661 IODMACommand * dma; 662 IODMACommand::SegmentOptions segmentOptions; 663 IOMapper * mapper; 664 665 if (options & ~((uint64_t) kIODMACommandCreateNoOptions)) { 666 // no other options currently defined 667 return kIOReturnBadArgument; 668 } 669 670 if (os_convert_overflow(specification->maxAddressBits, &segmentOptions.fNumAddressBits)) { 671 return kIOReturnBadArgument; 672 } 673 segmentOptions.fMaxSegmentSize = 0; 674 segmentOptions.fMaxTransferSize = 0; 675 segmentOptions.fAlignment = 1; 676 segmentOptions.fAlignmentLength = 1; 677 segmentOptions.fAlignmentInternalSegments = 1; 678 segmentOptions.fStructSize = sizeof(segmentOptions); 679 680 mapper = IOMapper::copyMapperForDevice(device); 681 682 dma = IODMACommand::withSpecification( 683 kIODMACommandOutputHost64, 684 &segmentOptions, 685 kIODMAMapOptionMapped, 686 mapper, 687 NULL); 688 689 OSSafeReleaseNULL(mapper); 690 *command = dma; 691 692 if (!dma) { 693 return kIOReturnNoMemory; 694 } 695 ret = kIOReturnSuccess; 696 697 return ret; 698 } 699 700 kern_return_t 701 IODMACommand::PrepareForDMA_Impl( 702 uint64_t options, 703 IOMemoryDescriptor * memory, 704 uint64_t offset, 705 uint64_t length, 706 uint64_t * flags, 707 uint32_t * segmentsCount, 708 IOAddressSegment * segments) 709 { 710 IOReturn ret; 711 uint64_t lflags, mdFlags; 712 UInt32 numSegments; 713 UInt64 genOffset; 714 715 if (options & ~((uint64_t) kIODMACommandPrepareForDMANoOptions)) { 716 // no other options currently defined 717 return kIOReturnBadArgument; 718 } 719 720 // uses IOMD direction 721 ret = memory->prepare(); 722 if (kIOReturnSuccess != ret) { 723 return ret; 724 } 725 726 ret = setMemoryDescriptor(memory, false); 727 if (kIOReturnSuccess != ret) { 728 memory->complete(); 729 return ret; 730 } 731 732 ret = prepare(offset, length); 733 if (kIOReturnSuccess != ret) { 734 clearMemoryDescriptor(false); 735 memory->complete(); 736 return ret; 737 } 738 739 static_assert(sizeof(IODMACommand::Segment64) == sizeof(IOAddressSegment)); 740 741 numSegments = *segmentsCount; 742 genOffset = offset; 743 ret = genIOVMSegments(&genOffset, segments, &numSegments); 744 745 if (kIOReturnSuccess == ret) { 746 mdFlags = fMemory->getFlags(); 747 lflags = 0; 748 if (kIODirectionOut & mdFlags) { 749 lflags |= kIOMemoryDirectionOut; 750 } 751 if (kIODirectionIn & mdFlags) { 752 lflags |= kIOMemoryDirectionIn; 753 } 754 *flags = lflags; 755 *segmentsCount = numSegments; 756 } 757 758 return ret; 759 } 760 761 kern_return_t 762 IODMACommand::CompleteDMA_Impl( 763 uint64_t options) 764 { 765 IOReturn ret, completeRet; 766 IOMemoryDescriptor * md; 767 768 if (options & ~((uint64_t) kIODMACommandCompleteDMANoOptions)) { 769 // no other options currently defined 770 return kIOReturnBadArgument; 771 } 772 if (!fActive) { 773 return kIOReturnNotReady; 774 } 775 776 md = __DECONST(IOMemoryDescriptor *, fMemory); 777 if (md) { 778 md->retain(); 779 } 780 781 ret = clearMemoryDescriptor(true); 782 783 if (md) { 784 completeRet = md->complete(); 785 OSSafeReleaseNULL(md); 786 if (kIOReturnSuccess == ret) { 787 ret = completeRet; 788 } 789 } 790 791 return ret; 792 } 793 794 kern_return_t 795 IODMACommand::GetPreparation_Impl( 796 uint64_t * offset, 797 uint64_t * length, 798 IOMemoryDescriptor ** memory) 799 { 800 IOReturn ret; 801 IOMemoryDescriptor * md; 802 803 if (!fActive) { 804 return kIOReturnNotReady; 805 } 806 807 ret = getPreparedOffsetAndLength(offset, length); 808 if (kIOReturnSuccess != ret) { 809 return ret; 810 } 811 812 if (memory) { 813 md = __DECONST(IOMemoryDescriptor *, fMemory); 814 *memory = md; 815 if (!md) { 816 ret = kIOReturnNotReady; 817 } else { 818 md->retain(); 819 } 820 } 821 return ret; 822 } 823 824 kern_return_t 825 IODMACommand::PerformOperation_Impl( 826 uint64_t options, 827 uint64_t dmaOffset, 828 uint64_t length, 829 uint64_t dataOffset, 830 IOMemoryDescriptor * data) 831 { 832 IOReturn ret; 833 void * buffer; 834 UInt64 copiedDMA; 835 IOByteCount mdOffset, mdLength, copied; 836 837 if (options & ~((uint64_t) 838 (kIODMACommandPerformOperationOptionRead 839 | kIODMACommandPerformOperationOptionWrite 840 | kIODMACommandPerformOperationOptionZero))) { 841 // no other options currently defined 842 return kIOReturnBadArgument; 843 } 844 845 if (!fActive) { 846 return kIOReturnNotReady; 847 } 848 if (os_convert_overflow(dataOffset, &mdOffset)) { 849 return kIOReturnBadArgument; 850 } 851 if (os_convert_overflow(length, &mdLength)) { 852 return kIOReturnBadArgument; 853 } 854 if (length > fMemory->getLength()) { 855 return kIOReturnBadArgument; 856 } 857 buffer = IONew(uint8_t, length); 858 if (NULL == buffer) { 859 return kIOReturnNoMemory; 860 } 861 862 switch (options) { 863 case kIODMACommandPerformOperationOptionZero: 864 bzero(buffer, length); 865 copiedDMA = writeBytes(dmaOffset, buffer, length); 866 if (copiedDMA != length) { 867 ret = kIOReturnUnderrun; 868 break; 869 } 870 ret = kIOReturnSuccess; 871 break; 872 873 case kIODMACommandPerformOperationOptionRead: 874 case kIODMACommandPerformOperationOptionWrite: 875 876 if (!data) { 877 ret = kIOReturnBadArgument; 878 break; 879 } 880 if (length > data->getLength()) { 881 ret = kIOReturnBadArgument; 882 break; 883 } 884 if (kIODMACommandPerformOperationOptionWrite == options) { 885 copied = data->readBytes(mdOffset, buffer, mdLength); 886 if (copied != mdLength) { 887 ret = kIOReturnUnderrun; 888 break; 889 } 890 copiedDMA = writeBytes(dmaOffset, buffer, length); 891 if (copiedDMA != length) { 892 ret = kIOReturnUnderrun; 893 break; 894 } 895 } else { /* kIODMACommandPerformOperationOptionRead */ 896 copiedDMA = readBytes(dmaOffset, buffer, length); 897 if (copiedDMA != length) { 898 ret = kIOReturnUnderrun; 899 break; 900 } 901 copied = data->writeBytes(mdOffset, buffer, mdLength); 902 if (copied != mdLength) { 903 ret = kIOReturnUnderrun; 904 break; 905 } 906 } 907 ret = kIOReturnSuccess; 908 break; 909 default: 910 ret = kIOReturnBadArgument; 911 break; 912 } 913 914 IODelete(buffer, uint8_t, length); 915 916 return ret; 917 } 918 919 920 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 921 922 static kern_return_t 923 OSActionCreateWithTypeNameInternal(OSObject * target, uint64_t targetmsgid, uint64_t msgid, size_t referenceSize, OSString * typeName, bool fromKernel, OSAction ** action) 924 { 925 OSAction * inst = NULL; 926 vm_size_t allocsize; 927 const OSSymbol *sym = NULL; // must release 928 OSObject *obj = NULL; // must release 929 const OSMetaClass *actionMetaClass = NULL; // do not release 930 kern_return_t ret; 931 932 if (os_add_overflow(referenceSize, sizeof(OSAction_IVars), &allocsize)) { 933 ret = kIOReturnBadArgument; 934 goto finish; 935 } 936 937 if (fromKernel && typeName) { 938 /* The action is being constructed in the kernel with a type name */ 939 sym = OSSymbol::withString(typeName); 940 actionMetaClass = OSMetaClass::getMetaClassWithName(sym); 941 if (actionMetaClass && actionMetaClass->getSuperClass() == OSTypeID(OSAction)) { 942 obj = actionMetaClass->alloc(); 943 if (!obj) { 944 ret = kIOReturnNoMemory; 945 goto finish; 946 } 947 inst = OSDynamicCast(OSAction, obj); 948 obj = NULL; // prevent release 949 assert(inst); // obj is a subclass of OSAction so the dynamic cast should always work 950 } else { 951 DKLOG("Attempted to create action object with type \"%s\" which does not inherit from OSAction\n", typeName->getCStringNoCopy()); 952 ret = kIOReturnBadArgument; 953 goto finish; 954 } 955 } else { 956 inst = OSTypeAlloc(OSAction); 957 if (!inst) { 958 ret = kIOReturnNoMemory; 959 goto finish; 960 } 961 } 962 963 inst->ivars = (typeof(inst->ivars))(uintptr_t) IONewZero(uint8_t, allocsize); 964 if (!inst->ivars) { 965 ret = kIOReturnNoMemory; 966 goto finish; 967 } 968 target->retain(); 969 inst->ivars->target = target; 970 inst->ivars->targetmsgid = targetmsgid; 971 inst->ivars->msgid = msgid; 972 inst->ivars->referenceSize = referenceSize; 973 if (typeName) { 974 typeName->retain(); 975 } 976 inst->ivars->typeName = typeName; 977 978 *action = inst; 979 inst = NULL; // prevent release 980 ret = kIOReturnSuccess; 981 982 finish: 983 OSSafeReleaseNULL(obj); 984 OSSafeReleaseNULL(sym); 985 OSSafeReleaseNULL(inst); 986 987 return ret; 988 } 989 990 kern_return_t 991 OSAction::Create(OSAction_Create_Args) 992 { 993 return OSAction::CreateWithTypeName(target, targetmsgid, msgid, referenceSize, NULL, action); 994 } 995 996 kern_return_t 997 OSAction::CreateWithTypeName(OSAction_CreateWithTypeName_Args) 998 { 999 return OSActionCreateWithTypeNameInternal(target, targetmsgid, msgid, referenceSize, typeName, true, action); 1000 } 1001 1002 kern_return_t 1003 OSAction::Create_Impl( 1004 OSObject * target, 1005 uint64_t targetmsgid, 1006 uint64_t msgid, 1007 size_t referenceSize, 1008 OSAction ** action) 1009 { 1010 return OSAction::CreateWithTypeName_Impl(target, targetmsgid, msgid, referenceSize, NULL, action); 1011 } 1012 1013 kern_return_t 1014 OSAction::CreateWithTypeName_Impl( 1015 OSObject * target, 1016 uint64_t targetmsgid, 1017 uint64_t msgid, 1018 size_t referenceSize, 1019 OSString * typeName, 1020 OSAction ** action) 1021 { 1022 return OSActionCreateWithTypeNameInternal(target, targetmsgid, msgid, referenceSize, typeName, false, action); 1023 } 1024 1025 void 1026 OSAction::free() 1027 { 1028 if (ivars) { 1029 if (ivars->abortedHandler) { 1030 Block_release(ivars->abortedHandler); 1031 ivars->abortedHandler = NULL; 1032 } 1033 OSSafeReleaseNULL(ivars->target); 1034 OSSafeReleaseNULL(ivars->typeName); 1035 IOSafeDeleteNULL(ivars, uint8_t, ivars->referenceSize + sizeof(OSAction_IVars)); 1036 } 1037 return super::free(); 1038 } 1039 1040 void * 1041 OSAction::GetReference() 1042 { 1043 assert(ivars && ivars->referenceSize); 1044 return &ivars->reference[0]; 1045 } 1046 1047 kern_return_t 1048 OSAction::SetAbortedHandler(OSActionAbortedHandler handler) 1049 { 1050 ivars->abortedHandler = Block_copy(handler); 1051 return kIOReturnSuccess; 1052 } 1053 1054 void 1055 OSAction::Aborted_Impl(void) 1056 { 1057 if (ivars->abortedHandler) { 1058 ivars->abortedHandler(); 1059 } 1060 } 1061 1062 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1063 1064 struct IODispatchSource_IVars { 1065 queue_chain_t link; 1066 IODispatchSource * source; 1067 IOUserServer * server; 1068 IODispatchQueue_IVars * queue; 1069 bool enabled; 1070 }; 1071 1072 bool 1073 IODispatchSource::init() 1074 { 1075 if (!super::init()) { 1076 return false; 1077 } 1078 1079 ivars = IONewZero(IODispatchSource_IVars, 1); 1080 1081 ivars->source = this; 1082 1083 return true; 1084 } 1085 1086 void 1087 IODispatchSource::free() 1088 { 1089 IOSafeDeleteNULL(ivars, IODispatchSource_IVars, 1); 1090 super::free(); 1091 } 1092 1093 kern_return_t 1094 IODispatchSource::SetEnable_Impl( 1095 bool enable) 1096 { 1097 return SetEnableWithCompletion(enable, NULL); 1098 } 1099 1100 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1101 1102 struct IOInterruptDispatchSource_IVars { 1103 IOService * provider; 1104 uint32_t intIndex; 1105 int interruptType; 1106 IOSimpleLock * lock; 1107 thread_t waiter; 1108 uint64_t count; 1109 uint64_t time; 1110 OSAction * action; 1111 bool enable; 1112 }; 1113 1114 static void 1115 IOInterruptDispatchSourceInterrupt(OSObject * target, void * refCon, 1116 IOService * nub, int source ) 1117 { 1118 IOInterruptDispatchSource_IVars * ivars = (typeof(ivars))refCon; 1119 IOInterruptState is; 1120 1121 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1122 ivars->count++; 1123 if (ivars->waiter) { 1124 ivars->time = mach_absolute_time(); 1125 thread_wakeup_thread((event_t) ivars, ivars->waiter); 1126 ivars->waiter = NULL; 1127 } 1128 if (kIOInterruptTypeLevel & ivars->interruptType) { 1129 ivars->provider->disableInterrupt(ivars->intIndex); 1130 } 1131 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1132 } 1133 1134 kern_return_t 1135 IOInterruptDispatchSource::Create_Impl( 1136 IOService * provider, 1137 uint32_t index, 1138 IODispatchQueue * queue, 1139 IOInterruptDispatchSource ** source) 1140 { 1141 IOReturn ret; 1142 IOInterruptDispatchSource * inst; 1143 1144 inst = OSTypeAlloc(IOInterruptDispatchSource); 1145 if (!inst->init()) { 1146 inst->free(); 1147 return kIOReturnNoMemory; 1148 } 1149 1150 inst->ivars->lock = IOSimpleLockAlloc(); 1151 1152 ret = provider->getInterruptType(index, &inst->ivars->interruptType); 1153 if (kIOReturnSuccess != ret) { 1154 OSSafeReleaseNULL(inst); 1155 return ret; 1156 } 1157 ret = provider->registerInterrupt(index, inst, IOInterruptDispatchSourceInterrupt, inst->ivars); 1158 if (kIOReturnSuccess == ret) { 1159 inst->ivars->intIndex = index; 1160 inst->ivars->provider = provider; 1161 inst->ivars->provider->retain(); 1162 *source = inst; 1163 } 1164 return ret; 1165 } 1166 1167 kern_return_t 1168 IOInterruptDispatchSource::GetInterruptType_Impl( 1169 IOService * provider, 1170 uint32_t index, 1171 uint64_t * interruptType) 1172 { 1173 IOReturn ret; 1174 int type; 1175 1176 *interruptType = 0; 1177 ret = provider->getInterruptType(index, &type); 1178 if (kIOReturnSuccess == ret) { 1179 *interruptType = type; 1180 } 1181 1182 return ret; 1183 } 1184 1185 bool 1186 IOInterruptDispatchSource::init() 1187 { 1188 if (!super::init()) { 1189 return false; 1190 } 1191 ivars = IONewZero(IOInterruptDispatchSource_IVars, 1); 1192 if (!ivars) { 1193 return false; 1194 } 1195 1196 return true; 1197 } 1198 1199 void 1200 IOInterruptDispatchSource::free() 1201 { 1202 IOReturn ret; 1203 1204 if (ivars && ivars->provider) { 1205 ret = ivars->provider->unregisterInterrupt(ivars->intIndex); 1206 assert(kIOReturnSuccess == ret); 1207 ivars->provider->release(); 1208 } 1209 1210 if (ivars && ivars->lock) { 1211 IOSimpleLockFree(ivars->lock); 1212 } 1213 1214 IOSafeDeleteNULL(ivars, IOInterruptDispatchSource_IVars, 1); 1215 1216 super::free(); 1217 } 1218 1219 kern_return_t 1220 IOInterruptDispatchSource::SetHandler_Impl( 1221 OSAction * action) 1222 { 1223 IOReturn ret; 1224 OSAction * oldAction; 1225 1226 oldAction = (typeof(oldAction))ivars->action; 1227 if (oldAction && OSCompareAndSwapPtr(oldAction, NULL, &ivars->action)) { 1228 oldAction->release(); 1229 } 1230 action->retain(); 1231 ivars->action = action; 1232 1233 ret = kIOReturnSuccess; 1234 1235 return ret; 1236 } 1237 1238 kern_return_t 1239 IOInterruptDispatchSource::SetEnableWithCompletion_Impl( 1240 bool enable, 1241 IODispatchSourceCancelHandler handler) 1242 { 1243 IOReturn ret; 1244 IOInterruptState is; 1245 1246 if (enable == ivars->enable) { 1247 return kIOReturnSuccess; 1248 } 1249 1250 if (enable) { 1251 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1252 ivars->enable = enable; 1253 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1254 ret = ivars->provider->enableInterrupt(ivars->intIndex); 1255 } else { 1256 ret = ivars->provider->disableInterrupt(ivars->intIndex); 1257 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1258 ivars->enable = enable; 1259 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1260 } 1261 1262 return ret; 1263 } 1264 1265 kern_return_t 1266 IOInterruptDispatchSource::Cancel_Impl( 1267 IODispatchSourceCancelHandler handler) 1268 { 1269 return kIOReturnUnsupported; 1270 } 1271 1272 kern_return_t 1273 IOInterruptDispatchSource::CheckForWork_Impl( 1274 const IORPC rpc, 1275 bool synchronous) 1276 { 1277 IOReturn ret = kIOReturnNotReady; 1278 IOInterruptState is; 1279 bool willWait; 1280 wait_result_t waitResult; 1281 uint64_t icount; 1282 uint64_t itime; 1283 thread_t self; 1284 1285 self = current_thread(); 1286 icount = 0; 1287 do { 1288 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1289 if ((icount = ivars->count)) { 1290 itime = ivars->time; 1291 ivars->count = 0; 1292 waitResult = THREAD_AWAKENED; 1293 } else if (synchronous) { 1294 assert(NULL == ivars->waiter); 1295 ivars->waiter = self; 1296 waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE); 1297 } 1298 willWait = (synchronous && (waitResult == THREAD_WAITING)); 1299 if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) { 1300 ivars->provider->enableInterrupt(ivars->intIndex); 1301 } 1302 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1303 if (willWait) { 1304 waitResult = thread_block(THREAD_CONTINUE_NULL); 1305 if (THREAD_INTERRUPTED == waitResult) { 1306 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1307 ivars->waiter = NULL; 1308 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1309 break; 1310 } 1311 } 1312 } while (synchronous && !icount); 1313 1314 if (icount && ivars->action) { 1315 ret = InterruptOccurred(rpc, ivars->action, icount, itime); 1316 } 1317 1318 return ret; 1319 } 1320 1321 void 1322 IOInterruptDispatchSource::InterruptOccurred_Impl( 1323 OSAction * action, 1324 uint64_t count, 1325 uint64_t time) 1326 { 1327 } 1328 1329 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1330 1331 enum { 1332 kIOServiceNotificationTypeCount = kIOServiceNotificationTypeLast + 1, 1333 }; 1334 1335 struct IOServiceNotificationDispatchSource_IVars { 1336 OSObject * serverName; 1337 OSAction * action; 1338 IOLock * lock; 1339 IONotifier * notifier; 1340 OSDictionary * interestNotifiers; 1341 OSArray * pending[kIOServiceNotificationTypeCount]; 1342 bool enable; 1343 }; 1344 1345 kern_return_t 1346 IOServiceNotificationDispatchSource::Create_Impl( 1347 OSDictionary * matching, 1348 uint64_t options, 1349 IODispatchQueue * queue, 1350 IOServiceNotificationDispatchSource ** notification) 1351 { 1352 IOUserServer * us; 1353 IOReturn ret; 1354 IOServiceNotificationDispatchSource * inst; 1355 1356 inst = OSTypeAlloc(IOServiceNotificationDispatchSource); 1357 if (!inst->init()) { 1358 OSSafeReleaseNULL(inst); 1359 return kIOReturnNoMemory; 1360 } 1361 1362 us = (typeof(us))thread_iokit_tls_get(0); 1363 assert(OSDynamicCast(IOUserServer, us)); 1364 if (!us) { 1365 OSSafeReleaseNULL(inst); 1366 return kIOReturnError; 1367 } 1368 inst->ivars->serverName = us->copyProperty(gIOUserServerNameKey); 1369 if (!inst->ivars->serverName) { 1370 OSSafeReleaseNULL(inst); 1371 return kIOReturnNoMemory; 1372 } 1373 1374 inst->ivars->lock = IOLockAlloc(); 1375 if (!inst->ivars->lock) { 1376 OSSafeReleaseNULL(inst); 1377 return kIOReturnNoMemory; 1378 } 1379 for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) { 1380 inst->ivars->pending[idx] = OSArray::withCapacity(4); 1381 if (!inst->ivars->pending[idx]) { 1382 OSSafeReleaseNULL(inst); 1383 return kIOReturnNoMemory; 1384 } 1385 } 1386 inst->ivars->interestNotifiers = OSDictionary::withCapacity(4); 1387 if (!inst->ivars->interestNotifiers) { 1388 OSSafeReleaseNULL(inst); 1389 return kIOReturnNoMemory; 1390 } 1391 1392 inst->ivars->notifier = IOService::addMatchingNotification(gIOMatchedNotification, matching, 0 /*priority*/, 1393 ^bool (IOService * newService, IONotifier * notifier) { 1394 bool notifyReady = false; 1395 IONotifier * interest; 1396 OSObject * serverName; 1397 bool okToUse; 1398 1399 serverName = newService->copyProperty(gIOUserServerNameKey); 1400 okToUse = (serverName && inst->ivars->serverName->isEqualTo(serverName)); 1401 OSSafeReleaseNULL(serverName); 1402 if (!okToUse) { 1403 return false; 1404 } 1405 1406 IOLockLock(inst->ivars->lock); 1407 notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeMatched]->getCount()); 1408 inst->ivars->pending[kIOServiceNotificationTypeMatched]->setObject(newService); 1409 IOLockUnlock(inst->ivars->lock); 1410 1411 interest = newService->registerInterest(gIOGeneralInterest, 1412 ^IOReturn (uint32_t messageType, IOService * provider, 1413 void * messageArgument, size_t argSize) { 1414 IONotifier * interest; 1415 bool notifyReady = false; 1416 1417 switch (messageType) { 1418 case kIOMessageServiceIsTerminated: 1419 IOLockLock(inst->ivars->lock); 1420 notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeTerminated]->getCount()); 1421 inst->ivars->pending[kIOServiceNotificationTypeTerminated]->setObject(provider); 1422 interest = (typeof(interest))inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService); 1423 assert(interest); 1424 interest->remove(); 1425 inst->ivars->interestNotifiers->removeObject((const OSSymbol *) newService); 1426 IOLockUnlock(inst->ivars->lock); 1427 break; 1428 default: 1429 break; 1430 } 1431 if (notifyReady && inst->ivars->action) { 1432 inst->ServiceNotificationReady(inst->ivars->action); 1433 } 1434 return kIOReturnSuccess; 1435 }); 1436 if (interest) { 1437 IOLockLock(inst->ivars->lock); 1438 inst->ivars->interestNotifiers->setObject((const OSSymbol *) newService, interest); 1439 IOLockUnlock(inst->ivars->lock); 1440 } 1441 if (notifyReady) { 1442 if (inst->ivars->action) { 1443 inst->ServiceNotificationReady(inst->ivars->action); 1444 } 1445 } 1446 return false; 1447 }); 1448 1449 if (!inst->ivars->notifier) { 1450 OSSafeReleaseNULL(inst); 1451 ret = kIOReturnError; 1452 } 1453 1454 *notification = inst; 1455 ret = kIOReturnSuccess; 1456 1457 return ret; 1458 } 1459 1460 kern_return_t 1461 IOServiceNotificationDispatchSource::CopyNextNotification_Impl( 1462 uint64_t * type, 1463 IOService ** service, 1464 uint64_t * options) 1465 { 1466 IOService * next; 1467 uint32_t idx; 1468 1469 IOLockLock(ivars->lock); 1470 for (idx = 0; idx < kIOServiceNotificationTypeCount; idx++) { 1471 next = (IOService *) ivars->pending[idx]->getObject(0); 1472 if (next) { 1473 next->retain(); 1474 ivars->pending[idx]->removeObject(0); 1475 break; 1476 } 1477 } 1478 IOLockUnlock(ivars->lock); 1479 1480 if (idx == kIOServiceNotificationTypeCount) { 1481 idx = kIOServiceNotificationTypeNone; 1482 } 1483 *type = idx; 1484 *service = next; 1485 *options = 0; 1486 1487 return kIOReturnSuccess; 1488 } 1489 1490 bool 1491 IOServiceNotificationDispatchSource::init() 1492 { 1493 if (!super::init()) { 1494 return false; 1495 } 1496 ivars = IONewZero(IOServiceNotificationDispatchSource_IVars, 1); 1497 if (!ivars) { 1498 return false; 1499 } 1500 1501 return true; 1502 } 1503 1504 void 1505 IOServiceNotificationDispatchSource::free() 1506 { 1507 if (ivars) { 1508 OSSafeReleaseNULL(ivars->serverName); 1509 if (ivars->interestNotifiers) { 1510 ivars->interestNotifiers->iterateObjects(^bool (const OSSymbol * key, OSObject * object) { 1511 IONotifier * interest = (typeof(interest))object; 1512 interest->remove(); 1513 return false; 1514 }); 1515 OSSafeReleaseNULL(ivars->interestNotifiers); 1516 } 1517 for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) { 1518 OSSafeReleaseNULL(ivars->pending[idx]); 1519 } 1520 if (ivars->lock) { 1521 IOLockFree(ivars->lock); 1522 ivars->lock = NULL; 1523 } 1524 if (ivars->notifier) { 1525 ivars->notifier->remove(); 1526 ivars->notifier = NULL; 1527 } 1528 IOSafeDeleteNULL(ivars, IOServiceNotificationDispatchSource_IVars, 1); 1529 } 1530 1531 super::free(); 1532 } 1533 1534 kern_return_t 1535 IOServiceNotificationDispatchSource::SetHandler_Impl( 1536 OSAction * action) 1537 { 1538 IOReturn ret; 1539 bool notifyReady; 1540 1541 notifyReady = false; 1542 1543 IOLockLock(ivars->lock); 1544 OSSafeReleaseNULL(ivars->action); 1545 action->retain(); 1546 ivars->action = action; 1547 if (action) { 1548 for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) { 1549 notifyReady = (ivars->pending[idx]->getCount()); 1550 if (notifyReady) { 1551 break; 1552 } 1553 } 1554 } 1555 IOLockUnlock(ivars->lock); 1556 1557 if (notifyReady) { 1558 ServiceNotificationReady(action); 1559 } 1560 ret = kIOReturnSuccess; 1561 1562 return ret; 1563 } 1564 1565 kern_return_t 1566 IOServiceNotificationDispatchSource::SetEnableWithCompletion_Impl( 1567 bool enable, 1568 IODispatchSourceCancelHandler handler) 1569 { 1570 if (enable == ivars->enable) { 1571 return kIOReturnSuccess; 1572 } 1573 1574 IOLockLock(ivars->lock); 1575 ivars->enable = enable; 1576 IOLockUnlock(ivars->lock); 1577 1578 return kIOReturnSuccess; 1579 } 1580 1581 kern_return_t 1582 IOServiceNotificationDispatchSource::Cancel_Impl( 1583 IODispatchSourceCancelHandler handler) 1584 { 1585 return kIOReturnUnsupported; 1586 } 1587 1588 kern_return_t 1589 IOServiceNotificationDispatchSource::CheckForWork_Impl( 1590 const IORPC rpc, 1591 bool synchronous) 1592 { 1593 return kIOReturnNotReady; 1594 } 1595 1596 kern_return_t 1597 IOServiceNotificationDispatchSource::DeliverNotifications(IOServiceNotificationBlock block) 1598 { 1599 return kIOReturnUnsupported; 1600 } 1601 1602 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1603 1604 kern_return_t 1605 IOUserServer::waitInterruptTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6) 1606 { 1607 IOReturn ret = kIOReturnBadArgument; 1608 IOInterruptState is; 1609 IOInterruptDispatchSource * interrupt; 1610 IOInterruptDispatchSource_IVars * ivars; 1611 IOInterruptDispatchSourcePayload payload; 1612 1613 bool willWait; 1614 wait_result_t waitResult; 1615 thread_t self; 1616 1617 OSObject * object; 1618 1619 object = iokit_lookup_object_with_port_name((mach_port_name_t)(uintptr_t)p1, IKOT_UEXT_OBJECT, current_task()); 1620 1621 if (!object) { 1622 return kIOReturnBadArgument; 1623 } 1624 if (!(interrupt = OSDynamicCast(IOInterruptDispatchSource, object))) { 1625 ret = kIOReturnBadArgument; 1626 } else { 1627 self = current_thread(); 1628 ivars = interrupt->ivars; 1629 payload.count = 0; 1630 do { 1631 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1632 if ((payload.count = ivars->count)) { 1633 payload.time = ivars->time; 1634 ivars->count = 0; 1635 waitResult = THREAD_AWAKENED; 1636 } else { 1637 assert(NULL == ivars->waiter); 1638 ivars->waiter = self; 1639 waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE); 1640 } 1641 willWait = (waitResult == THREAD_WAITING); 1642 if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) { 1643 ivars->provider->enableInterrupt(ivars->intIndex); 1644 } 1645 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1646 if (willWait) { 1647 waitResult = thread_block(THREAD_CONTINUE_NULL); 1648 if (THREAD_INTERRUPTED == waitResult) { 1649 is = IOSimpleLockLockDisableInterrupt(ivars->lock); 1650 ivars->waiter = NULL; 1651 IOSimpleLockUnlockEnableInterrupt(ivars->lock, is); 1652 break; 1653 } 1654 } 1655 } while (!payload.count); 1656 ret = (payload.count ? kIOReturnSuccess : kIOReturnAborted); 1657 } 1658 1659 if (kIOReturnSuccess == ret) { 1660 int copyerr = copyout(&payload, (user_addr_t) p2, sizeof(payload)); 1661 if (copyerr) { 1662 ret = kIOReturnVMError; 1663 } 1664 } 1665 1666 object->release(); 1667 1668 return ret; 1669 } 1670 1671 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1672 1673 kern_return_t 1674 IOUserServer::Create_Impl( 1675 const char * name, 1676 uint64_t tag, 1677 uint64_t options, 1678 IOUserServer ** server) 1679 { 1680 IOReturn ret; 1681 IOUserServer * us; 1682 const OSSymbol * sym; 1683 OSNumber * serverTag; 1684 io_name_t rname; 1685 1686 us = (typeof(us))thread_iokit_tls_get(0); 1687 assert(OSDynamicCast(IOUserServer, us)); 1688 if (kIODKLogSetup & gIODKDebug) { 1689 DKLOG(DKS "::Create(" DKS ") %p\n", DKN(us), name, tag, us); 1690 } 1691 if (!us) { 1692 return kIOReturnError; 1693 } 1694 1695 sym = OSSymbol::withCString(name); 1696 serverTag = OSNumber::withNumber(tag, 64); 1697 1698 us->setProperty(gIOUserServerNameKey, (OSObject *) sym); 1699 us->setProperty(gIOUserServerTagKey, serverTag); 1700 1701 serverTag->release(); 1702 OSSafeReleaseNULL(sym); 1703 1704 snprintf(rname, sizeof(rname), "IOUserServer(%s-0x%qx)", name, tag); 1705 us->setName(rname); 1706 1707 us->retain(); 1708 *server = us; 1709 ret = kIOReturnSuccess; 1710 1711 return ret; 1712 } 1713 1714 kern_return_t 1715 IOUserServer::Exit_Impl( 1716 const char * reason) 1717 { 1718 return kIOReturnUnsupported; 1719 } 1720 1721 kern_return_t 1722 IOUserServer::LoadModule_Impl( 1723 const char * path) 1724 { 1725 return kIOReturnUnsupported; 1726 } 1727 1728 1729 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1730 1731 kern_return_t 1732 IODispatchQueue::Create_Impl( 1733 const char * name, 1734 uint64_t options, 1735 uint64_t priority, 1736 IODispatchQueue ** queue) 1737 { 1738 IODispatchQueue * result; 1739 IOUserServer * us; 1740 1741 result = OSTypeAlloc(IODispatchQueue); 1742 if (!result) { 1743 return kIOReturnNoMemory; 1744 } 1745 if (!result->init()) { 1746 return kIOReturnNoMemory; 1747 } 1748 1749 *queue = result; 1750 1751 if (!strcmp("Root", name)) { 1752 us = (typeof(us))thread_iokit_tls_get(0); 1753 assert(OSDynamicCast(IOUserServer, us)); 1754 us->setRootQueue(result); 1755 } 1756 1757 if (kIODKLogSetup & gIODKDebug) { 1758 DKLOG("IODispatchQueue::Create %s %p\n", name, result); 1759 } 1760 1761 return kIOReturnSuccess; 1762 } 1763 1764 kern_return_t 1765 IODispatchQueue::SetPort_Impl( 1766 mach_port_t port) 1767 { 1768 if (MACH_PORT_NULL != ivars->serverPort) { 1769 return kIOReturnNotReady; 1770 } 1771 1772 ivars->serverPort = port; 1773 return kIOReturnSuccess; 1774 } 1775 1776 bool 1777 IODispatchQueue::init() 1778 { 1779 ivars = IONewZero(IODispatchQueue_IVars, 1); 1780 if (!ivars) { 1781 return false; 1782 } 1783 ivars->queue = this; 1784 1785 return true; 1786 } 1787 1788 void 1789 IODispatchQueue::free() 1790 { 1791 if (ivars && ivars->serverPort) { 1792 ipc_port_release_send(ivars->serverPort); 1793 ivars->serverPort = MACH_PORT_NULL; 1794 } 1795 IOSafeDeleteNULL(ivars, IODispatchQueue_IVars, 1); 1796 super::free(); 1797 } 1798 1799 bool 1800 IODispatchQueue::OnQueue() 1801 { 1802 return false; 1803 } 1804 1805 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1806 1807 1808 kern_return_t 1809 OSMetaClassBase::Dispatch(IORPC rpc) 1810 { 1811 return kIOReturnUnsupported; 1812 } 1813 1814 kern_return_t 1815 OSMetaClassBase::Invoke(IORPC rpc) 1816 { 1817 IOReturn ret = kIOReturnUnsupported; 1818 OSMetaClassBase * object; 1819 OSAction * action; 1820 IOService * service; 1821 IOUserServer * us; 1822 IORPCMessage * message; 1823 1824 assert(rpc.sendSize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))); 1825 message = IORPCMessageFromMach(rpc.message, false); 1826 if (!message) { 1827 return kIOReturnIPCError; 1828 } 1829 message->flags |= kIORPCMessageKernel; 1830 1831 us = NULL; 1832 if (!(kIORPCMessageLocalHost & message->flags)) { 1833 us = OSDynamicCast(IOUserServer, this); 1834 if (!us) { 1835 if ((action = OSDynamicCast(OSAction, this))) { 1836 object = IOUserServer::target(action, message); 1837 } else { 1838 object = this; 1839 } 1840 if ((service = OSDynamicCast(IOService, object)) 1841 && service->reserved->uvars) { 1842 // xxx other classes 1843 us = service->reserved->uvars->userServer; 1844 } 1845 } 1846 } 1847 if (us) { 1848 message->flags |= kIORPCMessageRemote; 1849 ret = us->rpc(rpc); 1850 if (kIOReturnSuccess != ret) { 1851 if (kIODKLogIPC & gIODKDebug) { 1852 DKLOG("OSMetaClassBase::Invoke user 0x%x\n", ret); 1853 } 1854 } 1855 } else { 1856 if (kIODKLogIPC & gIODKDebug) { 1857 DKLOG("OSMetaClassBase::Invoke kernel %s 0x%qx\n", getMetaClass()->getClassName(), message->msgid); 1858 } 1859 ret = Dispatch(rpc); 1860 } 1861 1862 return ret; 1863 } 1864 1865 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1866 1867 struct IOPStrings { 1868 uint32_t dataSize; 1869 uint32_t count; 1870 const char strings[0]; 1871 }; 1872 1873 kern_return_t 1874 OSUserMetaClass::Dispatch(IORPC rpc) 1875 { 1876 if (meta) { 1877 return const_cast<OSMetaClass *>(meta)->Dispatch(rpc); 1878 } else { 1879 return kIOReturnUnsupported; 1880 } 1881 } 1882 1883 void 1884 OSUserMetaClass::free() 1885 { 1886 if (queueNames) { 1887 IOFree(queueNames, sizeof(IOPStrings) + queueNames->dataSize * sizeof(char)); 1888 queueNames = NULL; 1889 } 1890 if (description) { 1891 IOFree(description, description->descriptionSize); 1892 description = NULL; 1893 } 1894 IOSafeDeleteNULL(methods, uint64_t, 2 * methodCount); 1895 if (meta) { 1896 meta->releaseMetaClass(); 1897 } 1898 if (name) { 1899 name->release(); 1900 } 1901 OSObject::free(); 1902 } 1903 1904 /* 1905 * Sets the loadTag of the associated OSKext 1906 * in the dext task. 1907 * NOTE: different instances of the same OSKext 1908 * (so same BounleID but different tasks) 1909 * will have the same loadTag. 1910 */ 1911 void 1912 IOUserServer::setTaskLoadTag(OSKext *kext) 1913 { 1914 task_t owningTask; 1915 uint32_t loadTag, prev_taskloadTag; 1916 1917 owningTask = this->fOwningTask; 1918 if (!owningTask) { 1919 printf("%s: fOwningTask not found\n", __FUNCTION__); 1920 return; 1921 } 1922 1923 loadTag = kext->getLoadTag(); 1924 prev_taskloadTag = set_task_loadTag(owningTask, loadTag); 1925 if (prev_taskloadTag) { 1926 printf("%s: found the task loadTag already set to %u (set to %u)\n", 1927 __FUNCTION__, prev_taskloadTag, loadTag); 1928 } 1929 } 1930 1931 /* 1932 * Sets the OSKext uuid as the uuid of the userspace 1933 * dext executable. 1934 */ 1935 void 1936 IOUserServer::setDriverKitUUID(OSKext *kext) 1937 { 1938 task_t task; 1939 proc_t p; 1940 uuid_t p_uuid, k_uuid; 1941 OSData *k_data_uuid; 1942 OSData *new_uuid; 1943 uuid_string_t uuid_string = ""; 1944 1945 task = this->fOwningTask; 1946 if (!task) { 1947 printf("%s: fOwningTask not found\n", __FUNCTION__); 1948 return; 1949 } 1950 1951 p = (proc_t)(get_bsdtask_info(task)); 1952 if (!p) { 1953 printf("%s: proc not found\n", __FUNCTION__); 1954 return; 1955 } 1956 proc_getexecutableuuid(p, p_uuid, sizeof(p_uuid)); 1957 1958 k_data_uuid = kext->copyUUID(); 1959 if (k_data_uuid) { 1960 memcpy(&k_uuid, k_data_uuid->getBytesNoCopy(), sizeof(k_uuid)); 1961 OSSafeReleaseNULL(k_data_uuid); 1962 if (uuid_compare(k_uuid, p_uuid) != 0) { 1963 printf("%s: uuid not matching\n", __FUNCTION__); 1964 } 1965 return; 1966 } 1967 1968 uuid_unparse(p_uuid, uuid_string); 1969 new_uuid = OSData::withBytes(p_uuid, sizeof(p_uuid)); 1970 kext->setDriverKitUUID(new_uuid); 1971 } 1972 1973 void 1974 IOUserServer::setCheckInToken(IOUserServerCheckInToken *token) 1975 { 1976 if (token != NULL && fCheckInToken == NULL) { 1977 token->retain(); 1978 fCheckInToken = token; 1979 } else { 1980 printf("%s: failed to set check in token. token=%p, fCheckInToken=%p\n", __FUNCTION__, token, fCheckInToken); 1981 } 1982 } 1983 1984 bool 1985 IOUserServer::serviceMatchesCheckInToken(IOUserServerCheckInToken *token) 1986 { 1987 if (token != NULL) { 1988 return token == fCheckInToken; 1989 } else { 1990 printf("%s: null check in token\n", __FUNCTION__); 1991 return false; 1992 } 1993 } 1994 1995 bool 1996 IOUserServer::checkEntitlements( 1997 OSDictionary * entitlements, OSObject * prop, 1998 IOService * provider, IOService * dext) 1999 { 2000 OSDictionary * matching; 2001 2002 if (!prop) { 2003 return true; 2004 } 2005 if (!entitlements) { 2006 return false; 2007 } 2008 2009 matching = NULL; 2010 if (dext) { 2011 matching = dext->dictionaryWithProperties(); 2012 if (!matching) { 2013 return false; 2014 } 2015 } 2016 2017 bool allPresent __block; 2018 prop->iterateObjects(^bool (OSObject * object) { 2019 allPresent = false; 2020 object->iterateObjects(^bool (OSObject * object) { 2021 OSString * string; 2022 OSObject * value; 2023 string = OSDynamicCast(OSString, object); 2024 value = entitlements->getObject(string); 2025 if (matching && value) { 2026 matching->setObject(string, value); 2027 } 2028 allPresent = (NULL != value); 2029 return !allPresent; 2030 }); 2031 return allPresent; 2032 }); 2033 2034 if (allPresent && matching && provider) { 2035 allPresent = provider->matchPropertyTable(matching); 2036 } 2037 2038 OSSafeReleaseNULL(matching); 2039 OSSafeReleaseNULL(prop); 2040 2041 return allPresent; 2042 } 2043 2044 bool 2045 IOUserServer::checkEntitlements(IOService * provider, IOService * dext) 2046 { 2047 OSObject * prop; 2048 bool ok; 2049 2050 if (!fOwningTask) { 2051 return false; 2052 } 2053 2054 prop = provider->copyProperty(gIOServiceDEXTEntitlementsKey); 2055 ok = checkEntitlements(fEntitlements, prop, provider, dext); 2056 if (!ok) { 2057 DKLOG(DKS ": provider entitlements check failed\n", DKN(dext)); 2058 } 2059 if (ok) { 2060 prop = dext->copyProperty(gIOServiceDEXTEntitlementsKey); 2061 ok = checkEntitlements(fEntitlements, prop, NULL, NULL); 2062 if (!ok) { 2063 DKLOG(DKS ": family entitlements check failed\n", DKN(dext)); 2064 } 2065 } 2066 2067 return ok; 2068 } 2069 2070 IOReturn 2071 IOUserServer::exit(const char * reason) 2072 { 2073 DKLOG("%s::exit(%s)\n", getName(), reason); 2074 Exit(reason); 2075 return kIOReturnSuccess; 2076 } 2077 2078 OSObjectUserVars * 2079 IOUserServer::varsForObject(OSObject * obj) 2080 { 2081 IOService * service; 2082 2083 if ((service = OSDynamicCast(IOService, obj))) { 2084 return service->reserved->uvars; 2085 } 2086 2087 return NULL; 2088 } 2089 2090 IOPStrings * 2091 IOUserServer::copyInStringArray(const char * string, uint32_t userSize) 2092 { 2093 IOPStrings * array; 2094 vm_size_t alloc; 2095 size_t len; 2096 const char * cstr; 2097 const char * end; 2098 2099 if (userSize <= 1) { 2100 return NULL; 2101 } 2102 2103 if (os_add_overflow(sizeof(IOPStrings), userSize, &alloc)) { 2104 assert(false); 2105 return NULL; 2106 } 2107 if (alloc > 16384) { 2108 assert(false); 2109 return NULL; 2110 } 2111 array = (typeof(array))IOMalloc(alloc); 2112 if (!array) { 2113 return NULL; 2114 } 2115 array->dataSize = userSize; 2116 bcopy(string, (void *) &array->strings[0], userSize); 2117 2118 array->count = 0; 2119 cstr = &array->strings[0]; 2120 end = &array->strings[array->dataSize]; 2121 while ((len = (unsigned char)cstr[0])) { 2122 cstr++; 2123 if ((cstr + len) >= end) { 2124 break; 2125 } 2126 cstr += len; 2127 array->count++; 2128 } 2129 if (len) { 2130 IOFree(array, alloc); 2131 array = NULL; 2132 } 2133 2134 return array; 2135 } 2136 2137 uint32_t 2138 IOUserServer::stringArrayIndex(IOPStrings * array, const char * look) 2139 { 2140 uint32_t idx; 2141 size_t len, llen; 2142 const char * cstr; 2143 const char * end; 2144 2145 idx = 0; 2146 cstr = &array->strings[0]; 2147 end = &array->strings[array->dataSize]; 2148 llen = strlen(look); 2149 while ((len = (unsigned char)cstr[0])) { 2150 cstr++; 2151 if ((cstr + len) >= end) { 2152 break; 2153 } 2154 if ((len == llen) && !strncmp(cstr, look, len)) { 2155 return idx; 2156 } 2157 cstr += len; 2158 idx++; 2159 } 2160 2161 return -1U; 2162 } 2163 #define kIODispatchQueueStopped ((IODispatchQueue *) -1L) 2164 2165 IODispatchQueue * 2166 IOUserServer::queueForObject(OSObject * obj, uint64_t msgid) 2167 { 2168 IODispatchQueue * queue; 2169 OSObjectUserVars * uvars; 2170 uint64_t option; 2171 2172 uvars = varsForObject(obj); 2173 if (!uvars) { 2174 return NULL; 2175 } 2176 if (!uvars->queueArray) { 2177 if (uvars->stopped) { 2178 return kIODispatchQueueStopped; 2179 } 2180 return NULL; 2181 } 2182 queue = uvars->queueArray[0]; 2183 2184 if (uvars->userMeta 2185 && uvars->userMeta->methods) { 2186 uint32_t idx, baseIdx; 2187 uint32_t lim; 2188 // bsearch 2189 for (baseIdx = 0, lim = uvars->userMeta->methodCount; lim; lim >>= 1) { 2190 idx = baseIdx + (lim >> 1); 2191 if (msgid == uvars->userMeta->methods[idx]) { 2192 option = uvars->userMeta->methods[uvars->userMeta->methodCount + idx]; 2193 option &= 0xFF; 2194 if (option < uvars->userMeta->queueNames->count) { 2195 queue = uvars->queueArray[option + 1]; 2196 } 2197 break; 2198 } else if (msgid > uvars->userMeta->methods[idx]) { 2199 // move right 2200 baseIdx += (lim >> 1) + 1; 2201 lim--; 2202 } 2203 // else move left 2204 } 2205 } 2206 return queue; 2207 } 2208 2209 IOReturn 2210 IOUserServer::objectInstantiate(OSObject * obj, IORPC rpc, IORPCMessage * message) 2211 { 2212 IOReturn ret; 2213 OSString * str; 2214 OSObject * prop; 2215 IOService * service; 2216 2217 OSAction * action; 2218 OSObject * target; 2219 uint32_t queueCount, queueAlloc; 2220 const char * resultClassName; 2221 uint64_t resultFlags; 2222 2223 mach_msg_size_t replySize; 2224 uint32_t methodCount; 2225 const uint64_t * methods; 2226 IODispatchQueue * queue; 2227 OSUserMetaClass * userMeta; 2228 OSObjectUserVars * uvars; 2229 uint32_t idx; 2230 ipc_port_t sendPort; 2231 2232 OSObject_Instantiate_Rpl_Content * reply; 2233 2234 queueCount = 0; 2235 methodCount = 0; 2236 methods = NULL; 2237 str = NULL; 2238 prop = NULL; 2239 userMeta = NULL; 2240 resultClassName = NULL; 2241 resultFlags = 0; 2242 ret = kIOReturnUnsupportedMode; 2243 2244 service = OSDynamicCast(IOService, obj); 2245 action = OSDynamicCast(OSAction, obj); 2246 if (!service) { 2247 // xxx other classes hosted 2248 resultFlags |= kOSObjectRPCKernel; 2249 resultFlags |= kOSObjectRPCRemote; 2250 } else { 2251 if (service->isInactive()) { 2252 DKLOG(DKS "::instantiate inactive\n", DKN(service)); 2253 return kIOReturnOffline; 2254 } 2255 prop = service->copyProperty(gIOUserClassKey); 2256 str = OSDynamicCast(OSString, prop); 2257 if (!service->reserved->uvars) { 2258 resultFlags |= kOSObjectRPCRemote; 2259 resultFlags |= kOSObjectRPCKernel; 2260 } else if (this != service->reserved->uvars->userServer) { 2261 // remote, use base class 2262 resultFlags |= kOSObjectRPCRemote; 2263 } 2264 if (service->reserved->uvars && service->reserved->uvars->userServer) { 2265 IOLockLock(service->reserved->uvars->userServer->fLock); 2266 userMeta = (typeof(userMeta))service->reserved->uvars->userServer->fClasses->getObject(str); 2267 IOLockUnlock(service->reserved->uvars->userServer->fLock); 2268 } 2269 } 2270 if (!str && !userMeta) { 2271 const OSMetaClass * meta; 2272 meta = obj->getMetaClass(); 2273 IOLockLock(fLock); 2274 if (action) { 2275 str = action->ivars->typeName; 2276 if (str) { 2277 userMeta = (typeof(userMeta))fClasses->getObject(str); 2278 } 2279 } 2280 while (meta && !userMeta) { 2281 str = (OSString *) meta->getClassNameSymbol(); 2282 userMeta = (typeof(userMeta))fClasses->getObject(str); 2283 if (!userMeta) { 2284 meta = meta->getSuperClass(); 2285 } 2286 } 2287 IOLockUnlock(fLock); 2288 } 2289 if (str) { 2290 if (!userMeta) { 2291 IOLockLock(fLock); 2292 userMeta = (typeof(userMeta))fClasses->getObject(str); 2293 IOLockUnlock(fLock); 2294 } 2295 if (kIODKLogSetup & gIODKDebug) { 2296 DKLOG("userMeta %s %p\n", str->getCStringNoCopy(), userMeta); 2297 } 2298 if (userMeta) { 2299 if (kOSObjectRPCRemote & resultFlags) { 2300 if (!action) { 2301 /* Special case: For OSAction subclasses, do not use the superclass */ 2302 while (userMeta && !(kOSClassCanRemote & userMeta->description->flags)) { 2303 userMeta = userMeta->superMeta; 2304 } 2305 } 2306 if (userMeta) { 2307 resultClassName = userMeta->description->name; 2308 ret = kIOReturnSuccess; 2309 } 2310 } else { 2311 service->reserved->uvars->userMeta = userMeta; 2312 queueAlloc = 1; 2313 if (userMeta->queueNames) { 2314 queueAlloc += userMeta->queueNames->count; 2315 } 2316 service->reserved->uvars->queueArray = 2317 IONewZero(IODispatchQueue *, queueAlloc); 2318 resultClassName = str->getCStringNoCopy(); 2319 ret = kIOReturnSuccess; 2320 } 2321 } else if (kIODKLogSetup & gIODKDebug) { 2322 DKLOG("userMeta %s was not found in fClasses\n", str->getCStringNoCopy()); 2323 IOLockLock(fLock); 2324 fClasses->iterateObjects(^bool (const OSSymbol * key, OSObject * val) { 2325 DKLOG(" fClasses[\"%s\"] => %p\n", key->getCStringNoCopy(), val); 2326 return false; 2327 }); 2328 IOLockUnlock(fLock); 2329 } 2330 } 2331 OSSafeReleaseNULL(prop); 2332 2333 IORPCMessageMach * machReply = rpc.reply; 2334 replySize = sizeof(OSObject_Instantiate_Rpl); 2335 2336 if ((kIOReturnSuccess == ret) && (kOSObjectRPCRemote & resultFlags)) { 2337 target = obj; 2338 if (action) { 2339 if (action->ivars->referenceSize) { 2340 resultFlags |= kOSObjectRPCKernel; 2341 } else { 2342 resultFlags &= ~kOSObjectRPCKernel; 2343 target = action->ivars->target; 2344 2345 queueCount = 1; 2346 queue = queueForObject(target, action->ivars->targetmsgid); 2347 idx = 0; 2348 sendPort = NULL; 2349 if (queue && (kIODispatchQueueStopped != queue)) { 2350 sendPort = ipc_port_copy_send(queue->ivars->serverPort); 2351 } 2352 replySize = sizeof(OSObject_Instantiate_Rpl) 2353 + queueCount * sizeof(machReply->objects[0]) 2354 + 2 * methodCount * sizeof(reply->methods[0]); 2355 if (replySize > rpc.replySize) { 2356 assert(false); 2357 return kIOReturnIPCError; 2358 } 2359 machReply->objects[idx].type = MACH_MSG_PORT_DESCRIPTOR; 2360 machReply->objects[idx].disposition = MACH_MSG_TYPE_MOVE_SEND; 2361 machReply->objects[idx].name = sendPort; 2362 machReply->objects[idx].pad2 = 0; 2363 machReply->objects[idx].pad_end = 0; 2364 } 2365 } else { 2366 uvars = varsForObject(target); 2367 if (uvars && uvars->userMeta) { 2368 queueCount = 1; 2369 if (uvars->userMeta->queueNames) { 2370 queueCount += uvars->userMeta->queueNames->count; 2371 } 2372 methods = &uvars->userMeta->methods[0]; 2373 methodCount = uvars->userMeta->methodCount; 2374 replySize = sizeof(OSObject_Instantiate_Rpl) 2375 + queueCount * sizeof(machReply->objects[0]) 2376 + 2 * methodCount * sizeof(reply->methods[0]); 2377 if (replySize > rpc.replySize) { 2378 assert(false); 2379 return kIOReturnIPCError; 2380 } 2381 for (idx = 0; idx < queueCount; idx++) { 2382 queue = uvars->queueArray[idx]; 2383 sendPort = NULL; 2384 if (queue) { 2385 sendPort = ipc_port_copy_send(queue->ivars->serverPort); 2386 } 2387 machReply->objects[idx].type = MACH_MSG_PORT_DESCRIPTOR; 2388 machReply->objects[idx].disposition = MACH_MSG_TYPE_MOVE_SEND; 2389 machReply->objects[idx].name = sendPort; 2390 machReply->objects[idx].pad2 = 0; 2391 machReply->objects[idx].pad_end = 0; 2392 } 2393 } 2394 } 2395 } 2396 2397 if (kIODKLogIPC & gIODKDebug) { 2398 DKLOG("instantiate object %s with user class %s\n", obj->getMetaClass()->getClassName(), str ? str->getCStringNoCopy() : "(null)"); 2399 } 2400 2401 if (kIOReturnSuccess != ret) { 2402 DKLOG("%s: no user class found\n", str ? str->getCStringNoCopy() : obj->getMetaClass()->getClassName()); 2403 resultClassName = "unknown"; 2404 } 2405 2406 machReply->msgh.msgh_id = kIORPCVersionCurrentReply; 2407 machReply->msgh.msgh_size = replySize; 2408 machReply->msgh_body.msgh_descriptor_count = queueCount; 2409 2410 reply = (typeof(reply))IORPCMessageFromMach(machReply, true); 2411 if (!reply) { 2412 return kIOReturnIPCError; 2413 } 2414 if (methodCount) { 2415 bcopy(methods, &reply->methods[0], methodCount * 2 * sizeof(reply->methods[0])); 2416 } 2417 reply->__hdr.msgid = OSObject_Instantiate_ID; 2418 reply->__hdr.flags = kIORPCMessageOneway; 2419 reply->__hdr.objectRefs = 0; 2420 reply->__pad = 0; 2421 reply->flags = resultFlags; 2422 strlcpy(reply->classname, resultClassName, sizeof(reply->classname)); 2423 reply->__result = ret; 2424 2425 ret = kIOReturnSuccess; 2426 2427 return ret; 2428 } 2429 2430 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2431 2432 IOReturn 2433 IOUserServer::kernelDispatch(OSObject * obj, IORPC rpc) 2434 { 2435 IOReturn ret; 2436 IORPCMessage * message; 2437 2438 message = IORPCMessageFromMach(rpc.message, false); 2439 if (!message) { 2440 return kIOReturnIPCError; 2441 } 2442 2443 if (OSObject_Instantiate_ID == message->msgid) { 2444 ret = objectInstantiate(obj, rpc, message); 2445 if (kIOReturnSuccess != ret) { 2446 DKLOG("%s: instantiate failed 0x%x\n", obj->getMetaClass()->getClassName(), ret); 2447 } 2448 } else { 2449 if (kIODKLogIPC & gIODKDebug) { 2450 DKLOG("%s::Dispatch kernel 0x%qx\n", obj->getMetaClass()->getClassName(), message->msgid); 2451 } 2452 ret = obj->Dispatch(rpc); 2453 if (kIODKLogIPC & gIODKDebug) { 2454 DKLOG("%s::Dispatch kernel 0x%qx result 0x%x\n", obj->getMetaClass()->getClassName(), message->msgid, ret); 2455 } 2456 } 2457 2458 return ret; 2459 } 2460 2461 2462 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2463 2464 OSObject * 2465 IOUserServer::target(OSAction * action, IORPCMessage * message) 2466 { 2467 OSObject * object; 2468 2469 if (message->msgid != action->ivars->msgid) { 2470 return action; 2471 } 2472 object = action->ivars->target; 2473 message->msgid = action->ivars->targetmsgid; 2474 message->objects[0] = (OSObjectRef) object; 2475 if (kIORPCMessageRemote & message->flags) { 2476 object->retain(); 2477 #ifndef __clang_analyzer__ 2478 // Hide the release of 'action' from the clang static analyzer to suppress 2479 // an overrelease diagnostic. The analyzer doesn't have a way to express the 2480 // non-standard contract of this method, which is that it releases 'action' when 2481 // the message flags have kIORPCMessageRemote set. 2482 action->release(); 2483 #endif 2484 } 2485 if (kIODKLogIPC & gIODKDebug) { 2486 DKLOG("TARGET %s msg 0x%qx from 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid, action->ivars->msgid); 2487 } 2488 2489 return object; 2490 } 2491 2492 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2493 2494 kern_return_t 2495 uext_server(ipc_kmsg_t requestkmsg, ipc_kmsg_t * pReply) 2496 { 2497 kern_return_t ret; 2498 IORPCMessageMach * msgin; 2499 OSObject * object; 2500 IOUserServer * server; 2501 2502 msgin = (typeof(msgin))ipc_kmsg_msg_header(requestkmsg); 2503 2504 object = IOUserServer::copyObjectForSendRight(msgin->msgh.msgh_remote_port, IKOT_UEXT_OBJECT); 2505 server = OSDynamicCast(IOUserServer, object); 2506 if (!server) { 2507 OSSafeReleaseNULL(object); 2508 return KERN_INVALID_NAME; 2509 } 2510 ret = server->server(requestkmsg, pReply); 2511 object->release(); 2512 2513 return ret; 2514 } 2515 2516 #define MAX_UEXT_REPLY_SIZE 0x17c0 2517 2518 kern_return_t 2519 IOUserServer::server(ipc_kmsg_t requestkmsg, ipc_kmsg_t * pReply) 2520 { 2521 kern_return_t ret; 2522 mach_msg_size_t replyAlloc; 2523 ipc_kmsg_t replykmsg; 2524 IORPCMessageMach * msgin; 2525 IORPCMessage * message; 2526 IORPCMessageMach * msgout; 2527 IORPCMessage * reply; 2528 uint32_t replySize; 2529 OSObject * object; 2530 OSAction * action; 2531 bool oneway; 2532 uint64_t msgid; 2533 2534 msgin = (typeof(msgin))ipc_kmsg_msg_header(requestkmsg); 2535 replyAlloc = 0; 2536 msgout = NULL; 2537 replykmsg = NULL; 2538 2539 if (msgin->msgh.msgh_size < (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))) { 2540 if (kIODKLogIPC & gIODKDebug) { 2541 DKLOG("UEXT notify %o\n", msgin->msgh.msgh_id); 2542 } 2543 return KERN_NOT_SUPPORTED; 2544 } 2545 2546 if (!(MACH_MSGH_BITS_COMPLEX & msgin->msgh.msgh_bits)) { 2547 msgin->msgh_body.msgh_descriptor_count = 0; 2548 } 2549 message = IORPCMessageFromMach(msgin, false); 2550 if (!message) { 2551 return kIOReturnIPCError; 2552 } 2553 if (message->objectRefs == 0) { 2554 return kIOReturnIPCError; 2555 } 2556 ret = copyInObjects(msgin, message, msgin->msgh.msgh_size, true, false); 2557 if (kIOReturnSuccess != ret) { 2558 if (kIODKLogIPC & gIODKDebug) { 2559 DKLOG("UEXT copyin(0x%x) %x\n", ret, msgin->msgh.msgh_id); 2560 } 2561 return KERN_NOT_SUPPORTED; 2562 } 2563 2564 if (msgin->msgh_body.msgh_descriptor_count < 1) { 2565 return KERN_NOT_SUPPORTED; 2566 } 2567 object = (OSObject *) message->objects[0]; 2568 msgid = message->msgid; 2569 message->flags &= ~kIORPCMessageKernel; 2570 message->flags |= kIORPCMessageRemote; 2571 2572 if ((action = OSDynamicCast(OSAction, object))) { 2573 object = target(action, message); 2574 msgid = message->msgid; 2575 } 2576 2577 oneway = (0 != (kIORPCMessageOneway & message->flags)); 2578 assert(oneway || (MACH_PORT_NULL != msgin->msgh.msgh_local_port)); 2579 2580 // includes trailer size 2581 replyAlloc = oneway ? 0 : MAX_UEXT_REPLY_SIZE; 2582 if (replyAlloc) { 2583 replykmsg = ipc_kmsg_alloc(replyAlloc); 2584 if (replykmsg == NULL) { 2585 // printf("uext_server: dropping request\n"); 2586 // ipc_kmsg_trace_send(request, option); 2587 consumeObjects(message, msgin->msgh.msgh_size); 2588 ipc_kmsg_destroy(requestkmsg); 2589 return KERN_MEMORY_FAILURE; 2590 } 2591 2592 msgout = (typeof(msgout))ipc_kmsg_msg_header(replykmsg); 2593 /* 2594 * MIG should really assure no data leakage - 2595 * but until it does, pessimistically zero the 2596 * whole reply buffer. 2597 */ 2598 bzero((void *)msgout, replyAlloc); 2599 } 2600 2601 IORPC rpc = { .message = msgin, .reply = msgout, .sendSize = msgin->msgh.msgh_size, .replySize = replyAlloc }; 2602 2603 if (object) { 2604 thread_iokit_tls_set(0, this); 2605 ret = kernelDispatch(object, rpc); 2606 thread_iokit_tls_set(0, NULL); 2607 } else { 2608 ret = kIOReturnBadArgument; 2609 } 2610 2611 // release objects 2612 consumeObjects(message, msgin->msgh.msgh_size); 2613 2614 // release ports 2615 copyInObjects(msgin, message, msgin->msgh.msgh_size, false, true); 2616 2617 if (!oneway) { 2618 if (kIOReturnSuccess == ret) { 2619 replySize = msgout->msgh.msgh_size; 2620 reply = IORPCMessageFromMach(msgout, true); 2621 if (!reply) { 2622 ret = kIOReturnIPCError; 2623 } else { 2624 ret = copyOutObjects(msgout, reply, replySize, (kIORPCVersionCurrentReply == msgout->msgh.msgh_id) /* =>!InvokeReply */); 2625 } 2626 } 2627 if (kIOReturnSuccess != ret) { 2628 IORPCMessageErrorReturnContent * errorMsg; 2629 2630 msgout->msgh_body.msgh_descriptor_count = 0; 2631 msgout->msgh.msgh_id = kIORPCVersionCurrentReply; 2632 errorMsg = (typeof(errorMsg))IORPCMessageFromMach(msgout, true); 2633 errorMsg->hdr.msgid = message->msgid; 2634 errorMsg->hdr.flags = kIORPCMessageOneway | kIORPCMessageError; 2635 errorMsg->hdr.objectRefs = 0; 2636 errorMsg->result = ret; 2637 errorMsg->pad = 0; 2638 replySize = sizeof(IORPCMessageErrorReturn); 2639 } 2640 2641 msgout->msgh.msgh_bits = MACH_MSGH_BITS_COMPLEX | 2642 MACH_MSGH_BITS_SET(MACH_MSGH_BITS_LOCAL(msgin->msgh.msgh_bits) /*remote*/, 0 /*local*/, 0, 0); 2643 2644 msgout->msgh.msgh_remote_port = msgin->msgh.msgh_local_port; 2645 msgout->msgh.msgh_local_port = MACH_PORT_NULL; 2646 msgout->msgh.msgh_voucher_port = (mach_port_name_t) 0; 2647 msgout->msgh.msgh_reserved = 0; 2648 msgout->msgh.msgh_size = replySize; 2649 } 2650 2651 *pReply = replykmsg; 2652 2653 return oneway ? MIG_NO_REPLY : KERN_SUCCESS; 2654 } 2655 2656 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2657 2658 #define MAX_OBJECT_COUNT(mach, size, message) \ 2659 ((uint32_t)(((((size) + ((uintptr_t) (mach))) - ((uintptr_t) (&message->objects[0]))) / sizeof(OSObjectRef)))) 2660 2661 kern_return_t 2662 IOUserServerUEXTTrap(OSObject * object, void * p1, void * p2, void * p3, void * p4, void * p5, void * p6) 2663 { 2664 const user_addr_t msg = (uintptr_t) p1; 2665 size_t inSize = (uintptr_t) p2; 2666 user_addr_t out = (uintptr_t) p3; 2667 size_t outSize = (uintptr_t) p4; 2668 mach_port_name_t objectName1 = (mach_port_name_t)(uintptr_t) p5; 2669 size_t totalSize; 2670 OSObject * objectArg1; 2671 2672 IORPCMessageMach * mach; 2673 mach_msg_port_descriptor_t * descs; 2674 2675 #pragma pack(4) 2676 struct { 2677 uint32_t pad; 2678 IORPCMessageMach mach; 2679 mach_msg_port_descriptor_t objects[2]; 2680 IOTrapMessageBuffer buffer; 2681 } buffer; 2682 #pragma pack() 2683 2684 IOReturn ret; 2685 OSAction * action; 2686 int copyerr; 2687 IORPCMessage * message; 2688 IORPCMessage * reply; 2689 IORPC rpc; 2690 uint64_t refs; 2691 uint32_t maxObjectCount; 2692 size_t copySize; 2693 uint64_t * replyHdr; 2694 uintptr_t p; 2695 2696 bzero(&buffer, sizeof(buffer)); 2697 2698 p = (typeof(p)) & buffer.buffer[0]; 2699 if (os_add_overflow(inSize, outSize, &totalSize)) { 2700 return kIOReturnMessageTooLarge; 2701 } 2702 if (totalSize > sizeof(buffer.buffer)) { 2703 return kIOReturnMessageTooLarge; 2704 } 2705 if (inSize < sizeof(IORPCMessage)) { 2706 return kIOReturnIPCError; 2707 } 2708 copyerr = copyin(msg, &buffer.buffer[0], inSize); 2709 if (copyerr) { 2710 return kIOReturnVMError; 2711 } 2712 2713 message = (typeof(message))p; 2714 refs = message->objectRefs; 2715 if ((refs > 2) || !refs) { 2716 return kIOReturnUnsupported; 2717 } 2718 if (!(kIORPCMessageSimpleReply & message->flags)) { 2719 return kIOReturnUnsupported; 2720 } 2721 2722 descs = (typeof(descs))(p - refs * sizeof(*descs)); 2723 mach = (typeof(mach))(p - refs * sizeof(*descs) - sizeof(*mach)); 2724 2725 mach->msgh.msgh_id = kIORPCVersionCurrent; 2726 mach->msgh.msgh_size = (mach_msg_size_t) (sizeof(IORPCMessageMach) + refs * sizeof(*descs) + inSize); // totalSize was checked 2727 mach->msgh_body.msgh_descriptor_count = ((mach_msg_size_t) refs); 2728 2729 rpc.message = mach; 2730 rpc.sendSize = mach->msgh.msgh_size; 2731 rpc.reply = (IORPCMessageMach *) (p + inSize); 2732 rpc.replySize = ((uint32_t) (sizeof(buffer.buffer) - inSize)); // inSize was checked 2733 2734 message->objects[0] = 0; 2735 if ((action = OSDynamicCast(OSAction, object))) { 2736 maxObjectCount = MAX_OBJECT_COUNT(rpc.message, rpc.sendSize, message); 2737 if (refs > maxObjectCount) { 2738 return kIOReturnBadArgument; 2739 } 2740 object = IOUserServer::target(action, message); 2741 message->objects[1] = (OSObjectRef) action; 2742 if (kIODKLogIPC & gIODKDebug) { 2743 DKLOG("%s::Dispatch(trap) kernel 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid); 2744 } 2745 ret = object->Dispatch(rpc); 2746 } else { 2747 objectArg1 = NULL; 2748 if (refs > 1) { 2749 if (objectName1) { 2750 objectArg1 = iokit_lookup_uext_ref_current_task(objectName1); 2751 if (!objectArg1) { 2752 return kIOReturnIPCError; 2753 } 2754 } 2755 message->objects[1] = (OSObjectRef) objectArg1; 2756 } 2757 if (kIODKLogIPC & gIODKDebug) { 2758 DKLOG("%s::Dispatch(trap) kernel 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid); 2759 } 2760 ret = object->Dispatch(rpc); 2761 if (kIODKLogIPC & gIODKDebug) { 2762 DKLOG("%s::Dispatch(trap) kernel 0x%qx 0x%x\n", object->getMetaClass()->getClassName(), message->msgid, ret); 2763 } 2764 OSSafeReleaseNULL(objectArg1); 2765 2766 if (kIOReturnSuccess == ret) { 2767 if (rpc.reply->msgh_body.msgh_descriptor_count) { 2768 return kIOReturnIPCError; 2769 } 2770 reply = IORPCMessageFromMach(rpc.reply, rpc.reply->msgh.msgh_size); 2771 if (!reply) { 2772 return kIOReturnIPCError; 2773 } 2774 copySize = rpc.reply->msgh.msgh_size - (((uintptr_t) reply) - ((uintptr_t) rpc.reply)) + sizeof(uint64_t); 2775 if (copySize > outSize) { 2776 return kIOReturnIPCError; 2777 } 2778 replyHdr = (uint64_t *) reply; 2779 replyHdr--; 2780 replyHdr[0] = copySize; 2781 copyerr = copyout(replyHdr, out, copySize); 2782 if (copyerr) { 2783 return kIOReturnVMError; 2784 } 2785 } 2786 } 2787 2788 return ret; 2789 } 2790 2791 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2792 2793 IOReturn 2794 IOUserServer::rpc(IORPC rpc) 2795 { 2796 if (isInactive() && !fRootQueue) { 2797 return kIOReturnOffline; 2798 } 2799 2800 IOReturn ret; 2801 IORPCMessage * message; 2802 IORPCMessageMach * mach; 2803 mach_msg_id_t machid; 2804 uint32_t sendSize, replySize; 2805 bool oneway; 2806 uint64_t msgid; 2807 IODispatchQueue * queue; 2808 IOService * service; 2809 ipc_port_t port; 2810 ipc_port_t sendPort; 2811 2812 queue = NULL; 2813 port = NULL; 2814 sendPort = NULL; 2815 2816 mach = rpc.message; 2817 sendSize = rpc.sendSize; 2818 replySize = rpc.replySize; 2819 2820 assert(sendSize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))); 2821 2822 message = IORPCMessageFromMach(mach, false); 2823 if (!message) { 2824 return kIOReturnIPCError; 2825 } 2826 msgid = message->msgid; 2827 machid = (msgid >> 32); 2828 2829 if (mach->msgh_body.msgh_descriptor_count < 1) { 2830 return kIOReturnNoMedia; 2831 } 2832 2833 IOLockLock(gIOUserServerLock); 2834 if ((service = OSDynamicCast(IOService, (OSObject *) message->objects[0]))) { 2835 queue = queueForObject(service, msgid); 2836 } 2837 if (!queue) { 2838 queue = fRootQueue; 2839 } 2840 if (queue && (kIODispatchQueueStopped != queue)) { 2841 port = queue->ivars->serverPort; 2842 } 2843 if (port) { 2844 sendPort = ipc_port_copy_send(port); 2845 } 2846 IOLockUnlock(gIOUserServerLock); 2847 if (!sendPort) { 2848 return kIOReturnNotReady; 2849 } 2850 2851 oneway = (0 != (kIORPCMessageOneway & message->flags)); 2852 2853 ret = copyOutObjects(mach, message, sendSize, false); 2854 2855 mach->msgh.msgh_bits = MACH_MSGH_BITS_COMPLEX | 2856 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, (oneway ? 0 : MACH_MSG_TYPE_MAKE_SEND_ONCE)); 2857 mach->msgh.msgh_remote_port = sendPort; 2858 mach->msgh.msgh_local_port = (oneway ? MACH_PORT_NULL : mig_get_reply_port()); 2859 mach->msgh.msgh_id = kIORPCVersionCurrent; 2860 mach->msgh.msgh_reserved = 0; 2861 2862 boolean_t message_moved; 2863 2864 if (oneway) { 2865 ret = kernel_mach_msg_send(&mach->msgh, sendSize, 2866 MACH_SEND_MSG | MACH_SEND_ALWAYS | MACH_SEND_NOIMPORTANCE, 2867 0, &message_moved); 2868 } else { 2869 assert(replySize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))); 2870 ret = kernel_mach_msg_rpc(&mach->msgh, sendSize, replySize, FALSE, &message_moved); 2871 } 2872 2873 ipc_port_release_send(sendPort); 2874 2875 if (MACH_MSG_SUCCESS != ret) { 2876 if (kIODKLogIPC & gIODKDebug) { 2877 DKLOG("mach_msg() failed 0x%x\n", ret); 2878 } 2879 if (!message_moved) { 2880 // release ports 2881 copyInObjects(mach, message, sendSize, false, true); 2882 } 2883 } 2884 2885 if ((KERN_SUCCESS == ret) && !oneway) { 2886 if (kIORPCVersionCurrentReply != mach->msgh.msgh_id) { 2887 ret = (MACH_NOTIFY_SEND_ONCE == mach->msgh.msgh_id) ? MIG_SERVER_DIED : MIG_REPLY_MISMATCH; 2888 } else if ((replySize = mach->msgh.msgh_size) < (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))) { 2889 // printf("BAD REPLY SIZE\n"); 2890 ret = MIG_BAD_ARGUMENTS; 2891 } else { 2892 if (!(MACH_MSGH_BITS_COMPLEX & mach->msgh.msgh_bits)) { 2893 mach->msgh_body.msgh_descriptor_count = 0; 2894 } 2895 message = IORPCMessageFromMach(mach, true); 2896 if (!message) { 2897 ret = kIOReturnIPCError; 2898 } else if (message->msgid != msgid) { 2899 // printf("BAD REPLY ID\n"); 2900 ret = MIG_BAD_ARGUMENTS; 2901 } else { 2902 bool isError = (0 != (kIORPCMessageError & message->flags)); 2903 ret = copyInObjects(mach, message, replySize, !isError, true); 2904 if (kIOReturnSuccess != ret) { 2905 if (kIODKLogIPC & gIODKDebug) { 2906 DKLOG("rpc copyin(0x%x) %x\n", ret, mach->msgh.msgh_id); 2907 } 2908 return KERN_NOT_SUPPORTED; 2909 } 2910 if (isError) { 2911 IORPCMessageErrorReturnContent * errorMsg = (typeof(errorMsg))message; 2912 ret = errorMsg->result; 2913 } 2914 } 2915 } 2916 } 2917 2918 return ret; 2919 } 2920 2921 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2922 2923 IORPCMessage * 2924 IORPCMessageFromMach(IORPCMessageMach * msg, bool reply) 2925 { 2926 mach_msg_size_t idx, count; 2927 mach_msg_port_descriptor_t * desc; 2928 mach_msg_port_descriptor_t * maxDesc; 2929 size_t size, msgsize; 2930 bool upgrade; 2931 2932 msgsize = msg->msgh.msgh_size; 2933 count = msg->msgh_body.msgh_descriptor_count; 2934 desc = &msg->objects[0]; 2935 maxDesc = (typeof(maxDesc))(((uintptr_t) msg) + msgsize); 2936 upgrade = (msg->msgh.msgh_id != (reply ? kIORPCVersionCurrentReply : kIORPCVersionCurrent)); 2937 2938 if (upgrade) { 2939 OSReportWithBacktrace("obsolete message"); 2940 return NULL; 2941 } 2942 2943 for (idx = 0; idx < count; idx++) { 2944 if (desc >= maxDesc) { 2945 return NULL; 2946 } 2947 switch (desc->type) { 2948 case MACH_MSG_PORT_DESCRIPTOR: 2949 size = sizeof(mach_msg_port_descriptor_t); 2950 break; 2951 case MACH_MSG_OOL_DESCRIPTOR: 2952 size = sizeof(mach_msg_ool_descriptor_t); 2953 break; 2954 default: 2955 return NULL; 2956 } 2957 desc = (typeof(desc))(((uintptr_t) desc) + size); 2958 } 2959 return (IORPCMessage *)(uintptr_t) desc; 2960 } 2961 2962 ipc_port_t 2963 IOUserServer::copySendRightForObject(OSObject * object, ipc_kobject_type_t type) 2964 { 2965 ipc_port_t port; 2966 ipc_port_t sendPort = NULL; 2967 2968 port = iokit_port_for_object(object, type); 2969 if (port) { 2970 sendPort = ipc_port_make_send(port); 2971 iokit_release_port(port); 2972 } 2973 2974 return sendPort; 2975 } 2976 2977 OSObject * 2978 IOUserServer::copyObjectForSendRight(ipc_port_t port, ipc_kobject_type_t type) 2979 { 2980 OSObject * object; 2981 object = iokit_lookup_io_object(port, type); 2982 return object; 2983 } 2984 2985 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2986 2987 // Create a vm_map_copy_t or kalloc'ed data for memory 2988 // to be copied out. ipc will free after the copyout. 2989 2990 static kern_return_t 2991 copyoutkdata(const void * data, vm_size_t len, void ** buf) 2992 { 2993 kern_return_t err; 2994 vm_map_copy_t copy; 2995 2996 err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len, 2997 false /* src_destroy */, ©); 2998 2999 assert( err == KERN_SUCCESS ); 3000 if (err == KERN_SUCCESS) { 3001 *buf = (char *) copy; 3002 } 3003 3004 return err; 3005 } 3006 3007 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3008 3009 IOReturn 3010 IOUserServer::copyOutObjects(IORPCMessageMach * mach, IORPCMessage * message, 3011 size_t size, bool consume) 3012 { 3013 uint64_t refs; 3014 uint32_t idx, maxObjectCount; 3015 ipc_port_t port; 3016 OSObject * object; 3017 size_t descsize; 3018 mach_msg_port_descriptor_t * desc; 3019 mach_msg_ool_descriptor_t * ool; 3020 vm_map_copy_t copy; 3021 void * address; 3022 mach_msg_size_t length; 3023 kern_return_t kr; 3024 OSSerialize * s; 3025 3026 refs = message->objectRefs; 3027 maxObjectCount = MAX_OBJECT_COUNT(mach, size, message); 3028 // assert(refs <= mach->msgh_body.msgh_descriptor_count); 3029 // assert(refs <= maxObjectCount); 3030 if (refs > mach->msgh_body.msgh_descriptor_count) { 3031 return kIOReturnBadArgument; 3032 } 3033 if (refs > maxObjectCount) { 3034 return kIOReturnBadArgument; 3035 } 3036 3037 desc = &mach->objects[0]; 3038 for (idx = 0; idx < refs; idx++) { 3039 object = (OSObject *) message->objects[idx]; 3040 3041 switch (desc->type) { 3042 case MACH_MSG_PORT_DESCRIPTOR: 3043 descsize = sizeof(mach_msg_port_descriptor_t); 3044 port = NULL; 3045 if (object) { 3046 port = copySendRightForObject(object, IKOT_UEXT_OBJECT); 3047 if (!port) { 3048 break; 3049 } 3050 if (consume) { 3051 object->release(); 3052 } 3053 message->objects[idx] = 0; 3054 } 3055 // desc->type = MACH_MSG_PORT_DESCRIPTOR; 3056 desc->disposition = MACH_MSG_TYPE_MOVE_SEND; 3057 desc->name = port; 3058 desc->pad2 = 0; 3059 desc->pad_end = 0; 3060 break; 3061 3062 case MACH_MSG_OOL_DESCRIPTOR: 3063 descsize = sizeof(mach_msg_ool_descriptor_t); 3064 3065 length = 0; 3066 address = NULL; 3067 if (object) { 3068 s = OSSerialize::binaryWithCapacity(4096); 3069 assert(s); 3070 if (!s) { 3071 break; 3072 } 3073 s->setIndexed(true); 3074 if (!object->serialize(s)) { 3075 assert(false); 3076 descsize = -1UL; 3077 s->release(); 3078 break; 3079 } 3080 length = s->getLength(); 3081 kr = copyoutkdata(s->text(), length, &address); 3082 s->release(); 3083 if (KERN_SUCCESS != kr) { 3084 descsize = -1UL; 3085 address = NULL; 3086 length = 0; 3087 } 3088 if (consume) { 3089 object->release(); 3090 } 3091 message->objects[idx] = 0; 3092 } 3093 ool = (typeof(ool))desc; 3094 // ool->type = MACH_MSG_OOL_DESCRIPTOR; 3095 ool->deallocate = false; 3096 ool->copy = MACH_MSG_PHYSICAL_COPY; 3097 ool->size = length; 3098 ool->address = address; 3099 break; 3100 3101 default: 3102 descsize = -1UL; 3103 break; 3104 } 3105 if (-1UL == descsize) { 3106 break; 3107 } 3108 desc = (typeof(desc))(((uintptr_t) desc) + descsize); 3109 } 3110 3111 if (idx >= refs) { 3112 return kIOReturnSuccess; 3113 } 3114 3115 desc = &mach->objects[0]; 3116 while (idx--) { 3117 switch (desc->type) { 3118 case MACH_MSG_PORT_DESCRIPTOR: 3119 descsize = sizeof(mach_msg_port_descriptor_t); 3120 port = desc->name; 3121 if (port) { 3122 ipc_port_release_send(port); 3123 } 3124 break; 3125 3126 case MACH_MSG_OOL_DESCRIPTOR: 3127 descsize = sizeof(mach_msg_ool_descriptor_t); 3128 ool = (typeof(ool))desc; 3129 copy = (vm_map_copy_t) ool->address; 3130 if (copy) { 3131 vm_map_copy_discard(copy); 3132 } 3133 break; 3134 3135 default: 3136 descsize = -1UL; 3137 break; 3138 } 3139 if (-1UL == descsize) { 3140 break; 3141 } 3142 desc = (typeof(desc))(((uintptr_t) desc) + descsize); 3143 } 3144 3145 return kIOReturnBadArgument; 3146 } 3147 3148 IOReturn 3149 IOUserServer::copyInObjects(IORPCMessageMach * mach, IORPCMessage * message, 3150 size_t size, bool copyObjects, bool consumePorts) 3151 { 3152 uint64_t refs; 3153 uint32_t idx, maxObjectCount; 3154 ipc_port_t port; 3155 OSObject * object; 3156 size_t descsize; 3157 mach_msg_port_descriptor_t * desc; 3158 mach_msg_ool_descriptor_t * ool; 3159 vm_map_address_t copyoutdata; 3160 kern_return_t kr; 3161 3162 refs = message->objectRefs; 3163 maxObjectCount = MAX_OBJECT_COUNT(mach, size, message); 3164 // assert(refs <= mach->msgh_body.msgh_descriptor_count); 3165 // assert(refs <= maxObjectCount); 3166 if (refs > mach->msgh_body.msgh_descriptor_count) { 3167 return kIOReturnBadArgument; 3168 } 3169 if (refs > maxObjectCount) { 3170 return kIOReturnBadArgument; 3171 } 3172 3173 desc = &mach->objects[0]; 3174 for (idx = 0; idx < refs; idx++) { 3175 switch (desc->type) { 3176 case MACH_MSG_PORT_DESCRIPTOR: 3177 descsize = sizeof(mach_msg_port_descriptor_t); 3178 3179 object = NULL; 3180 port = desc->name; 3181 if (port) { 3182 if (copyObjects) { 3183 object = copyObjectForSendRight(port, IKOT_UEXT_OBJECT); 3184 if (!object) { 3185 descsize = -1UL; 3186 break; 3187 } 3188 } 3189 if (consumePorts) { 3190 ipc_port_release_send(port); 3191 } 3192 } 3193 break; 3194 3195 case MACH_MSG_OOL_DESCRIPTOR: 3196 descsize = sizeof(mach_msg_ool_descriptor_t); 3197 ool = (typeof(ool))desc; 3198 3199 object = NULL; 3200 if (copyObjects && ool->size && ool->address) { 3201 kr = vm_map_copyout(kernel_map, ©outdata, (vm_map_copy_t) ool->address); 3202 if (KERN_SUCCESS == kr) { 3203 object = OSUnserializeXML((const char *) copyoutdata, ool->size); 3204 // vm_map_copyout() has consumed the vm_map_copy_t in the message 3205 ool->size = 0; 3206 ool->address = NULL; 3207 kr = vm_deallocate(kernel_map, copyoutdata, ool->size); 3208 assert(KERN_SUCCESS == kr); 3209 } 3210 if (!object) { 3211 descsize = -1UL; 3212 break; 3213 } 3214 } 3215 break; 3216 3217 default: 3218 descsize = -1UL; 3219 break; 3220 } 3221 if (-1UL == descsize) { 3222 break; 3223 } 3224 if (copyObjects) { 3225 message->objects[idx] = (OSObjectRef) object; 3226 } 3227 desc = (typeof(desc))(((uintptr_t) desc) + descsize); 3228 } 3229 3230 if (idx >= refs) { 3231 return kIOReturnSuccess; 3232 } 3233 3234 while (idx--) { 3235 object = (OSObject *) message->objects[idx]; 3236 object->release(); 3237 message->objects[idx] = 0; 3238 } 3239 3240 return kIOReturnBadArgument; 3241 } 3242 3243 IOReturn 3244 IOUserServer::consumeObjects(IORPCMessage * message, size_t messageSize) 3245 { 3246 uint64_t refs, idx; 3247 OSObject * object; 3248 3249 refs = message->objectRefs; 3250 for (idx = 0; idx < refs; idx++) { 3251 object = (OSObject *) message->objects[idx]; 3252 if (object) { 3253 object->release(); 3254 message->objects[idx] = 0; 3255 } 3256 } 3257 3258 return kIOReturnSuccess; 3259 } 3260 3261 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3262 3263 bool 3264 IOUserServer::finalize(IOOptionBits options) 3265 { 3266 OSArray * services; 3267 3268 if (kIODKLogSetup & gIODKDebug) { 3269 DKLOG("%s::finalize(%p)\n", getName(), this); 3270 } 3271 3272 IOLockLock(gIOUserServerLock); 3273 OSSafeReleaseNULL(fRootQueue); 3274 IOLockUnlock(gIOUserServerLock); 3275 3276 services = NULL; 3277 IOLockLock(fLock); 3278 if (fServices) { 3279 services = OSArray::withArray(fServices); 3280 } 3281 IOLockUnlock(fLock); 3282 3283 if (services) { 3284 services->iterateObjects(^bool (OSObject * obj) { 3285 IOService * service; 3286 IOService * provider; 3287 bool started = false; 3288 3289 service = (IOService *) obj; 3290 if (kIODKLogSetup & gIODKDebug) { 3291 DKLOG("%s::terminate(" DKS ")\n", getName(), DKN(service)); 3292 } 3293 if (service->reserved->uvars) { 3294 started = service->reserved->uvars->started; 3295 service->reserved->uvars->serverDied = true; 3296 if (started) { 3297 provider = service->getProvider(); 3298 serviceDidStop(service, provider); 3299 service->terminate(kIOServiceTerminateNeedWillTerminate | kIOServiceTerminateWithRematch); 3300 } 3301 } 3302 if (!started) { 3303 DKLOG("%s::terminate(" DKS ") server exit before start()\n", getName(), DKN(service)); 3304 serviceStop(service, NULL); 3305 } 3306 return false; 3307 }); 3308 services->release(); 3309 } 3310 3311 return IOUserClient::finalize(options); 3312 } 3313 3314 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3315 3316 #undef super 3317 #define super IOUserClient 3318 3319 OSDefineMetaClassAndStructors(IOUserServer, IOUserClient) 3320 3321 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3322 3323 IOUserClient * IOUserServer::withTask(task_t owningTask) 3324 { 3325 IOUserServer * inst; 3326 3327 inst = new IOUserServer; 3328 if (inst && !inst->init()) { 3329 inst->release(); 3330 inst = NULL; 3331 return inst; 3332 } 3333 inst->PMinit(); 3334 3335 inst->fOwningTask = current_task(); 3336 inst->fEntitlements = IOUserClient::copyClientEntitlements(inst->fOwningTask); 3337 3338 if (!(kIODKDisableEntitlementChecking & gIODKDebug)) { 3339 if (!inst->fEntitlements || !inst->fEntitlements->getObject(gIODriverKitEntitlementKey)) { 3340 proc_t p; 3341 pid_t pid; 3342 3343 p = (proc_t)get_bsdtask_info(inst->fOwningTask); 3344 if (p) { 3345 pid = proc_pid(p); 3346 IOLog(kIODriverKitEntitlementKey " entitlement check failed for %s[%d]\n", proc_best_name(p), pid); 3347 } 3348 inst->release(); 3349 inst = NULL; 3350 return inst; 3351 } 3352 } 3353 3354 /* Mark the current task's space as eligible for uext object ports */ 3355 iokit_label_dext_task(inst->fOwningTask); 3356 3357 inst->fLock = IOLockAlloc(); 3358 inst->fServices = OSArray::withCapacity(4); 3359 inst->fClasses = OSDictionary::withCapacity(16); 3360 inst->fClasses->setOptions(OSCollection::kSort, OSCollection::kSort); 3361 3362 return inst; 3363 } 3364 3365 IOReturn 3366 IOUserServer::clientClose(void) 3367 { 3368 terminate(); 3369 return kIOReturnSuccess; 3370 } 3371 3372 IOReturn 3373 IOUserServer::setProperties(OSObject * properties) 3374 { 3375 IOReturn kr = kIOReturnUnsupported; 3376 return kr; 3377 } 3378 3379 void 3380 IOUserServer::stop(IOService * provider) 3381 { 3382 fOwningTask = TASK_NULL; 3383 3384 PMstop(); 3385 3386 IOServicePH::serverRemove(this); 3387 3388 OSSafeReleaseNULL(fRootQueue); 3389 3390 if (fInterruptLock) { 3391 IOSimpleLockFree(fInterruptLock); 3392 } 3393 } 3394 3395 void 3396 IOUserServer::free() 3397 { 3398 OSSafeReleaseNULL(fEntitlements); 3399 OSSafeReleaseNULL(fClasses); 3400 if (fLock) { 3401 IOLockFree(fLock); 3402 } 3403 OSSafeReleaseNULL(fServices); 3404 OSSafeReleaseNULL(fCheckInToken); 3405 IOUserClient::free(); 3406 } 3407 3408 IOReturn 3409 IOUserServer::registerClass(OSClassDescription * desc, uint32_t size, OSUserMetaClass ** pCls) 3410 { 3411 OSUserMetaClass * cls; 3412 const OSSymbol * sym; 3413 uint64_t * methodOptions; 3414 const char * queueNames; 3415 uint32_t methodOptionsEnd, queueNamesEnd; 3416 IOReturn ret = kIOReturnSuccess; 3417 3418 if (size < sizeof(OSClassDescription)) { 3419 assert(false); 3420 return kIOReturnBadArgument; 3421 } 3422 3423 if (kIODKLogSetup & gIODKDebug) { 3424 DKLOG("%s::registerClass %s, %d, %d\n", getName(), desc->name, desc->queueNamesSize, desc->methodNamesSize); 3425 } 3426 3427 if (desc->descriptionSize != size) { 3428 assert(false); 3429 return kIOReturnBadArgument; 3430 } 3431 if (os_add_overflow(desc->queueNamesOffset, desc->queueNamesSize, &queueNamesEnd)) { 3432 assert(false); 3433 return kIOReturnBadArgument; 3434 } 3435 if (queueNamesEnd > size) { 3436 assert(false); 3437 return kIOReturnBadArgument; 3438 } 3439 if (os_add_overflow(desc->methodOptionsOffset, desc->methodOptionsSize, &methodOptionsEnd)) { 3440 assert(false); 3441 return kIOReturnBadArgument; 3442 } 3443 if (methodOptionsEnd > size) { 3444 assert(false); 3445 return kIOReturnBadArgument; 3446 } 3447 // overlaps? 3448 if ((desc->queueNamesOffset >= desc->methodOptionsOffset) && (desc->queueNamesOffset < methodOptionsEnd)) { 3449 assert(false); 3450 return kIOReturnBadArgument; 3451 } 3452 if ((queueNamesEnd >= desc->methodOptionsOffset) && (queueNamesEnd < methodOptionsEnd)) { 3453 assert(false); 3454 return kIOReturnBadArgument; 3455 } 3456 3457 if (desc->methodOptionsSize & ((2 * sizeof(uint64_t)) - 1)) { 3458 assert(false); 3459 return kIOReturnBadArgument; 3460 } 3461 if (sizeof(desc->name) == strnlen(desc->name, sizeof(desc->name))) { 3462 assert(false); 3463 return kIOReturnBadArgument; 3464 } 3465 if (sizeof(desc->superName) == strnlen(desc->superName, sizeof(desc->superName))) { 3466 assert(false); 3467 return kIOReturnBadArgument; 3468 } 3469 3470 cls = OSTypeAlloc(OSUserMetaClass); 3471 assert(cls); 3472 if (!cls) { 3473 return kIOReturnNoMemory; 3474 } 3475 3476 cls->description = (typeof(cls->description))IOMalloc(size); 3477 assert(cls->description); 3478 if (!cls->description) { 3479 assert(false); 3480 cls->release(); 3481 return kIOReturnNoMemory; 3482 } 3483 bcopy(desc, cls->description, size); 3484 3485 cls->methodCount = desc->methodOptionsSize / (2 * sizeof(uint64_t)); 3486 cls->methods = IONew(uint64_t, 2 * cls->methodCount); 3487 if (!cls->methods) { 3488 assert(false); 3489 cls->release(); 3490 return kIOReturnNoMemory; 3491 } 3492 3493 methodOptions = (typeof(methodOptions))(((uintptr_t) desc) + desc->methodOptionsOffset); 3494 bcopy(methodOptions, cls->methods, 2 * cls->methodCount * sizeof(uint64_t)); 3495 3496 queueNames = (typeof(queueNames))(((uintptr_t) desc) + desc->queueNamesOffset); 3497 cls->queueNames = copyInStringArray(queueNames, desc->queueNamesSize); 3498 3499 sym = OSSymbol::withCString(desc->name); 3500 assert(sym); 3501 if (!sym) { 3502 assert(false); 3503 cls->release(); 3504 return kIOReturnNoMemory; 3505 } 3506 3507 cls->name = sym; 3508 cls->meta = OSMetaClass::copyMetaClassWithName(sym); 3509 IOLockLock(fLock); 3510 cls->superMeta = OSDynamicCast(OSUserMetaClass, fClasses->getObject(desc->superName)); 3511 if (fClasses->getObject(sym) != NULL) { 3512 /* class with this name exists */ 3513 ret = kIOReturnBadArgument; 3514 } else { 3515 if (fClasses->setObject(sym, cls)) { 3516 *pCls = cls; 3517 } else { 3518 /* could not add class to fClasses */ 3519 ret = kIOReturnNoMemory; 3520 } 3521 } 3522 IOLockUnlock(fLock); 3523 cls->release(); 3524 return ret; 3525 } 3526 3527 IOReturn 3528 IOUserServer::registerClass(OSClassDescription * desc, uint32_t size, OSSharedPtr<OSUserMetaClass>& pCls) 3529 { 3530 OSUserMetaClass* pClsRaw = NULL; 3531 IOReturn result = registerClass(desc, size, &pClsRaw); 3532 if (result == kIOReturnSuccess) { 3533 pCls.reset(pClsRaw, OSRetain); 3534 } 3535 return result; 3536 } 3537 3538 IOReturn 3539 IOUserServer::setRootQueue(IODispatchQueue * queue) 3540 { 3541 assert(!fRootQueue); 3542 if (fRootQueue) { 3543 return kIOReturnStillOpen; 3544 } 3545 queue->retain(); 3546 fRootQueue = queue; 3547 3548 return kIOReturnSuccess; 3549 } 3550 3551 IOReturn 3552 IOUserServer::externalMethod(uint32_t selector, IOExternalMethodArguments * args, 3553 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) 3554 { 3555 IOReturn ret = kIOReturnBadArgument; 3556 mach_port_name_t portname; 3557 3558 switch (selector) { 3559 case kIOUserServerMethodRegisterClass: 3560 { 3561 OSUserMetaClass * cls; 3562 if (!args->structureInputSize) { 3563 return kIOReturnBadArgument; 3564 } 3565 if (args->scalarOutputCount != 2) { 3566 return kIOReturnBadArgument; 3567 } 3568 ret = registerClass((OSClassDescription *) args->structureInput, args->structureInputSize, &cls); 3569 if (kIOReturnSuccess == ret) { 3570 portname = iokit_make_send_right(fOwningTask, cls, IKOT_UEXT_OBJECT); 3571 assert(portname); 3572 args->scalarOutput[0] = portname; 3573 args->scalarOutput[1] = kOSObjectRPCRemote; 3574 } 3575 break; 3576 } 3577 case kIOUserServerMethodStart: 3578 { 3579 if (args->scalarOutputCount != 1) { 3580 return kIOReturnBadArgument; 3581 } 3582 if (!(kIODKDisableCheckInTokenVerification & gIODKDebug)) { 3583 if (args->scalarInputCount != 1) { 3584 return kIOReturnBadArgument; 3585 } 3586 mach_port_name_t checkInPortName = ((typeof(checkInPortName))args->scalarInput[0]); 3587 OSObject * obj = iokit_lookup_object_with_port_name(checkInPortName, IKOT_IOKIT_IDENT, fOwningTask); 3588 IOUserServerCheckInToken * retrievedToken = OSDynamicCast(IOUserServerCheckInToken, obj); 3589 if (retrievedToken != NULL) { 3590 setCheckInToken(retrievedToken); 3591 } else { 3592 OSSafeReleaseNULL(obj); 3593 return kIOReturnBadArgument; 3594 } 3595 OSSafeReleaseNULL(obj); 3596 } 3597 portname = iokit_make_send_right(fOwningTask, this, IKOT_UEXT_OBJECT); 3598 assert(portname); 3599 args->scalarOutput[0] = portname; 3600 ret = kIOReturnSuccess; 3601 break; 3602 } 3603 default: 3604 break; 3605 } 3606 3607 return ret; 3608 } 3609 3610 IOExternalTrap * 3611 IOUserServer::getTargetAndTrapForIndex( IOService **targetP, UInt32 index ) 3612 { 3613 static const IOExternalTrap trapTemplate[] = { 3614 { NULL, (IOTrap) & IOUserServer::waitInterruptTrap}, 3615 }; 3616 if (index >= (sizeof(trapTemplate) / sizeof(IOExternalTrap))) { 3617 return NULL; 3618 } 3619 *targetP = this; 3620 return (IOExternalTrap *)&trapTemplate[index]; 3621 } 3622 3623 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3624 3625 IOReturn 3626 IOUserServer::serviceAttach(IOService * service, IOService * provider) 3627 { 3628 IOReturn ret; 3629 OSObjectUserVars * vars; 3630 OSObject * prop; 3631 OSString * str; 3632 OSSymbol const* bundleID; 3633 char execPath[1024]; 3634 3635 vars = IONewZero(OSObjectUserVars, 1); 3636 service->reserved->uvars = vars; 3637 3638 vars->userServer = this; 3639 vars->userServer->retain(); 3640 IOLockLock(fLock); 3641 if (-1U == fServices->getNextIndexOfObject(service, 0)) { 3642 fServices->setObject(service); 3643 } 3644 IOLockUnlock(fLock); 3645 3646 prop = service->copyProperty(gIOUserClassKey); 3647 str = OSDynamicCast(OSString, prop); 3648 if (str) { 3649 service->setName(str); 3650 } 3651 OSSafeReleaseNULL(prop); 3652 3653 prop = service->copyProperty(gIOModuleIdentifierKey); 3654 bundleID = OSDynamicCast(OSSymbol, prop); 3655 if (bundleID) { 3656 execPath[0] = 0; 3657 bool ok = OSKext::copyUserExecutablePath(bundleID, execPath, sizeof(execPath)); 3658 if (ok) { 3659 ret = LoadModule(execPath); 3660 if (kIODKLogSetup & gIODKDebug) { 3661 DKLOG("%s::LoadModule 0x%x %s\n", getName(), ret, execPath); 3662 } 3663 } 3664 } 3665 OSSafeReleaseNULL(prop); 3666 3667 ret = kIOReturnSuccess; 3668 3669 return ret; 3670 } 3671 3672 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3673 3674 #define kDriverKitUCPrefix "com.apple.developer.driverkit.userclient-access." 3675 3676 IOReturn 3677 IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void * securityID, 3678 uint32_t type, OSDictionary * properties, IOUserClient ** handler) 3679 { 3680 IOReturn ret; 3681 IOUserClient * uc; 3682 IOUserUserClient * userUC; 3683 OSDictionary * entitlements; 3684 OSObject * prop; 3685 OSObject * bundleID; 3686 bool ok; 3687 3688 *handler = NULL; 3689 ret = service->NewUserClient(type, &uc); 3690 if (kIOReturnSuccess != ret) { 3691 return ret; 3692 } 3693 userUC = OSDynamicCast(IOUserUserClient, uc); 3694 if (!userUC) { 3695 uc->terminate(); 3696 OSSafeReleaseNULL(uc); 3697 return kIOReturnUnsupported; 3698 } 3699 userUC->setTask(owningTask); 3700 3701 if (!(kIODKDisableEntitlementChecking & gIODKDebug)) { 3702 bundleID = NULL; 3703 entitlements = NULL; 3704 if (fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowAnyKey)) { 3705 ok = true; 3706 } else { 3707 entitlements = IOUserClient::copyClientEntitlements(owningTask); 3708 bundleID = service->copyProperty(gIOModuleIdentifierKey); 3709 ok = (entitlements 3710 && bundleID 3711 && (prop = entitlements->getObject(gIODriverKitUserClientEntitlementsKey))); 3712 if (ok) { 3713 bool found __block = false; 3714 ok = prop->iterateObjects(^bool (OSObject * object) { 3715 found = object->isEqualTo(bundleID); 3716 return found; 3717 }); 3718 ok = found; 3719 } 3720 } 3721 if (ok) { 3722 prop = userUC->copyProperty(gIOServiceDEXTEntitlementsKey); 3723 ok = checkEntitlements(entitlements, prop, NULL, NULL); 3724 } 3725 OSSafeReleaseNULL(bundleID); 3726 OSSafeReleaseNULL(entitlements); 3727 if (!ok) { 3728 DKLOG(DKS ":UC entitlements check failed\n", DKN(userUC)); 3729 uc->terminate(); 3730 OSSafeReleaseNULL(uc); 3731 return kIOReturnNotPermitted; 3732 } 3733 } 3734 3735 *handler = userUC; 3736 3737 return ret; 3738 } 3739 3740 IOReturn 3741 IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void * securityID, 3742 uint32_t type, OSDictionary * properties, OSSharedPtr<IOUserClient>& handler) 3743 { 3744 IOUserClient* handlerRaw = NULL; 3745 IOReturn result = serviceNewUserClient(service, owningTask, securityID, type, properties, &handlerRaw); 3746 handler.reset(handlerRaw, OSNoRetain); 3747 return result; 3748 } 3749 3750 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3751 3752 static IOPMPowerState 3753 sPowerStates[] = { 3754 { .version = kIOPMPowerStateVersion1, 3755 .capabilityFlags = 0, 3756 .outputPowerCharacter = 0, 3757 .inputPowerRequirement = 0}, 3758 { .version = kIOPMPowerStateVersion1, 3759 .capabilityFlags = kIOPMLowPower, 3760 .outputPowerCharacter = kIOPMLowPower, 3761 .inputPowerRequirement = kIOPMLowPower}, 3762 { .version = kIOPMPowerStateVersion1, 3763 .capabilityFlags = kIOPMPowerOn, 3764 .outputPowerCharacter = kIOPMPowerOn, 3765 .inputPowerRequirement = kIOPMPowerOn}, 3766 }; 3767 3768 IOReturn 3769 IOUserServer::setPowerState(unsigned long state, IOService * service) 3770 { 3771 if (kIODKLogPM & gIODKDebug) { 3772 DKLOG(DKS "::setPowerState(%ld) %d\n", DKN(service), state, fSystemPowerAck); 3773 } 3774 return kIOPMAckImplied; 3775 } 3776 3777 IOReturn 3778 IOUserServer::serviceSetPowerState(IOService * controllingDriver, IOService * service, IOPMPowerFlags flags, unsigned long state) 3779 { 3780 IOReturn ret; 3781 3782 if (service->reserved->uvars) { 3783 if (!fSystemOff && !(kIODKDisablePM & gIODKDebug)) { 3784 service->reserved->uvars->willPower = true; 3785 service->reserved->uvars->willPowerState = state; 3786 service->reserved->uvars->controllingDriver = controllingDriver; 3787 if (kIODKLogPM & gIODKDebug) { 3788 DKLOG(DKS "::serviceSetPowerState(%ld) 0x%qx, %d\n", DKN(service), state, fPowerStates, fSystemPowerAck); 3789 } 3790 ret = service->SetPowerState((uint32_t) flags); 3791 if (kIOReturnSuccess == ret) { 3792 return 20 * 1000 * 1000; 3793 } 3794 } 3795 service->reserved->uvars->willPower = false; 3796 } 3797 3798 return kIOPMAckImplied; 3799 } 3800 3801 IOReturn 3802 IOUserServer::powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service) 3803 { 3804 return kIOPMAckImplied; 3805 } 3806 3807 IOReturn 3808 IOUserServer::powerStateDidChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service) 3809 { 3810 unsigned int idx; 3811 bool pmAck; 3812 3813 pmAck = false; 3814 IOLockLock(fLock); 3815 idx = fServices->getNextIndexOfObject(service, 0); 3816 if (-1U == idx) { 3817 IOLockUnlock(fLock); 3818 return kIOPMAckImplied; 3819 } 3820 assert(idx <= 63); 3821 3822 if (state) { 3823 fPowerStates |= (1ULL << idx); 3824 } else { 3825 fPowerStates &= ~(1ULL << idx); 3826 } 3827 if (kIODKLogPM & gIODKDebug) { 3828 DKLOG(DKS "::powerStateDidChangeTo(%ld) 0x%qx, %d\n", DKN(service), state, fPowerStates, fSystemPowerAck); 3829 } 3830 if (!fPowerStates && (pmAck = fSystemPowerAck)) { 3831 fSystemPowerAck = false; 3832 fSystemOff = true; 3833 } 3834 IOLockUnlock(fLock); 3835 3836 if (pmAck) { 3837 IOServicePH::serverAck(this); 3838 } 3839 3840 return kIOPMAckImplied; 3841 } 3842 3843 kern_return_t 3844 IOService::SetPowerState_Impl( 3845 uint32_t powerFlags) 3846 { 3847 if (kIODKLogPM & gIODKDebug) { 3848 DKLOG(DKS "::SetPowerState(%d), %d\n", DKN(this), powerFlags, reserved->uvars->willPower); 3849 } 3850 if (reserved->uvars 3851 && reserved->uvars->userServer 3852 && reserved->uvars->willPower) { 3853 IOReturn ret; 3854 reserved->uvars->willPower = false; 3855 ret = reserved->uvars->controllingDriver->setPowerState(reserved->uvars->willPowerState, this); 3856 if (kIOPMAckImplied == ret) { 3857 acknowledgeSetPowerState(); 3858 } 3859 return kIOReturnSuccess; 3860 } 3861 return kIOReturnNotReady; 3862 } 3863 3864 kern_return_t 3865 IOService::ChangePowerState_Impl( 3866 uint32_t powerFlags) 3867 { 3868 switch (powerFlags) { 3869 case kIOServicePowerCapabilityOff: 3870 changePowerStateToPriv(0); 3871 break; 3872 case kIOServicePowerCapabilityLow: 3873 changePowerStateToPriv(1); 3874 break; 3875 case kIOServicePowerCapabilityOn: 3876 changePowerStateToPriv(2); 3877 break; 3878 default: 3879 return kIOReturnBadArgument; 3880 } 3881 3882 return kIOReturnSuccess; 3883 } 3884 3885 kern_return_t 3886 IOService::Create_Impl( 3887 IOService * provider, 3888 const char * propertiesKey, 3889 IOService ** result) 3890 { 3891 OSObject * inst; 3892 IOService * service; 3893 OSString * str; 3894 const OSSymbol * sym; 3895 OSObject * prop; 3896 OSDictionary * properties; 3897 kern_return_t ret; 3898 3899 if (provider != this) { 3900 return kIOReturnUnsupported; 3901 } 3902 3903 ret = kIOReturnUnsupported; 3904 inst = NULL; 3905 service = NULL; 3906 3907 prop = copyProperty(propertiesKey); 3908 properties = OSDynamicCast(OSDictionary, prop); 3909 assert(properties); 3910 if (properties) { 3911 str = OSDynamicCast(OSString, properties->getObject(gIOClassKey)); 3912 assert(str); 3913 sym = OSSymbol::withString(str); 3914 if (sym) { 3915 inst = OSMetaClass::allocClassWithName(sym); 3916 service = OSDynamicCast(IOService, inst); 3917 if (service && service->init(properties) && service->attach(this)) { 3918 reserved->uvars->userServer->serviceAttach(service, this); 3919 service->reserved->uvars->started = true; 3920 ret = kIOReturnSuccess; 3921 *result = service; 3922 } 3923 OSSafeReleaseNULL(sym); 3924 } 3925 } 3926 3927 OSSafeReleaseNULL(prop); 3928 if (kIOReturnSuccess != ret) { 3929 OSSafeReleaseNULL(inst); 3930 } 3931 3932 return ret; 3933 } 3934 3935 kern_return_t 3936 IOService::Terminate_Impl( 3937 uint64_t options) 3938 { 3939 IOUserServer * us; 3940 3941 if (options) { 3942 return kIOReturnUnsupported; 3943 } 3944 3945 us = (typeof(us))thread_iokit_tls_get(0); 3946 if (!reserved->uvars 3947 || (reserved->uvars->userServer != us)) { 3948 return kIOReturnNotPermitted; 3949 } 3950 terminate(kIOServiceTerminateNeedWillTerminate); 3951 3952 return kIOReturnSuccess; 3953 } 3954 3955 kern_return_t 3956 IOService::NewUserClient_Impl( 3957 uint32_t type, 3958 IOUserClient ** userClient) 3959 { 3960 return kIOReturnError; 3961 } 3962 3963 kern_return_t 3964 IOService::SearchProperty_Impl( 3965 const char * name, 3966 const char * plane, 3967 uint64_t options, 3968 OSContainer ** property) 3969 { 3970 OSObject * object; 3971 IOOptionBits regOptions; 3972 3973 if (kIOServiceSearchPropertyParents & options) { 3974 regOptions = kIORegistryIterateParents | kIORegistryIterateRecursively; 3975 } else { 3976 regOptions = 0; 3977 } 3978 3979 object = copyProperty(name, IORegistryEntry::getPlane(plane), regOptions); 3980 *property = object; 3981 3982 return object ? kIOReturnSuccess : kIOReturnNotFound; 3983 } 3984 3985 kern_return_t 3986 IOService::CopyProviderProperties_Impl( 3987 OSArray * propertyKeys, 3988 OSArray ** properties) 3989 { 3990 IOReturn ret; 3991 OSArray * result; 3992 IOService * provider; 3993 3994 result = OSArray::withCapacity(8); 3995 if (!result) { 3996 return kIOReturnNoMemory; 3997 } 3998 3999 ret = kIOReturnSuccess; 4000 for (provider = this; provider; provider = provider->getProvider()) { 4001 OSObject * obj; 4002 OSDictionary * props; 4003 4004 obj = provider->copyProperty(gIOSupportedPropertiesKey); 4005 props = OSDynamicCast(OSDictionary, obj); 4006 if (!props) { 4007 OSSafeReleaseNULL(obj); 4008 props = provider->dictionaryWithProperties(); 4009 } 4010 if (!props) { 4011 ret = kIOReturnNoMemory; 4012 break; 4013 } 4014 bool __block addClass = true; 4015 if (propertyKeys) { 4016 OSDictionary * retProps; 4017 retProps = OSDictionary::withCapacity(4); 4018 addClass = false; 4019 if (!retProps) { 4020 ret = kIOReturnNoMemory; 4021 break; 4022 } 4023 propertyKeys->iterateObjects(^bool (OSObject * _key) { 4024 OSString * key = OSDynamicCast(OSString, _key); 4025 if (gIOClassKey->isEqualTo(key)) { 4026 addClass = true; 4027 return false; 4028 } 4029 retProps->setObject(key, props->getObject(key)); 4030 return false; 4031 }); 4032 OSSafeReleaseNULL(props); 4033 props = retProps; 4034 } 4035 if (addClass) { 4036 OSArray * classes = OSArray::withCapacity(8); 4037 if (!classes) { 4038 ret = kIOReturnNoMemory; 4039 break; 4040 } 4041 for (const OSMetaClass * meta = provider->getMetaClass(); meta; meta = meta->getSuperClass()) { 4042 classes->setObject(meta->getClassNameSymbol()); 4043 } 4044 props->setObject(gIOClassKey, classes); 4045 OSSafeReleaseNULL(classes); 4046 } 4047 bool ok = result->setObject(props); 4048 props->release(); 4049 if (!ok) { 4050 ret = kIOReturnNoMemory; 4051 break; 4052 } 4053 } 4054 if (kIOReturnSuccess != ret) { 4055 OSSafeReleaseNULL(result); 4056 } 4057 *properties = result; 4058 return ret; 4059 } 4060 4061 void 4062 IOUserServer::systemPower(bool powerOff) 4063 { 4064 OSArray * services; 4065 4066 if (kIODKLogPM & gIODKDebug) { 4067 DKLOG("%s::powerOff(%d) 0x%qx\n", getName(), powerOff, fPowerStates); 4068 } 4069 4070 IOLockLock(fLock); 4071 services = OSArray::withArray(fServices); 4072 4073 if (powerOff) { 4074 fSystemPowerAck = (0 != fPowerStates); 4075 if (!fSystemPowerAck) { 4076 fSystemOff = true; 4077 } 4078 IOLockUnlock(fLock); 4079 4080 if (!fSystemPowerAck) { 4081 IOServicePH::serverAck(this); 4082 } else { 4083 if (services) { 4084 services->iterateObjects(^bool (OSObject * obj) { 4085 IOService * service; 4086 service = (IOService *) obj; 4087 if (kIODKLogPM & gIODKDebug) { 4088 DKLOG("changePowerStateWithOverrideTo(" DKS ", %d)\n", DKN(service), 0); 4089 } 4090 service->reserved->uvars->powerOverride = service->getPowerState(); 4091 service->changePowerStateWithOverrideTo(0, 0); 4092 return false; 4093 }); 4094 } 4095 } 4096 } else { 4097 fSystemOff = false; 4098 IOLockUnlock(fLock); 4099 if (services) { 4100 services->iterateObjects(^bool (OSObject * obj) { 4101 IOService * service; 4102 service = (IOService *) obj; 4103 if (-1U != service->reserved->uvars->powerOverride) { 4104 if (kIODKLogPM & gIODKDebug) { 4105 DKLOG("changePowerStateWithOverrideTo(" DKS ", %d)\n", DKN(service), service->reserved->uvars->powerOverride); 4106 } 4107 service->changePowerStateWithOverrideTo(service->reserved->uvars->powerOverride, 0); 4108 service->reserved->uvars->powerOverride = -1U; 4109 } 4110 return false; 4111 }); 4112 } 4113 } 4114 OSSafeReleaseNULL(services); 4115 } 4116 4117 4118 4119 IOReturn 4120 IOUserServer::serviceStarted(IOService * service, IOService * provider, bool result) 4121 { 4122 IOReturn ret; 4123 IOService * pmProvider; 4124 bool joinTree; 4125 4126 DKLOG(DKS "::start(" DKS ") %s\n", DKN(service), DKN(provider), result ? "ok" : "fail"); 4127 4128 if (!result) { 4129 ret = kIOReturnSuccess; 4130 return ret; 4131 } 4132 4133 if (!fRootNotifier) { 4134 ret = registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0])); 4135 assert(kIOReturnSuccess == ret); 4136 IOServicePH::serverAdd(this); 4137 fRootNotifier = true; 4138 } 4139 4140 joinTree = false; 4141 if (!(kIODKDisablePM & gIODKDebug) && !service->pm_vars) { 4142 service->PMinit(); 4143 ret = service->registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0])); 4144 assert(kIOReturnSuccess == ret); 4145 joinTree = true; 4146 } 4147 4148 pmProvider = service; 4149 while (pmProvider && !pmProvider->inPlane(gIOPowerPlane)) { 4150 pmProvider = pmProvider->getProvider(); 4151 } 4152 if (pmProvider) { 4153 OSObject * prop; 4154 OSString * str; 4155 prop = pmProvider->copyProperty("non-removable"); 4156 if (prop) { 4157 str = OSDynamicCast(OSString, prop); 4158 if (str && str->isEqualTo("yes")) { 4159 pmProvider = NULL; 4160 } 4161 prop->release(); 4162 } 4163 } 4164 4165 if (!(kIODKDisablePM & gIODKDebug) && pmProvider) { 4166 IOLockLock(fLock); 4167 unsigned int idx = fServices->getNextIndexOfObject(service, 0); 4168 assert(idx <= 63); 4169 fPowerStates |= (1ULL << idx); 4170 IOLockUnlock(fLock); 4171 4172 if (joinTree) { 4173 pmProvider->joinPMtree(service); 4174 service->reserved->uvars->userServerPM = true; 4175 } 4176 } 4177 4178 service->registerInterestedDriver(this); 4179 service->reserved->uvars->started = true; 4180 4181 return kIOReturnSuccess; 4182 } 4183 4184 4185 IOReturn 4186 IOUserServer::serviceOpen(IOService * provider, IOService * client) 4187 { 4188 OSObjectUserVars * uvars; 4189 4190 uvars = client->reserved->uvars; 4191 if (!uvars->openProviders) { 4192 uvars->openProviders = OSArray::withObjects((const OSObject **) &provider, 1); 4193 } else if (-1U == uvars->openProviders->getNextIndexOfObject(client, 0)) { 4194 uvars->openProviders->setObject(provider); 4195 } 4196 4197 return kIOReturnSuccess; 4198 } 4199 4200 IOReturn 4201 IOUserServer::serviceClose(IOService * provider, IOService * client) 4202 { 4203 OSObjectUserVars * uvars; 4204 unsigned int idx; 4205 4206 uvars = client->reserved->uvars; 4207 if (!uvars->openProviders) { 4208 return kIOReturnNotOpen; 4209 } 4210 idx = uvars->openProviders->getNextIndexOfObject(client, 0); 4211 if (-1U == idx) { 4212 return kIOReturnNotOpen; 4213 } 4214 uvars->openProviders->removeObject(idx); 4215 4216 return kIOReturnSuccess; 4217 } 4218 4219 4220 IOReturn 4221 IOUserServer::serviceStop(IOService * service, IOService *) 4222 { 4223 IOReturn ret; 4224 uint32_t idx, queueAlloc; 4225 OSObjectUserVars * uvars; 4226 4227 IOLockLock(fLock); 4228 idx = fServices->getNextIndexOfObject(service, 0); 4229 if (-1U != idx) { 4230 fServices->removeObject(idx); 4231 uvars = service->reserved->uvars; 4232 uvars->stopped = true; 4233 } 4234 IOLockUnlock(fLock); 4235 4236 if (-1U == idx) { 4237 return kIOReturnSuccess; 4238 } 4239 4240 if (uvars->queueArray && uvars->userMeta) { 4241 queueAlloc = 1; 4242 if (uvars->userMeta->queueNames) { 4243 queueAlloc += uvars->userMeta->queueNames->count; 4244 } 4245 for (idx = 0; idx < queueAlloc; idx++) { 4246 OSSafeReleaseNULL(uvars->queueArray[idx]); 4247 } 4248 IOSafeDeleteNULL(uvars->queueArray, IODispatchQueue *, queueAlloc); 4249 } 4250 4251 (void) service->deRegisterInterestedDriver(this); 4252 if (uvars->userServerPM) { 4253 service->PMstop(); 4254 } 4255 4256 ret = kIOReturnSuccess; 4257 return ret; 4258 } 4259 4260 void 4261 IOUserServer::serviceFree(IOService * service) 4262 { 4263 OSObjectUserVars * uvars; 4264 4265 uvars = service->reserved->uvars; 4266 if (!uvars) { 4267 return; 4268 } 4269 OSSafeReleaseNULL(uvars->userServer); 4270 IOSafeDeleteNULL(service->reserved->uvars, OSObjectUserVars, 1); 4271 } 4272 4273 void 4274 IOUserServer::serviceWillTerminate(IOService * client, IOService * provider, IOOptionBits options) 4275 { 4276 IOReturn ret; 4277 bool willTerminate; 4278 4279 willTerminate = false; 4280 if (client->lockForArbitration(true)) { 4281 if (!client->reserved->uvars->serverDied 4282 && !client->reserved->uvars->willTerminate) { 4283 client->reserved->uvars->willTerminate = true; 4284 willTerminate = true; 4285 } 4286 client->unlockForArbitration(); 4287 } 4288 4289 if (willTerminate) { 4290 if (IOServicePH::serverSlept()) { 4291 client->Stop_async(provider); 4292 ret = kIOReturnOffline; 4293 } else { 4294 ret = client->Stop(provider); 4295 } 4296 if (kIOReturnSuccess != ret) { 4297 IOUserServer::serviceDidStop(client, provider); 4298 ret = kIOReturnSuccess; 4299 } 4300 } 4301 } 4302 4303 void 4304 IOUserServer::serviceDidTerminate(IOService * client, IOService * provider, IOOptionBits options, bool * defer) 4305 { 4306 if (client->lockForArbitration(true)) { 4307 client->reserved->uvars->didTerminate = true; 4308 if (!client->reserved->uvars->serverDied 4309 && !client->reserved->uvars->stopped) { 4310 *defer = true; 4311 } 4312 client->unlockForArbitration(); 4313 } 4314 } 4315 4316 void 4317 IOUserServer::serviceDidStop(IOService * client, IOService * provider) 4318 { 4319 bool complete; 4320 OSArray * closeArray; 4321 4322 complete = false; 4323 closeArray = NULL; 4324 4325 if (client->lockForArbitration(true)) { 4326 if (client->reserved->uvars 4327 && client->reserved->uvars->willTerminate 4328 && !client->reserved->uvars->stopped) { 4329 client->reserved->uvars->stopped = true; 4330 complete = client->reserved->uvars->didTerminate; 4331 } 4332 4333 if (client->reserved->uvars) { 4334 closeArray = client->reserved->uvars->openProviders; 4335 client->reserved->uvars->openProviders = NULL; 4336 } 4337 client->unlockForArbitration(); 4338 if (closeArray) { 4339 closeArray->iterateObjects(^bool (OSObject * obj) { 4340 IOService * toClose; 4341 toClose = OSDynamicCast(IOService, obj); 4342 if (toClose) { 4343 DKLOG(DKS ":force close (" DKS ")\n", DKN(client), DKN(toClose)); 4344 toClose->close(client); 4345 } 4346 return false; 4347 }); 4348 closeArray->release(); 4349 } 4350 } 4351 if (complete) { 4352 bool defer = false; 4353 client->didTerminate(provider, 0, &defer); 4354 } 4355 } 4356 4357 kern_return_t 4358 IOService::Stop_Impl( 4359 IOService * provider) 4360 { 4361 IOUserServer::serviceDidStop(this, provider); 4362 4363 return kIOReturnSuccess; 4364 } 4365 4366 void 4367 IOService::Stop_async_Impl( 4368 IOService * provider) 4369 { 4370 } 4371 4372 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4373 4374 #undef super 4375 #define super IOUserClient 4376 4377 OSDefineMetaClassAndStructors(IOUserUserClient, IOUserClient) 4378 4379 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4380 4381 IOReturn 4382 IOUserUserClient::setTask(task_t task) 4383 { 4384 task_reference(task); 4385 fTask = task; 4386 4387 return kIOReturnSuccess; 4388 } 4389 4390 void 4391 IOUserUserClient::stop(IOService * provider) 4392 { 4393 if (fTask) { 4394 task_deallocate(fTask); 4395 fTask = NULL; 4396 } 4397 super::stop(provider); 4398 } 4399 4400 IOReturn 4401 IOUserUserClient::clientClose(void) 4402 { 4403 terminate(kIOServiceTerminateNeedWillTerminate); 4404 return kIOReturnSuccess; 4405 } 4406 4407 IOReturn 4408 IOUserUserClient::setProperties(OSObject * properties) 4409 { 4410 IOReturn ret = kIOReturnUnsupported; 4411 return ret; 4412 } 4413 4414 struct IOUserUserClientActionRef { 4415 OSAsyncReference64 asyncRef; 4416 }; 4417 4418 void 4419 IOUserClient::KernelCompletion_Impl( 4420 OSAction * action, 4421 IOReturn status, 4422 const unsigned long long * asyncData, 4423 uint32_t asyncDataCount) 4424 { 4425 IOUserUserClientActionRef * ref; 4426 4427 ref = (typeof(ref))action->GetReference(); 4428 4429 IOUserClient::sendAsyncResult64(ref->asyncRef, status, (io_user_reference_t *) asyncData, asyncDataCount); 4430 } 4431 4432 kern_return_t 4433 IOUserClient::_ExternalMethod_Impl( 4434 uint64_t selector, 4435 const unsigned long long * scalarInput, 4436 uint32_t scalarInputCount, 4437 OSData * structureInput, 4438 IOMemoryDescriptor * structureInputDescriptor, 4439 unsigned long long * scalarOutput, 4440 uint32_t * scalarOutputCount, 4441 uint64_t structureOutputMaximumSize, 4442 OSData ** structureOutput, 4443 IOMemoryDescriptor * structureOutputDescriptor, 4444 OSAction * completion) 4445 { 4446 return kIOReturnUnsupported; 4447 } 4448 4449 IOReturn 4450 IOUserUserClient::clientMemoryForType(UInt32 type, 4451 IOOptionBits * koptions, 4452 IOMemoryDescriptor ** kmemory) 4453 { 4454 IOReturn kr; 4455 uint64_t options; 4456 IOMemoryDescriptor * memory; 4457 4458 kr = CopyClientMemoryForType(type, &options, &memory); 4459 4460 *koptions = 0; 4461 *kmemory = NULL; 4462 if (kIOReturnSuccess != kr) { 4463 return kr; 4464 } 4465 4466 if (kIOUserClientMemoryReadOnly & options) { 4467 *koptions |= kIOMapReadOnly; 4468 } 4469 *kmemory = memory; 4470 4471 return kr; 4472 } 4473 4474 IOReturn 4475 IOUserUserClient::externalMethod(uint32_t selector, IOExternalMethodArguments * args, 4476 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) 4477 { 4478 IOReturn kr; 4479 OSData * structureInput; 4480 OSData * structureOutput; 4481 size_t copylen; 4482 uint64_t structureOutputSize; 4483 OSAction * action; 4484 IOUserUserClientActionRef * ref; 4485 4486 kr = kIOReturnUnsupported; 4487 structureInput = NULL; 4488 action = NULL; 4489 ref = NULL; 4490 4491 if (args->structureInputSize) { 4492 structureInput = OSData::withBytesNoCopy((void *) args->structureInput, args->structureInputSize); 4493 } 4494 4495 if (MACH_PORT_NULL != args->asyncWakePort) { 4496 kr = CreateActionKernelCompletion(sizeof(IOUserUserClientActionRef), &action); 4497 assert(KERN_SUCCESS == kr); 4498 ref = (typeof(ref))action->GetReference(); 4499 bcopy(args->asyncReference, &ref->asyncRef[0], args->asyncReferenceCount * sizeof(ref->asyncRef[0])); 4500 4501 kr = action->SetAbortedHandler(^(void) { 4502 IOUserUserClientActionRef * ref; 4503 IOReturn ret; 4504 4505 ref = (typeof(ref))action->GetReference(); 4506 ret = releaseAsyncReference64(ref->asyncRef); 4507 assert(kIOReturnSuccess == ret); 4508 bzero(&ref->asyncRef[0], sizeof(ref->asyncRef)); 4509 }); 4510 assert(KERN_SUCCESS == kr); 4511 } 4512 4513 if (args->structureVariableOutputData) { 4514 structureOutputSize = kIOUserClientVariableStructureSize; 4515 } else if (args->structureOutputDescriptor) { 4516 structureOutputSize = args->structureOutputDescriptor->getLength(); 4517 } else { 4518 structureOutputSize = args->structureOutputSize; 4519 } 4520 4521 kr = _ExternalMethod(selector, &args->scalarInput[0], args->scalarInputCount, 4522 structureInput, args->structureInputDescriptor, 4523 args->scalarOutput, &args->scalarOutputCount, 4524 structureOutputSize, &structureOutput, args->structureOutputDescriptor, 4525 action); 4526 4527 OSSafeReleaseNULL(structureInput); 4528 OSSafeReleaseNULL(action); 4529 4530 if (kIOReturnSuccess != kr) { 4531 if (ref) { 4532 // mig will destroy any async port, remove our pointer to it 4533 bzero(&ref->asyncRef[0], sizeof(ref->asyncRef)); 4534 } 4535 return kr; 4536 } 4537 if (structureOutput) { 4538 if (args->structureVariableOutputData) { 4539 *args->structureVariableOutputData = structureOutput; 4540 } else { 4541 copylen = structureOutput->getLength(); 4542 if (copylen > args->structureOutputSize) { 4543 kr = kIOReturnBadArgument; 4544 } else { 4545 bcopy((const void *) structureOutput->getBytesNoCopy(), args->structureOutput, copylen); 4546 } 4547 OSSafeReleaseNULL(structureOutput); 4548 } 4549 } 4550 4551 return kr; 4552 } 4553 4554 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4555 4556 void 4557 IOUserServerCheckInToken::setNoSendersNotification(IOUserServerCheckInNotificationHandler handler, 4558 void* handlerArgs) 4559 { 4560 this->handler = handler; 4561 this->handlerArgs = handlerArgs; 4562 } 4563 4564 void 4565 IOUserServerCheckInToken::notifyNoSenders(IOUserServerCheckInToken *token) 4566 { 4567 if (token->handler) { 4568 token->handler(token, token->handlerArgs); 4569 } 4570 } 4571 4572 void 4573 IOUserServerCheckInToken::clearNotification() 4574 { 4575 this->handler = NULL; 4576 this->handlerArgs = NULL; 4577 } 4578 4579 IOUserServerCheckInToken * 4580 IOUserServerCheckInToken::create() 4581 { 4582 IOUserServerCheckInToken *me = new IOUserServerCheckInToken; 4583 if (me && !me->init()) { 4584 me->release(); 4585 return NULL; 4586 } 4587 me->clearNotification(); 4588 return me; 4589 } 4590 4591 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4592