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 IOLockLock(client
->lock
);
609 client
->clientDied();
610 IOLockUnlock(client
->lock
);
613 else if( IKOT_IOKIT_OBJECT
== type
)
615 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
617 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
618 notify
->setNotification( 0 );
621 return( kIOReturnSuccess
);
626 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
628 class IOServiceUserNotification
: public IOUserNotification
630 OSDeclareDefaultStructors(IOServiceUserNotification
)
633 mach_msg_header_t msgHdr
;
634 OSNotificationHeader64 notifyHeader
;
637 enum { kMaxOutstanding
= 1024 };
642 OSObject
* lastEntry
;
648 virtual bool init( mach_port_t port
, natural_t type
,
649 void * reference
, vm_size_t referenceSize
,
651 virtual void free() APPLE_KEXT_OVERRIDE
;
652 void invalidatePort(void);
654 static bool _handler( void * target
,
655 void * ref
, IOService
* newService
, IONotifier
* notifier
);
656 virtual bool handler( void * ref
, IOService
* newService
);
658 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
661 class IOServiceMessageUserNotification
: public IOUserNotification
663 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
666 mach_msg_header_t msgHdr
;
667 mach_msg_body_t msgBody
;
668 mach_msg_port_descriptor_t ports
[1];
669 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
680 virtual bool init( mach_port_t port
, natural_t type
,
681 void * reference
, vm_size_t referenceSize
,
685 virtual void free() APPLE_KEXT_OVERRIDE
;
686 void invalidatePort(void);
688 static IOReturn
_handler( void * target
, void * ref
,
689 UInt32 messageType
, IOService
* provider
,
690 void * messageArgument
, vm_size_t argSize
);
691 virtual IOReturn
handler( void * ref
,
692 UInt32 messageType
, IOService
* provider
,
693 void * messageArgument
, vm_size_t argSize
);
695 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
698 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
701 #define super IOUserIterator
702 OSDefineMetaClass( IOUserNotification
, IOUserIterator
)
703 OSDefineAbstractStructors( IOUserNotification
, IOUserIterator
)
705 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
707 void IOUserNotification::free( void )
711 assert(OSDynamicCast(IONotifier
, holdNotify
));
712 ((IONotifier
*)holdNotify
)->remove();
715 // can't be in handler now
721 void IOUserNotification::setNotification( IONotifier
* notify
)
723 OSObject
* previousNotify
;
725 IOLockLock( gIOObjectPortLock
);
727 previousNotify
= holdNotify
;
730 IOLockUnlock( gIOObjectPortLock
);
734 assert(OSDynamicCast(IONotifier
, previousNotify
));
735 ((IONotifier
*)previousNotify
)->remove();
739 void IOUserNotification::reset()
744 bool IOUserNotification::isValid()
749 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
752 #define super IOUserNotification
753 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
755 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
757 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
758 void * reference
, vm_size_t referenceSize
,
764 newSet
= OSArray::withCapacity( 1 );
768 if (referenceSize
> sizeof(OSAsyncReference64
))
771 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
772 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
776 bzero( pingMsg
, msgSize
);
778 pingMsg
->msgHdr
.msgh_remote_port
= port
;
779 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
780 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
781 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
782 pingMsg
->msgHdr
.msgh_size
= msgSize
;
783 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
785 pingMsg
->notifyHeader
.size
= 0;
786 pingMsg
->notifyHeader
.type
= type
;
787 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
792 void IOServiceUserNotification::invalidatePort(void)
794 if (pingMsg
) pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
797 void IOServiceUserNotification::free( void )
802 OSObject
* _lastEntry
;
806 _lastEntry
= lastEntry
;
811 if( _pingMsg
&& _msgSize
) {
812 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
813 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
815 IOFree(_pingMsg
, _msgSize
);
819 _lastEntry
->release();
825 bool IOServiceUserNotification::_handler( void * target
,
826 void * ref
, IOService
* newService
, IONotifier
* notifier
)
828 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
831 bool IOServiceUserNotification::handler( void * ref
,
832 IOService
* newService
)
836 ipc_port_t port
= NULL
;
837 bool sendPing
= false;
841 count
= newSet
->getCount();
842 if( count
< kMaxOutstanding
) {
844 newSet
->setObject( newService
);
845 if( (sendPing
= (armed
&& (0 == count
))))
851 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
852 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
855 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
856 pingMsg
->msgHdr
.msgh_local_port
= port
;
858 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
860 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
861 pingMsg
->msgHdr
.msgh_size
,
862 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
865 iokit_release_port( port
);
867 if( (KERN_SUCCESS
!= kr
) && !ipcLogged
)
870 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
877 OSObject
* IOServiceUserNotification::getNextObject()
881 OSObject
* releaseEntry
;
885 releaseEntry
= lastEntry
;
886 count
= newSet
->getCount();
888 result
= newSet
->getObject( count
- 1 );
890 newSet
->removeObject( count
- 1);
899 if (releaseEntry
) releaseEntry
->release();
904 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
906 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
908 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
910 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
911 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
917 if (referenceSize
> sizeof(OSAsyncReference64
))
920 clientIs64
= client64
;
922 owningPID
= proc_selfpid();
924 extraSize
+= sizeof(IOServiceInterestContent64
);
925 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
926 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
930 bzero( pingMsg
, msgSize
);
932 pingMsg
->msgHdr
.msgh_remote_port
= port
;
933 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
935 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
936 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
937 pingMsg
->msgHdr
.msgh_size
= msgSize
;
938 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
940 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
942 pingMsg
->ports
[0].name
= 0;
943 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
944 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
946 pingMsg
->notifyHeader
.size
= extraSize
;
947 pingMsg
->notifyHeader
.type
= type
;
948 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
953 void IOServiceMessageUserNotification::invalidatePort(void)
955 if (pingMsg
) pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
958 void IOServiceMessageUserNotification::free( void )
968 if( _pingMsg
&& _msgSize
) {
969 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
970 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
972 IOFree( _pingMsg
, _msgSize
);
976 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
977 UInt32 messageType
, IOService
* provider
,
978 void * argument
, vm_size_t argSize
)
980 return( ((IOServiceMessageUserNotification
*) target
)->handler(
981 ref
, messageType
, provider
, argument
, argSize
));
984 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
985 UInt32 messageType
, IOService
* provider
,
986 void * messageArgument
, vm_size_t callerArgSize
)
988 enum { kLocalMsgSize
= 0x100 };
989 uint64_t stackMsg
[kLocalMsgSize
/ sizeof(uint64_t)];
993 vm_size_t thisMsgSize
;
994 ipc_port_t thisPort
, providerPort
;
995 struct PingMsg
* thisMsg
;
996 IOServiceInterestContent64
* data
;
998 if (kIOMessageCopyClientID
== messageType
)
1000 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
1001 return (kIOReturnSuccess
);
1004 if (callerArgSize
== 0)
1006 if (clientIs64
) argSize
= sizeof(data
->messageArgument
[0]);
1007 else argSize
= sizeof(uint32_t);
1011 if( callerArgSize
> kIOUserNotifyMaxMessageSize
)
1012 callerArgSize
= kIOUserNotifyMaxMessageSize
;
1013 argSize
= callerArgSize
;
1016 // adjust message size for ipc restrictions
1018 type
= pingMsg
->notifyHeader
.type
;
1019 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
1020 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
1021 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
1023 thisMsgSize
= msgSize
1024 + sizeof( IOServiceInterestContent64
)
1025 - sizeof( data
->messageArgument
)
1028 if (thisMsgSize
> sizeof(stackMsg
))
1030 allocMsg
= IOMalloc(thisMsgSize
);
1031 if (!allocMsg
) return (kIOReturnNoMemory
);
1032 thisMsg
= (typeof(thisMsg
)) allocMsg
;
1037 thisMsg
= (typeof(thisMsg
)) stackMsg
;
1040 bcopy(pingMsg
, thisMsg
, msgSize
);
1041 thisMsg
->notifyHeader
.type
= type
;
1042 data
= (IOServiceInterestContent64
*) (((uint8_t *) thisMsg
) + msgSize
);
1043 // == pingMsg->notifyHeader.content;
1044 data
->messageType
= messageType
;
1046 if (callerArgSize
== 0)
1048 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
1051 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
1056 bcopy( messageArgument
, data
->messageArgument
, callerArgSize
);
1057 bzero((void *)(((uintptr_t) &data
->messageArgument
[0]) + callerArgSize
), argSize
- callerArgSize
);
1060 thisMsg
->notifyHeader
.type
= type
;
1061 thisMsg
->msgHdr
.msgh_size
= thisMsgSize
;
1063 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
1064 thisMsg
->ports
[0].name
= providerPort
;
1065 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
1066 thisMsg
->msgHdr
.msgh_local_port
= thisPort
;
1068 kr
= mach_msg_send_from_kernel_with_options( &thisMsg
->msgHdr
,
1069 thisMsg
->msgHdr
.msgh_size
,
1070 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
1073 iokit_release_port( thisPort
);
1075 iokit_release_port( providerPort
);
1078 IOFree(allocMsg
, thisMsgSize
);
1080 if((KERN_SUCCESS
!= kr
) && !ipcLogged
)
1083 IOLog("%s: mach_msg_send_from_kernel_proper (0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1086 return( kIOReturnSuccess
);
1089 OSObject
* IOServiceMessageUserNotification::getNextObject()
1094 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1097 #define super IOService
1098 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
1100 IOLock
* gIOUserClientOwnersLock
;
1102 void IOUserClient::initialize( void )
1104 gIOObjectPortLock
= IOLockAlloc();
1105 gIOUserClientOwnersLock
= IOLockAlloc();
1106 assert(gIOObjectPortLock
&& gIOUserClientOwnersLock
);
1109 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
1110 mach_port_t wakePort
,
1111 void *callback
, void *refcon
)
1113 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
1114 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1115 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
1116 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
1119 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1120 mach_port_t wakePort
,
1121 mach_vm_address_t callback
, io_user_reference_t refcon
)
1123 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
1124 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1125 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
1126 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
1129 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1130 mach_port_t wakePort
,
1131 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
1133 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
1134 if (vm_map_is_64bit(get_task_map(task
))) {
1135 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
1139 static OSDictionary
* CopyConsoleUser(UInt32 uid
)
1142 OSDictionary
* user
= 0;
1144 if ((array
= OSDynamicCast(OSArray
,
1145 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1147 for (unsigned int idx
= 0;
1148 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1152 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
1153 && (uid
== num
->unsigned32BitValue())) {
1163 static OSDictionary
* CopyUserOnConsole(void)
1166 OSDictionary
* user
= 0;
1168 if ((array
= OSDynamicCast(OSArray
,
1169 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1171 for (unsigned int idx
= 0;
1172 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1175 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
1186 IOReturn
IOUserClient::clientHasAuthorization( task_t task
,
1187 IOService
* service
)
1191 p
= (proc_t
) get_bsdtask_info(task
);
1194 uint64_t authorizationID
;
1196 authorizationID
= proc_uniqueid(p
);
1197 if (authorizationID
)
1199 if (service
->getAuthorizationID() == authorizationID
)
1201 return (kIOReturnSuccess
);
1206 return (kIOReturnNotPermitted
);
1209 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
1210 const char * privilegeName
)
1213 security_token_t token
;
1214 mach_msg_type_number_t count
;
1216 OSDictionary
* user
;
1220 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
1221 sizeof(kIOClientPrivilegeForeground
)))
1223 if (task_is_gpu_denied(current_task()))
1224 return (kIOReturnNotPrivileged
);
1226 return (kIOReturnSuccess
);
1229 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1230 sizeof(kIOClientPrivilegeConsoleSession
)))
1235 task
= (task_t
) securityToken
;
1237 task
= current_task();
1238 p
= (proc_t
) get_bsdtask_info(task
);
1239 kr
= kIOReturnNotPrivileged
;
1241 if (p
&& (cred
= kauth_cred_proc_ref(p
)))
1243 user
= CopyUserOnConsole();
1247 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1248 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue()))
1250 kr
= kIOReturnSuccess
;
1254 kauth_cred_unref(&cred
);
1259 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1260 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
1261 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1263 task
= (task_t
)securityToken
;
1265 count
= TASK_SECURITY_TOKEN_COUNT
;
1266 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1268 if (KERN_SUCCESS
!= kr
)
1270 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1271 sizeof(kIOClientPrivilegeAdministrator
))) {
1272 if (0 != token
.val
[0])
1273 kr
= kIOReturnNotPrivileged
;
1274 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1275 sizeof(kIOClientPrivilegeLocalUser
))) {
1276 user
= CopyConsoleUser(token
.val
[0]);
1280 kr
= kIOReturnNotPrivileged
;
1281 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1282 sizeof(kIOClientPrivilegeConsoleUser
))) {
1283 user
= CopyConsoleUser(token
.val
[0]);
1285 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
1286 kr
= kIOReturnNotPrivileged
;
1287 else if ( secureConsole
) {
1288 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1289 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
1290 kr
= kIOReturnNotPrivileged
;
1295 kr
= kIOReturnNotPrivileged
;
1297 kr
= kIOReturnUnsupported
;
1302 OSObject
* IOUserClient::copyClientEntitlement( task_t task
,
1303 const char * entitlement
)
1305 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1309 char procname
[MAXCOMLEN
+ 1] = "";
1311 void *entitlements_blob
= NULL
;
1312 char *entitlements_data
= NULL
;
1313 OSObject
*entitlements_obj
= NULL
;
1314 OSDictionary
*entitlements
= NULL
;
1315 OSString
*errorString
= NULL
;
1316 OSObject
*value
= NULL
;
1318 p
= (proc_t
)get_bsdtask_info(task
);
1322 proc_name(pid
, procname
, (int)sizeof(procname
));
1324 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0)
1327 if (len
<= offsetof(CS_GenericBlob
, data
))
1331 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1332 * we'll try to parse in the kernel.
1334 len
-= offsetof(CS_GenericBlob
, data
);
1335 if (len
> MAX_ENTITLEMENTS_LEN
) {
1336 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n", procname
, pid
, len
, MAX_ENTITLEMENTS_LEN
);
1341 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1342 * what is stored in the entitlements blob. Copy the string and
1345 entitlements_data
= (char *)IOMalloc(len
+ 1);
1346 if (entitlements_data
== NULL
)
1348 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1349 entitlements_data
[len
] = '\0';
1351 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1352 if (errorString
!= NULL
) {
1353 IOLog("failed to parse entitlements for %s[%u]: %s\n", procname
, pid
, errorString
->getCStringNoCopy());
1356 if (entitlements_obj
== NULL
)
1359 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1360 if (entitlements
== NULL
)
1363 /* Fetch the entitlement value from the dictionary. */
1364 value
= entitlements
->getObject(entitlement
);
1369 if (entitlements_data
!= NULL
)
1370 IOFree(entitlements_data
, len
+ 1);
1371 if (entitlements_obj
!= NULL
)
1372 entitlements_obj
->release();
1373 if (errorString
!= NULL
)
1374 errorString
->release();
1378 bool IOUserClient::init()
1380 if (getPropertyTable() || super::init())
1386 bool IOUserClient::init(OSDictionary
* dictionary
)
1388 if (getPropertyTable() || super::init(dictionary
))
1394 bool IOUserClient::initWithTask(task_t owningTask
,
1398 if (getPropertyTable() || super::init())
1404 bool IOUserClient::initWithTask(task_t owningTask
,
1407 OSDictionary
* properties
)
1411 ok
= super::init( properties
);
1412 ok
&= initWithTask( owningTask
, securityID
, type
);
1417 bool IOUserClient::reserve()
1420 reserved
= IONew(ExpansionData
, 1);
1425 setTerminateDefer(NULL
, true);
1426 IOStatisticsRegisterCounter();
1431 struct IOUserClientOwner
1434 queue_chain_t taskLink
;
1436 queue_chain_t ucLink
;
1440 IOUserClient::registerOwner(task_t task
)
1442 IOUserClientOwner
* owner
;
1446 IOLockLock(gIOUserClientOwnersLock
);
1449 ret
= kIOReturnSuccess
;
1451 if (!owners
.next
) queue_init(&owners
);
1454 queue_iterate(&owners
, owner
, IOUserClientOwner
*, ucLink
)
1456 if (task
!= owner
->task
) continue;
1463 owner
= IONew(IOUserClientOwner
, 1);
1464 if (!newOwner
) ret
= kIOReturnNoMemory
;
1469 queue_enter_first(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1470 queue_enter_first(task_io_user_clients(task
), owner
, IOUserClientOwner
*, taskLink
);
1474 IOLockUnlock(gIOUserClientOwnersLock
);
1480 IOUserClient::noMoreSenders(void)
1482 IOUserClientOwner
* owner
;
1484 IOLockLock(gIOUserClientOwnersLock
);
1488 while (!queue_empty(&owners
))
1490 owner
= (IOUserClientOwner
*)(void *) queue_first(&owners
);
1491 queue_remove(task_io_user_clients(owner
->task
), owner
, IOUserClientOwner
*, taskLink
);
1492 queue_remove(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1493 IODelete(owner
, IOUserClientOwner
, 1);
1495 owners
.next
= owners
.prev
= NULL
;
1498 IOLockUnlock(gIOUserClientOwnersLock
);
1501 extern "C" kern_return_t
1502 iokit_task_terminate(task_t task
)
1504 IOUserClientOwner
* owner
;
1505 IOUserClient
* dead
;
1507 queue_head_t
* taskque
;
1509 IOLockLock(gIOUserClientOwnersLock
);
1511 taskque
= task_io_user_clients(task
);
1513 while (!queue_empty(taskque
))
1515 owner
= (IOUserClientOwner
*)(void *) queue_first(taskque
);
1517 queue_remove(taskque
, owner
, IOUserClientOwner
*, taskLink
);
1518 queue_remove(&uc
->owners
, owner
, IOUserClientOwner
*, ucLink
);
1519 if (queue_empty(&uc
->owners
))
1522 IOLog("destroying out of band connect for %s\n", uc
->getName());
1523 // now using the uc queue head as a singly linked queue,
1524 // leaving .next as NULL to mark it empty
1525 uc
->owners
.next
= NULL
;
1526 uc
->owners
.prev
= (queue_entry_t
) dead
;
1529 IODelete(owner
, IOUserClientOwner
, 1);
1532 IOLockUnlock(gIOUserClientOwnersLock
);
1537 dead
= (IOUserClient
*)(void *) dead
->owners
.prev
;
1538 uc
->owners
.prev
= NULL
;
1539 if (uc
->sharedInstance
|| !uc
->closed
) uc
->clientDied();
1543 return (KERN_SUCCESS
);
1546 void IOUserClient::free()
1548 if( mappings
) mappings
->release();
1549 if (lock
) IOLockFree(lock
);
1551 IOStatisticsUnregisterCounter();
1553 assert(!owners
.next
);
1554 assert(!owners
.prev
);
1556 if (reserved
) IODelete(reserved
, ExpansionData
, 1);
1561 IOReturn
IOUserClient::clientDied( void )
1563 IOReturn ret
= kIOReturnNotReady
;
1565 if (sharedInstance
|| OSCompareAndSwap8(0, 1, &closed
))
1567 ret
= clientClose();
1573 IOReturn
IOUserClient::clientClose( void )
1575 return( kIOReturnUnsupported
);
1578 IOService
* IOUserClient::getService( void )
1583 IOReturn
IOUserClient::registerNotificationPort(
1584 mach_port_t
/* port */,
1586 UInt32
/* refCon */)
1588 return( kIOReturnUnsupported
);
1591 IOReturn
IOUserClient::registerNotificationPort(
1594 io_user_reference_t refCon
)
1596 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
1599 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1600 semaphore_t
* semaphore
)
1602 return( kIOReturnUnsupported
);
1605 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
1607 return( kIOReturnUnsupported
);
1610 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
1611 IOOptionBits
* options
,
1612 IOMemoryDescriptor
** memory
)
1614 return( kIOReturnUnsupported
);
1618 IOMemoryMap
* IOUserClient::mapClientMemory(
1621 IOOptionBits mapFlags
,
1622 IOVirtualAddress atAddress
)
1628 IOMemoryMap
* IOUserClient::mapClientMemory64(
1631 IOOptionBits mapFlags
,
1632 mach_vm_address_t atAddress
)
1635 IOOptionBits options
= 0;
1636 IOMemoryDescriptor
* memory
= 0;
1637 IOMemoryMap
* map
= 0;
1639 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1641 if( memory
&& (kIOReturnSuccess
== err
)) {
1643 FAKE_STACK_FRAME(getMetaClass());
1645 options
= (options
& ~kIOMapUserOptionsMask
)
1646 | (mapFlags
& kIOMapUserOptionsMask
);
1647 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1650 FAKE_STACK_FRAME_END();
1656 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1657 OSObject
*obj
, io_object_t
*clientObj
)
1659 mach_port_name_t name
;
1661 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1663 *(mach_port_name_t
*)clientObj
= name
;
1664 return kIOReturnSuccess
;
1667 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1672 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1677 IOExternalTrap
* IOUserClient::
1678 getExternalTrapForIndex(UInt32 index
)
1683 #pragma clang diagnostic push
1684 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1686 // Suppressing the deprecated-declarations warning. Avoiding the use of deprecated
1687 // functions can break clients of kexts implementing getExternalMethodForIndex()
1688 IOExternalMethod
* IOUserClient::
1689 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1691 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1694 *targetP
= (IOService
*) method
->object
;
1699 IOExternalAsyncMethod
* IOUserClient::
1700 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1702 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1705 *targetP
= (IOService
*) method
->object
;
1710 IOExternalTrap
* IOUserClient::
1711 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1713 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1716 *targetP
= trap
->object
;
1721 #pragma clang diagnostic pop
1723 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1726 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1728 if (MACH_PORT_NULL
!= port
)
1729 iokit_release_port_send(port
);
1731 return (kIOReturnSuccess
);
1734 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1736 if (MACH_PORT_NULL
!= port
)
1737 iokit_release_port_send(port
);
1739 return (kIOReturnSuccess
);
1742 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1743 IOReturn result
, void *args
[], UInt32 numArgs
)
1745 OSAsyncReference64 reference64
;
1746 io_user_reference_t args64
[kMaxAsyncArgs
];
1749 if (numArgs
> kMaxAsyncArgs
)
1750 return kIOReturnMessageTooLarge
;
1752 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1753 reference64
[idx
] = REF64(reference
[idx
]);
1755 for (idx
= 0; idx
< numArgs
; idx
++)
1756 args64
[idx
] = REF64(args
[idx
]);
1758 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1761 IOReturn
IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
1762 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1764 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
1767 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1768 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1770 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
1773 IOReturn
IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
1774 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1778 mach_msg_header_t msgHdr
;
1783 OSNotificationHeader notifyHdr
;
1784 IOAsyncCompletionContent asyncContent
;
1785 uint32_t args
[kMaxAsyncArgs
];
1789 OSNotificationHeader64 notifyHdr
;
1790 IOAsyncCompletionContent asyncContent
;
1791 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1796 mach_port_t replyPort
;
1799 // If no reply port, do nothing.
1800 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1801 if (replyPort
== MACH_PORT_NULL
)
1802 return kIOReturnSuccess
;
1804 if (numArgs
> kMaxAsyncArgs
)
1805 return kIOReturnMessageTooLarge
;
1807 bzero(&replyMsg
, sizeof(replyMsg
));
1808 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1810 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1811 replyMsg
.msgHdr
.msgh_local_port
= 0;
1812 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1813 if (kIOUCAsync64Flag
& reference
[0])
1815 replyMsg
.msgHdr
.msgh_size
=
1816 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1817 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1818 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1819 + numArgs
* sizeof(io_user_reference_t
);
1820 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1821 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1823 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1825 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1831 replyMsg
.msgHdr
.msgh_size
=
1832 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1833 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1835 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1836 + numArgs
* sizeof(uint32_t);
1837 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1839 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1840 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1842 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1844 for (idx
= 0; idx
< numArgs
; idx
++)
1845 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1848 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
1849 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
1850 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
1852 /* Fail on full queue. */
1853 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1854 replyMsg
.msgHdr
.msgh_size
);
1856 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
) && !(kIOUCAsyncErrorLoggedFlag
& reference
[0]))
1858 reference
[0] |= kIOUCAsyncErrorLoggedFlag
;
1859 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1865 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1869 #define CHECK(cls,obj,out) \
1871 if( !(out = OSDynamicCast( cls, obj))) \
1872 return( kIOReturnBadArgument )
1874 #define CHECKLOCKED(cls,obj,out) \
1875 IOUserIterator * oIter; \
1877 if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
1878 return (kIOReturnBadArgument); \
1879 if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
1880 return (kIOReturnBadArgument)
1882 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1884 // Create a vm_map_copy_t or kalloc'ed data for memory
1885 // to be copied out. ipc will free after the copyout.
1887 static kern_return_t
copyoutkdata( const void * data
, vm_size_t len
,
1888 io_buf_ptr_t
* buf
)
1893 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1894 false /* src_destroy */, ©
);
1896 assert( err
== KERN_SUCCESS
);
1897 if( err
== KERN_SUCCESS
)
1898 *buf
= (char *) copy
;
1903 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1905 /* Routine io_server_version */
1906 kern_return_t
is_io_server_version(
1907 mach_port_t master_port
,
1910 *version
= IOKIT_SERVER_VERSION
;
1911 return (kIOReturnSuccess
);
1914 /* Routine io_object_get_class */
1915 kern_return_t
is_io_object_get_class(
1917 io_name_t className
)
1919 const OSMetaClass
* my_obj
= NULL
;
1922 return( kIOReturnBadArgument
);
1924 my_obj
= object
->getMetaClass();
1926 return (kIOReturnNotFound
);
1929 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
1931 return( kIOReturnSuccess
);
1934 /* Routine io_object_get_superclass */
1935 kern_return_t
is_io_object_get_superclass(
1936 mach_port_t master_port
,
1938 io_name_t class_name
)
1941 const OSMetaClass
* meta
;
1942 const OSMetaClass
* super
;
1943 const OSSymbol
* name
;
1946 if (!obj_name
|| !class_name
) return (kIOReturnBadArgument
);
1947 if (master_port
!= master_device_port
) return( kIOReturnNotPrivileged
);
1949 ret
= kIOReturnNotFound
;
1953 name
= OSSymbol::withCString(obj_name
);
1955 meta
= OSMetaClass::copyMetaClassWithName(name
);
1957 super
= meta
->getSuperClass();
1959 cstr
= super
->getClassName();
1961 strlcpy(class_name
, cstr
, sizeof(io_name_t
));
1962 ret
= kIOReturnSuccess
;
1966 OSSafeReleaseNULL(name
);
1967 if (meta
) meta
->releaseMetaClass();
1972 /* Routine io_object_get_bundle_identifier */
1973 kern_return_t
is_io_object_get_bundle_identifier(
1974 mach_port_t master_port
,
1976 io_name_t bundle_name
)
1979 const OSMetaClass
* meta
;
1980 const OSSymbol
* name
;
1981 const OSSymbol
* identifier
;
1984 if (!obj_name
|| !bundle_name
) return (kIOReturnBadArgument
);
1985 if (master_port
!= master_device_port
) return( kIOReturnNotPrivileged
);
1987 ret
= kIOReturnNotFound
;
1991 name
= OSSymbol::withCString(obj_name
);
1993 meta
= OSMetaClass::copyMetaClassWithName(name
);
1995 identifier
= meta
->getKmodName();
1996 if (!identifier
) break;
1997 cstr
= identifier
->getCStringNoCopy();
1999 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
2000 ret
= kIOReturnSuccess
;
2004 OSSafeReleaseNULL(name
);
2005 if (meta
) meta
->releaseMetaClass();
2010 /* Routine io_object_conforms_to */
2011 kern_return_t
is_io_object_conforms_to(
2013 io_name_t className
,
2014 boolean_t
*conforms
)
2017 return( kIOReturnBadArgument
);
2019 *conforms
= (0 != object
->metaCast( className
));
2021 return( kIOReturnSuccess
);
2024 /* Routine io_object_get_retain_count */
2025 kern_return_t
is_io_object_get_retain_count(
2027 uint32_t *retainCount
)
2030 return( kIOReturnBadArgument
);
2032 *retainCount
= object
->getRetainCount();
2033 return( kIOReturnSuccess
);
2036 /* Routine io_iterator_next */
2037 kern_return_t
is_io_iterator_next(
2038 io_object_t iterator
,
2039 io_object_t
*object
)
2044 CHECK( OSIterator
, iterator
, iter
);
2046 obj
= iter
->getNextObject();
2050 ret
= kIOReturnSuccess
;
2052 ret
= kIOReturnNoDevice
;
2057 /* Routine io_iterator_reset */
2058 kern_return_t
is_io_iterator_reset(
2059 io_object_t iterator
)
2061 CHECK( OSIterator
, iterator
, iter
);
2065 return( kIOReturnSuccess
);
2068 /* Routine io_iterator_is_valid */
2069 kern_return_t
is_io_iterator_is_valid(
2070 io_object_t iterator
,
2071 boolean_t
*is_valid
)
2073 CHECK( OSIterator
, iterator
, iter
);
2075 *is_valid
= iter
->isValid();
2077 return( kIOReturnSuccess
);
2081 static kern_return_t
internal_io_service_match_property_table(
2082 io_service_t _service
,
2083 const char * matching
,
2084 mach_msg_type_number_t matching_size
,
2087 CHECK( IOService
, _service
, service
);
2091 OSDictionary
* dict
;
2093 assert(matching_size
);
2094 obj
= OSUnserializeXML(matching
, matching_size
);
2096 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2097 *matches
= service
->passiveMatch( dict
);
2098 kr
= kIOReturnSuccess
;
2100 kr
= kIOReturnBadArgument
;
2108 /* Routine io_service_match_property_table */
2109 kern_return_t
is_io_service_match_property_table(
2110 io_service_t service
,
2111 io_string_t matching
,
2112 boolean_t
*matches
)
2114 return (kIOReturnUnsupported
);
2118 /* Routine io_service_match_property_table_ool */
2119 kern_return_t
is_io_service_match_property_table_ool(
2120 io_object_t service
,
2121 io_buf_ptr_t matching
,
2122 mach_msg_type_number_t matchingCnt
,
2123 kern_return_t
*result
,
2124 boolean_t
*matches
)
2128 vm_map_offset_t map_data
;
2130 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2131 data
= CAST_DOWN(vm_offset_t
, map_data
);
2133 if( KERN_SUCCESS
== kr
) {
2134 // must return success after vm_map_copyout() succeeds
2135 *result
= internal_io_service_match_property_table(service
,
2136 (const char *)data
, matchingCnt
, matches
);
2137 vm_deallocate( kernel_map
, data
, matchingCnt
);
2143 /* Routine io_service_match_property_table_bin */
2144 kern_return_t
is_io_service_match_property_table_bin(
2145 io_object_t service
,
2146 io_struct_inband_t matching
,
2147 mach_msg_type_number_t matchingCnt
,
2150 return (internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
));
2153 static kern_return_t
internal_io_service_get_matching_services(
2154 mach_port_t master_port
,
2155 const char * matching
,
2156 mach_msg_type_number_t matching_size
,
2157 io_iterator_t
*existing
)
2161 OSDictionary
* dict
;
2163 if( master_port
!= master_device_port
)
2164 return( kIOReturnNotPrivileged
);
2166 assert(matching_size
);
2167 obj
= OSUnserializeXML(matching
, matching_size
);
2169 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2170 *existing
= IOUserIterator::withIterator(IOService::getMatchingServices( dict
));
2171 kr
= kIOReturnSuccess
;
2173 kr
= kIOReturnBadArgument
;
2181 /* Routine io_service_get_matching_services */
2182 kern_return_t
is_io_service_get_matching_services(
2183 mach_port_t master_port
,
2184 io_string_t matching
,
2185 io_iterator_t
*existing
)
2187 return (kIOReturnUnsupported
);
2190 /* Routine io_service_get_matching_services_ool */
2191 kern_return_t
is_io_service_get_matching_services_ool(
2192 mach_port_t master_port
,
2193 io_buf_ptr_t matching
,
2194 mach_msg_type_number_t matchingCnt
,
2195 kern_return_t
*result
,
2196 io_object_t
*existing
)
2200 vm_map_offset_t map_data
;
2202 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2203 data
= CAST_DOWN(vm_offset_t
, map_data
);
2205 if( KERN_SUCCESS
== kr
) {
2206 // must return success after vm_map_copyout() succeeds
2207 // and mig will copy out objects on success
2209 *result
= internal_io_service_get_matching_services(master_port
,
2210 (const char *) data
, matchingCnt
, existing
);
2211 vm_deallocate( kernel_map
, data
, matchingCnt
);
2217 /* Routine io_service_get_matching_services_bin */
2218 kern_return_t
is_io_service_get_matching_services_bin(
2219 mach_port_t master_port
,
2220 io_struct_inband_t matching
,
2221 mach_msg_type_number_t matchingCnt
,
2222 io_object_t
*existing
)
2224 return (internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
));
2228 static kern_return_t
internal_io_service_get_matching_service(
2229 mach_port_t master_port
,
2230 const char * matching
,
2231 mach_msg_type_number_t matching_size
,
2232 io_service_t
*service
)
2236 OSDictionary
* dict
;
2238 if( master_port
!= master_device_port
)
2239 return( kIOReturnNotPrivileged
);
2241 assert(matching_size
);
2242 obj
= OSUnserializeXML(matching
, matching_size
);
2244 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2245 *service
= IOService::copyMatchingService( dict
);
2246 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
2248 kr
= kIOReturnBadArgument
;
2256 /* Routine io_service_get_matching_service */
2257 kern_return_t
is_io_service_get_matching_service(
2258 mach_port_t master_port
,
2259 io_string_t matching
,
2260 io_service_t
*service
)
2262 return (kIOReturnUnsupported
);
2265 /* Routine io_service_get_matching_services_ool */
2266 kern_return_t
is_io_service_get_matching_service_ool(
2267 mach_port_t master_port
,
2268 io_buf_ptr_t matching
,
2269 mach_msg_type_number_t matchingCnt
,
2270 kern_return_t
*result
,
2271 io_object_t
*service
)
2275 vm_map_offset_t map_data
;
2277 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2278 data
= CAST_DOWN(vm_offset_t
, map_data
);
2280 if( KERN_SUCCESS
== kr
) {
2281 // must return success after vm_map_copyout() succeeds
2282 // and mig will copy out objects on success
2284 *result
= internal_io_service_get_matching_service(master_port
,
2285 (const char *) data
, matchingCnt
, service
);
2286 vm_deallocate( kernel_map
, data
, matchingCnt
);
2292 /* Routine io_service_get_matching_service_bin */
2293 kern_return_t
is_io_service_get_matching_service_bin(
2294 mach_port_t master_port
,
2295 io_struct_inband_t matching
,
2296 mach_msg_type_number_t matchingCnt
,
2297 io_object_t
*service
)
2299 return (internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
));
2302 static kern_return_t
internal_io_service_add_notification(
2303 mach_port_t master_port
,
2304 io_name_t notification_type
,
2305 const char * matching
,
2306 size_t matching_size
,
2309 vm_size_t referenceSize
,
2311 io_object_t
* notification
)
2313 IOServiceUserNotification
* userNotify
= 0;
2314 IONotifier
* notify
= 0;
2315 const OSSymbol
* sym
;
2316 OSDictionary
* dict
;
2318 unsigned long int userMsgType
;
2320 if( master_port
!= master_device_port
)
2321 return( kIOReturnNotPrivileged
);
2324 err
= kIOReturnNoResources
;
2326 if (matching_size
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2328 if( !(sym
= OSSymbol::withCString( notification_type
)))
2329 err
= kIOReturnNoResources
;
2331 assert(matching_size
);
2332 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
2334 err
= kIOReturnBadArgument
;
2338 if( (sym
== gIOPublishNotification
)
2339 || (sym
== gIOFirstPublishNotification
))
2340 userMsgType
= kIOServicePublishNotificationType
;
2341 else if( (sym
== gIOMatchedNotification
)
2342 || (sym
== gIOFirstMatchNotification
))
2343 userMsgType
= kIOServiceMatchedNotificationType
;
2344 else if ((sym
== gIOTerminatedNotification
)
2345 || (sym
== gIOWillTerminateNotification
))
2346 userMsgType
= kIOServiceTerminatedNotificationType
;
2348 userMsgType
= kLastIOKitNotificationType
;
2350 userNotify
= new IOServiceUserNotification
;
2352 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
2353 reference
, referenceSize
, client64
)) {
2354 userNotify
->release();
2360 notify
= IOService::addMatchingNotification( sym
, dict
,
2361 &userNotify
->_handler
, userNotify
);
2363 *notification
= userNotify
;
2364 userNotify
->setNotification( notify
);
2365 err
= kIOReturnSuccess
;
2367 err
= kIOReturnUnsupported
;
2371 if ((kIOReturnSuccess
!= err
) && userNotify
)
2373 userNotify
->invalidatePort();
2374 userNotify
->release();
2387 /* Routine io_service_add_notification */
2388 kern_return_t
is_io_service_add_notification(
2389 mach_port_t master_port
,
2390 io_name_t notification_type
,
2391 io_string_t matching
,
2393 io_async_ref_t reference
,
2394 mach_msg_type_number_t referenceCnt
,
2395 io_object_t
* notification
)
2397 return (kIOReturnUnsupported
);
2400 /* Routine io_service_add_notification_64 */
2401 kern_return_t
is_io_service_add_notification_64(
2402 mach_port_t master_port
,
2403 io_name_t notification_type
,
2404 io_string_t matching
,
2405 mach_port_t wake_port
,
2406 io_async_ref64_t reference
,
2407 mach_msg_type_number_t referenceCnt
,
2408 io_object_t
*notification
)
2410 return (kIOReturnUnsupported
);
2413 /* Routine io_service_add_notification_bin */
2414 kern_return_t is_io_service_add_notification_bin
2416 mach_port_t master_port
,
2417 io_name_t notification_type
,
2418 io_struct_inband_t matching
,
2419 mach_msg_type_number_t matchingCnt
,
2420 mach_port_t wake_port
,
2421 io_async_ref_t reference
,
2422 mach_msg_type_number_t referenceCnt
,
2423 io_object_t
*notification
)
2425 return (internal_io_service_add_notification(master_port
, notification_type
,
2426 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2427 false, notification
));
2430 /* Routine io_service_add_notification_bin_64 */
2431 kern_return_t is_io_service_add_notification_bin_64
2433 mach_port_t master_port
,
2434 io_name_t notification_type
,
2435 io_struct_inband_t matching
,
2436 mach_msg_type_number_t matchingCnt
,
2437 mach_port_t wake_port
,
2438 io_async_ref64_t reference
,
2439 mach_msg_type_number_t referenceCnt
,
2440 io_object_t
*notification
)
2442 return (internal_io_service_add_notification(master_port
, notification_type
,
2443 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2444 true, notification
));
2447 static kern_return_t
internal_io_service_add_notification_ool(
2448 mach_port_t master_port
,
2449 io_name_t notification_type
,
2450 io_buf_ptr_t matching
,
2451 mach_msg_type_number_t matchingCnt
,
2452 mach_port_t wake_port
,
2454 vm_size_t referenceSize
,
2456 kern_return_t
*result
,
2457 io_object_t
*notification
)
2461 vm_map_offset_t map_data
;
2463 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2464 data
= CAST_DOWN(vm_offset_t
, map_data
);
2466 if( KERN_SUCCESS
== kr
) {
2467 // must return success after vm_map_copyout() succeeds
2468 // and mig will copy out objects on success
2470 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2471 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2472 vm_deallocate( kernel_map
, data
, matchingCnt
);
2478 /* Routine io_service_add_notification_ool */
2479 kern_return_t
is_io_service_add_notification_ool(
2480 mach_port_t master_port
,
2481 io_name_t notification_type
,
2482 io_buf_ptr_t matching
,
2483 mach_msg_type_number_t matchingCnt
,
2484 mach_port_t wake_port
,
2485 io_async_ref_t reference
,
2486 mach_msg_type_number_t referenceCnt
,
2487 kern_return_t
*result
,
2488 io_object_t
*notification
)
2490 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2491 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2492 false, result
, notification
));
2495 /* Routine io_service_add_notification_ool_64 */
2496 kern_return_t
is_io_service_add_notification_ool_64(
2497 mach_port_t master_port
,
2498 io_name_t notification_type
,
2499 io_buf_ptr_t matching
,
2500 mach_msg_type_number_t matchingCnt
,
2501 mach_port_t wake_port
,
2502 io_async_ref64_t reference
,
2503 mach_msg_type_number_t referenceCnt
,
2504 kern_return_t
*result
,
2505 io_object_t
*notification
)
2507 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2508 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2509 true, result
, notification
));
2512 /* Routine io_service_add_notification_old */
2513 kern_return_t
is_io_service_add_notification_old(
2514 mach_port_t master_port
,
2515 io_name_t notification_type
,
2516 io_string_t matching
,
2518 // for binary compatibility reasons, this must be natural_t for ILP32
2520 io_object_t
* notification
)
2522 return( is_io_service_add_notification( master_port
, notification_type
,
2523 matching
, port
, &ref
, 1, notification
));
2527 static kern_return_t
internal_io_service_add_interest_notification(
2528 io_object_t _service
,
2529 io_name_t type_of_interest
,
2532 vm_size_t referenceSize
,
2534 io_object_t
* notification
)
2537 IOServiceMessageUserNotification
* userNotify
= 0;
2538 IONotifier
* notify
= 0;
2539 const OSSymbol
* sym
;
2542 CHECK( IOService
, _service
, service
);
2544 err
= kIOReturnNoResources
;
2545 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
2547 userNotify
= new IOServiceMessageUserNotification
;
2549 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2550 reference
, referenceSize
,
2551 kIOUserNotifyMaxMessageSize
,
2553 userNotify
->release();
2559 notify
= service
->registerInterest( sym
,
2560 &userNotify
->_handler
, userNotify
);
2562 *notification
= userNotify
;
2563 userNotify
->setNotification( notify
);
2564 err
= kIOReturnSuccess
;
2566 err
= kIOReturnUnsupported
;
2572 if ((kIOReturnSuccess
!= err
) && userNotify
)
2574 userNotify
->invalidatePort();
2575 userNotify
->release();
2582 /* Routine io_service_add_message_notification */
2583 kern_return_t
is_io_service_add_interest_notification(
2584 io_object_t service
,
2585 io_name_t type_of_interest
,
2587 io_async_ref_t reference
,
2588 mach_msg_type_number_t referenceCnt
,
2589 io_object_t
* notification
)
2591 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2592 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
2595 /* Routine io_service_add_interest_notification_64 */
2596 kern_return_t
is_io_service_add_interest_notification_64(
2597 io_object_t service
,
2598 io_name_t type_of_interest
,
2599 mach_port_t wake_port
,
2600 io_async_ref64_t reference
,
2601 mach_msg_type_number_t referenceCnt
,
2602 io_object_t
*notification
)
2604 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2605 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
2609 /* Routine io_service_acknowledge_notification */
2610 kern_return_t
is_io_service_acknowledge_notification(
2611 io_object_t _service
,
2612 natural_t notify_ref
,
2613 natural_t response
)
2615 CHECK( IOService
, _service
, service
);
2617 return( service
->acknowledgeNotification( (IONotificationRef
)(uintptr_t) notify_ref
,
2618 (IOOptionBits
) response
));
2622 /* Routine io_connect_get_semaphore */
2623 kern_return_t
is_io_connect_get_notification_semaphore(
2624 io_connect_t connection
,
2625 natural_t notification_type
,
2626 semaphore_t
*semaphore
)
2628 CHECK( IOUserClient
, connection
, client
);
2630 IOStatisticsClientCall();
2631 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
2635 /* Routine io_registry_get_root_entry */
2636 kern_return_t
is_io_registry_get_root_entry(
2637 mach_port_t master_port
,
2640 IORegistryEntry
* entry
;
2642 if( master_port
!= master_device_port
)
2643 return( kIOReturnNotPrivileged
);
2645 entry
= IORegistryEntry::getRegistryRoot();
2650 return( kIOReturnSuccess
);
2653 /* Routine io_registry_create_iterator */
2654 kern_return_t
is_io_registry_create_iterator(
2655 mach_port_t master_port
,
2658 io_object_t
*iterator
)
2660 if( master_port
!= master_device_port
)
2661 return( kIOReturnNotPrivileged
);
2663 *iterator
= IOUserIterator::withIterator(
2664 IORegistryIterator::iterateOver(
2665 IORegistryEntry::getPlane( plane
), options
));
2667 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2670 /* Routine io_registry_entry_create_iterator */
2671 kern_return_t
is_io_registry_entry_create_iterator(
2672 io_object_t registry_entry
,
2675 io_object_t
*iterator
)
2677 CHECK( IORegistryEntry
, registry_entry
, entry
);
2679 *iterator
= IOUserIterator::withIterator(
2680 IORegistryIterator::iterateOver( entry
,
2681 IORegistryEntry::getPlane( plane
), options
));
2683 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2686 /* Routine io_registry_iterator_enter */
2687 kern_return_t
is_io_registry_iterator_enter_entry(
2688 io_object_t iterator
)
2690 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2692 IOLockLock(oIter
->lock
);
2694 IOLockUnlock(oIter
->lock
);
2696 return( kIOReturnSuccess
);
2699 /* Routine io_registry_iterator_exit */
2700 kern_return_t
is_io_registry_iterator_exit_entry(
2701 io_object_t iterator
)
2705 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2707 IOLockLock(oIter
->lock
);
2708 didIt
= iter
->exitEntry();
2709 IOLockUnlock(oIter
->lock
);
2711 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
2714 /* Routine io_registry_entry_from_path */
2715 kern_return_t
is_io_registry_entry_from_path(
2716 mach_port_t master_port
,
2718 io_object_t
*registry_entry
)
2720 IORegistryEntry
* entry
;
2722 if( master_port
!= master_device_port
)
2723 return( kIOReturnNotPrivileged
);
2725 entry
= IORegistryEntry::fromPath( path
);
2727 *registry_entry
= entry
;
2729 return( kIOReturnSuccess
);
2733 /* Routine io_registry_entry_from_path */
2734 kern_return_t
is_io_registry_entry_from_path_ool(
2735 mach_port_t master_port
,
2736 io_string_inband_t path
,
2737 io_buf_ptr_t path_ool
,
2738 mach_msg_type_number_t path_oolCnt
,
2739 kern_return_t
*result
,
2740 io_object_t
*registry_entry
)
2742 IORegistryEntry
* entry
;
2743 vm_map_offset_t map_data
;
2748 if (master_port
!= master_device_port
) return(kIOReturnNotPrivileged
);
2752 res
= err
= KERN_SUCCESS
;
2753 if (path
[0]) cpath
= path
;
2756 if (!path_oolCnt
) return(kIOReturnBadArgument
);
2757 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2759 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
2760 if (KERN_SUCCESS
== err
)
2762 // must return success to mig after vm_map_copyout() succeeds, so result is actual
2763 cpath
= CAST_DOWN(const char *, map_data
);
2764 if (cpath
[path_oolCnt
- 1]) res
= kIOReturnBadArgument
;
2768 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
))
2770 entry
= IORegistryEntry::fromPath(cpath
);
2771 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
2774 if (map_data
) vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
2776 if (KERN_SUCCESS
!= err
) res
= err
;
2777 *registry_entry
= entry
;
2784 /* Routine io_registry_entry_in_plane */
2785 kern_return_t
is_io_registry_entry_in_plane(
2786 io_object_t registry_entry
,
2788 boolean_t
*inPlane
)
2790 CHECK( IORegistryEntry
, registry_entry
, entry
);
2792 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
2794 return( kIOReturnSuccess
);
2798 /* Routine io_registry_entry_get_path */
2799 kern_return_t
is_io_registry_entry_get_path(
2800 io_object_t registry_entry
,
2805 CHECK( IORegistryEntry
, registry_entry
, entry
);
2807 length
= sizeof( io_string_t
);
2808 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
2809 return( kIOReturnSuccess
);
2811 return( kIOReturnBadArgument
);
2814 /* Routine io_registry_entry_get_path */
2815 kern_return_t
is_io_registry_entry_get_path_ool(
2816 io_object_t registry_entry
,
2818 io_string_inband_t path
,
2819 io_buf_ptr_t
*path_ool
,
2820 mach_msg_type_number_t
*path_oolCnt
)
2822 enum { kMaxPath
= 16384 };
2827 CHECK( IORegistryEntry
, registry_entry
, entry
);
2831 length
= sizeof(io_string_inband_t
);
2832 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnSuccess
;
2836 buf
= IONew(char, length
);
2837 if (!buf
) err
= kIOReturnNoMemory
;
2838 else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnError
;
2841 *path_oolCnt
= length
;
2842 err
= copyoutkdata(buf
, length
, path_ool
);
2844 if (buf
) IODelete(buf
, char, kMaxPath
);
2851 /* Routine io_registry_entry_get_name */
2852 kern_return_t
is_io_registry_entry_get_name(
2853 io_object_t registry_entry
,
2856 CHECK( IORegistryEntry
, registry_entry
, entry
);
2858 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
2860 return( kIOReturnSuccess
);
2863 /* Routine io_registry_entry_get_name_in_plane */
2864 kern_return_t
is_io_registry_entry_get_name_in_plane(
2865 io_object_t registry_entry
,
2866 io_name_t planeName
,
2869 const IORegistryPlane
* plane
;
2870 CHECK( IORegistryEntry
, registry_entry
, entry
);
2873 plane
= IORegistryEntry::getPlane( planeName
);
2877 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
2879 return( kIOReturnSuccess
);
2882 /* Routine io_registry_entry_get_location_in_plane */
2883 kern_return_t
is_io_registry_entry_get_location_in_plane(
2884 io_object_t registry_entry
,
2885 io_name_t planeName
,
2886 io_name_t location
)
2888 const IORegistryPlane
* plane
;
2889 CHECK( IORegistryEntry
, registry_entry
, entry
);
2892 plane
= IORegistryEntry::getPlane( planeName
);
2896 const char * cstr
= entry
->getLocation( plane
);
2899 strncpy( location
, cstr
, sizeof( io_name_t
));
2900 return( kIOReturnSuccess
);
2902 return( kIOReturnNotFound
);
2905 /* Routine io_registry_entry_get_registry_entry_id */
2906 kern_return_t
is_io_registry_entry_get_registry_entry_id(
2907 io_object_t registry_entry
,
2908 uint64_t *entry_id
)
2910 CHECK( IORegistryEntry
, registry_entry
, entry
);
2912 *entry_id
= entry
->getRegistryEntryID();
2914 return (kIOReturnSuccess
);
2917 /* Routine io_registry_entry_get_property */
2918 kern_return_t
is_io_registry_entry_get_property_bytes(
2919 io_object_t registry_entry
,
2920 io_name_t property_name
,
2921 io_struct_inband_t buf
,
2922 mach_msg_type_number_t
*dataCnt
)
2930 unsigned int len
= 0;
2931 const void * bytes
= 0;
2932 IOReturn ret
= kIOReturnSuccess
;
2934 CHECK( IORegistryEntry
, registry_entry
, entry
);
2937 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2938 return kIOReturnNotPermitted
;
2941 obj
= entry
->copyProperty(property_name
);
2943 return( kIOReturnNoResources
);
2945 // One day OSData will be a common container base class
2947 if( (data
= OSDynamicCast( OSData
, obj
))) {
2948 len
= data
->getLength();
2949 bytes
= data
->getBytesNoCopy();
2950 if (!data
->isSerializable()) len
= 0;
2952 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2953 len
= str
->getLength() + 1;
2954 bytes
= str
->getCStringNoCopy();
2956 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2957 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2958 bytes
= boo
->isTrue() ? "Yes" : "No";
2960 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2961 offsetBytes
= off
->unsigned64BitValue();
2962 len
= off
->numberOfBytes();
2963 if (len
> sizeof(offsetBytes
)) len
= sizeof(offsetBytes
);
2964 bytes
= &offsetBytes
;
2965 #ifdef __BIG_ENDIAN__
2966 bytes
= (const void *)
2967 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2971 ret
= kIOReturnBadArgument
;
2975 ret
= kIOReturnIPCError
;
2978 bcopy( bytes
, buf
, len
);
2987 /* Routine io_registry_entry_get_property */
2988 kern_return_t
is_io_registry_entry_get_property(
2989 io_object_t registry_entry
,
2990 io_name_t property_name
,
2991 io_buf_ptr_t
*properties
,
2992 mach_msg_type_number_t
*propertiesCnt
)
2998 CHECK( IORegistryEntry
, registry_entry
, entry
);
3001 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3002 return kIOReturnNotPermitted
;
3005 obj
= entry
->copyProperty(property_name
);
3007 return( kIOReturnNotFound
);
3009 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3012 return( kIOReturnNoMemory
);
3015 if( obj
->serialize( s
)) {
3016 len
= s
->getLength();
3017 *propertiesCnt
= len
;
3018 err
= copyoutkdata( s
->text(), len
, properties
);
3021 err
= kIOReturnUnsupported
;
3029 /* Routine io_registry_entry_get_property_recursively */
3030 kern_return_t
is_io_registry_entry_get_property_recursively(
3031 io_object_t registry_entry
,
3033 io_name_t property_name
,
3035 io_buf_ptr_t
*properties
,
3036 mach_msg_type_number_t
*propertiesCnt
)
3042 CHECK( IORegistryEntry
, registry_entry
, entry
);
3045 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3046 return kIOReturnNotPermitted
;
3049 obj
= entry
->copyProperty( property_name
,
3050 IORegistryEntry::getPlane( plane
), options
);
3052 return( kIOReturnNotFound
);
3054 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3057 return( kIOReturnNoMemory
);
3060 if( obj
->serialize( s
)) {
3061 len
= s
->getLength();
3062 *propertiesCnt
= len
;
3063 err
= copyoutkdata( s
->text(), len
, properties
);
3066 err
= kIOReturnUnsupported
;
3074 /* Routine io_registry_entry_get_properties */
3075 kern_return_t
is_io_registry_entry_get_properties(
3076 io_object_t registry_entry
,
3077 io_buf_ptr_t
*properties
,
3078 mach_msg_type_number_t
*propertiesCnt
)
3080 return (kIOReturnUnsupported
);
3085 struct GetPropertiesEditorRef
3088 IORegistryEntry
* entry
;
3089 OSCollection
* root
;
3092 static const OSMetaClassBase
*
3093 GetPropertiesEditor(void * reference
,
3095 OSCollection
* container
,
3096 const OSSymbol
* name
,
3097 const OSMetaClassBase
* value
)
3099 GetPropertiesEditorRef
* ref
= (typeof(ref
)) reference
;
3101 if (!ref
->root
) ref
->root
= container
;
3102 if (ref
->root
== container
)
3104 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy()))
3109 if (value
) value
->retain();
3113 #endif /* CONFIG_MACF */
3115 /* Routine io_registry_entry_get_properties */
3116 kern_return_t
is_io_registry_entry_get_properties_bin(
3117 io_object_t registry_entry
,
3118 io_buf_ptr_t
*properties
,
3119 mach_msg_type_number_t
*propertiesCnt
)
3121 kern_return_t err
= kIOReturnSuccess
;
3124 OSSerialize::Editor editor
= 0;
3127 CHECK(IORegistryEntry
, registry_entry
, entry
);
3130 GetPropertiesEditorRef ref
;
3131 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
))
3133 editor
= &GetPropertiesEditor
;
3135 ref
.cred
= kauth_cred_get();
3141 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
3142 if (!s
) return (kIOReturnNoMemory
);
3144 if (!entry
->serializeProperties(s
)) err
= kIOReturnUnsupported
;
3146 if (kIOReturnSuccess
== err
)
3148 len
= s
->getLength();
3149 *propertiesCnt
= len
;
3150 err
= copyoutkdata(s
->text(), len
, properties
);
3157 /* Routine io_registry_entry_get_property_bin */
3158 kern_return_t
is_io_registry_entry_get_property_bin(
3159 io_object_t registry_entry
,
3161 io_name_t property_name
,
3163 io_buf_ptr_t
*properties
,
3164 mach_msg_type_number_t
*propertiesCnt
)
3169 const OSSymbol
* sym
;
3171 CHECK( IORegistryEntry
, registry_entry
, entry
);
3174 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3175 return kIOReturnNotPermitted
;
3178 sym
= OSSymbol::withCString(property_name
);
3179 if (!sym
) return (kIOReturnNoMemory
);
3181 if (gIORegistryEntryPropertyKeysKey
== sym
)
3183 obj
= entry
->copyPropertyKeys();
3187 if ((kIORegistryIterateRecursively
& options
) && plane
[0])
3189 obj
= entry
->copyProperty(property_name
,
3190 IORegistryEntry::getPlane(plane
), options
);
3194 obj
= entry
->copyProperty(property_name
);
3196 if (obj
&& gIORemoveOnReadProperties
->containsObject(sym
)) entry
->removeProperty(sym
);
3200 if (!obj
) return (kIOReturnNotFound
);
3202 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
3205 return( kIOReturnNoMemory
);
3208 if( obj
->serialize( s
)) {
3209 len
= s
->getLength();
3210 *propertiesCnt
= len
;
3211 err
= copyoutkdata( s
->text(), len
, properties
);
3213 } else err
= kIOReturnUnsupported
;
3222 /* Routine io_registry_entry_set_properties */
3223 kern_return_t is_io_registry_entry_set_properties
3225 io_object_t registry_entry
,
3226 io_buf_ptr_t properties
,
3227 mach_msg_type_number_t propertiesCnt
,
3228 kern_return_t
* result
)
3234 vm_map_offset_t map_data
;
3236 CHECK( IORegistryEntry
, registry_entry
, entry
);
3238 if( propertiesCnt
> sizeof(io_struct_inband_t
) * 1024)
3239 return( kIOReturnMessageTooLarge
);
3241 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3242 data
= CAST_DOWN(vm_offset_t
, map_data
);
3244 if( KERN_SUCCESS
== err
) {
3246 FAKE_STACK_FRAME(entry
->getMetaClass());
3248 // must return success after vm_map_copyout() succeeds
3249 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3250 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3253 res
= kIOReturnBadArgument
;
3255 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
3256 registry_entry
, obj
))
3258 res
= kIOReturnNotPermitted
;
3263 res
= entry
->setProperties( obj
);
3269 FAKE_STACK_FRAME_END();
3278 /* Routine io_registry_entry_get_child_iterator */
3279 kern_return_t
is_io_registry_entry_get_child_iterator(
3280 io_object_t registry_entry
,
3282 io_object_t
*iterator
)
3284 CHECK( IORegistryEntry
, registry_entry
, entry
);
3286 *iterator
= entry
->getChildIterator(
3287 IORegistryEntry::getPlane( plane
));
3289 return( kIOReturnSuccess
);
3292 /* Routine io_registry_entry_get_parent_iterator */
3293 kern_return_t
is_io_registry_entry_get_parent_iterator(
3294 io_object_t registry_entry
,
3296 io_object_t
*iterator
)
3298 CHECK( IORegistryEntry
, registry_entry
, entry
);
3300 *iterator
= entry
->getParentIterator(
3301 IORegistryEntry::getPlane( plane
));
3303 return( kIOReturnSuccess
);
3306 /* Routine io_service_get_busy_state */
3307 kern_return_t
is_io_service_get_busy_state(
3308 io_object_t _service
,
3309 uint32_t *busyState
)
3311 CHECK( IOService
, _service
, service
);
3313 *busyState
= service
->getBusyState();
3315 return( kIOReturnSuccess
);
3318 /* Routine io_service_get_state */
3319 kern_return_t
is_io_service_get_state(
3320 io_object_t _service
,
3322 uint32_t *busy_state
,
3323 uint64_t *accumulated_busy_time
)
3325 CHECK( IOService
, _service
, service
);
3327 *state
= service
->getState();
3328 *busy_state
= service
->getBusyState();
3329 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
3331 return( kIOReturnSuccess
);
3334 /* Routine io_service_wait_quiet */
3335 kern_return_t
is_io_service_wait_quiet(
3336 io_object_t _service
,
3337 mach_timespec_t wait_time
)
3341 CHECK( IOService
, _service
, service
);
3343 timeoutNS
= wait_time
.tv_sec
;
3344 timeoutNS
*= kSecondScale
;
3345 timeoutNS
+= wait_time
.tv_nsec
;
3347 return( service
->waitQuiet(timeoutNS
) );
3350 /* Routine io_service_request_probe */
3351 kern_return_t
is_io_service_request_probe(
3352 io_object_t _service
,
3355 CHECK( IOService
, _service
, service
);
3357 return( service
->requestProbe( options
));
3360 /* Routine io_service_get_authorization_id */
3361 kern_return_t
is_io_service_get_authorization_id(
3362 io_object_t _service
,
3363 uint64_t *authorization_id
)
3367 CHECK( IOService
, _service
, service
);
3369 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3370 kIOClientPrivilegeAdministrator
);
3371 if( kIOReturnSuccess
!= kr
)
3374 *authorization_id
= service
->getAuthorizationID();
3379 /* Routine io_service_set_authorization_id */
3380 kern_return_t
is_io_service_set_authorization_id(
3381 io_object_t _service
,
3382 uint64_t authorization_id
)
3384 CHECK( IOService
, _service
, service
);
3386 return( service
->setAuthorizationID( authorization_id
) );
3389 /* Routine io_service_open_ndr */
3390 kern_return_t
is_io_service_open_extended(
3391 io_object_t _service
,
3393 uint32_t connect_type
,
3395 io_buf_ptr_t properties
,
3396 mach_msg_type_number_t propertiesCnt
,
3397 kern_return_t
* result
,
3398 io_object_t
*connection
)
3400 IOUserClient
* client
= 0;
3401 kern_return_t err
= KERN_SUCCESS
;
3402 IOReturn res
= kIOReturnSuccess
;
3403 OSDictionary
* propertiesDict
= 0;
3405 bool disallowAccess
;
3407 CHECK( IOService
, _service
, service
);
3409 if (!owningTask
) return (kIOReturnBadArgument
);
3410 assert(owningTask
== current_task());
3411 if (owningTask
!= current_task()) return (kIOReturnBadArgument
);
3415 if (properties
) return (kIOReturnUnsupported
);
3420 vm_map_offset_t map_data
;
3422 if( propertiesCnt
> sizeof(io_struct_inband_t
))
3423 return( kIOReturnMessageTooLarge
);
3425 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3427 data
= CAST_DOWN(vm_offset_t
, map_data
);
3428 if (KERN_SUCCESS
== err
)
3430 // must return success after vm_map_copyout() succeeds
3431 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3432 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3433 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3434 if (!propertiesDict
)
3436 res
= kIOReturnBadArgument
;
3441 if (kIOReturnSuccess
!= res
)
3445 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3448 if (!propertiesDict
)
3449 propertiesDict
= OSDictionary::withCapacity(4);
3450 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3454 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
3459 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
3460 connect_type
, propertiesDict
, &client
);
3463 propertiesDict
->release();
3465 if (res
== kIOReturnSuccess
)
3467 assert( OSDynamicCast(IOUserClient
, client
) );
3469 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
3470 client
->closed
= false;
3471 client
->lock
= IOLockAlloc();
3473 disallowAccess
= (crossEndian
3474 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
3475 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
3476 if (disallowAccess
) res
= kIOReturnUnsupported
;
3478 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
))
3479 res
= kIOReturnNotPermitted
;
3482 if (kIOReturnSuccess
== res
) res
= client
->registerOwner(owningTask
);
3484 if (kIOReturnSuccess
!= res
)
3486 IOStatisticsClientCall();
3487 client
->clientClose();
3492 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
3495 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
3496 creatorName
->release();
3498 client
->setTerminateDefer(service
, false);
3503 *connection
= client
;
3509 /* Routine io_service_close */
3510 kern_return_t
is_io_service_close(
3511 io_object_t connection
)
3514 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
3515 return( kIOReturnSuccess
);
3517 CHECK( IOUserClient
, connection
, client
);
3519 IOStatisticsClientCall();
3521 if (client
->sharedInstance
|| OSCompareAndSwap8(0, 1, &client
->closed
))
3523 IOLockLock(client
->lock
);
3524 client
->clientClose();
3525 IOLockUnlock(client
->lock
);
3529 IOLog("ignored is_io_service_close(0x%qx,%s)\n",
3530 client
->getRegistryEntryID(), client
->getName());
3533 return( kIOReturnSuccess
);
3536 /* Routine io_connect_get_service */
3537 kern_return_t
is_io_connect_get_service(
3538 io_object_t connection
,
3539 io_object_t
*service
)
3541 IOService
* theService
;
3543 CHECK( IOUserClient
, connection
, client
);
3545 theService
= client
->getService();
3547 theService
->retain();
3549 *service
= theService
;
3551 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
3554 /* Routine io_connect_set_notification_port */
3555 kern_return_t
is_io_connect_set_notification_port(
3556 io_object_t connection
,
3557 uint32_t notification_type
,
3562 CHECK( IOUserClient
, connection
, client
);
3564 IOStatisticsClientCall();
3565 IOLockLock(client
->lock
);
3566 ret
= client
->registerNotificationPort( port
, notification_type
,
3567 (io_user_reference_t
) reference
);
3568 IOLockUnlock(client
->lock
);
3572 /* Routine io_connect_set_notification_port */
3573 kern_return_t
is_io_connect_set_notification_port_64(
3574 io_object_t connection
,
3575 uint32_t notification_type
,
3577 io_user_reference_t reference
)
3580 CHECK( IOUserClient
, connection
, client
);
3582 IOStatisticsClientCall();
3583 IOLockLock(client
->lock
);
3584 ret
= client
->registerNotificationPort( port
, notification_type
,
3586 IOLockUnlock(client
->lock
);
3590 /* Routine io_connect_map_memory_into_task */
3591 kern_return_t is_io_connect_map_memory_into_task
3593 io_connect_t connection
,
3594 uint32_t memory_type
,
3596 mach_vm_address_t
*address
,
3597 mach_vm_size_t
*size
,
3604 CHECK( IOUserClient
, connection
, client
);
3606 if (!into_task
) return (kIOReturnBadArgument
);
3608 IOStatisticsClientCall();
3609 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
3612 *address
= map
->getAddress();
3614 *size
= map
->getSize();
3616 if( client
->sharedInstance
3617 || (into_task
!= current_task())) {
3618 // push a name out to the task owning the map,
3619 // so we can clean up maps
3620 mach_port_name_t name __unused
=
3621 IOMachPort::makeSendRightForTask(
3622 into_task
, map
, IKOT_IOKIT_OBJECT
);
3625 // keep it with the user client
3626 IOLockLock( gIOObjectPortLock
);
3627 if( 0 == client
->mappings
)
3628 client
->mappings
= OSSet::withCapacity(2);
3629 if( client
->mappings
)
3630 client
->mappings
->setObject( map
);
3631 IOLockUnlock( gIOObjectPortLock
);
3634 err
= kIOReturnSuccess
;
3637 err
= kIOReturnBadArgument
;
3642 /* Routine is_io_connect_map_memory */
3643 kern_return_t
is_io_connect_map_memory(
3644 io_object_t connect
,
3652 mach_vm_address_t address
;
3653 mach_vm_size_t size
;
3655 address
= SCALAR64(*mapAddr
);
3656 size
= SCALAR64(*mapSize
);
3658 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
3660 *mapAddr
= SCALAR32(address
);
3661 *mapSize
= SCALAR32(size
);
3668 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
3671 IOMemoryMap
* map
= 0;
3673 IOLockLock(gIOObjectPortLock
);
3675 iter
= OSCollectionIterator::withCollection(mappings
);
3678 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
3680 if(mem
== map
->getMemoryDescriptor())
3683 mappings
->removeObject(map
);
3690 IOLockUnlock(gIOObjectPortLock
);
3697 /* Routine io_connect_unmap_memory_from_task */
3698 kern_return_t is_io_connect_unmap_memory_from_task
3700 io_connect_t connection
,
3701 uint32_t memory_type
,
3703 mach_vm_address_t address
)
3706 IOOptionBits options
= 0;
3707 IOMemoryDescriptor
* memory
= 0;
3710 CHECK( IOUserClient
, connection
, client
);
3712 if (!from_task
) return (kIOReturnBadArgument
);
3714 IOStatisticsClientCall();
3715 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
3717 if( memory
&& (kIOReturnSuccess
== err
)) {
3719 options
= (options
& ~kIOMapUserOptionsMask
)
3720 | kIOMapAnywhere
| kIOMapReference
;
3722 map
= memory
->createMappingInTask( from_task
, address
, options
);
3726 IOLockLock( gIOObjectPortLock
);
3727 if( client
->mappings
)
3728 client
->mappings
->removeObject( map
);
3729 IOLockUnlock( gIOObjectPortLock
);
3731 mach_port_name_t name
= 0;
3732 if (from_task
!= current_task())
3733 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
3736 map
->userClientUnmap();
3737 err
= iokit_mod_send_right( from_task
, name
, -2 );
3738 err
= kIOReturnSuccess
;
3741 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
3742 if (from_task
== current_task())
3746 err
= kIOReturnBadArgument
;
3752 kern_return_t
is_io_connect_unmap_memory(
3753 io_object_t connect
,
3759 mach_vm_address_t address
;
3761 address
= SCALAR64(mapAddr
);
3763 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
3769 /* Routine io_connect_add_client */
3770 kern_return_t
is_io_connect_add_client(
3771 io_object_t connection
,
3772 io_object_t connect_to
)
3774 CHECK( IOUserClient
, connection
, client
);
3775 CHECK( IOUserClient
, connect_to
, to
);
3777 IOStatisticsClientCall();
3778 return( client
->connectClient( to
) );
3782 /* Routine io_connect_set_properties */
3783 kern_return_t
is_io_connect_set_properties(
3784 io_object_t connection
,
3785 io_buf_ptr_t properties
,
3786 mach_msg_type_number_t propertiesCnt
,
3787 kern_return_t
* result
)
3789 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
3792 /* Routine io_user_client_method */
3793 kern_return_t is_io_connect_method_var_output
3795 io_connect_t connection
,
3797 io_scalar_inband64_t scalar_input
,
3798 mach_msg_type_number_t scalar_inputCnt
,
3799 io_struct_inband_t inband_input
,
3800 mach_msg_type_number_t inband_inputCnt
,
3801 mach_vm_address_t ool_input
,
3802 mach_vm_size_t ool_input_size
,
3803 io_struct_inband_t inband_output
,
3804 mach_msg_type_number_t
*inband_outputCnt
,
3805 io_scalar_inband64_t scalar_output
,
3806 mach_msg_type_number_t
*scalar_outputCnt
,
3807 io_buf_ptr_t
*var_output
,
3808 mach_msg_type_number_t
*var_outputCnt
3811 CHECK( IOUserClient
, connection
, client
);
3813 IOExternalMethodArguments args
;
3815 IOMemoryDescriptor
* inputMD
= 0;
3816 OSObject
* structureVariableOutputData
= 0;
3818 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3819 args
.__reservedA
= 0;
3820 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3822 args
.selector
= selector
;
3824 args
.asyncWakePort
= MACH_PORT_NULL
;
3825 args
.asyncReference
= 0;
3826 args
.asyncReferenceCount
= 0;
3827 args
.structureVariableOutputData
= &structureVariableOutputData
;
3829 args
.scalarInput
= scalar_input
;
3830 args
.scalarInputCount
= scalar_inputCnt
;
3831 args
.structureInput
= inband_input
;
3832 args
.structureInputSize
= inband_inputCnt
;
3834 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
3837 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3838 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
3841 args
.structureInputDescriptor
= inputMD
;
3843 args
.scalarOutput
= scalar_output
;
3844 args
.scalarOutputCount
= *scalar_outputCnt
;
3845 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3846 args
.structureOutput
= inband_output
;
3847 args
.structureOutputSize
= *inband_outputCnt
;
3848 args
.structureOutputDescriptor
= NULL
;
3849 args
.structureOutputDescriptorSize
= 0;
3851 IOStatisticsClientCall();
3852 ret
= client
->externalMethod( selector
, &args
);
3854 *scalar_outputCnt
= args
.scalarOutputCount
;
3855 *inband_outputCnt
= args
.structureOutputSize
;
3857 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
))
3859 OSSerialize
* serialize
;
3863 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
)))
3865 len
= serialize
->getLength();
3866 *var_outputCnt
= len
;
3867 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
3869 else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
)))
3871 len
= data
->getLength();
3872 *var_outputCnt
= len
;
3873 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
3877 ret
= kIOReturnUnderrun
;
3883 if (structureVariableOutputData
)
3884 structureVariableOutputData
->release();
3889 /* Routine io_user_client_method */
3890 kern_return_t is_io_connect_method
3892 io_connect_t connection
,
3894 io_scalar_inband64_t scalar_input
,
3895 mach_msg_type_number_t scalar_inputCnt
,
3896 io_struct_inband_t inband_input
,
3897 mach_msg_type_number_t inband_inputCnt
,
3898 mach_vm_address_t ool_input
,
3899 mach_vm_size_t ool_input_size
,
3900 io_struct_inband_t inband_output
,
3901 mach_msg_type_number_t
*inband_outputCnt
,
3902 io_scalar_inband64_t scalar_output
,
3903 mach_msg_type_number_t
*scalar_outputCnt
,
3904 mach_vm_address_t ool_output
,
3905 mach_vm_size_t
*ool_output_size
3908 CHECK( IOUserClient
, connection
, client
);
3910 IOExternalMethodArguments args
;
3912 IOMemoryDescriptor
* inputMD
= 0;
3913 IOMemoryDescriptor
* outputMD
= 0;
3915 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3916 args
.__reservedA
= 0;
3917 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3919 args
.selector
= selector
;
3921 args
.asyncWakePort
= MACH_PORT_NULL
;
3922 args
.asyncReference
= 0;
3923 args
.asyncReferenceCount
= 0;
3924 args
.structureVariableOutputData
= 0;
3926 args
.scalarInput
= scalar_input
;
3927 args
.scalarInputCount
= scalar_inputCnt
;
3928 args
.structureInput
= inband_input
;
3929 args
.structureInputSize
= inband_inputCnt
;
3931 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
3932 if (ool_output
&& (*ool_output_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
3935 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3936 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
3939 args
.structureInputDescriptor
= inputMD
;
3941 args
.scalarOutput
= scalar_output
;
3942 args
.scalarOutputCount
= *scalar_outputCnt
;
3943 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3944 args
.structureOutput
= inband_output
;
3945 args
.structureOutputSize
= *inband_outputCnt
;
3947 if (ool_output
&& ool_output_size
)
3949 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3950 kIODirectionIn
, current_task());
3953 args
.structureOutputDescriptor
= outputMD
;
3954 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
3956 IOStatisticsClientCall();
3957 ret
= client
->externalMethod( selector
, &args
);
3959 *scalar_outputCnt
= args
.scalarOutputCount
;
3960 *inband_outputCnt
= args
.structureOutputSize
;
3961 *ool_output_size
= args
.structureOutputDescriptorSize
;
3966 outputMD
->release();
3971 /* Routine io_async_user_client_method */
3972 kern_return_t is_io_connect_async_method
3974 io_connect_t connection
,
3975 mach_port_t wake_port
,
3976 io_async_ref64_t reference
,
3977 mach_msg_type_number_t referenceCnt
,
3979 io_scalar_inband64_t scalar_input
,
3980 mach_msg_type_number_t scalar_inputCnt
,
3981 io_struct_inband_t inband_input
,
3982 mach_msg_type_number_t inband_inputCnt
,
3983 mach_vm_address_t ool_input
,
3984 mach_vm_size_t ool_input_size
,
3985 io_struct_inband_t inband_output
,
3986 mach_msg_type_number_t
*inband_outputCnt
,
3987 io_scalar_inband64_t scalar_output
,
3988 mach_msg_type_number_t
*scalar_outputCnt
,
3989 mach_vm_address_t ool_output
,
3990 mach_vm_size_t
* ool_output_size
3993 CHECK( IOUserClient
, connection
, client
);
3995 IOExternalMethodArguments args
;
3997 IOMemoryDescriptor
* inputMD
= 0;
3998 IOMemoryDescriptor
* outputMD
= 0;
4000 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4001 args
.__reservedA
= 0;
4002 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4004 reference
[0] = (io_user_reference_t
) wake_port
;
4005 if (vm_map_is_64bit(get_task_map(current_task())))
4006 reference
[0] |= kIOUCAsync64Flag
;
4008 args
.selector
= selector
;
4010 args
.asyncWakePort
= wake_port
;
4011 args
.asyncReference
= reference
;
4012 args
.asyncReferenceCount
= referenceCnt
;
4014 args
.structureVariableOutputData
= 0;
4016 args
.scalarInput
= scalar_input
;
4017 args
.scalarInputCount
= scalar_inputCnt
;
4018 args
.structureInput
= inband_input
;
4019 args
.structureInputSize
= inband_inputCnt
;
4021 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
4022 if (ool_output
&& (*ool_output_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
4025 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4026 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4029 args
.structureInputDescriptor
= inputMD
;
4031 args
.scalarOutput
= scalar_output
;
4032 args
.scalarOutputCount
= *scalar_outputCnt
;
4033 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4034 args
.structureOutput
= inband_output
;
4035 args
.structureOutputSize
= *inband_outputCnt
;
4039 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
4040 kIODirectionIn
, current_task());
4043 args
.structureOutputDescriptor
= outputMD
;
4044 args
.structureOutputDescriptorSize
= *ool_output_size
;
4046 IOStatisticsClientCall();
4047 ret
= client
->externalMethod( selector
, &args
);
4049 *inband_outputCnt
= args
.structureOutputSize
;
4050 *ool_output_size
= args
.structureOutputDescriptorSize
;
4055 outputMD
->release();
4060 /* Routine io_connect_method_scalarI_scalarO */
4061 kern_return_t
is_io_connect_method_scalarI_scalarO(
4062 io_object_t connect
,
4064 io_scalar_inband_t input
,
4065 mach_msg_type_number_t inputCount
,
4066 io_scalar_inband_t output
,
4067 mach_msg_type_number_t
* outputCount
)
4071 io_scalar_inband64_t _input
;
4072 io_scalar_inband64_t _output
;
4074 mach_msg_type_number_t struct_outputCnt
= 0;
4075 mach_vm_size_t ool_output_size
= 0;
4077 bzero(&_output
[0], sizeof(_output
));
4078 for (i
= 0; i
< inputCount
; i
++)
4079 _input
[i
] = SCALAR64(input
[i
]);
4081 err
= is_io_connect_method(connect
, index
,
4085 NULL
, &struct_outputCnt
,
4086 _output
, outputCount
,
4087 0, &ool_output_size
);
4089 for (i
= 0; i
< *outputCount
; i
++)
4090 output
[i
] = SCALAR32(_output
[i
]);
4095 kern_return_t
shim_io_connect_method_scalarI_scalarO(
4096 IOExternalMethod
* method
,
4098 const io_user_scalar_t
* input
,
4099 mach_msg_type_number_t inputCount
,
4100 io_user_scalar_t
* output
,
4101 mach_msg_type_number_t
* outputCount
)
4104 io_scalar_inband_t _output
;
4106 err
= kIOReturnBadArgument
;
4108 bzero(&_output
[0], sizeof(_output
));
4111 if( inputCount
!= method
->count0
)
4113 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4114 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4117 if( *outputCount
!= method
->count1
)
4119 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4120 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4124 func
= method
->func
;
4126 switch( inputCount
) {
4129 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4130 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4133 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4134 ARG32(input
[3]), ARG32(input
[4]),
4138 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4140 &_output
[0], &_output
[1] );
4143 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4144 &_output
[0], &_output
[1], &_output
[2] );
4147 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4148 &_output
[0], &_output
[1], &_output
[2],
4152 err
= (object
->*func
)( ARG32(input
[0]),
4153 &_output
[0], &_output
[1], &_output
[2],
4154 &_output
[3], &_output
[4] );
4157 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
4158 &_output
[3], &_output
[4], &_output
[5] );
4162 IOLog("%s: Bad method table\n", object
->getName());
4168 for (i
= 0; i
< *outputCount
; i
++)
4169 output
[i
] = SCALAR32(_output
[i
]);
4174 /* Routine io_async_method_scalarI_scalarO */
4175 kern_return_t
is_io_async_method_scalarI_scalarO(
4176 io_object_t connect
,
4177 mach_port_t wake_port
,
4178 io_async_ref_t reference
,
4179 mach_msg_type_number_t referenceCnt
,
4181 io_scalar_inband_t input
,
4182 mach_msg_type_number_t inputCount
,
4183 io_scalar_inband_t output
,
4184 mach_msg_type_number_t
* outputCount
)
4188 io_scalar_inband64_t _input
;
4189 io_scalar_inband64_t _output
;
4190 io_async_ref64_t _reference
;
4192 bzero(&_output
[0], sizeof(_output
));
4193 for (i
= 0; i
< referenceCnt
; i
++)
4194 _reference
[i
] = REF64(reference
[i
]);
4196 mach_msg_type_number_t struct_outputCnt
= 0;
4197 mach_vm_size_t ool_output_size
= 0;
4199 for (i
= 0; i
< inputCount
; i
++)
4200 _input
[i
] = SCALAR64(input
[i
]);
4202 err
= is_io_connect_async_method(connect
,
4203 wake_port
, _reference
, referenceCnt
,
4208 NULL
, &struct_outputCnt
,
4209 _output
, outputCount
,
4210 0, &ool_output_size
);
4212 for (i
= 0; i
< *outputCount
; i
++)
4213 output
[i
] = SCALAR32(_output
[i
]);
4217 /* Routine io_async_method_scalarI_structureO */
4218 kern_return_t
is_io_async_method_scalarI_structureO(
4219 io_object_t connect
,
4220 mach_port_t wake_port
,
4221 io_async_ref_t reference
,
4222 mach_msg_type_number_t referenceCnt
,
4224 io_scalar_inband_t input
,
4225 mach_msg_type_number_t inputCount
,
4226 io_struct_inband_t output
,
4227 mach_msg_type_number_t
* outputCount
)
4230 io_scalar_inband64_t _input
;
4231 io_async_ref64_t _reference
;
4233 for (i
= 0; i
< referenceCnt
; i
++)
4234 _reference
[i
] = REF64(reference
[i
]);
4236 mach_msg_type_number_t scalar_outputCnt
= 0;
4237 mach_vm_size_t ool_output_size
= 0;
4239 for (i
= 0; i
< inputCount
; i
++)
4240 _input
[i
] = SCALAR64(input
[i
]);
4242 return (is_io_connect_async_method(connect
,
4243 wake_port
, _reference
, referenceCnt
,
4248 output
, outputCount
,
4249 NULL
, &scalar_outputCnt
,
4250 0, &ool_output_size
));
4253 /* Routine io_async_method_scalarI_structureI */
4254 kern_return_t
is_io_async_method_scalarI_structureI(
4255 io_connect_t connect
,
4256 mach_port_t wake_port
,
4257 io_async_ref_t reference
,
4258 mach_msg_type_number_t referenceCnt
,
4260 io_scalar_inband_t input
,
4261 mach_msg_type_number_t inputCount
,
4262 io_struct_inband_t inputStruct
,
4263 mach_msg_type_number_t inputStructCount
)
4266 io_scalar_inband64_t _input
;
4267 io_async_ref64_t _reference
;
4269 for (i
= 0; i
< referenceCnt
; i
++)
4270 _reference
[i
] = REF64(reference
[i
]);
4272 mach_msg_type_number_t scalar_outputCnt
= 0;
4273 mach_msg_type_number_t inband_outputCnt
= 0;
4274 mach_vm_size_t ool_output_size
= 0;
4276 for (i
= 0; i
< inputCount
; i
++)
4277 _input
[i
] = SCALAR64(input
[i
]);
4279 return (is_io_connect_async_method(connect
,
4280 wake_port
, _reference
, referenceCnt
,
4283 inputStruct
, inputStructCount
,
4285 NULL
, &inband_outputCnt
,
4286 NULL
, &scalar_outputCnt
,
4287 0, &ool_output_size
));
4290 /* Routine io_async_method_structureI_structureO */
4291 kern_return_t
is_io_async_method_structureI_structureO(
4292 io_object_t connect
,
4293 mach_port_t wake_port
,
4294 io_async_ref_t reference
,
4295 mach_msg_type_number_t referenceCnt
,
4297 io_struct_inband_t input
,
4298 mach_msg_type_number_t inputCount
,
4299 io_struct_inband_t output
,
4300 mach_msg_type_number_t
* outputCount
)
4303 mach_msg_type_number_t scalar_outputCnt
= 0;
4304 mach_vm_size_t ool_output_size
= 0;
4305 io_async_ref64_t _reference
;
4307 for (i
= 0; i
< referenceCnt
; i
++)
4308 _reference
[i
] = REF64(reference
[i
]);
4310 return (is_io_connect_async_method(connect
,
4311 wake_port
, _reference
, referenceCnt
,
4316 output
, outputCount
,
4317 NULL
, &scalar_outputCnt
,
4318 0, &ool_output_size
));
4322 kern_return_t
shim_io_async_method_scalarI_scalarO(
4323 IOExternalAsyncMethod
* method
,
4325 mach_port_t asyncWakePort
,
4326 io_user_reference_t
* asyncReference
,
4327 uint32_t asyncReferenceCount
,
4328 const io_user_scalar_t
* input
,
4329 mach_msg_type_number_t inputCount
,
4330 io_user_scalar_t
* output
,
4331 mach_msg_type_number_t
* outputCount
)
4335 io_scalar_inband_t _output
;
4337 io_async_ref_t reference
;
4339 bzero(&_output
[0], sizeof(_output
));
4340 for (i
= 0; i
< asyncReferenceCount
; i
++)
4341 reference
[i
] = REF32(asyncReference
[i
]);
4343 err
= kIOReturnBadArgument
;
4347 if( inputCount
!= method
->count0
)
4349 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4350 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4353 if( *outputCount
!= method
->count1
)
4355 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4356 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4360 func
= method
->func
;
4362 switch( inputCount
) {
4365 err
= (object
->*func
)( reference
,
4366 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4367 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4370 err
= (object
->*func
)( reference
,
4371 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4372 ARG32(input
[3]), ARG32(input
[4]),
4376 err
= (object
->*func
)( reference
,
4377 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4379 &_output
[0], &_output
[1] );
4382 err
= (object
->*func
)( reference
,
4383 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4384 &_output
[0], &_output
[1], &_output
[2] );
4387 err
= (object
->*func
)( reference
,
4388 ARG32(input
[0]), ARG32(input
[1]),
4389 &_output
[0], &_output
[1], &_output
[2],
4393 err
= (object
->*func
)( reference
,
4395 &_output
[0], &_output
[1], &_output
[2],
4396 &_output
[3], &_output
[4] );
4399 err
= (object
->*func
)( reference
,
4400 &_output
[0], &_output
[1], &_output
[2],
4401 &_output
[3], &_output
[4], &_output
[5] );
4405 IOLog("%s: Bad method table\n", object
->getName());
4410 for (i
= 0; i
< *outputCount
; i
++)
4411 output
[i
] = SCALAR32(_output
[i
]);
4417 /* Routine io_connect_method_scalarI_structureO */
4418 kern_return_t
is_io_connect_method_scalarI_structureO(
4419 io_object_t connect
,
4421 io_scalar_inband_t input
,
4422 mach_msg_type_number_t inputCount
,
4423 io_struct_inband_t output
,
4424 mach_msg_type_number_t
* outputCount
)
4427 io_scalar_inband64_t _input
;
4429 mach_msg_type_number_t scalar_outputCnt
= 0;
4430 mach_vm_size_t ool_output_size
= 0;
4432 for (i
= 0; i
< inputCount
; i
++)
4433 _input
[i
] = SCALAR64(input
[i
]);
4435 return (is_io_connect_method(connect
, index
,
4439 output
, outputCount
,
4440 NULL
, &scalar_outputCnt
,
4441 0, &ool_output_size
));
4444 kern_return_t
shim_io_connect_method_scalarI_structureO(
4446 IOExternalMethod
* method
,
4448 const io_user_scalar_t
* input
,
4449 mach_msg_type_number_t inputCount
,
4450 io_struct_inband_t output
,
4451 IOByteCount
* outputCount
)
4456 err
= kIOReturnBadArgument
;
4459 if( inputCount
!= method
->count0
)
4461 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4462 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4465 if( (kIOUCVariableStructureSize
!= method
->count1
)
4466 && (*outputCount
!= method
->count1
))
4468 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
);
4469 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4473 func
= method
->func
;
4475 switch( inputCount
) {
4478 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4479 ARG32(input
[3]), ARG32(input
[4]),
4483 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4485 output
, (void *)outputCount
);
4488 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4489 output
, (void *)outputCount
, 0 );
4492 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4493 output
, (void *)outputCount
, 0, 0 );
4496 err
= (object
->*func
)( ARG32(input
[0]),
4497 output
, (void *)outputCount
, 0, 0, 0 );
4500 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
4504 IOLog("%s: Bad method table\n", object
->getName());
4513 kern_return_t
shim_io_async_method_scalarI_structureO(
4514 IOExternalAsyncMethod
* method
,
4516 mach_port_t asyncWakePort
,
4517 io_user_reference_t
* asyncReference
,
4518 uint32_t asyncReferenceCount
,
4519 const io_user_scalar_t
* input
,
4520 mach_msg_type_number_t inputCount
,
4521 io_struct_inband_t output
,
4522 mach_msg_type_number_t
* outputCount
)
4527 io_async_ref_t reference
;
4529 for (i
= 0; i
< asyncReferenceCount
; i
++)
4530 reference
[i
] = REF32(asyncReference
[i
]);
4532 err
= kIOReturnBadArgument
;
4534 if( inputCount
!= method
->count0
)
4536 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4537 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4540 if( (kIOUCVariableStructureSize
!= method
->count1
)
4541 && (*outputCount
!= method
->count1
))
4543 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
);
4544 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4548 func
= method
->func
;
4550 switch( inputCount
) {
4553 err
= (object
->*func
)( reference
,
4554 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4555 ARG32(input
[3]), ARG32(input
[4]),
4559 err
= (object
->*func
)( reference
,
4560 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4562 output
, (void *)outputCount
);
4565 err
= (object
->*func
)( reference
,
4566 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4567 output
, (void *)outputCount
, 0 );
4570 err
= (object
->*func
)( reference
,
4571 ARG32(input
[0]), ARG32(input
[1]),
4572 output
, (void *)outputCount
, 0, 0 );
4575 err
= (object
->*func
)( reference
,
4577 output
, (void *)outputCount
, 0, 0, 0 );
4580 err
= (object
->*func
)( reference
,
4581 output
, (void *)outputCount
, 0, 0, 0, 0 );
4585 IOLog("%s: Bad method table\n", object
->getName());
4593 /* Routine io_connect_method_scalarI_structureI */
4594 kern_return_t
is_io_connect_method_scalarI_structureI(
4595 io_connect_t connect
,
4597 io_scalar_inband_t input
,
4598 mach_msg_type_number_t inputCount
,
4599 io_struct_inband_t inputStruct
,
4600 mach_msg_type_number_t inputStructCount
)
4603 io_scalar_inband64_t _input
;
4605 mach_msg_type_number_t scalar_outputCnt
= 0;
4606 mach_msg_type_number_t inband_outputCnt
= 0;
4607 mach_vm_size_t ool_output_size
= 0;
4609 for (i
= 0; i
< inputCount
; i
++)
4610 _input
[i
] = SCALAR64(input
[i
]);
4612 return (is_io_connect_method(connect
, index
,
4614 inputStruct
, inputStructCount
,
4616 NULL
, &inband_outputCnt
,
4617 NULL
, &scalar_outputCnt
,
4618 0, &ool_output_size
));
4621 kern_return_t
shim_io_connect_method_scalarI_structureI(
4622 IOExternalMethod
* method
,
4624 const io_user_scalar_t
* input
,
4625 mach_msg_type_number_t inputCount
,
4626 io_struct_inband_t inputStruct
,
4627 mach_msg_type_number_t inputStructCount
)
4630 IOReturn err
= kIOReturnBadArgument
;
4634 if (inputCount
!= method
->count0
)
4636 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4637 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4640 if( (kIOUCVariableStructureSize
!= method
->count1
)
4641 && (inputStructCount
!= method
->count1
))
4643 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
);
4644 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
4648 func
= method
->func
;
4650 switch( inputCount
) {
4653 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4654 ARG32(input
[3]), ARG32(input
[4]),
4658 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
4660 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4663 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4664 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4668 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4669 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4673 err
= (object
->*func
)( ARG32(input
[0]),
4674 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4678 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
4683 IOLog("%s: Bad method table\n", object
->getName());
4691 kern_return_t
shim_io_async_method_scalarI_structureI(
4692 IOExternalAsyncMethod
* method
,
4694 mach_port_t asyncWakePort
,
4695 io_user_reference_t
* asyncReference
,
4696 uint32_t asyncReferenceCount
,
4697 const io_user_scalar_t
* input
,
4698 mach_msg_type_number_t inputCount
,
4699 io_struct_inband_t inputStruct
,
4700 mach_msg_type_number_t inputStructCount
)
4704 IOReturn err
= kIOReturnBadArgument
;
4705 io_async_ref_t reference
;
4707 for (i
= 0; i
< asyncReferenceCount
; i
++)
4708 reference
[i
] = REF32(asyncReference
[i
]);
4712 if (inputCount
!= method
->count0
)
4714 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4715 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4718 if( (kIOUCVariableStructureSize
!= method
->count1
)
4719 && (inputStructCount
!= method
->count1
))
4721 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
);
4722 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
4726 func
= method
->func
;
4728 switch( inputCount
) {
4731 err
= (object
->*func
)( reference
,
4732 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4733 ARG32(input
[3]), ARG32(input
[4]),
4737 err
= (object
->*func
)( reference
,
4738 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4740 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4743 err
= (object
->*func
)( reference
,
4744 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4745 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4749 err
= (object
->*func
)( reference
,
4750 ARG32(input
[0]), ARG32(input
[1]),
4751 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4755 err
= (object
->*func
)( reference
,
4757 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4761 err
= (object
->*func
)( reference
,
4762 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4767 IOLog("%s: Bad method table\n", object
->getName());
4775 /* Routine io_connect_method_structureI_structureO */
4776 kern_return_t
is_io_connect_method_structureI_structureO(
4777 io_object_t connect
,
4779 io_struct_inband_t input
,
4780 mach_msg_type_number_t inputCount
,
4781 io_struct_inband_t output
,
4782 mach_msg_type_number_t
* outputCount
)
4784 mach_msg_type_number_t scalar_outputCnt
= 0;
4785 mach_vm_size_t ool_output_size
= 0;
4787 return (is_io_connect_method(connect
, index
,
4791 output
, outputCount
,
4792 NULL
, &scalar_outputCnt
,
4793 0, &ool_output_size
));
4796 kern_return_t
shim_io_connect_method_structureI_structureO(
4797 IOExternalMethod
* method
,
4799 io_struct_inband_t input
,
4800 mach_msg_type_number_t inputCount
,
4801 io_struct_inband_t output
,
4802 IOByteCount
* outputCount
)
4805 IOReturn err
= kIOReturnBadArgument
;
4809 if( (kIOUCVariableStructureSize
!= method
->count0
)
4810 && (inputCount
!= method
->count0
))
4812 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
);
4813 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4816 if( (kIOUCVariableStructureSize
!= method
->count1
)
4817 && (*outputCount
!= method
->count1
))
4819 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
);
4820 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4824 func
= method
->func
;
4826 if( method
->count1
) {
4827 if( method
->count0
) {
4828 err
= (object
->*func
)( input
, output
,
4829 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4831 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
4834 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4843 kern_return_t
shim_io_async_method_structureI_structureO(
4844 IOExternalAsyncMethod
* method
,
4846 mach_port_t asyncWakePort
,
4847 io_user_reference_t
* asyncReference
,
4848 uint32_t asyncReferenceCount
,
4849 io_struct_inband_t input
,
4850 mach_msg_type_number_t inputCount
,
4851 io_struct_inband_t output
,
4852 mach_msg_type_number_t
* outputCount
)
4857 io_async_ref_t reference
;
4859 for (i
= 0; i
< asyncReferenceCount
; i
++)
4860 reference
[i
] = REF32(asyncReference
[i
]);
4862 err
= kIOReturnBadArgument
;
4865 if( (kIOUCVariableStructureSize
!= method
->count0
)
4866 && (inputCount
!= method
->count0
))
4868 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
);
4869 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4872 if( (kIOUCVariableStructureSize
!= method
->count1
)
4873 && (*outputCount
!= method
->count1
))
4875 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
);
4876 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4880 func
= method
->func
;
4882 if( method
->count1
) {
4883 if( method
->count0
) {
4884 err
= (object
->*func
)( reference
,
4886 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4888 err
= (object
->*func
)( reference
,
4889 output
, outputCount
, 0, 0, 0, 0 );
4892 err
= (object
->*func
)( reference
,
4893 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4902 bool gIOKextdClearedBusy
= false;
4905 /* Routine io_catalog_send_data */
4906 kern_return_t
is_io_catalog_send_data(
4907 mach_port_t master_port
,
4909 io_buf_ptr_t inData
,
4910 mach_msg_type_number_t inDataCount
,
4911 kern_return_t
* result
)
4914 return kIOReturnNotPrivileged
;
4915 #else /* NO_KEXTD */
4918 kern_return_t kr
= kIOReturnError
;
4920 //printf("io_catalog_send_data called. flag: %d\n", flag);
4922 if( master_port
!= master_device_port
)
4923 return kIOReturnNotPrivileged
;
4925 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
4926 flag
!= kIOCatalogKextdActive
&&
4927 flag
!= kIOCatalogKextdFinishedLaunching
) &&
4928 ( !inData
|| !inDataCount
) )
4930 return kIOReturnBadArgument
;
4933 if (!IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management"))
4935 OSString
* taskName
= IOCopyLogNameForPID(proc_selfpid());
4936 IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName
? taskName
->getCStringNoCopy() : "");
4937 OSSafeReleaseNULL(taskName
);
4938 // For now, fake success to not break applications relying on this function succeeding.
4939 // See <rdar://problem/32554970> for more details.
4940 return kIOReturnSuccess
;
4944 vm_map_offset_t map_data
;
4946 if( inDataCount
> sizeof(io_struct_inband_t
) * 1024)
4947 return( kIOReturnMessageTooLarge
);
4949 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
4950 data
= CAST_DOWN(vm_offset_t
, map_data
);
4952 if( kr
!= KERN_SUCCESS
)
4955 // must return success after vm_map_copyout() succeeds
4958 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
4959 vm_deallocate( kernel_map
, data
, inDataCount
);
4961 *result
= kIOReturnNoMemory
;
4962 return( KERN_SUCCESS
);
4968 case kIOCatalogResetDrivers
:
4969 case kIOCatalogResetDriversNoMatch
: {
4972 array
= OSDynamicCast(OSArray
, obj
);
4974 if ( !gIOCatalogue
->resetAndAddDrivers(array
,
4975 flag
== kIOCatalogResetDrivers
) ) {
4977 kr
= kIOReturnError
;
4980 kr
= kIOReturnBadArgument
;
4985 case kIOCatalogAddDrivers
:
4986 case kIOCatalogAddDriversNoMatch
: {
4989 array
= OSDynamicCast(OSArray
, obj
);
4991 if ( !gIOCatalogue
->addDrivers( array
,
4992 flag
== kIOCatalogAddDrivers
) ) {
4993 kr
= kIOReturnError
;
4997 kr
= kIOReturnBadArgument
;
5002 case kIOCatalogRemoveDrivers
:
5003 case kIOCatalogRemoveDriversNoMatch
: {
5004 OSDictionary
* dict
;
5006 dict
= OSDynamicCast(OSDictionary
, obj
);
5008 if ( !gIOCatalogue
->removeDrivers( dict
,
5009 flag
== kIOCatalogRemoveDrivers
) ) {
5010 kr
= kIOReturnError
;
5014 kr
= kIOReturnBadArgument
;
5019 case kIOCatalogStartMatching
: {
5020 OSDictionary
* dict
;
5022 dict
= OSDynamicCast(OSDictionary
, obj
);
5024 if ( !gIOCatalogue
->startMatching( dict
) ) {
5025 kr
= kIOReturnError
;
5029 kr
= kIOReturnBadArgument
;
5034 case kIOCatalogRemoveKernelLinker
:
5035 kr
= KERN_NOT_SUPPORTED
;
5038 case kIOCatalogKextdActive
:
5040 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
5041 OSKext::setKextdActive();
5043 /* Dump all nonloaded startup extensions; kextd will now send them
5046 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
5048 kr
= kIOReturnSuccess
;
5051 case kIOCatalogKextdFinishedLaunching
: {
5053 if (!gIOKextdClearedBusy
) {
5054 IOService
* serviceRoot
= IOService::getServiceRoot();
5056 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
5057 serviceRoot
->adjustBusy(-1);
5058 gIOKextdClearedBusy
= true;
5062 kr
= kIOReturnSuccess
;
5067 kr
= kIOReturnBadArgument
;
5071 if (obj
) obj
->release();
5074 return( KERN_SUCCESS
);
5075 #endif /* NO_KEXTD */
5078 /* Routine io_catalog_terminate */
5079 kern_return_t
is_io_catalog_terminate(
5080 mach_port_t master_port
,
5086 if( master_port
!= master_device_port
)
5087 return kIOReturnNotPrivileged
;
5089 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
5090 kIOClientPrivilegeAdministrator
);
5091 if( kIOReturnSuccess
!= kr
)
5095 #if !defined(SECURE_KERNEL)
5096 case kIOCatalogServiceTerminate
:
5098 IOService
* service
;
5100 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
5101 kIORegistryIterateRecursively
);
5103 return kIOReturnNoMemory
;
5107 while( (service
= (IOService
*)iter
->getNextObject()) ) {
5108 if( service
->metaCast(name
)) {
5109 if ( !service
->terminate( kIOServiceRequired
5110 | kIOServiceSynchronous
) ) {
5111 kr
= kIOReturnUnsupported
;
5116 } while( !service
&& !iter
->isValid());
5120 case kIOCatalogModuleUnload
:
5121 case kIOCatalogModuleTerminate
:
5122 kr
= gIOCatalogue
->terminateDriversForModule(name
,
5123 flag
== kIOCatalogModuleUnload
);
5128 kr
= kIOReturnBadArgument
;
5135 /* Routine io_catalog_get_data */
5136 kern_return_t
is_io_catalog_get_data(
5137 mach_port_t master_port
,
5139 io_buf_ptr_t
*outData
,
5140 mach_msg_type_number_t
*outDataCount
)
5142 kern_return_t kr
= kIOReturnSuccess
;
5145 if( master_port
!= master_device_port
)
5146 return kIOReturnNotPrivileged
;
5148 //printf("io_catalog_get_data called. flag: %d\n", flag);
5150 s
= OSSerialize::withCapacity(4096);
5152 return kIOReturnNoMemory
;
5154 kr
= gIOCatalogue
->serializeData(flag
, s
);
5156 if ( kr
== kIOReturnSuccess
) {
5161 size
= s
->getLength();
5162 kr
= vm_allocate_kernel(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
, VM_KERN_MEMORY_IOKIT
);
5163 if ( kr
== kIOReturnSuccess
) {
5164 bcopy(s
->text(), (void *)data
, size
);
5165 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
5166 (vm_map_size_t
)size
, true, ©
);
5167 *outData
= (char *)copy
;
5168 *outDataCount
= size
;
5177 /* Routine io_catalog_get_gen_count */
5178 kern_return_t
is_io_catalog_get_gen_count(
5179 mach_port_t master_port
,
5182 if( master_port
!= master_device_port
)
5183 return kIOReturnNotPrivileged
;
5185 //printf("io_catalog_get_gen_count called.\n");
5188 return kIOReturnBadArgument
;
5190 *genCount
= gIOCatalogue
->getGenerationCount();
5192 return kIOReturnSuccess
;
5195 /* Routine io_catalog_module_loaded.
5196 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
5198 kern_return_t
is_io_catalog_module_loaded(
5199 mach_port_t master_port
,
5202 if( master_port
!= master_device_port
)
5203 return kIOReturnNotPrivileged
;
5205 //printf("io_catalog_module_loaded called. name %s\n", name);
5208 return kIOReturnBadArgument
;
5210 gIOCatalogue
->moduleHasLoaded(name
);
5212 return kIOReturnSuccess
;
5215 kern_return_t
is_io_catalog_reset(
5216 mach_port_t master_port
,
5219 if( master_port
!= master_device_port
)
5220 return kIOReturnNotPrivileged
;
5223 case kIOCatalogResetDefault
:
5224 gIOCatalogue
->reset();
5228 return kIOReturnBadArgument
;
5231 return kIOReturnSuccess
;
5234 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
5236 kern_return_t result
= kIOReturnBadArgument
;
5237 IOUserClient
*userClient
;
5239 if ((userClient
= OSDynamicCast(IOUserClient
,
5240 iokit_lookup_connect_ref_current_task((OSObject
*)(args
->userClientRef
))))) {
5241 IOExternalTrap
*trap
;
5242 IOService
*target
= NULL
;
5244 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
5246 if (trap
&& target
) {
5252 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
5256 iokit_remove_connect_reference(userClient
);
5264 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
5265 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
5269 IOByteCount structureOutputSize
;
5274 count
= dispatch
->checkScalarInputCount
;
5275 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
5277 return (kIOReturnBadArgument
);
5280 count
= dispatch
->checkStructureInputSize
;
5281 if ((kIOUCVariableStructureSize
!= count
)
5282 && (count
!= ((args
->structureInputDescriptor
)
5283 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
5285 return (kIOReturnBadArgument
);
5288 count
= dispatch
->checkScalarOutputCount
;
5289 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
5291 return (kIOReturnBadArgument
);
5294 count
= dispatch
->checkStructureOutputSize
;
5295 if ((kIOUCVariableStructureSize
!= count
)
5296 && (count
!= ((args
->structureOutputDescriptor
)
5297 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
5299 return (kIOReturnBadArgument
);
5302 if (dispatch
->function
)
5303 err
= (*dispatch
->function
)(target
, reference
, args
);
5305 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
5311 // pre-Leopard API's don't do ool structs
5312 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
5314 err
= kIOReturnIPCError
;
5318 structureOutputSize
= args
->structureOutputSize
;
5320 if (args
->asyncWakePort
)
5322 IOExternalAsyncMethod
* method
;
5324 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
)
5325 return (kIOReturnUnsupported
);
5327 if (kIOUCForegroundOnly
& method
->flags
)
5329 if (task_is_gpu_denied(current_task()))
5330 return (kIOReturnNotPermitted
);
5333 switch (method
->flags
& kIOUCTypeMask
)
5335 case kIOUCScalarIStructI
:
5336 err
= shim_io_async_method_scalarI_structureI( method
, object
,
5337 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5338 args
->scalarInput
, args
->scalarInputCount
,
5339 (char *)args
->structureInput
, args
->structureInputSize
);
5342 case kIOUCScalarIScalarO
:
5343 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
5344 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5345 args
->scalarInput
, args
->scalarInputCount
,
5346 args
->scalarOutput
, &args
->scalarOutputCount
);
5349 case kIOUCScalarIStructO
:
5350 err
= shim_io_async_method_scalarI_structureO( method
, object
,
5351 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5352 args
->scalarInput
, args
->scalarInputCount
,
5353 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5357 case kIOUCStructIStructO
:
5358 err
= shim_io_async_method_structureI_structureO( method
, object
,
5359 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5360 (char *)args
->structureInput
, args
->structureInputSize
,
5361 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5365 err
= kIOReturnBadArgument
;
5371 IOExternalMethod
* method
;
5373 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
)
5374 return (kIOReturnUnsupported
);
5376 if (kIOUCForegroundOnly
& method
->flags
)
5378 if (task_is_gpu_denied(current_task()))
5379 return (kIOReturnNotPermitted
);
5382 switch (method
->flags
& kIOUCTypeMask
)
5384 case kIOUCScalarIStructI
:
5385 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
5386 args
->scalarInput
, args
->scalarInputCount
,
5387 (char *) args
->structureInput
, args
->structureInputSize
);
5390 case kIOUCScalarIScalarO
:
5391 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
5392 args
->scalarInput
, args
->scalarInputCount
,
5393 args
->scalarOutput
, &args
->scalarOutputCount
);
5396 case kIOUCScalarIStructO
:
5397 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
5398 args
->scalarInput
, args
->scalarInputCount
,
5399 (char *) args
->structureOutput
, &structureOutputSize
);
5403 case kIOUCStructIStructO
:
5404 err
= shim_io_connect_method_structureI_structureO( method
, object
,
5405 (char *) args
->structureInput
, args
->structureInputSize
,
5406 (char *) args
->structureOutput
, &structureOutputSize
);
5410 err
= kIOReturnBadArgument
;
5415 args
->structureOutputSize
= structureOutputSize
;
5421 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
5422 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
5424 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
5425 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
5427 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
5428 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
5429 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
5430 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
5431 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
5432 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
5433 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
5434 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
5435 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
5436 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
5437 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
5438 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
5439 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
5440 OSMetaClassDefineReservedUnused(IOUserClient
, 15);