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 30#include <libkern/c++/OSKext.h> 31#include <IOKit/IOKitServer.h> 32#include <IOKit/IOKitKeysPrivate.h> 33#include <IOKit/IOUserClient.h> 34#include <IOKit/IOService.h> 35#include <IOKit/IORegistryEntry.h> 36#include <IOKit/IOCatalogue.h> 37#include <IOKit/IOMemoryDescriptor.h> 38#include <IOKit/IOBufferMemoryDescriptor.h> 39#include <IOKit/IOLib.h> 40#include <IOKit/IOStatisticsPrivate.h> 41#include <IOKit/IOTimeStamp.h> 42#include <IOKit/system.h> 43#include <libkern/OSDebug.h> 44#include <sys/proc.h> 45#include <sys/kauth.h> 46#include <sys/codesign.h> 47 48#if CONFIG_MACF 49 50extern "C" { 51#include <security/mac_framework.h> 52}; 53#include <sys/kauth.h> 54 55#define IOMACF_LOG 0 56 57#endif /* CONFIG_MACF */ 58 59#include <IOKit/assert.h> 60 61#include "IOServicePrivate.h" 62#include "IOKitKernelInternal.h" 63 64#define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x)) 65#define SCALAR32(x) ((uint32_t )x) 66#define ARG32(x) ((void *)(uintptr_t)SCALAR32(x)) 67#define REF64(x) ((io_user_reference_t)((UInt64)(x))) 68#define REF32(x) ((int)(x)) 69 70enum 71{ 72 kIOUCAsync0Flags = 3ULL, 73 kIOUCAsync64Flag = 1ULL 74}; 75 76#if IOKITSTATS 77 78#define IOStatisticsRegisterCounter() \ 79do { \ 80 reserved->counter = IOStatistics::registerUserClient(this); \ 81} while (0) 82 83#define IOStatisticsUnregisterCounter() \ 84do { \ 85 if (reserved) \ 86 IOStatistics::unregisterUserClient(reserved->counter); \ 87} while (0) 88 89#define IOStatisticsClientCall() \ 90do { \ 91 IOStatistics::countUserClientCall(client); \ 92} while (0) 93 94#else 95 96#define IOStatisticsRegisterCounter() 97#define IOStatisticsUnregisterCounter() 98#define IOStatisticsClientCall() 99 100#endif /* IOKITSTATS */ 101 102/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 103 104// definitions we should get from osfmk 105 106//typedef struct ipc_port * ipc_port_t; 107typedef natural_t ipc_kobject_type_t; 108 109#define IKOT_IOKIT_SPARE 27 110#define IKOT_IOKIT_CONNECT 29 111#define IKOT_IOKIT_OBJECT 30 112 113extern "C" { 114 115extern ipc_port_t iokit_alloc_object_port( io_object_t obj, 116 ipc_kobject_type_t type ); 117 118extern kern_return_t iokit_destroy_object_port( ipc_port_t port ); 119 120extern mach_port_name_t iokit_make_send_right( task_t task, 121 io_object_t obj, ipc_kobject_type_t type ); 122 123extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta ); 124 125extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task); 126 127extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef); 128 129extern ipc_port_t master_device_port; 130 131extern void iokit_retain_port( ipc_port_t port ); 132extern void iokit_release_port( ipc_port_t port ); 133extern void iokit_release_port_send( ipc_port_t port ); 134 135extern kern_return_t iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type ); 136 137#include <mach/mach_traps.h> 138#include <vm/vm_map.h> 139 140} /* extern "C" */ 141 142 143/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 144 145// IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject. 146 147class IOMachPort : public OSObject 148{ 149 OSDeclareDefaultStructors(IOMachPort) 150public: 151 OSObject * object; 152 ipc_port_t port; 153 UInt32 mscount; 154 UInt8 holdDestroy; 155 156 static IOMachPort * portForObject( OSObject * obj, 157 ipc_kobject_type_t type ); 158 static bool noMoreSendersForObject( OSObject * obj, 159 ipc_kobject_type_t type, mach_port_mscount_t * mscount ); 160 static void releasePortForObject( OSObject * obj, 161 ipc_kobject_type_t type ); 162 static void setHoldDestroy( OSObject * obj, ipc_kobject_type_t type ); 163 164 static OSDictionary * dictForType( ipc_kobject_type_t type ); 165 166 static mach_port_name_t makeSendRightForTask( task_t task, 167 io_object_t obj, ipc_kobject_type_t type ); 168 169 virtual void free(); 170}; 171 172#define super OSObject 173OSDefineMetaClassAndStructors(IOMachPort, OSObject) 174 175static IOLock * gIOObjectPortLock; 176 177/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 178 179// not in dictForType() for debugging ease 180static OSDictionary * gIOObjectPorts; 181static OSDictionary * gIOConnectPorts; 182 183OSDictionary * IOMachPort::dictForType( ipc_kobject_type_t type ) 184{ 185 OSDictionary ** dict; 186 187 if( IKOT_IOKIT_OBJECT == type ) 188 dict = &gIOObjectPorts; 189 else if( IKOT_IOKIT_CONNECT == type ) 190 dict = &gIOConnectPorts; 191 else 192 return( 0 ); 193 194 if( 0 == *dict) 195 *dict = OSDictionary::withCapacity( 1 ); 196 197 return( *dict ); 198} 199 200IOMachPort * IOMachPort::portForObject ( OSObject * obj, 201 ipc_kobject_type_t type ) 202{ 203 IOMachPort * inst = 0; 204 OSDictionary * dict; 205 206 IOTakeLock( gIOObjectPortLock); 207 208 do { 209 210 dict = dictForType( type ); 211 if( !dict) 212 continue; 213 214 if( (inst = (IOMachPort *) 215 dict->getObject( (const OSSymbol *) obj ))) { 216 inst->mscount++; 217 inst->retain(); 218 continue; 219 } 220 221 inst = new IOMachPort; 222 if( inst && !inst->init()) { 223 inst = 0; 224 continue; 225 } 226 227 inst->port = iokit_alloc_object_port( obj, type ); 228 if( inst->port) { 229 // retains obj 230 dict->setObject( (const OSSymbol *) obj, inst ); 231 inst->mscount++; 232 233 } else { 234 inst->release(); 235 inst = 0; 236 } 237 238 } while( false ); 239 240 IOUnlock( gIOObjectPortLock); 241 242 return( inst ); 243} 244 245bool IOMachPort::noMoreSendersForObject( OSObject * obj, 246 ipc_kobject_type_t type, mach_port_mscount_t * mscount ) 247{ 248 OSDictionary * dict; 249 IOMachPort * machPort; 250 bool destroyed = true; 251 252 IOTakeLock( gIOObjectPortLock); 253 254 if( (dict = dictForType( type ))) { 255 obj->retain(); 256 257 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj ); 258 if( machPort) { 259 destroyed = (machPort->mscount <= *mscount); 260 if( destroyed) 261 dict->removeObject( (const OSSymbol *) obj ); 262 else 263 *mscount = machPort->mscount; 264 } 265 obj->release(); 266 } 267 268 IOUnlock( gIOObjectPortLock); 269 270 return( destroyed ); 271} 272 273void IOMachPort::releasePortForObject( OSObject * obj, 274 ipc_kobject_type_t type ) 275{ 276 OSDictionary * dict; 277 IOMachPort * machPort; 278 279 IOTakeLock( gIOObjectPortLock); 280 281 if( (dict = dictForType( type ))) { 282 obj->retain(); 283 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj ); 284 if( machPort && !machPort->holdDestroy) 285 dict->removeObject( (const OSSymbol *) obj ); 286 obj->release(); 287 } 288 289 IOUnlock( gIOObjectPortLock); 290} 291 292void IOMachPort::setHoldDestroy( OSObject * obj, ipc_kobject_type_t type ) 293{ 294 OSDictionary * dict; 295 IOMachPort * machPort; 296 297 IOLockLock( gIOObjectPortLock ); 298 299 if( (dict = dictForType( type ))) { 300 machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj ); 301 if( machPort) 302 machPort->holdDestroy = true; 303 } 304 305 IOLockUnlock( gIOObjectPortLock ); 306} 307 308void IOUserClient::destroyUserReferences( OSObject * obj ) 309{ 310 IOMachPort::releasePortForObject( obj, IKOT_IOKIT_OBJECT ); 311 312 // panther, 3160200 313 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT ); 314 315 OSDictionary * dict; 316 317 IOTakeLock( gIOObjectPortLock); 318 obj->retain(); 319 320 if( (dict = IOMachPort::dictForType( IKOT_IOKIT_CONNECT ))) 321 { 322 IOMachPort * port; 323 port = (IOMachPort *) dict->getObject( (const OSSymbol *) obj ); 324 if (port) 325 { 326 IOUserClient * uc; 327 if ((uc = OSDynamicCast(IOUserClient, obj)) && uc->mappings) 328 { 329 dict->setObject((const OSSymbol *) uc->mappings, port); 330 iokit_switch_object_port(port->port, uc->mappings, IKOT_IOKIT_CONNECT); 331 332 uc->mappings->release(); 333 uc->mappings = 0; 334 } 335 dict->removeObject( (const OSSymbol *) obj ); 336 } 337 } 338 obj->release(); 339 IOUnlock( gIOObjectPortLock); 340} 341 342mach_port_name_t IOMachPort::makeSendRightForTask( task_t task, 343 io_object_t obj, ipc_kobject_type_t type ) 344{ 345 return( iokit_make_send_right( task, obj, type )); 346} 347 348void IOMachPort::free( void ) 349{ 350 if( port) 351 iokit_destroy_object_port( port ); 352 super::free(); 353} 354 355/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 356 357class IOUserNotification : public OSIterator 358{ 359 OSDeclareDefaultStructors(IOUserNotification) 360 361 IONotifier * holdNotify; 362 IOLock * lock; 363 364public: 365 366 virtual bool init( void ); 367 virtual void free(); 368 369 virtual void setNotification( IONotifier * obj ); 370 371 virtual void reset(); 372 virtual bool isValid(); 373}; 374 375/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 376extern "C" { 377 378// functions called from osfmk/device/iokit_rpc.c 379 380void 381iokit_add_reference( io_object_t obj ) 382{ 383 if( obj) 384 obj->retain(); 385} 386 387void 388iokit_remove_reference( io_object_t obj ) 389{ 390 if( obj) 391 obj->release(); 392} 393 394ipc_port_t 395iokit_port_for_object( io_object_t obj, ipc_kobject_type_t type ) 396{ 397 IOMachPort * machPort; 398 ipc_port_t port; 399 400 if( (machPort = IOMachPort::portForObject( obj, type ))) { 401 402 port = machPort->port; 403 if( port) 404 iokit_retain_port( port ); 405 406 machPort->release(); 407 408 } else 409 port = NULL; 410 411 return( port ); 412} 413 414kern_return_t 415iokit_client_died( io_object_t obj, ipc_port_t /* port */, 416 ipc_kobject_type_t type, mach_port_mscount_t * mscount ) 417{ 418 IOUserClient * client; 419 IOMemoryMap * map; 420 IOUserNotification * notify; 421 422 if( !IOMachPort::noMoreSendersForObject( obj, type, mscount )) 423 return( kIOReturnNotReady ); 424 425 if( IKOT_IOKIT_CONNECT == type) 426 { 427 if( (client = OSDynamicCast( IOUserClient, obj ))) { 428 IOStatisticsClientCall(); 429 client->clientDied(); 430 } 431 } 432 else if( IKOT_IOKIT_OBJECT == type) 433 { 434 if( (map = OSDynamicCast( IOMemoryMap, obj ))) 435 map->taskDied(); 436 else if( (notify = OSDynamicCast( IOUserNotification, obj ))) 437 notify->setNotification( 0 ); 438 } 439 440 return( kIOReturnSuccess ); 441} 442 443}; /* extern "C" */ 444 445/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 446 447class IOServiceUserNotification : public IOUserNotification 448{ 449 OSDeclareDefaultStructors(IOServiceUserNotification) 450 451 struct PingMsg { 452 mach_msg_header_t msgHdr; 453 OSNotificationHeader64 notifyHeader; 454 }; 455 456 enum { kMaxOutstanding = 1024 }; 457 458 PingMsg * pingMsg; 459 vm_size_t msgSize; 460 OSArray * newSet; 461 OSObject * lastEntry; 462 bool armed; 463 464public: 465 466 virtual bool init( mach_port_t port, natural_t type, 467 void * reference, vm_size_t referenceSize, 468 bool clientIs64 ); 469 virtual void free(); 470 471 static bool _handler( void * target, 472 void * ref, IOService * newService, IONotifier * notifier ); 473 virtual bool handler( void * ref, IOService * newService ); 474 475 virtual OSObject * getNextObject(); 476}; 477 478class IOServiceMessageUserNotification : public IOUserNotification 479{ 480 OSDeclareDefaultStructors(IOServiceMessageUserNotification) 481 482 struct PingMsg { 483 mach_msg_header_t msgHdr; 484 mach_msg_body_t msgBody; 485 mach_msg_port_descriptor_t ports[1]; 486 OSNotificationHeader64 notifyHeader __attribute__ ((packed)); 487 }; 488 489 PingMsg * pingMsg; 490 vm_size_t msgSize; 491 uint8_t clientIs64; 492 int owningPID; 493 494public: 495 496 virtual bool init( mach_port_t port, natural_t type, 497 void * reference, vm_size_t referenceSize, 498 vm_size_t extraSize, 499 bool clientIs64 ); 500 501 virtual void free(); 502 503 static IOReturn _handler( void * target, void * ref, 504 UInt32 messageType, IOService * provider, 505 void * messageArgument, vm_size_t argSize ); 506 virtual IOReturn handler( void * ref, 507 UInt32 messageType, IOService * provider, 508 void * messageArgument, vm_size_t argSize ); 509 510 virtual OSObject * getNextObject(); 511}; 512 513/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 514 515#undef super 516#define super OSIterator 517OSDefineMetaClass( IOUserNotification, OSIterator ) 518OSDefineAbstractStructors( IOUserNotification, OSIterator ) 519 520/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 521 522bool IOUserNotification::init( void ) 523{ 524 if( !super::init()) 525 return( false ); 526 527 lock = IOLockAlloc(); 528 if( !lock) 529 return( false ); 530 531 return( true ); 532} 533 534void IOUserNotification::free( void ) 535{ 536 if( holdNotify) 537 holdNotify->remove(); 538 // can't be in handler now 539 540 if( lock) 541 IOLockFree( lock ); 542 543 super::free(); 544} 545 546 547void IOUserNotification::setNotification( IONotifier * notify ) 548{ 549 IONotifier * previousNotify; 550 551 IOLockLock( gIOObjectPortLock); 552 553 previousNotify = holdNotify; 554 holdNotify = notify; 555 556 IOLockUnlock( gIOObjectPortLock); 557 558 if( previousNotify) 559 previousNotify->remove(); 560} 561 562void IOUserNotification::reset() 563{ 564 // ? 565} 566 567bool IOUserNotification::isValid() 568{ 569 return( true ); 570} 571 572/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 573 574#undef super 575#define super IOUserNotification 576OSDefineMetaClassAndStructors(IOServiceUserNotification, IOUserNotification) 577 578/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 579 580bool IOServiceUserNotification::init( mach_port_t port, natural_t type, 581 void * reference, vm_size_t referenceSize, 582 bool clientIs64 ) 583{ 584 if( !super::init()) 585 return( false ); 586 587 newSet = OSArray::withCapacity( 1 ); 588 if( !newSet) 589 return( false ); 590 591 if (referenceSize > sizeof(OSAsyncReference64)) 592 return( false ); 593 594 msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize; 595 pingMsg = (PingMsg *) IOMalloc( msgSize); 596 if( !pingMsg) 597 return( false ); 598 599 bzero( pingMsg, msgSize); 600 601 pingMsg->msgHdr.msgh_remote_port = port; 602 pingMsg->msgHdr.msgh_bits = MACH_MSGH_BITS( 603 MACH_MSG_TYPE_COPY_SEND /*remote*/, 604 MACH_MSG_TYPE_MAKE_SEND /*local*/); 605 pingMsg->msgHdr.msgh_size = msgSize; 606 pingMsg->msgHdr.msgh_id = kOSNotificationMessageID; 607 608 pingMsg->notifyHeader.size = 0; 609 pingMsg->notifyHeader.type = type; 610 bcopy( reference, pingMsg->notifyHeader.reference, referenceSize ); 611 612 return( true ); 613} 614 615void IOServiceUserNotification::free( void ) 616{ 617 PingMsg * _pingMsg; 618 vm_size_t _msgSize; 619 OSArray * _newSet; 620 OSObject * _lastEntry; 621 622 _pingMsg = pingMsg; 623 _msgSize = msgSize; 624 _lastEntry = lastEntry; 625 _newSet = newSet; 626 627 super::free(); 628 629 if( _pingMsg && _msgSize) { 630 if (_pingMsg->msgHdr.msgh_remote_port) { 631 iokit_release_port_send(_pingMsg->msgHdr.msgh_remote_port); 632 } 633 IOFree(_pingMsg, _msgSize); 634 } 635 636 if( _lastEntry) 637 _lastEntry->release(); 638 639 if( _newSet) 640 _newSet->release(); 641} 642 643bool IOServiceUserNotification::_handler( void * target, 644 void * ref, IOService * newService, IONotifier * notifier ) 645{ 646 return( ((IOServiceUserNotification *) target)->handler( ref, newService )); 647} 648 649bool IOServiceUserNotification::handler( void * ref, 650 IOService * newService ) 651{ 652 unsigned int count; 653 kern_return_t kr; 654 ipc_port_t port = NULL; 655 bool sendPing = false; 656 657 IOTakeLock( lock ); 658 659 count = newSet->getCount(); 660 if( count < kMaxOutstanding) { 661 662 newSet->setObject( newService ); 663 if( (sendPing = (armed && (0 == count)))) 664 armed = false; 665 } 666 667 IOUnlock( lock ); 668 669 if( kIOServiceTerminatedNotificationType == pingMsg->notifyHeader.type) 670 IOMachPort::setHoldDestroy( newService, IKOT_IOKIT_OBJECT ); 671 672 if( sendPing) { 673 if( (port = iokit_port_for_object( this, IKOT_IOKIT_OBJECT ) )) 674 pingMsg->msgHdr.msgh_local_port = port; 675 else 676 pingMsg->msgHdr.msgh_local_port = NULL; 677 678 kr = mach_msg_send_from_kernel_with_options( &pingMsg->msgHdr, 679 pingMsg->msgHdr.msgh_size, 680 (MACH_SEND_MSG | MACH_SEND_ALWAYS | MACH_SEND_IMPORTANCE), 681 0); 682 if( port) 683 iokit_release_port( port ); 684 685 if( KERN_SUCCESS != kr) 686 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr ); 687 } 688 689 return( true ); 690} 691 692OSObject * IOServiceUserNotification::getNextObject() 693{ 694 unsigned int count; 695 OSObject * result; 696 697 IOTakeLock( lock ); 698 699 if( lastEntry) 700 lastEntry->release(); 701 702 count = newSet->getCount(); 703 if( count ) { 704 result = newSet->getObject( count - 1 ); 705 result->retain(); 706 newSet->removeObject( count - 1); 707 } else { 708 result = 0; 709 armed = true; 710 } 711 lastEntry = result; 712 713 IOUnlock( lock ); 714 715 return( result ); 716} 717 718/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 719 720OSDefineMetaClassAndStructors(IOServiceMessageUserNotification, IOUserNotification) 721 722/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 723 724bool IOServiceMessageUserNotification::init( mach_port_t port, natural_t type, 725 void * reference, vm_size_t referenceSize, vm_size_t extraSize, 726 bool client64 ) 727{ 728 if( !super::init()) 729 return( false ); 730 731 if (referenceSize > sizeof(OSAsyncReference64)) 732 return( false ); 733 734 clientIs64 = client64; 735 736 owningPID = proc_selfpid(); 737 738 extraSize += sizeof(IOServiceInterestContent64); 739 msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize + extraSize; 740 pingMsg = (PingMsg *) IOMalloc( msgSize); 741 if( !pingMsg) 742 return( false ); 743 744 bzero( pingMsg, msgSize); 745 746 pingMsg->msgHdr.msgh_remote_port = port; 747 pingMsg->msgHdr.msgh_bits = MACH_MSGH_BITS_COMPLEX 748 | MACH_MSGH_BITS( 749 MACH_MSG_TYPE_COPY_SEND /*remote*/, 750 MACH_MSG_TYPE_MAKE_SEND /*local*/); 751 pingMsg->msgHdr.msgh_size = msgSize; 752 pingMsg->msgHdr.msgh_id = kOSNotificationMessageID; 753 754 pingMsg->msgBody.msgh_descriptor_count = 1; 755 756 pingMsg->ports[0].name = 0; 757 pingMsg->ports[0].disposition = MACH_MSG_TYPE_MAKE_SEND; 758 pingMsg->ports[0].type = MACH_MSG_PORT_DESCRIPTOR; 759 760 pingMsg->notifyHeader.size = extraSize; 761 pingMsg->notifyHeader.type = type; 762 bcopy( reference, pingMsg->notifyHeader.reference, referenceSize ); 763 764 return( true ); 765} 766 767void IOServiceMessageUserNotification::free( void ) 768{ 769 PingMsg * _pingMsg; 770 vm_size_t _msgSize; 771 772 _pingMsg = pingMsg; 773 _msgSize = msgSize; 774 775 super::free(); 776 777 if( _pingMsg && _msgSize) { 778 if (_pingMsg->msgHdr.msgh_remote_port) { 779 iokit_release_port_send(_pingMsg->msgHdr.msgh_remote_port); 780 } 781 IOFree( _pingMsg, _msgSize); 782 } 783} 784 785IOReturn IOServiceMessageUserNotification::_handler( void * target, void * ref, 786 UInt32 messageType, IOService * provider, 787 void * argument, vm_size_t argSize ) 788{ 789 return( ((IOServiceMessageUserNotification *) target)->handler( 790 ref, messageType, provider, argument, argSize)); 791} 792 793IOReturn IOServiceMessageUserNotification::handler( void * ref, 794 UInt32 messageType, IOService * provider, 795 void * messageArgument, vm_size_t argSize ) 796{ 797 kern_return_t kr; 798 ipc_port_t thisPort, providerPort; 799 IOServiceInterestContent64 * data = (IOServiceInterestContent64 *) 800 ((((uint8_t *) pingMsg) + msgSize) - pingMsg->notifyHeader.size); 801 // == pingMsg->notifyHeader.content; 802 803 if (kIOMessageCopyClientID == messageType) 804 { 805 *((void **) messageArgument) = OSNumber::withNumber(owningPID, 32); 806 return (kIOReturnSuccess); 807 } 808 809 data->messageType = messageType; 810 811 if( argSize == 0) 812 { 813 data->messageArgument[0] = (io_user_reference_t) messageArgument; 814 if (clientIs64) 815 argSize = sizeof(data->messageArgument[0]); 816 else 817 { 818 data->messageArgument[0] |= (data->messageArgument[0] << 32); 819 argSize = sizeof(uint32_t); 820 } 821 } 822 else 823 { 824 if( argSize > kIOUserNotifyMaxMessageSize) 825 argSize = kIOUserNotifyMaxMessageSize; 826 bcopy( messageArgument, data->messageArgument, argSize ); 827 } 828 829 // adjust message size for ipc restrictions 830 natural_t type; 831 type = pingMsg->notifyHeader.type; 832 type &= ~(kIOKitNoticationMsgSizeMask << kIOKitNoticationTypeSizeAdjShift); 833 type |= ((argSize & kIOKitNoticationMsgSizeMask) << kIOKitNoticationTypeSizeAdjShift); 834 pingMsg->notifyHeader.type = type; 835 argSize = (argSize + kIOKitNoticationMsgSizeMask) & ~kIOKitNoticationMsgSizeMask; 836 837 pingMsg->msgHdr.msgh_size = msgSize - pingMsg->notifyHeader.size 838 + sizeof( IOServiceInterestContent64 ) 839 - sizeof( data->messageArgument) 840 + argSize; 841 842 providerPort = iokit_port_for_object( provider, IKOT_IOKIT_OBJECT ); 843 pingMsg->ports[0].name = providerPort; 844 thisPort = iokit_port_for_object( this, IKOT_IOKIT_OBJECT ); 845 pingMsg->msgHdr.msgh_local_port = thisPort; 846 kr = mach_msg_send_from_kernel_with_options( &pingMsg->msgHdr, 847 pingMsg->msgHdr.msgh_size, 848 (MACH_SEND_MSG | MACH_SEND_ALWAYS | MACH_SEND_IMPORTANCE), 849 0); 850 if( thisPort) 851 iokit_release_port( thisPort ); 852 if( providerPort) 853 iokit_release_port( providerPort ); 854 855 if( KERN_SUCCESS != kr) 856 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr ); 857 858 return( kIOReturnSuccess ); 859} 860 861OSObject * IOServiceMessageUserNotification::getNextObject() 862{ 863 return( 0 ); 864} 865 866/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 867 868#undef super 869#define super IOService 870OSDefineMetaClassAndAbstractStructors( IOUserClient, IOService ) 871 872void IOUserClient::initialize( void ) 873{ 874 gIOObjectPortLock = IOLockAlloc(); 875 876 assert( gIOObjectPortLock ); 877} 878 879void IOUserClient::setAsyncReference(OSAsyncReference asyncRef, 880 mach_port_t wakePort, 881 void *callback, void *refcon) 882{ 883 asyncRef[kIOAsyncReservedIndex] = ((uintptr_t) wakePort) 884 | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]); 885 asyncRef[kIOAsyncCalloutFuncIndex] = (uintptr_t) callback; 886 asyncRef[kIOAsyncCalloutRefconIndex] = (uintptr_t) refcon; 887} 888 889void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef, 890 mach_port_t wakePort, 891 mach_vm_address_t callback, io_user_reference_t refcon) 892{ 893 asyncRef[kIOAsyncReservedIndex] = ((io_user_reference_t) wakePort) 894 | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]); 895 asyncRef[kIOAsyncCalloutFuncIndex] = (io_user_reference_t) callback; 896 asyncRef[kIOAsyncCalloutRefconIndex] = refcon; 897} 898 899void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef, 900 mach_port_t wakePort, 901 mach_vm_address_t callback, io_user_reference_t refcon, task_t task) 902{ 903 setAsyncReference64(asyncRef, wakePort, callback, refcon); 904 if (vm_map_is_64bit(get_task_map(task))) { 905 asyncRef[kIOAsyncReservedIndex] |= kIOUCAsync64Flag; 906 } 907} 908 909static OSDictionary * CopyConsoleUser(UInt32 uid) 910{ 911 OSArray * array; 912 OSDictionary * user = 0; 913 914 if ((array = OSDynamicCast(OSArray, 915 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey)))) 916 { 917 for (unsigned int idx = 0; 918 (user = OSDynamicCast(OSDictionary, array->getObject(idx))); 919 idx++) { 920 OSNumber * num; 921 922 if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionUIDKey))) 923 && (uid == num->unsigned32BitValue())) { 924 user->retain(); 925 break; 926 } 927 } 928 array->release(); 929 } 930 return user; 931} 932 933static OSDictionary * CopyUserOnConsole(void) 934{ 935 OSArray * array; 936 OSDictionary * user = 0; 937 938 if ((array = OSDynamicCast(OSArray, 939 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey)))) 940 { 941 for (unsigned int idx = 0; 942 (user = OSDynamicCast(OSDictionary, array->getObject(idx))); 943 idx++) 944 { 945 if (kOSBooleanTrue == user->getObject(gIOConsoleSessionOnConsoleKey)) 946 { 947 user->retain(); 948 break; 949 } 950 } 951 array->release(); 952 } 953 return (user); 954} 955 956IOReturn IOUserClient::clientHasAuthorization( task_t task, 957 IOService * service ) 958{ 959 proc_t p; 960 961 p = (proc_t) get_bsdtask_info(task); 962 if (p) 963 { 964 uint64_t authorizationID; 965 966 authorizationID = proc_uniqueid(p); 967 if (authorizationID) 968 { 969 if (service->getAuthorizationID() == authorizationID) 970 { 971 return (kIOReturnSuccess); 972 } 973 } 974 } 975 976 return (kIOReturnNotPermitted); 977} 978 979IOReturn IOUserClient::clientHasPrivilege( void * securityToken, 980 const char * privilegeName ) 981{ 982 kern_return_t kr; 983 security_token_t token; 984 mach_msg_type_number_t count; 985 task_t task; 986 OSDictionary * user; 987 bool secureConsole; 988 989 990 if (!strncmp(privilegeName, kIOClientPrivilegeForeground, 991 sizeof(kIOClientPrivilegeForeground))) 992 { 993 if (task_is_gpu_denied(current_task())) 994 return (kIOReturnNotPrivileged); 995 else 996 return (kIOReturnSuccess); 997 } 998 999 if (!strncmp(privilegeName, kIOClientPrivilegeConsoleSession, 1000 sizeof(kIOClientPrivilegeConsoleSession))) 1001 { 1002 kauth_cred_t cred; 1003 proc_t p; 1004 1005 task = (task_t) securityToken; 1006 if (!task) 1007 task = current_task(); 1008 p = (proc_t) get_bsdtask_info(task); 1009 kr = kIOReturnNotPrivileged; 1010 1011 if (p && (cred = kauth_cred_proc_ref(p))) 1012 { 1013 user = CopyUserOnConsole(); 1014 if (user) 1015 { 1016 OSNumber * num; 1017 if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionAuditIDKey))) 1018 && (cred->cr_audit.as_aia_p->ai_asid == (au_asid_t) num->unsigned32BitValue())) 1019 { 1020 kr = kIOReturnSuccess; 1021 } 1022 user->release(); 1023 } 1024 kauth_cred_unref(&cred); 1025 } 1026 return (kr); 1027 } 1028 1029 if ((secureConsole = !strncmp(privilegeName, kIOClientPrivilegeSecureConsoleProcess, 1030 sizeof(kIOClientPrivilegeSecureConsoleProcess)))) 1031 task = (task_t)((IOUCProcessToken *)securityToken)->token; 1032 else 1033 task = (task_t)securityToken; 1034 1035 count = TASK_SECURITY_TOKEN_COUNT; 1036 kr = task_info( task, TASK_SECURITY_TOKEN, (task_info_t) &token, &count ); 1037 1038 if (KERN_SUCCESS != kr) 1039 {} 1040 else if (!strncmp(privilegeName, kIOClientPrivilegeAdministrator, 1041 sizeof(kIOClientPrivilegeAdministrator))) { 1042 if (0 != token.val[0]) 1043 kr = kIOReturnNotPrivileged; 1044 } else if (!strncmp(privilegeName, kIOClientPrivilegeLocalUser, 1045 sizeof(kIOClientPrivilegeLocalUser))) { 1046 user = CopyConsoleUser(token.val[0]); 1047 if ( user ) 1048 user->release(); 1049 else 1050 kr = kIOReturnNotPrivileged; 1051 } else if (secureConsole || !strncmp(privilegeName, kIOClientPrivilegeConsoleUser, 1052 sizeof(kIOClientPrivilegeConsoleUser))) { 1053 user = CopyConsoleUser(token.val[0]); 1054 if ( user ) { 1055 if (user->getObject(gIOConsoleSessionOnConsoleKey) != kOSBooleanTrue) 1056 kr = kIOReturnNotPrivileged; 1057 else if ( secureConsole ) { 1058 OSNumber * pid = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionSecureInputPIDKey)); 1059 if ( pid && pid->unsigned32BitValue() != ((IOUCProcessToken *)securityToken)->pid) 1060 kr = kIOReturnNotPrivileged; 1061 } 1062 user->release(); 1063 } 1064 else 1065 kr = kIOReturnNotPrivileged; 1066 } else 1067 kr = kIOReturnUnsupported; 1068 1069 return (kr); 1070} 1071 1072OSObject * IOUserClient::copyClientEntitlement( task_t task, 1073 const char * entitlement ) 1074{ 1075#define MAX_ENTITLEMENTS_LEN (128 * 1024) 1076 1077 proc_t p = NULL; 1078 pid_t pid = 0; 1079 char procname[MAXCOMLEN + 1] = ""; 1080 size_t len = 0; 1081 void *entitlements_blob = NULL; 1082 char *entitlements_data = NULL; 1083 OSObject *entitlements_obj = NULL; 1084 OSDictionary *entitlements = NULL; 1085 OSString *errorString = NULL; 1086 OSObject *value = NULL; 1087 1088 p = (proc_t)get_bsdtask_info(task); 1089 if (p == NULL) 1090 goto fail; 1091 pid = proc_pid(p); 1092 proc_name(pid, procname, (int)sizeof(procname)); 1093 1094 if (cs_entitlements_blob_get(p, &entitlements_blob, &len) != 0) 1095 goto fail; 1096 1097 if (len <= offsetof(CS_GenericBlob, data)) 1098 goto fail; 1099 1100 /* 1101 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML 1102 * we'll try to parse in the kernel. 1103 */ 1104 len -= offsetof(CS_GenericBlob, data); 1105 if (len > MAX_ENTITLEMENTS_LEN) { 1106 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n", procname, pid, len, MAX_ENTITLEMENTS_LEN); 1107 goto fail; 1108 } 1109 1110 /* 1111 * OSUnserializeXML() expects a nul-terminated string, but that isn't 1112 * what is stored in the entitlements blob. Copy the string and 1113 * terminate it. 1114 */ 1115 entitlements_data = (char *)IOMalloc(len + 1); 1116 if (entitlements_data == NULL) 1117 goto fail; 1118 memcpy(entitlements_data, ((CS_GenericBlob *)entitlements_blob)->data, len); 1119 entitlements_data[len] = '\0'; 1120 1121 entitlements_obj = OSUnserializeXML(entitlements_data, len + 1, &errorString); 1122 if (errorString != NULL) { 1123 IOLog("failed to parse entitlements for %s[%u]: %s\n", procname, pid, errorString->getCStringNoCopy()); 1124 goto fail; 1125 } 1126 if (entitlements_obj == NULL) 1127 goto fail; 1128 1129 entitlements = OSDynamicCast(OSDictionary, entitlements_obj); 1130 if (entitlements == NULL) 1131 goto fail; 1132 1133 /* Fetch the entitlement value from the dictionary. */ 1134 value = entitlements->getObject(entitlement); 1135 if (value != NULL) 1136 value->retain(); 1137 1138fail: 1139 if (entitlements_data != NULL) 1140 IOFree(entitlements_data, len + 1); 1141 if (entitlements_obj != NULL) 1142 entitlements_obj->release(); 1143 if (errorString != NULL) 1144 errorString->release(); 1145 return value; 1146} 1147 1148bool IOUserClient::init() 1149{ 1150 if (getPropertyTable() || super::init()) 1151 return reserve(); 1152 1153 return false; 1154} 1155 1156bool IOUserClient::init(OSDictionary * dictionary) 1157{ 1158 if (getPropertyTable() || super::init(dictionary)) 1159 return reserve(); 1160 1161 return false; 1162} 1163 1164bool IOUserClient::initWithTask(task_t owningTask, 1165 void * securityID, 1166 UInt32 type ) 1167{ 1168 if (getPropertyTable() || super::init()) 1169 return reserve(); 1170 1171 return false; 1172} 1173 1174bool IOUserClient::initWithTask(task_t owningTask, 1175 void * securityID, 1176 UInt32 type, 1177 OSDictionary * properties ) 1178{ 1179 bool ok; 1180 1181 ok = super::init( properties ); 1182 ok &= initWithTask( owningTask, securityID, type ); 1183 1184 return( ok ); 1185} 1186 1187bool IOUserClient::reserve() 1188{ 1189 if(!reserved) { 1190 reserved = IONew(ExpansionData, 1); 1191 if (!reserved) { 1192 return false; 1193 } 1194 } 1195 setTerminateDefer(NULL, true); 1196 IOStatisticsRegisterCounter(); 1197 1198 return true; 1199} 1200 1201void IOUserClient::free() 1202{ 1203 if( mappings) 1204 mappings->release(); 1205 1206 IOStatisticsUnregisterCounter(); 1207 1208 if (reserved) 1209 IODelete(reserved, ExpansionData, 1); 1210 1211 super::free(); 1212} 1213 1214IOReturn IOUserClient::clientDied( void ) 1215{ 1216 return( clientClose()); 1217} 1218 1219IOReturn IOUserClient::clientClose( void ) 1220{ 1221 return( kIOReturnUnsupported ); 1222} 1223 1224IOService * IOUserClient::getService( void ) 1225{ 1226 return( 0 ); 1227} 1228 1229IOReturn IOUserClient::registerNotificationPort( 1230 mach_port_t /* port */, 1231 UInt32 /* type */, 1232 UInt32 /* refCon */) 1233{ 1234 return( kIOReturnUnsupported); 1235} 1236 1237IOReturn IOUserClient::registerNotificationPort( 1238 mach_port_t port, 1239 UInt32 type, 1240 io_user_reference_t refCon) 1241{ 1242 return (registerNotificationPort(port, type, (UInt32) refCon)); 1243} 1244 1245IOReturn IOUserClient::getNotificationSemaphore( UInt32 notification_type, 1246 semaphore_t * semaphore ) 1247{ 1248 return( kIOReturnUnsupported); 1249} 1250 1251IOReturn IOUserClient::connectClient( IOUserClient * /* client */ ) 1252{ 1253 return( kIOReturnUnsupported); 1254} 1255 1256IOReturn IOUserClient::clientMemoryForType( UInt32 type, 1257 IOOptionBits * options, 1258 IOMemoryDescriptor ** memory ) 1259{ 1260 return( kIOReturnUnsupported); 1261} 1262 1263#if !__LP64__ 1264IOMemoryMap * IOUserClient::mapClientMemory( 1265 IOOptionBits type, 1266 task_t task, 1267 IOOptionBits mapFlags, 1268 IOVirtualAddress atAddress ) 1269{ 1270 return (NULL); 1271} 1272#endif 1273 1274IOMemoryMap * IOUserClient::mapClientMemory64( 1275 IOOptionBits type, 1276 task_t task, 1277 IOOptionBits mapFlags, 1278 mach_vm_address_t atAddress ) 1279{ 1280 IOReturn err; 1281 IOOptionBits options = 0; 1282 IOMemoryDescriptor * memory; 1283 IOMemoryMap * map = 0; 1284 1285 err = clientMemoryForType( (UInt32) type, &options, &memory ); 1286 1287 if( memory && (kIOReturnSuccess == err)) { 1288 1289 options = (options & ~kIOMapUserOptionsMask) 1290 | (mapFlags & kIOMapUserOptionsMask); 1291 map = memory->createMappingInTask( task, atAddress, options ); 1292 memory->release(); 1293 } 1294 1295 return( map ); 1296} 1297 1298IOReturn IOUserClient::exportObjectToClient(task_t task, 1299 OSObject *obj, io_object_t *clientObj) 1300{ 1301 mach_port_name_t name; 1302 1303 name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT ); 1304 1305 *(mach_port_name_t *)clientObj = name; 1306 return kIOReturnSuccess; 1307} 1308 1309IOExternalMethod * IOUserClient::getExternalMethodForIndex( UInt32 /* index */) 1310{ 1311 return( 0 ); 1312} 1313 1314IOExternalAsyncMethod * IOUserClient::getExternalAsyncMethodForIndex( UInt32 /* index */) 1315{ 1316 return( 0 ); 1317} 1318 1319IOExternalMethod * IOUserClient:: 1320getTargetAndMethodForIndex(IOService **targetP, UInt32 index) 1321{ 1322 IOExternalMethod *method = getExternalMethodForIndex(index); 1323 1324 if (method) 1325 *targetP = (IOService *) method->object; 1326 1327 return method; 1328} 1329 1330IOExternalAsyncMethod * IOUserClient:: 1331getAsyncTargetAndMethodForIndex(IOService ** targetP, UInt32 index) 1332{ 1333 IOExternalAsyncMethod *method = getExternalAsyncMethodForIndex(index); 1334 1335 if (method) 1336 *targetP = (IOService *) method->object; 1337 1338 return method; 1339} 1340 1341IOExternalTrap * IOUserClient:: 1342getExternalTrapForIndex(UInt32 index) 1343{ 1344 return NULL; 1345} 1346 1347IOExternalTrap * IOUserClient:: 1348getTargetAndTrapForIndex(IOService ** targetP, UInt32 index) 1349{ 1350 IOExternalTrap *trap = getExternalTrapForIndex(index); 1351 1352 if (trap) { 1353 *targetP = trap->object; 1354 } 1355 1356 return trap; 1357} 1358 1359IOReturn IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference) 1360{ 1361 mach_port_t port; 1362 port = (mach_port_t) (reference[0] & ~kIOUCAsync0Flags); 1363 1364 if (MACH_PORT_NULL != port) 1365 iokit_release_port_send(port); 1366 1367 return (kIOReturnSuccess); 1368} 1369 1370IOReturn IOUserClient::releaseNotificationPort(mach_port_t port) 1371{ 1372 if (MACH_PORT_NULL != port) 1373 iokit_release_port_send(port); 1374 1375 return (kIOReturnSuccess); 1376} 1377 1378IOReturn IOUserClient::sendAsyncResult(OSAsyncReference reference, 1379 IOReturn result, void *args[], UInt32 numArgs) 1380{ 1381 OSAsyncReference64 reference64; 1382 io_user_reference_t args64[kMaxAsyncArgs]; 1383 unsigned int idx; 1384 1385 if (numArgs > kMaxAsyncArgs) 1386 return kIOReturnMessageTooLarge; 1387 1388 for (idx = 0; idx < kOSAsyncRef64Count; idx++) 1389 reference64[idx] = REF64(reference[idx]); 1390 1391 for (idx = 0; idx < numArgs; idx++) 1392 args64[idx] = REF64(args[idx]); 1393 1394 return (sendAsyncResult64(reference64, result, args64, numArgs)); 1395} 1396 1397IOReturn IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference, 1398 IOReturn result, io_user_reference_t args[], UInt32 numArgs, IOOptionBits options) 1399{ 1400 return _sendAsyncResult64(reference, result, args, numArgs, options); 1401} 1402 1403IOReturn IOUserClient::sendAsyncResult64(OSAsyncReference64 reference, 1404 IOReturn result, io_user_reference_t args[], UInt32 numArgs) 1405{ 1406 return _sendAsyncResult64(reference, result, args, numArgs, 0); 1407} 1408 1409IOReturn IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference, 1410 IOReturn result, io_user_reference_t args[], UInt32 numArgs, IOOptionBits options) 1411{ 1412 struct ReplyMsg 1413 { 1414 mach_msg_header_t msgHdr; 1415 union 1416 { 1417 struct 1418 { 1419 OSNotificationHeader notifyHdr; 1420 IOAsyncCompletionContent asyncContent; 1421 uint32_t args[kMaxAsyncArgs]; 1422 } msg32; 1423 struct 1424 { 1425 OSNotificationHeader64 notifyHdr; 1426 IOAsyncCompletionContent asyncContent; 1427 io_user_reference_t args[kMaxAsyncArgs] __attribute__ ((packed)); 1428 } msg64; 1429 } m; 1430 }; 1431 ReplyMsg replyMsg; 1432 mach_port_t replyPort; 1433 kern_return_t kr; 1434 1435 // If no reply port, do nothing. 1436 replyPort = (mach_port_t) (reference[0] & ~kIOUCAsync0Flags); 1437 if (replyPort == MACH_PORT_NULL) 1438 return kIOReturnSuccess; 1439 1440 if (numArgs > kMaxAsyncArgs) 1441 return kIOReturnMessageTooLarge; 1442 1443 replyMsg.msgHdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND /*remote*/, 1444 0 /*local*/); 1445 replyMsg.msgHdr.msgh_remote_port = replyPort; 1446 replyMsg.msgHdr.msgh_local_port = 0; 1447 replyMsg.msgHdr.msgh_id = kOSNotificationMessageID; 1448 if (kIOUCAsync64Flag & reference[0]) 1449 { 1450 replyMsg.msgHdr.msgh_size = 1451 sizeof(replyMsg.msgHdr) + sizeof(replyMsg.m.msg64) 1452 - (kMaxAsyncArgs - numArgs) * sizeof(io_user_reference_t); 1453 replyMsg.m.msg64.notifyHdr.size = sizeof(IOAsyncCompletionContent) 1454 + numArgs * sizeof(io_user_reference_t); 1455 replyMsg.m.msg64.notifyHdr.type = kIOAsyncCompletionNotificationType; 1456 bcopy(reference, replyMsg.m.msg64.notifyHdr.reference, sizeof(OSAsyncReference64)); 1457 1458 replyMsg.m.msg64.asyncContent.result = result; 1459 if (numArgs) 1460 bcopy(args, replyMsg.m.msg64.args, numArgs * sizeof(io_user_reference_t)); 1461 } 1462 else 1463 { 1464 unsigned int idx; 1465 1466 replyMsg.msgHdr.msgh_size = 1467 sizeof(replyMsg.msgHdr) + sizeof(replyMsg.m.msg32) 1468 - (kMaxAsyncArgs - numArgs) * sizeof(uint32_t); 1469 1470 replyMsg.m.msg32.notifyHdr.size = sizeof(IOAsyncCompletionContent) 1471 + numArgs * sizeof(uint32_t); 1472 replyMsg.m.msg32.notifyHdr.type = kIOAsyncCompletionNotificationType; 1473 1474 for (idx = 0; idx < kOSAsyncRefCount; idx++) 1475 replyMsg.m.msg32.notifyHdr.reference[idx] = REF32(reference[idx]); 1476 1477 replyMsg.m.msg32.asyncContent.result = result; 1478 1479 for (idx = 0; idx < numArgs; idx++) 1480 replyMsg.m.msg32.args[idx] = REF32(args[idx]); 1481 } 1482 1483 if ((options & kIOUserNotifyOptionCanDrop) != 0) { 1484 kr = mach_msg_send_from_kernel_with_options( &replyMsg.msgHdr, 1485 replyMsg.msgHdr.msgh_size, MACH_SEND_TIMEOUT, MACH_MSG_TIMEOUT_NONE); 1486 } else { 1487 /* Fail on full queue. */ 1488 kr = mach_msg_send_from_kernel_proper( &replyMsg.msgHdr, 1489 replyMsg.msgHdr.msgh_size); 1490 } 1491 if ((KERN_SUCCESS != kr) && (MACH_SEND_TIMED_OUT != kr)) 1492 IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr ); 1493 return kr; 1494} 1495 1496 1497/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1498 1499extern "C" { 1500 1501#define CHECK(cls,obj,out) \ 1502 cls * out; \ 1503 if( !(out = OSDynamicCast( cls, obj))) \ 1504 return( kIOReturnBadArgument ) 1505 1506/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1507 1508/* Routine io_server_version */ 1509kern_return_t is_io_server_version( 1510 mach_port_t master_port, 1511 uint64_t *version) 1512{ 1513 *version = IOKIT_SERVER_VERSION; 1514 return (kIOReturnSuccess); 1515} 1516 1517/* Routine io_object_get_class */ 1518kern_return_t is_io_object_get_class( 1519 io_object_t object, 1520 io_name_t className ) 1521{ 1522 const OSMetaClass* my_obj = NULL; 1523 1524 if( !object) 1525 return( kIOReturnBadArgument ); 1526 1527 my_obj = object->getMetaClass(); 1528 if (!my_obj) { 1529 return (kIOReturnNotFound); 1530 } 1531 1532 strlcpy( className, my_obj->getClassName(), sizeof(io_name_t)); 1533 return( kIOReturnSuccess ); 1534} 1535 1536/* Routine io_object_get_superclass */ 1537kern_return_t is_io_object_get_superclass( 1538 mach_port_t master_port, 1539 io_name_t obj_name, 1540 io_name_t class_name) 1541{ 1542 const OSMetaClass* my_obj = NULL; 1543 const OSMetaClass* superclass = NULL; 1544 const OSSymbol *my_name = NULL; 1545 const char *my_cstr = NULL; 1546 1547 if (!obj_name || !class_name) 1548 return (kIOReturnBadArgument); 1549 1550 if( master_port != master_device_port) 1551 return( kIOReturnNotPrivileged); 1552 1553 my_name = OSSymbol::withCString(obj_name); 1554 1555 if (my_name) { 1556 my_obj = OSMetaClass::getMetaClassWithName(my_name); 1557 my_name->release(); 1558 } 1559 if (my_obj) { 1560 superclass = my_obj->getSuperClass(); 1561 } 1562 1563 if (!superclass) { 1564 return( kIOReturnNotFound ); 1565 } 1566 1567 my_cstr = superclass->getClassName(); 1568 1569 if (my_cstr) { 1570 strlcpy(class_name, my_cstr, sizeof(io_name_t)); 1571 return( kIOReturnSuccess ); 1572 } 1573 return (kIOReturnNotFound); 1574} 1575 1576/* Routine io_object_get_bundle_identifier */ 1577kern_return_t is_io_object_get_bundle_identifier( 1578 mach_port_t master_port, 1579 io_name_t obj_name, 1580 io_name_t bundle_name) 1581{ 1582 const OSMetaClass* my_obj = NULL; 1583 const OSSymbol *my_name = NULL; 1584 const OSSymbol *identifier = NULL; 1585 const char *my_cstr = NULL; 1586 1587 if (!obj_name || !bundle_name) 1588 return (kIOReturnBadArgument); 1589 1590 if( master_port != master_device_port) 1591 return( kIOReturnNotPrivileged); 1592 1593 my_name = OSSymbol::withCString(obj_name); 1594 1595 if (my_name) { 1596 my_obj = OSMetaClass::getMetaClassWithName(my_name); 1597 my_name->release(); 1598 } 1599 1600 if (my_obj) { 1601 identifier = my_obj->getKmodName(); 1602 } 1603 if (!identifier) { 1604 return( kIOReturnNotFound ); 1605 } 1606 1607 my_cstr = identifier->getCStringNoCopy(); 1608 if (my_cstr) { 1609 strlcpy(bundle_name, identifier->getCStringNoCopy(), sizeof(io_name_t)); 1610 return( kIOReturnSuccess ); 1611 } 1612 1613 return (kIOReturnBadArgument); 1614} 1615 1616/* Routine io_object_conforms_to */ 1617kern_return_t is_io_object_conforms_to( 1618 io_object_t object, 1619 io_name_t className, 1620 boolean_t *conforms ) 1621{ 1622 if( !object) 1623 return( kIOReturnBadArgument ); 1624 1625 *conforms = (0 != object->metaCast( className )); 1626 return( kIOReturnSuccess ); 1627} 1628 1629/* Routine io_object_get_retain_count */ 1630kern_return_t is_io_object_get_retain_count( 1631 io_object_t object, 1632 uint32_t *retainCount ) 1633{ 1634 if( !object) 1635 return( kIOReturnBadArgument ); 1636 1637 *retainCount = object->getRetainCount(); 1638 return( kIOReturnSuccess ); 1639} 1640 1641/* Routine io_iterator_next */ 1642kern_return_t is_io_iterator_next( 1643 io_object_t iterator, 1644 io_object_t *object ) 1645{ 1646 OSObject * obj; 1647 1648 CHECK( OSIterator, iterator, iter ); 1649 1650 obj = iter->getNextObject(); 1651 if( obj) { 1652 obj->retain(); 1653 *object = obj; 1654 return( kIOReturnSuccess ); 1655 } else 1656 return( kIOReturnNoDevice ); 1657} 1658 1659/* Routine io_iterator_reset */ 1660kern_return_t is_io_iterator_reset( 1661 io_object_t iterator ) 1662{ 1663 CHECK( OSIterator, iterator, iter ); 1664 1665 iter->reset(); 1666 1667 return( kIOReturnSuccess ); 1668} 1669 1670/* Routine io_iterator_is_valid */ 1671kern_return_t is_io_iterator_is_valid( 1672 io_object_t iterator, 1673 boolean_t *is_valid ) 1674{ 1675 CHECK( OSIterator, iterator, iter ); 1676 1677 *is_valid = iter->isValid(); 1678 1679 return( kIOReturnSuccess ); 1680} 1681 1682 1683static kern_return_t internal_io_service_match_property_table( 1684 io_service_t _service, 1685 const char * matching, 1686 mach_msg_type_number_t matching_size, 1687 boolean_t *matches) 1688{ 1689 CHECK( IOService, _service, service ); 1690 1691 kern_return_t kr; 1692 OSObject * obj; 1693 OSDictionary * dict; 1694 1695 obj = matching_size ? OSUnserializeXML(matching, matching_size) 1696 : OSUnserializeXML(matching); 1697 if( (dict = OSDynamicCast( OSDictionary, obj))) { 1698 *matches = service->passiveMatch( dict ); 1699 kr = kIOReturnSuccess; 1700 } else 1701 kr = kIOReturnBadArgument; 1702 1703 if( obj) 1704 obj->release(); 1705 1706 return( kr ); 1707} 1708 1709/* Routine io_service_match_property_table */ 1710kern_return_t is_io_service_match_property_table( 1711 io_service_t service, 1712 io_string_t matching, 1713 boolean_t *matches ) 1714{ 1715 return (internal_io_service_match_property_table(service, matching, 0, matches)); 1716} 1717 1718 1719/* Routine io_service_match_property_table_ool */ 1720kern_return_t is_io_service_match_property_table_ool( 1721 io_object_t service, 1722 io_buf_ptr_t matching, 1723 mach_msg_type_number_t matchingCnt, 1724 kern_return_t *result, 1725 boolean_t *matches ) 1726{ 1727 kern_return_t kr; 1728 vm_offset_t data; 1729 vm_map_offset_t map_data; 1730 1731 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching ); 1732 data = CAST_DOWN(vm_offset_t, map_data); 1733 1734 if( KERN_SUCCESS == kr) { 1735 // must return success after vm_map_copyout() succeeds 1736 *result = internal_io_service_match_property_table(service, 1737 (const char *)data, matchingCnt, matches ); 1738 vm_deallocate( kernel_map, data, matchingCnt ); 1739 } 1740 1741 return( kr ); 1742} 1743 1744/* Routine io_service_match_property_table_bin */ 1745kern_return_t is_io_service_match_property_table_bin( 1746 io_object_t service, 1747 io_struct_inband_t matching, 1748 mach_msg_type_number_t matchingCnt, 1749 boolean_t *matches) 1750{ 1751 return (internal_io_service_match_property_table(service, matching, matchingCnt, matches)); 1752} 1753 1754static kern_return_t internal_io_service_get_matching_services( 1755 mach_port_t master_port, 1756 const char * matching, 1757 mach_msg_type_number_t matching_size, 1758 io_iterator_t *existing ) 1759{ 1760 kern_return_t kr; 1761 OSObject * obj; 1762 OSDictionary * dict; 1763 1764 if( master_port != master_device_port) 1765 return( kIOReturnNotPrivileged); 1766 1767 obj = matching_size ? OSUnserializeXML(matching, matching_size) 1768 : OSUnserializeXML(matching); 1769 if( (dict = OSDynamicCast( OSDictionary, obj))) { 1770 *existing = IOService::getMatchingServices( dict ); 1771 kr = kIOReturnSuccess; 1772 } else 1773 kr = kIOReturnBadArgument; 1774 1775 if( obj) 1776 obj->release(); 1777 1778 return( kr ); 1779} 1780 1781/* Routine io_service_get_matching_services */ 1782kern_return_t is_io_service_get_matching_services( 1783 mach_port_t master_port, 1784 io_string_t matching, 1785 io_iterator_t *existing ) 1786{ 1787 return (internal_io_service_get_matching_services(master_port, matching, 0, existing)); 1788} 1789 1790/* Routine io_service_get_matching_services_ool */ 1791kern_return_t is_io_service_get_matching_services_ool( 1792 mach_port_t master_port, 1793 io_buf_ptr_t matching, 1794 mach_msg_type_number_t matchingCnt, 1795 kern_return_t *result, 1796 io_object_t *existing ) 1797{ 1798 kern_return_t kr; 1799 vm_offset_t data; 1800 vm_map_offset_t map_data; 1801 1802 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching ); 1803 data = CAST_DOWN(vm_offset_t, map_data); 1804 1805 if( KERN_SUCCESS == kr) { 1806 // must return success after vm_map_copyout() succeeds 1807 *result = internal_io_service_get_matching_services(master_port, 1808 (const char *) data, matchingCnt, existing); 1809 vm_deallocate( kernel_map, data, matchingCnt ); 1810 } 1811 1812 return( kr ); 1813} 1814 1815/* Routine io_service_get_matching_services_bin */ 1816kern_return_t is_io_service_get_matching_services_bin( 1817 mach_port_t master_port, 1818 io_struct_inband_t matching, 1819 mach_msg_type_number_t matchingCnt, 1820 io_object_t *existing) 1821{ 1822 return (internal_io_service_get_matching_services(master_port, matching, matchingCnt, existing)); 1823} 1824 1825 1826static kern_return_t internal_io_service_get_matching_service( 1827 mach_port_t master_port, 1828 const char * matching, 1829 mach_msg_type_number_t matching_size, 1830 io_service_t *service ) 1831{ 1832 kern_return_t kr; 1833 OSObject * obj; 1834 OSDictionary * dict; 1835 1836 if( master_port != master_device_port) 1837 return( kIOReturnNotPrivileged); 1838 1839 obj = matching_size ? OSUnserializeXML(matching, matching_size) 1840 : OSUnserializeXML(matching); 1841 if( (dict = OSDynamicCast( OSDictionary, obj))) { 1842 *service = IOService::copyMatchingService( dict ); 1843 kr = *service ? kIOReturnSuccess : kIOReturnNotFound; 1844 } else 1845 kr = kIOReturnBadArgument; 1846 1847 if( obj) 1848 obj->release(); 1849 1850 return( kr ); 1851} 1852 1853/* Routine io_service_get_matching_service */ 1854kern_return_t is_io_service_get_matching_service( 1855 mach_port_t master_port, 1856 io_string_t matching, 1857 io_service_t *service ) 1858{ 1859 return (internal_io_service_get_matching_service(master_port, matching, 0, service)); 1860} 1861 1862/* Routine io_service_get_matching_services_ool */ 1863kern_return_t is_io_service_get_matching_service_ool( 1864 mach_port_t master_port, 1865 io_buf_ptr_t matching, 1866 mach_msg_type_number_t matchingCnt, 1867 kern_return_t *result, 1868 io_object_t *service ) 1869{ 1870 kern_return_t kr; 1871 vm_offset_t data; 1872 vm_map_offset_t map_data; 1873 1874 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching ); 1875 data = CAST_DOWN(vm_offset_t, map_data); 1876 1877 if( KERN_SUCCESS == kr) { 1878 // must return success after vm_map_copyout() succeeds 1879 *result = internal_io_service_get_matching_service(master_port, 1880 (const char *) data, matchingCnt, service ); 1881 vm_deallocate( kernel_map, data, matchingCnt ); 1882 } 1883 1884 return( kr ); 1885} 1886 1887/* Routine io_service_get_matching_service_bin */ 1888kern_return_t is_io_service_get_matching_service_bin( 1889 mach_port_t master_port, 1890 io_struct_inband_t matching, 1891 mach_msg_type_number_t matchingCnt, 1892 io_object_t *service) 1893{ 1894 return (internal_io_service_get_matching_service(master_port, matching, matchingCnt, service)); 1895} 1896 1897static kern_return_t internal_io_service_add_notification( 1898 mach_port_t master_port, 1899 io_name_t notification_type, 1900 const char * matching, 1901 size_t matching_size, 1902 mach_port_t port, 1903 void * reference, 1904 vm_size_t referenceSize, 1905 bool client64, 1906 io_object_t * notification ) 1907{ 1908 IOServiceUserNotification * userNotify = 0; 1909 IONotifier * notify = 0; 1910 const OSSymbol * sym; 1911 OSDictionary * dict; 1912 IOReturn err; 1913 unsigned long int userMsgType; 1914 1915 if( master_port != master_device_port) 1916 return( kIOReturnNotPrivileged); 1917 1918 do { 1919 err = kIOReturnNoResources; 1920 1921 if( !(sym = OSSymbol::withCString( notification_type ))) 1922 err = kIOReturnNoResources; 1923 1924 if (matching_size) 1925 { 1926 dict = OSDynamicCast(OSDictionary, OSUnserializeXML(matching, matching_size)); 1927 } 1928 else 1929 { 1930 dict = OSDynamicCast(OSDictionary, OSUnserializeXML(matching)); 1931 } 1932 1933 if (!dict) { 1934 err = kIOReturnBadArgument; 1935 continue; 1936 } 1937 1938 if( (sym == gIOPublishNotification) 1939 || (sym == gIOFirstPublishNotification)) 1940 userMsgType = kIOServicePublishNotificationType; 1941 else if( (sym == gIOMatchedNotification) 1942 || (sym == gIOFirstMatchNotification)) 1943 userMsgType = kIOServiceMatchedNotificationType; 1944 else if( sym == gIOTerminatedNotification) 1945 userMsgType = kIOServiceTerminatedNotificationType; 1946 else 1947 userMsgType = kLastIOKitNotificationType; 1948 1949 userNotify = new IOServiceUserNotification; 1950 1951 if( userNotify && !userNotify->init( port, userMsgType, 1952 reference, referenceSize, client64)) { 1953 iokit_release_port_send(port); 1954 userNotify->release(); 1955 userNotify = 0; 1956 } 1957 if( !userNotify) 1958 continue; 1959 1960 notify = IOService::addMatchingNotification( sym, dict, 1961 &userNotify->_handler, userNotify ); 1962 if( notify) { 1963 *notification = userNotify; 1964 userNotify->setNotification( notify ); 1965 err = kIOReturnSuccess; 1966 } else 1967 err = kIOReturnUnsupported; 1968 1969 } while( false ); 1970 1971 if( sym) 1972 sym->release(); 1973 if( dict) 1974 dict->release(); 1975 1976 return( err ); 1977} 1978 1979 1980/* Routine io_service_add_notification */ 1981kern_return_t is_io_service_add_notification( 1982 mach_port_t master_port, 1983 io_name_t notification_type, 1984 io_string_t matching, 1985 mach_port_t port, 1986 io_async_ref_t reference, 1987 mach_msg_type_number_t referenceCnt, 1988 io_object_t * notification ) 1989{ 1990 return (internal_io_service_add_notification(master_port, notification_type, 1991 matching, 0, port, &reference[0], sizeof(io_async_ref_t), 1992 false, notification)); 1993} 1994 1995/* Routine io_service_add_notification_64 */ 1996kern_return_t is_io_service_add_notification_64( 1997 mach_port_t master_port, 1998 io_name_t notification_type, 1999 io_string_t matching, 2000 mach_port_t wake_port, 2001 io_async_ref64_t reference, 2002 mach_msg_type_number_t referenceCnt, 2003 io_object_t *notification ) 2004{ 2005 return (internal_io_service_add_notification(master_port, notification_type, 2006 matching, 0, wake_port, &reference[0], sizeof(io_async_ref64_t), 2007 true, notification)); 2008} 2009 2010/* Routine io_service_add_notification_bin */ 2011kern_return_t is_io_service_add_notification_bin 2012( 2013 mach_port_t master_port, 2014 io_name_t notification_type, 2015 io_struct_inband_t matching, 2016 mach_msg_type_number_t matchingCnt, 2017 mach_port_t wake_port, 2018 io_async_ref_t reference, 2019 mach_msg_type_number_t referenceCnt, 2020 io_object_t *notification) 2021{ 2022 return (internal_io_service_add_notification(master_port, notification_type, 2023 matching, matchingCnt, wake_port, &reference[0], sizeof(io_async_ref_t), 2024 false, notification)); 2025} 2026 2027/* Routine io_service_add_notification_bin_64 */ 2028kern_return_t is_io_service_add_notification_bin_64 2029( 2030 mach_port_t master_port, 2031 io_name_t notification_type, 2032 io_struct_inband_t matching, 2033 mach_msg_type_number_t matchingCnt, 2034 mach_port_t wake_port, 2035 io_async_ref64_t reference, 2036 mach_msg_type_number_t referenceCnt, 2037 io_object_t *notification) 2038{ 2039 return (internal_io_service_add_notification(master_port, notification_type, 2040 matching, matchingCnt, wake_port, &reference[0], sizeof(io_async_ref64_t), 2041 true, notification)); 2042} 2043 2044static kern_return_t internal_io_service_add_notification_ool( 2045 mach_port_t master_port, 2046 io_name_t notification_type, 2047 io_buf_ptr_t matching, 2048 mach_msg_type_number_t matchingCnt, 2049 mach_port_t wake_port, 2050 void * reference, 2051 vm_size_t referenceSize, 2052 bool client64, 2053 kern_return_t *result, 2054 io_object_t *notification ) 2055{ 2056 kern_return_t kr; 2057 vm_offset_t data; 2058 vm_map_offset_t map_data; 2059 2060 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching ); 2061 data = CAST_DOWN(vm_offset_t, map_data); 2062 2063 if( KERN_SUCCESS == kr) { 2064 // must return success after vm_map_copyout() succeeds 2065 *result = internal_io_service_add_notification( master_port, notification_type, 2066 (char *) data, matchingCnt, wake_port, reference, referenceSize, client64, notification ); 2067 vm_deallocate( kernel_map, data, matchingCnt ); 2068 } 2069 2070 return( kr ); 2071} 2072 2073/* Routine io_service_add_notification_ool */ 2074kern_return_t is_io_service_add_notification_ool( 2075 mach_port_t master_port, 2076 io_name_t notification_type, 2077 io_buf_ptr_t matching, 2078 mach_msg_type_number_t matchingCnt, 2079 mach_port_t wake_port, 2080 io_async_ref_t reference, 2081 mach_msg_type_number_t referenceCnt, 2082 kern_return_t *result, 2083 io_object_t *notification ) 2084{ 2085 return (internal_io_service_add_notification_ool(master_port, notification_type, 2086 matching, matchingCnt, wake_port, &reference[0], sizeof(io_async_ref_t), 2087 false, result, notification)); 2088} 2089 2090/* Routine io_service_add_notification_ool_64 */ 2091kern_return_t is_io_service_add_notification_ool_64( 2092 mach_port_t master_port, 2093 io_name_t notification_type, 2094 io_buf_ptr_t matching, 2095 mach_msg_type_number_t matchingCnt, 2096 mach_port_t wake_port, 2097 io_async_ref64_t reference, 2098 mach_msg_type_number_t referenceCnt, 2099 kern_return_t *result, 2100 io_object_t *notification ) 2101{ 2102 return (internal_io_service_add_notification_ool(master_port, notification_type, 2103 matching, matchingCnt, wake_port, &reference[0], sizeof(io_async_ref64_t), 2104 true, result, notification)); 2105} 2106 2107/* Routine io_service_add_notification_old */ 2108kern_return_t is_io_service_add_notification_old( 2109 mach_port_t master_port, 2110 io_name_t notification_type, 2111 io_string_t matching, 2112 mach_port_t port, 2113 // for binary compatibility reasons, this must be natural_t for ILP32 2114 natural_t ref, 2115 io_object_t * notification ) 2116{ 2117 return( is_io_service_add_notification( master_port, notification_type, 2118 matching, port, &ref, 1, notification )); 2119} 2120 2121 2122static kern_return_t internal_io_service_add_interest_notification( 2123 io_object_t _service, 2124 io_name_t type_of_interest, 2125 mach_port_t port, 2126 void * reference, 2127 vm_size_t referenceSize, 2128 bool client64, 2129 io_object_t * notification ) 2130{ 2131 2132 IOServiceMessageUserNotification * userNotify = 0; 2133 IONotifier * notify = 0; 2134 const OSSymbol * sym; 2135 IOReturn err; 2136 2137 CHECK( IOService, _service, service ); 2138 2139 err = kIOReturnNoResources; 2140 if( (sym = OSSymbol::withCString( type_of_interest ))) do { 2141 2142 userNotify = new IOServiceMessageUserNotification; 2143 2144 if( userNotify && !userNotify->init( port, kIOServiceMessageNotificationType, 2145 reference, referenceSize, 2146 kIOUserNotifyMaxMessageSize, 2147 client64 )) { 2148 iokit_release_port_send(port); 2149 userNotify->release(); 2150 userNotify = 0; 2151 } 2152 if( !userNotify) 2153 continue; 2154 2155 notify = service->registerInterest( sym, 2156 &userNotify->_handler, userNotify ); 2157 if( notify) { 2158 *notification = userNotify; 2159 userNotify->setNotification( notify ); 2160 err = kIOReturnSuccess; 2161 } else 2162 err = kIOReturnUnsupported; 2163 2164 sym->release(); 2165 2166 } while( false ); 2167 2168 return( err ); 2169} 2170 2171/* Routine io_service_add_message_notification */ 2172kern_return_t is_io_service_add_interest_notification( 2173 io_object_t service, 2174 io_name_t type_of_interest, 2175 mach_port_t port, 2176 io_async_ref_t reference, 2177 mach_msg_type_number_t referenceCnt, 2178 io_object_t * notification ) 2179{ 2180 return (internal_io_service_add_interest_notification(service, type_of_interest, 2181 port, &reference[0], sizeof(io_async_ref_t), false, notification)); 2182} 2183 2184/* Routine io_service_add_interest_notification_64 */ 2185kern_return_t is_io_service_add_interest_notification_64( 2186 io_object_t service, 2187 io_name_t type_of_interest, 2188 mach_port_t wake_port, 2189 io_async_ref64_t reference, 2190 mach_msg_type_number_t referenceCnt, 2191 io_object_t *notification ) 2192{ 2193 return (internal_io_service_add_interest_notification(service, type_of_interest, 2194 wake_port, &reference[0], sizeof(io_async_ref64_t), true, notification)); 2195} 2196 2197 2198/* Routine io_service_acknowledge_notification */ 2199kern_return_t is_io_service_acknowledge_notification( 2200 io_object_t _service, 2201 natural_t notify_ref, 2202 natural_t response ) 2203{ 2204 CHECK( IOService, _service, service ); 2205 2206 return( service->acknowledgeNotification( (IONotificationRef)(uintptr_t) notify_ref, 2207 (IOOptionBits) response )); 2208 2209} 2210 2211/* Routine io_connect_get_semaphore */ 2212kern_return_t is_io_connect_get_notification_semaphore( 2213 io_connect_t connection, 2214 natural_t notification_type, 2215 semaphore_t *semaphore ) 2216{ 2217 CHECK( IOUserClient, connection, client ); 2218 2219 IOStatisticsClientCall(); 2220 return( client->getNotificationSemaphore( (UInt32) notification_type, 2221 semaphore )); 2222} 2223 2224/* Routine io_registry_get_root_entry */ 2225kern_return_t is_io_registry_get_root_entry( 2226 mach_port_t master_port, 2227 io_object_t *root ) 2228{ 2229 IORegistryEntry * entry; 2230 2231 if( master_port != master_device_port) 2232 return( kIOReturnNotPrivileged); 2233 2234 entry = IORegistryEntry::getRegistryRoot(); 2235 if( entry) 2236 entry->retain(); 2237 *root = entry; 2238 2239 return( kIOReturnSuccess ); 2240} 2241 2242/* Routine io_registry_create_iterator */ 2243kern_return_t is_io_registry_create_iterator( 2244 mach_port_t master_port, 2245 io_name_t plane, 2246 uint32_t options, 2247 io_object_t *iterator ) 2248{ 2249 if( master_port != master_device_port) 2250 return( kIOReturnNotPrivileged); 2251 2252 *iterator = IORegistryIterator::iterateOver( 2253 IORegistryEntry::getPlane( plane ), options ); 2254 2255 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument ); 2256} 2257 2258/* Routine io_registry_entry_create_iterator */ 2259kern_return_t is_io_registry_entry_create_iterator( 2260 io_object_t registry_entry, 2261 io_name_t plane, 2262 uint32_t options, 2263 io_object_t *iterator ) 2264{ 2265 CHECK( IORegistryEntry, registry_entry, entry ); 2266 2267 *iterator = IORegistryIterator::iterateOver( entry, 2268 IORegistryEntry::getPlane( plane ), options ); 2269 2270 return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument ); 2271} 2272 2273/* Routine io_registry_iterator_enter */ 2274kern_return_t is_io_registry_iterator_enter_entry( 2275 io_object_t iterator ) 2276{ 2277 CHECK( IORegistryIterator, iterator, iter ); 2278 2279 iter->enterEntry(); 2280 2281 return( kIOReturnSuccess ); 2282} 2283 2284/* Routine io_registry_iterator_exit */ 2285kern_return_t is_io_registry_iterator_exit_entry( 2286 io_object_t iterator ) 2287{ 2288 bool didIt; 2289 2290 CHECK( IORegistryIterator, iterator, iter ); 2291 2292 didIt = iter->exitEntry(); 2293 2294 return( didIt ? kIOReturnSuccess : kIOReturnNoDevice ); 2295} 2296 2297/* Routine io_registry_entry_from_path */ 2298kern_return_t is_io_registry_entry_from_path( 2299 mach_port_t master_port, 2300 io_string_t path, 2301 io_object_t *registry_entry ) 2302{ 2303 IORegistryEntry * entry; 2304 2305 if( master_port != master_device_port) 2306 return( kIOReturnNotPrivileged); 2307 2308 entry = IORegistryEntry::fromPath( path ); 2309 2310 *registry_entry = entry; 2311 2312 return( kIOReturnSuccess ); 2313} 2314 2315/* Routine io_registry_entry_in_plane */ 2316kern_return_t is_io_registry_entry_in_plane( 2317 io_object_t registry_entry, 2318 io_name_t plane, 2319 boolean_t *inPlane ) 2320{ 2321 CHECK( IORegistryEntry, registry_entry, entry ); 2322 2323 *inPlane = entry->inPlane( IORegistryEntry::getPlane( plane )); 2324 2325 return( kIOReturnSuccess ); 2326} 2327 2328 2329/* Routine io_registry_entry_get_path */ 2330kern_return_t is_io_registry_entry_get_path( 2331 io_object_t registry_entry, 2332 io_name_t plane, 2333 io_string_t path ) 2334{ 2335 int length; 2336 CHECK( IORegistryEntry, registry_entry, entry ); 2337 2338 length = sizeof( io_string_t); 2339 if( entry->getPath( path, &length, IORegistryEntry::getPlane( plane ))) 2340 return( kIOReturnSuccess ); 2341 else 2342 return( kIOReturnBadArgument ); 2343} 2344 2345 2346/* Routine io_registry_entry_get_name */ 2347kern_return_t is_io_registry_entry_get_name( 2348 io_object_t registry_entry, 2349 io_name_t name ) 2350{ 2351 CHECK( IORegistryEntry, registry_entry, entry ); 2352 2353 strncpy( name, entry->getName(), sizeof( io_name_t)); 2354 2355 return( kIOReturnSuccess ); 2356} 2357 2358/* Routine io_registry_entry_get_name_in_plane */ 2359kern_return_t is_io_registry_entry_get_name_in_plane( 2360 io_object_t registry_entry, 2361 io_name_t planeName, 2362 io_name_t name ) 2363{ 2364 const IORegistryPlane * plane; 2365 CHECK( IORegistryEntry, registry_entry, entry ); 2366 2367 if( planeName[0]) 2368 plane = IORegistryEntry::getPlane( planeName ); 2369 else 2370 plane = 0; 2371 2372 strncpy( name, entry->getName( plane), sizeof( io_name_t)); 2373 2374 return( kIOReturnSuccess ); 2375} 2376 2377/* Routine io_registry_entry_get_location_in_plane */ 2378kern_return_t is_io_registry_entry_get_location_in_plane( 2379 io_object_t registry_entry, 2380 io_name_t planeName, 2381 io_name_t location ) 2382{ 2383 const IORegistryPlane * plane; 2384 CHECK( IORegistryEntry, registry_entry, entry ); 2385 2386 if( planeName[0]) 2387 plane = IORegistryEntry::getPlane( planeName ); 2388 else 2389 plane = 0; 2390 2391 const char * cstr = entry->getLocation( plane ); 2392 2393 if( cstr) { 2394 strncpy( location, cstr, sizeof( io_name_t)); 2395 return( kIOReturnSuccess ); 2396 } else 2397 return( kIOReturnNotFound ); 2398} 2399 2400/* Routine io_registry_entry_get_registry_entry_id */ 2401kern_return_t is_io_registry_entry_get_registry_entry_id( 2402 io_object_t registry_entry, 2403 uint64_t *entry_id ) 2404{ 2405 CHECK( IORegistryEntry, registry_entry, entry ); 2406 2407 *entry_id = entry->getRegistryEntryID(); 2408 2409 return (kIOReturnSuccess); 2410} 2411 2412// Create a vm_map_copy_t or kalloc'ed data for memory 2413// to be copied out. ipc will free after the copyout. 2414 2415static kern_return_t copyoutkdata( const void * data, vm_size_t len, 2416 io_buf_ptr_t * buf ) 2417{ 2418 kern_return_t err; 2419 vm_map_copy_t copy; 2420 2421 err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len, 2422 false /* src_destroy */, ©); 2423 2424 assert( err == KERN_SUCCESS ); 2425 if( err == KERN_SUCCESS ) 2426 *buf = (char *) copy; 2427 2428 return( err ); 2429} 2430 2431/* Routine io_registry_entry_get_property */ 2432kern_return_t is_io_registry_entry_get_property_bytes( 2433 io_object_t registry_entry, 2434 io_name_t property_name, 2435 io_struct_inband_t buf, 2436 mach_msg_type_number_t *dataCnt ) 2437{ 2438 OSObject * obj; 2439 OSData * data; 2440 OSString * str; 2441 OSBoolean * boo; 2442 OSNumber * off; 2443 UInt64 offsetBytes; 2444 unsigned int len = 0; 2445 const void * bytes = 0; 2446 IOReturn ret = kIOReturnSuccess; 2447 2448 CHECK( IORegistryEntry, registry_entry, entry ); 2449 2450#if CONFIG_MACF 2451 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) 2452 return kIOReturnNotPermitted; 2453#endif 2454 2455 obj = entry->copyProperty(property_name); 2456 if( !obj) 2457 return( kIOReturnNoResources ); 2458 2459 // One day OSData will be a common container base class 2460 // until then... 2461 if( (data = OSDynamicCast( OSData, obj ))) { 2462 len = data->getLength(); 2463 bytes = data->getBytesNoCopy(); 2464 2465 } else if( (str = OSDynamicCast( OSString, obj ))) { 2466 len = str->getLength() + 1; 2467 bytes = str->getCStringNoCopy(); 2468 2469 } else if( (boo = OSDynamicCast( OSBoolean, obj ))) { 2470 len = boo->isTrue() ? sizeof("Yes") : sizeof("No"); 2471 bytes = boo->isTrue() ? "Yes" : "No"; 2472 2473 } else if( (off = OSDynamicCast( OSNumber, obj ))) { 2474 offsetBytes = off->unsigned64BitValue(); 2475 len = off->numberOfBytes(); 2476 bytes = &offsetBytes; 2477#ifdef __BIG_ENDIAN__ 2478 bytes = (const void *) 2479 (((UInt32) bytes) + (sizeof( UInt64) - len)); 2480#endif 2481 2482 } else 2483 ret = kIOReturnBadArgument; 2484 2485 if( bytes) { 2486 if( *dataCnt < len) 2487 ret = kIOReturnIPCError; 2488 else { 2489 *dataCnt = len; 2490 bcopy( bytes, buf, len ); 2491 } 2492 } 2493 obj->release(); 2494 2495 return( ret ); 2496} 2497 2498 2499/* Routine io_registry_entry_get_property */ 2500kern_return_t is_io_registry_entry_get_property( 2501 io_object_t registry_entry, 2502 io_name_t property_name, 2503 io_buf_ptr_t *properties, 2504 mach_msg_type_number_t *propertiesCnt ) 2505{ 2506 kern_return_t err; 2507 vm_size_t len; 2508 OSObject * obj; 2509 2510 CHECK( IORegistryEntry, registry_entry, entry ); 2511 2512#if CONFIG_MACF 2513 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) 2514 return kIOReturnNotPermitted; 2515#endif 2516 2517 obj = entry->copyProperty(property_name); 2518 if( !obj) 2519 return( kIOReturnNotFound ); 2520 2521 OSSerialize * s = OSSerialize::withCapacity(4096); 2522 if( !s) { 2523 obj->release(); 2524 return( kIOReturnNoMemory ); 2525 } 2526 2527 if( obj->serialize( s )) { 2528 len = s->getLength(); 2529 *propertiesCnt = len; 2530 err = copyoutkdata( s->text(), len, properties ); 2531 2532 } else 2533 err = kIOReturnUnsupported; 2534 2535 s->release(); 2536 obj->release(); 2537 2538 return( err ); 2539} 2540 2541/* Routine io_registry_entry_get_property_recursively */ 2542kern_return_t is_io_registry_entry_get_property_recursively( 2543 io_object_t registry_entry, 2544 io_name_t plane, 2545 io_name_t property_name, 2546 uint32_t options, 2547 io_buf_ptr_t *properties, 2548 mach_msg_type_number_t *propertiesCnt ) 2549{ 2550 kern_return_t err; 2551 vm_size_t len; 2552 OSObject * obj; 2553 2554 CHECK( IORegistryEntry, registry_entry, entry ); 2555 2556#if CONFIG_MACF 2557 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) 2558 return kIOReturnNotPermitted; 2559#endif 2560 2561 obj = entry->copyProperty( property_name, 2562 IORegistryEntry::getPlane( plane ), options); 2563 if( !obj) 2564 return( kIOReturnNotFound ); 2565 2566 OSSerialize * s = OSSerialize::withCapacity(4096); 2567 if( !s) { 2568 obj->release(); 2569 return( kIOReturnNoMemory ); 2570 } 2571 2572 if( obj->serialize( s )) { 2573 len = s->getLength(); 2574 *propertiesCnt = len; 2575 err = copyoutkdata( s->text(), len, properties ); 2576 2577 } else 2578 err = kIOReturnUnsupported; 2579 2580 s->release(); 2581 obj->release(); 2582 2583 return( err ); 2584} 2585 2586#if CONFIG_MACF 2587 2588static kern_return_t 2589filteredProperties(IORegistryEntry *entry, OSDictionary *properties, OSDictionary **filteredp) 2590{ 2591 kern_return_t err = 0; 2592 OSDictionary *filtered = NULL; 2593 OSCollectionIterator *iter = NULL; 2594 OSSymbol *key; 2595 OSObject *p; 2596 kauth_cred_t cred = kauth_cred_get(); 2597 2598 if (properties == NULL) 2599 return kIOReturnUnsupported; 2600 2601 if ((iter = OSCollectionIterator::withCollection(properties)) == NULL || 2602 (filtered = OSDictionary::withCapacity(properties->getCapacity())) == NULL) { 2603 err = kIOReturnNoMemory; 2604 goto out; 2605 } 2606 2607 while ((p = iter->getNextObject()) != NULL) { 2608 if ((key = OSDynamicCast(OSSymbol, p)) == NULL || 2609 mac_iokit_check_get_property(cred, entry, key->getCStringNoCopy()) != 0) 2610 continue; 2611 filtered->setObject(key, properties->getObject(key)); 2612 } 2613 2614out: 2615 if (iter != NULL) 2616 iter->release(); 2617 *filteredp = filtered; 2618 return err; 2619} 2620 2621#endif 2622 2623/* Routine io_registry_entry_get_properties */ 2624kern_return_t is_io_registry_entry_get_properties( 2625 io_object_t registry_entry, 2626 io_buf_ptr_t *properties, 2627 mach_msg_type_number_t *propertiesCnt ) 2628{ 2629 kern_return_t err = 0; 2630 vm_size_t len; 2631 2632 CHECK( IORegistryEntry, registry_entry, entry ); 2633 2634 OSSerialize * s = OSSerialize::withCapacity(4096); 2635 if( !s) 2636 return( kIOReturnNoMemory ); 2637 2638 if (!entry->serializeProperties(s)) 2639 err = kIOReturnUnsupported; 2640 2641#if CONFIG_MACF 2642 if (!err && mac_iokit_check_filter_properties(kauth_cred_get(), entry)) { 2643 OSObject *propobj = OSUnserializeXML(s->text(), s->getLength()); 2644 OSDictionary *filteredprops = NULL; 2645 err = filteredProperties(entry, OSDynamicCast(OSDictionary, propobj), &filteredprops); 2646 if (propobj) propobj->release(); 2647 2648 if (!err) { 2649 s->clearText(); 2650 if (!filteredprops->serialize(s)) 2651 err = kIOReturnUnsupported; 2652 } 2653 if (filteredprops != NULL) 2654 filteredprops->release(); 2655 } 2656#endif /* CONFIG_MACF */ 2657 2658 if (!err) { 2659 len = s->getLength(); 2660 *propertiesCnt = len; 2661 err = copyoutkdata( s->text(), len, properties ); 2662 } 2663 2664 s->release(); 2665 return( err ); 2666} 2667 2668#if CONFIG_MACF 2669 2670struct GetPropertiesEditorRef 2671{ 2672 kauth_cred_t cred; 2673 IORegistryEntry * entry; 2674 OSCollection * root; 2675}; 2676 2677static const OSMetaClassBase * 2678GetPropertiesEditor(void * reference, 2679 OSSerialize * s, 2680 OSCollection * container, 2681 const OSSymbol * name, 2682 const OSMetaClassBase * value) 2683{ 2684 GetPropertiesEditorRef * ref = (typeof(ref)) reference; 2685 2686 if (!ref->root) ref->root = container; 2687 if (ref->root == container) 2688 { 2689 if (0 != mac_iokit_check_get_property(ref->cred, ref->entry, name->getCStringNoCopy())) 2690 { 2691 value = 0; 2692 } 2693 } 2694 if (value) value->retain(); 2695 return (value); 2696} 2697 2698#endif /* CONFIG_MACF */ 2699 2700/* Routine io_registry_entry_get_properties */ 2701kern_return_t is_io_registry_entry_get_properties_bin( 2702 io_object_t registry_entry, 2703 io_buf_ptr_t *properties, 2704 mach_msg_type_number_t *propertiesCnt) 2705{ 2706 kern_return_t err = kIOReturnSuccess; 2707 vm_size_t len; 2708 OSSerialize * s; 2709 OSSerialize::Editor editor = 0; 2710 void * editRef = 0; 2711 2712 CHECK(IORegistryEntry, registry_entry, entry); 2713 2714#if CONFIG_MACF 2715 GetPropertiesEditorRef ref; 2716 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry)) 2717 { 2718 editor = &GetPropertiesEditor; 2719 editRef = &ref; 2720 ref.cred = kauth_cred_get(); 2721 ref.entry = entry; 2722 ref.root = 0; 2723 } 2724#endif 2725 2726 s = OSSerialize::binaryWithCapacity(4096, editor, editRef); 2727 if (!s) return (kIOReturnNoMemory); 2728 2729 if (!entry->serializeProperties(s)) err = kIOReturnUnsupported; 2730 2731 if (kIOReturnSuccess == err) 2732 { 2733 len = s->getLength(); 2734 *propertiesCnt = len; 2735 err = copyoutkdata(s->text(), len, properties); 2736 } 2737 s->release(); 2738 2739 return (err); 2740} 2741 2742/* Routine io_registry_entry_get_property_bin */ 2743kern_return_t is_io_registry_entry_get_property_bin( 2744 io_object_t registry_entry, 2745 io_name_t plane, 2746 io_name_t property_name, 2747 uint32_t options, 2748 io_buf_ptr_t *properties, 2749 mach_msg_type_number_t *propertiesCnt ) 2750{ 2751 kern_return_t err; 2752 vm_size_t len; 2753 OSObject * obj; 2754 const OSSymbol * sym; 2755 2756 CHECK( IORegistryEntry, registry_entry, entry ); 2757 2758#if CONFIG_MACF 2759 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) 2760 return kIOReturnNotPermitted; 2761#endif 2762 2763 if ((kIORegistryIterateRecursively & options) && plane[0]) 2764 { 2765 obj = entry->copyProperty(property_name, 2766 IORegistryEntry::getPlane(plane), options); 2767 } 2768 else 2769 { 2770 obj = entry->copyProperty(property_name); 2771 } 2772 2773 if( !obj) 2774 return( kIOReturnNotFound ); 2775 2776 sym = OSSymbol::withCString(property_name); 2777 if (sym) 2778 { 2779 if (gIORemoveOnReadProperties->containsObject(sym)) entry->removeProperty(sym); 2780 sym->release(); 2781 } 2782 2783 OSSerialize * s = OSSerialize::binaryWithCapacity(4096); 2784 if( !s) { 2785 obj->release(); 2786 return( kIOReturnNoMemory ); 2787 } 2788 2789 if( obj->serialize( s )) { 2790 len = s->getLength(); 2791 *propertiesCnt = len; 2792 err = copyoutkdata( s->text(), len, properties ); 2793 2794 } else err = kIOReturnUnsupported; 2795 2796 s->release(); 2797 obj->release(); 2798 2799 return( err ); 2800} 2801 2802/* Routine io_registry_entry_set_properties */ 2803kern_return_t is_io_registry_entry_set_properties 2804( 2805 io_object_t registry_entry, 2806 io_buf_ptr_t properties, 2807 mach_msg_type_number_t propertiesCnt, 2808 kern_return_t * result) 2809{ 2810 OSObject * obj; 2811 kern_return_t err; 2812 IOReturn res; 2813 vm_offset_t data; 2814 vm_map_offset_t map_data; 2815 2816 CHECK( IORegistryEntry, registry_entry, entry ); 2817 2818 if( propertiesCnt > sizeof(io_struct_inband_t) * 1024) 2819 return( kIOReturnMessageTooLarge); 2820 2821 err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties ); 2822 data = CAST_DOWN(vm_offset_t, map_data); 2823 2824 if( KERN_SUCCESS == err) { 2825 2826 // must return success after vm_map_copyout() succeeds 2827 obj = OSUnserializeXML( (const char *) data, propertiesCnt ); 2828 vm_deallocate( kernel_map, data, propertiesCnt ); 2829 2830 if (!obj) 2831 res = kIOReturnBadArgument; 2832#if CONFIG_MACF 2833 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(), 2834 registry_entry, obj)) 2835 { 2836 res = kIOReturnNotPermitted; 2837 } 2838#endif 2839 else 2840 { 2841 res = entry->setProperties( obj ); 2842 } 2843 2844 if (obj) 2845 obj->release(); 2846 } else 2847 res = err; 2848 2849 *result = res; 2850 return( err ); 2851} 2852 2853/* Routine io_registry_entry_get_child_iterator */ 2854kern_return_t is_io_registry_entry_get_child_iterator( 2855 io_object_t registry_entry, 2856 io_name_t plane, 2857 io_object_t *iterator ) 2858{ 2859 CHECK( IORegistryEntry, registry_entry, entry ); 2860 2861 *iterator = entry->getChildIterator( 2862 IORegistryEntry::getPlane( plane )); 2863 2864 return( kIOReturnSuccess ); 2865} 2866 2867/* Routine io_registry_entry_get_parent_iterator */ 2868kern_return_t is_io_registry_entry_get_parent_iterator( 2869 io_object_t registry_entry, 2870 io_name_t plane, 2871 io_object_t *iterator) 2872{ 2873 CHECK( IORegistryEntry, registry_entry, entry ); 2874 2875 *iterator = entry->getParentIterator( 2876 IORegistryEntry::getPlane( plane )); 2877 2878 return( kIOReturnSuccess ); 2879} 2880 2881/* Routine io_service_get_busy_state */ 2882kern_return_t is_io_service_get_busy_state( 2883 io_object_t _service, 2884 uint32_t *busyState ) 2885{ 2886 CHECK( IOService, _service, service ); 2887 2888 *busyState = service->getBusyState(); 2889 2890 return( kIOReturnSuccess ); 2891} 2892 2893/* Routine io_service_get_state */ 2894kern_return_t is_io_service_get_state( 2895 io_object_t _service, 2896 uint64_t *state, 2897 uint32_t *busy_state, 2898 uint64_t *accumulated_busy_time ) 2899{ 2900 CHECK( IOService, _service, service ); 2901 2902 *state = service->getState(); 2903 *busy_state = service->getBusyState(); 2904 *accumulated_busy_time = service->getAccumulatedBusyTime(); 2905 2906 return( kIOReturnSuccess ); 2907} 2908 2909/* Routine io_service_wait_quiet */ 2910kern_return_t is_io_service_wait_quiet( 2911 io_object_t _service, 2912 mach_timespec_t wait_time ) 2913{ 2914 uint64_t timeoutNS; 2915 2916 CHECK( IOService, _service, service ); 2917 2918 timeoutNS = wait_time.tv_sec; 2919 timeoutNS *= kSecondScale; 2920 timeoutNS += wait_time.tv_nsec; 2921 2922 return( service->waitQuiet(timeoutNS) ); 2923} 2924 2925/* Routine io_service_request_probe */ 2926kern_return_t is_io_service_request_probe( 2927 io_object_t _service, 2928 uint32_t options ) 2929{ 2930 CHECK( IOService, _service, service ); 2931 2932 return( service->requestProbe( options )); 2933} 2934 2935/* Routine io_service_get_authorization_id */ 2936kern_return_t is_io_service_get_authorization_id( 2937 io_object_t _service, 2938 uint64_t *authorization_id ) 2939{ 2940 kern_return_t kr; 2941 2942 CHECK( IOService, _service, service ); 2943 2944 kr = IOUserClient::clientHasPrivilege( (void *) current_task(), 2945 kIOClientPrivilegeAdministrator ); 2946 if( kIOReturnSuccess != kr) 2947 return( kr ); 2948 2949 *authorization_id = service->getAuthorizationID(); 2950 2951 return( kr ); 2952} 2953 2954/* Routine io_service_set_authorization_id */ 2955kern_return_t is_io_service_set_authorization_id( 2956 io_object_t _service, 2957 uint64_t authorization_id ) 2958{ 2959 CHECK( IOService, _service, service ); 2960 2961 return( service->setAuthorizationID( authorization_id ) ); 2962} 2963 2964/* Routine io_service_open_ndr */ 2965kern_return_t is_io_service_open_extended( 2966 io_object_t _service, 2967 task_t owningTask, 2968 uint32_t connect_type, 2969 NDR_record_t ndr, 2970 io_buf_ptr_t properties, 2971 mach_msg_type_number_t propertiesCnt, 2972 kern_return_t * result, 2973 io_object_t *connection ) 2974{ 2975 IOUserClient * client = 0; 2976 kern_return_t err = KERN_SUCCESS; 2977 IOReturn res = kIOReturnSuccess; 2978 OSDictionary * propertiesDict = 0; 2979 bool crossEndian; 2980 bool disallowAccess; 2981 2982 CHECK( IOService, _service, service ); 2983 2984 do 2985 { 2986 if (properties) 2987 { 2988 OSObject * obj; 2989 vm_offset_t data; 2990 vm_map_offset_t map_data; 2991 2992 if( propertiesCnt > sizeof(io_struct_inband_t)) 2993 return( kIOReturnMessageTooLarge); 2994 2995 err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties ); 2996 res = err; 2997 data = CAST_DOWN(vm_offset_t, map_data); 2998 if (KERN_SUCCESS == err) 2999 { 3000 // must return success after vm_map_copyout() succeeds 3001 obj = OSUnserializeXML( (const char *) data, propertiesCnt ); 3002 vm_deallocate( kernel_map, data, propertiesCnt ); 3003 propertiesDict = OSDynamicCast(OSDictionary, obj); 3004 if (!propertiesDict) 3005 { 3006 res = kIOReturnBadArgument; 3007 if (obj) 3008 obj->release(); 3009 } 3010 } 3011 if (kIOReturnSuccess != res) 3012 break; 3013 } 3014 3015 crossEndian = (ndr.int_rep != NDR_record.int_rep); 3016 if (crossEndian) 3017 { 3018 if (!propertiesDict) 3019 propertiesDict = OSDictionary::withCapacity(4); 3020 OSData * data = OSData::withBytes(&ndr, sizeof(ndr)); 3021 if (data) 3022 { 3023 if (propertiesDict) 3024 propertiesDict->setObject(kIOUserClientCrossEndianKey, data); 3025 data->release(); 3026 } 3027 } 3028 3029 res = service->newUserClient( owningTask, (void *) owningTask, 3030 connect_type, propertiesDict, &client ); 3031 3032 if (propertiesDict) 3033 propertiesDict->release(); 3034 3035 if (res == kIOReturnSuccess) 3036 { 3037 assert( OSDynamicCast(IOUserClient, client) ); 3038 3039 disallowAccess = (crossEndian 3040 && (kOSBooleanTrue != service->getProperty(kIOUserClientCrossEndianCompatibleKey)) 3041 && (kOSBooleanTrue != client->getProperty(kIOUserClientCrossEndianCompatibleKey))); 3042 if (disallowAccess) res = kIOReturnUnsupported; 3043#if CONFIG_MACF 3044 else if (0 != mac_iokit_check_open(kauth_cred_get(), client, connect_type)) 3045 res = kIOReturnNotPermitted; 3046#endif 3047 if (kIOReturnSuccess != res) 3048 { 3049 IOStatisticsClientCall(); 3050 client->clientClose(); 3051 client->release(); 3052 client = 0; 3053 break; 3054 } 3055 client->sharedInstance = (0 != client->getProperty(kIOUserClientSharedInstanceKey)); 3056 OSString * creatorName = IOCopyLogNameForPID(proc_selfpid()); 3057 if (creatorName) 3058 { 3059 client->setProperty(kIOUserClientCreatorKey, creatorName); 3060 creatorName->release(); 3061 } 3062 client->setTerminateDefer(service, false); 3063 } 3064 } 3065 while (false); 3066 3067 *connection = client; 3068 *result = res; 3069 3070 return (err); 3071} 3072 3073/* Routine io_service_close */ 3074kern_return_t is_io_service_close( 3075 io_object_t connection ) 3076{ 3077 OSSet * mappings; 3078 if ((mappings = OSDynamicCast(OSSet, connection))) 3079 return( kIOReturnSuccess ); 3080 3081 CHECK( IOUserClient, connection, client ); 3082 3083 IOStatisticsClientCall(); 3084 client->clientClose(); 3085 3086 return( kIOReturnSuccess ); 3087} 3088 3089/* Routine io_connect_get_service */ 3090kern_return_t is_io_connect_get_service( 3091 io_object_t connection, 3092 io_object_t *service ) 3093{ 3094 IOService * theService; 3095 3096 CHECK( IOUserClient, connection, client ); 3097 3098 theService = client->getService(); 3099 if( theService) 3100 theService->retain(); 3101 3102 *service = theService; 3103 3104 return( theService ? kIOReturnSuccess : kIOReturnUnsupported ); 3105} 3106 3107/* Routine io_connect_set_notification_port */ 3108kern_return_t is_io_connect_set_notification_port( 3109 io_object_t connection, 3110 uint32_t notification_type, 3111 mach_port_t port, 3112 uint32_t reference) 3113{ 3114 CHECK( IOUserClient, connection, client ); 3115 3116 IOStatisticsClientCall(); 3117 return( client->registerNotificationPort( port, notification_type, 3118 (io_user_reference_t) reference )); 3119} 3120 3121/* Routine io_connect_set_notification_port */ 3122kern_return_t is_io_connect_set_notification_port_64( 3123 io_object_t connection, 3124 uint32_t notification_type, 3125 mach_port_t port, 3126 io_user_reference_t reference) 3127{ 3128 CHECK( IOUserClient, connection, client ); 3129 3130 IOStatisticsClientCall(); 3131 return( client->registerNotificationPort( port, notification_type, 3132 reference )); 3133} 3134 3135/* Routine io_connect_map_memory_into_task */ 3136kern_return_t is_io_connect_map_memory_into_task 3137( 3138 io_connect_t connection, 3139 uint32_t memory_type, 3140 task_t into_task, 3141 mach_vm_address_t *address, 3142 mach_vm_size_t *size, 3143 uint32_t flags 3144) 3145{ 3146 IOReturn err; 3147 IOMemoryMap * map; 3148 3149 CHECK( IOUserClient, connection, client ); 3150 3151 IOStatisticsClientCall(); 3152 map = client->mapClientMemory64( memory_type, into_task, flags, *address ); 3153 3154 if( map) { 3155 *address = map->getAddress(); 3156 if( size) 3157 *size = map->getSize(); 3158 3159 if( client->sharedInstance 3160 || (into_task != current_task())) { 3161 // push a name out to the task owning the map, 3162 // so we can clean up maps 3163 mach_port_name_t name __unused = 3164 IOMachPort::makeSendRightForTask( 3165 into_task, map, IKOT_IOKIT_OBJECT ); 3166 3167 } else { 3168 // keep it with the user client 3169 IOLockLock( gIOObjectPortLock); 3170 if( 0 == client->mappings) 3171 client->mappings = OSSet::withCapacity(2); 3172 if( client->mappings) 3173 client->mappings->setObject( map); 3174 IOLockUnlock( gIOObjectPortLock); 3175 map->release(); 3176 } 3177 err = kIOReturnSuccess; 3178 3179 } else 3180 err = kIOReturnBadArgument; 3181 3182 return( err ); 3183} 3184 3185/* Routine is_io_connect_map_memory */ 3186kern_return_t is_io_connect_map_memory( 3187 io_object_t connect, 3188 uint32_t type, 3189 task_t task, 3190 uint32_t * mapAddr, 3191 uint32_t * mapSize, 3192 uint32_t flags ) 3193{ 3194 IOReturn err; 3195 mach_vm_address_t address; 3196 mach_vm_size_t size; 3197 3198 address = SCALAR64(*mapAddr); 3199 size = SCALAR64(*mapSize); 3200 3201 err = is_io_connect_map_memory_into_task(connect, type, task, &address, &size, flags); 3202 3203 *mapAddr = SCALAR32(address); 3204 *mapSize = SCALAR32(size); 3205 3206 return (err); 3207} 3208 3209} /* extern "C" */ 3210 3211IOMemoryMap * IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor * mem) 3212{ 3213 OSIterator * iter; 3214 IOMemoryMap * map = 0; 3215 3216 IOLockLock(gIOObjectPortLock); 3217 3218 iter = OSCollectionIterator::withCollection(mappings); 3219 if(iter) 3220 { 3221 while ((map = OSDynamicCast(IOMemoryMap, iter->getNextObject()))) 3222 { 3223 if(mem == map->getMemoryDescriptor()) 3224 { 3225 map->retain(); 3226 mappings->removeObject(map); 3227 break; 3228 } 3229 } 3230 iter->release(); 3231 } 3232 3233 IOLockUnlock(gIOObjectPortLock); 3234 3235 return (map); 3236} 3237 3238extern "C" { 3239 3240/* Routine io_connect_unmap_memory_from_task */ 3241kern_return_t is_io_connect_unmap_memory_from_task 3242( 3243 io_connect_t connection, 3244 uint32_t memory_type, 3245 task_t from_task, 3246 mach_vm_address_t address) 3247{ 3248 IOReturn err; 3249 IOOptionBits options = 0; 3250 IOMemoryDescriptor * memory; 3251 IOMemoryMap * map; 3252 3253 CHECK( IOUserClient, connection, client ); 3254 3255 IOStatisticsClientCall(); 3256 err = client->clientMemoryForType( (UInt32) memory_type, &options, &memory ); 3257 3258 if( memory && (kIOReturnSuccess == err)) { 3259 3260 options = (options & ~kIOMapUserOptionsMask) 3261 | kIOMapAnywhere | kIOMapReference; 3262 3263 map = memory->createMappingInTask( from_task, address, options ); 3264 memory->release(); 3265 if( map) 3266 { 3267 IOLockLock( gIOObjectPortLock); 3268 if( client->mappings) 3269 client->mappings->removeObject( map); 3270 IOLockUnlock( gIOObjectPortLock); 3271 3272 mach_port_name_t name = 0; 3273 if (from_task != current_task()) 3274 name = IOMachPort::makeSendRightForTask( from_task, map, IKOT_IOKIT_OBJECT ); 3275 if (name) 3276 { 3277 map->userClientUnmap(); 3278 err = iokit_mod_send_right( from_task, name, -2 ); 3279 err = kIOReturnSuccess; 3280 } 3281 else 3282 IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT ); 3283 if (from_task == current_task()) 3284 map->release(); 3285 } 3286 else 3287 err = kIOReturnBadArgument; 3288 } 3289 3290 return( err ); 3291} 3292 3293kern_return_t is_io_connect_unmap_memory( 3294 io_object_t connect, 3295 uint32_t type, 3296 task_t task, 3297 uint32_t mapAddr ) 3298{ 3299 IOReturn err; 3300 mach_vm_address_t address; 3301 3302 address = SCALAR64(mapAddr); 3303 3304 err = is_io_connect_unmap_memory_from_task(connect, type, task, mapAddr); 3305 3306 return (err); 3307} 3308 3309 3310/* Routine io_connect_add_client */ 3311kern_return_t is_io_connect_add_client( 3312 io_object_t connection, 3313 io_object_t connect_to) 3314{ 3315 CHECK( IOUserClient, connection, client ); 3316 CHECK( IOUserClient, connect_to, to ); 3317 3318 IOStatisticsClientCall(); 3319 return( client->connectClient( to ) ); 3320} 3321 3322 3323/* Routine io_connect_set_properties */ 3324kern_return_t is_io_connect_set_properties( 3325 io_object_t connection, 3326 io_buf_ptr_t properties, 3327 mach_msg_type_number_t propertiesCnt, 3328 kern_return_t * result) 3329{ 3330 return( is_io_registry_entry_set_properties( connection, properties, propertiesCnt, result )); 3331} 3332 3333/* Routine io_user_client_method */ 3334kern_return_t is_io_connect_method_var_output 3335( 3336 io_connect_t connection, 3337 uint32_t selector, 3338 io_scalar_inband64_t scalar_input, 3339 mach_msg_type_number_t scalar_inputCnt, 3340 io_struct_inband_t inband_input, 3341 mach_msg_type_number_t inband_inputCnt, 3342 mach_vm_address_t ool_input, 3343 mach_vm_size_t ool_input_size, 3344 io_struct_inband_t inband_output, 3345 mach_msg_type_number_t *inband_outputCnt, 3346 io_scalar_inband64_t scalar_output, 3347 mach_msg_type_number_t *scalar_outputCnt, 3348 io_buf_ptr_t *var_output, 3349 mach_msg_type_number_t *var_outputCnt 3350) 3351{ 3352 CHECK( IOUserClient, connection, client ); 3353 3354 IOExternalMethodArguments args; 3355 IOReturn ret; 3356 IOMemoryDescriptor * inputMD = 0; 3357 OSObject * structureVariableOutputData = 0; 3358 3359 bzero(&args.__reserved[0], sizeof(args.__reserved)); 3360 args.version = kIOExternalMethodArgumentsCurrentVersion; 3361 3362 args.selector = selector; 3363 3364 args.asyncWakePort = MACH_PORT_NULL; 3365 args.asyncReference = 0; 3366 args.asyncReferenceCount = 0; 3367 args.structureVariableOutputData = &structureVariableOutputData; 3368 3369 args.scalarInput = scalar_input; 3370 args.scalarInputCount = scalar_inputCnt; 3371 args.structureInput = inband_input; 3372 args.structureInputSize = inband_inputCnt; 3373 3374 if (ool_input) 3375 inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size, 3376 kIODirectionOut, current_task()); 3377 3378 args.structureInputDescriptor = inputMD; 3379 3380 args.scalarOutput = scalar_output; 3381 args.scalarOutputCount = *scalar_outputCnt; 3382 bzero(&scalar_output[0], *scalar_outputCnt * sizeof(scalar_output[0])); 3383 args.structureOutput = inband_output; 3384 args.structureOutputSize = *inband_outputCnt; 3385 args.structureOutputDescriptor = NULL; 3386 args.structureOutputDescriptorSize = 0; 3387 3388 IOStatisticsClientCall(); 3389 ret = client->externalMethod( selector, &args ); 3390 3391 *scalar_outputCnt = args.scalarOutputCount; 3392 *inband_outputCnt = args.structureOutputSize; 3393 3394 if (var_outputCnt && var_output && (kIOReturnSuccess == ret)) 3395 { 3396 OSSerialize * serialize; 3397 OSData * data; 3398 vm_size_t len; 3399 3400 if ((serialize = OSDynamicCast(OSSerialize, structureVariableOutputData))) 3401 { 3402 len = serialize->getLength(); 3403 *var_outputCnt = len; 3404 ret = copyoutkdata(serialize->text(), len, var_output); 3405 } 3406 else if ((data = OSDynamicCast(OSData, structureVariableOutputData))) 3407 { 3408 len = data->getLength(); 3409 *var_outputCnt = len; 3410 ret = copyoutkdata(data->getBytesNoCopy(), len, var_output); 3411 } 3412 else 3413 { 3414 ret = kIOReturnUnderrun; 3415 } 3416 } 3417 3418 if (inputMD) 3419 inputMD->release(); 3420 if (structureVariableOutputData) 3421 structureVariableOutputData->release(); 3422 3423 return (ret); 3424} 3425 3426/* Routine io_user_client_method */ 3427kern_return_t is_io_connect_method 3428( 3429 io_connect_t connection, 3430 uint32_t selector, 3431 io_scalar_inband64_t scalar_input, 3432 mach_msg_type_number_t scalar_inputCnt, 3433 io_struct_inband_t inband_input, 3434 mach_msg_type_number_t inband_inputCnt, 3435 mach_vm_address_t ool_input, 3436 mach_vm_size_t ool_input_size, 3437 io_struct_inband_t inband_output, 3438 mach_msg_type_number_t *inband_outputCnt, 3439 io_scalar_inband64_t scalar_output, 3440 mach_msg_type_number_t *scalar_outputCnt, 3441 mach_vm_address_t ool_output, 3442 mach_vm_size_t *ool_output_size 3443) 3444{ 3445 CHECK( IOUserClient, connection, client ); 3446 3447 IOExternalMethodArguments args; 3448 IOReturn ret; 3449 IOMemoryDescriptor * inputMD = 0; 3450 IOMemoryDescriptor * outputMD = 0; 3451 3452 bzero(&args.__reserved[0], sizeof(args.__reserved)); 3453 args.version = kIOExternalMethodArgumentsCurrentVersion; 3454 3455 args.selector = selector; 3456 3457 args.asyncWakePort = MACH_PORT_NULL; 3458 args.asyncReference = 0; 3459 args.asyncReferenceCount = 0; 3460 args.structureVariableOutputData = 0; 3461 3462 args.scalarInput = scalar_input; 3463 args.scalarInputCount = scalar_inputCnt; 3464 args.structureInput = inband_input; 3465 args.structureInputSize = inband_inputCnt; 3466 3467 if (ool_input) 3468 inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size, 3469 kIODirectionOut, current_task()); 3470 3471 args.structureInputDescriptor = inputMD; 3472 3473 args.scalarOutput = scalar_output; 3474 args.scalarOutputCount = *scalar_outputCnt; 3475 bzero(&scalar_output[0], *scalar_outputCnt * sizeof(scalar_output[0])); 3476 args.structureOutput = inband_output; 3477 args.structureOutputSize = *inband_outputCnt; 3478 3479 if (ool_output && ool_output_size) 3480 { 3481 outputMD = IOMemoryDescriptor::withAddressRange(ool_output, *ool_output_size, 3482 kIODirectionIn, current_task()); 3483 } 3484 3485 args.structureOutputDescriptor = outputMD; 3486 args.structureOutputDescriptorSize = ool_output_size ? *ool_output_size : 0; 3487 3488 IOStatisticsClientCall(); 3489 ret = client->externalMethod( selector, &args ); 3490 3491 *scalar_outputCnt = args.scalarOutputCount; 3492 *inband_outputCnt = args.structureOutputSize; 3493 *ool_output_size = args.structureOutputDescriptorSize; 3494 3495 if (inputMD) 3496 inputMD->release(); 3497 if (outputMD) 3498 outputMD->release(); 3499 3500 return (ret); 3501} 3502 3503/* Routine io_async_user_client_method */ 3504kern_return_t is_io_connect_async_method 3505( 3506 io_connect_t connection, 3507 mach_port_t wake_port, 3508 io_async_ref64_t reference, 3509 mach_msg_type_number_t referenceCnt, 3510 uint32_t selector, 3511 io_scalar_inband64_t scalar_input, 3512 mach_msg_type_number_t scalar_inputCnt, 3513 io_struct_inband_t inband_input, 3514 mach_msg_type_number_t inband_inputCnt, 3515 mach_vm_address_t ool_input, 3516 mach_vm_size_t ool_input_size, 3517 io_struct_inband_t inband_output, 3518 mach_msg_type_number_t *inband_outputCnt, 3519 io_scalar_inband64_t scalar_output, 3520 mach_msg_type_number_t *scalar_outputCnt, 3521 mach_vm_address_t ool_output, 3522 mach_vm_size_t * ool_output_size 3523) 3524{ 3525 CHECK( IOUserClient, connection, client ); 3526 3527 IOExternalMethodArguments args; 3528 IOReturn ret; 3529 IOMemoryDescriptor * inputMD = 0; 3530 IOMemoryDescriptor * outputMD = 0; 3531 3532 bzero(&args.__reserved[0], sizeof(args.__reserved)); 3533 args.version = kIOExternalMethodArgumentsCurrentVersion; 3534 3535 reference[0] = (io_user_reference_t) wake_port; 3536 if (vm_map_is_64bit(get_task_map(current_task()))) 3537 reference[0] |= kIOUCAsync64Flag; 3538 3539 args.selector = selector; 3540 3541 args.asyncWakePort = wake_port; 3542 args.asyncReference = reference; 3543 args.asyncReferenceCount = referenceCnt; 3544 3545 args.scalarInput = scalar_input; 3546 args.scalarInputCount = scalar_inputCnt; 3547 args.structureInput = inband_input; 3548 args.structureInputSize = inband_inputCnt; 3549 3550 if (ool_input) 3551 inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size, 3552 kIODirectionOut, current_task()); 3553 3554 args.structureInputDescriptor = inputMD; 3555 3556 args.scalarOutput = scalar_output; 3557 args.scalarOutputCount = *scalar_outputCnt; 3558 bzero(&scalar_output[0], *scalar_outputCnt * sizeof(scalar_output[0])); 3559 args.structureOutput = inband_output; 3560 args.structureOutputSize = *inband_outputCnt; 3561 3562 if (ool_output) 3563 { 3564 outputMD = IOMemoryDescriptor::withAddressRange(ool_output, *ool_output_size, 3565 kIODirectionIn, current_task()); 3566 } 3567 3568 args.structureOutputDescriptor = outputMD; 3569 args.structureOutputDescriptorSize = *ool_output_size; 3570 3571 IOStatisticsClientCall(); 3572 ret = client->externalMethod( selector, &args ); 3573 3574 *inband_outputCnt = args.structureOutputSize; 3575 *ool_output_size = args.structureOutputDescriptorSize; 3576 3577 if (inputMD) 3578 inputMD->release(); 3579 if (outputMD) 3580 outputMD->release(); 3581 3582 return (ret); 3583} 3584 3585/* Routine io_connect_method_scalarI_scalarO */ 3586kern_return_t is_io_connect_method_scalarI_scalarO( 3587 io_object_t connect, 3588 uint32_t index, 3589 io_scalar_inband_t input, 3590 mach_msg_type_number_t inputCount, 3591 io_scalar_inband_t output, 3592 mach_msg_type_number_t * outputCount ) 3593{ 3594 IOReturn err; 3595 uint32_t i; 3596 io_scalar_inband64_t _input; 3597 io_scalar_inband64_t _output; 3598 3599 mach_msg_type_number_t struct_outputCnt = 0; 3600 mach_vm_size_t ool_output_size = 0; 3601 3602 bzero(&_output[0], sizeof(_output)); 3603 for (i = 0; i < inputCount; i++) 3604 _input[i] = SCALAR64(input[i]); 3605 3606 err = is_io_connect_method(connect, index, 3607 _input, inputCount, 3608 NULL, 0, 3609 0, 0, 3610 NULL, &struct_outputCnt, 3611 _output, outputCount, 3612 0, &ool_output_size); 3613 3614 for (i = 0; i < *outputCount; i++) 3615 output[i] = SCALAR32(_output[i]); 3616 3617 return (err); 3618} 3619 3620kern_return_t shim_io_connect_method_scalarI_scalarO( 3621 IOExternalMethod * method, 3622 IOService * object, 3623 const io_user_scalar_t * input, 3624 mach_msg_type_number_t inputCount, 3625 io_user_scalar_t * output, 3626 mach_msg_type_number_t * outputCount ) 3627{ 3628 IOMethod func; 3629 io_scalar_inband_t _output; 3630 IOReturn err; 3631 err = kIOReturnBadArgument; 3632 3633 bzero(&_output[0], sizeof(_output)); 3634 do { 3635 3636 if( inputCount != method->count0) 3637 { 3638 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName()); 3639 continue; 3640 } 3641 if( *outputCount != method->count1) 3642 { 3643 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName()); 3644 continue; 3645 } 3646 3647 func = method->func; 3648 3649 switch( inputCount) { 3650 3651 case 6: 3652 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 3653 ARG32(input[3]), ARG32(input[4]), ARG32(input[5]) ); 3654 break; 3655 case 5: 3656 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 3657 ARG32(input[3]), ARG32(input[4]), 3658 &_output[0] ); 3659 break; 3660 case 4: 3661 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 3662 ARG32(input[3]), 3663 &_output[0], &_output[1] ); 3664 break; 3665 case 3: 3666 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 3667 &_output[0], &_output[1], &_output[2] ); 3668 break; 3669 case 2: 3670 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), 3671 &_output[0], &_output[1], &_output[2], 3672 &_output[3] ); 3673 break; 3674 case 1: 3675 err = (object->*func)( ARG32(input[0]), 3676 &_output[0], &_output[1], &_output[2], 3677 &_output[3], &_output[4] ); 3678 break; 3679 case 0: 3680 err = (object->*func)( &_output[0], &_output[1], &_output[2], 3681 &_output[3], &_output[4], &_output[5] ); 3682 break; 3683 3684 default: 3685 IOLog("%s: Bad method table\n", object->getName()); 3686 } 3687 } 3688 while( false); 3689 3690 uint32_t i; 3691 for (i = 0; i < *outputCount; i++) 3692 output[i] = SCALAR32(_output[i]); 3693 3694 return( err); 3695} 3696 3697/* Routine io_async_method_scalarI_scalarO */ 3698kern_return_t is_io_async_method_scalarI_scalarO( 3699 io_object_t connect, 3700 mach_port_t wake_port, 3701 io_async_ref_t reference, 3702 mach_msg_type_number_t referenceCnt, 3703 uint32_t index, 3704 io_scalar_inband_t input, 3705 mach_msg_type_number_t inputCount, 3706 io_scalar_inband_t output, 3707 mach_msg_type_number_t * outputCount ) 3708{ 3709 IOReturn err; 3710 uint32_t i; 3711 io_scalar_inband64_t _input; 3712 io_scalar_inband64_t _output; 3713 io_async_ref64_t _reference; 3714 3715 bzero(&_output[0], sizeof(_output)); 3716 for (i = 0; i < referenceCnt; i++) 3717 _reference[i] = REF64(reference[i]); 3718 3719 mach_msg_type_number_t struct_outputCnt = 0; 3720 mach_vm_size_t ool_output_size = 0; 3721 3722 for (i = 0; i < inputCount; i++) 3723 _input[i] = SCALAR64(input[i]); 3724 3725 err = is_io_connect_async_method(connect, 3726 wake_port, _reference, referenceCnt, 3727 index, 3728 _input, inputCount, 3729 NULL, 0, 3730 0, 0, 3731 NULL, &struct_outputCnt, 3732 _output, outputCount, 3733 0, &ool_output_size); 3734 3735 for (i = 0; i < *outputCount; i++) 3736 output[i] = SCALAR32(_output[i]); 3737 3738 return (err); 3739} 3740/* Routine io_async_method_scalarI_structureO */ 3741kern_return_t is_io_async_method_scalarI_structureO( 3742 io_object_t connect, 3743 mach_port_t wake_port, 3744 io_async_ref_t reference, 3745 mach_msg_type_number_t referenceCnt, 3746 uint32_t index, 3747 io_scalar_inband_t input, 3748 mach_msg_type_number_t inputCount, 3749 io_struct_inband_t output, 3750 mach_msg_type_number_t * outputCount ) 3751{ 3752 uint32_t i; 3753 io_scalar_inband64_t _input; 3754 io_async_ref64_t _reference; 3755 3756 for (i = 0; i < referenceCnt; i++) 3757 _reference[i] = REF64(reference[i]); 3758 3759 mach_msg_type_number_t scalar_outputCnt = 0; 3760 mach_vm_size_t ool_output_size = 0; 3761 3762 for (i = 0; i < inputCount; i++) 3763 _input[i] = SCALAR64(input[i]); 3764 3765 return (is_io_connect_async_method(connect, 3766 wake_port, _reference, referenceCnt, 3767 index, 3768 _input, inputCount, 3769 NULL, 0, 3770 0, 0, 3771 output, outputCount, 3772 NULL, &scalar_outputCnt, 3773 0, &ool_output_size)); 3774} 3775 3776/* Routine io_async_method_scalarI_structureI */ 3777kern_return_t is_io_async_method_scalarI_structureI( 3778 io_connect_t connect, 3779 mach_port_t wake_port, 3780 io_async_ref_t reference, 3781 mach_msg_type_number_t referenceCnt, 3782 uint32_t index, 3783 io_scalar_inband_t input, 3784 mach_msg_type_number_t inputCount, 3785 io_struct_inband_t inputStruct, 3786 mach_msg_type_number_t inputStructCount ) 3787{ 3788 uint32_t i; 3789 io_scalar_inband64_t _input; 3790 io_async_ref64_t _reference; 3791 3792 for (i = 0; i < referenceCnt; i++) 3793 _reference[i] = REF64(reference[i]); 3794 3795 mach_msg_type_number_t scalar_outputCnt = 0; 3796 mach_msg_type_number_t inband_outputCnt = 0; 3797 mach_vm_size_t ool_output_size = 0; 3798 3799 for (i = 0; i < inputCount; i++) 3800 _input[i] = SCALAR64(input[i]); 3801 3802 return (is_io_connect_async_method(connect, 3803 wake_port, _reference, referenceCnt, 3804 index, 3805 _input, inputCount, 3806 inputStruct, inputStructCount, 3807 0, 0, 3808 NULL, &inband_outputCnt, 3809 NULL, &scalar_outputCnt, 3810 0, &ool_output_size)); 3811} 3812 3813/* Routine io_async_method_structureI_structureO */ 3814kern_return_t is_io_async_method_structureI_structureO( 3815 io_object_t connect, 3816 mach_port_t wake_port, 3817 io_async_ref_t reference, 3818 mach_msg_type_number_t referenceCnt, 3819 uint32_t index, 3820 io_struct_inband_t input, 3821 mach_msg_type_number_t inputCount, 3822 io_struct_inband_t output, 3823 mach_msg_type_number_t * outputCount ) 3824{ 3825 uint32_t i; 3826 mach_msg_type_number_t scalar_outputCnt = 0; 3827 mach_vm_size_t ool_output_size = 0; 3828 io_async_ref64_t _reference; 3829 3830 for (i = 0; i < referenceCnt; i++) 3831 _reference[i] = REF64(reference[i]); 3832 3833 return (is_io_connect_async_method(connect, 3834 wake_port, _reference, referenceCnt, 3835 index, 3836 NULL, 0, 3837 input, inputCount, 3838 0, 0, 3839 output, outputCount, 3840 NULL, &scalar_outputCnt, 3841 0, &ool_output_size)); 3842} 3843 3844 3845kern_return_t shim_io_async_method_scalarI_scalarO( 3846 IOExternalAsyncMethod * method, 3847 IOService * object, 3848 mach_port_t asyncWakePort, 3849 io_user_reference_t * asyncReference, 3850 uint32_t asyncReferenceCount, 3851 const io_user_scalar_t * input, 3852 mach_msg_type_number_t inputCount, 3853 io_user_scalar_t * output, 3854 mach_msg_type_number_t * outputCount ) 3855{ 3856 IOAsyncMethod func; 3857 uint32_t i; 3858 io_scalar_inband_t _output; 3859 IOReturn err; 3860 io_async_ref_t reference; 3861 3862 bzero(&_output[0], sizeof(_output)); 3863 for (i = 0; i < asyncReferenceCount; i++) 3864 reference[i] = REF32(asyncReference[i]); 3865 3866 err = kIOReturnBadArgument; 3867 3868 do { 3869 3870 if( inputCount != method->count0) 3871 { 3872 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName()); 3873 continue; 3874 } 3875 if( *outputCount != method->count1) 3876 { 3877 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName()); 3878 continue; 3879 } 3880 3881 func = method->func; 3882 3883 switch( inputCount) { 3884 3885 case 6: 3886 err = (object->*func)( reference, 3887 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 3888 ARG32(input[3]), ARG32(input[4]), ARG32(input[5]) ); 3889 break; 3890 case 5: 3891 err = (object->*func)( reference, 3892 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 3893 ARG32(input[3]), ARG32(input[4]), 3894 &_output[0] ); 3895 break; 3896 case 4: 3897 err = (object->*func)( reference, 3898 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 3899 ARG32(input[3]), 3900 &_output[0], &_output[1] ); 3901 break; 3902 case 3: 3903 err = (object->*func)( reference, 3904 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 3905 &_output[0], &_output[1], &_output[2] ); 3906 break; 3907 case 2: 3908 err = (object->*func)( reference, 3909 ARG32(input[0]), ARG32(input[1]), 3910 &_output[0], &_output[1], &_output[2], 3911 &_output[3] ); 3912 break; 3913 case 1: 3914 err = (object->*func)( reference, 3915 ARG32(input[0]), 3916 &_output[0], &_output[1], &_output[2], 3917 &_output[3], &_output[4] ); 3918 break; 3919 case 0: 3920 err = (object->*func)( reference, 3921 &_output[0], &_output[1], &_output[2], 3922 &_output[3], &_output[4], &_output[5] ); 3923 break; 3924 3925 default: 3926 IOLog("%s: Bad method table\n", object->getName()); 3927 } 3928 } 3929 while( false); 3930 3931 for (i = 0; i < *outputCount; i++) 3932 output[i] = SCALAR32(_output[i]); 3933 3934 return( err); 3935} 3936 3937 3938/* Routine io_connect_method_scalarI_structureO */ 3939kern_return_t is_io_connect_method_scalarI_structureO( 3940 io_object_t connect, 3941 uint32_t index, 3942 io_scalar_inband_t input, 3943 mach_msg_type_number_t inputCount, 3944 io_struct_inband_t output, 3945 mach_msg_type_number_t * outputCount ) 3946{ 3947 uint32_t i; 3948 io_scalar_inband64_t _input; 3949 3950 mach_msg_type_number_t scalar_outputCnt = 0; 3951 mach_vm_size_t ool_output_size = 0; 3952 3953 for (i = 0; i < inputCount; i++) 3954 _input[i] = SCALAR64(input[i]); 3955 3956 return (is_io_connect_method(connect, index, 3957 _input, inputCount, 3958 NULL, 0, 3959 0, 0, 3960 output, outputCount, 3961 NULL, &scalar_outputCnt, 3962 0, &ool_output_size)); 3963} 3964 3965kern_return_t shim_io_connect_method_scalarI_structureO( 3966 3967 IOExternalMethod * method, 3968 IOService * object, 3969 const io_user_scalar_t * input, 3970 mach_msg_type_number_t inputCount, 3971 io_struct_inband_t output, 3972 IOByteCount * outputCount ) 3973{ 3974 IOMethod func; 3975 IOReturn err; 3976 3977 err = kIOReturnBadArgument; 3978 3979 do { 3980 if( inputCount != method->count0) 3981 { 3982 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName()); 3983 continue; 3984 } 3985 if( (kIOUCVariableStructureSize != method->count1) 3986 && (*outputCount != method->count1)) 3987 { 3988 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName()); 3989 continue; 3990 } 3991 3992 func = method->func; 3993 3994 switch( inputCount) { 3995 3996 case 5: 3997 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 3998 ARG32(input[3]), ARG32(input[4]), 3999 output ); 4000 break; 4001 case 4: 4002 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 4003 ARG32(input[3]), 4004 output, (void *)outputCount ); 4005 break; 4006 case 3: 4007 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 4008 output, (void *)outputCount, 0 ); 4009 break; 4010 case 2: 4011 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), 4012 output, (void *)outputCount, 0, 0 ); 4013 break; 4014 case 1: 4015 err = (object->*func)( ARG32(input[0]), 4016 output, (void *)outputCount, 0, 0, 0 ); 4017 break; 4018 case 0: 4019 err = (object->*func)( output, (void *)outputCount, 0, 0, 0, 0 ); 4020 break; 4021 4022 default: 4023 IOLog("%s: Bad method table\n", object->getName()); 4024 } 4025 } 4026 while( false); 4027 4028 return( err); 4029} 4030 4031 4032kern_return_t shim_io_async_method_scalarI_structureO( 4033 IOExternalAsyncMethod * method, 4034 IOService * object, 4035 mach_port_t asyncWakePort, 4036 io_user_reference_t * asyncReference, 4037 uint32_t asyncReferenceCount, 4038 const io_user_scalar_t * input, 4039 mach_msg_type_number_t inputCount, 4040 io_struct_inband_t output, 4041 mach_msg_type_number_t * outputCount ) 4042{ 4043 IOAsyncMethod func; 4044 uint32_t i; 4045 IOReturn err; 4046 io_async_ref_t reference; 4047 4048 for (i = 0; i < asyncReferenceCount; i++) 4049 reference[i] = REF32(asyncReference[i]); 4050 4051 err = kIOReturnBadArgument; 4052 do { 4053 if( inputCount != method->count0) 4054 { 4055 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName()); 4056 continue; 4057 } 4058 if( (kIOUCVariableStructureSize != method->count1) 4059 && (*outputCount != method->count1)) 4060 { 4061 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName()); 4062 continue; 4063 } 4064 4065 func = method->func; 4066 4067 switch( inputCount) { 4068 4069 case 5: 4070 err = (object->*func)( reference, 4071 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 4072 ARG32(input[3]), ARG32(input[4]), 4073 output ); 4074 break; 4075 case 4: 4076 err = (object->*func)( reference, 4077 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 4078 ARG32(input[3]), 4079 output, (void *)outputCount ); 4080 break; 4081 case 3: 4082 err = (object->*func)( reference, 4083 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 4084 output, (void *)outputCount, 0 ); 4085 break; 4086 case 2: 4087 err = (object->*func)( reference, 4088 ARG32(input[0]), ARG32(input[1]), 4089 output, (void *)outputCount, 0, 0 ); 4090 break; 4091 case 1: 4092 err = (object->*func)( reference, 4093 ARG32(input[0]), 4094 output, (void *)outputCount, 0, 0, 0 ); 4095 break; 4096 case 0: 4097 err = (object->*func)( reference, 4098 output, (void *)outputCount, 0, 0, 0, 0 ); 4099 break; 4100 4101 default: 4102 IOLog("%s: Bad method table\n", object->getName()); 4103 } 4104 } 4105 while( false); 4106 4107 return( err); 4108} 4109 4110/* Routine io_connect_method_scalarI_structureI */ 4111kern_return_t is_io_connect_method_scalarI_structureI( 4112 io_connect_t connect, 4113 uint32_t index, 4114 io_scalar_inband_t input, 4115 mach_msg_type_number_t inputCount, 4116 io_struct_inband_t inputStruct, 4117 mach_msg_type_number_t inputStructCount ) 4118{ 4119 uint32_t i; 4120 io_scalar_inband64_t _input; 4121 4122 mach_msg_type_number_t scalar_outputCnt = 0; 4123 mach_msg_type_number_t inband_outputCnt = 0; 4124 mach_vm_size_t ool_output_size = 0; 4125 4126 for (i = 0; i < inputCount; i++) 4127 _input[i] = SCALAR64(input[i]); 4128 4129 return (is_io_connect_method(connect, index, 4130 _input, inputCount, 4131 inputStruct, inputStructCount, 4132 0, 0, 4133 NULL, &inband_outputCnt, 4134 NULL, &scalar_outputCnt, 4135 0, &ool_output_size)); 4136} 4137 4138kern_return_t shim_io_connect_method_scalarI_structureI( 4139 IOExternalMethod * method, 4140 IOService * object, 4141 const io_user_scalar_t * input, 4142 mach_msg_type_number_t inputCount, 4143 io_struct_inband_t inputStruct, 4144 mach_msg_type_number_t inputStructCount ) 4145{ 4146 IOMethod func; 4147 IOReturn err = kIOReturnBadArgument; 4148 4149 do 4150 { 4151 if( (kIOUCVariableStructureSize != method->count0) 4152 && (inputCount != method->count0)) 4153 { 4154 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName()); 4155 continue; 4156 } 4157 if( (kIOUCVariableStructureSize != method->count1) 4158 && (inputStructCount != method->count1)) 4159 { 4160 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName()); 4161 continue; 4162 } 4163 4164 func = method->func; 4165 4166 switch( inputCount) { 4167 4168 case 5: 4169 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 4170 ARG32(input[3]), ARG32(input[4]), 4171 inputStruct ); 4172 break; 4173 case 4: 4174 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), (void *) input[2], 4175 ARG32(input[3]), 4176 inputStruct, (void *)(uintptr_t)inputStructCount ); 4177 break; 4178 case 3: 4179 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 4180 inputStruct, (void *)(uintptr_t)inputStructCount, 4181 0 ); 4182 break; 4183 case 2: 4184 err = (object->*func)( ARG32(input[0]), ARG32(input[1]), 4185 inputStruct, (void *)(uintptr_t)inputStructCount, 4186 0, 0 ); 4187 break; 4188 case 1: 4189 err = (object->*func)( ARG32(input[0]), 4190 inputStruct, (void *)(uintptr_t)inputStructCount, 4191 0, 0, 0 ); 4192 break; 4193 case 0: 4194 err = (object->*func)( inputStruct, (void *)(uintptr_t)inputStructCount, 4195 0, 0, 0, 0 ); 4196 break; 4197 4198 default: 4199 IOLog("%s: Bad method table\n", object->getName()); 4200 } 4201 } 4202 while (false); 4203 4204 return( err); 4205} 4206 4207kern_return_t shim_io_async_method_scalarI_structureI( 4208 IOExternalAsyncMethod * method, 4209 IOService * object, 4210 mach_port_t asyncWakePort, 4211 io_user_reference_t * asyncReference, 4212 uint32_t asyncReferenceCount, 4213 const io_user_scalar_t * input, 4214 mach_msg_type_number_t inputCount, 4215 io_struct_inband_t inputStruct, 4216 mach_msg_type_number_t inputStructCount ) 4217{ 4218 IOAsyncMethod func; 4219 uint32_t i; 4220 IOReturn err = kIOReturnBadArgument; 4221 io_async_ref_t reference; 4222 4223 for (i = 0; i < asyncReferenceCount; i++) 4224 reference[i] = REF32(asyncReference[i]); 4225 4226 do 4227 { 4228 if( (kIOUCVariableStructureSize != method->count0) 4229 && (inputCount != method->count0)) 4230 { 4231 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName()); 4232 continue; 4233 } 4234 if( (kIOUCVariableStructureSize != method->count1) 4235 && (inputStructCount != method->count1)) 4236 { 4237 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName()); 4238 continue; 4239 } 4240 4241 func = method->func; 4242 4243 switch( inputCount) { 4244 4245 case 5: 4246 err = (object->*func)( reference, 4247 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 4248 ARG32(input[3]), ARG32(input[4]), 4249 inputStruct ); 4250 break; 4251 case 4: 4252 err = (object->*func)( reference, 4253 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 4254 ARG32(input[3]), 4255 inputStruct, (void *)(uintptr_t)inputStructCount ); 4256 break; 4257 case 3: 4258 err = (object->*func)( reference, 4259 ARG32(input[0]), ARG32(input[1]), ARG32(input[2]), 4260 inputStruct, (void *)(uintptr_t)inputStructCount, 4261 0 ); 4262 break; 4263 case 2: 4264 err = (object->*func)( reference, 4265 ARG32(input[0]), ARG32(input[1]), 4266 inputStruct, (void *)(uintptr_t)inputStructCount, 4267 0, 0 ); 4268 break; 4269 case 1: 4270 err = (object->*func)( reference, 4271 ARG32(input[0]), 4272 inputStruct, (void *)(uintptr_t)inputStructCount, 4273 0, 0, 0 ); 4274 break; 4275 case 0: 4276 err = (object->*func)( reference, 4277 inputStruct, (void *)(uintptr_t)inputStructCount, 4278 0, 0, 0, 0 ); 4279 break; 4280 4281 default: 4282 IOLog("%s: Bad method table\n", object->getName()); 4283 } 4284 } 4285 while (false); 4286 4287 return( err); 4288} 4289 4290/* Routine io_connect_method_structureI_structureO */ 4291kern_return_t is_io_connect_method_structureI_structureO( 4292 io_object_t connect, 4293 uint32_t index, 4294 io_struct_inband_t input, 4295 mach_msg_type_number_t inputCount, 4296 io_struct_inband_t output, 4297 mach_msg_type_number_t * outputCount ) 4298{ 4299 mach_msg_type_number_t scalar_outputCnt = 0; 4300 mach_vm_size_t ool_output_size = 0; 4301 4302 return (is_io_connect_method(connect, index, 4303 NULL, 0, 4304 input, inputCount, 4305 0, 0, 4306 output, outputCount, 4307 NULL, &scalar_outputCnt, 4308 0, &ool_output_size)); 4309} 4310 4311kern_return_t shim_io_connect_method_structureI_structureO( 4312 IOExternalMethod * method, 4313 IOService * object, 4314 io_struct_inband_t input, 4315 mach_msg_type_number_t inputCount, 4316 io_struct_inband_t output, 4317 IOByteCount * outputCount ) 4318{ 4319 IOMethod func; 4320 IOReturn err = kIOReturnBadArgument; 4321 4322 do 4323 { 4324 if( (kIOUCVariableStructureSize != method->count0) 4325 && (inputCount != method->count0)) 4326 { 4327 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName()); 4328 continue; 4329 } 4330 if( (kIOUCVariableStructureSize != method->count1) 4331 && (*outputCount != method->count1)) 4332 { 4333 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName()); 4334 continue; 4335 } 4336 4337 func = method->func; 4338 4339 if( method->count1) { 4340 if( method->count0) { 4341 err = (object->*func)( input, output, 4342 (void *)(uintptr_t)inputCount, outputCount, 0, 0 ); 4343 } else { 4344 err = (object->*func)( output, outputCount, 0, 0, 0, 0 ); 4345 } 4346 } else { 4347 err = (object->*func)( input, (void *)(uintptr_t)inputCount, 0, 0, 0, 0 ); 4348 } 4349 } 4350 while( false); 4351 4352 4353 return( err); 4354} 4355 4356kern_return_t shim_io_async_method_structureI_structureO( 4357 IOExternalAsyncMethod * method, 4358 IOService * object, 4359 mach_port_t asyncWakePort, 4360 io_user_reference_t * asyncReference, 4361 uint32_t asyncReferenceCount, 4362 io_struct_inband_t input, 4363 mach_msg_type_number_t inputCount, 4364 io_struct_inband_t output, 4365 mach_msg_type_number_t * outputCount ) 4366{ 4367 IOAsyncMethod func; 4368 uint32_t i; 4369 IOReturn err; 4370 io_async_ref_t reference; 4371 4372 for (i = 0; i < asyncReferenceCount; i++) 4373 reference[i] = REF32(asyncReference[i]); 4374 4375 err = kIOReturnBadArgument; 4376 do 4377 { 4378 if( (kIOUCVariableStructureSize != method->count0) 4379 && (inputCount != method->count0)) 4380 { 4381 IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName()); 4382 continue; 4383 } 4384 if( (kIOUCVariableStructureSize != method->count1) 4385 && (*outputCount != method->count1)) 4386 { 4387 IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName()); 4388 continue; 4389 } 4390 4391 func = method->func; 4392 4393 if( method->count1) { 4394 if( method->count0) { 4395 err = (object->*func)( reference, 4396 input, output, 4397 (void *)(uintptr_t)inputCount, outputCount, 0, 0 ); 4398 } else { 4399 err = (object->*func)( reference, 4400 output, outputCount, 0, 0, 0, 0 ); 4401 } 4402 } else { 4403 err = (object->*func)( reference, 4404 input, (void *)(uintptr_t)inputCount, 0, 0, 0, 0 ); 4405 } 4406 } 4407 while( false); 4408 4409 return( err); 4410} 4411 4412/* Routine io_catalog_send_data */ 4413kern_return_t is_io_catalog_send_data( 4414 mach_port_t master_port, 4415 uint32_t flag, 4416 io_buf_ptr_t inData, 4417 mach_msg_type_number_t inDataCount, 4418 kern_return_t * result) 4419{ 4420 OSObject * obj = 0; 4421 vm_offset_t data; 4422 kern_return_t kr = kIOReturnError; 4423 4424 //printf("io_catalog_send_data called. flag: %d\n", flag); 4425 4426 if( master_port != master_device_port) 4427 return kIOReturnNotPrivileged; 4428 4429 if( (flag != kIOCatalogRemoveKernelLinker && 4430 flag != kIOCatalogKextdActive && 4431 flag != kIOCatalogKextdFinishedLaunching) && 4432 ( !inData || !inDataCount) ) 4433 { 4434 return kIOReturnBadArgument; 4435 } 4436 4437 if (inData) { 4438 vm_map_offset_t map_data; 4439 4440 if( inDataCount > sizeof(io_struct_inband_t) * 1024) 4441 return( kIOReturnMessageTooLarge); 4442 4443 kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t)inData); 4444 data = CAST_DOWN(vm_offset_t, map_data); 4445 4446 if( kr != KERN_SUCCESS) 4447 return kr; 4448 4449 // must return success after vm_map_copyout() succeeds 4450 4451 if( inDataCount ) { 4452 obj = (OSObject *)OSUnserializeXML((const char *)data, inDataCount); 4453 vm_deallocate( kernel_map, data, inDataCount ); 4454 if( !obj) { 4455 *result = kIOReturnNoMemory; 4456 return( KERN_SUCCESS); 4457 } 4458 } 4459 } 4460 4461 switch ( flag ) { 4462 case kIOCatalogResetDrivers: 4463 case kIOCatalogResetDriversNoMatch: { 4464 OSArray * array; 4465 4466 array = OSDynamicCast(OSArray, obj); 4467 if (array) { 4468 if ( !gIOCatalogue->resetAndAddDrivers(array, 4469 flag == kIOCatalogResetDrivers) ) { 4470 4471 kr = kIOReturnError; 4472 } 4473 } else { 4474 kr = kIOReturnBadArgument; 4475 } 4476 } 4477 break; 4478 4479 case kIOCatalogAddDrivers: 4480 case kIOCatalogAddDriversNoMatch: { 4481 OSArray * array; 4482 4483 array = OSDynamicCast(OSArray, obj); 4484 if ( array ) { 4485 if ( !gIOCatalogue->addDrivers( array , 4486 flag == kIOCatalogAddDrivers) ) { 4487 kr = kIOReturnError; 4488 } 4489 } 4490 else { 4491 kr = kIOReturnBadArgument; 4492 } 4493 } 4494 break; 4495 4496 case kIOCatalogRemoveDrivers: 4497 case kIOCatalogRemoveDriversNoMatch: { 4498 OSDictionary * dict; 4499 4500 dict = OSDynamicCast(OSDictionary, obj); 4501 if ( dict ) { 4502 if ( !gIOCatalogue->removeDrivers( dict, 4503 flag == kIOCatalogRemoveDrivers ) ) { 4504 kr = kIOReturnError; 4505 } 4506 } 4507 else { 4508 kr = kIOReturnBadArgument; 4509 } 4510 } 4511 break; 4512 4513 case kIOCatalogStartMatching: { 4514 OSDictionary * dict; 4515 4516 dict = OSDynamicCast(OSDictionary, obj); 4517 if ( dict ) { 4518 if ( !gIOCatalogue->startMatching( dict ) ) { 4519 kr = kIOReturnError; 4520 } 4521 } 4522 else { 4523 kr = kIOReturnBadArgument; 4524 } 4525 } 4526 break; 4527 4528 case kIOCatalogRemoveKernelLinker: 4529 kr = KERN_NOT_SUPPORTED; 4530 break; 4531 4532 case kIOCatalogKextdActive: 4533#if !NO_KEXTD 4534 IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0); 4535 OSKext::setKextdActive(); 4536 4537 /* Dump all nonloaded startup extensions; kextd will now send them 4538 * down on request. 4539 */ 4540 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false); 4541#endif 4542 kr = kIOReturnSuccess; 4543 break; 4544 4545 case kIOCatalogKextdFinishedLaunching: { 4546#if !NO_KEXTD 4547 static bool clearedBusy = false; 4548 4549 if (!clearedBusy) { 4550 IOService * serviceRoot = IOService::getServiceRoot(); 4551 if (serviceRoot) { 4552 IOServiceTrace(IOSERVICE_KEXTD_READY, 0, 0, 0, 0); 4553 serviceRoot->adjustBusy(-1); 4554 clearedBusy = true; 4555 } 4556 } 4557#endif 4558 kr = kIOReturnSuccess; 4559 } 4560 break; 4561 4562 default: 4563 kr = kIOReturnBadArgument; 4564 break; 4565 } 4566 4567 if (obj) obj->release(); 4568 4569 *result = kr; 4570 return( KERN_SUCCESS); 4571} 4572 4573/* Routine io_catalog_terminate */ 4574kern_return_t is_io_catalog_terminate( 4575 mach_port_t master_port, 4576 uint32_t flag, 4577 io_name_t name ) 4578{ 4579 kern_return_t kr; 4580 4581 if( master_port != master_device_port ) 4582 return kIOReturnNotPrivileged; 4583 4584 kr = IOUserClient::clientHasPrivilege( (void *) current_task(), 4585 kIOClientPrivilegeAdministrator ); 4586 if( kIOReturnSuccess != kr) 4587 return( kr ); 4588 4589 switch ( flag ) { 4590#if !defined(SECURE_KERNEL) 4591 case kIOCatalogServiceTerminate: 4592 OSIterator * iter; 4593 IOService * service; 4594 4595 iter = IORegistryIterator::iterateOver(gIOServicePlane, 4596 kIORegistryIterateRecursively); 4597 if ( !iter ) 4598 return kIOReturnNoMemory; 4599 4600 do { 4601 iter->reset(); 4602 while( (service = (IOService *)iter->getNextObject()) ) { 4603 if( service->metaCast(name)) { 4604 if ( !service->terminate( kIOServiceRequired 4605 | kIOServiceSynchronous) ) { 4606 kr = kIOReturnUnsupported; 4607 break; 4608 } 4609 } 4610 } 4611 } while( !service && !iter->isValid()); 4612 iter->release(); 4613 break; 4614 4615 case kIOCatalogModuleUnload: 4616 case kIOCatalogModuleTerminate: 4617 kr = gIOCatalogue->terminateDriversForModule(name, 4618 flag == kIOCatalogModuleUnload); 4619 break; 4620#endif 4621 4622 default: 4623 kr = kIOReturnBadArgument; 4624 break; 4625 } 4626 4627 return( kr ); 4628} 4629 4630/* Routine io_catalog_get_data */ 4631kern_return_t is_io_catalog_get_data( 4632 mach_port_t master_port, 4633 uint32_t flag, 4634 io_buf_ptr_t *outData, 4635 mach_msg_type_number_t *outDataCount) 4636{ 4637 kern_return_t kr = kIOReturnSuccess; 4638 OSSerialize * s; 4639 4640 if( master_port != master_device_port) 4641 return kIOReturnNotPrivileged; 4642 4643 //printf("io_catalog_get_data called. flag: %d\n", flag); 4644 4645 s = OSSerialize::withCapacity(4096); 4646 if ( !s ) 4647 return kIOReturnNoMemory; 4648 4649 kr = gIOCatalogue->serializeData(flag, s); 4650 4651 if ( kr == kIOReturnSuccess ) { 4652 vm_offset_t data; 4653 vm_map_copy_t copy; 4654 vm_size_t size; 4655 4656 size = s->getLength(); 4657 kr = vm_allocate(kernel_map, &data, size, VM_FLAGS_ANYWHERE); 4658 if ( kr == kIOReturnSuccess ) { 4659 bcopy(s->text(), (void *)data, size); 4660 kr = vm_map_copyin(kernel_map, (vm_map_address_t)data, 4661 (vm_map_size_t)size, true, ©); 4662 *outData = (char *)copy; 4663 *outDataCount = size; 4664 } 4665 } 4666 4667 s->release(); 4668 4669 return kr; 4670} 4671 4672/* Routine io_catalog_get_gen_count */ 4673kern_return_t is_io_catalog_get_gen_count( 4674 mach_port_t master_port, 4675 uint32_t *genCount) 4676{ 4677 if( master_port != master_device_port) 4678 return kIOReturnNotPrivileged; 4679 4680 //printf("io_catalog_get_gen_count called.\n"); 4681 4682 if ( !genCount ) 4683 return kIOReturnBadArgument; 4684 4685 *genCount = gIOCatalogue->getGenerationCount(); 4686 4687 return kIOReturnSuccess; 4688} 4689 4690/* Routine io_catalog_module_loaded. 4691 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used. 4692 */ 4693kern_return_t is_io_catalog_module_loaded( 4694 mach_port_t master_port, 4695 io_name_t name) 4696{ 4697 if( master_port != master_device_port) 4698 return kIOReturnNotPrivileged; 4699 4700 //printf("io_catalog_module_loaded called. name %s\n", name); 4701 4702 if ( !name ) 4703 return kIOReturnBadArgument; 4704 4705 gIOCatalogue->moduleHasLoaded(name); 4706 4707 return kIOReturnSuccess; 4708} 4709 4710kern_return_t is_io_catalog_reset( 4711 mach_port_t master_port, 4712 uint32_t flag) 4713{ 4714 if( master_port != master_device_port) 4715 return kIOReturnNotPrivileged; 4716 4717 switch ( flag ) { 4718 case kIOCatalogResetDefault: 4719 gIOCatalogue->reset(); 4720 break; 4721 4722 default: 4723 return kIOReturnBadArgument; 4724 } 4725 4726 return kIOReturnSuccess; 4727} 4728 4729kern_return_t iokit_user_client_trap(struct iokit_user_client_trap_args *args) 4730{ 4731 kern_return_t result = kIOReturnBadArgument; 4732 IOUserClient *userClient; 4733 4734 if ((userClient = OSDynamicCast(IOUserClient, 4735 iokit_lookup_connect_ref_current_task((OSObject *)(args->userClientRef))))) { 4736 IOExternalTrap *trap; 4737 IOService *target = NULL; 4738 4739 trap = userClient->getTargetAndTrapForIndex(&target, args->index); 4740 4741 if (trap && target) { 4742 IOTrap func; 4743 4744 func = trap->func; 4745 4746 if (func) { 4747 result = (target->*func)(args->p1, args->p2, args->p3, args->p4, args->p5, args->p6); 4748 } 4749 } 4750 4751 userClient->release(); 4752 } 4753 4754 return result; 4755} 4756 4757} /* extern "C" */ 4758 4759IOReturn IOUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args, 4760 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference ) 4761{ 4762 IOReturn err; 4763 IOService * object; 4764 IOByteCount structureOutputSize; 4765 4766 if (dispatch) 4767 { 4768 uint32_t count; 4769 count = dispatch->checkScalarInputCount; 4770 if ((kIOUCVariableStructureSize != count) && (count != args->scalarInputCount)) 4771 { 4772 return (kIOReturnBadArgument); 4773 } 4774 4775 count = dispatch->checkStructureInputSize; 4776 if ((kIOUCVariableStructureSize != count) 4777 && (count != ((args->structureInputDescriptor) 4778 ? args->structureInputDescriptor->getLength() : args->structureInputSize))) 4779 { 4780 return (kIOReturnBadArgument); 4781 } 4782 4783 count = dispatch->checkScalarOutputCount; 4784 if ((kIOUCVariableStructureSize != count) && (count != args->scalarOutputCount)) 4785 { 4786 return (kIOReturnBadArgument); 4787 } 4788 4789 count = dispatch->checkStructureOutputSize; 4790 if ((kIOUCVariableStructureSize != count) 4791 && (count != ((args->structureOutputDescriptor) 4792 ? args->structureOutputDescriptor->getLength() : args->structureOutputSize))) 4793 { 4794 return (kIOReturnBadArgument); 4795 } 4796 4797 if (dispatch->function) 4798 err = (*dispatch->function)(target, reference, args); 4799 else 4800 err = kIOReturnNoCompletion; /* implementator can dispatch */ 4801 4802 return (err); 4803 } 4804 4805 4806 // pre-Leopard API's don't do ool structs 4807 if (args->structureInputDescriptor || args->structureOutputDescriptor) 4808 { 4809 err = kIOReturnIPCError; 4810 return (err); 4811 } 4812 4813 structureOutputSize = args->structureOutputSize; 4814 4815 if (args->asyncWakePort) 4816 { 4817 IOExternalAsyncMethod * method; 4818 4819 if( !(method = getAsyncTargetAndMethodForIndex(&object, selector)) ) 4820 return (kIOReturnUnsupported); 4821 4822 if (kIOUCForegroundOnly & method->flags) 4823 { 4824 if (task_is_gpu_denied(current_task())) 4825 return (kIOReturnNotPermitted); 4826 } 4827 4828 switch (method->flags & kIOUCTypeMask) 4829 { 4830 case kIOUCScalarIStructI: 4831 err = shim_io_async_method_scalarI_structureI( method, object, 4832 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount, 4833 args->scalarInput, args->scalarInputCount, 4834 (char *)args->structureInput, args->structureInputSize ); 4835 break; 4836 4837 case kIOUCScalarIScalarO: 4838 err = shim_io_async_method_scalarI_scalarO( method, object, 4839 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount, 4840 args->scalarInput, args->scalarInputCount, 4841 args->scalarOutput, &args->scalarOutputCount ); 4842 break; 4843 4844 case kIOUCScalarIStructO: 4845 err = shim_io_async_method_scalarI_structureO( method, object, 4846 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount, 4847 args->scalarInput, args->scalarInputCount, 4848 (char *) args->structureOutput, &args->structureOutputSize ); 4849 break; 4850 4851 4852 case kIOUCStructIStructO: 4853 err = shim_io_async_method_structureI_structureO( method, object, 4854 args->asyncWakePort, args->asyncReference, args->asyncReferenceCount, 4855 (char *)args->structureInput, args->structureInputSize, 4856 (char *) args->structureOutput, &args->structureOutputSize ); 4857 break; 4858 4859 default: 4860 err = kIOReturnBadArgument; 4861 break; 4862 } 4863 } 4864 else 4865 { 4866 IOExternalMethod * method; 4867 4868 if( !(method = getTargetAndMethodForIndex(&object, selector)) ) 4869 return (kIOReturnUnsupported); 4870 4871 if (kIOUCForegroundOnly & method->flags) 4872 { 4873 if (task_is_gpu_denied(current_task())) 4874 return (kIOReturnNotPermitted); 4875 } 4876 4877 switch (method->flags & kIOUCTypeMask) 4878 { 4879 case kIOUCScalarIStructI: 4880 err = shim_io_connect_method_scalarI_structureI( method, object, 4881 args->scalarInput, args->scalarInputCount, 4882 (char *) args->structureInput, args->structureInputSize ); 4883 break; 4884 4885 case kIOUCScalarIScalarO: 4886 err = shim_io_connect_method_scalarI_scalarO( method, object, 4887 args->scalarInput, args->scalarInputCount, 4888 args->scalarOutput, &args->scalarOutputCount ); 4889 break; 4890 4891 case kIOUCScalarIStructO: 4892 err = shim_io_connect_method_scalarI_structureO( method, object, 4893 args->scalarInput, args->scalarInputCount, 4894 (char *) args->structureOutput, &structureOutputSize ); 4895 break; 4896 4897 4898 case kIOUCStructIStructO: 4899 err = shim_io_connect_method_structureI_structureO( method, object, 4900 (char *) args->structureInput, args->structureInputSize, 4901 (char *) args->structureOutput, &structureOutputSize ); 4902 break; 4903 4904 default: 4905 err = kIOReturnBadArgument; 4906 break; 4907 } 4908 } 4909 4910 args->structureOutputSize = structureOutputSize; 4911 4912 return (err); 4913} 4914 4915 4916#if __LP64__ 4917OSMetaClassDefineReservedUnused(IOUserClient, 0); 4918OSMetaClassDefineReservedUnused(IOUserClient, 1); 4919#else 4920OSMetaClassDefineReservedUsed(IOUserClient, 0); 4921OSMetaClassDefineReservedUsed(IOUserClient, 1); 4922#endif 4923OSMetaClassDefineReservedUnused(IOUserClient, 2); 4924OSMetaClassDefineReservedUnused(IOUserClient, 3); 4925OSMetaClassDefineReservedUnused(IOUserClient, 4); 4926OSMetaClassDefineReservedUnused(IOUserClient, 5); 4927OSMetaClassDefineReservedUnused(IOUserClient, 6); 4928OSMetaClassDefineReservedUnused(IOUserClient, 7); 4929OSMetaClassDefineReservedUnused(IOUserClient, 8); 4930OSMetaClassDefineReservedUnused(IOUserClient, 9); 4931OSMetaClassDefineReservedUnused(IOUserClient, 10); 4932OSMetaClassDefineReservedUnused(IOUserClient, 11); 4933OSMetaClassDefineReservedUnused(IOUserClient, 12); 4934OSMetaClassDefineReservedUnused(IOUserClient, 13); 4935OSMetaClassDefineReservedUnused(IOUserClient, 14); 4936OSMetaClassDefineReservedUnused(IOUserClient, 15); 4937 4938