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/IODeviceTreeSupport.h>
44 #include <IOKit/system.h>
45 #include <libkern/OSDebug.h>
47 #include <sys/kauth.h>
48 #include <sys/codesign.h>
55 #include <security/mac_framework.h>
57 #include <sys/kauth.h>
61 #endif /* CONFIG_MACF */
63 #include <IOKit/assert.h>
65 #include "IOServicePrivate.h"
66 #include "IOKitKernelInternal.h"
68 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
69 #define SCALAR32(x) ((uint32_t )x)
70 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
71 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
72 #define REF32(x) ((int)(x))
76 kIOUCAsync0Flags
= 3ULL,
77 kIOUCAsync64Flag
= 1ULL,
78 kIOUCAsyncErrorLoggedFlag
= 2ULL
83 #define IOStatisticsRegisterCounter() \
85 reserved->counter = IOStatistics::registerUserClient(this); \
88 #define IOStatisticsUnregisterCounter() \
91 IOStatistics::unregisterUserClient(reserved->counter); \
94 #define IOStatisticsClientCall() \
96 IOStatistics::countUserClientCall(client); \
101 #define IOStatisticsRegisterCounter()
102 #define IOStatisticsUnregisterCounter()
103 #define IOStatisticsClientCall()
105 #endif /* IOKITSTATS */
107 #if DEVELOPMENT || DEBUG
109 #define FAKE_STACK_FRAME(a) \
110 const void ** __frameptr; \
111 const void * __retaddr; \
112 __frameptr = (typeof(__frameptr)) __builtin_frame_address(0); \
113 __retaddr = __frameptr[1]; \
116 #define FAKE_STACK_FRAME_END() \
117 __frameptr[1] = __retaddr;
119 #else /* DEVELOPMENT || DEBUG */
121 #define FAKE_STACK_FRAME(a)
122 #define FAKE_STACK_FRAME_END()
124 #endif /* DEVELOPMENT || DEBUG */
126 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
130 #include <mach/mach_traps.h>
131 #include <vm/vm_map.h>
135 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
137 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
139 class IOMachPort
: public OSObject
141 OSDeclareDefaultStructors(IOMachPort
)
148 static IOMachPort
* portForObject( OSObject
* obj
,
149 ipc_kobject_type_t type
);
150 static bool noMoreSendersForObject( OSObject
* obj
,
151 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
152 static void releasePortForObject( OSObject
* obj
,
153 ipc_kobject_type_t type
);
154 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
156 static OSDictionary
* dictForType( ipc_kobject_type_t type
);
158 static mach_port_name_t
makeSendRightForTask( task_t task
,
159 io_object_t obj
, ipc_kobject_type_t type
);
161 virtual void free() APPLE_KEXT_OVERRIDE
;
164 #define super OSObject
165 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
)
167 static IOLock
* gIOObjectPortLock
;
169 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
171 // not in dictForType() for debugging ease
172 static OSDictionary
* gIOObjectPorts
;
173 static OSDictionary
* gIOConnectPorts
;
174 static OSDictionary
* gIOIdentifierPorts
;
176 OSDictionary
* IOMachPort::dictForType( ipc_kobject_type_t type
)
178 OSDictionary
** dict
;
182 case IKOT_IOKIT_OBJECT
:
183 dict
= &gIOObjectPorts
;
185 case IKOT_IOKIT_CONNECT
:
186 dict
= &gIOConnectPorts
;
188 case IKOT_IOKIT_IDENT
:
189 dict
= &gIOIdentifierPorts
;
192 panic("dictForType %d", type
);
198 *dict
= OSDictionary::withCapacity( 1 );
203 IOMachPort
* IOMachPort::portForObject ( OSObject
* obj
,
204 ipc_kobject_type_t type
)
206 IOMachPort
* inst
= 0;
209 IOTakeLock( gIOObjectPortLock
);
213 dict
= dictForType( type
);
217 if( (inst
= (IOMachPort
*)
218 dict
->getObject( (const OSSymbol
*) obj
))) {
224 inst
= new IOMachPort
;
225 if( inst
&& !inst
->init()) {
230 inst
->port
= iokit_alloc_object_port( obj
, type
);
233 dict
->setObject( (const OSSymbol
*) obj
, inst
);
243 IOUnlock( gIOObjectPortLock
);
248 bool IOMachPort::noMoreSendersForObject( OSObject
* obj
,
249 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
252 IOMachPort
* machPort
;
254 bool destroyed
= true;
256 IOTakeLock( gIOObjectPortLock
);
258 if( (dict
= dictForType( type
))) {
261 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
263 destroyed
= (machPort
->mscount
<= *mscount
);
264 if (!destroyed
) *mscount
= machPort
->mscount
;
267 if ((IKOT_IOKIT_CONNECT
== type
) && (uc
= OSDynamicCast(IOUserClient
, obj
)))
271 dict
->removeObject( (const OSSymbol
*) obj
);
277 IOUnlock( gIOObjectPortLock
);
282 void IOMachPort::releasePortForObject( OSObject
* obj
,
283 ipc_kobject_type_t type
)
286 IOMachPort
* machPort
;
288 assert(IKOT_IOKIT_CONNECT
!= type
);
290 IOTakeLock( gIOObjectPortLock
);
292 if( (dict
= dictForType( type
))) {
294 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
295 if( machPort
&& !machPort
->holdDestroy
)
296 dict
->removeObject( (const OSSymbol
*) obj
);
300 IOUnlock( gIOObjectPortLock
);
303 void IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
306 IOMachPort
* machPort
;
308 IOLockLock( gIOObjectPortLock
);
310 if( (dict
= dictForType( type
))) {
311 machPort
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
313 machPort
->holdDestroy
= true;
316 IOLockUnlock( gIOObjectPortLock
);
319 void IOUserClient::destroyUserReferences( OSObject
* obj
)
321 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
324 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
328 IOTakeLock( gIOObjectPortLock
);
331 if( (dict
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT
)))
334 port
= (IOMachPort
*) dict
->getObject( (const OSSymbol
*) obj
);
338 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
343 dict
->setObject((const OSSymbol
*) uc
->mappings
, port
);
344 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
346 uc
->mappings
->release();
350 dict
->removeObject( (const OSSymbol
*) obj
);
354 IOUnlock( gIOObjectPortLock
);
357 mach_port_name_t
IOMachPort::makeSendRightForTask( task_t task
,
358 io_object_t obj
, ipc_kobject_type_t type
)
360 return( iokit_make_send_right( task
, obj
, type
));
363 void IOMachPort::free( void )
366 iokit_destroy_object_port( port
);
370 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
372 class IOUserIterator
: public OSIterator
374 OSDeclareDefaultStructors(IOUserIterator
)
376 OSObject
* userIteratorObject
;
379 static IOUserIterator
* withIterator(OSIterator
* iter
);
380 virtual bool init( void ) APPLE_KEXT_OVERRIDE
;
381 virtual void free() APPLE_KEXT_OVERRIDE
;
383 virtual void reset() APPLE_KEXT_OVERRIDE
;
384 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
385 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
388 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
390 class IOUserNotification
: public IOUserIterator
392 OSDeclareDefaultStructors(IOUserNotification
)
394 #define holdNotify userIteratorObject
398 virtual void free() APPLE_KEXT_OVERRIDE
;
400 virtual void setNotification( IONotifier
* obj
);
402 virtual void reset() APPLE_KEXT_OVERRIDE
;
403 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
406 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
408 OSDefineMetaClassAndStructors( IOUserIterator
, OSIterator
)
411 IOUserIterator::withIterator(OSIterator
* iter
)
415 if (!iter
) return (0);
417 me
= new IOUserIterator
;
418 if (me
&& !me
->init())
424 me
->userIteratorObject
= iter
;
430 IOUserIterator::init( void )
432 if (!OSObject::init()) return (false);
434 lock
= IOLockAlloc();
442 IOUserIterator::free()
444 if (userIteratorObject
) userIteratorObject
->release();
445 if (lock
) IOLockFree(lock
);
450 IOUserIterator::reset()
453 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
454 ((OSIterator
*)userIteratorObject
)->reset();
459 IOUserIterator::isValid()
464 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
465 ret
= ((OSIterator
*)userIteratorObject
)->isValid();
472 IOUserIterator::getNextObject()
477 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
478 ret
= ((OSIterator
*)userIteratorObject
)->getNextObject();
484 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
487 // functions called from osfmk/device/iokit_rpc.c
490 iokit_add_reference( io_object_t obj
, ipc_kobject_type_t type
)
496 if ((IKOT_IOKIT_CONNECT
== type
)
497 && (uc
= OSDynamicCast(IOUserClient
, obj
)))
499 OSIncrementAtomic(&uc
->__ipc
);
506 iokit_remove_reference( io_object_t obj
)
513 iokit_remove_connect_reference( io_object_t obj
)
516 bool finalize
= false;
520 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
522 if (1 == OSDecrementAtomic(&uc
->__ipc
) && uc
->isInactive())
524 IOLockLock(gIOObjectPortLock
);
525 if ((finalize
= uc
->__ipcFinal
)) uc
->__ipcFinal
= false;
526 IOLockUnlock(gIOObjectPortLock
);
528 if (finalize
) uc
->scheduleFinalize(true);
535 IOUserClient::finalizeUserReferences(OSObject
* obj
)
540 if ((uc
= OSDynamicCast(IOUserClient
, obj
)))
542 IOLockLock(gIOObjectPortLock
);
543 if ((uc
->__ipcFinal
= (0 != uc
->__ipc
))) ok
= false;
544 IOLockUnlock(gIOObjectPortLock
);
550 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
552 IOMachPort
* machPort
;
555 if( (machPort
= IOMachPort::portForObject( obj
, type
))) {
557 port
= machPort
->port
;
559 iokit_retain_port( port
);
570 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
571 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
573 IOUserClient
* client
;
575 IOUserNotification
* notify
;
577 if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount
))
578 return( kIOReturnNotReady
);
580 if( IKOT_IOKIT_CONNECT
== type
)
582 if( (client
= OSDynamicCast( IOUserClient
, obj
)))
584 IOStatisticsClientCall();
585 IOLockLock(client
->lock
);
586 client
->clientDied();
587 IOLockUnlock(client
->lock
);
590 else if( IKOT_IOKIT_OBJECT
== type
)
592 if( (map
= OSDynamicCast( IOMemoryMap
, obj
)))
594 else if( (notify
= OSDynamicCast( IOUserNotification
, obj
)))
595 notify
->setNotification( 0 );
598 return( kIOReturnSuccess
);
603 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
605 class IOServiceUserNotification
: public IOUserNotification
607 OSDeclareDefaultStructors(IOServiceUserNotification
)
610 mach_msg_header_t msgHdr
;
611 OSNotificationHeader64 notifyHeader
;
614 enum { kMaxOutstanding
= 1024 };
619 OSObject
* lastEntry
;
625 virtual bool init( mach_port_t port
, natural_t type
,
626 void * reference
, vm_size_t referenceSize
,
628 virtual void free() APPLE_KEXT_OVERRIDE
;
629 void invalidatePort(void);
631 static bool _handler( void * target
,
632 void * ref
, IOService
* newService
, IONotifier
* notifier
);
633 virtual bool handler( void * ref
, IOService
* newService
);
635 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
638 class IOServiceMessageUserNotification
: public IOUserNotification
640 OSDeclareDefaultStructors(IOServiceMessageUserNotification
)
643 mach_msg_header_t msgHdr
;
644 mach_msg_body_t msgBody
;
645 mach_msg_port_descriptor_t ports
[1];
646 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
657 virtual bool init( mach_port_t port
, natural_t type
,
658 void * reference
, vm_size_t referenceSize
,
662 virtual void free() APPLE_KEXT_OVERRIDE
;
663 void invalidatePort(void);
665 static IOReturn
_handler( void * target
, void * ref
,
666 UInt32 messageType
, IOService
* provider
,
667 void * messageArgument
, vm_size_t argSize
);
668 virtual IOReturn
handler( void * ref
,
669 UInt32 messageType
, IOService
* provider
,
670 void * messageArgument
, vm_size_t argSize
);
672 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
675 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
678 #define super IOUserIterator
679 OSDefineMetaClass( IOUserNotification
, IOUserIterator
)
680 OSDefineAbstractStructors( IOUserNotification
, IOUserIterator
)
682 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
684 void IOUserNotification::free( void )
688 assert(OSDynamicCast(IONotifier
, holdNotify
));
689 ((IONotifier
*)holdNotify
)->remove();
692 // can't be in handler now
698 void IOUserNotification::setNotification( IONotifier
* notify
)
700 OSObject
* previousNotify
;
702 IOLockLock( gIOObjectPortLock
);
704 previousNotify
= holdNotify
;
707 IOLockUnlock( gIOObjectPortLock
);
711 assert(OSDynamicCast(IONotifier
, previousNotify
));
712 ((IONotifier
*)previousNotify
)->remove();
716 void IOUserNotification::reset()
721 bool IOUserNotification::isValid()
726 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
729 #define super IOUserNotification
730 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
732 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
734 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
735 void * reference
, vm_size_t referenceSize
,
741 newSet
= OSArray::withCapacity( 1 );
745 if (referenceSize
> sizeof(OSAsyncReference64
))
748 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
749 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
753 bzero( pingMsg
, msgSize
);
755 pingMsg
->msgHdr
.msgh_remote_port
= port
;
756 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
757 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
758 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
759 pingMsg
->msgHdr
.msgh_size
= msgSize
;
760 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
762 pingMsg
->notifyHeader
.size
= 0;
763 pingMsg
->notifyHeader
.type
= type
;
764 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
769 void IOServiceUserNotification::invalidatePort(void)
771 if (pingMsg
) pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
774 void IOServiceUserNotification::free( void )
779 OSObject
* _lastEntry
;
783 _lastEntry
= lastEntry
;
788 if( _pingMsg
&& _msgSize
) {
789 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
790 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
792 IOFree(_pingMsg
, _msgSize
);
796 _lastEntry
->release();
802 bool IOServiceUserNotification::_handler( void * target
,
803 void * ref
, IOService
* newService
, IONotifier
* notifier
)
805 return( ((IOServiceUserNotification
*) target
)->handler( ref
, newService
));
808 bool IOServiceUserNotification::handler( void * ref
,
809 IOService
* newService
)
813 ipc_port_t port
= NULL
;
814 bool sendPing
= false;
818 count
= newSet
->getCount();
819 if( count
< kMaxOutstanding
) {
821 newSet
->setObject( newService
);
822 if( (sendPing
= (armed
&& (0 == count
))))
828 if( kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
)
829 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
832 if( (port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
) ))
833 pingMsg
->msgHdr
.msgh_local_port
= port
;
835 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
837 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
838 pingMsg
->msgHdr
.msgh_size
,
839 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
842 iokit_release_port( port
);
844 if( (KERN_SUCCESS
!= kr
) && !ipcLogged
)
847 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
854 OSObject
* IOServiceUserNotification::getNextObject()
858 OSObject
* releaseEntry
;
862 releaseEntry
= lastEntry
;
863 count
= newSet
->getCount();
865 result
= newSet
->getObject( count
- 1 );
867 newSet
->removeObject( count
- 1);
876 if (releaseEntry
) releaseEntry
->release();
881 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
883 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
885 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
887 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
888 void * reference
, vm_size_t referenceSize
, vm_size_t extraSize
,
894 if (referenceSize
> sizeof(OSAsyncReference64
))
897 clientIs64
= client64
;
899 owningPID
= proc_selfpid();
901 extraSize
+= sizeof(IOServiceInterestContent64
);
902 msgSize
= sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
;
903 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
907 bzero( pingMsg
, msgSize
);
909 pingMsg
->msgHdr
.msgh_remote_port
= port
;
910 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
912 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
913 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
914 pingMsg
->msgHdr
.msgh_size
= msgSize
;
915 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
917 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
919 pingMsg
->ports
[0].name
= 0;
920 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
921 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
923 pingMsg
->notifyHeader
.size
= extraSize
;
924 pingMsg
->notifyHeader
.type
= type
;
925 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
930 void IOServiceMessageUserNotification::invalidatePort(void)
932 if (pingMsg
) pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
935 void IOServiceMessageUserNotification::free( void )
945 if( _pingMsg
&& _msgSize
) {
946 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
947 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
949 IOFree( _pingMsg
, _msgSize
);
953 IOReturn
IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
954 UInt32 messageType
, IOService
* provider
,
955 void * argument
, vm_size_t argSize
)
957 return( ((IOServiceMessageUserNotification
*) target
)->handler(
958 ref
, messageType
, provider
, argument
, argSize
));
961 IOReturn
IOServiceMessageUserNotification::handler( void * ref
,
962 UInt32 messageType
, IOService
* provider
,
963 void * messageArgument
, vm_size_t callerArgSize
)
965 enum { kLocalMsgSize
= 0x100 };
966 uint64_t stackMsg
[kLocalMsgSize
/ sizeof(uint64_t)];
970 vm_size_t thisMsgSize
;
971 ipc_port_t thisPort
, providerPort
;
972 struct PingMsg
* thisMsg
;
973 IOServiceInterestContent64
* data
;
975 if (kIOMessageCopyClientID
== messageType
)
977 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
978 return (kIOReturnSuccess
);
981 if (callerArgSize
== 0)
983 if (clientIs64
) argSize
= sizeof(data
->messageArgument
[0]);
984 else argSize
= sizeof(uint32_t);
988 if( callerArgSize
> kIOUserNotifyMaxMessageSize
)
989 callerArgSize
= kIOUserNotifyMaxMessageSize
;
990 argSize
= callerArgSize
;
993 // adjust message size for ipc restrictions
995 type
= pingMsg
->notifyHeader
.type
;
996 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
997 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
998 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
1000 thisMsgSize
= msgSize
1001 + sizeof( IOServiceInterestContent64
)
1002 - sizeof( data
->messageArgument
)
1005 if (thisMsgSize
> sizeof(stackMsg
))
1007 allocMsg
= IOMalloc(thisMsgSize
);
1008 if (!allocMsg
) return (kIOReturnNoMemory
);
1009 thisMsg
= (typeof(thisMsg
)) allocMsg
;
1014 thisMsg
= (typeof(thisMsg
)) stackMsg
;
1017 bcopy(pingMsg
, thisMsg
, msgSize
);
1018 thisMsg
->notifyHeader
.type
= type
;
1019 data
= (IOServiceInterestContent64
*) (((uint8_t *) thisMsg
) + msgSize
);
1020 // == pingMsg->notifyHeader.content;
1021 data
->messageType
= messageType
;
1023 if (callerArgSize
== 0)
1025 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
1028 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
1033 bcopy( messageArgument
, data
->messageArgument
, callerArgSize
);
1034 bzero((void *)(((uintptr_t) &data
->messageArgument
[0]) + callerArgSize
), argSize
- callerArgSize
);
1037 thisMsg
->notifyHeader
.type
= type
;
1038 thisMsg
->msgHdr
.msgh_size
= thisMsgSize
;
1040 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
1041 thisMsg
->ports
[0].name
= providerPort
;
1042 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
1043 thisMsg
->msgHdr
.msgh_local_port
= thisPort
;
1045 kr
= mach_msg_send_from_kernel_with_options( &thisMsg
->msgHdr
,
1046 thisMsg
->msgHdr
.msgh_size
,
1047 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
1050 iokit_release_port( thisPort
);
1052 iokit_release_port( providerPort
);
1055 IOFree(allocMsg
, thisMsgSize
);
1057 if((KERN_SUCCESS
!= kr
) && !ipcLogged
)
1060 IOLog("%s: mach_msg_send_from_kernel_proper (0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1063 return( kIOReturnSuccess
);
1066 OSObject
* IOServiceMessageUserNotification::getNextObject()
1071 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1074 #define super IOService
1075 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
1077 IOLock
* gIOUserClientOwnersLock
;
1079 void IOUserClient::initialize( void )
1081 gIOObjectPortLock
= IOLockAlloc();
1082 gIOUserClientOwnersLock
= IOLockAlloc();
1083 assert(gIOObjectPortLock
&& gIOUserClientOwnersLock
);
1086 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
1087 mach_port_t wakePort
,
1088 void *callback
, void *refcon
)
1090 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
1091 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1092 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
1093 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
1096 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1097 mach_port_t wakePort
,
1098 mach_vm_address_t callback
, io_user_reference_t refcon
)
1100 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
1101 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1102 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
1103 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
1106 void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1107 mach_port_t wakePort
,
1108 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
1110 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
1111 if (vm_map_is_64bit(get_task_map(task
))) {
1112 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
1116 static OSDictionary
* CopyConsoleUser(UInt32 uid
)
1119 OSDictionary
* user
= 0;
1121 if ((array
= OSDynamicCast(OSArray
,
1122 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1124 for (unsigned int idx
= 0;
1125 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1129 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
1130 && (uid
== num
->unsigned32BitValue())) {
1140 static OSDictionary
* CopyUserOnConsole(void)
1143 OSDictionary
* user
= 0;
1145 if ((array
= OSDynamicCast(OSArray
,
1146 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
))))
1148 for (unsigned int idx
= 0;
1149 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1152 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
1163 IOReturn
IOUserClient::clientHasAuthorization( task_t task
,
1164 IOService
* service
)
1168 p
= (proc_t
) get_bsdtask_info(task
);
1171 uint64_t authorizationID
;
1173 authorizationID
= proc_uniqueid(p
);
1174 if (authorizationID
)
1176 if (service
->getAuthorizationID() == authorizationID
)
1178 return (kIOReturnSuccess
);
1183 return (kIOReturnNotPermitted
);
1186 IOReturn
IOUserClient::clientHasPrivilege( void * securityToken
,
1187 const char * privilegeName
)
1190 security_token_t token
;
1191 mach_msg_type_number_t count
;
1193 OSDictionary
* user
;
1197 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
1198 sizeof(kIOClientPrivilegeForeground
)))
1200 if (task_is_gpu_denied(current_task()))
1201 return (kIOReturnNotPrivileged
);
1203 return (kIOReturnSuccess
);
1206 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1207 sizeof(kIOClientPrivilegeConsoleSession
)))
1212 task
= (task_t
) securityToken
;
1214 task
= current_task();
1215 p
= (proc_t
) get_bsdtask_info(task
);
1216 kr
= kIOReturnNotPrivileged
;
1218 if (p
&& (cred
= kauth_cred_proc_ref(p
)))
1220 user
= CopyUserOnConsole();
1224 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1225 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue()))
1227 kr
= kIOReturnSuccess
;
1231 kauth_cred_unref(&cred
);
1236 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1237 sizeof(kIOClientPrivilegeSecureConsoleProcess
))))
1238 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1240 task
= (task_t
)securityToken
;
1242 count
= TASK_SECURITY_TOKEN_COUNT
;
1243 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1245 if (KERN_SUCCESS
!= kr
)
1247 else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1248 sizeof(kIOClientPrivilegeAdministrator
))) {
1249 if (0 != token
.val
[0])
1250 kr
= kIOReturnNotPrivileged
;
1251 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1252 sizeof(kIOClientPrivilegeLocalUser
))) {
1253 user
= CopyConsoleUser(token
.val
[0]);
1257 kr
= kIOReturnNotPrivileged
;
1258 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1259 sizeof(kIOClientPrivilegeConsoleUser
))) {
1260 user
= CopyConsoleUser(token
.val
[0]);
1262 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
)
1263 kr
= kIOReturnNotPrivileged
;
1264 else if ( secureConsole
) {
1265 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1266 if ( pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
)
1267 kr
= kIOReturnNotPrivileged
;
1272 kr
= kIOReturnNotPrivileged
;
1274 kr
= kIOReturnUnsupported
;
1279 OSObject
* IOUserClient::copyClientEntitlement( task_t task
,
1280 const char * entitlement
)
1282 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1286 char procname
[MAXCOMLEN
+ 1] = "";
1288 void *entitlements_blob
= NULL
;
1289 char *entitlements_data
= NULL
;
1290 OSObject
*entitlements_obj
= NULL
;
1291 OSDictionary
*entitlements
= NULL
;
1292 OSString
*errorString
= NULL
;
1293 OSObject
*value
= NULL
;
1295 p
= (proc_t
)get_bsdtask_info(task
);
1299 proc_name(pid
, procname
, (int)sizeof(procname
));
1301 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0)
1304 if (len
<= offsetof(CS_GenericBlob
, data
))
1308 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1309 * we'll try to parse in the kernel.
1311 len
-= offsetof(CS_GenericBlob
, data
);
1312 if (len
> MAX_ENTITLEMENTS_LEN
) {
1313 IOLog("failed to parse entitlements for %s[%u]: %lu bytes of entitlements exceeds maximum of %u\n", procname
, pid
, len
, MAX_ENTITLEMENTS_LEN
);
1318 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1319 * what is stored in the entitlements blob. Copy the string and
1322 entitlements_data
= (char *)IOMalloc(len
+ 1);
1323 if (entitlements_data
== NULL
)
1325 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1326 entitlements_data
[len
] = '\0';
1328 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1329 if (errorString
!= NULL
) {
1330 IOLog("failed to parse entitlements for %s[%u]: %s\n", procname
, pid
, errorString
->getCStringNoCopy());
1333 if (entitlements_obj
== NULL
)
1336 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1337 if (entitlements
== NULL
)
1340 /* Fetch the entitlement value from the dictionary. */
1341 value
= entitlements
->getObject(entitlement
);
1346 if (entitlements_data
!= NULL
)
1347 IOFree(entitlements_data
, len
+ 1);
1348 if (entitlements_obj
!= NULL
)
1349 entitlements_obj
->release();
1350 if (errorString
!= NULL
)
1351 errorString
->release();
1355 bool IOUserClient::init()
1357 if (getPropertyTable() || super::init())
1363 bool IOUserClient::init(OSDictionary
* dictionary
)
1365 if (getPropertyTable() || super::init(dictionary
))
1371 bool IOUserClient::initWithTask(task_t owningTask
,
1375 if (getPropertyTable() || super::init())
1381 bool IOUserClient::initWithTask(task_t owningTask
,
1384 OSDictionary
* properties
)
1388 ok
= super::init( properties
);
1389 ok
&= initWithTask( owningTask
, securityID
, type
);
1394 bool IOUserClient::reserve()
1397 reserved
= IONew(ExpansionData
, 1);
1402 setTerminateDefer(NULL
, true);
1403 IOStatisticsRegisterCounter();
1408 struct IOUserClientOwner
1411 queue_chain_t taskLink
;
1413 queue_chain_t ucLink
;
1417 IOUserClient::registerOwner(task_t task
)
1419 IOUserClientOwner
* owner
;
1423 IOLockLock(gIOUserClientOwnersLock
);
1426 ret
= kIOReturnSuccess
;
1428 if (!owners
.next
) queue_init(&owners
);
1431 queue_iterate(&owners
, owner
, IOUserClientOwner
*, ucLink
)
1433 if (task
!= owner
->task
) continue;
1440 owner
= IONew(IOUserClientOwner
, 1);
1441 if (!newOwner
) ret
= kIOReturnNoMemory
;
1446 queue_enter_first(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1447 queue_enter_first(task_io_user_clients(task
), owner
, IOUserClientOwner
*, taskLink
);
1451 IOLockUnlock(gIOUserClientOwnersLock
);
1457 IOUserClient::noMoreSenders(void)
1459 IOUserClientOwner
* owner
;
1461 IOLockLock(gIOUserClientOwnersLock
);
1465 while (!queue_empty(&owners
))
1467 owner
= (IOUserClientOwner
*)(void *) queue_first(&owners
);
1468 queue_remove(task_io_user_clients(owner
->task
), owner
, IOUserClientOwner
*, taskLink
);
1469 queue_remove(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1470 IODelete(owner
, IOUserClientOwner
, 1);
1472 owners
.next
= owners
.prev
= NULL
;
1475 IOLockUnlock(gIOUserClientOwnersLock
);
1478 extern "C" kern_return_t
1479 iokit_task_terminate(task_t task
)
1481 IOUserClientOwner
* owner
;
1482 IOUserClient
* dead
;
1484 queue_head_t
* taskque
;
1486 IOLockLock(gIOUserClientOwnersLock
);
1488 taskque
= task_io_user_clients(task
);
1490 while (!queue_empty(taskque
))
1492 owner
= (IOUserClientOwner
*)(void *) queue_first(taskque
);
1494 queue_remove(taskque
, owner
, IOUserClientOwner
*, taskLink
);
1495 queue_remove(&uc
->owners
, owner
, IOUserClientOwner
*, ucLink
);
1496 if (queue_empty(&uc
->owners
))
1499 IOLog("destroying out of band connect for %s\n", uc
->getName());
1500 // now using the uc queue head as a singly linked queue,
1501 // leaving .next as NULL to mark it empty
1502 uc
->owners
.next
= NULL
;
1503 uc
->owners
.prev
= (queue_entry_t
) dead
;
1506 IODelete(owner
, IOUserClientOwner
, 1);
1509 IOLockUnlock(gIOUserClientOwnersLock
);
1514 dead
= (IOUserClient
*)(void *) dead
->owners
.prev
;
1515 uc
->owners
.prev
= NULL
;
1516 if (uc
->sharedInstance
|| !uc
->closed
) uc
->clientDied();
1520 return (KERN_SUCCESS
);
1523 void IOUserClient::free()
1525 if( mappings
) mappings
->release();
1526 if (lock
) IOLockFree(lock
);
1528 IOStatisticsUnregisterCounter();
1530 assert(!owners
.next
);
1531 assert(!owners
.prev
);
1533 if (reserved
) IODelete(reserved
, ExpansionData
, 1);
1538 IOReturn
IOUserClient::clientDied( void )
1540 IOReturn ret
= kIOReturnNotReady
;
1542 if (sharedInstance
|| OSCompareAndSwap8(0, 1, &closed
))
1544 ret
= clientClose();
1550 IOReturn
IOUserClient::clientClose( void )
1552 return( kIOReturnUnsupported
);
1555 IOService
* IOUserClient::getService( void )
1560 IOReturn
IOUserClient::registerNotificationPort(
1561 mach_port_t
/* port */,
1563 UInt32
/* refCon */)
1565 return( kIOReturnUnsupported
);
1568 IOReturn
IOUserClient::registerNotificationPort(
1571 io_user_reference_t refCon
)
1573 return (registerNotificationPort(port
, type
, (UInt32
) refCon
));
1576 IOReturn
IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1577 semaphore_t
* semaphore
)
1579 return( kIOReturnUnsupported
);
1582 IOReturn
IOUserClient::connectClient( IOUserClient
* /* client */ )
1584 return( kIOReturnUnsupported
);
1587 IOReturn
IOUserClient::clientMemoryForType( UInt32 type
,
1588 IOOptionBits
* options
,
1589 IOMemoryDescriptor
** memory
)
1591 return( kIOReturnUnsupported
);
1595 IOMemoryMap
* IOUserClient::mapClientMemory(
1598 IOOptionBits mapFlags
,
1599 IOVirtualAddress atAddress
)
1605 IOMemoryMap
* IOUserClient::mapClientMemory64(
1608 IOOptionBits mapFlags
,
1609 mach_vm_address_t atAddress
)
1612 IOOptionBits options
= 0;
1613 IOMemoryDescriptor
* memory
= 0;
1614 IOMemoryMap
* map
= 0;
1616 err
= clientMemoryForType( (UInt32
) type
, &options
, &memory
);
1618 if( memory
&& (kIOReturnSuccess
== err
)) {
1620 FAKE_STACK_FRAME(getMetaClass());
1622 options
= (options
& ~kIOMapUserOptionsMask
)
1623 | (mapFlags
& kIOMapUserOptionsMask
);
1624 map
= memory
->createMappingInTask( task
, atAddress
, options
);
1627 FAKE_STACK_FRAME_END();
1633 IOReturn
IOUserClient::exportObjectToClient(task_t task
,
1634 OSObject
*obj
, io_object_t
*clientObj
)
1636 mach_port_name_t name
;
1638 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
1640 *(mach_port_name_t
*)clientObj
= name
;
1642 if (obj
) obj
->release();
1644 return kIOReturnSuccess
;
1647 IOReturn
IOUserClient::copyPortNameForObjectInTask(task_t task
,
1648 OSObject
*obj
, mach_port_name_t
* port_name
)
1650 mach_port_name_t name
;
1652 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_IDENT
);
1654 *(mach_port_name_t
*) port_name
= name
;
1656 return kIOReturnSuccess
;
1659 IOReturn
IOUserClient::copyObjectForPortNameInTask(task_t task
, mach_port_name_t port_name
,
1664 object
= iokit_lookup_object_with_port_name(port_name
, IKOT_IOKIT_IDENT
, task
);
1668 return (object
? kIOReturnSuccess
: kIOReturnIPCError
);
1671 IOReturn
IOUserClient::adjustPortNameReferencesInTask(task_t task
, mach_port_name_t port_name
, mach_port_delta_t delta
)
1673 return (iokit_mod_send_right(task
, port_name
, delta
));
1676 IOExternalMethod
* IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
1681 IOExternalAsyncMethod
* IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
1686 IOExternalTrap
* IOUserClient::
1687 getExternalTrapForIndex(UInt32 index
)
1692 #pragma clang diagnostic push
1693 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1695 // Suppressing the deprecated-declarations warning. Avoiding the use of deprecated
1696 // functions can break clients of kexts implementing getExternalMethodForIndex()
1697 IOExternalMethod
* IOUserClient::
1698 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
1700 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
1703 *targetP
= (IOService
*) method
->object
;
1708 IOExternalAsyncMethod
* IOUserClient::
1709 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
1711 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
1714 *targetP
= (IOService
*) method
->object
;
1719 IOExternalTrap
* IOUserClient::
1720 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
1722 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
1725 *targetP
= trap
->object
;
1730 #pragma clang diagnostic pop
1732 IOReturn
IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
1735 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1737 if (MACH_PORT_NULL
!= port
)
1738 iokit_release_port_send(port
);
1740 return (kIOReturnSuccess
);
1743 IOReturn
IOUserClient::releaseNotificationPort(mach_port_t port
)
1745 if (MACH_PORT_NULL
!= port
)
1746 iokit_release_port_send(port
);
1748 return (kIOReturnSuccess
);
1751 IOReturn
IOUserClient::sendAsyncResult(OSAsyncReference reference
,
1752 IOReturn result
, void *args
[], UInt32 numArgs
)
1754 OSAsyncReference64 reference64
;
1755 io_user_reference_t args64
[kMaxAsyncArgs
];
1758 if (numArgs
> kMaxAsyncArgs
)
1759 return kIOReturnMessageTooLarge
;
1761 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++)
1762 reference64
[idx
] = REF64(reference
[idx
]);
1764 for (idx
= 0; idx
< numArgs
; idx
++)
1765 args64
[idx
] = REF64(args
[idx
]);
1767 return (sendAsyncResult64(reference64
, result
, args64
, numArgs
));
1770 IOReturn
IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
1771 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1773 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
1776 IOReturn
IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
1777 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
1779 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
1782 IOReturn
IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
1783 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
1787 mach_msg_header_t msgHdr
;
1792 OSNotificationHeader notifyHdr
;
1793 IOAsyncCompletionContent asyncContent
;
1794 uint32_t args
[kMaxAsyncArgs
];
1798 OSNotificationHeader64 notifyHdr
;
1799 IOAsyncCompletionContent asyncContent
;
1800 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
1805 mach_port_t replyPort
;
1808 // If no reply port, do nothing.
1809 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
1810 if (replyPort
== MACH_PORT_NULL
)
1811 return kIOReturnSuccess
;
1813 if (numArgs
> kMaxAsyncArgs
)
1814 return kIOReturnMessageTooLarge
;
1816 bzero(&replyMsg
, sizeof(replyMsg
));
1817 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1819 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
1820 replyMsg
.msgHdr
.msgh_local_port
= 0;
1821 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
1822 if (kIOUCAsync64Flag
& reference
[0])
1824 replyMsg
.msgHdr
.msgh_size
=
1825 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
1826 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
1827 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1828 + numArgs
* sizeof(io_user_reference_t
);
1829 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1830 bcopy(reference
, replyMsg
.m
.msg64
.notifyHdr
.reference
, sizeof(OSAsyncReference64
));
1832 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
1834 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
1840 replyMsg
.msgHdr
.msgh_size
=
1841 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
1842 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
1844 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
1845 + numArgs
* sizeof(uint32_t);
1846 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
1848 for (idx
= 0; idx
< kOSAsyncRefCount
; idx
++)
1849 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
1851 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
1853 for (idx
= 0; idx
< numArgs
; idx
++)
1854 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
1857 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
1858 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
1859 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
1861 /* Fail on full queue. */
1862 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
1863 replyMsg
.msgHdr
.msgh_size
);
1865 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
) && !(kIOUCAsyncErrorLoggedFlag
& reference
[0]))
1867 reference
[0] |= kIOUCAsyncErrorLoggedFlag
;
1868 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1874 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1878 #define CHECK(cls,obj,out) \
1880 if( !(out = OSDynamicCast( cls, obj))) \
1881 return( kIOReturnBadArgument )
1883 #define CHECKLOCKED(cls,obj,out) \
1884 IOUserIterator * oIter; \
1886 if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
1887 return (kIOReturnBadArgument); \
1888 if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
1889 return (kIOReturnBadArgument)
1891 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1893 // Create a vm_map_copy_t or kalloc'ed data for memory
1894 // to be copied out. ipc will free after the copyout.
1896 static kern_return_t
copyoutkdata( const void * data
, vm_size_t len
,
1897 io_buf_ptr_t
* buf
)
1902 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
1903 false /* src_destroy */, ©
);
1905 assert( err
== KERN_SUCCESS
);
1906 if( err
== KERN_SUCCESS
)
1907 *buf
= (char *) copy
;
1912 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1914 /* Routine io_server_version */
1915 kern_return_t
is_io_server_version(
1916 mach_port_t master_port
,
1919 *version
= IOKIT_SERVER_VERSION
;
1920 return (kIOReturnSuccess
);
1923 /* Routine io_object_get_class */
1924 kern_return_t
is_io_object_get_class(
1926 io_name_t className
)
1928 const OSMetaClass
* my_obj
= NULL
;
1931 return( kIOReturnBadArgument
);
1933 my_obj
= object
->getMetaClass();
1935 return (kIOReturnNotFound
);
1938 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
1940 return( kIOReturnSuccess
);
1943 /* Routine io_object_get_superclass */
1944 kern_return_t
is_io_object_get_superclass(
1945 mach_port_t master_port
,
1947 io_name_t class_name
)
1950 const OSMetaClass
* meta
;
1951 const OSMetaClass
* super
;
1952 const OSSymbol
* name
;
1955 if (!obj_name
|| !class_name
) return (kIOReturnBadArgument
);
1956 if (master_port
!= master_device_port
) return( kIOReturnNotPrivileged
);
1958 ret
= kIOReturnNotFound
;
1962 name
= OSSymbol::withCString(obj_name
);
1964 meta
= OSMetaClass::copyMetaClassWithName(name
);
1966 super
= meta
->getSuperClass();
1968 cstr
= super
->getClassName();
1970 strlcpy(class_name
, cstr
, sizeof(io_name_t
));
1971 ret
= kIOReturnSuccess
;
1975 OSSafeReleaseNULL(name
);
1976 if (meta
) meta
->releaseMetaClass();
1981 /* Routine io_object_get_bundle_identifier */
1982 kern_return_t
is_io_object_get_bundle_identifier(
1983 mach_port_t master_port
,
1985 io_name_t bundle_name
)
1988 const OSMetaClass
* meta
;
1989 const OSSymbol
* name
;
1990 const OSSymbol
* identifier
;
1993 if (!obj_name
|| !bundle_name
) return (kIOReturnBadArgument
);
1994 if (master_port
!= master_device_port
) return( kIOReturnNotPrivileged
);
1996 ret
= kIOReturnNotFound
;
2000 name
= OSSymbol::withCString(obj_name
);
2002 meta
= OSMetaClass::copyMetaClassWithName(name
);
2004 identifier
= meta
->getKmodName();
2005 if (!identifier
) break;
2006 cstr
= identifier
->getCStringNoCopy();
2008 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
2009 ret
= kIOReturnSuccess
;
2013 OSSafeReleaseNULL(name
);
2014 if (meta
) meta
->releaseMetaClass();
2019 /* Routine io_object_conforms_to */
2020 kern_return_t
is_io_object_conforms_to(
2022 io_name_t className
,
2023 boolean_t
*conforms
)
2026 return( kIOReturnBadArgument
);
2028 *conforms
= (0 != object
->metaCast( className
));
2030 return( kIOReturnSuccess
);
2033 /* Routine io_object_get_retain_count */
2034 kern_return_t
is_io_object_get_retain_count(
2036 uint32_t *retainCount
)
2039 return( kIOReturnBadArgument
);
2041 *retainCount
= object
->getRetainCount();
2042 return( kIOReturnSuccess
);
2045 /* Routine io_iterator_next */
2046 kern_return_t
is_io_iterator_next(
2047 io_object_t iterator
,
2048 io_object_t
*object
)
2053 CHECK( OSIterator
, iterator
, iter
);
2055 obj
= iter
->getNextObject();
2059 ret
= kIOReturnSuccess
;
2061 ret
= kIOReturnNoDevice
;
2066 /* Routine io_iterator_reset */
2067 kern_return_t
is_io_iterator_reset(
2068 io_object_t iterator
)
2070 CHECK( OSIterator
, iterator
, iter
);
2074 return( kIOReturnSuccess
);
2077 /* Routine io_iterator_is_valid */
2078 kern_return_t
is_io_iterator_is_valid(
2079 io_object_t iterator
,
2080 boolean_t
*is_valid
)
2082 CHECK( OSIterator
, iterator
, iter
);
2084 *is_valid
= iter
->isValid();
2086 return( kIOReturnSuccess
);
2090 static kern_return_t
internal_io_service_match_property_table(
2091 io_service_t _service
,
2092 const char * matching
,
2093 mach_msg_type_number_t matching_size
,
2096 CHECK( IOService
, _service
, service
);
2100 OSDictionary
* dict
;
2102 assert(matching_size
);
2103 obj
= OSUnserializeXML(matching
, matching_size
);
2105 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2106 *matches
= service
->passiveMatch( dict
);
2107 kr
= kIOReturnSuccess
;
2109 kr
= kIOReturnBadArgument
;
2117 /* Routine io_service_match_property_table */
2118 kern_return_t
is_io_service_match_property_table(
2119 io_service_t service
,
2120 io_string_t matching
,
2121 boolean_t
*matches
)
2123 return (kIOReturnUnsupported
);
2127 /* Routine io_service_match_property_table_ool */
2128 kern_return_t
is_io_service_match_property_table_ool(
2129 io_object_t service
,
2130 io_buf_ptr_t matching
,
2131 mach_msg_type_number_t matchingCnt
,
2132 kern_return_t
*result
,
2133 boolean_t
*matches
)
2137 vm_map_offset_t map_data
;
2139 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2140 data
= CAST_DOWN(vm_offset_t
, map_data
);
2142 if( KERN_SUCCESS
== kr
) {
2143 // must return success after vm_map_copyout() succeeds
2144 *result
= internal_io_service_match_property_table(service
,
2145 (const char *)data
, matchingCnt
, matches
);
2146 vm_deallocate( kernel_map
, data
, matchingCnt
);
2152 /* Routine io_service_match_property_table_bin */
2153 kern_return_t
is_io_service_match_property_table_bin(
2154 io_object_t service
,
2155 io_struct_inband_t matching
,
2156 mach_msg_type_number_t matchingCnt
,
2159 return (internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
));
2162 static kern_return_t
internal_io_service_get_matching_services(
2163 mach_port_t master_port
,
2164 const char * matching
,
2165 mach_msg_type_number_t matching_size
,
2166 io_iterator_t
*existing
)
2170 OSDictionary
* dict
;
2172 if( master_port
!= master_device_port
)
2173 return( kIOReturnNotPrivileged
);
2175 assert(matching_size
);
2176 obj
= OSUnserializeXML(matching
, matching_size
);
2178 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2179 *existing
= IOUserIterator::withIterator(IOService::getMatchingServices( dict
));
2180 kr
= kIOReturnSuccess
;
2182 kr
= kIOReturnBadArgument
;
2190 /* Routine io_service_get_matching_services */
2191 kern_return_t
is_io_service_get_matching_services(
2192 mach_port_t master_port
,
2193 io_string_t matching
,
2194 io_iterator_t
*existing
)
2196 return (kIOReturnUnsupported
);
2199 /* Routine io_service_get_matching_services_ool */
2200 kern_return_t
is_io_service_get_matching_services_ool(
2201 mach_port_t master_port
,
2202 io_buf_ptr_t matching
,
2203 mach_msg_type_number_t matchingCnt
,
2204 kern_return_t
*result
,
2205 io_object_t
*existing
)
2209 vm_map_offset_t map_data
;
2211 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2212 data
= CAST_DOWN(vm_offset_t
, map_data
);
2214 if( KERN_SUCCESS
== kr
) {
2215 // must return success after vm_map_copyout() succeeds
2216 // and mig will copy out objects on success
2218 *result
= internal_io_service_get_matching_services(master_port
,
2219 (const char *) data
, matchingCnt
, existing
);
2220 vm_deallocate( kernel_map
, data
, matchingCnt
);
2226 /* Routine io_service_get_matching_services_bin */
2227 kern_return_t
is_io_service_get_matching_services_bin(
2228 mach_port_t master_port
,
2229 io_struct_inband_t matching
,
2230 mach_msg_type_number_t matchingCnt
,
2231 io_object_t
*existing
)
2233 return (internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
));
2237 static kern_return_t
internal_io_service_get_matching_service(
2238 mach_port_t master_port
,
2239 const char * matching
,
2240 mach_msg_type_number_t matching_size
,
2241 io_service_t
*service
)
2245 OSDictionary
* dict
;
2247 if( master_port
!= master_device_port
)
2248 return( kIOReturnNotPrivileged
);
2250 assert(matching_size
);
2251 obj
= OSUnserializeXML(matching
, matching_size
);
2253 if( (dict
= OSDynamicCast( OSDictionary
, obj
))) {
2254 *service
= IOService::copyMatchingService( dict
);
2255 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
2257 kr
= kIOReturnBadArgument
;
2265 /* Routine io_service_get_matching_service */
2266 kern_return_t
is_io_service_get_matching_service(
2267 mach_port_t master_port
,
2268 io_string_t matching
,
2269 io_service_t
*service
)
2271 return (kIOReturnUnsupported
);
2274 /* Routine io_service_get_matching_services_ool */
2275 kern_return_t
is_io_service_get_matching_service_ool(
2276 mach_port_t master_port
,
2277 io_buf_ptr_t matching
,
2278 mach_msg_type_number_t matchingCnt
,
2279 kern_return_t
*result
,
2280 io_object_t
*service
)
2284 vm_map_offset_t map_data
;
2286 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2287 data
= CAST_DOWN(vm_offset_t
, map_data
);
2289 if( KERN_SUCCESS
== kr
) {
2290 // must return success after vm_map_copyout() succeeds
2291 // and mig will copy out objects on success
2293 *result
= internal_io_service_get_matching_service(master_port
,
2294 (const char *) data
, matchingCnt
, service
);
2295 vm_deallocate( kernel_map
, data
, matchingCnt
);
2301 /* Routine io_service_get_matching_service_bin */
2302 kern_return_t
is_io_service_get_matching_service_bin(
2303 mach_port_t master_port
,
2304 io_struct_inband_t matching
,
2305 mach_msg_type_number_t matchingCnt
,
2306 io_object_t
*service
)
2308 return (internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
));
2311 static kern_return_t
internal_io_service_add_notification(
2312 mach_port_t master_port
,
2313 io_name_t notification_type
,
2314 const char * matching
,
2315 size_t matching_size
,
2318 vm_size_t referenceSize
,
2320 io_object_t
* notification
)
2322 IOServiceUserNotification
* userNotify
= 0;
2323 IONotifier
* notify
= 0;
2324 const OSSymbol
* sym
;
2325 OSDictionary
* dict
;
2327 unsigned long int userMsgType
;
2329 if( master_port
!= master_device_port
)
2330 return( kIOReturnNotPrivileged
);
2333 err
= kIOReturnNoResources
;
2335 if (matching_size
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2337 if( !(sym
= OSSymbol::withCString( notification_type
)))
2338 err
= kIOReturnNoResources
;
2340 assert(matching_size
);
2341 dict
= OSDynamicCast(OSDictionary
, OSUnserializeXML(matching
, matching_size
));
2343 err
= kIOReturnBadArgument
;
2347 if( (sym
== gIOPublishNotification
)
2348 || (sym
== gIOFirstPublishNotification
))
2349 userMsgType
= kIOServicePublishNotificationType
;
2350 else if( (sym
== gIOMatchedNotification
)
2351 || (sym
== gIOFirstMatchNotification
))
2352 userMsgType
= kIOServiceMatchedNotificationType
;
2353 else if ((sym
== gIOTerminatedNotification
)
2354 || (sym
== gIOWillTerminateNotification
))
2355 userMsgType
= kIOServiceTerminatedNotificationType
;
2357 userMsgType
= kLastIOKitNotificationType
;
2359 userNotify
= new IOServiceUserNotification
;
2361 if( userNotify
&& !userNotify
->init( port
, userMsgType
,
2362 reference
, referenceSize
, client64
)) {
2363 userNotify
->release();
2369 notify
= IOService::addMatchingNotification( sym
, dict
,
2370 &userNotify
->_handler
, userNotify
);
2372 *notification
= userNotify
;
2373 userNotify
->setNotification( notify
);
2374 err
= kIOReturnSuccess
;
2376 err
= kIOReturnUnsupported
;
2380 if ((kIOReturnSuccess
!= err
) && userNotify
)
2382 userNotify
->invalidatePort();
2383 userNotify
->release();
2396 /* Routine io_service_add_notification */
2397 kern_return_t
is_io_service_add_notification(
2398 mach_port_t master_port
,
2399 io_name_t notification_type
,
2400 io_string_t matching
,
2402 io_async_ref_t reference
,
2403 mach_msg_type_number_t referenceCnt
,
2404 io_object_t
* notification
)
2406 return (kIOReturnUnsupported
);
2409 /* Routine io_service_add_notification_64 */
2410 kern_return_t
is_io_service_add_notification_64(
2411 mach_port_t master_port
,
2412 io_name_t notification_type
,
2413 io_string_t matching
,
2414 mach_port_t wake_port
,
2415 io_async_ref64_t reference
,
2416 mach_msg_type_number_t referenceCnt
,
2417 io_object_t
*notification
)
2419 return (kIOReturnUnsupported
);
2422 /* Routine io_service_add_notification_bin */
2423 kern_return_t is_io_service_add_notification_bin
2425 mach_port_t master_port
,
2426 io_name_t notification_type
,
2427 io_struct_inband_t matching
,
2428 mach_msg_type_number_t matchingCnt
,
2429 mach_port_t wake_port
,
2430 io_async_ref_t reference
,
2431 mach_msg_type_number_t referenceCnt
,
2432 io_object_t
*notification
)
2434 return (internal_io_service_add_notification(master_port
, notification_type
,
2435 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2436 false, notification
));
2439 /* Routine io_service_add_notification_bin_64 */
2440 kern_return_t is_io_service_add_notification_bin_64
2442 mach_port_t master_port
,
2443 io_name_t notification_type
,
2444 io_struct_inband_t matching
,
2445 mach_msg_type_number_t matchingCnt
,
2446 mach_port_t wake_port
,
2447 io_async_ref64_t reference
,
2448 mach_msg_type_number_t referenceCnt
,
2449 io_object_t
*notification
)
2451 return (internal_io_service_add_notification(master_port
, notification_type
,
2452 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2453 true, notification
));
2456 static kern_return_t
internal_io_service_add_notification_ool(
2457 mach_port_t master_port
,
2458 io_name_t notification_type
,
2459 io_buf_ptr_t matching
,
2460 mach_msg_type_number_t matchingCnt
,
2461 mach_port_t wake_port
,
2463 vm_size_t referenceSize
,
2465 kern_return_t
*result
,
2466 io_object_t
*notification
)
2470 vm_map_offset_t map_data
;
2472 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2473 data
= CAST_DOWN(vm_offset_t
, map_data
);
2475 if( KERN_SUCCESS
== kr
) {
2476 // must return success after vm_map_copyout() succeeds
2477 // and mig will copy out objects on success
2479 *result
= internal_io_service_add_notification( master_port
, notification_type
,
2480 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
2481 vm_deallocate( kernel_map
, data
, matchingCnt
);
2487 /* Routine io_service_add_notification_ool */
2488 kern_return_t
is_io_service_add_notification_ool(
2489 mach_port_t master_port
,
2490 io_name_t notification_type
,
2491 io_buf_ptr_t matching
,
2492 mach_msg_type_number_t matchingCnt
,
2493 mach_port_t wake_port
,
2494 io_async_ref_t reference
,
2495 mach_msg_type_number_t referenceCnt
,
2496 kern_return_t
*result
,
2497 io_object_t
*notification
)
2499 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2500 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref_t
),
2501 false, result
, notification
));
2504 /* Routine io_service_add_notification_ool_64 */
2505 kern_return_t
is_io_service_add_notification_ool_64(
2506 mach_port_t master_port
,
2507 io_name_t notification_type
,
2508 io_buf_ptr_t matching
,
2509 mach_msg_type_number_t matchingCnt
,
2510 mach_port_t wake_port
,
2511 io_async_ref64_t reference
,
2512 mach_msg_type_number_t referenceCnt
,
2513 kern_return_t
*result
,
2514 io_object_t
*notification
)
2516 return (internal_io_service_add_notification_ool(master_port
, notification_type
,
2517 matching
, matchingCnt
, wake_port
, &reference
[0], sizeof(io_async_ref64_t
),
2518 true, result
, notification
));
2521 /* Routine io_service_add_notification_old */
2522 kern_return_t
is_io_service_add_notification_old(
2523 mach_port_t master_port
,
2524 io_name_t notification_type
,
2525 io_string_t matching
,
2527 // for binary compatibility reasons, this must be natural_t for ILP32
2529 io_object_t
* notification
)
2531 return( is_io_service_add_notification( master_port
, notification_type
,
2532 matching
, port
, &ref
, 1, notification
));
2536 static kern_return_t
internal_io_service_add_interest_notification(
2537 io_object_t _service
,
2538 io_name_t type_of_interest
,
2541 vm_size_t referenceSize
,
2543 io_object_t
* notification
)
2546 IOServiceMessageUserNotification
* userNotify
= 0;
2547 IONotifier
* notify
= 0;
2548 const OSSymbol
* sym
;
2551 CHECK( IOService
, _service
, service
);
2553 err
= kIOReturnNoResources
;
2554 if( (sym
= OSSymbol::withCString( type_of_interest
))) do {
2556 userNotify
= new IOServiceMessageUserNotification
;
2558 if( userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
2559 reference
, referenceSize
,
2560 kIOUserNotifyMaxMessageSize
,
2562 userNotify
->release();
2568 notify
= service
->registerInterest( sym
,
2569 &userNotify
->_handler
, userNotify
);
2571 *notification
= userNotify
;
2572 userNotify
->setNotification( notify
);
2573 err
= kIOReturnSuccess
;
2575 err
= kIOReturnUnsupported
;
2581 if ((kIOReturnSuccess
!= err
) && userNotify
)
2583 userNotify
->invalidatePort();
2584 userNotify
->release();
2591 /* Routine io_service_add_message_notification */
2592 kern_return_t
is_io_service_add_interest_notification(
2593 io_object_t service
,
2594 io_name_t type_of_interest
,
2596 io_async_ref_t reference
,
2597 mach_msg_type_number_t referenceCnt
,
2598 io_object_t
* notification
)
2600 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2601 port
, &reference
[0], sizeof(io_async_ref_t
), false, notification
));
2604 /* Routine io_service_add_interest_notification_64 */
2605 kern_return_t
is_io_service_add_interest_notification_64(
2606 io_object_t service
,
2607 io_name_t type_of_interest
,
2608 mach_port_t wake_port
,
2609 io_async_ref64_t reference
,
2610 mach_msg_type_number_t referenceCnt
,
2611 io_object_t
*notification
)
2613 return (internal_io_service_add_interest_notification(service
, type_of_interest
,
2614 wake_port
, &reference
[0], sizeof(io_async_ref64_t
), true, notification
));
2618 /* Routine io_service_acknowledge_notification */
2619 kern_return_t
is_io_service_acknowledge_notification(
2620 io_object_t _service
,
2621 natural_t notify_ref
,
2622 natural_t response
)
2624 CHECK( IOService
, _service
, service
);
2626 return( service
->acknowledgeNotification( (IONotificationRef
)(uintptr_t) notify_ref
,
2627 (IOOptionBits
) response
));
2631 /* Routine io_connect_get_semaphore */
2632 kern_return_t
is_io_connect_get_notification_semaphore(
2633 io_connect_t connection
,
2634 natural_t notification_type
,
2635 semaphore_t
*semaphore
)
2637 CHECK( IOUserClient
, connection
, client
);
2639 IOStatisticsClientCall();
2640 return( client
->getNotificationSemaphore( (UInt32
) notification_type
,
2644 /* Routine io_registry_get_root_entry */
2645 kern_return_t
is_io_registry_get_root_entry(
2646 mach_port_t master_port
,
2649 IORegistryEntry
* entry
;
2651 if( master_port
!= master_device_port
)
2652 return( kIOReturnNotPrivileged
);
2654 entry
= IORegistryEntry::getRegistryRoot();
2659 return( kIOReturnSuccess
);
2662 /* Routine io_registry_create_iterator */
2663 kern_return_t
is_io_registry_create_iterator(
2664 mach_port_t master_port
,
2667 io_object_t
*iterator
)
2669 if( master_port
!= master_device_port
)
2670 return( kIOReturnNotPrivileged
);
2672 *iterator
= IOUserIterator::withIterator(
2673 IORegistryIterator::iterateOver(
2674 IORegistryEntry::getPlane( plane
), options
));
2676 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2679 /* Routine io_registry_entry_create_iterator */
2680 kern_return_t
is_io_registry_entry_create_iterator(
2681 io_object_t registry_entry
,
2684 io_object_t
*iterator
)
2686 CHECK( IORegistryEntry
, registry_entry
, entry
);
2688 *iterator
= IOUserIterator::withIterator(
2689 IORegistryIterator::iterateOver( entry
,
2690 IORegistryEntry::getPlane( plane
), options
));
2692 return( *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
);
2695 /* Routine io_registry_iterator_enter */
2696 kern_return_t
is_io_registry_iterator_enter_entry(
2697 io_object_t iterator
)
2699 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2701 IOLockLock(oIter
->lock
);
2703 IOLockUnlock(oIter
->lock
);
2705 return( kIOReturnSuccess
);
2708 /* Routine io_registry_iterator_exit */
2709 kern_return_t
is_io_registry_iterator_exit_entry(
2710 io_object_t iterator
)
2714 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
2716 IOLockLock(oIter
->lock
);
2717 didIt
= iter
->exitEntry();
2718 IOLockUnlock(oIter
->lock
);
2720 return( didIt
? kIOReturnSuccess
: kIOReturnNoDevice
);
2723 /* Routine io_registry_entry_from_path */
2724 kern_return_t
is_io_registry_entry_from_path(
2725 mach_port_t master_port
,
2727 io_object_t
*registry_entry
)
2729 IORegistryEntry
* entry
;
2731 if( master_port
!= master_device_port
)
2732 return( kIOReturnNotPrivileged
);
2734 entry
= IORegistryEntry::fromPath( path
);
2736 *registry_entry
= entry
;
2738 return( kIOReturnSuccess
);
2742 /* Routine io_registry_entry_from_path */
2743 kern_return_t
is_io_registry_entry_from_path_ool(
2744 mach_port_t master_port
,
2745 io_string_inband_t path
,
2746 io_buf_ptr_t path_ool
,
2747 mach_msg_type_number_t path_oolCnt
,
2748 kern_return_t
*result
,
2749 io_object_t
*registry_entry
)
2751 IORegistryEntry
* entry
;
2752 vm_map_offset_t map_data
;
2757 if (master_port
!= master_device_port
) return(kIOReturnNotPrivileged
);
2761 res
= err
= KERN_SUCCESS
;
2762 if (path
[0]) cpath
= path
;
2765 if (!path_oolCnt
) return(kIOReturnBadArgument
);
2766 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) return(kIOReturnMessageTooLarge
);
2768 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
2769 if (KERN_SUCCESS
== err
)
2771 // must return success to mig after vm_map_copyout() succeeds, so result is actual
2772 cpath
= CAST_DOWN(const char *, map_data
);
2773 if (cpath
[path_oolCnt
- 1]) res
= kIOReturnBadArgument
;
2777 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
))
2779 entry
= IORegistryEntry::fromPath(cpath
);
2780 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
2783 if (map_data
) vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
2785 if (KERN_SUCCESS
!= err
) res
= err
;
2786 *registry_entry
= entry
;
2793 /* Routine io_registry_entry_in_plane */
2794 kern_return_t
is_io_registry_entry_in_plane(
2795 io_object_t registry_entry
,
2797 boolean_t
*inPlane
)
2799 CHECK( IORegistryEntry
, registry_entry
, entry
);
2801 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
2803 return( kIOReturnSuccess
);
2807 /* Routine io_registry_entry_get_path */
2808 kern_return_t
is_io_registry_entry_get_path(
2809 io_object_t registry_entry
,
2814 CHECK( IORegistryEntry
, registry_entry
, entry
);
2816 length
= sizeof( io_string_t
);
2817 if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
)))
2818 return( kIOReturnSuccess
);
2820 return( kIOReturnBadArgument
);
2823 /* Routine io_registry_entry_get_path */
2824 kern_return_t
is_io_registry_entry_get_path_ool(
2825 io_object_t registry_entry
,
2827 io_string_inband_t path
,
2828 io_buf_ptr_t
*path_ool
,
2829 mach_msg_type_number_t
*path_oolCnt
)
2831 enum { kMaxPath
= 16384 };
2836 CHECK( IORegistryEntry
, registry_entry
, entry
);
2840 length
= sizeof(io_string_inband_t
);
2841 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnSuccess
;
2845 buf
= IONew(char, length
);
2846 if (!buf
) err
= kIOReturnNoMemory
;
2847 else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) err
= kIOReturnError
;
2850 *path_oolCnt
= length
;
2851 err
= copyoutkdata(buf
, length
, path_ool
);
2853 if (buf
) IODelete(buf
, char, kMaxPath
);
2860 /* Routine io_registry_entry_get_name */
2861 kern_return_t
is_io_registry_entry_get_name(
2862 io_object_t registry_entry
,
2865 CHECK( IORegistryEntry
, registry_entry
, entry
);
2867 strncpy( name
, entry
->getName(), sizeof( io_name_t
));
2869 return( kIOReturnSuccess
);
2872 /* Routine io_registry_entry_get_name_in_plane */
2873 kern_return_t
is_io_registry_entry_get_name_in_plane(
2874 io_object_t registry_entry
,
2875 io_name_t planeName
,
2878 const IORegistryPlane
* plane
;
2879 CHECK( IORegistryEntry
, registry_entry
, entry
);
2882 plane
= IORegistryEntry::getPlane( planeName
);
2886 strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
));
2888 return( kIOReturnSuccess
);
2891 /* Routine io_registry_entry_get_location_in_plane */
2892 kern_return_t
is_io_registry_entry_get_location_in_plane(
2893 io_object_t registry_entry
,
2894 io_name_t planeName
,
2895 io_name_t location
)
2897 const IORegistryPlane
* plane
;
2898 CHECK( IORegistryEntry
, registry_entry
, entry
);
2901 plane
= IORegistryEntry::getPlane( planeName
);
2905 const char * cstr
= entry
->getLocation( plane
);
2908 strncpy( location
, cstr
, sizeof( io_name_t
));
2909 return( kIOReturnSuccess
);
2911 return( kIOReturnNotFound
);
2914 /* Routine io_registry_entry_get_registry_entry_id */
2915 kern_return_t
is_io_registry_entry_get_registry_entry_id(
2916 io_object_t registry_entry
,
2917 uint64_t *entry_id
)
2919 CHECK( IORegistryEntry
, registry_entry
, entry
);
2921 *entry_id
= entry
->getRegistryEntryID();
2923 return (kIOReturnSuccess
);
2926 /* Routine io_registry_entry_get_property */
2927 kern_return_t
is_io_registry_entry_get_property_bytes(
2928 io_object_t registry_entry
,
2929 io_name_t property_name
,
2930 io_struct_inband_t buf
,
2931 mach_msg_type_number_t
*dataCnt
)
2939 unsigned int len
= 0;
2940 const void * bytes
= 0;
2941 IOReturn ret
= kIOReturnSuccess
;
2943 CHECK( IORegistryEntry
, registry_entry
, entry
);
2946 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
2947 return kIOReturnNotPermitted
;
2950 obj
= entry
->copyProperty(property_name
);
2952 return( kIOReturnNoResources
);
2954 // One day OSData will be a common container base class
2956 if( (data
= OSDynamicCast( OSData
, obj
))) {
2957 len
= data
->getLength();
2958 bytes
= data
->getBytesNoCopy();
2959 if (!data
->isSerializable()) len
= 0;
2961 } else if( (str
= OSDynamicCast( OSString
, obj
))) {
2962 len
= str
->getLength() + 1;
2963 bytes
= str
->getCStringNoCopy();
2965 } else if( (boo
= OSDynamicCast( OSBoolean
, obj
))) {
2966 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
2967 bytes
= boo
->isTrue() ? "Yes" : "No";
2969 } else if( (off
= OSDynamicCast( OSNumber
, obj
))) {
2970 offsetBytes
= off
->unsigned64BitValue();
2971 len
= off
->numberOfBytes();
2972 if (len
> sizeof(offsetBytes
)) len
= sizeof(offsetBytes
);
2973 bytes
= &offsetBytes
;
2974 #ifdef __BIG_ENDIAN__
2975 bytes
= (const void *)
2976 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
));
2980 ret
= kIOReturnBadArgument
;
2984 ret
= kIOReturnIPCError
;
2987 bcopy( bytes
, buf
, len
);
2996 /* Routine io_registry_entry_get_property */
2997 kern_return_t
is_io_registry_entry_get_property(
2998 io_object_t registry_entry
,
2999 io_name_t property_name
,
3000 io_buf_ptr_t
*properties
,
3001 mach_msg_type_number_t
*propertiesCnt
)
3007 CHECK( IORegistryEntry
, registry_entry
, entry
);
3010 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3011 return kIOReturnNotPermitted
;
3014 obj
= entry
->copyProperty(property_name
);
3016 return( kIOReturnNotFound
);
3018 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3021 return( kIOReturnNoMemory
);
3024 if( obj
->serialize( s
)) {
3025 len
= s
->getLength();
3026 *propertiesCnt
= len
;
3027 err
= copyoutkdata( s
->text(), len
, properties
);
3030 err
= kIOReturnUnsupported
;
3038 /* Routine io_registry_entry_get_property_recursively */
3039 kern_return_t
is_io_registry_entry_get_property_recursively(
3040 io_object_t registry_entry
,
3042 io_name_t property_name
,
3044 io_buf_ptr_t
*properties
,
3045 mach_msg_type_number_t
*propertiesCnt
)
3051 CHECK( IORegistryEntry
, registry_entry
, entry
);
3054 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3055 return kIOReturnNotPermitted
;
3058 obj
= entry
->copyProperty( property_name
,
3059 IORegistryEntry::getPlane( plane
), options
);
3061 return( kIOReturnNotFound
);
3063 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3066 return( kIOReturnNoMemory
);
3069 if( obj
->serialize( s
)) {
3070 len
= s
->getLength();
3071 *propertiesCnt
= len
;
3072 err
= copyoutkdata( s
->text(), len
, properties
);
3075 err
= kIOReturnUnsupported
;
3083 /* Routine io_registry_entry_get_properties */
3084 kern_return_t
is_io_registry_entry_get_properties(
3085 io_object_t registry_entry
,
3086 io_buf_ptr_t
*properties
,
3087 mach_msg_type_number_t
*propertiesCnt
)
3089 return (kIOReturnUnsupported
);
3094 struct GetPropertiesEditorRef
3097 IORegistryEntry
* entry
;
3098 OSCollection
* root
;
3101 static const OSMetaClassBase
*
3102 GetPropertiesEditor(void * reference
,
3104 OSCollection
* container
,
3105 const OSSymbol
* name
,
3106 const OSMetaClassBase
* value
)
3108 GetPropertiesEditorRef
* ref
= (typeof(ref
)) reference
;
3110 if (!ref
->root
) ref
->root
= container
;
3111 if (ref
->root
== container
)
3113 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy()))
3118 if (value
) value
->retain();
3122 #endif /* CONFIG_MACF */
3124 /* Routine io_registry_entry_get_properties */
3125 kern_return_t
is_io_registry_entry_get_properties_bin(
3126 io_object_t registry_entry
,
3127 io_buf_ptr_t
*properties
,
3128 mach_msg_type_number_t
*propertiesCnt
)
3130 kern_return_t err
= kIOReturnSuccess
;
3133 OSSerialize::Editor editor
= 0;
3136 CHECK(IORegistryEntry
, registry_entry
, entry
);
3139 GetPropertiesEditorRef ref
;
3140 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
))
3142 editor
= &GetPropertiesEditor
;
3144 ref
.cred
= kauth_cred_get();
3150 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
3151 if (!s
) return (kIOReturnNoMemory
);
3153 if (!entry
->serializeProperties(s
)) err
= kIOReturnUnsupported
;
3155 if (kIOReturnSuccess
== err
)
3157 len
= s
->getLength();
3158 *propertiesCnt
= len
;
3159 err
= copyoutkdata(s
->text(), len
, properties
);
3166 /* Routine io_registry_entry_get_property_bin */
3167 kern_return_t
is_io_registry_entry_get_property_bin(
3168 io_object_t registry_entry
,
3170 io_name_t property_name
,
3172 io_buf_ptr_t
*properties
,
3173 mach_msg_type_number_t
*propertiesCnt
)
3178 const OSSymbol
* sym
;
3180 CHECK( IORegistryEntry
, registry_entry
, entry
);
3183 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
))
3184 return kIOReturnNotPermitted
;
3187 sym
= OSSymbol::withCString(property_name
);
3188 if (!sym
) return (kIOReturnNoMemory
);
3190 if (gIORegistryEntryPropertyKeysKey
== sym
)
3192 obj
= entry
->copyPropertyKeys();
3196 if ((kIORegistryIterateRecursively
& options
) && plane
[0])
3198 obj
= entry
->copyProperty(property_name
,
3199 IORegistryEntry::getPlane(plane
), options
);
3203 obj
= entry
->copyProperty(property_name
);
3205 if (obj
&& gIORemoveOnReadProperties
->containsObject(sym
)) entry
->removeProperty(sym
);
3209 if (!obj
) return (kIOReturnNotFound
);
3211 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
3214 return( kIOReturnNoMemory
);
3217 if( obj
->serialize( s
)) {
3218 len
= s
->getLength();
3219 *propertiesCnt
= len
;
3220 err
= copyoutkdata( s
->text(), len
, properties
);
3222 } else err
= kIOReturnUnsupported
;
3231 /* Routine io_registry_entry_set_properties */
3232 kern_return_t is_io_registry_entry_set_properties
3234 io_object_t registry_entry
,
3235 io_buf_ptr_t properties
,
3236 mach_msg_type_number_t propertiesCnt
,
3237 kern_return_t
* result
)
3243 vm_map_offset_t map_data
;
3245 CHECK( IORegistryEntry
, registry_entry
, entry
);
3247 if( propertiesCnt
> sizeof(io_struct_inband_t
) * 1024)
3248 return( kIOReturnMessageTooLarge
);
3250 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3251 data
= CAST_DOWN(vm_offset_t
, map_data
);
3253 if( KERN_SUCCESS
== err
) {
3255 FAKE_STACK_FRAME(entry
->getMetaClass());
3257 // must return success after vm_map_copyout() succeeds
3258 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3259 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3262 res
= kIOReturnBadArgument
;
3264 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
3265 registry_entry
, obj
))
3267 res
= kIOReturnNotPermitted
;
3272 res
= entry
->setProperties( obj
);
3278 FAKE_STACK_FRAME_END();
3287 /* Routine io_registry_entry_get_child_iterator */
3288 kern_return_t
is_io_registry_entry_get_child_iterator(
3289 io_object_t registry_entry
,
3291 io_object_t
*iterator
)
3293 CHECK( IORegistryEntry
, registry_entry
, entry
);
3295 *iterator
= entry
->getChildIterator(
3296 IORegistryEntry::getPlane( plane
));
3298 return( kIOReturnSuccess
);
3301 /* Routine io_registry_entry_get_parent_iterator */
3302 kern_return_t
is_io_registry_entry_get_parent_iterator(
3303 io_object_t registry_entry
,
3305 io_object_t
*iterator
)
3307 CHECK( IORegistryEntry
, registry_entry
, entry
);
3309 *iterator
= entry
->getParentIterator(
3310 IORegistryEntry::getPlane( plane
));
3312 return( kIOReturnSuccess
);
3315 /* Routine io_service_get_busy_state */
3316 kern_return_t
is_io_service_get_busy_state(
3317 io_object_t _service
,
3318 uint32_t *busyState
)
3320 CHECK( IOService
, _service
, service
);
3322 *busyState
= service
->getBusyState();
3324 return( kIOReturnSuccess
);
3327 /* Routine io_service_get_state */
3328 kern_return_t
is_io_service_get_state(
3329 io_object_t _service
,
3331 uint32_t *busy_state
,
3332 uint64_t *accumulated_busy_time
)
3334 CHECK( IOService
, _service
, service
);
3336 *state
= service
->getState();
3337 *busy_state
= service
->getBusyState();
3338 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
3340 return( kIOReturnSuccess
);
3343 /* Routine io_service_wait_quiet */
3344 kern_return_t
is_io_service_wait_quiet(
3345 io_object_t _service
,
3346 mach_timespec_t wait_time
)
3350 CHECK( IOService
, _service
, service
);
3352 timeoutNS
= wait_time
.tv_sec
;
3353 timeoutNS
*= kSecondScale
;
3354 timeoutNS
+= wait_time
.tv_nsec
;
3356 return( service
->waitQuiet(timeoutNS
) );
3359 /* Routine io_service_request_probe */
3360 kern_return_t
is_io_service_request_probe(
3361 io_object_t _service
,
3364 CHECK( IOService
, _service
, service
);
3366 return( service
->requestProbe( options
));
3369 /* Routine io_service_get_authorization_id */
3370 kern_return_t
is_io_service_get_authorization_id(
3371 io_object_t _service
,
3372 uint64_t *authorization_id
)
3376 CHECK( IOService
, _service
, service
);
3378 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
3379 kIOClientPrivilegeAdministrator
);
3380 if( kIOReturnSuccess
!= kr
)
3383 *authorization_id
= service
->getAuthorizationID();
3388 /* Routine io_service_set_authorization_id */
3389 kern_return_t
is_io_service_set_authorization_id(
3390 io_object_t _service
,
3391 uint64_t authorization_id
)
3393 CHECK( IOService
, _service
, service
);
3395 return( service
->setAuthorizationID( authorization_id
) );
3398 /* Routine io_service_open_ndr */
3399 kern_return_t
is_io_service_open_extended(
3400 io_object_t _service
,
3402 uint32_t connect_type
,
3404 io_buf_ptr_t properties
,
3405 mach_msg_type_number_t propertiesCnt
,
3406 kern_return_t
* result
,
3407 io_object_t
*connection
)
3409 IOUserClient
* client
= 0;
3410 kern_return_t err
= KERN_SUCCESS
;
3411 IOReturn res
= kIOReturnSuccess
;
3412 OSDictionary
* propertiesDict
= 0;
3414 bool disallowAccess
;
3416 CHECK( IOService
, _service
, service
);
3418 if (!owningTask
) return (kIOReturnBadArgument
);
3419 assert(owningTask
== current_task());
3420 if (owningTask
!= current_task()) return (kIOReturnBadArgument
);
3424 if (properties
) return (kIOReturnUnsupported
);
3429 vm_map_offset_t map_data
;
3431 if( propertiesCnt
> sizeof(io_struct_inband_t
))
3432 return( kIOReturnMessageTooLarge
);
3434 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
3436 data
= CAST_DOWN(vm_offset_t
, map_data
);
3437 if (KERN_SUCCESS
== err
)
3439 // must return success after vm_map_copyout() succeeds
3440 obj
= OSUnserializeXML( (const char *) data
, propertiesCnt
);
3441 vm_deallocate( kernel_map
, data
, propertiesCnt
);
3442 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
3443 if (!propertiesDict
)
3445 res
= kIOReturnBadArgument
;
3450 if (kIOReturnSuccess
!= res
)
3454 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
3457 if (!propertiesDict
)
3458 propertiesDict
= OSDictionary::withCapacity(4);
3459 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
3463 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
3468 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
3469 connect_type
, propertiesDict
, &client
);
3472 propertiesDict
->release();
3474 if (res
== kIOReturnSuccess
)
3476 assert( OSDynamicCast(IOUserClient
, client
) );
3478 client
->sharedInstance
= (0 != client
->getProperty(kIOUserClientSharedInstanceKey
));
3479 client
->closed
= false;
3480 client
->lock
= IOLockAlloc();
3482 disallowAccess
= (crossEndian
3483 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
3484 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
3485 if (disallowAccess
) res
= kIOReturnUnsupported
;
3487 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
))
3488 res
= kIOReturnNotPermitted
;
3491 if (kIOReturnSuccess
== res
) res
= client
->registerOwner(owningTask
);
3493 if (kIOReturnSuccess
!= res
)
3495 IOStatisticsClientCall();
3496 client
->clientClose();
3501 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
3504 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
3505 creatorName
->release();
3507 client
->setTerminateDefer(service
, false);
3512 *connection
= client
;
3518 /* Routine io_service_close */
3519 kern_return_t
is_io_service_close(
3520 io_object_t connection
)
3523 if ((mappings
= OSDynamicCast(OSSet
, connection
)))
3524 return( kIOReturnSuccess
);
3526 CHECK( IOUserClient
, connection
, client
);
3528 IOStatisticsClientCall();
3530 if (client
->sharedInstance
|| OSCompareAndSwap8(0, 1, &client
->closed
))
3532 IOLockLock(client
->lock
);
3533 client
->clientClose();
3534 IOLockUnlock(client
->lock
);
3538 IOLog("ignored is_io_service_close(0x%qx,%s)\n",
3539 client
->getRegistryEntryID(), client
->getName());
3542 return( kIOReturnSuccess
);
3545 /* Routine io_connect_get_service */
3546 kern_return_t
is_io_connect_get_service(
3547 io_object_t connection
,
3548 io_object_t
*service
)
3550 IOService
* theService
;
3552 CHECK( IOUserClient
, connection
, client
);
3554 theService
= client
->getService();
3556 theService
->retain();
3558 *service
= theService
;
3560 return( theService
? kIOReturnSuccess
: kIOReturnUnsupported
);
3563 /* Routine io_connect_set_notification_port */
3564 kern_return_t
is_io_connect_set_notification_port(
3565 io_object_t connection
,
3566 uint32_t notification_type
,
3571 CHECK( IOUserClient
, connection
, client
);
3573 IOStatisticsClientCall();
3574 IOLockLock(client
->lock
);
3575 ret
= client
->registerNotificationPort( port
, notification_type
,
3576 (io_user_reference_t
) reference
);
3577 IOLockUnlock(client
->lock
);
3581 /* Routine io_connect_set_notification_port */
3582 kern_return_t
is_io_connect_set_notification_port_64(
3583 io_object_t connection
,
3584 uint32_t notification_type
,
3586 io_user_reference_t reference
)
3589 CHECK( IOUserClient
, connection
, client
);
3591 IOStatisticsClientCall();
3592 IOLockLock(client
->lock
);
3593 ret
= client
->registerNotificationPort( port
, notification_type
,
3595 IOLockUnlock(client
->lock
);
3599 /* Routine io_connect_map_memory_into_task */
3600 kern_return_t is_io_connect_map_memory_into_task
3602 io_connect_t connection
,
3603 uint32_t memory_type
,
3605 mach_vm_address_t
*address
,
3606 mach_vm_size_t
*size
,
3613 CHECK( IOUserClient
, connection
, client
);
3615 if (!into_task
) return (kIOReturnBadArgument
);
3617 IOStatisticsClientCall();
3618 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
3621 *address
= map
->getAddress();
3623 *size
= map
->getSize();
3625 if( client
->sharedInstance
3626 || (into_task
!= current_task())) {
3627 // push a name out to the task owning the map,
3628 // so we can clean up maps
3629 mach_port_name_t name __unused
=
3630 IOMachPort::makeSendRightForTask(
3631 into_task
, map
, IKOT_IOKIT_OBJECT
);
3635 // keep it with the user client
3636 IOLockLock( gIOObjectPortLock
);
3637 if( 0 == client
->mappings
)
3638 client
->mappings
= OSSet::withCapacity(2);
3639 if( client
->mappings
)
3640 client
->mappings
->setObject( map
);
3641 IOLockUnlock( gIOObjectPortLock
);
3644 err
= kIOReturnSuccess
;
3647 err
= kIOReturnBadArgument
;
3652 /* Routine is_io_connect_map_memory */
3653 kern_return_t
is_io_connect_map_memory(
3654 io_object_t connect
,
3662 mach_vm_address_t address
;
3663 mach_vm_size_t size
;
3665 address
= SCALAR64(*mapAddr
);
3666 size
= SCALAR64(*mapSize
);
3668 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
3670 *mapAddr
= SCALAR32(address
);
3671 *mapSize
= SCALAR32(size
);
3678 IOMemoryMap
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
3681 IOMemoryMap
* map
= 0;
3683 IOLockLock(gIOObjectPortLock
);
3685 iter
= OSCollectionIterator::withCollection(mappings
);
3688 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject())))
3690 if(mem
== map
->getMemoryDescriptor())
3693 mappings
->removeObject(map
);
3700 IOLockUnlock(gIOObjectPortLock
);
3707 /* Routine io_connect_unmap_memory_from_task */
3708 kern_return_t is_io_connect_unmap_memory_from_task
3710 io_connect_t connection
,
3711 uint32_t memory_type
,
3713 mach_vm_address_t address
)
3716 IOOptionBits options
= 0;
3717 IOMemoryDescriptor
* memory
= 0;
3720 CHECK( IOUserClient
, connection
, client
);
3722 if (!from_task
) return (kIOReturnBadArgument
);
3724 IOStatisticsClientCall();
3725 err
= client
->clientMemoryForType( (UInt32
) memory_type
, &options
, &memory
);
3727 if( memory
&& (kIOReturnSuccess
== err
)) {
3729 options
= (options
& ~kIOMapUserOptionsMask
)
3730 | kIOMapAnywhere
| kIOMapReference
;
3732 map
= memory
->createMappingInTask( from_task
, address
, options
);
3736 IOLockLock( gIOObjectPortLock
);
3737 if( client
->mappings
)
3738 client
->mappings
->removeObject( map
);
3739 IOLockUnlock( gIOObjectPortLock
);
3741 mach_port_name_t name
= 0;
3742 if (from_task
!= current_task())
3744 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
3750 map
->userClientUnmap();
3751 err
= iokit_mod_send_right( from_task
, name
, -2 );
3752 err
= kIOReturnSuccess
;
3755 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
3756 if (from_task
== current_task())
3760 err
= kIOReturnBadArgument
;
3766 kern_return_t
is_io_connect_unmap_memory(
3767 io_object_t connect
,
3773 mach_vm_address_t address
;
3775 address
= SCALAR64(mapAddr
);
3777 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
3783 /* Routine io_connect_add_client */
3784 kern_return_t
is_io_connect_add_client(
3785 io_object_t connection
,
3786 io_object_t connect_to
)
3788 CHECK( IOUserClient
, connection
, client
);
3789 CHECK( IOUserClient
, connect_to
, to
);
3791 IOStatisticsClientCall();
3792 return( client
->connectClient( to
) );
3796 /* Routine io_connect_set_properties */
3797 kern_return_t
is_io_connect_set_properties(
3798 io_object_t connection
,
3799 io_buf_ptr_t properties
,
3800 mach_msg_type_number_t propertiesCnt
,
3801 kern_return_t
* result
)
3803 return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
));
3806 /* Routine io_user_client_method */
3807 kern_return_t is_io_connect_method_var_output
3809 io_connect_t connection
,
3811 io_scalar_inband64_t scalar_input
,
3812 mach_msg_type_number_t scalar_inputCnt
,
3813 io_struct_inband_t inband_input
,
3814 mach_msg_type_number_t inband_inputCnt
,
3815 mach_vm_address_t ool_input
,
3816 mach_vm_size_t ool_input_size
,
3817 io_struct_inband_t inband_output
,
3818 mach_msg_type_number_t
*inband_outputCnt
,
3819 io_scalar_inband64_t scalar_output
,
3820 mach_msg_type_number_t
*scalar_outputCnt
,
3821 io_buf_ptr_t
*var_output
,
3822 mach_msg_type_number_t
*var_outputCnt
3825 CHECK( IOUserClient
, connection
, client
);
3827 IOExternalMethodArguments args
;
3829 IOMemoryDescriptor
* inputMD
= 0;
3830 OSObject
* structureVariableOutputData
= 0;
3832 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3833 args
.__reservedA
= 0;
3834 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3836 args
.selector
= selector
;
3838 args
.asyncWakePort
= MACH_PORT_NULL
;
3839 args
.asyncReference
= 0;
3840 args
.asyncReferenceCount
= 0;
3841 args
.structureVariableOutputData
= &structureVariableOutputData
;
3843 args
.scalarInput
= scalar_input
;
3844 args
.scalarInputCount
= scalar_inputCnt
;
3845 args
.structureInput
= inband_input
;
3846 args
.structureInputSize
= inband_inputCnt
;
3848 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
3851 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3852 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
3855 args
.structureInputDescriptor
= inputMD
;
3857 args
.scalarOutput
= scalar_output
;
3858 args
.scalarOutputCount
= *scalar_outputCnt
;
3859 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3860 args
.structureOutput
= inband_output
;
3861 args
.structureOutputSize
= *inband_outputCnt
;
3862 args
.structureOutputDescriptor
= NULL
;
3863 args
.structureOutputDescriptorSize
= 0;
3865 IOStatisticsClientCall();
3866 ret
= client
->externalMethod( selector
, &args
);
3868 *scalar_outputCnt
= args
.scalarOutputCount
;
3869 *inband_outputCnt
= args
.structureOutputSize
;
3871 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
))
3873 OSSerialize
* serialize
;
3877 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
)))
3879 len
= serialize
->getLength();
3880 *var_outputCnt
= len
;
3881 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
3883 else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
)))
3885 len
= data
->getLength();
3886 *var_outputCnt
= len
;
3887 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
3891 ret
= kIOReturnUnderrun
;
3897 if (structureVariableOutputData
)
3898 structureVariableOutputData
->release();
3903 /* Routine io_user_client_method */
3904 kern_return_t is_io_connect_method
3906 io_connect_t connection
,
3908 io_scalar_inband64_t scalar_input
,
3909 mach_msg_type_number_t scalar_inputCnt
,
3910 io_struct_inband_t inband_input
,
3911 mach_msg_type_number_t inband_inputCnt
,
3912 mach_vm_address_t ool_input
,
3913 mach_vm_size_t ool_input_size
,
3914 io_struct_inband_t inband_output
,
3915 mach_msg_type_number_t
*inband_outputCnt
,
3916 io_scalar_inband64_t scalar_output
,
3917 mach_msg_type_number_t
*scalar_outputCnt
,
3918 mach_vm_address_t ool_output
,
3919 mach_vm_size_t
*ool_output_size
3922 CHECK( IOUserClient
, connection
, client
);
3924 IOExternalMethodArguments args
;
3926 IOMemoryDescriptor
* inputMD
= 0;
3927 IOMemoryDescriptor
* outputMD
= 0;
3929 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
3930 args
.__reservedA
= 0;
3931 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
3933 args
.selector
= selector
;
3935 args
.asyncWakePort
= MACH_PORT_NULL
;
3936 args
.asyncReference
= 0;
3937 args
.asyncReferenceCount
= 0;
3938 args
.structureVariableOutputData
= 0;
3940 args
.scalarInput
= scalar_input
;
3941 args
.scalarInputCount
= scalar_inputCnt
;
3942 args
.structureInput
= inband_input
;
3943 args
.structureInputSize
= inband_inputCnt
;
3945 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
3946 if (ool_output
&& (*ool_output_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
3949 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
3950 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
3953 args
.structureInputDescriptor
= inputMD
;
3955 args
.scalarOutput
= scalar_output
;
3956 args
.scalarOutputCount
= *scalar_outputCnt
;
3957 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
3958 args
.structureOutput
= inband_output
;
3959 args
.structureOutputSize
= *inband_outputCnt
;
3961 if (ool_output
&& ool_output_size
)
3963 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
3964 kIODirectionIn
, current_task());
3967 args
.structureOutputDescriptor
= outputMD
;
3968 args
.structureOutputDescriptorSize
= ool_output_size
? *ool_output_size
: 0;
3970 IOStatisticsClientCall();
3971 ret
= client
->externalMethod( selector
, &args
);
3973 *scalar_outputCnt
= args
.scalarOutputCount
;
3974 *inband_outputCnt
= args
.structureOutputSize
;
3975 *ool_output_size
= args
.structureOutputDescriptorSize
;
3980 outputMD
->release();
3985 /* Routine io_async_user_client_method */
3986 kern_return_t is_io_connect_async_method
3988 io_connect_t connection
,
3989 mach_port_t wake_port
,
3990 io_async_ref64_t reference
,
3991 mach_msg_type_number_t referenceCnt
,
3993 io_scalar_inband64_t scalar_input
,
3994 mach_msg_type_number_t scalar_inputCnt
,
3995 io_struct_inband_t inband_input
,
3996 mach_msg_type_number_t inband_inputCnt
,
3997 mach_vm_address_t ool_input
,
3998 mach_vm_size_t ool_input_size
,
3999 io_struct_inband_t inband_output
,
4000 mach_msg_type_number_t
*inband_outputCnt
,
4001 io_scalar_inband64_t scalar_output
,
4002 mach_msg_type_number_t
*scalar_outputCnt
,
4003 mach_vm_address_t ool_output
,
4004 mach_vm_size_t
* ool_output_size
4007 CHECK( IOUserClient
, connection
, client
);
4009 IOExternalMethodArguments args
;
4011 IOMemoryDescriptor
* inputMD
= 0;
4012 IOMemoryDescriptor
* outputMD
= 0;
4014 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4015 args
.__reservedA
= 0;
4016 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4018 reference
[0] = (io_user_reference_t
) wake_port
;
4019 if (vm_map_is_64bit(get_task_map(current_task())))
4020 reference
[0] |= kIOUCAsync64Flag
;
4022 args
.selector
= selector
;
4024 args
.asyncWakePort
= wake_port
;
4025 args
.asyncReference
= reference
;
4026 args
.asyncReferenceCount
= referenceCnt
;
4028 args
.structureVariableOutputData
= 0;
4030 args
.scalarInput
= scalar_input
;
4031 args
.scalarInputCount
= scalar_inputCnt
;
4032 args
.structureInput
= inband_input
;
4033 args
.structureInputSize
= inband_inputCnt
;
4035 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
4036 if (ool_output
&& (*ool_output_size
<= sizeof(io_struct_inband_t
))) return (kIOReturnIPCError
);
4039 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4040 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4043 args
.structureInputDescriptor
= inputMD
;
4045 args
.scalarOutput
= scalar_output
;
4046 args
.scalarOutputCount
= *scalar_outputCnt
;
4047 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4048 args
.structureOutput
= inband_output
;
4049 args
.structureOutputSize
= *inband_outputCnt
;
4053 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
4054 kIODirectionIn
, current_task());
4057 args
.structureOutputDescriptor
= outputMD
;
4058 args
.structureOutputDescriptorSize
= *ool_output_size
;
4060 IOStatisticsClientCall();
4061 ret
= client
->externalMethod( selector
, &args
);
4063 *inband_outputCnt
= args
.structureOutputSize
;
4064 *ool_output_size
= args
.structureOutputDescriptorSize
;
4069 outputMD
->release();
4074 /* Routine io_connect_method_scalarI_scalarO */
4075 kern_return_t
is_io_connect_method_scalarI_scalarO(
4076 io_object_t connect
,
4078 io_scalar_inband_t input
,
4079 mach_msg_type_number_t inputCount
,
4080 io_scalar_inband_t output
,
4081 mach_msg_type_number_t
* outputCount
)
4085 io_scalar_inband64_t _input
;
4086 io_scalar_inband64_t _output
;
4088 mach_msg_type_number_t struct_outputCnt
= 0;
4089 mach_vm_size_t ool_output_size
= 0;
4091 bzero(&_output
[0], sizeof(_output
));
4092 for (i
= 0; i
< inputCount
; i
++)
4093 _input
[i
] = SCALAR64(input
[i
]);
4095 err
= is_io_connect_method(connect
, index
,
4099 NULL
, &struct_outputCnt
,
4100 _output
, outputCount
,
4101 0, &ool_output_size
);
4103 for (i
= 0; i
< *outputCount
; i
++)
4104 output
[i
] = SCALAR32(_output
[i
]);
4109 kern_return_t
shim_io_connect_method_scalarI_scalarO(
4110 IOExternalMethod
* method
,
4112 const io_user_scalar_t
* input
,
4113 mach_msg_type_number_t inputCount
,
4114 io_user_scalar_t
* output
,
4115 mach_msg_type_number_t
* outputCount
)
4118 io_scalar_inband_t _output
;
4120 err
= kIOReturnBadArgument
;
4122 bzero(&_output
[0], sizeof(_output
));
4125 if( inputCount
!= method
->count0
)
4127 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4128 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4131 if( *outputCount
!= method
->count1
)
4133 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4134 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4138 func
= method
->func
;
4140 switch( inputCount
) {
4143 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4144 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4147 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4148 ARG32(input
[3]), ARG32(input
[4]),
4152 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4154 &_output
[0], &_output
[1] );
4157 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4158 &_output
[0], &_output
[1], &_output
[2] );
4161 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4162 &_output
[0], &_output
[1], &_output
[2],
4166 err
= (object
->*func
)( ARG32(input
[0]),
4167 &_output
[0], &_output
[1], &_output
[2],
4168 &_output
[3], &_output
[4] );
4171 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
4172 &_output
[3], &_output
[4], &_output
[5] );
4176 IOLog("%s: Bad method table\n", object
->getName());
4182 for (i
= 0; i
< *outputCount
; i
++)
4183 output
[i
] = SCALAR32(_output
[i
]);
4188 /* Routine io_async_method_scalarI_scalarO */
4189 kern_return_t
is_io_async_method_scalarI_scalarO(
4190 io_object_t connect
,
4191 mach_port_t wake_port
,
4192 io_async_ref_t reference
,
4193 mach_msg_type_number_t referenceCnt
,
4195 io_scalar_inband_t input
,
4196 mach_msg_type_number_t inputCount
,
4197 io_scalar_inband_t output
,
4198 mach_msg_type_number_t
* outputCount
)
4202 io_scalar_inband64_t _input
;
4203 io_scalar_inband64_t _output
;
4204 io_async_ref64_t _reference
;
4206 bzero(&_output
[0], sizeof(_output
));
4207 for (i
= 0; i
< referenceCnt
; i
++)
4208 _reference
[i
] = REF64(reference
[i
]);
4210 mach_msg_type_number_t struct_outputCnt
= 0;
4211 mach_vm_size_t ool_output_size
= 0;
4213 for (i
= 0; i
< inputCount
; i
++)
4214 _input
[i
] = SCALAR64(input
[i
]);
4216 err
= is_io_connect_async_method(connect
,
4217 wake_port
, _reference
, referenceCnt
,
4222 NULL
, &struct_outputCnt
,
4223 _output
, outputCount
,
4224 0, &ool_output_size
);
4226 for (i
= 0; i
< *outputCount
; i
++)
4227 output
[i
] = SCALAR32(_output
[i
]);
4231 /* Routine io_async_method_scalarI_structureO */
4232 kern_return_t
is_io_async_method_scalarI_structureO(
4233 io_object_t connect
,
4234 mach_port_t wake_port
,
4235 io_async_ref_t reference
,
4236 mach_msg_type_number_t referenceCnt
,
4238 io_scalar_inband_t input
,
4239 mach_msg_type_number_t inputCount
,
4240 io_struct_inband_t output
,
4241 mach_msg_type_number_t
* outputCount
)
4244 io_scalar_inband64_t _input
;
4245 io_async_ref64_t _reference
;
4247 for (i
= 0; i
< referenceCnt
; i
++)
4248 _reference
[i
] = REF64(reference
[i
]);
4250 mach_msg_type_number_t scalar_outputCnt
= 0;
4251 mach_vm_size_t ool_output_size
= 0;
4253 for (i
= 0; i
< inputCount
; i
++)
4254 _input
[i
] = SCALAR64(input
[i
]);
4256 return (is_io_connect_async_method(connect
,
4257 wake_port
, _reference
, referenceCnt
,
4262 output
, outputCount
,
4263 NULL
, &scalar_outputCnt
,
4264 0, &ool_output_size
));
4267 /* Routine io_async_method_scalarI_structureI */
4268 kern_return_t
is_io_async_method_scalarI_structureI(
4269 io_connect_t connect
,
4270 mach_port_t wake_port
,
4271 io_async_ref_t reference
,
4272 mach_msg_type_number_t referenceCnt
,
4274 io_scalar_inband_t input
,
4275 mach_msg_type_number_t inputCount
,
4276 io_struct_inband_t inputStruct
,
4277 mach_msg_type_number_t inputStructCount
)
4280 io_scalar_inband64_t _input
;
4281 io_async_ref64_t _reference
;
4283 for (i
= 0; i
< referenceCnt
; i
++)
4284 _reference
[i
] = REF64(reference
[i
]);
4286 mach_msg_type_number_t scalar_outputCnt
= 0;
4287 mach_msg_type_number_t inband_outputCnt
= 0;
4288 mach_vm_size_t ool_output_size
= 0;
4290 for (i
= 0; i
< inputCount
; i
++)
4291 _input
[i
] = SCALAR64(input
[i
]);
4293 return (is_io_connect_async_method(connect
,
4294 wake_port
, _reference
, referenceCnt
,
4297 inputStruct
, inputStructCount
,
4299 NULL
, &inband_outputCnt
,
4300 NULL
, &scalar_outputCnt
,
4301 0, &ool_output_size
));
4304 /* Routine io_async_method_structureI_structureO */
4305 kern_return_t
is_io_async_method_structureI_structureO(
4306 io_object_t connect
,
4307 mach_port_t wake_port
,
4308 io_async_ref_t reference
,
4309 mach_msg_type_number_t referenceCnt
,
4311 io_struct_inband_t input
,
4312 mach_msg_type_number_t inputCount
,
4313 io_struct_inband_t output
,
4314 mach_msg_type_number_t
* outputCount
)
4317 mach_msg_type_number_t scalar_outputCnt
= 0;
4318 mach_vm_size_t ool_output_size
= 0;
4319 io_async_ref64_t _reference
;
4321 for (i
= 0; i
< referenceCnt
; i
++)
4322 _reference
[i
] = REF64(reference
[i
]);
4324 return (is_io_connect_async_method(connect
,
4325 wake_port
, _reference
, referenceCnt
,
4330 output
, outputCount
,
4331 NULL
, &scalar_outputCnt
,
4332 0, &ool_output_size
));
4336 kern_return_t
shim_io_async_method_scalarI_scalarO(
4337 IOExternalAsyncMethod
* method
,
4339 mach_port_t asyncWakePort
,
4340 io_user_reference_t
* asyncReference
,
4341 uint32_t asyncReferenceCount
,
4342 const io_user_scalar_t
* input
,
4343 mach_msg_type_number_t inputCount
,
4344 io_user_scalar_t
* output
,
4345 mach_msg_type_number_t
* outputCount
)
4349 io_scalar_inband_t _output
;
4351 io_async_ref_t reference
;
4353 bzero(&_output
[0], sizeof(_output
));
4354 for (i
= 0; i
< asyncReferenceCount
; i
++)
4355 reference
[i
] = REF32(asyncReference
[i
]);
4357 err
= kIOReturnBadArgument
;
4361 if( inputCount
!= method
->count0
)
4363 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4364 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4367 if( *outputCount
!= method
->count1
)
4369 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
4370 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4374 func
= method
->func
;
4376 switch( inputCount
) {
4379 err
= (object
->*func
)( reference
,
4380 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4381 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]) );
4384 err
= (object
->*func
)( reference
,
4385 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4386 ARG32(input
[3]), ARG32(input
[4]),
4390 err
= (object
->*func
)( reference
,
4391 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4393 &_output
[0], &_output
[1] );
4396 err
= (object
->*func
)( reference
,
4397 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4398 &_output
[0], &_output
[1], &_output
[2] );
4401 err
= (object
->*func
)( reference
,
4402 ARG32(input
[0]), ARG32(input
[1]),
4403 &_output
[0], &_output
[1], &_output
[2],
4407 err
= (object
->*func
)( reference
,
4409 &_output
[0], &_output
[1], &_output
[2],
4410 &_output
[3], &_output
[4] );
4413 err
= (object
->*func
)( reference
,
4414 &_output
[0], &_output
[1], &_output
[2],
4415 &_output
[3], &_output
[4], &_output
[5] );
4419 IOLog("%s: Bad method table\n", object
->getName());
4424 for (i
= 0; i
< *outputCount
; i
++)
4425 output
[i
] = SCALAR32(_output
[i
]);
4431 /* Routine io_connect_method_scalarI_structureO */
4432 kern_return_t
is_io_connect_method_scalarI_structureO(
4433 io_object_t connect
,
4435 io_scalar_inband_t input
,
4436 mach_msg_type_number_t inputCount
,
4437 io_struct_inband_t output
,
4438 mach_msg_type_number_t
* outputCount
)
4441 io_scalar_inband64_t _input
;
4443 mach_msg_type_number_t scalar_outputCnt
= 0;
4444 mach_vm_size_t ool_output_size
= 0;
4446 for (i
= 0; i
< inputCount
; i
++)
4447 _input
[i
] = SCALAR64(input
[i
]);
4449 return (is_io_connect_method(connect
, index
,
4453 output
, outputCount
,
4454 NULL
, &scalar_outputCnt
,
4455 0, &ool_output_size
));
4458 kern_return_t
shim_io_connect_method_scalarI_structureO(
4460 IOExternalMethod
* method
,
4462 const io_user_scalar_t
* input
,
4463 mach_msg_type_number_t inputCount
,
4464 io_struct_inband_t output
,
4465 IOByteCount
* outputCount
)
4470 err
= kIOReturnBadArgument
;
4473 if( inputCount
!= method
->count0
)
4475 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4476 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4479 if( (kIOUCVariableStructureSize
!= method
->count1
)
4480 && (*outputCount
!= method
->count1
))
4482 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
);
4483 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4487 func
= method
->func
;
4489 switch( inputCount
) {
4492 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4493 ARG32(input
[3]), ARG32(input
[4]),
4497 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4499 output
, (void *)outputCount
);
4502 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4503 output
, (void *)outputCount
, 0 );
4506 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4507 output
, (void *)outputCount
, 0, 0 );
4510 err
= (object
->*func
)( ARG32(input
[0]),
4511 output
, (void *)outputCount
, 0, 0, 0 );
4514 err
= (object
->*func
)( output
, (void *)outputCount
, 0, 0, 0, 0 );
4518 IOLog("%s: Bad method table\n", object
->getName());
4527 kern_return_t
shim_io_async_method_scalarI_structureO(
4528 IOExternalAsyncMethod
* method
,
4530 mach_port_t asyncWakePort
,
4531 io_user_reference_t
* asyncReference
,
4532 uint32_t asyncReferenceCount
,
4533 const io_user_scalar_t
* input
,
4534 mach_msg_type_number_t inputCount
,
4535 io_struct_inband_t output
,
4536 mach_msg_type_number_t
* outputCount
)
4541 io_async_ref_t reference
;
4543 for (i
= 0; i
< asyncReferenceCount
; i
++)
4544 reference
[i
] = REF32(asyncReference
[i
]);
4546 err
= kIOReturnBadArgument
;
4548 if( inputCount
!= method
->count0
)
4550 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4551 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4554 if( (kIOUCVariableStructureSize
!= method
->count1
)
4555 && (*outputCount
!= method
->count1
))
4557 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
);
4558 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4562 func
= method
->func
;
4564 switch( inputCount
) {
4567 err
= (object
->*func
)( reference
,
4568 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4569 ARG32(input
[3]), ARG32(input
[4]),
4573 err
= (object
->*func
)( reference
,
4574 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4576 output
, (void *)outputCount
);
4579 err
= (object
->*func
)( reference
,
4580 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4581 output
, (void *)outputCount
, 0 );
4584 err
= (object
->*func
)( reference
,
4585 ARG32(input
[0]), ARG32(input
[1]),
4586 output
, (void *)outputCount
, 0, 0 );
4589 err
= (object
->*func
)( reference
,
4591 output
, (void *)outputCount
, 0, 0, 0 );
4594 err
= (object
->*func
)( reference
,
4595 output
, (void *)outputCount
, 0, 0, 0, 0 );
4599 IOLog("%s: Bad method table\n", object
->getName());
4607 /* Routine io_connect_method_scalarI_structureI */
4608 kern_return_t
is_io_connect_method_scalarI_structureI(
4609 io_connect_t connect
,
4611 io_scalar_inband_t input
,
4612 mach_msg_type_number_t inputCount
,
4613 io_struct_inband_t inputStruct
,
4614 mach_msg_type_number_t inputStructCount
)
4617 io_scalar_inband64_t _input
;
4619 mach_msg_type_number_t scalar_outputCnt
= 0;
4620 mach_msg_type_number_t inband_outputCnt
= 0;
4621 mach_vm_size_t ool_output_size
= 0;
4623 for (i
= 0; i
< inputCount
; i
++)
4624 _input
[i
] = SCALAR64(input
[i
]);
4626 return (is_io_connect_method(connect
, index
,
4628 inputStruct
, inputStructCount
,
4630 NULL
, &inband_outputCnt
,
4631 NULL
, &scalar_outputCnt
,
4632 0, &ool_output_size
));
4635 kern_return_t
shim_io_connect_method_scalarI_structureI(
4636 IOExternalMethod
* method
,
4638 const io_user_scalar_t
* input
,
4639 mach_msg_type_number_t inputCount
,
4640 io_struct_inband_t inputStruct
,
4641 mach_msg_type_number_t inputStructCount
)
4644 IOReturn err
= kIOReturnBadArgument
;
4648 if (inputCount
!= method
->count0
)
4650 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4651 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4654 if( (kIOUCVariableStructureSize
!= method
->count1
)
4655 && (inputStructCount
!= method
->count1
))
4657 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
);
4658 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
4662 func
= method
->func
;
4664 switch( inputCount
) {
4667 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4668 ARG32(input
[3]), ARG32(input
[4]),
4672 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
4674 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4677 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4678 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4682 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
4683 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4687 err
= (object
->*func
)( ARG32(input
[0]),
4688 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4692 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
4697 IOLog("%s: Bad method table\n", object
->getName());
4705 kern_return_t
shim_io_async_method_scalarI_structureI(
4706 IOExternalAsyncMethod
* method
,
4708 mach_port_t asyncWakePort
,
4709 io_user_reference_t
* asyncReference
,
4710 uint32_t asyncReferenceCount
,
4711 const io_user_scalar_t
* input
,
4712 mach_msg_type_number_t inputCount
,
4713 io_struct_inband_t inputStruct
,
4714 mach_msg_type_number_t inputStructCount
)
4718 IOReturn err
= kIOReturnBadArgument
;
4719 io_async_ref_t reference
;
4721 for (i
= 0; i
< asyncReferenceCount
; i
++)
4722 reference
[i
] = REF32(asyncReference
[i
]);
4726 if (inputCount
!= method
->count0
)
4728 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
4729 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4732 if( (kIOUCVariableStructureSize
!= method
->count1
)
4733 && (inputStructCount
!= method
->count1
))
4735 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
);
4736 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
4740 func
= method
->func
;
4742 switch( inputCount
) {
4745 err
= (object
->*func
)( reference
,
4746 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4747 ARG32(input
[3]), ARG32(input
[4]),
4751 err
= (object
->*func
)( reference
,
4752 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4754 inputStruct
, (void *)(uintptr_t)inputStructCount
);
4757 err
= (object
->*func
)( reference
,
4758 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
4759 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4763 err
= (object
->*func
)( reference
,
4764 ARG32(input
[0]), ARG32(input
[1]),
4765 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4769 err
= (object
->*func
)( reference
,
4771 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4775 err
= (object
->*func
)( reference
,
4776 inputStruct
, (void *)(uintptr_t)inputStructCount
,
4781 IOLog("%s: Bad method table\n", object
->getName());
4789 /* Routine io_connect_method_structureI_structureO */
4790 kern_return_t
is_io_connect_method_structureI_structureO(
4791 io_object_t connect
,
4793 io_struct_inband_t input
,
4794 mach_msg_type_number_t inputCount
,
4795 io_struct_inband_t output
,
4796 mach_msg_type_number_t
* outputCount
)
4798 mach_msg_type_number_t scalar_outputCnt
= 0;
4799 mach_vm_size_t ool_output_size
= 0;
4801 return (is_io_connect_method(connect
, index
,
4805 output
, outputCount
,
4806 NULL
, &scalar_outputCnt
,
4807 0, &ool_output_size
));
4810 kern_return_t
shim_io_connect_method_structureI_structureO(
4811 IOExternalMethod
* method
,
4813 io_struct_inband_t input
,
4814 mach_msg_type_number_t inputCount
,
4815 io_struct_inband_t output
,
4816 IOByteCount
* outputCount
)
4819 IOReturn err
= kIOReturnBadArgument
;
4823 if( (kIOUCVariableStructureSize
!= method
->count0
)
4824 && (inputCount
!= method
->count0
))
4826 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
);
4827 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4830 if( (kIOUCVariableStructureSize
!= method
->count1
)
4831 && (*outputCount
!= method
->count1
))
4833 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
);
4834 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4838 func
= method
->func
;
4840 if( method
->count1
) {
4841 if( method
->count0
) {
4842 err
= (object
->*func
)( input
, output
,
4843 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4845 err
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 );
4848 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4857 kern_return_t
shim_io_async_method_structureI_structureO(
4858 IOExternalAsyncMethod
* method
,
4860 mach_port_t asyncWakePort
,
4861 io_user_reference_t
* asyncReference
,
4862 uint32_t asyncReferenceCount
,
4863 io_struct_inband_t input
,
4864 mach_msg_type_number_t inputCount
,
4865 io_struct_inband_t output
,
4866 mach_msg_type_number_t
* outputCount
)
4871 io_async_ref_t reference
;
4873 for (i
= 0; i
< asyncReferenceCount
; i
++)
4874 reference
[i
] = REF32(asyncReference
[i
]);
4876 err
= kIOReturnBadArgument
;
4879 if( (kIOUCVariableStructureSize
!= method
->count0
)
4880 && (inputCount
!= method
->count0
))
4882 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
);
4883 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
4886 if( (kIOUCVariableStructureSize
!= method
->count1
)
4887 && (*outputCount
!= method
->count1
))
4889 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
);
4890 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
4894 func
= method
->func
;
4896 if( method
->count1
) {
4897 if( method
->count0
) {
4898 err
= (object
->*func
)( reference
,
4900 (void *)(uintptr_t)inputCount
, outputCount
, 0, 0 );
4902 err
= (object
->*func
)( reference
,
4903 output
, outputCount
, 0, 0, 0, 0 );
4906 err
= (object
->*func
)( reference
,
4907 input
, (void *)(uintptr_t)inputCount
, 0, 0, 0, 0 );
4916 bool gIOKextdClearedBusy
= false;
4919 /* Routine io_catalog_send_data */
4920 kern_return_t
is_io_catalog_send_data(
4921 mach_port_t master_port
,
4923 io_buf_ptr_t inData
,
4924 mach_msg_type_number_t inDataCount
,
4925 kern_return_t
* result
)
4928 return kIOReturnNotPrivileged
;
4929 #else /* NO_KEXTD */
4932 kern_return_t kr
= kIOReturnError
;
4934 //printf("io_catalog_send_data called. flag: %d\n", flag);
4936 if( master_port
!= master_device_port
)
4937 return kIOReturnNotPrivileged
;
4939 if( (flag
!= kIOCatalogRemoveKernelLinker
&&
4940 flag
!= kIOCatalogKextdActive
&&
4941 flag
!= kIOCatalogKextdFinishedLaunching
) &&
4942 ( !inData
|| !inDataCount
) )
4944 return kIOReturnBadArgument
;
4947 if (!IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management"))
4949 OSString
* taskName
= IOCopyLogNameForPID(proc_selfpid());
4950 IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName
? taskName
->getCStringNoCopy() : "");
4951 OSSafeReleaseNULL(taskName
);
4952 // For now, fake success to not break applications relying on this function succeeding.
4953 // See <rdar://problem/32554970> for more details.
4954 return kIOReturnSuccess
;
4958 vm_map_offset_t map_data
;
4960 if( inDataCount
> sizeof(io_struct_inband_t
) * 1024)
4961 return( kIOReturnMessageTooLarge
);
4963 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
4964 data
= CAST_DOWN(vm_offset_t
, map_data
);
4966 if( kr
!= KERN_SUCCESS
)
4969 // must return success after vm_map_copyout() succeeds
4972 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
4973 vm_deallocate( kernel_map
, data
, inDataCount
);
4975 *result
= kIOReturnNoMemory
;
4976 return( KERN_SUCCESS
);
4982 case kIOCatalogResetDrivers
:
4983 case kIOCatalogResetDriversNoMatch
: {
4986 array
= OSDynamicCast(OSArray
, obj
);
4988 if ( !gIOCatalogue
->resetAndAddDrivers(array
,
4989 flag
== kIOCatalogResetDrivers
) ) {
4991 kr
= kIOReturnError
;
4994 kr
= kIOReturnBadArgument
;
4999 case kIOCatalogAddDrivers
:
5000 case kIOCatalogAddDriversNoMatch
: {
5003 array
= OSDynamicCast(OSArray
, obj
);
5005 if ( !gIOCatalogue
->addDrivers( array
,
5006 flag
== kIOCatalogAddDrivers
) ) {
5007 kr
= kIOReturnError
;
5011 kr
= kIOReturnBadArgument
;
5016 case kIOCatalogRemoveDrivers
:
5017 case kIOCatalogRemoveDriversNoMatch
: {
5018 OSDictionary
* dict
;
5020 dict
= OSDynamicCast(OSDictionary
, obj
);
5022 if ( !gIOCatalogue
->removeDrivers( dict
,
5023 flag
== kIOCatalogRemoveDrivers
) ) {
5024 kr
= kIOReturnError
;
5028 kr
= kIOReturnBadArgument
;
5033 case kIOCatalogStartMatching
: {
5034 OSDictionary
* dict
;
5036 dict
= OSDynamicCast(OSDictionary
, obj
);
5038 if ( !gIOCatalogue
->startMatching( dict
) ) {
5039 kr
= kIOReturnError
;
5043 kr
= kIOReturnBadArgument
;
5048 case kIOCatalogRemoveKernelLinker
:
5049 kr
= KERN_NOT_SUPPORTED
;
5052 case kIOCatalogKextdActive
:
5054 IOServiceTrace(IOSERVICE_KEXTD_ALIVE
, 0, 0, 0, 0);
5055 OSKext::setKextdActive();
5057 /* Dump all nonloaded startup extensions; kextd will now send them
5060 OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
5062 kr
= kIOReturnSuccess
;
5065 case kIOCatalogKextdFinishedLaunching
: {
5067 if (!gIOKextdClearedBusy
) {
5068 IOService
* serviceRoot
= IOService::getServiceRoot();
5070 IOServiceTrace(IOSERVICE_KEXTD_READY
, 0, 0, 0, 0);
5071 serviceRoot
->adjustBusy(-1);
5072 gIOKextdClearedBusy
= true;
5076 kr
= kIOReturnSuccess
;
5081 kr
= kIOReturnBadArgument
;
5085 if (obj
) obj
->release();
5088 return( KERN_SUCCESS
);
5089 #endif /* NO_KEXTD */
5092 /* Routine io_catalog_terminate */
5093 kern_return_t
is_io_catalog_terminate(
5094 mach_port_t master_port
,
5100 if( master_port
!= master_device_port
)
5101 return kIOReturnNotPrivileged
;
5103 kr
= IOUserClient::clientHasPrivilege( (void *) current_task(),
5104 kIOClientPrivilegeAdministrator
);
5105 if( kIOReturnSuccess
!= kr
)
5109 #if !defined(SECURE_KERNEL)
5110 case kIOCatalogServiceTerminate
:
5112 IOService
* service
;
5114 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
5115 kIORegistryIterateRecursively
);
5117 return kIOReturnNoMemory
;
5121 while( (service
= (IOService
*)iter
->getNextObject()) ) {
5122 if( service
->metaCast(name
)) {
5123 if ( !service
->terminate( kIOServiceRequired
5124 | kIOServiceSynchronous
) ) {
5125 kr
= kIOReturnUnsupported
;
5130 } while( !service
&& !iter
->isValid());
5134 case kIOCatalogModuleUnload
:
5135 case kIOCatalogModuleTerminate
:
5136 kr
= gIOCatalogue
->terminateDriversForModule(name
,
5137 flag
== kIOCatalogModuleUnload
);
5142 kr
= kIOReturnBadArgument
;
5149 /* Routine io_catalog_get_data */
5150 kern_return_t
is_io_catalog_get_data(
5151 mach_port_t master_port
,
5153 io_buf_ptr_t
*outData
,
5154 mach_msg_type_number_t
*outDataCount
)
5156 kern_return_t kr
= kIOReturnSuccess
;
5159 if( master_port
!= master_device_port
)
5160 return kIOReturnNotPrivileged
;
5162 //printf("io_catalog_get_data called. flag: %d\n", flag);
5164 s
= OSSerialize::withCapacity(4096);
5166 return kIOReturnNoMemory
;
5168 kr
= gIOCatalogue
->serializeData(flag
, s
);
5170 if ( kr
== kIOReturnSuccess
) {
5175 size
= s
->getLength();
5176 kr
= vm_allocate_kernel(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
, VM_KERN_MEMORY_IOKIT
);
5177 if ( kr
== kIOReturnSuccess
) {
5178 bcopy(s
->text(), (void *)data
, size
);
5179 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
5180 (vm_map_size_t
)size
, true, ©
);
5181 *outData
= (char *)copy
;
5182 *outDataCount
= size
;
5191 /* Routine io_catalog_get_gen_count */
5192 kern_return_t
is_io_catalog_get_gen_count(
5193 mach_port_t master_port
,
5196 if( master_port
!= master_device_port
)
5197 return kIOReturnNotPrivileged
;
5199 //printf("io_catalog_get_gen_count called.\n");
5202 return kIOReturnBadArgument
;
5204 *genCount
= gIOCatalogue
->getGenerationCount();
5206 return kIOReturnSuccess
;
5209 /* Routine io_catalog_module_loaded.
5210 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
5212 kern_return_t
is_io_catalog_module_loaded(
5213 mach_port_t master_port
,
5216 if( master_port
!= master_device_port
)
5217 return kIOReturnNotPrivileged
;
5219 //printf("io_catalog_module_loaded called. name %s\n", name);
5222 return kIOReturnBadArgument
;
5224 gIOCatalogue
->moduleHasLoaded(name
);
5226 return kIOReturnSuccess
;
5229 kern_return_t
is_io_catalog_reset(
5230 mach_port_t master_port
,
5233 if( master_port
!= master_device_port
)
5234 return kIOReturnNotPrivileged
;
5237 case kIOCatalogResetDefault
:
5238 gIOCatalogue
->reset();
5242 return kIOReturnBadArgument
;
5245 return kIOReturnSuccess
;
5248 kern_return_t
iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
5250 kern_return_t result
= kIOReturnBadArgument
;
5251 IOUserClient
*userClient
;
5253 if ((userClient
= OSDynamicCast(IOUserClient
,
5254 iokit_lookup_connect_ref_current_task((mach_port_name_t
)(uintptr_t)args
->userClientRef
)))) {
5255 IOExternalTrap
*trap
;
5256 IOService
*target
= NULL
;
5258 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
5260 if (trap
&& target
) {
5266 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
5270 iokit_remove_connect_reference(userClient
);
5276 /* Routine io_device_tree_entry_exists_with_name */
5277 kern_return_t
is_io_device_tree_entry_exists_with_name(
5278 mach_port_t master_port
,
5282 OSCollectionIterator
*iter
;
5284 if (master_port
!= master_device_port
)
5285 return (kIOReturnNotPrivileged
);
5287 iter
= IODTFindMatchingEntries(IORegistryEntry::getRegistryRoot(), kIODTRecursive
, name
);
5288 *exists
= iter
&& iter
->getNextObject();
5289 OSSafeReleaseNULL(iter
);
5291 return kIOReturnSuccess
;
5296 IOReturn
IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
5297 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
5301 IOByteCount structureOutputSize
;
5306 count
= dispatch
->checkScalarInputCount
;
5307 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
))
5309 return (kIOReturnBadArgument
);
5312 count
= dispatch
->checkStructureInputSize
;
5313 if ((kIOUCVariableStructureSize
!= count
)
5314 && (count
!= ((args
->structureInputDescriptor
)
5315 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
)))
5317 return (kIOReturnBadArgument
);
5320 count
= dispatch
->checkScalarOutputCount
;
5321 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
))
5323 return (kIOReturnBadArgument
);
5326 count
= dispatch
->checkStructureOutputSize
;
5327 if ((kIOUCVariableStructureSize
!= count
)
5328 && (count
!= ((args
->structureOutputDescriptor
)
5329 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
)))
5331 return (kIOReturnBadArgument
);
5334 if (dispatch
->function
)
5335 err
= (*dispatch
->function
)(target
, reference
, args
);
5337 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
5343 // pre-Leopard API's don't do ool structs
5344 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
)
5346 err
= kIOReturnIPCError
;
5350 structureOutputSize
= args
->structureOutputSize
;
5352 if (args
->asyncWakePort
)
5354 IOExternalAsyncMethod
* method
;
5356 if( !(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
)
5357 return (kIOReturnUnsupported
);
5359 if (kIOUCForegroundOnly
& method
->flags
)
5361 if (task_is_gpu_denied(current_task()))
5362 return (kIOReturnNotPermitted
);
5365 switch (method
->flags
& kIOUCTypeMask
)
5367 case kIOUCScalarIStructI
:
5368 err
= shim_io_async_method_scalarI_structureI( method
, object
,
5369 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5370 args
->scalarInput
, args
->scalarInputCount
,
5371 (char *)args
->structureInput
, args
->structureInputSize
);
5374 case kIOUCScalarIScalarO
:
5375 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
5376 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5377 args
->scalarInput
, args
->scalarInputCount
,
5378 args
->scalarOutput
, &args
->scalarOutputCount
);
5381 case kIOUCScalarIStructO
:
5382 err
= shim_io_async_method_scalarI_structureO( method
, object
,
5383 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5384 args
->scalarInput
, args
->scalarInputCount
,
5385 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5389 case kIOUCStructIStructO
:
5390 err
= shim_io_async_method_structureI_structureO( method
, object
,
5391 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
5392 (char *)args
->structureInput
, args
->structureInputSize
,
5393 (char *) args
->structureOutput
, &args
->structureOutputSize
);
5397 err
= kIOReturnBadArgument
;
5403 IOExternalMethod
* method
;
5405 if( !(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
)
5406 return (kIOReturnUnsupported
);
5408 if (kIOUCForegroundOnly
& method
->flags
)
5410 if (task_is_gpu_denied(current_task()))
5411 return (kIOReturnNotPermitted
);
5414 switch (method
->flags
& kIOUCTypeMask
)
5416 case kIOUCScalarIStructI
:
5417 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
5418 args
->scalarInput
, args
->scalarInputCount
,
5419 (char *) args
->structureInput
, args
->structureInputSize
);
5422 case kIOUCScalarIScalarO
:
5423 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
5424 args
->scalarInput
, args
->scalarInputCount
,
5425 args
->scalarOutput
, &args
->scalarOutputCount
);
5428 case kIOUCScalarIStructO
:
5429 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
5430 args
->scalarInput
, args
->scalarInputCount
,
5431 (char *) args
->structureOutput
, &structureOutputSize
);
5435 case kIOUCStructIStructO
:
5436 err
= shim_io_connect_method_structureI_structureO( method
, object
,
5437 (char *) args
->structureInput
, args
->structureInputSize
,
5438 (char *) args
->structureOutput
, &structureOutputSize
);
5442 err
= kIOReturnBadArgument
;
5447 args
->structureOutputSize
= structureOutputSize
;
5453 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
5454 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
5456 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
5457 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
5459 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
5460 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
5461 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
5462 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
5463 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
5464 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
5465 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
5466 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
5467 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
5468 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
5469 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
5470 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
5471 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
5472 OSMetaClassDefineReservedUnused(IOUserClient
, 15);