2 * Copyright (c) 1998-2014 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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/IOBSD.h>
41 #include <IOKit/IOStatisticsPrivate.h>
42 #include <IOKit/IOTimeStamp.h>
43 #include <IOKit/system.h>
44 #include <libkern/OSDebug.h>
46 #include <sys/kauth.h>
47 #include <sys/codesign.h>
54 #include <security/mac_framework.h>
56 #include <sys/kauth.h>
60 #endif /* CONFIG_MACF */
62 #include <IOKit/assert.h>
64 #include "IOServicePrivate.h"
65 #include "IOKitKernelInternal.h"
67 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
68 #define SCALAR32(x) ((uint32_t )x)
69 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
70 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
71 #define REF32(x) ((int)(x))
75 kIOUCAsync0Flags
= 3ULL,
76 kIOUCAsync64Flag
= 1ULL,
77 kIOUCAsyncErrorLoggedFlag
= 2ULL
82 #define IOStatisticsRegisterCounter() \
84 reserved->counter = IOStatistics::registerUserClient(this); \
87 #define IOStatisticsUnregisterCounter() \
90 IOStatistics::unregisterUserClient(reserved->counter); \
93 #define IOStatisticsClientCall() \
95 IOStatistics::countUserClientCall(client); \
100 #define IOStatisticsRegisterCounter()
101 #define IOStatisticsUnregisterCounter()
102 #define IOStatisticsClientCall()
104 #endif /* IOKITSTATS */
106 #if DEVELOPMENT || DEBUG
108 #define FAKE_STACK_FRAME(a) \
109 const void ** __frameptr; \
110 const void * __retaddr; \
111 __frameptr = (typeof(__frameptr)) __builtin_frame_address(0); \
112 __retaddr = __frameptr[1]; \
115 #define FAKE_STACK_FRAME_END() \
116 __frameptr[1] = __retaddr;
118 #else /* DEVELOPMENT || DEBUG */
120 #define FAKE_STACK_FRAME(a)
121 #define FAKE_STACK_FRAME_END()
123 #endif /* DEVELOPMENT || DEBUG */
125 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
127 // definitions we should get from osfmk
129 //typedef struct ipc_port * ipc_port_t;
130 typedef natural_t ipc_kobject_type_t
;
132 #define IKOT_IOKIT_SPARE 27
133 #define IKOT_IOKIT_CONNECT 29
134 #define IKOT_IOKIT_OBJECT 30
138 extern ipc_port_t
iokit_alloc_object_port( io_object_t obj
,
139 ipc_kobject_type_t type
);
141 extern kern_return_t
iokit_destroy_object_port( ipc_port_t port
);
143 extern mach_port_name_t
iokit_make_send_right( task_t task
,
144 io_object_t obj
, ipc_kobject_type_t type
);
146 extern kern_return_t
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta
);
148 extern io_object_t
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
);
150 extern io_object_t
iokit_lookup_connect_ref_current_task(io_object_t clientRef
);
152 extern ipc_port_t master_device_port
;
154 extern void iokit_retain_port( ipc_port_t port
);
155 extern void iokit_release_port( ipc_port_t port
);
156 extern void iokit_release_port_send( ipc_port_t port
);
158 extern kern_return_t
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type
);
160 #include <mach/mach_traps.h>
161 #include <vm/vm_map.h>
166 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
168 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
170 class IOMachPort
: public OSObject
172 OSDeclareDefaultStructors(IOMachPort
)
179 static IOMachPort
* portForObject( OSObject
* obj
,
180 ipc_kobject_type_t type
);
181 static bool noMoreSendersForObject( OSObject
* obj
,
182 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
183 static void releasePortForObject( OSObject
* obj
,
184 ipc_kobject_type_t type
);
185 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
187 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
189 static mach_port_name_t
makeSendRightForTask( task_t task
,
190 io_object_t obj
, ipc_kobject_type_t type
);
192 virtual void free() APPLE_KEXT_OVERRIDE
;
195 #define super OSObject
196 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
198 static IOLock
* gIOObjectPortLock
;
200 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
202 // not in dictForType() for debugging ease
203 static OSDictionary
* gIOObjectPorts
;
204 static OSDictionary
* gIOConnectPorts
;
206 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
208 OSDictionary
** dict
;
210 if( IKOT_IOKIT_OBJECT
== type
)
211 dict
= &gIOObjectPorts
;
212 else if( IKOT_IOKIT_CONNECT
== type
)
213 dict
= &gIOConnectPorts
;
218 *dict
= OSDictionary::withCapacity( 1 );
223 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
224 ipc_kobject_type_t type
)
226 IOMachPort
* inst
= 0;
229 IOTakeLock( gIOObjectPortLock
);
233 dict
= dictForType( type
);
237 if( (inst
= (IOMachPort
*)
238 dict
->getObject( (const OSSymbol
*) obj
))) {
244 inst
= new IOMachPort
;
245 if( inst
&& !inst
->init()) {
250 inst
->port
= iokit_alloc_object_port( obj
, type
);
253 dict
->setObject( (const OSSymbol
*) obj
, inst
);
263 IOUnlock( gIOObjectPortLock
);
268 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
269 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
272 IOMachPort
* machPort
;
274 bool destroyed
= true;
276 IOTakeLock( gIOObjectPortLock
);
278 if( (dict
= dictForType( type
))) {
281 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
283 destroyed
= (machPort
->mscount
<= *mscount
);
284 if (!destroyed
) *mscount
= machPort
->mscount
;
287 if ((IKOT_IOKIT_CONNECT
== type
) && (uc
= OSDynamicCast(IOUserClient
, obj
)))
291 dict
->removeObject( (const OSSymbol
*) obj
);
297 IOUnlock( gIOObjectPortLock
);
302 void IOMachPort::releasePortForObject( OSObject
* obj
,
303 ipc_kobject_type_t type
)
306 IOMachPort
* machPort
;
308 assert(IKOT_IOKIT_CONNECT
!= type
);
310 IOTakeLock( gIOObjectPortLock
);
312 if( (dict
= dictForType( type
))) {
314 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
315 if( machPort
&& !machPort
->holdDestroy
)
316 dict
->removeObject( (const OSSymbol
*) obj
);
320 IOUnlock( gIOObjectPortLock
);
323 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
326 IOMachPort
* machPort
;
328 IOLockLock( gIOObjectPortLock
);
330 if( (dict
= dictForType( type
))) {
331 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
333 machPort
->holdDestroy
= true;
336 IOLockUnlock( gIOObjectPortLock
);
339 void IOUserClient::destroyUserReferences( OSObject
* obj
)
341 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
344 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
348 IOTakeLock( gIOObjectPortLock
);
351 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
354 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
358 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
363 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
364 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
366 uc
->mappings
->release();
370 dict
->removeObject( (const OSSymbol
*) obj
);
374 IOUnlock( gIOObjectPortLock
);
377 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
378 io_object_t obj
, ipc_kobject_type_t type
)
380 return( iokit_make_send_right( task
, obj
, type
));
383 void IOMachPort::free( void )
386 iokit_destroy_object_port( port
);
390 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
392 class IOUserIterator
: public OSIterator
394 OSDeclareDefaultStructors(IOUserIterator
)
396 OSObject
* userIteratorObject
;
399 static IOUserIterator
* withIterator(OSIterator
* iter
);
400 virtual bool init( void ) APPLE_KEXT_OVERRIDE
;
401 virtual void free() APPLE_KEXT_OVERRIDE
;
403 virtual void reset() APPLE_KEXT_OVERRIDE
;
404 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
405 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
408 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
410 class IOUserNotification
: public IOUserIterator
412 OSDeclareDefaultStructors(IOUserNotification
)
414 #define holdNotify userIteratorObject
418 virtual void free() APPLE_KEXT_OVERRIDE
;
420 virtual void setNotification( IONotifier
* obj
);
422 virtual void reset() APPLE_KEXT_OVERRIDE
;
423 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
426 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
428 OSDefineMetaClassAndStructors( IOUserIterator
, OSIterator
)
431 IOUserIterator::withIterator(OSIterator
* iter
)
435 if (!iter
) return (0);
437 me
= new IOUserIterator
;
438 if (me
&& !me
->init())
444 me
->userIteratorObject
= iter
;
450 IOUserIterator::init( void )
452 if (!OSObject::init()) return (false);
454 lock
= IOLockAlloc();
462 IOUserIterator::free()
464 if (userIteratorObject
) userIteratorObject
->release();
465 if (lock
) IOLockFree(lock
);
470 IOUserIterator::reset()
473 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
474 ((OSIterator
*)userIteratorObject
)->reset();
479 IOUserIterator::isValid()
484 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
485 ret
= ((OSIterator
*)userIteratorObject
)->isValid();
492 IOUserIterator::getNextObject()
497 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
498 ret
= ((OSIterator
*)userIteratorObject
)->getNextObject();
504 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
507 // functions called from osfmk/device/iokit_rpc.c
510 iokit_add_reference( io_object_t obj
)
517 iokit_remove_reference( io_object_t obj
)
524 iokit_add_connect_reference( io_object_t obj
)
530 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) OSIncrementAtomic(&uc
->__ipc
);
536 iokit_remove_connect_reference( io_object_t obj
)
539 bool finalize
= false;
543 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
545 if (1 == OSDecrementAtomic(&uc
->__ipc
) && uc
->isInactive())
547 IOLockLock(gIOObjectPortLock
);
548 if ((finalize
= uc
->__ipcFinal
)) uc
->__ipcFinal
= false;
549 IOLockUnlock(gIOObjectPortLock
);
551 if (finalize
) uc
->scheduleFinalize(true);
558 IOUserClient::finalizeUserReferences(OSObject
* obj
)
563 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
565 IOLockLock(gIOObjectPortLock
);
566 if ((uc
->__ipcFinal
= (0 != uc
->__ipc
))) ok
= false;
567 IOLockUnlock(gIOObjectPortLock
);
573 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
575 IOMachPort
* machPort
;
578 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
580 port
= machPort
->port
;
582 iokit_retain_port( port
);
593 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
594 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
596 IOUserClient
* client
;
598 IOUserNotification
* notify
;
600 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
601 return( kIOReturnNotReady
);
603 if( IKOT_IOKIT_CONNECT
== type
)
605 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
607 IOStatisticsClientCall();
608 client
->clientDied();
611 else if( IKOT_IOKIT_OBJECT
== type
)
613 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
615 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
616 notify
->setNotification( 0 );
619 return( kIOReturnSuccess
);
624 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
626 class IOServiceUserNotification
: public IOUserNotification
628 OSDeclareDefaultStructors(IOServiceUserNotification
)
631 mach_msg_header_t msgHdr
;
632 OSNotificationHeader64 notifyHeader
;
635 enum { kMaxOutstanding
= 1024 };
640 OSObject
* lastEntry
;
646 virtual bool init( mach_port_t port
, natural_t type
,
647 void * reference
, vm_size_t referenceSize
,
649 virtual void free() APPLE_KEXT_OVERRIDE
;
650 void invalidatePort(void);
652 static bool _handler( void * target
,
653 void * ref
, IOService
* newService
, IONotifier
* notifier
);
654 virtual bool handler( void * ref
, IOService
* newService
);
656 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
659 class IOServiceMessageUserNotification
: public IOUserNotification
661 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
664 mach_msg_header_t msgHdr
;
665 mach_msg_body_t msgBody
;
666 mach_msg_port_descriptor_t ports
[1];
667 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
678 virtual bool init( mach_port_t port
, natural_t type
,
679 void * reference
, vm_size_t referenceSize
,
683 virtual void free() APPLE_KEXT_OVERRIDE
;
684 void invalidatePort(void);
686 static IOReturn
_handler( void * target
, void * ref
,
687 UInt32 messageType
, IOService
* provider
,
688 void * messageArgument
, vm_size_t argSize
);
689 virtual IOReturn
handler( void * ref
,
690 UInt32 messageType
, IOService
* provider
,
691 void * messageArgument
, vm_size_t argSize
);
693 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
696 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
699 #define super IOUserIterator
700 OSDefineMetaClass( IOUserNotification
, IOUserIterator
)
701 OSDefineAbstractStructors( IOUserNotification
, IOUserIterator
)
703 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
705 void IOUserNotification::free( void )
709 assert(OSDynamicCast(IONotifier
, holdNotify
));
710 ((IONotifier
*)holdNotify
)->remove();
713 // can't be in handler now
719 void IOUserNotification::setNotification( IONotifier
* notify
)
721 OSObject
* previousNotify
;
723 IOLockLock( gIOObjectPortLock
);
725 previousNotify
= holdNotify
;
728 IOLockUnlock( gIOObjectPortLock
);
732 assert(OSDynamicCast(IONotifier
, previousNotify
));
733 ((IONotifier
*)previousNotify
)->remove();
737 void IOUserNotification::reset()
742 bool IOUserNotification::isValid()
747 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
750 #define super IOUserNotification
751 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
753 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
755 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
756 void * reference
, vm_size_t referenceSize
,
762 newSet
= OSArray::withCapacity( 1 );
766 if (referenceSize
> sizeof(OSAsyncReference64
))
769 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
770 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
774 bzero( pingMsg
, msgSize
);
776 pingMsg
->msgHdr
.msgh_remote_port
= port
;
777 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
778 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
779 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
780 pingMsg
->msgHdr
.msgh_size
= msgSize
;
781 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
783 pingMsg
->notifyHeader
.size
= 0;
784 pingMsg
->notifyHeader
.type
= type
;
785 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
790 void IOServiceUserNotification::invalidatePort(void)
792 if (pingMsg
) pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
795 void IOServiceUserNotification::free( void )
800 OSObject
* _lastEntry
;
804 _lastEntry
= lastEntry
;
809 if( _pingMsg
&& _msgSize
) {
810 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
811 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
813 IOFree(_pingMsg
, _msgSize
);
817 _lastEntry
->release();
823 bool IOServiceUserNotification::_handler( void * target
,
824 void * ref
, IOService
* newService
, IONotifier
* notifier
)
826 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
829 bool IOServiceUserNotification::handler( void * ref
,
830 IOService
* newService
)
834 ipc_port_t port
= NULL
;
835 bool sendPing
= false;
839 count
= newSet
->getCount();
840 if( count
< kMaxOutstanding
) {
842 newSet
->setObject( newService
);
843 if( (sendPing
= (armed
&& (0 == count
))))
849 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
850 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
853 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
854 pingMsg
->msgHdr
.msgh_local_port
= port
;
856 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
858 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
859 pingMsg
->msgHdr
.msgh_size
,
860 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
863 iokit_release_port( port
);
865 if( (KERN_SUCCESS
!= kr
) && !ipcLogged
)
868 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
875 OSObject
* IOServiceUserNotification::getNextObject()
879 OSObject
* releaseEntry
;
883 releaseEntry
= lastEntry
;
884 count
= newSet
->getCount();
886 result
= newSet
->getObject( count
- 1 );
888 newSet
->removeObject( count
- 1);
897 if (releaseEntry
) releaseEntry
->release();
902 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
904 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
906 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
908 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
909 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
915 if (referenceSize
> sizeof(OSAsyncReference64
))
918 clientIs64
= client64
;
920 owningPID
= proc_selfpid();
922 extraSize
+= sizeof(IOServiceInterestContent64
);
923 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
924 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
928 bzero( pingMsg
, msgSize
);
930 pingMsg
->msgHdr
.msgh_remote_port
= port
;
931 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
933 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
934 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
935 pingMsg
->msgHdr
.msgh_size
= msgSize
;
936 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
938 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
940 pingMsg
->ports
[0].name
= 0;
941 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
942 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
944 pingMsg
->notifyHeader
.size
= extraSize
;
945 pingMsg
->notifyHeader
.type
= type
;
946 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
951 void IOServiceMessageUserNotification::invalidatePort(void)
953 if (pingMsg
) pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
956 void IOServiceMessageUserNotification::free( void )
966 if( _pingMsg
&& _msgSize
) {
967 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
968 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
970 IOFree( _pingMsg
, _msgSize
);
974 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
975 UInt32 messageType
, IOService
* provider
,
976 void * argument
, vm_size_t argSize
)
978 return( ((IOServiceMessageUserNotification
*) target
)->handler(
979 ref
, messageType
, provider
, argument
, argSize
));
982 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
983 UInt32 messageType
, IOService
* provider
,
984 void * messageArgument
, vm_size_t callerArgSize
)
986 enum { kLocalMsgSize
= 0x100 };
987 uint64_t stackMsg
[kLocalMsgSize
/ sizeof(uint64_t)];
991 vm_size_t thisMsgSize
;
992 ipc_port_t thisPort
, providerPort
;
993 struct PingMsg
* thisMsg
;
994 IOServiceInterestContent64
* data
;
996 if (kIOMessageCopyClientID
== messageType
)
998 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
999 return (kIOReturnSuccess
);
1002 if (callerArgSize
== 0)
1004 if (clientIs64
) argSize
= sizeof(data
->messageArgument
[0]);
1005 else argSize
= sizeof(uint32_t);
1009 if( callerArgSize
> kIOUserNotifyMaxMessageSize
)
1010 callerArgSize
= kIOUserNotifyMaxMessageSize
;
1011 argSize
= callerArgSize
;
1014 // adjust message size for ipc restrictions
1016 type
= pingMsg
->notifyHeader
.type
;
1017 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
1018 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
1019 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
1021 thisMsgSize
= msgSize
1022 + sizeof( IOServiceInterestContent64
)
1023 - sizeof( data
->messageArgument
)
1026 if (thisMsgSize
> sizeof(stackMsg
))
1028 allocMsg
= IOMalloc(thisMsgSize
);
1029 if (!allocMsg
) return (kIOReturnNoMemory
);
1030 thisMsg
= (typeof(thisMsg
)) allocMsg
;
1035 thisMsg
= (typeof(thisMsg
)) stackMsg
;
1038 bcopy(pingMsg
, thisMsg
, msgSize
);
1039 thisMsg
->notifyHeader
.type
= type
;
1040 data
= (IOServiceInterestContent64
*) (((uint8_t *) thisMsg
) + msgSize
);
1041 // == pingMsg->notifyHeader.content;
1042 data
->messageType
= messageType
;
1044 if (callerArgSize
== 0)
1046 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
1049 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
1054 bcopy( messageArgument
, data
->messageArgument
, callerArgSize
);
1055 bzero((void *)(((uintptr_t) &data
->messageArgument
[0]) + callerArgSize
), argSize
- callerArgSize
);
1058 thisMsg
->notifyHeader
.type
= type
;
1059 thisMsg
->msgHdr
.msgh_size
= thisMsgSize
;
1061 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
1062 thisMsg
->ports
[0].name
= providerPort
;
1063 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
1064 thisMsg
->msgHdr
.msgh_local_port
= thisPort
;
1066 kr
= mach_msg_send_from_kernel_with_options( &thisMsg
->msgHdr
,
1067 thisMsg
->msgHdr
.msgh_size
,
1068 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
1071 iokit_release_port( thisPort
);
1073 iokit_release_port( providerPort
);
1076 IOFree(allocMsg
, thisMsgSize
);
1078 if((KERN_SUCCESS
!= kr
) && !ipcLogged
)
1081 IOLog("%s: mach_msg_send_from_kernel_proper (0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1084 return( kIOReturnSuccess
);
1087 OSObject
* IOServiceMessageUserNotification::getNextObject()
1092 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1095 #define super IOService
1096 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
1098 IOLock
* gIOUserClientOwnersLock
;
1100 void IOUserClient::initialize( void )
1102 gIOObjectPortLock
= IOLockAlloc();
1103 gIOUserClientOwnersLock
= IOLockAlloc();
1104 assert(gIOObjectPortLock
&& gIOUserClientOwnersLock
);
1107 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
1108 mach_port_t wakePort
,
1109 void *callback
, void *refcon
)
1111 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
1112 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1113 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
1114 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
1117 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1118 mach_port_t wakePort
,
1119 mach_vm_address_t callback
, io_user_reference_t refcon
)
1121 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
1122 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1123 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
1124 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
1127 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1128 mach_port_t wakePort
,
1129 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
1131 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
1132 if (vm_map_is_64bit(get_task_map(task
))) {
1133 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
1137 static OSDictionary
* CopyConsoleUser(UInt32 uid
)
1140 OSDictionary
* user
= 0;
1142 if ((array
= OSDynamicCast(OSArray
,
1143 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1145 for (unsigned int idx
= 0;
1146 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1150 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
1151 && (uid
== num
->unsigned32BitValue())) {
1161 static OSDictionary
* CopyUserOnConsole(void)
1164 OSDictionary
* user
= 0;
1166 if ((array
= OSDynamicCast(OSArray
,
1167 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1169 for (unsigned int idx
= 0;
1170 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1173 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
1184 IOReturn
IOUserClient::clientHasAuthorization( task_t task
,
1185 IOService
* service
)
1189 p
= (proc_t
) get_bsdtask_info(task
);
1192 uint64_t authorizationID
;
1194 authorizationID
= proc_uniqueid(p
);
1195 if (authorizationID
)
1197 if (service
->getAuthorizationID() == authorizationID
)
1199 return (kIOReturnSuccess
);
1204 return (kIOReturnNotPermitted
);
1207 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
1208 const char * privilegeName
)
1211 security_token_t token
;
1212 mach_msg_type_number_t count
;
1214 OSDictionary
* user
;
1218 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
1219 sizeof(kIOClientPrivilegeForeground
)))
1221 if (task_is_gpu_denied(current_task()))
1222 return (kIOReturnNotPrivileged
);
1224 return (kIOReturnSuccess
);
1227 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1228 sizeof(kIOClientPrivilegeConsoleSession
)))
1233 task
= (task_t
) securityToken
;
1235 task
= current_task();
1236 p
= (proc_t
) get_bsdtask_info(task
);
1237 kr
= kIOReturnNotPrivileged
;
1239 if (p
&& (cred
= kauth_cred_proc_ref(p
)))
1241 user
= CopyUserOnConsole();
1245 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1246 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue()))
1248 kr
= kIOReturnSuccess
;
1252 kauth_cred_unref(&cred
);
1257 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1258 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
1259 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1261 task
= (task_t
)securityToken
;
1263 count
= TASK_SECURITY_TOKEN_COUNT
;
1264 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1266 if (KERN_SUCCESS
!= kr
)
1268 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1269 sizeof(kIOClientPrivilegeAdministrator
))) {
1270 if (0 != token
.val
[0])
1271 kr
= kIOReturnNotPrivileged
;
1272 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1273 sizeof(kIOClientPrivilegeLocalUser
))) {
1274 user
= CopyConsoleUser(token
.val
[0]);
1278 kr
= kIOReturnNotPrivileged
;
1279 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1280 sizeof(kIOClientPrivilegeConsoleUser
))) {
1281 user
= CopyConsoleUser(token
.val
[0]);
1283 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
1284 kr
= kIOReturnNotPrivileged
;
1285 else if ( secureConsole
) {
1286 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1287 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
1288 kr
= kIOReturnNotPrivileged
;
1293 kr
= kIOReturnNotPrivileged
;
1295 kr
= kIOReturnUnsupported
;
1300 OSObject
* IOUserClient::copyClientEntitlement( task_t task
,
1301 const char * entitlement
)
1303 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1307 char procname
[MAXCOMLEN
+ 1] = "";
1309 void *entitlements_blob
= NULL
;
1310 char *entitlements_data
= NULL
;
1311 OSObject
*entitlements_obj
= NULL
;
1312 OSDictionary
*entitlements
= NULL
;
1313 OSString
*errorString
= NULL
;
1314 OSObject
*value
= NULL
;
1316 p
= (proc_t
)get_bsdtask_info(task
);
1320 proc_name(pid
, procname
, (int)sizeof(procname
));
1322 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0)
1325 if (len
<= offsetof(CS_GenericBlob
, data
))
1329 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1330 * we'll try to parse in the kernel.
1332 len
-= offsetof(CS_GenericBlob
, data
);
1333 if (len
> MAX_ENTITLEMENTS_LEN
) {
1334 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n", procname
, pid
, len
, MAX_ENTITLEMENTS_LEN
);
1339 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1340 * what is stored in the entitlements blob. Copy the string and
1343 entitlements_data
= (char *)IOMalloc(len
+ 1);
1344 if (entitlements_data
== NULL
)
1346 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1347 entitlements_data
[len
] = '\0';
1349 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1350 if (errorString
!= NULL
) {
1351 IOLog("failed to parse entitlements for %s[%u]: %s\n", procname
, pid
, errorString
->getCStringNoCopy());
1354 if (entitlements_obj
== NULL
)
1357 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1358 if (entitlements
== NULL
)
1361 /* Fetch the entitlement value from the dictionary. */
1362 value
= entitlements
->getObject(entitlement
);
1367 if (entitlements_data
!= NULL
)
1368 IOFree(entitlements_data
, len
+ 1);
1369 if (entitlements_obj
!= NULL
)
1370 entitlements_obj
->release();
1371 if (errorString
!= NULL
)
1372 errorString
->release();
1376 bool IOUserClient::init()
1378 if (getPropertyTable() || super::init())
1384 bool IOUserClient::init(OSDictionary
* dictionary
)
1386 if (getPropertyTable() || super::init(dictionary
))
1392 bool IOUserClient::initWithTask(task_t owningTask
,
1396 if (getPropertyTable() || super::init())
1402 bool IOUserClient::initWithTask(task_t owningTask
,
1405 OSDictionary
* properties
)
1409 ok
= super::init( properties
);
1410 ok
&= initWithTask( owningTask
, securityID
, type
);
1415 bool IOUserClient::reserve()
1418 reserved
= IONew(ExpansionData
, 1);
1423 setTerminateDefer(NULL
, true);
1424 IOStatisticsRegisterCounter();
1429 struct IOUserClientOwner
1432 queue_chain_t taskLink
;
1434 queue_chain_t ucLink
;
1438 IOUserClient::registerOwner(task_t task
)
1440 IOUserClientOwner
* owner
;
1444 IOLockLock(gIOUserClientOwnersLock
);
1447 ret
= kIOReturnSuccess
;
1449 if (!owners
.next
) queue_init(&owners
);
1452 queue_iterate(&owners
, owner
, IOUserClientOwner
*, ucLink
)
1454 if (task
!= owner
->task
) continue;
1461 owner
= IONew(IOUserClientOwner
, 1);
1462 if (!newOwner
) ret
= kIOReturnNoMemory
;
1467 queue_enter_first(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1468 queue_enter_first(task_io_user_clients(task
), owner
, IOUserClientOwner
*, taskLink
);
1472 IOLockUnlock(gIOUserClientOwnersLock
);
1478 IOUserClient::noMoreSenders(void)
1480 IOUserClientOwner
* owner
;
1482 IOLockLock(gIOUserClientOwnersLock
);
1486 while (!queue_empty(&owners
))
1488 owner
= (IOUserClientOwner
*)(void *) queue_first(&owners
);
1489 queue_remove(task_io_user_clients(owner
->task
), owner
, IOUserClientOwner
*, taskLink
);
1490 queue_remove(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1491 IODelete(owner
, IOUserClientOwner
, 1);
1493 owners
.next
= owners
.prev
= NULL
;
1496 IOLockUnlock(gIOUserClientOwnersLock
);
1499 extern "C" kern_return_t
1500 iokit_task_terminate(task_t task
)
1502 IOUserClientOwner
* owner
;
1503 IOUserClient
* dead
;
1505 queue_head_t
* taskque
;
1507 IOLockLock(gIOUserClientOwnersLock
);
1509 taskque
= task_io_user_clients(task
);
1511 while (!queue_empty(taskque
))
1513 owner
= (IOUserClientOwner
*)(void *) queue_first(taskque
);
1515 queue_remove(taskque
, owner
, IOUserClientOwner
*, taskLink
);
1516 queue_remove(&uc
->owners
, owner
, IOUserClientOwner
*, ucLink
);
1517 if (queue_empty(&uc
->owners
))
1520 IOLog("destroying out of band connect for %s\n", uc
->getName());
1521 // now using the uc queue head as a singly linked queue,
1522 // leaving .next as NULL to mark it empty
1523 uc
->owners
.next
= NULL
;
1524 uc
->owners
.prev
= (queue_entry_t
) dead
;
1527 IODelete(owner
, IOUserClientOwner
, 1);
1530 IOLockUnlock(gIOUserClientOwnersLock
);
1535 dead
= (IOUserClient
*)(void *) dead
->owners
.prev
;
1536 uc
->owners
.prev
= NULL
;
1537 if (uc
->sharedInstance
|| !uc
->closed
) uc
->clientDied();
1541 return (KERN_SUCCESS
);
1544 void IOUserClient::free()
1546 if( mappings
) mappings
->release();
1548 IOStatisticsUnregisterCounter();
1550 assert(!owners
.next
);
1551 assert(!owners
.prev
);
1553 if (reserved
) IODelete(reserved
, ExpansionData
, 1);
1558 IOReturn
IOUserClient::clientDied( void )
1560 IOReturn ret
= kIOReturnNotReady
;
1562 if (sharedInstance
|| OSCompareAndSwap8(0, 1, &closed
))
1564 ret
= clientClose();
1570 IOReturn
IOUserClient::clientClose( void )
1572 return( kIOReturnUnsupported
);
1575 IOService
* IOUserClient::getService( void )
1580 IOReturn
IOUserClient::registerNotificationPort(
1581 mach_port_t
/* port */,
1583 UInt32
/* refCon */)
1585 return( kIOReturnUnsupported
);
1588 IOReturn
IOUserClient::registerNotificationPort(
1591 io_user_reference_t refCon
)
1593 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
1596 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1597 semaphore_t
* semaphore
)
1599 return( kIOReturnUnsupported
);
1602 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
1604 return( kIOReturnUnsupported
);
1607 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
1608 IOOptionBits
* options
,
1609 IOMemoryDescriptor
** memory
)
1611 return( kIOReturnUnsupported
);
1615 IOMemoryMap
* IOUserClient::mapClientMemory(
1618 IOOptionBits mapFlags
,
1619 IOVirtualAddress atAddress
)
1625 IOMemoryMap
* IOUserClient::mapClientMemory64(
1628 IOOptionBits mapFlags
,
1629 mach_vm_address_t atAddress
)
1632 IOOptionBits options
= 0;
1633 IOMemoryDescriptor
* memory
= 0;
1634 IOMemoryMap
* map
= 0;
1636 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1638 if( memory
&& (kIOReturnSuccess
== err
)) {
1640 FAKE_STACK_FRAME(getMetaClass());
1642 options
= (options
& ~kIOMapUserOptionsMask
)
1643 | (mapFlags
& kIOMapUserOptionsMask
);
1644 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1647 FAKE_STACK_FRAME_END();
1653 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1654 OSObject
*obj
, io_object_t
*clientObj
)
1656 mach_port_name_t name
;
1658 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1660 *(mach_port_name_t
*)clientObj
= name
;
1661 return kIOReturnSuccess
;
1664 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1669 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1674 IOExternalTrap
* IOUserClient::
1675 getExternalTrapForIndex(UInt32 index
)
1680 #pragma clang diagnostic push
1681 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1683 // Suppressing the deprecated-declarations warning. Avoiding the use of deprecated
1684 // functions can break clients of kexts implementing getExternalMethodForIndex()
1685 IOExternalMethod
* IOUserClient::
1686 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1688 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1691 *targetP
= (IOService
*) method
->object
;
1696 IOExternalAsyncMethod
* IOUserClient::
1697 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1699 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1702 *targetP
= (IOService
*) method
->object
;
1707 IOExternalTrap
* IOUserClient::
1708 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1710 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1713 *targetP
= trap
->object
;
1718 #pragma clang diagnostic pop
1720 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1723 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1725 if (MACH_PORT_NULL
!= port
)
1726 iokit_release_port_send(port
);
1728 return (kIOReturnSuccess
);
1731 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1733 if (MACH_PORT_NULL
!= port
)
1734 iokit_release_port_send(port
);
1736 return (kIOReturnSuccess
);
1739 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1740 IOReturn result
, void *args
[], UInt32 numArgs
)
1742 OSAsyncReference64 reference64
;
1743 io_user_reference_t args64
[kMaxAsyncArgs
];
1746 if (numArgs
> kMaxAsyncArgs
)
1747 return kIOReturnMessageTooLarge
;
1749 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1750 reference64
[idx
] = REF64(reference
[idx
]);
1752 for (idx
= 0; idx
< numArgs
; idx
++)
1753 args64
[idx
] = REF64(args
[idx
]);
1755 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1758 IOReturn
IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
1759 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1761 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
1764 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1765 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1767 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
1770 IOReturn
IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
1771 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1775 mach_msg_header_t msgHdr
;
1780 OSNotificationHeader notifyHdr
;
1781 IOAsyncCompletionContent asyncContent
;
1782 uint32_t args
[kMaxAsyncArgs
];
1786 OSNotificationHeader64 notifyHdr
;
1787 IOAsyncCompletionContent asyncContent
;
1788 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1793 mach_port_t replyPort
;
1796 // If no reply port, do nothing.
1797 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1798 if (replyPort
== MACH_PORT_NULL
)
1799 return kIOReturnSuccess
;
1801 if (numArgs
> kMaxAsyncArgs
)
1802 return kIOReturnMessageTooLarge
;
1804 bzero(&replyMsg
, sizeof(replyMsg
));
1805 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1807 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1808 replyMsg
.msgHdr
.msgh_local_port
= 0;
1809 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1810 if (kIOUCAsync64Flag
& reference
[0])
1812 replyMsg
.msgHdr
.msgh_size
=
1813 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1814 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1815 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1816 + numArgs
* sizeof(io_user_reference_t
);
1817 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1818 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1820 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1822 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1828 replyMsg
.msgHdr
.msgh_size
=
1829 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1830 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1832 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1833 + numArgs
* sizeof(uint32_t);
1834 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1836 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1837 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1839 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1841 for (idx
= 0; idx
< numArgs
; idx
++)
1842 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1845 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
1846 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
1847 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
1849 /* Fail on full queue. */
1850 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1851 replyMsg
.msgHdr
.msgh_size
);
1853 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
) && !(kIOUCAsyncErrorLoggedFlag
& reference
[0]))
1855 reference
[0] |= kIOUCAsyncErrorLoggedFlag
;
1856 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1862 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1866 #define CHECK(cls,obj,out) \
1868 if( !(out = OSDynamicCast( cls, obj))) \
1869 return( kIOReturnBadArgument )
1871 #define CHECKLOCKED(cls,obj,out) \
1872 IOUserIterator * oIter; \
1874 if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
1875 return (kIOReturnBadArgument); \
1876 if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
1877 return (kIOReturnBadArgument)
1879 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1881 // Create a vm_map_copy_t or kalloc'ed data for memory
1882 // to be copied out. ipc will free after the copyout.
1884 static kern_return_t
copyoutkdata( const void * data
, vm_size_t len
,
1885 io_buf_ptr_t
* buf
)
1890 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1891 false /* src_destroy */, ©
);
1893 assert( err
== KERN_SUCCESS
);
1894 if( err
== KERN_SUCCESS
)
1895 *buf
= (char *) copy
;
1900 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1902 /* Routine io_server_version */
1903 kern_return_t
is_io_server_version(
1904 mach_port_t master_port
,
1907 *version
= IOKIT_SERVER_VERSION
;
1908 return (kIOReturnSuccess
);
1911 /* Routine io_object_get_class */
1912 kern_return_t
is_io_object_get_class(
1914 io_name_t className
)
1916 const OSMetaClass
* my_obj
= NULL
;
1919 return( kIOReturnBadArgument
);
1921 my_obj
= object
->getMetaClass();
1923 return (kIOReturnNotFound
);
1926 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
1928 return( kIOReturnSuccess
);
1931 /* Routine io_object_get_superclass */
1932 kern_return_t
is_io_object_get_superclass(
1933 mach_port_t master_port
,
1935 io_name_t class_name
)
1938 const OSMetaClass
* meta
;
1939 const OSMetaClass
* super
;
1940 const OSSymbol
* name
;
1943 if (!obj_name
|| !class_name
) return (kIOReturnBadArgument
);
1944 if (master_port
!= master_device_port
) return( kIOReturnNotPrivileged
);
1946 ret
= kIOReturnNotFound
;
1950 name
= OSSymbol::withCString(obj_name
);
1952 meta
= OSMetaClass::copyMetaClassWithName(name
);
1954 super
= meta
->getSuperClass();
1956 cstr
= super
->getClassName();
1958 strlcpy(class_name
, cstr
, sizeof(io_name_t
));
1959 ret
= kIOReturnSuccess
;
1963 OSSafeReleaseNULL(name
);
1964 if (meta
) meta
->releaseMetaClass();
1969 /* Routine io_object_get_bundle_identifier */
1970 kern_return_t
is_io_object_get_bundle_identifier(
1971 mach_port_t master_port
,
1973 io_name_t bundle_name
)
1976 const OSMetaClass
* meta
;
1977 const OSSymbol
* name
;
1978 const OSSymbol
* identifier
;
1981 if (!obj_name
|| !bundle_name
) return (kIOReturnBadArgument
);
1982 if (master_port
!= master_device_port
) return( kIOReturnNotPrivileged
);
1984 ret
= kIOReturnNotFound
;
1988 name
= OSSymbol::withCString(obj_name
);
1990 meta
= OSMetaClass::copyMetaClassWithName(name
);
1992 identifier
= meta
->getKmodName();
1993 if (!identifier
) break;
1994 cstr
= identifier
->getCStringNoCopy();
1996 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
1997 ret
= kIOReturnSuccess
;
2001 OSSafeReleaseNULL(name
);
2002 if (meta
) meta
->releaseMetaClass();
2007 /* Routine io_object_conforms_to */
2008 kern_return_t
is_io_object_conforms_to(
2010 io_name_t className
,
2011 boolean_t
*conforms
)
2014 return( kIOReturnBadArgument
);
2016 *conforms
= (0 != object
->metaCast( className
));
2018 return( kIOReturnSuccess
);
2021 /* Routine io_object_get_retain_count */
2022 kern_return_t
is_io_object_get_retain_count(
2024 uint32_t *retainCount
)
2027 return( kIOReturnBadArgument
);
2029 *retainCount
= object
->getRetainCount();
2030 return( kIOReturnSuccess
);
2033 /* Routine io_iterator_next */
2034 kern_return_t
is_io_iterator_next(
2035 io_object_t iterator
,
2036 io_object_t
*object
)
2041 CHECK( OSIterator
, iterator
, iter
);
2043 obj
= iter
->getNextObject();
2047 ret
= kIOReturnSuccess
;
2049 ret
= kIOReturnNoDevice
;
2054 /* Routine io_iterator_reset */
2055 kern_return_t
is_io_iterator_reset(
2056 io_object_t iterator
)
2058 CHECK( OSIterator
, iterator
, iter
);
2062 return( kIOReturnSuccess
);
2065 /* Routine io_iterator_is_valid */
2066 kern_return_t
is_io_iterator_is_valid(
2067 io_object_t iterator
,
2068 boolean_t
*is_valid
)
2070 CHECK( OSIterator
, iterator
, iter
);
2072 *is_valid
= iter
->isValid();
2074 return( kIOReturnSuccess
);
2078 static kern_return_t
internal_io_service_match_property_table(
2079 io_service_t _service
,
2080 const char * matching
,
2081 mach_msg_type_number_t matching_size
,
2084 CHECK( IOService
, _service
, service
);
2088 OSDictionary
* dict
;
2090 assert(matching_size
);
2091 obj
= OSUnserializeXML(matching
, matching_size
);
2093 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2094 *matches
= service
->passiveMatch( dict
);
2095 kr
= kIOReturnSuccess
;
2097 kr
= kIOReturnBadArgument
;
2105 /* Routine io_service_match_property_table */
2106 kern_return_t
is_io_service_match_property_table(
2107 io_service_t service
,
2108 io_string_t matching
,
2109 boolean_t
*matches
)
2111 return (kIOReturnUnsupported
);
2115 /* Routine io_service_match_property_table_ool */
2116 kern_return_t
is_io_service_match_property_table_ool(
2117 io_object_t service
,
2118 io_buf_ptr_t matching
,
2119 mach_msg_type_number_t matchingCnt
,
2120 kern_return_t
*result
,
2121 boolean_t
*matches
)
2125 vm_map_offset_t map_data
;
2127 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2128 data
= CAST_DOWN(vm_offset_t
, map_data
);
2130 if( KERN_SUCCESS
== kr
) {
2131 // must return success after vm_map_copyout() succeeds
2132 *result
= internal_io_service_match_property_table(service
,
2133 (const char *)data
, matchingCnt
, matches
);
2134 vm_deallocate( kernel_map
, data
, matchingCnt
);
2140 /* Routine io_service_match_property_table_bin */
2141 kern_return_t
is_io_service_match_property_table_bin(
2142 io_object_t service
,
2143 io_struct_inband_t matching
,
2144 mach_msg_type_number_t matchingCnt
,
2147 return (internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
));
2150 static kern_return_t
internal_io_service_get_matching_services(
2151 mach_port_t master_port
,
2152 const char * matching
,
2153 mach_msg_type_number_t matching_size
,
2154 io_iterator_t
*existing
)
2158 OSDictionary
* dict
;
2160 if( master_port
!= master_device_port
)
2161 return( kIOReturnNotPrivileged
);
2163 assert(matching_size
);
2164 obj
= OSUnserializeXML(matching
, matching_size
);
2166 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2167 *existing
= IOUserIterator::withIterator(IOService::getMatchingServices( dict
));
2168 kr
= kIOReturnSuccess
;
2170 kr
= kIOReturnBadArgument
;
2178 /* Routine io_service_get_matching_services */
2179 kern_return_t
is_io_service_get_matching_services(
2180 mach_port_t master_port
,
2181 io_string_t matching
,
2182 io_iterator_t
*existing
)
2184 return (kIOReturnUnsupported
);
2187 /* Routine io_service_get_matching_services_ool */
2188 kern_return_t
is_io_service_get_matching_services_ool(
2189 mach_port_t master_port
,
2190 io_buf_ptr_t matching
,
2191 mach_msg_type_number_t matchingCnt
,
2192 kern_return_t
*result
,
2193 io_object_t
*existing
)
2197 vm_map_offset_t map_data
;
2199 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2200 data
= CAST_DOWN(vm_offset_t
, map_data
);
2202 if( KERN_SUCCESS
== kr
) {
2203 // must return success after vm_map_copyout() succeeds
2204 // and mig will copy out objects on success
2206 *result
= internal_io_service_get_matching_services(master_port
,
2207 (const char *) data
, matchingCnt
, existing
);
2208 vm_deallocate( kernel_map
, data
, matchingCnt
);
2214 /* Routine io_service_get_matching_services_bin */
2215 kern_return_t
is_io_service_get_matching_services_bin(
2216 mach_port_t master_port
,
2217 io_struct_inband_t matching
,
2218 mach_msg_type_number_t matchingCnt
,
2219 io_object_t
*existing
)
2221 return (internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
));
2225 static kern_return_t
internal_io_service_get_matching_service(
2226 mach_port_t master_port
,
2227 const char * matching
,
2228 mach_msg_type_number_t matching_size
,
2229 io_service_t
*service
)
2233 OSDictionary
* dict
;
2235 if( master_port
!= master_device_port
)
2236 return( kIOReturnNotPrivileged
);
2238 assert(matching_size
);
2239 obj
= OSUnserializeXML(matching
, matching_size
);
2241 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2242 *service
= IOService::copyMatchingService( dict
);
2243 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
2245 kr
= kIOReturnBadArgument
;
2253 /* Routine io_service_get_matching_service */
2254 kern_return_t
is_io_service_get_matching_service(
2255 mach_port_t master_port
,
2256 io_string_t matching
,
2257 io_service_t
*service
)
2259 return (kIOReturnUnsupported
);
2262 /* Routine io_service_get_matching_services_ool */
2263 kern_return_t
is_io_service_get_matching_service_ool(
2264 mach_port_t master_port
,
2265 io_buf_ptr_t matching
,
2266 mach_msg_type_number_t matchingCnt
,
2267 kern_return_t
*result
,
2268 io_object_t
*service
)
2272 vm_map_offset_t map_data
;
2274 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2275 data
= CAST_DOWN(vm_offset_t
, map_data
);
2277 if( KERN_SUCCESS
== kr
) {
2278 // must return success after vm_map_copyout() succeeds
2279 // and mig will copy out objects on success
2281 *result
= internal_io_service_get_matching_service(master_port
,
2282 (const char *) data
, matchingCnt
, service
);
2283 vm_deallocate( kernel_map
, data
, matchingCnt
);
2289 /* Routine io_service_get_matching_service_bin */
2290 kern_return_t
is_io_service_get_matching_service_bin(
2291 mach_port_t master_port
,
2292 io_struct_inband_t matching
,
2293 mach_msg_type_number_t matchingCnt
,
2294 io_object_t
*service
)
2296 return (internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
));
2299 static kern_return_t
internal_io_service_add_notification(
2300 mach_port_t master_port
,
2301 io_name_t notification_type
,
2302 const char * matching
,
2303 size_t matching_size
,
2306 vm_size_t referenceSize
,
2308 io_object_t
* notification
)
2310 IOServiceUserNotification
* userNotify
= 0;
2311 IONotifier
* notify
= 0;
2312 const OSSymbol
* sym
;
2313 OSDictionary
* dict
;
2315 unsigned long int userMsgType
;
2317 if( master_port
!= master_device_port
)
2318 return( kIOReturnNotPrivileged
);
2321 err
= kIOReturnNoResources
;
2323 if (matching_size
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2325 if( !(sym
= OSSymbol::withCString( notification_type
)))
2326 err
= kIOReturnNoResources
;
2328 assert(matching_size
);
2329 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
2331 err
= kIOReturnBadArgument
;
2335 if( (sym
== gIOPublishNotification
)
2336 || (sym
== gIOFirstPublishNotification
))
2337 userMsgType
= kIOServicePublishNotificationType
;
2338 else if( (sym
== gIOMatchedNotification
)
2339 || (sym
== gIOFirstMatchNotification
))
2340 userMsgType
= kIOServiceMatchedNotificationType
;
2341 else if ((sym
== gIOTerminatedNotification
)
2342 || (sym
== gIOWillTerminateNotification
))
2343 userMsgType
= kIOServiceTerminatedNotificationType
;
2345 userMsgType
= kLastIOKitNotificationType
;
2347 userNotify
= new IOServiceUserNotification
;
2349 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
2350 reference
, referenceSize
, client64
)) {
2351 userNotify
->release();
2357 notify
= IOService::addMatchingNotification( sym
, dict
,
2358 &userNotify
->_handler
, userNotify
);
2360 *notification
= userNotify
;
2361 userNotify
->setNotification( notify
);
2362 err
= kIOReturnSuccess
;
2364 err
= kIOReturnUnsupported
;
2368 if ((kIOReturnSuccess
!= err
) && userNotify
)
2370 userNotify
->invalidatePort();
2371 userNotify
->release();
2384 /* Routine io_service_add_notification */
2385 kern_return_t
is_io_service_add_notification(
2386 mach_port_t master_port
,
2387 io_name_t notification_type
,
2388 io_string_t matching
,
2390 io_async_ref_t reference
,
2391 mach_msg_type_number_t referenceCnt
,
2392 io_object_t
* notification
)
2394 return (kIOReturnUnsupported
);
2397 /* Routine io_service_add_notification_64 */
2398 kern_return_t
is_io_service_add_notification_64(
2399 mach_port_t master_port
,
2400 io_name_t notification_type
,
2401 io_string_t matching
,
2402 mach_port_t wake_port
,
2403 io_async_ref64_t reference
,
2404 mach_msg_type_number_t referenceCnt
,
2405 io_object_t
*notification
)
2407 return (kIOReturnUnsupported
);
2410 /* Routine io_service_add_notification_bin */
2411 kern_return_t is_io_service_add_notification_bin
2413 mach_port_t master_port
,
2414 io_name_t notification_type
,
2415 io_struct_inband_t matching
,
2416 mach_msg_type_number_t matchingCnt
,
2417 mach_port_t wake_port
,
2418 io_async_ref_t reference
,
2419 mach_msg_type_number_t referenceCnt
,
2420 io_object_t
*notification
)
2422 return (internal_io_service_add_notification(master_port
, notification_type
,
2423 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2424 false, notification
));
2427 /* Routine io_service_add_notification_bin_64 */
2428 kern_return_t is_io_service_add_notification_bin_64
2430 mach_port_t master_port
,
2431 io_name_t notification_type
,
2432 io_struct_inband_t matching
,
2433 mach_msg_type_number_t matchingCnt
,
2434 mach_port_t wake_port
,
2435 io_async_ref64_t reference
,
2436 mach_msg_type_number_t referenceCnt
,
2437 io_object_t
*notification
)
2439 return (internal_io_service_add_notification(master_port
, notification_type
,
2440 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2441 true, notification
));
2444 static kern_return_t
internal_io_service_add_notification_ool(
2445 mach_port_t master_port
,
2446 io_name_t notification_type
,
2447 io_buf_ptr_t matching
,
2448 mach_msg_type_number_t matchingCnt
,
2449 mach_port_t wake_port
,
2451 vm_size_t referenceSize
,
2453 kern_return_t
*result
,
2454 io_object_t
*notification
)
2458 vm_map_offset_t map_data
;
2460 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2461 data
= CAST_DOWN(vm_offset_t
, map_data
);
2463 if( KERN_SUCCESS
== kr
) {
2464 // must return success after vm_map_copyout() succeeds
2465 // and mig will copy out objects on success
2467 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2468 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2469 vm_deallocate( kernel_map
, data
, matchingCnt
);
2475 /* Routine io_service_add_notification_ool */
2476 kern_return_t
is_io_service_add_notification_ool(
2477 mach_port_t master_port
,
2478 io_name_t notification_type
,
2479 io_buf_ptr_t matching
,
2480 mach_msg_type_number_t matchingCnt
,
2481 mach_port_t wake_port
,
2482 io_async_ref_t reference
,
2483 mach_msg_type_number_t referenceCnt
,
2484 kern_return_t
*result
,
2485 io_object_t
*notification
)
2487 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2488 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2489 false, result
, notification
));
2492 /* Routine io_service_add_notification_ool_64 */
2493 kern_return_t
is_io_service_add_notification_ool_64(
2494 mach_port_t master_port
,
2495 io_name_t notification_type
,
2496 io_buf_ptr_t matching
,
2497 mach_msg_type_number_t matchingCnt
,
2498 mach_port_t wake_port
,
2499 io_async_ref64_t reference
,
2500 mach_msg_type_number_t referenceCnt
,
2501 kern_return_t
*result
,
2502 io_object_t
*notification
)
2504 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2505 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2506 true, result
, notification
));
2509 /* Routine io_service_add_notification_old */
2510 kern_return_t
is_io_service_add_notification_old(
2511 mach_port_t master_port
,
2512 io_name_t notification_type
,
2513 io_string_t matching
,
2515 // for binary compatibility reasons, this must be natural_t for ILP32
2517 io_object_t
* notification
)
2519 return( is_io_service_add_notification( master_port
, notification_type
,
2520 matching
, port
, &ref
, 1, notification
));
2524 static kern_return_t
internal_io_service_add_interest_notification(
2525 io_object_t _service
,
2526 io_name_t type_of_interest
,
2529 vm_size_t referenceSize
,
2531 io_object_t
* notification
)
2534 IOServiceMessageUserNotification
* userNotify
= 0;
2535 IONotifier
* notify
= 0;
2536 const OSSymbol
* sym
;
2539 CHECK( IOService
, _service
, service
);
2541 err
= kIOReturnNoResources
;
2542 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
2544 userNotify
= new IOServiceMessageUserNotification
;
2546 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2547 reference
, referenceSize
,
2548 kIOUserNotifyMaxMessageSize
,
2550 userNotify
->release();
2556 notify
= service
->registerInterest( sym
,
2557 &userNotify
->_handler
, userNotify
);
2559 *notification
= userNotify
;
2560 userNotify
->setNotification( notify
);
2561 err
= kIOReturnSuccess
;
2563 err
= kIOReturnUnsupported
;
2569 if ((kIOReturnSuccess
!= err
) && userNotify
)
2571 userNotify
->invalidatePort();
2572 userNotify
->release();
2579 /* Routine io_service_add_message_notification */
2580 kern_return_t
is_io_service_add_interest_notification(
2581 io_object_t service
,
2582 io_name_t type_of_interest
,
2584 io_async_ref_t reference
,
2585 mach_msg_type_number_t referenceCnt
,
2586 io_object_t
* notification
)
2588 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2589 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
2592 /* Routine io_service_add_interest_notification_64 */
2593 kern_return_t
is_io_service_add_interest_notification_64(
2594 io_object_t service
,
2595 io_name_t type_of_interest
,
2596 mach_port_t wake_port
,
2597 io_async_ref64_t reference
,
2598 mach_msg_type_number_t referenceCnt
,
2599 io_object_t
*notification
)
2601 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2602 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
2606 /* Routine io_service_acknowledge_notification */
2607 kern_return_t
is_io_service_acknowledge_notification(
2608 io_object_t _service
,
2609 natural_t notify_ref
,
2610 natural_t response
)
2612 CHECK( IOService
, _service
, service
);
2614 return( service
->acknowledgeNotification( (IONotificationRef
)(uintptr_t) notify_ref
,
2615 (IOOptionBits
) response
));
2619 /* Routine io_connect_get_semaphore */
2620 kern_return_t
is_io_connect_get_notification_semaphore(
2621 io_connect_t connection
,
2622 natural_t notification_type
,
2623 semaphore_t
*semaphore
)
2625 CHECK( IOUserClient
, connection
, client
);
2627 IOStatisticsClientCall();
2628 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
2632 /* Routine io_registry_get_root_entry */
2633 kern_return_t
is_io_registry_get_root_entry(
2634 mach_port_t master_port
,
2637 IORegistryEntry
* entry
;
2639 if( master_port
!= master_device_port
)
2640 return( kIOReturnNotPrivileged
);
2642 entry
= IORegistryEntry::getRegistryRoot();
2647 return( kIOReturnSuccess
);
2650 /* Routine io_registry_create_iterator */
2651 kern_return_t
is_io_registry_create_iterator(
2652 mach_port_t master_port
,
2655 io_object_t
*iterator
)
2657 if( master_port
!= master_device_port
)
2658 return( kIOReturnNotPrivileged
);
2660 *iterator
= IOUserIterator::withIterator(
2661 IORegistryIterator::iterateOver(
2662 IORegistryEntry::getPlane( plane
), options
));
2664 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2667 /* Routine io_registry_entry_create_iterator */
2668 kern_return_t
is_io_registry_entry_create_iterator(
2669 io_object_t registry_entry
,
2672 io_object_t
*iterator
)
2674 CHECK( IORegistryEntry
, registry_entry
, entry
);
2676 *iterator
= IOUserIterator::withIterator(
2677 IORegistryIterator::iterateOver( entry
,
2678 IORegistryEntry::getPlane( plane
), options
));
2680 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2683 /* Routine io_registry_iterator_enter */
2684 kern_return_t
is_io_registry_iterator_enter_entry(
2685 io_object_t iterator
)
2687 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2689 IOLockLock(oIter
->lock
);
2691 IOLockUnlock(oIter
->lock
);
2693 return( kIOReturnSuccess
);
2696 /* Routine io_registry_iterator_exit */
2697 kern_return_t
is_io_registry_iterator_exit_entry(
2698 io_object_t iterator
)
2702 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2704 IOLockLock(oIter
->lock
);
2705 didIt
= iter
->exitEntry();
2706 IOLockUnlock(oIter
->lock
);
2708 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
2711 /* Routine io_registry_entry_from_path */
2712 kern_return_t
is_io_registry_entry_from_path(
2713 mach_port_t master_port
,
2715 io_object_t
*registry_entry
)
2717 IORegistryEntry
* entry
;
2719 if( master_port
!= master_device_port
)
2720 return( kIOReturnNotPrivileged
);
2722 entry
= IORegistryEntry::fromPath( path
);
2724 *registry_entry
= entry
;
2726 return( kIOReturnSuccess
);
2730 /* Routine io_registry_entry_from_path */
2731 kern_return_t
is_io_registry_entry_from_path_ool(
2732 mach_port_t master_port
,
2733 io_string_inband_t path
,
2734 io_buf_ptr_t path_ool
,
2735 mach_msg_type_number_t path_oolCnt
,
2736 kern_return_t
*result
,
2737 io_object_t
*registry_entry
)
2739 IORegistryEntry
* entry
;
2740 vm_map_offset_t map_data
;
2745 if (master_port
!= master_device_port
) return(kIOReturnNotPrivileged
);
2749 res
= err
= KERN_SUCCESS
;
2750 if (path
[0]) cpath
= path
;
2753 if (!path_oolCnt
) return(kIOReturnBadArgument
);
2754 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2756 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
2757 if (KERN_SUCCESS
== err
)
2759 // must return success to mig after vm_map_copyout() succeeds, so result is actual
2760 cpath
= CAST_DOWN(const char *, map_data
);
2761 if (cpath
[path_oolCnt
- 1]) res
= kIOReturnBadArgument
;
2765 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
))
2767 entry
= IORegistryEntry::fromPath(cpath
);
2768 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
2771 if (map_data
) vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
2773 if (KERN_SUCCESS
!= err
) res
= err
;
2774 *registry_entry
= entry
;
2781 /* Routine io_registry_entry_in_plane */
2782 kern_return_t
is_io_registry_entry_in_plane(
2783 io_object_t registry_entry
,
2785 boolean_t
*inPlane
)
2787 CHECK( IORegistryEntry
, registry_entry
, entry
);
2789 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
2791 return( kIOReturnSuccess
);
2795 /* Routine io_registry_entry_get_path */
2796 kern_return_t
is_io_registry_entry_get_path(
2797 io_object_t registry_entry
,
2802 CHECK( IORegistryEntry
, registry_entry
, entry
);
2804 length
= sizeof( io_string_t
);
2805 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
2806 return( kIOReturnSuccess
);
2808 return( kIOReturnBadArgument
);
2811 /* Routine io_registry_entry_get_path */
2812 kern_return_t
is_io_registry_entry_get_path_ool(
2813 io_object_t registry_entry
,
2815 io_string_inband_t path
,
2816 io_buf_ptr_t
*path_ool
,
2817 mach_msg_type_number_t
*path_oolCnt
)
2819 enum { kMaxPath
= 16384 };
2824 CHECK( IORegistryEntry
, registry_entry
, entry
);
2828 length
= sizeof(io_string_inband_t
);
2829 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnSuccess
;
2833 buf
= IONew(char, length
);
2834 if (!buf
) err
= kIOReturnNoMemory
;
2835 else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnError
;
2838 *path_oolCnt
= length
;
2839 err
= copyoutkdata(buf
, length
, path_ool
);
2841 if (buf
) IODelete(buf
, char, kMaxPath
);
2848 /* Routine io_registry_entry_get_name */
2849 kern_return_t
is_io_registry_entry_get_name(
2850 io_object_t registry_entry
,
2853 CHECK( IORegistryEntry
, registry_entry
, entry
);
2855 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
2857 return( kIOReturnSuccess
);
2860 /* Routine io_registry_entry_get_name_in_plane */
2861 kern_return_t
is_io_registry_entry_get_name_in_plane(
2862 io_object_t registry_entry
,
2863 io_name_t planeName
,
2866 const IORegistryPlane
* plane
;
2867 CHECK( IORegistryEntry
, registry_entry
, entry
);
2870 plane
= IORegistryEntry::getPlane( planeName
);
2874 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
2876 return( kIOReturnSuccess
);
2879 /* Routine io_registry_entry_get_location_in_plane */
2880 kern_return_t
is_io_registry_entry_get_location_in_plane(
2881 io_object_t registry_entry
,
2882 io_name_t planeName
,
2883 io_name_t location
)
2885 const IORegistryPlane
* plane
;
2886 CHECK( IORegistryEntry
, registry_entry
, entry
);
2889 plane
= IORegistryEntry::getPlane( planeName
);
2893 const char * cstr
= entry
->getLocation( plane
);
2896 strncpy( location
, cstr
, sizeof( io_name_t
));
2897 return( kIOReturnSuccess
);
2899 return( kIOReturnNotFound
);
2902 /* Routine io_registry_entry_get_registry_entry_id */
2903 kern_return_t
is_io_registry_entry_get_registry_entry_id(
2904 io_object_t registry_entry
,
2905 uint64_t *entry_id
)
2907 CHECK( IORegistryEntry
, registry_entry
, entry
);
2909 *entry_id
= entry
->getRegistryEntryID();
2911 return (kIOReturnSuccess
);
2914 /* Routine io_registry_entry_get_property */
2915 kern_return_t
is_io_registry_entry_get_property_bytes(
2916 io_object_t registry_entry
,
2917 io_name_t property_name
,
2918 io_struct_inband_t buf
,
2919 mach_msg_type_number_t
*dataCnt
)
2927 unsigned int len
= 0;
2928 const void * bytes
= 0;
2929 IOReturn ret
= kIOReturnSuccess
;
2931 CHECK( IORegistryEntry
, registry_entry
, entry
);
2934 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2935 return kIOReturnNotPermitted
;
2938 obj
= entry
->copyProperty(property_name
);
2940 return( kIOReturnNoResources
);
2942 // One day OSData will be a common container base class
2944 if( (data
= OSDynamicCast( OSData
, obj
))) {
2945 len
= data
->getLength();
2946 bytes
= data
->getBytesNoCopy();
2947 if (!data
->isSerializable()) len
= 0;
2949 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2950 len
= str
->getLength() + 1;
2951 bytes
= str
->getCStringNoCopy();
2953 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2954 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2955 bytes
= boo
->isTrue() ? "Yes" : "No";
2957 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2958 offsetBytes
= off
->unsigned64BitValue();
2959 len
= off
->numberOfBytes();
2960 if (len
> sizeof(offsetBytes
)) len
= sizeof(offsetBytes
);
2961 bytes
= &offsetBytes
;
2962 #ifdef __BIG_ENDIAN__
2963 bytes
= (const void *)
2964 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2968 ret
= kIOReturnBadArgument
;
2972 ret
= kIOReturnIPCError
;
2975 bcopy( bytes
, buf
, len
);
2984 /* Routine io_registry_entry_get_property */
2985 kern_return_t
is_io_registry_entry_get_property(
2986 io_object_t registry_entry
,
2987 io_name_t property_name
,
2988 io_buf_ptr_t
*properties
,
2989 mach_msg_type_number_t
*propertiesCnt
)
2995 CHECK( IORegistryEntry
, registry_entry
, entry
);
2998 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2999 return kIOReturnNotPermitted
;
3002 obj
= entry
->copyProperty(property_name
);
3004 return( kIOReturnNotFound
);
3006 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3009 return( kIOReturnNoMemory
);
3012 if( obj
->serialize( s
)) {
3013 len
= s
->getLength();
3014 *propertiesCnt
= len
;
3015 err
= copyoutkdata( s
->text(), len
, properties
);
3018 err
= kIOReturnUnsupported
;
3026 /* Routine io_registry_entry_get_property_recursively */
3027 kern_return_t
is_io_registry_entry_get_property_recursively(
3028 io_object_t registry_entry
,
3030 io_name_t property_name
,
3032 io_buf_ptr_t
*properties
,
3033 mach_msg_type_number_t
*propertiesCnt
)
3039 CHECK( IORegistryEntry
, registry_entry
, entry
);
3042 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3043 return kIOReturnNotPermitted
;
3046 obj
= entry
->copyProperty( property_name
,
3047 IORegistryEntry::getPlane( plane
), options
);
3049 return( kIOReturnNotFound
);
3051 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3054 return( kIOReturnNoMemory
);
3057 if( obj
->serialize( s
)) {
3058 len
= s
->getLength();
3059 *propertiesCnt
= len
;
3060 err
= copyoutkdata( s
->text(), len
, properties
);
3063 err
= kIOReturnUnsupported
;
3071 /* Routine io_registry_entry_get_properties */
3072 kern_return_t
is_io_registry_entry_get_properties(
3073 io_object_t registry_entry
,
3074 io_buf_ptr_t
*properties
,
3075 mach_msg_type_number_t
*propertiesCnt
)
3077 return (kIOReturnUnsupported
);
3082 struct GetPropertiesEditorRef
3085 IORegistryEntry
* entry
;
3086 OSCollection
* root
;
3089 static const OSMetaClassBase
*
3090 GetPropertiesEditor(void * reference
,
3092 OSCollection
* container
,
3093 const OSSymbol
* name
,
3094 const OSMetaClassBase
* value
)
3096 GetPropertiesEditorRef
* ref
= (typeof(ref
)) reference
;
3098 if (!ref
->root
) ref
->root
= container
;
3099 if (ref
->root
== container
)
3101 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy()))
3106 if (value
) value
->retain();
3110 #endif /* CONFIG_MACF */
3112 /* Routine io_registry_entry_get_properties */
3113 kern_return_t
is_io_registry_entry_get_properties_bin(
3114 io_object_t registry_entry
,
3115 io_buf_ptr_t
*properties
,
3116 mach_msg_type_number_t
*propertiesCnt
)
3118 kern_return_t err
= kIOReturnSuccess
;
3121 OSSerialize::Editor editor
= 0;
3124 CHECK(IORegistryEntry
, registry_entry
, entry
);
3127 GetPropertiesEditorRef ref
;
3128 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
))
3130 editor
= &GetPropertiesEditor
;
3132 ref
.cred
= kauth_cred_get();
3138 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
3139 if (!s
) return (kIOReturnNoMemory
);
3141 if (!entry
->serializeProperties(s
)) err
= kIOReturnUnsupported
;
3143 if (kIOReturnSuccess
== err
)
3145 len
= s
->getLength();
3146 *propertiesCnt
= len
;
3147 err
= copyoutkdata(s
->text(), len
, properties
);
3154 /* Routine io_registry_entry_get_property_bin */
3155 kern_return_t
is_io_registry_entry_get_property_bin(
3156 io_object_t registry_entry
,
3158 io_name_t property_name
,
3160 io_buf_ptr_t
*properties
,
3161 mach_msg_type_number_t
*propertiesCnt
)
3166 const OSSymbol
* sym
;
3168 CHECK( IORegistryEntry
, registry_entry
, entry
);
3171 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3172 return kIOReturnNotPermitted
;
3175 sym
= OSSymbol::withCString(property_name
);
3176 if (!sym
) return (kIOReturnNoMemory
);
3178 if (gIORegistryEntryPropertyKeysKey
== sym
)
3180 obj
= entry
->copyPropertyKeys();
3184 if ((kIORegistryIterateRecursively
& options
) && plane
[0])
3186 obj
= entry
->copyProperty(property_name
,
3187 IORegistryEntry::getPlane(plane
), options
);
3191 obj
= entry
->copyProperty(property_name
);
3193 if (obj
&& gIORemoveOnReadProperties
->containsObject(sym
)) entry
->removeProperty(sym
);
3197 if (!obj
) return (kIOReturnNotFound
);
3199 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
3202 return( kIOReturnNoMemory
);
3205 if( obj
->serialize( s
)) {
3206 len
= s
->getLength();
3207 *propertiesCnt
= len
;
3208 err
= copyoutkdata( s
->text(), len
, properties
);
3210 } else err
= kIOReturnUnsupported
;
3219 /* Routine io_registry_entry_set_properties */
3220 kern_return_t is_io_registry_entry_set_properties
3222 io_object_t registry_entry
,
3223 io_buf_ptr_t properties
,
3224 mach_msg_type_number_t propertiesCnt
,
3225 kern_return_t
* result
)
3231 vm_map_offset_t map_data
;
3233 CHECK( IORegistryEntry
, registry_entry
, entry
);
3235 if( propertiesCnt
> sizeof(io_struct_inband_t
) * 1024)
3236 return( kIOReturnMessageTooLarge
);
3238 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3239 data
= CAST_DOWN(vm_offset_t
, map_data
);
3241 if( KERN_SUCCESS
== err
) {
3243 FAKE_STACK_FRAME(entry
->getMetaClass());
3245 // must return success after vm_map_copyout() succeeds
3246 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3247 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3250 res
= kIOReturnBadArgument
;
3252 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
3253 registry_entry
, obj
))
3255 res
= kIOReturnNotPermitted
;
3260 res
= entry
->setProperties( obj
);
3266 FAKE_STACK_FRAME_END();
3275 /* Routine io_registry_entry_get_child_iterator */
3276 kern_return_t
is_io_registry_entry_get_child_iterator(
3277 io_object_t registry_entry
,
3279 io_object_t
*iterator
)
3281 CHECK( IORegistryEntry
, registry_entry
, entry
);
3283 *iterator
= entry
->getChildIterator(
3284 IORegistryEntry::getPlane( plane
));
3286 return( kIOReturnSuccess
);
3289 /* Routine io_registry_entry_get_parent_iterator */
3290 kern_return_t
is_io_registry_entry_get_parent_iterator(
3291 io_object_t registry_entry
,
3293 io_object_t
*iterator
)
3295 CHECK( IORegistryEntry
, registry_entry
, entry
);
3297 *iterator
= entry
->getParentIterator(
3298 IORegistryEntry::getPlane( plane
));
3300 return( kIOReturnSuccess
);
3303 /* Routine io_service_get_busy_state */
3304 kern_return_t
is_io_service_get_busy_state(
3305 io_object_t _service
,
3306 uint32_t *busyState
)
3308 CHECK( IOService
, _service
, service
);
3310 *busyState
= service
->getBusyState();
3312 return( kIOReturnSuccess
);
3315 /* Routine io_service_get_state */
3316 kern_return_t
is_io_service_get_state(
3317 io_object_t _service
,
3319 uint32_t *busy_state
,
3320 uint64_t *accumulated_busy_time
)
3322 CHECK( IOService
, _service
, service
);
3324 *state
= service
->getState();
3325 *busy_state
= service
->getBusyState();
3326 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
3328 return( kIOReturnSuccess
);
3331 /* Routine io_service_wait_quiet */
3332 kern_return_t
is_io_service_wait_quiet(
3333 io_object_t _service
,
3334 mach_timespec_t wait_time
)
3338 CHECK( IOService
, _service
, service
);
3340 timeoutNS
= wait_time
.tv_sec
;
3341 timeoutNS
*= kSecondScale
;
3342 timeoutNS
+= wait_time
.tv_nsec
;
3344 return( service
->waitQuiet(timeoutNS
) );
3347 /* Routine io_service_request_probe */
3348 kern_return_t
is_io_service_request_probe(
3349 io_object_t _service
,
3352 CHECK( IOService
, _service
, service
);
3354 return( service
->requestProbe( options
));
3357 /* Routine io_service_get_authorization_id */
3358 kern_return_t
is_io_service_get_authorization_id(
3359 io_object_t _service
,
3360 uint64_t *authorization_id
)
3364 CHECK( IOService
, _service
, service
);
3366 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3367 kIOClientPrivilegeAdministrator
);
3368 if( kIOReturnSuccess
!= kr
)
3371 *authorization_id
= service
->getAuthorizationID();
3376 /* Routine io_service_set_authorization_id */
3377 kern_return_t
is_io_service_set_authorization_id(
3378 io_object_t _service
,
3379 uint64_t authorization_id
)
3381 CHECK( IOService
, _service
, service
);
3383 return( service
->setAuthorizationID( authorization_id
) );
3386 /* Routine io_service_open_ndr */
3387 kern_return_t
is_io_service_open_extended(
3388 io_object_t _service
,
3390 uint32_t connect_type
,
3392 io_buf_ptr_t properties
,
3393 mach_msg_type_number_t propertiesCnt
,
3394 kern_return_t
* result
,
3395 io_object_t
*connection
)
3397 IOUserClient
* client
= 0;
3398 kern_return_t err
= KERN_SUCCESS
;
3399 IOReturn res
= kIOReturnSuccess
;
3400 OSDictionary
* propertiesDict
= 0;
3402 bool disallowAccess
;
3404 CHECK( IOService
, _service
, service
);
3406 if (!owningTask
) return (kIOReturnBadArgument
);
3407 assert(owningTask
== current_task());
3408 if (owningTask
!= current_task()) return (kIOReturnBadArgument
);
3412 if (properties
) return (kIOReturnUnsupported
);
3417 vm_map_offset_t map_data
;
3419 if( propertiesCnt
> sizeof(io_struct_inband_t
))
3420 return( kIOReturnMessageTooLarge
);
3422 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3424 data
= CAST_DOWN(vm_offset_t
, map_data
);
3425 if (KERN_SUCCESS
== err
)
3427 // must return success after vm_map_copyout() succeeds
3428 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3429 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3430 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3431 if (!propertiesDict
)
3433 res
= kIOReturnBadArgument
;
3438 if (kIOReturnSuccess
!= res
)
3442 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3445 if (!propertiesDict
)
3446 propertiesDict
= OSDictionary::withCapacity(4);
3447 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3451 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
3456 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
3457 connect_type
, propertiesDict
, &client
);
3460 propertiesDict
->release();
3462 if (res
== kIOReturnSuccess
)
3464 assert( OSDynamicCast(IOUserClient
, client
) );
3466 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
3467 client
->closed
= false;
3469 disallowAccess
= (crossEndian
3470 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
3471 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
3472 if (disallowAccess
) res
= kIOReturnUnsupported
;
3474 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
))
3475 res
= kIOReturnNotPermitted
;
3478 if (kIOReturnSuccess
== res
) res
= client
->registerOwner(owningTask
);
3480 if (kIOReturnSuccess
!= res
)
3482 IOStatisticsClientCall();
3483 client
->clientClose();
3488 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
3491 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
3492 creatorName
->release();
3494 client
->setTerminateDefer(service
, false);
3499 *connection
= client
;
3505 /* Routine io_service_close */
3506 kern_return_t
is_io_service_close(
3507 io_object_t connection
)
3510 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
3511 return( kIOReturnSuccess
);
3513 CHECK( IOUserClient
, connection
, client
);
3515 IOStatisticsClientCall();
3517 if (client
->sharedInstance
|| OSCompareAndSwap8(0, 1, &client
->closed
))
3519 client
->clientClose();
3523 IOLog("ignored is_io_service_close(0x%qx,%s)\n",
3524 client
->getRegistryEntryID(), client
->getName());
3527 return( kIOReturnSuccess
);
3530 /* Routine io_connect_get_service */
3531 kern_return_t
is_io_connect_get_service(
3532 io_object_t connection
,
3533 io_object_t
*service
)
3535 IOService
* theService
;
3537 CHECK( IOUserClient
, connection
, client
);
3539 theService
= client
->getService();
3541 theService
->retain();
3543 *service
= theService
;
3545 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
3548 /* Routine io_connect_set_notification_port */
3549 kern_return_t
is_io_connect_set_notification_port(
3550 io_object_t connection
,
3551 uint32_t notification_type
,
3555 CHECK( IOUserClient
, connection
, client
);
3557 IOStatisticsClientCall();
3558 return( client
->registerNotificationPort( port
, notification_type
,
3559 (io_user_reference_t
) reference
));
3562 /* Routine io_connect_set_notification_port */
3563 kern_return_t
is_io_connect_set_notification_port_64(
3564 io_object_t connection
,
3565 uint32_t notification_type
,
3567 io_user_reference_t reference
)
3569 CHECK( IOUserClient
, connection
, client
);
3571 IOStatisticsClientCall();
3572 return( client
->registerNotificationPort( port
, notification_type
,
3576 /* Routine io_connect_map_memory_into_task */
3577 kern_return_t is_io_connect_map_memory_into_task
3579 io_connect_t connection
,
3580 uint32_t memory_type
,
3582 mach_vm_address_t
*address
,
3583 mach_vm_size_t
*size
,
3590 CHECK( IOUserClient
, connection
, client
);
3592 if (!into_task
) return (kIOReturnBadArgument
);
3594 IOStatisticsClientCall();
3595 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
3598 *address
= map
->getAddress();
3600 *size
= map
->getSize();
3602 if( client
->sharedInstance
3603 || (into_task
!= current_task())) {
3604 // push a name out to the task owning the map,
3605 // so we can clean up maps
3606 mach_port_name_t name __unused
=
3607 IOMachPort::makeSendRightForTask(
3608 into_task
, map
, IKOT_IOKIT_OBJECT
);
3611 // keep it with the user client
3612 IOLockLock( gIOObjectPortLock
);
3613 if( 0 == client
->mappings
)
3614 client
->mappings
= OSSet::withCapacity(2);
3615 if( client
->mappings
)
3616 client
->mappings
->setObject( map
);
3617 IOLockUnlock( gIOObjectPortLock
);
3620 err
= kIOReturnSuccess
;
3623 err
= kIOReturnBadArgument
;
3628 /* Routine is_io_connect_map_memory */
3629 kern_return_t
is_io_connect_map_memory(
3630 io_object_t connect
,
3638 mach_vm_address_t address
;
3639 mach_vm_size_t size
;
3641 address
= SCALAR64(*mapAddr
);
3642 size
= SCALAR64(*mapSize
);
3644 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
3646 *mapAddr
= SCALAR32(address
);
3647 *mapSize
= SCALAR32(size
);
3654 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
3657 IOMemoryMap
* map
= 0;
3659 IOLockLock(gIOObjectPortLock
);
3661 iter
= OSCollectionIterator::withCollection(mappings
);
3664 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
3666 if(mem
== map
->getMemoryDescriptor())
3669 mappings
->removeObject(map
);
3676 IOLockUnlock(gIOObjectPortLock
);
3683 /* Routine io_connect_unmap_memory_from_task */
3684 kern_return_t is_io_connect_unmap_memory_from_task
3686 io_connect_t connection
,
3687 uint32_t memory_type
,
3689 mach_vm_address_t address
)
3692 IOOptionBits options
= 0;
3693 IOMemoryDescriptor
* memory
= 0;
3696 CHECK( IOUserClient
, connection
, client
);
3698 if (!from_task
) return (kIOReturnBadArgument
);
3700 IOStatisticsClientCall();
3701 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
3703 if( memory
&& (kIOReturnSuccess
== err
)) {
3705 options
= (options
& ~kIOMapUserOptionsMask
)
3706 | kIOMapAnywhere
| kIOMapReference
;
3708 map
= memory
->createMappingInTask( from_task
, address
, options
);
3712 IOLockLock( gIOObjectPortLock
);
3713 if( client
->mappings
)
3714 client
->mappings
->removeObject( map
);
3715 IOLockUnlock( gIOObjectPortLock
);
3717 mach_port_name_t name
= 0;
3718 if (from_task
!= current_task())
3719 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
3722 map
->userClientUnmap();
3723 err
= iokit_mod_send_right( from_task
, name
, -2 );
3724 err
= kIOReturnSuccess
;
3727 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
3728 if (from_task
== current_task())
3732 err
= kIOReturnBadArgument
;
3738 kern_return_t
is_io_connect_unmap_memory(
3739 io_object_t connect
,
3745 mach_vm_address_t address
;
3747 address
= SCALAR64(mapAddr
);
3749 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
3755 /* Routine io_connect_add_client */
3756 kern_return_t
is_io_connect_add_client(
3757 io_object_t connection
,
3758 io_object_t connect_to
)
3760 CHECK( IOUserClient
, connection
, client
);
3761 CHECK( IOUserClient
, connect_to
, to
);
3763 IOStatisticsClientCall();
3764 return( client
->connectClient( to
) );
3768 /* Routine io_connect_set_properties */
3769 kern_return_t
is_io_connect_set_properties(
3770 io_object_t connection
,
3771 io_buf_ptr_t properties
,
3772 mach_msg_type_number_t propertiesCnt
,
3773 kern_return_t
* result
)
3775 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
3778 /* Routine io_user_client_method */
3779 kern_return_t is_io_connect_method_var_output
3781 io_connect_t connection
,
3783 io_scalar_inband64_t scalar_input
,
3784 mach_msg_type_number_t scalar_inputCnt
,
3785 io_struct_inband_t inband_input
,
3786 mach_msg_type_number_t inband_inputCnt
,
3787 mach_vm_address_t ool_input
,
3788 mach_vm_size_t ool_input_size
,
3789 io_struct_inband_t inband_output
,
3790 mach_msg_type_number_t
*inband_outputCnt
,
3791 io_scalar_inband64_t scalar_output
,
3792 mach_msg_type_number_t
*scalar_outputCnt
,
3793 io_buf_ptr_t
*var_output
,
3794 mach_msg_type_number_t
*var_outputCnt
3797 CHECK( IOUserClient
, connection
, client
);
3799 IOExternalMethodArguments args
;
3801 IOMemoryDescriptor
* inputMD
= 0;
3802 OSObject
* structureVariableOutputData
= 0;
3804 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3805 args
.__reservedA
= 0;
3806 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3808 args
.selector
= selector
;
3810 args
.asyncWakePort
= MACH_PORT_NULL
;
3811 args
.asyncReference
= 0;
3812 args
.asyncReferenceCount
= 0;
3813 args
.structureVariableOutputData
= &structureVariableOutputData
;
3815 args
.scalarInput
= scalar_input
;
3816 args
.scalarInputCount
= scalar_inputCnt
;
3817 args
.structureInput
= inband_input
;
3818 args
.structureInputSize
= inband_inputCnt
;
3820 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
3823 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3824 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
3827 args
.structureInputDescriptor
= inputMD
;
3829 args
.scalarOutput
= scalar_output
;
3830 args
.scalarOutputCount
= *scalar_outputCnt
;
3831 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3832 args
.structureOutput
= inband_output
;
3833 args
.structureOutputSize
= *inband_outputCnt
;
3834 args
.structureOutputDescriptor
= NULL
;
3835 args
.structureOutputDescriptorSize
= 0;
3837 IOStatisticsClientCall();
3838 ret
= client
->externalMethod( selector
, &args
);
3840 *scalar_outputCnt
= args
.scalarOutputCount
;
3841 *inband_outputCnt
= args
.structureOutputSize
;
3843 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
))
3845 OSSerialize
* serialize
;
3849 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
)))
3851 len
= serialize
->getLength();
3852 *var_outputCnt
= len
;
3853 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
3855 else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
)))
3857 len
= data
->getLength();
3858 *var_outputCnt
= len
;
3859 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
3863 ret
= kIOReturnUnderrun
;
3869 if (structureVariableOutputData
)
3870 structureVariableOutputData
->release();
3875 /* Routine io_user_client_method */
3876 kern_return_t is_io_connect_method
3878 io_connect_t connection
,
3880 io_scalar_inband64_t scalar_input
,
3881 mach_msg_type_number_t scalar_inputCnt
,
3882 io_struct_inband_t inband_input
,
3883 mach_msg_type_number_t inband_inputCnt
,
3884 mach_vm_address_t ool_input
,
3885 mach_vm_size_t ool_input_size
,
3886 io_struct_inband_t inband_output
,
3887 mach_msg_type_number_t
*inband_outputCnt
,
3888 io_scalar_inband64_t scalar_output
,
3889 mach_msg_type_number_t
*scalar_outputCnt
,
3890 mach_vm_address_t ool_output
,
3891 mach_vm_size_t
*ool_output_size
3894 CHECK( IOUserClient
, connection
, client
);
3896 IOExternalMethodArguments args
;
3898 IOMemoryDescriptor
* inputMD
= 0;
3899 IOMemoryDescriptor
* outputMD
= 0;
3901 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3902 args
.__reservedA
= 0;
3903 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3905 args
.selector
= selector
;
3907 args
.asyncWakePort
= MACH_PORT_NULL
;
3908 args
.asyncReference
= 0;
3909 args
.asyncReferenceCount
= 0;
3910 args
.structureVariableOutputData
= 0;
3912 args
.scalarInput
= scalar_input
;
3913 args
.scalarInputCount
= scalar_inputCnt
;
3914 args
.structureInput
= inband_input
;
3915 args
.structureInputSize
= inband_inputCnt
;
3917 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
3918 if (ool_output
&& (*ool_output_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
3921 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3922 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
3925 args
.structureInputDescriptor
= inputMD
;
3927 args
.scalarOutput
= scalar_output
;
3928 args
.scalarOutputCount
= *scalar_outputCnt
;
3929 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3930 args
.structureOutput
= inband_output
;
3931 args
.structureOutputSize
= *inband_outputCnt
;
3933 if (ool_output
&& ool_output_size
)
3935 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3936 kIODirectionIn
, current_task());
3939 args
.structureOutputDescriptor
= outputMD
;
3940 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
3942 IOStatisticsClientCall();
3943 ret
= client
->externalMethod( selector
, &args
);
3945 *scalar_outputCnt
= args
.scalarOutputCount
;
3946 *inband_outputCnt
= args
.structureOutputSize
;
3947 *ool_output_size
= args
.structureOutputDescriptorSize
;
3952 outputMD
->release();
3957 /* Routine io_async_user_client_method */
3958 kern_return_t is_io_connect_async_method
3960 io_connect_t connection
,
3961 mach_port_t wake_port
,
3962 io_async_ref64_t reference
,
3963 mach_msg_type_number_t referenceCnt
,
3965 io_scalar_inband64_t scalar_input
,
3966 mach_msg_type_number_t scalar_inputCnt
,
3967 io_struct_inband_t inband_input
,
3968 mach_msg_type_number_t inband_inputCnt
,
3969 mach_vm_address_t ool_input
,
3970 mach_vm_size_t ool_input_size
,
3971 io_struct_inband_t inband_output
,
3972 mach_msg_type_number_t
*inband_outputCnt
,
3973 io_scalar_inband64_t scalar_output
,
3974 mach_msg_type_number_t
*scalar_outputCnt
,
3975 mach_vm_address_t ool_output
,
3976 mach_vm_size_t
* ool_output_size
3979 CHECK( IOUserClient
, connection
, client
);
3981 IOExternalMethodArguments args
;
3983 IOMemoryDescriptor
* inputMD
= 0;
3984 IOMemoryDescriptor
* outputMD
= 0;
3986 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3987 args
.__reservedA
= 0;
3988 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3990 reference
[0] = (io_user_reference_t
) wake_port
;
3991 if (vm_map_is_64bit(get_task_map(current_task())))
3992 reference
[0] |= kIOUCAsync64Flag
;
3994 args
.selector
= selector
;
3996 args
.asyncWakePort
= wake_port
;
3997 args
.asyncReference
= reference
;
3998 args
.asyncReferenceCount
= referenceCnt
;
4000 args
.structureVariableOutputData
= 0;
4002 args
.scalarInput
= scalar_input
;
4003 args
.scalarInputCount
= scalar_inputCnt
;
4004 args
.structureInput
= inband_input
;
4005 args
.structureInputSize
= inband_inputCnt
;
4007 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
4008 if (ool_output
&& (*ool_output_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
4011 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4012 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4015 args
.structureInputDescriptor
= inputMD
;
4017 args
.scalarOutput
= scalar_output
;
4018 args
.scalarOutputCount
= *scalar_outputCnt
;
4019 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4020 args
.structureOutput
= inband_output
;
4021 args
.structureOutputSize
= *inband_outputCnt
;
4025 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
4026 kIODirectionIn
, current_task());
4029 args
.structureOutputDescriptor
= outputMD
;
4030 args
.structureOutputDescriptorSize
= *ool_output_size
;
4032 IOStatisticsClientCall();
4033 ret
= client
->externalMethod( selector
, &args
);
4035 *inband_outputCnt
= args
.structureOutputSize
;
4036 *ool_output_size
= args
.structureOutputDescriptorSize
;
4041 outputMD
->release();
4046 /* Routine io_connect_method_scalarI_scalarO */
4047 kern_return_t
is_io_connect_method_scalarI_scalarO(
4048 io_object_t connect
,
4050 io_scalar_inband_t input
,
4051 mach_msg_type_number_t inputCount
,
4052 io_scalar_inband_t output
,
4053 mach_msg_type_number_t
* outputCount
)
4057 io_scalar_inband64_t _input
;
4058 io_scalar_inband64_t _output
;
4060 mach_msg_type_number_t struct_outputCnt
= 0;
4061 mach_vm_size_t ool_output_size
= 0;
4063 bzero(&_output
[0], sizeof(_output
));
4064 for (i
= 0; i
< inputCount
; i
++)
4065 _input
[i
] = SCALAR64(input
[i
]);
4067 err
= is_io_connect_method(connect
, index
,
4071 NULL
, &struct_outputCnt
,
4072 _output
, outputCount
,
4073 0, &ool_output_size
);
4075 for (i
= 0; i
< *outputCount
; i
++)
4076 output
[i
] = SCALAR32(_output
[i
]);
4081 kern_return_t
shim_io_connect_method_scalarI_scalarO(
4082 IOExternalMethod
* method
,
4084 const io_user_scalar_t
* input
,
4085 mach_msg_type_number_t inputCount
,
4086 io_user_scalar_t
* output
,
4087 mach_msg_type_number_t
* outputCount
)
4090 io_scalar_inband_t _output
;
4092 err
= kIOReturnBadArgument
;
4094 bzero(&_output
[0], sizeof(_output
));
4097 if( inputCount
!= method
->count0
)
4099 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4100 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4103 if( *outputCount
!= method
->count1
)
4105 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4106 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4110 func
= method
->func
;
4112 switch( inputCount
) {
4115 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4116 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4119 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4120 ARG32(input
[3]), ARG32(input
[4]),
4124 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4126 &_output
[0], &_output
[1] );
4129 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4130 &_output
[0], &_output
[1], &_output
[2] );
4133 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4134 &_output
[0], &_output
[1], &_output
[2],
4138 err
= (object
->*func
)( ARG32(input
[0]),
4139 &_output
[0], &_output
[1], &_output
[2],
4140 &_output
[3], &_output
[4] );
4143 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
4144 &_output
[3], &_output
[4], &_output
[5] );
4148 IOLog("%s: Bad method table\n", object
->getName());
4154 for (i
= 0; i
< *outputCount
; i
++)
4155 output
[i
] = SCALAR32(_output
[i
]);
4160 /* Routine io_async_method_scalarI_scalarO */
4161 kern_return_t
is_io_async_method_scalarI_scalarO(
4162 io_object_t connect
,
4163 mach_port_t wake_port
,
4164 io_async_ref_t reference
,
4165 mach_msg_type_number_t referenceCnt
,
4167 io_scalar_inband_t input
,
4168 mach_msg_type_number_t inputCount
,
4169 io_scalar_inband_t output
,
4170 mach_msg_type_number_t
* outputCount
)
4174 io_scalar_inband64_t _input
;
4175 io_scalar_inband64_t _output
;
4176 io_async_ref64_t _reference
;
4178 bzero(&_output
[0], sizeof(_output
));
4179 for (i
= 0; i
< referenceCnt
; i
++)
4180 _reference
[i
] = REF64(reference
[i
]);
4182 mach_msg_type_number_t struct_outputCnt
= 0;
4183 mach_vm_size_t ool_output_size
= 0;
4185 for (i
= 0; i
< inputCount
; i
++)
4186 _input
[i
] = SCALAR64(input
[i
]);
4188 err
= is_io_connect_async_method(connect
,
4189 wake_port
, _reference
, referenceCnt
,
4194 NULL
, &struct_outputCnt
,
4195 _output
, outputCount
,
4196 0, &ool_output_size
);
4198 for (i
= 0; i
< *outputCount
; i
++)
4199 output
[i
] = SCALAR32(_output
[i
]);
4203 /* Routine io_async_method_scalarI_structureO */
4204 kern_return_t
is_io_async_method_scalarI_structureO(
4205 io_object_t connect
,
4206 mach_port_t wake_port
,
4207 io_async_ref_t reference
,
4208 mach_msg_type_number_t referenceCnt
,
4210 io_scalar_inband_t input
,
4211 mach_msg_type_number_t inputCount
,
4212 io_struct_inband_t output
,
4213 mach_msg_type_number_t
* outputCount
)
4216 io_scalar_inband64_t _input
;
4217 io_async_ref64_t _reference
;
4219 for (i
= 0; i
< referenceCnt
; i
++)
4220 _reference
[i
] = REF64(reference
[i
]);
4222 mach_msg_type_number_t scalar_outputCnt
= 0;
4223 mach_vm_size_t ool_output_size
= 0;
4225 for (i
= 0; i
< inputCount
; i
++)
4226 _input
[i
] = SCALAR64(input
[i
]);
4228 return (is_io_connect_async_method(connect
,
4229 wake_port
, _reference
, referenceCnt
,
4234 output
, outputCount
,
4235 NULL
, &scalar_outputCnt
,
4236 0, &ool_output_size
));
4239 /* Routine io_async_method_scalarI_structureI */
4240 kern_return_t
is_io_async_method_scalarI_structureI(
4241 io_connect_t connect
,
4242 mach_port_t wake_port
,
4243 io_async_ref_t reference
,
4244 mach_msg_type_number_t referenceCnt
,
4246 io_scalar_inband_t input
,
4247 mach_msg_type_number_t inputCount
,
4248 io_struct_inband_t inputStruct
,
4249 mach_msg_type_number_t inputStructCount
)
4252 io_scalar_inband64_t _input
;
4253 io_async_ref64_t _reference
;
4255 for (i
= 0; i
< referenceCnt
; i
++)
4256 _reference
[i
] = REF64(reference
[i
]);
4258 mach_msg_type_number_t scalar_outputCnt
= 0;
4259 mach_msg_type_number_t inband_outputCnt
= 0;
4260 mach_vm_size_t ool_output_size
= 0;
4262 for (i
= 0; i
< inputCount
; i
++)
4263 _input
[i
] = SCALAR64(input
[i
]);
4265 return (is_io_connect_async_method(connect
,
4266 wake_port
, _reference
, referenceCnt
,
4269 inputStruct
, inputStructCount
,
4271 NULL
, &inband_outputCnt
,
4272 NULL
, &scalar_outputCnt
,
4273 0, &ool_output_size
));
4276 /* Routine io_async_method_structureI_structureO */
4277 kern_return_t
is_io_async_method_structureI_structureO(
4278 io_object_t connect
,
4279 mach_port_t wake_port
,
4280 io_async_ref_t reference
,
4281 mach_msg_type_number_t referenceCnt
,
4283 io_struct_inband_t input
,
4284 mach_msg_type_number_t inputCount
,
4285 io_struct_inband_t output
,
4286 mach_msg_type_number_t
* outputCount
)
4289 mach_msg_type_number_t scalar_outputCnt
= 0;
4290 mach_vm_size_t ool_output_size
= 0;
4291 io_async_ref64_t _reference
;
4293 for (i
= 0; i
< referenceCnt
; i
++)
4294 _reference
[i
] = REF64(reference
[i
]);
4296 return (is_io_connect_async_method(connect
,
4297 wake_port
, _reference
, referenceCnt
,
4302 output
, outputCount
,
4303 NULL
, &scalar_outputCnt
,
4304 0, &ool_output_size
));
4308 kern_return_t
shim_io_async_method_scalarI_scalarO(
4309 IOExternalAsyncMethod
* method
,
4311 mach_port_t asyncWakePort
,
4312 io_user_reference_t
* asyncReference
,
4313 uint32_t asyncReferenceCount
,
4314 const io_user_scalar_t
* input
,
4315 mach_msg_type_number_t inputCount
,
4316 io_user_scalar_t
* output
,
4317 mach_msg_type_number_t
* outputCount
)
4321 io_scalar_inband_t _output
;
4323 io_async_ref_t reference
;
4325 bzero(&_output
[0], sizeof(_output
));
4326 for (i
= 0; i
< asyncReferenceCount
; i
++)
4327 reference
[i
] = REF32(asyncReference
[i
]);
4329 err
= kIOReturnBadArgument
;
4333 if( inputCount
!= method
->count0
)
4335 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4336 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4339 if( *outputCount
!= method
->count1
)
4341 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4342 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4346 func
= method
->func
;
4348 switch( inputCount
) {
4351 err
= (object
->*func
)( reference
,
4352 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4353 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4356 err
= (object
->*func
)( reference
,
4357 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4358 ARG32(input
[3]), ARG32(input
[4]),
4362 err
= (object
->*func
)( reference
,
4363 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4365 &_output
[0], &_output
[1] );
4368 err
= (object
->*func
)( reference
,
4369 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4370 &_output
[0], &_output
[1], &_output
[2] );
4373 err
= (object
->*func
)( reference
,
4374 ARG32(input
[0]), ARG32(input
[1]),
4375 &_output
[0], &_output
[1], &_output
[2],
4379 err
= (object
->*func
)( reference
,
4381 &_output
[0], &_output
[1], &_output
[2],
4382 &_output
[3], &_output
[4] );
4385 err
= (object
->*func
)( reference
,
4386 &_output
[0], &_output
[1], &_output
[2],
4387 &_output
[3], &_output
[4], &_output
[5] );
4391 IOLog("%s: Bad method table\n", object
->getName());
4396 for (i
= 0; i
< *outputCount
; i
++)
4397 output
[i
] = SCALAR32(_output
[i
]);
4403 /* Routine io_connect_method_scalarI_structureO */
4404 kern_return_t
is_io_connect_method_scalarI_structureO(
4405 io_object_t connect
,
4407 io_scalar_inband_t input
,
4408 mach_msg_type_number_t inputCount
,
4409 io_struct_inband_t output
,
4410 mach_msg_type_number_t
* outputCount
)
4413 io_scalar_inband64_t _input
;
4415 mach_msg_type_number_t scalar_outputCnt
= 0;
4416 mach_vm_size_t ool_output_size
= 0;
4418 for (i
= 0; i
< inputCount
; i
++)
4419 _input
[i
] = SCALAR64(input
[i
]);
4421 return (is_io_connect_method(connect
, index
,
4425 output
, outputCount
,
4426 NULL
, &scalar_outputCnt
,
4427 0, &ool_output_size
));
4430 kern_return_t
shim_io_connect_method_scalarI_structureO(
4432 IOExternalMethod
* method
,
4434 const io_user_scalar_t
* input
,
4435 mach_msg_type_number_t inputCount
,
4436 io_struct_inband_t output
,
4437 IOByteCount
* outputCount
)
4442 err
= kIOReturnBadArgument
;
4445 if( inputCount
!= method
->count0
)
4447 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4448 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4451 if( (kIOUCVariableStructureSize
!= method
->count1
)
4452 && (*outputCount
!= method
->count1
))
4454 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4455 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4459 func
= method
->func
;
4461 switch( inputCount
) {
4464 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4465 ARG32(input
[3]), ARG32(input
[4]),
4469 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4471 output
, (void *)outputCount
);
4474 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4475 output
, (void *)outputCount
, 0 );
4478 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4479 output
, (void *)outputCount
, 0, 0 );
4482 err
= (object
->*func
)( ARG32(input
[0]),
4483 output
, (void *)outputCount
, 0, 0, 0 );
4486 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
4490 IOLog("%s: Bad method table\n", object
->getName());
4499 kern_return_t
shim_io_async_method_scalarI_structureO(
4500 IOExternalAsyncMethod
* method
,
4502 mach_port_t asyncWakePort
,
4503 io_user_reference_t
* asyncReference
,
4504 uint32_t asyncReferenceCount
,
4505 const io_user_scalar_t
* input
,
4506 mach_msg_type_number_t inputCount
,
4507 io_struct_inband_t output
,
4508 mach_msg_type_number_t
* outputCount
)
4513 io_async_ref_t reference
;
4515 for (i
= 0; i
< asyncReferenceCount
; i
++)
4516 reference
[i
] = REF32(asyncReference
[i
]);
4518 err
= kIOReturnBadArgument
;
4520 if( inputCount
!= method
->count0
)
4522 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4523 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4526 if( (kIOUCVariableStructureSize
!= method
->count1
)
4527 && (*outputCount
!= method
->count1
))
4529 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4530 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4534 func
= method
->func
;
4536 switch( inputCount
) {
4539 err
= (object
->*func
)( reference
,
4540 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4541 ARG32(input
[3]), ARG32(input
[4]),
4545 err
= (object
->*func
)( reference
,
4546 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4548 output
, (void *)outputCount
);
4551 err
= (object
->*func
)( reference
,
4552 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4553 output
, (void *)outputCount
, 0 );
4556 err
= (object
->*func
)( reference
,
4557 ARG32(input
[0]), ARG32(input
[1]),
4558 output
, (void *)outputCount
, 0, 0 );
4561 err
= (object
->*func
)( reference
,
4563 output
, (void *)outputCount
, 0, 0, 0 );
4566 err
= (object
->*func
)( reference
,
4567 output
, (void *)outputCount
, 0, 0, 0, 0 );
4571 IOLog("%s: Bad method table\n", object
->getName());
4579 /* Routine io_connect_method_scalarI_structureI */
4580 kern_return_t
is_io_connect_method_scalarI_structureI(
4581 io_connect_t connect
,
4583 io_scalar_inband_t input
,
4584 mach_msg_type_number_t inputCount
,
4585 io_struct_inband_t inputStruct
,
4586 mach_msg_type_number_t inputStructCount
)
4589 io_scalar_inband64_t _input
;
4591 mach_msg_type_number_t scalar_outputCnt
= 0;
4592 mach_msg_type_number_t inband_outputCnt
= 0;
4593 mach_vm_size_t ool_output_size
= 0;
4595 for (i
= 0; i
< inputCount
; i
++)
4596 _input
[i
] = SCALAR64(input
[i
]);
4598 return (is_io_connect_method(connect
, index
,
4600 inputStruct
, inputStructCount
,
4602 NULL
, &inband_outputCnt
,
4603 NULL
, &scalar_outputCnt
,
4604 0, &ool_output_size
));
4607 kern_return_t
shim_io_connect_method_scalarI_structureI(
4608 IOExternalMethod
* method
,
4610 const io_user_scalar_t
* input
,
4611 mach_msg_type_number_t inputCount
,
4612 io_struct_inband_t inputStruct
,
4613 mach_msg_type_number_t inputStructCount
)
4616 IOReturn err
= kIOReturnBadArgument
;
4620 if (inputCount
!= method
->count0
)
4622 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4623 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4626 if( (kIOUCVariableStructureSize
!= method
->count1
)
4627 && (inputStructCount
!= method
->count1
))
4629 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputStructCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4630 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
4634 func
= method
->func
;
4636 switch( inputCount
) {
4639 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4640 ARG32(input
[3]), ARG32(input
[4]),
4644 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
4646 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4649 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4650 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4654 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4655 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4659 err
= (object
->*func
)( ARG32(input
[0]),
4660 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4664 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
4669 IOLog("%s: Bad method table\n", object
->getName());
4677 kern_return_t
shim_io_async_method_scalarI_structureI(
4678 IOExternalAsyncMethod
* method
,
4680 mach_port_t asyncWakePort
,
4681 io_user_reference_t
* asyncReference
,
4682 uint32_t asyncReferenceCount
,
4683 const io_user_scalar_t
* input
,
4684 mach_msg_type_number_t inputCount
,
4685 io_struct_inband_t inputStruct
,
4686 mach_msg_type_number_t inputStructCount
)
4690 IOReturn err
= kIOReturnBadArgument
;
4691 io_async_ref_t reference
;
4693 for (i
= 0; i
< asyncReferenceCount
; i
++)
4694 reference
[i
] = REF32(asyncReference
[i
]);
4698 if (inputCount
!= method
->count0
)
4700 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4701 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4704 if( (kIOUCVariableStructureSize
!= method
->count1
)
4705 && (inputStructCount
!= method
->count1
))
4707 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputStructCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4708 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
4712 func
= method
->func
;
4714 switch( inputCount
) {
4717 err
= (object
->*func
)( reference
,
4718 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4719 ARG32(input
[3]), ARG32(input
[4]),
4723 err
= (object
->*func
)( reference
,
4724 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4726 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4729 err
= (object
->*func
)( reference
,
4730 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4731 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4735 err
= (object
->*func
)( reference
,
4736 ARG32(input
[0]), ARG32(input
[1]),
4737 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4741 err
= (object
->*func
)( reference
,
4743 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4747 err
= (object
->*func
)( reference
,
4748 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4753 IOLog("%s: Bad method table\n", object
->getName());
4761 /* Routine io_connect_method_structureI_structureO */
4762 kern_return_t
is_io_connect_method_structureI_structureO(
4763 io_object_t connect
,
4765 io_struct_inband_t input
,
4766 mach_msg_type_number_t inputCount
,
4767 io_struct_inband_t output
,
4768 mach_msg_type_number_t
* outputCount
)
4770 mach_msg_type_number_t scalar_outputCnt
= 0;
4771 mach_vm_size_t ool_output_size
= 0;
4773 return (is_io_connect_method(connect
, index
,
4777 output
, outputCount
,
4778 NULL
, &scalar_outputCnt
,
4779 0, &ool_output_size
));
4782 kern_return_t
shim_io_connect_method_structureI_structureO(
4783 IOExternalMethod
* method
,
4785 io_struct_inband_t input
,
4786 mach_msg_type_number_t inputCount
,
4787 io_struct_inband_t output
,
4788 IOByteCount
* outputCount
)
4791 IOReturn err
= kIOReturnBadArgument
;
4795 if( (kIOUCVariableStructureSize
!= method
->count0
)
4796 && (inputCount
!= method
->count0
))
4798 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
, (uint64_t)kIOUCVariableStructureSize
);
4799 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4802 if( (kIOUCVariableStructureSize
!= method
->count1
)
4803 && (*outputCount
!= method
->count1
))
4805 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4806 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4810 func
= method
->func
;
4812 if( method
->count1
) {
4813 if( method
->count0
) {
4814 err
= (object
->*func
)( input
, output
,
4815 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4817 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
4820 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4829 kern_return_t
shim_io_async_method_structureI_structureO(
4830 IOExternalAsyncMethod
* method
,
4832 mach_port_t asyncWakePort
,
4833 io_user_reference_t
* asyncReference
,
4834 uint32_t asyncReferenceCount
,
4835 io_struct_inband_t input
,
4836 mach_msg_type_number_t inputCount
,
4837 io_struct_inband_t output
,
4838 mach_msg_type_number_t
* outputCount
)
4843 io_async_ref_t reference
;
4845 for (i
= 0; i
< asyncReferenceCount
; i
++)
4846 reference
[i
] = REF32(asyncReference
[i
]);
4848 err
= kIOReturnBadArgument
;
4851 if( (kIOUCVariableStructureSize
!= method
->count0
)
4852 && (inputCount
!= method
->count0
))
4854 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
, (uint64_t)kIOUCVariableStructureSize
);
4855 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4858 if( (kIOUCVariableStructureSize
!= method
->count1
)
4859 && (*outputCount
!= method
->count1
))
4861 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
, (uint64_t)kIOUCVariableStructureSize
);
4862 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4866 func
= method
->func
;
4868 if( method
->count1
) {
4869 if( method
->count0
) {
4870 err
= (object
->*func
)( reference
,
4872 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4874 err
= (object
->*func
)( reference
,
4875 output
, outputCount
, 0, 0, 0, 0 );
4878 err
= (object
->*func
)( reference
,
4879 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4888 bool gIOKextdClearedBusy
= false;
4891 /* Routine io_catalog_send_data */
4892 kern_return_t
is_io_catalog_send_data(
4893 mach_port_t master_port
,
4895 io_buf_ptr_t inData
,
4896 mach_msg_type_number_t inDataCount
,
4897 kern_return_t
* result
)
4900 return kIOReturnNotPrivileged
;
4901 #else /* NO_KEXTD */
4904 kern_return_t kr
= kIOReturnError
;
4906 //printf("io_catalog_send_data called. flag: %d\n", flag);
4908 if( master_port
!= master_device_port
)
4909 return kIOReturnNotPrivileged
;
4911 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
4912 flag
!= kIOCatalogKextdActive
&&
4913 flag
!= kIOCatalogKextdFinishedLaunching
) &&
4914 ( !inData
|| !inDataCount
) )
4916 return kIOReturnBadArgument
;
4919 if (!IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management"))
4921 OSString
* taskName
= IOCopyLogNameForPID(proc_selfpid());
4922 IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName
? taskName
->getCStringNoCopy() : "");
4923 OSSafeReleaseNULL(taskName
);
4924 // For now, fake success to not break applications relying on this function succeeding.
4925 // See <rdar://problem/32554970> for more details.
4926 return kIOReturnSuccess
;
4930 vm_map_offset_t map_data
;
4932 if( inDataCount
> sizeof(io_struct_inband_t
) * 1024)
4933 return( kIOReturnMessageTooLarge
);
4935 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
4936 data
= CAST_DOWN(vm_offset_t
, map_data
);
4938 if( kr
!= KERN_SUCCESS
)
4941 // must return success after vm_map_copyout() succeeds
4944 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
4945 vm_deallocate( kernel_map
, data
, inDataCount
);
4947 *result
= kIOReturnNoMemory
;
4948 return( KERN_SUCCESS
);
4954 case kIOCatalogResetDrivers
:
4955 case kIOCatalogResetDriversNoMatch
: {
4958 array
= OSDynamicCast(OSArray
, obj
);
4960 if ( !gIOCatalogue
->resetAndAddDrivers(array
,
4961 flag
== kIOCatalogResetDrivers
) ) {
4963 kr
= kIOReturnError
;
4966 kr
= kIOReturnBadArgument
;
4971 case kIOCatalogAddDrivers
:
4972 case kIOCatalogAddDriversNoMatch
: {
4975 array
= OSDynamicCast(OSArray
, obj
);
4977 if ( !gIOCatalogue
->addDrivers( array
,
4978 flag
== kIOCatalogAddDrivers
) ) {
4979 kr
= kIOReturnError
;
4983 kr
= kIOReturnBadArgument
;
4988 case kIOCatalogRemoveDrivers
:
4989 case kIOCatalogRemoveDriversNoMatch
: {
4990 OSDictionary
* dict
;
4992 dict
= OSDynamicCast(OSDictionary
, obj
);
4994 if ( !gIOCatalogue
->removeDrivers( dict
,
4995 flag
== kIOCatalogRemoveDrivers
) ) {
4996 kr
= kIOReturnError
;
5000 kr
= kIOReturnBadArgument
;
5005 case kIOCatalogStartMatching
: {
5006 OSDictionary
* dict
;
5008 dict
= OSDynamicCast(OSDictionary
, obj
);
5010 if ( !gIOCatalogue
->startMatching( dict
) ) {
5011 kr
= kIOReturnError
;
5015 kr
= kIOReturnBadArgument
;
5020 case kIOCatalogRemoveKernelLinker
:
5021 kr
= KERN_NOT_SUPPORTED
;
5024 case kIOCatalogKextdActive
:
5026 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
5027 OSKext::setKextdActive();
5029 /* Dump all nonloaded startup extensions; kextd will now send them
5032 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
5034 kr
= kIOReturnSuccess
;
5037 case kIOCatalogKextdFinishedLaunching
: {
5039 if (!gIOKextdClearedBusy
) {
5040 IOService
* serviceRoot
= IOService::getServiceRoot();
5042 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
5043 serviceRoot
->adjustBusy(-1);
5044 gIOKextdClearedBusy
= true;
5048 kr
= kIOReturnSuccess
;
5053 kr
= kIOReturnBadArgument
;
5057 if (obj
) obj
->release();
5060 return( KERN_SUCCESS
);
5061 #endif /* NO_KEXTD */
5064 /* Routine io_catalog_terminate */
5065 kern_return_t
is_io_catalog_terminate(
5066 mach_port_t master_port
,
5072 if( master_port
!= master_device_port
)
5073 return kIOReturnNotPrivileged
;
5075 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
5076 kIOClientPrivilegeAdministrator
);
5077 if( kIOReturnSuccess
!= kr
)
5081 #if !defined(SECURE_KERNEL)
5082 case kIOCatalogServiceTerminate
:
5084 IOService
* service
;
5086 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
5087 kIORegistryIterateRecursively
);
5089 return kIOReturnNoMemory
;
5093 while( (service
= (IOService
*)iter
->getNextObject()) ) {
5094 if( service
->metaCast(name
)) {
5095 if ( !service
->terminate( kIOServiceRequired
5096 | kIOServiceSynchronous
) ) {
5097 kr
= kIOReturnUnsupported
;
5102 } while( !service
&& !iter
->isValid());
5106 case kIOCatalogModuleUnload
:
5107 case kIOCatalogModuleTerminate
:
5108 kr
= gIOCatalogue
->terminateDriversForModule(name
,
5109 flag
== kIOCatalogModuleUnload
);
5114 kr
= kIOReturnBadArgument
;
5121 /* Routine io_catalog_get_data */
5122 kern_return_t
is_io_catalog_get_data(
5123 mach_port_t master_port
,
5125 io_buf_ptr_t
*outData
,
5126 mach_msg_type_number_t
*outDataCount
)
5128 kern_return_t kr
= kIOReturnSuccess
;
5131 if( master_port
!= master_device_port
)
5132 return kIOReturnNotPrivileged
;
5134 //printf("io_catalog_get_data called. flag: %d\n", flag);
5136 s
= OSSerialize::withCapacity(4096);
5138 return kIOReturnNoMemory
;
5140 kr
= gIOCatalogue
->serializeData(flag
, s
);
5142 if ( kr
== kIOReturnSuccess
) {
5147 size
= s
->getLength();
5148 kr
= vm_allocate_kernel(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
, VM_KERN_MEMORY_IOKIT
);
5149 if ( kr
== kIOReturnSuccess
) {
5150 bcopy(s
->text(), (void *)data
, size
);
5151 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
5152 (vm_map_size_t
)size
, true, ©
);
5153 *outData
= (char *)copy
;
5154 *outDataCount
= size
;
5163 /* Routine io_catalog_get_gen_count */
5164 kern_return_t
is_io_catalog_get_gen_count(
5165 mach_port_t master_port
,
5168 if( master_port
!= master_device_port
)
5169 return kIOReturnNotPrivileged
;
5171 //printf("io_catalog_get_gen_count called.\n");
5174 return kIOReturnBadArgument
;
5176 *genCount
= gIOCatalogue
->getGenerationCount();
5178 return kIOReturnSuccess
;
5181 /* Routine io_catalog_module_loaded.
5182 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
5184 kern_return_t
is_io_catalog_module_loaded(
5185 mach_port_t master_port
,
5188 if( master_port
!= master_device_port
)
5189 return kIOReturnNotPrivileged
;
5191 //printf("io_catalog_module_loaded called. name %s\n", name);
5194 return kIOReturnBadArgument
;
5196 gIOCatalogue
->moduleHasLoaded(name
);
5198 return kIOReturnSuccess
;
5201 kern_return_t
is_io_catalog_reset(
5202 mach_port_t master_port
,
5205 if( master_port
!= master_device_port
)
5206 return kIOReturnNotPrivileged
;
5209 case kIOCatalogResetDefault
:
5210 gIOCatalogue
->reset();
5214 return kIOReturnBadArgument
;
5217 return kIOReturnSuccess
;
5220 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
5222 kern_return_t result
= kIOReturnBadArgument
;
5223 IOUserClient
*userClient
;
5225 if ((userClient
= OSDynamicCast(IOUserClient
,
5226 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
5227 IOExternalTrap
*trap
;
5228 IOService
*target
= NULL
;
5230 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
5232 if (trap
&& target
) {
5238 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
5242 iokit_remove_connect_reference(userClient
);
5250 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
5251 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
5255 IOByteCount structureOutputSize
;
5260 count
= dispatch
->checkScalarInputCount
;
5261 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
5263 return (kIOReturnBadArgument
);
5266 count
= dispatch
->checkStructureInputSize
;
5267 if ((kIOUCVariableStructureSize
!= count
)
5268 && (count
!= ((args
->structureInputDescriptor
)
5269 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
5271 return (kIOReturnBadArgument
);
5274 count
= dispatch
->checkScalarOutputCount
;
5275 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
5277 return (kIOReturnBadArgument
);
5280 count
= dispatch
->checkStructureOutputSize
;
5281 if ((kIOUCVariableStructureSize
!= count
)
5282 && (count
!= ((args
->structureOutputDescriptor
)
5283 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
5285 return (kIOReturnBadArgument
);
5288 if (dispatch
->function
)
5289 err
= (*dispatch
->function
)(target
, reference
, args
);
5291 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
5297 // pre-Leopard API's don't do ool structs
5298 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
5300 err
= kIOReturnIPCError
;
5304 structureOutputSize
= args
->structureOutputSize
;
5306 if (args
->asyncWakePort
)
5308 IOExternalAsyncMethod
* method
;
5310 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
)
5311 return (kIOReturnUnsupported
);
5313 if (kIOUCForegroundOnly
& method
->flags
)
5315 if (task_is_gpu_denied(current_task()))
5316 return (kIOReturnNotPermitted
);
5319 switch (method
->flags
& kIOUCTypeMask
)
5321 case kIOUCScalarIStructI
:
5322 err
= shim_io_async_method_scalarI_structureI( method
, object
,
5323 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5324 args
->scalarInput
, args
->scalarInputCount
,
5325 (char *)args
->structureInput
, args
->structureInputSize
);
5328 case kIOUCScalarIScalarO
:
5329 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
5330 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5331 args
->scalarInput
, args
->scalarInputCount
,
5332 args
->scalarOutput
, &args
->scalarOutputCount
);
5335 case kIOUCScalarIStructO
:
5336 err
= shim_io_async_method_scalarI_structureO( method
, object
,
5337 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5338 args
->scalarInput
, args
->scalarInputCount
,
5339 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5343 case kIOUCStructIStructO
:
5344 err
= shim_io_async_method_structureI_structureO( method
, object
,
5345 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5346 (char *)args
->structureInput
, args
->structureInputSize
,
5347 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5351 err
= kIOReturnBadArgument
;
5357 IOExternalMethod
* method
;
5359 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
)
5360 return (kIOReturnUnsupported
);
5362 if (kIOUCForegroundOnly
& method
->flags
)
5364 if (task_is_gpu_denied(current_task()))
5365 return (kIOReturnNotPermitted
);
5368 switch (method
->flags
& kIOUCTypeMask
)
5370 case kIOUCScalarIStructI
:
5371 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
5372 args
->scalarInput
, args
->scalarInputCount
,
5373 (char *) args
->structureInput
, args
->structureInputSize
);
5376 case kIOUCScalarIScalarO
:
5377 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
5378 args
->scalarInput
, args
->scalarInputCount
,
5379 args
->scalarOutput
, &args
->scalarOutputCount
);
5382 case kIOUCScalarIStructO
:
5383 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
5384 args
->scalarInput
, args
->scalarInputCount
,
5385 (char *) args
->structureOutput
, &structureOutputSize
);
5389 case kIOUCStructIStructO
:
5390 err
= shim_io_connect_method_structureI_structureO( method
, object
,
5391 (char *) args
->structureInput
, args
->structureInputSize
,
5392 (char *) args
->structureOutput
, &structureOutputSize
);
5396 err
= kIOReturnBadArgument
;
5401 args
->structureOutputSize
= structureOutputSize
;
5407 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
5408 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
5410 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
5411 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
5413 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
5414 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
5415 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
5416 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
5417 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
5418 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
5419 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
5420 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
5421 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
5422 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
5423 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
5424 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
5425 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
5426 OSMetaClassDefineReservedUnused(IOUserClient
, 15);