2 * Copyright (c) 1998-2019 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 <libkern/c++/OSSharedPtr.h>
32 #include <IOKit/IOKitServer.h>
33 #include <IOKit/IOKitKeysPrivate.h>
34 #include <IOKit/IOUserClient.h>
35 #include <IOKit/IOService.h>
36 #include <IOKit/IORegistryEntry.h>
37 #include <IOKit/IOCatalogue.h>
38 #include <IOKit/IOMemoryDescriptor.h>
39 #include <IOKit/IOBufferMemoryDescriptor.h>
40 #include <IOKit/IOLib.h>
41 #include <IOKit/IOBSD.h>
42 #include <IOKit/IOStatisticsPrivate.h>
43 #include <IOKit/IOTimeStamp.h>
44 #include <IOKit/IODeviceTreeSupport.h>
45 #include <IOKit/IOUserServer.h>
46 #include <IOKit/system.h>
47 #include <libkern/OSDebug.h>
48 #include <DriverKit/OSAction.h>
50 #include <sys/kauth.h>
51 #include <sys/codesign.h>
59 #include <security/mac_framework.h>
61 #include <sys/kauth.h>
65 #endif /* CONFIG_MACF */
67 #include <IOKit/assert.h>
69 #include "IOServicePrivate.h"
70 #include "IOKitKernelInternal.h"
72 #define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
73 #define SCALAR32(x) ((uint32_t )x)
74 #define ARG32(x) ((void *)(uintptr_t)SCALAR32(x))
75 #define REF64(x) ((io_user_reference_t)((UInt64)(x)))
76 #define REF32(x) ((int)(x))
79 kIOUCAsync0Flags
= 3ULL,
80 kIOUCAsync64Flag
= 1ULL,
81 kIOUCAsyncErrorLoggedFlag
= 2ULL
86 #define IOStatisticsRegisterCounter() \
88 reserved->counter = IOStatistics::registerUserClient(this); \
91 #define IOStatisticsUnregisterCounter() \
94 IOStatistics::unregisterUserClient(reserved->counter); \
97 #define IOStatisticsClientCall() \
99 IOStatistics::countUserClientCall(client); \
104 #define IOStatisticsRegisterCounter()
105 #define IOStatisticsUnregisterCounter()
106 #define IOStatisticsClientCall()
108 #endif /* IOKITSTATS */
110 #if DEVELOPMENT || DEBUG
112 #define FAKE_STACK_FRAME(a) \
113 const void ** __frameptr; \
114 const void * __retaddr; \
115 __frameptr = (typeof(__frameptr)) __builtin_frame_address(0); \
116 __retaddr = __frameptr[1]; \
119 #define FAKE_STACK_FRAME_END() \
120 __frameptr[1] = __retaddr;
122 #else /* DEVELOPMENT || DEBUG */
124 #define FAKE_STACK_FRAME(a)
125 #define FAKE_STACK_FRAME_END()
127 #endif /* DEVELOPMENT || DEBUG */
129 #define ASYNC_REF_COUNT (sizeof(io_async_ref_t) / sizeof(natural_t))
130 #define ASYNC_REF64_COUNT (sizeof(io_async_ref64_t) / sizeof(io_user_reference_t))
132 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
135 #include <mach/mach_traps.h>
136 #include <vm/vm_map.h>
139 struct IOMachPortHashList
;
141 static_assert(IKOT_MAX_TYPE
<= 255);
143 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
145 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
146 class IOMachPort
: public OSObject
148 OSDeclareDefaultStructors(IOMachPort
);
150 SLIST_ENTRY(IOMachPort
) link
;
157 static IOMachPort
* withObjectAndType(OSObject
*obj
, ipc_kobject_type_t type
);
159 static IOMachPortHashList
* bucketForObject(OSObject
*obj
,
160 ipc_kobject_type_t type
);
162 static IOMachPort
* portForObjectInBucket(IOMachPortHashList
*bucket
, OSObject
*obj
, ipc_kobject_type_t type
);
164 static bool noMoreSendersForObject( OSObject
* obj
,
165 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
);
166 static void releasePortForObject( OSObject
* obj
,
167 ipc_kobject_type_t type
);
168 static void setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
);
170 static mach_port_name_t
makeSendRightForTask( task_t task
,
171 io_object_t obj
, ipc_kobject_type_t type
);
173 virtual void free() APPLE_KEXT_OVERRIDE
;
176 #define super OSObject
177 OSDefineMetaClassAndStructorsWithZone(IOMachPort
, OSObject
, ZC_ZFREE_CLEARMEM
)
179 static IOLock
* gIOObjectPortLock
;
180 IOLock
* gIOUserServerLock
;
182 SECURITY_READ_ONLY_LATE(const struct io_filter_callbacks
*) gIOUCFilterCallbacks
;
184 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
186 SLIST_HEAD(IOMachPortHashList
, IOMachPort
);
188 #if defined(XNU_TARGET_OS_OSX)
189 #define PORT_HASH_SIZE 4096
190 #else /* defined(!XNU_TARGET_OS_OSX) */
191 #define PORT_HASH_SIZE 256
192 #endif /* !defined(!XNU_TARGET_OS_OSX) */
194 IOMachPortHashList gIOMachPortHash
[PORT_HASH_SIZE
];
197 IOMachPortInitialize(void)
199 for (size_t i
= 0; i
< PORT_HASH_SIZE
; i
++) {
200 SLIST_INIT(&gIOMachPortHash
[i
]);
205 IOMachPort::bucketForObject(OSObject
*obj
, ipc_kobject_type_t type
)
207 return &gIOMachPortHash
[os_hash_kernel_pointer(obj
) % PORT_HASH_SIZE
];
211 IOMachPort::portForObjectInBucket(IOMachPortHashList
*bucket
, OSObject
*obj
, ipc_kobject_type_t type
)
213 IOMachPort
*machPort
;
215 SLIST_FOREACH(machPort
, bucket
, link
) {
216 if (machPort
->object
== obj
&& machPort
->type
== type
) {
224 IOMachPort::withObjectAndType(OSObject
*obj
, ipc_kobject_type_t type
)
226 IOMachPort
*machPort
= NULL
;
228 machPort
= new IOMachPort
;
229 if (__improbable(machPort
&& !machPort
->init())) {
233 machPort
->object
= obj
;
234 machPort
->type
= (typeof(machPort
->type
))type
;
235 machPort
->port
= iokit_alloc_object_port(obj
, type
);
237 obj
->taggedRetain(OSTypeID(OSCollection
));
244 IOMachPort::noMoreSendersForObject( OSObject
* obj
,
245 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
247 IOMachPort
*machPort
= NULL
;
250 bool destroyed
= true;
252 IOMachPortHashList
*bucket
= IOMachPort::bucketForObject(obj
, type
);
256 lck_mtx_lock(gIOObjectPortLock
);
258 machPort
= IOMachPort::portForObjectInBucket(bucket
, obj
, type
);
261 destroyed
= (machPort
->mscount
<= *mscount
);
263 *mscount
= machPort
->mscount
;
264 lck_mtx_unlock(gIOObjectPortLock
);
266 if ((IKOT_IOKIT_CONNECT
== type
) && (uc
= OSDynamicCast(IOUserClient
, obj
))) {
269 SLIST_REMOVE(bucket
, machPort
, IOMachPort
, link
);
271 lck_mtx_unlock(gIOObjectPortLock
);
274 obj
->taggedRelease(OSTypeID(OSCollection
));
277 lck_mtx_unlock(gIOObjectPortLock
);
280 if ((IKOT_UEXT_OBJECT
== type
) && (action
= OSDynamicCast(OSAction
, obj
))) {
290 IOMachPort::releasePortForObject( OSObject
* obj
,
291 ipc_kobject_type_t type
)
293 IOMachPort
*machPort
;
294 IOMachPortHashList
*bucket
= IOMachPort::bucketForObject(obj
, type
);
296 assert(IKOT_IOKIT_CONNECT
!= type
);
298 lck_mtx_lock(gIOObjectPortLock
);
300 machPort
= IOMachPort::portForObjectInBucket(bucket
, obj
, type
);
302 if (machPort
&& !machPort
->holdDestroy
) {
304 SLIST_REMOVE(bucket
, machPort
, IOMachPort
, link
);
306 lck_mtx_unlock(gIOObjectPortLock
);
309 obj
->taggedRelease(OSTypeID(OSCollection
));
312 lck_mtx_unlock(gIOObjectPortLock
);
317 IOMachPort::setHoldDestroy( OSObject
* obj
, ipc_kobject_type_t type
)
319 IOMachPort
* machPort
;
321 IOMachPortHashList
*bucket
= IOMachPort::bucketForObject(obj
, type
);
322 lck_mtx_lock(gIOObjectPortLock
);
324 machPort
= IOMachPort::portForObjectInBucket(bucket
, obj
, type
);
327 machPort
->holdDestroy
= true;
330 lck_mtx_unlock(gIOObjectPortLock
);
334 IOMachPortDestroyUserReferences(OSObject
* obj
, natural_t type
)
336 IOMachPort::releasePortForObject(obj
, type
);
340 IOUserClient::destroyUserReferences( OSObject
* obj
)
342 IOMachPort
*machPort
;
344 IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT
);
347 // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
350 IOMachPortHashList
*bucket
= IOMachPort::bucketForObject(obj
, IKOT_IOKIT_CONNECT
);
351 IOMachPortHashList
*mappingBucket
= NULL
;
353 lck_mtx_lock(gIOObjectPortLock
);
355 IOUserClient
* uc
= OSDynamicCast(IOUserClient
, obj
);
356 if (uc
&& uc
->mappings
) {
357 mappingBucket
= IOMachPort::bucketForObject(uc
->mappings
, IKOT_IOKIT_CONNECT
);
360 machPort
= IOMachPort::portForObjectInBucket(bucket
, obj
, IKOT_IOKIT_CONNECT
);
362 if (machPort
== NULL
) {
363 lck_mtx_unlock(gIOObjectPortLock
);
367 SLIST_REMOVE(bucket
, machPort
, IOMachPort
, link
);
368 obj
->taggedRelease(OSTypeID(OSCollection
));
373 uc
->mappings
->taggedRetain(OSTypeID(OSCollection
));
374 machPort
->object
= uc
->mappings
;
375 SLIST_INSERT_HEAD(mappingBucket
, machPort
, link
);
376 iokit_switch_object_port(machPort
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
);
378 lck_mtx_unlock(gIOObjectPortLock
);
380 uc
->mappings
->release();
383 lck_mtx_unlock(gIOObjectPortLock
);
387 lck_mtx_unlock(gIOObjectPortLock
);
398 IOMachPort::makeSendRightForTask( task_t task
,
399 io_object_t obj
, ipc_kobject_type_t type
)
401 return iokit_make_send_right( task
, obj
, type
);
405 IOMachPort::free( void )
408 iokit_destroy_object_port( port
);
413 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
416 IOTaskRegistryCompatibility(task_t task
)
422 IOTaskRegistryCompatibilityMatching(task_t task
, OSDictionary
* matching
)
424 if (!IOTaskRegistryCompatibility(task
)) {
427 matching
->setObject(gIOCompatibilityMatchKey
, kOSBooleanTrue
);
430 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
432 class IOUserIterator
: public OSIterator
434 OSDeclareDefaultStructors(IOUserIterator
);
436 OSObject
* userIteratorObject
;
439 static IOUserIterator
* withIterator(LIBKERN_CONSUMED OSIterator
* iter
);
440 virtual bool init( void ) APPLE_KEXT_OVERRIDE
;
441 virtual void free() APPLE_KEXT_OVERRIDE
;
443 virtual void reset() APPLE_KEXT_OVERRIDE
;
444 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
445 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
446 virtual OSObject
* copyNextObject();
449 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
451 class IOUserNotification
: public IOUserIterator
453 OSDeclareDefaultStructors(IOUserNotification
);
455 #define holdNotify userIteratorObject
459 virtual void free() APPLE_KEXT_OVERRIDE
;
461 virtual void setNotification( IONotifier
* obj
);
463 virtual void reset() APPLE_KEXT_OVERRIDE
;
464 virtual bool isValid() APPLE_KEXT_OVERRIDE
;
467 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
469 OSDefineMetaClassAndStructors( IOUserIterator
, OSIterator
)
472 IOUserIterator::withIterator(OSIterator
* iter
)
480 me
= new IOUserIterator
;
481 if (me
&& !me
->init()) {
488 me
->userIteratorObject
= iter
;
494 IOUserIterator::init( void )
496 if (!OSObject::init()) {
500 lock
= IOLockAlloc();
509 IOUserIterator::free()
511 if (userIteratorObject
) {
512 userIteratorObject
->release();
521 IOUserIterator::reset()
524 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
525 ((OSIterator
*)userIteratorObject
)->reset();
530 IOUserIterator::isValid()
535 assert(OSDynamicCast(OSIterator
, userIteratorObject
));
536 ret
= ((OSIterator
*)userIteratorObject
)->isValid();
543 IOUserIterator::getNextObject()
550 IOUserIterator::copyNextObject()
552 OSObject
* ret
= NULL
;
555 if (userIteratorObject
) {
556 ret
= ((OSIterator
*)userIteratorObject
)->getNextObject();
566 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
568 // functions called from osfmk/device/iokit_rpc.c
571 iokit_port_object_description(io_object_t obj
, kobject_description_t desc
)
573 IORegistryEntry
* regEntry
;
574 IOUserNotification
* __unused noti
;
575 _IOServiceNotifier
* __unused serviceNoti
;
576 OSSerialize
* __unused s
;
578 if ((regEntry
= OSDynamicCast(IORegistryEntry
, obj
))) {
579 snprintf(desc
, KOBJECT_DESCRIPTION_LENGTH
, "%s(0x%qx)", obj
->getMetaClass()->getClassName(), regEntry
->getRegistryEntryID());
580 #if DEVELOPMENT || DEBUG
581 } else if ((noti
= OSDynamicCast(IOUserNotification
, obj
))
582 && ((serviceNoti
= OSDynamicCast(_IOServiceNotifier
, noti
->holdNotify
)))) {
583 s
= OSSerialize::withCapacity((unsigned int) page_size
);
584 if (s
&& serviceNoti
->matching
->serialize(s
)) {
585 snprintf(desc
, KOBJECT_DESCRIPTION_LENGTH
, "%s(%s)", obj
->getMetaClass()->getClassName(), s
->text());
587 OSSafeReleaseNULL(s
);
588 #endif /* DEVELOPMENT || DEBUG */
590 snprintf(desc
, KOBJECT_DESCRIPTION_LENGTH
, "%s", obj
->getMetaClass()->getClassName());
594 // FIXME: Implementation of these functions are hidden from the static analyzer.
595 // As for now, the analyzer doesn't consistently support wrapper functions
596 // for retain and release.
597 #ifndef __clang_analyzer__
599 iokit_add_reference( io_object_t obj
, natural_t type
)
607 if ((IKOT_IOKIT_CONNECT
== type
)
608 && (uc
= OSDynamicCast(IOUserClient
, obj
))) {
609 OSIncrementAtomic(&uc
->__ipc
);
616 iokit_remove_reference( io_object_t obj
)
622 #endif // __clang_analyzer__
625 iokit_remove_connect_reference( io_object_t obj
)
628 bool finalize
= false;
634 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) {
635 if (1 == OSDecrementAtomic(&uc
->__ipc
) && uc
->isInactive()) {
636 IOLockLock(gIOObjectPortLock
);
637 if ((finalize
= uc
->__ipcFinal
)) {
638 uc
->__ipcFinal
= false;
640 IOLockUnlock(gIOObjectPortLock
);
643 uc
->scheduleFinalize(true);
651 IOUserClient::finalizeUserReferences(OSObject
* obj
)
656 if ((uc
= OSDynamicCast(IOUserClient
, obj
))) {
657 IOLockLock(gIOObjectPortLock
);
658 if ((uc
->__ipcFinal
= (0 != uc
->__ipc
))) {
661 IOLockUnlock(gIOObjectPortLock
);
667 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type
)
669 IOMachPort
*machPort
= NULL
;
670 ipc_port_t port
= NULL
;
672 IOMachPortHashList
*bucket
= IOMachPort::bucketForObject(obj
, type
);
674 lck_mtx_lock(gIOObjectPortLock
);
676 machPort
= IOMachPort::portForObjectInBucket(bucket
, obj
, type
);
678 if (__improbable(machPort
== NULL
)) {
679 machPort
= IOMachPort::withObjectAndType(obj
, type
);
680 if (__improbable(machPort
== NULL
)) {
683 SLIST_INSERT_HEAD(bucket
, machPort
, link
);
688 iokit_retain_port(machPort
->port
);
689 port
= machPort
->port
;
692 lck_mtx_unlock(gIOObjectPortLock
);
698 iokit_client_died( io_object_t obj
, ipc_port_t
/* port */,
699 ipc_kobject_type_t type
, mach_port_mscount_t
* mscount
)
701 IOUserClient
* client
;
703 IOUserNotification
* notify
;
704 IOUserServerCheckInToken
* token
;
706 if (!IOMachPort::noMoreSendersForObject( obj
, type
, mscount
)) {
707 return kIOReturnNotReady
;
711 case IKOT_IOKIT_CONNECT
:
712 if ((client
= OSDynamicCast( IOUserClient
, obj
))) {
713 IOStatisticsClientCall();
714 IORWLockWrite(client
->lock
);
715 client
->clientDied();
716 IORWLockUnlock(client
->lock
);
719 case IKOT_IOKIT_OBJECT
:
720 if ((map
= OSDynamicCast( IOMemoryMap
, obj
))) {
722 } else if ((notify
= OSDynamicCast( IOUserNotification
, obj
))) {
723 notify
->setNotification( NULL
);
726 case IKOT_IOKIT_IDENT
:
727 if ((token
= OSDynamicCast( IOUserServerCheckInToken
, obj
))) {
728 IOUserServerCheckInToken::notifyNoSenders( token
);
733 return kIOReturnSuccess
;
737 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
739 class IOServiceUserNotification
: public IOUserNotification
741 OSDeclareDefaultStructors(IOServiceUserNotification
);
744 mach_msg_header_t msgHdr
;
745 OSNotificationHeader64 notifyHeader
;
748 enum { kMaxOutstanding
= 1024 };
751 mach_msg_size_t msgSize
;
758 virtual bool init( mach_port_t port
, natural_t type
,
759 void * reference
, vm_size_t referenceSize
,
761 virtual void free() APPLE_KEXT_OVERRIDE
;
762 void invalidatePort(void);
764 static bool _handler( void * target
,
765 void * ref
, IOService
* newService
, IONotifier
* notifier
);
766 virtual bool handler( void * ref
, IOService
* newService
);
768 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
769 virtual OSObject
* copyNextObject() APPLE_KEXT_OVERRIDE
;
772 class IOServiceMessageUserNotification
: public IOUserNotification
774 OSDeclareDefaultStructors(IOServiceMessageUserNotification
);
777 mach_msg_header_t msgHdr
;
778 mach_msg_body_t msgBody
;
779 mach_msg_port_descriptor_t ports
[1];
780 OSNotificationHeader64 notifyHeader
__attribute__ ((packed
));
784 mach_msg_size_t msgSize
;
791 virtual bool init( mach_port_t port
, natural_t type
,
792 void * reference
, vm_size_t referenceSize
,
793 mach_msg_size_t extraSize
,
796 virtual void free() APPLE_KEXT_OVERRIDE
;
797 void invalidatePort(void);
799 static IOReturn
_handler( void * target
, void * ref
,
800 UInt32 messageType
, IOService
* provider
,
801 void * messageArgument
, vm_size_t argSize
);
802 virtual IOReturn
handler( void * ref
,
803 UInt32 messageType
, IOService
* provider
,
804 void * messageArgument
, vm_size_t argSize
);
806 virtual OSObject
* getNextObject() APPLE_KEXT_OVERRIDE
;
807 virtual OSObject
* copyNextObject() APPLE_KEXT_OVERRIDE
;
810 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
813 #define super IOUserIterator
814 OSDefineMetaClass( IOUserNotification
, IOUserIterator
);
815 OSDefineAbstractStructors( IOUserNotification
, IOUserIterator
);
817 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
820 IOUserNotification::free( void )
823 assert(OSDynamicCast(IONotifier
, holdNotify
));
824 ((IONotifier
*)holdNotify
)->remove();
827 // can't be in handler now
834 IOUserNotification::setNotification( IONotifier
* notify
)
836 OSObject
* previousNotify
;
838 IOLockLock( gIOObjectPortLock
);
840 previousNotify
= holdNotify
;
843 IOLockUnlock( gIOObjectPortLock
);
845 if (previousNotify
) {
846 assert(OSDynamicCast(IONotifier
, previousNotify
));
847 ((IONotifier
*)previousNotify
)->remove();
852 IOUserNotification::reset()
858 IOUserNotification::isValid()
863 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
866 #define super IOUserNotification
867 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
)
869 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
872 IOServiceUserNotification::init( mach_port_t port
, natural_t type
,
873 void * reference
, vm_size_t referenceSize
,
876 if (!super::init()) {
880 newSet
= OSArray::withCapacity( 1 );
885 if (referenceSize
> sizeof(OSAsyncReference64
)) {
889 msgSize
= (mach_msg_size_t
) (sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
);
891 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
896 bzero( pingMsg
, msgSize
);
898 pingMsg
->msgHdr
.msgh_remote_port
= port
;
899 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS(
900 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
901 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
902 pingMsg
->msgHdr
.msgh_size
= msgSize
;
903 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
905 pingMsg
->notifyHeader
.size
= 0;
906 pingMsg
->notifyHeader
.type
= type
;
907 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
913 IOServiceUserNotification::invalidatePort(void)
916 pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
921 IOServiceUserNotification::free( void )
933 if (_pingMsg
&& _msgSize
) {
934 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
935 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
937 IOFree(_pingMsg
, _msgSize
);
946 IOServiceUserNotification::_handler( void * target
,
947 void * ref
, IOService
* newService
, IONotifier
* notifier
)
949 return ((IOServiceUserNotification
*) target
)->handler( ref
, newService
);
953 IOServiceUserNotification::handler( void * ref
,
954 IOService
* newService
)
958 ipc_port_t port
= NULL
;
959 bool sendPing
= false;
963 count
= newSet
->getCount();
964 if (count
< kMaxOutstanding
) {
965 newSet
->setObject( newService
);
966 if ((sendPing
= (armed
&& (0 == count
)))) {
973 if (kIOServiceTerminatedNotificationType
== pingMsg
->notifyHeader
.type
) {
974 IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT
);
978 if ((port
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
))) {
979 pingMsg
->msgHdr
.msgh_local_port
= port
;
981 pingMsg
->msgHdr
.msgh_local_port
= NULL
;
984 kr
= mach_msg_send_from_kernel_with_options( &pingMsg
->msgHdr
,
985 pingMsg
->msgHdr
.msgh_size
,
986 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
989 iokit_release_port( port
);
992 if ((KERN_SUCCESS
!= kr
) && !ipcLogged
) {
994 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1001 IOServiceUserNotification::getNextObject()
1008 IOServiceUserNotification::copyNextObject()
1015 count
= newSet
->getCount();
1017 result
= newSet
->getObject( count
- 1 );
1019 newSet
->removeObject( count
- 1);
1030 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1032 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
)
1034 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1037 IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
,
1038 void * reference
, vm_size_t referenceSize
, mach_msg_size_t extraSize
,
1041 if (!super::init()) {
1045 if (referenceSize
> sizeof(OSAsyncReference64
)) {
1049 clientIs64
= client64
;
1051 owningPID
= proc_selfpid();
1053 extraSize
+= sizeof(IOServiceInterestContent64
);
1054 msgSize
= (mach_msg_size_t
) (sizeof(PingMsg
) - sizeof(OSAsyncReference64
) + referenceSize
);
1055 pingMsg
= (PingMsg
*) IOMalloc( msgSize
);
1060 bzero( pingMsg
, msgSize
);
1062 pingMsg
->msgHdr
.msgh_remote_port
= port
;
1063 pingMsg
->msgHdr
.msgh_bits
= MACH_MSGH_BITS_COMPLEX
1065 MACH_MSG_TYPE_COPY_SEND
/*remote*/,
1066 MACH_MSG_TYPE_MAKE_SEND
/*local*/);
1067 pingMsg
->msgHdr
.msgh_size
= msgSize
;
1068 pingMsg
->msgHdr
.msgh_id
= kOSNotificationMessageID
;
1070 pingMsg
->msgBody
.msgh_descriptor_count
= 1;
1072 pingMsg
->ports
[0].name
= NULL
;
1073 pingMsg
->ports
[0].disposition
= MACH_MSG_TYPE_MAKE_SEND
;
1074 pingMsg
->ports
[0].type
= MACH_MSG_PORT_DESCRIPTOR
;
1076 pingMsg
->notifyHeader
.size
= extraSize
;
1077 pingMsg
->notifyHeader
.type
= type
;
1078 bcopy( reference
, pingMsg
->notifyHeader
.reference
, referenceSize
);
1084 IOServiceMessageUserNotification::invalidatePort(void)
1087 pingMsg
->msgHdr
.msgh_remote_port
= MACH_PORT_NULL
;
1092 IOServiceMessageUserNotification::free( void )
1102 if (_pingMsg
&& _msgSize
) {
1103 if (_pingMsg
->msgHdr
.msgh_remote_port
) {
1104 iokit_release_port_send(_pingMsg
->msgHdr
.msgh_remote_port
);
1106 IOFree( _pingMsg
, _msgSize
);
1111 IOServiceMessageUserNotification::_handler( void * target
, void * ref
,
1112 UInt32 messageType
, IOService
* provider
,
1113 void * argument
, vm_size_t argSize
)
1115 return ((IOServiceMessageUserNotification
*) target
)->handler(
1116 ref
, messageType
, provider
, argument
, argSize
);
1120 IOServiceMessageUserNotification::handler( void * ref
,
1121 UInt32 messageType
, IOService
* provider
,
1122 void * messageArgument
, vm_size_t callerArgSize
)
1124 enum { kLocalMsgSize
= 0x100 };
1125 uint64_t stackMsg
[kLocalMsgSize
/ sizeof(uint64_t)];
1129 mach_msg_size_t thisMsgSize
;
1130 ipc_port_t thisPort
, providerPort
;
1131 struct PingMsg
* thisMsg
;
1132 IOServiceInterestContent64
* data
;
1134 if (kIOMessageCopyClientID
== messageType
) {
1135 *((void **) messageArgument
) = OSNumber::withNumber(owningPID
, 32);
1136 return kIOReturnSuccess
;
1139 if (callerArgSize
== 0) {
1141 argSize
= sizeof(data
->messageArgument
[0]);
1143 argSize
= sizeof(uint32_t);
1146 if (callerArgSize
> kIOUserNotifyMaxMessageSize
) {
1147 callerArgSize
= kIOUserNotifyMaxMessageSize
;
1149 argSize
= callerArgSize
;
1152 // adjust message size for ipc restrictions
1154 type
= pingMsg
->notifyHeader
.type
;
1155 type
&= ~(kIOKitNoticationMsgSizeMask
<< kIOKitNoticationTypeSizeAdjShift
);
1156 type
|= ((argSize
& kIOKitNoticationMsgSizeMask
) << kIOKitNoticationTypeSizeAdjShift
);
1157 argSize
= (argSize
+ kIOKitNoticationMsgSizeMask
) & ~kIOKitNoticationMsgSizeMask
;
1159 if (os_add3_overflow(msgSize
, sizeof(IOServiceInterestContent64
) - sizeof(data
->messageArgument
), argSize
, &thisMsgSize
)) {
1160 return kIOReturnBadArgument
;
1163 if (thisMsgSize
> sizeof(stackMsg
)) {
1164 allocMsg
= IOMalloc(thisMsgSize
);
1166 return kIOReturnNoMemory
;
1168 thisMsg
= (typeof(thisMsg
))allocMsg
;
1171 thisMsg
= (typeof(thisMsg
))stackMsg
;
1174 bcopy(pingMsg
, thisMsg
, msgSize
);
1175 thisMsg
->notifyHeader
.type
= type
;
1176 data
= (IOServiceInterestContent64
*) (((uint8_t *) thisMsg
) + msgSize
);
1177 // == pingMsg->notifyHeader.content;
1178 data
->messageType
= messageType
;
1180 if (callerArgSize
== 0) {
1181 data
->messageArgument
[0] = (io_user_reference_t
) messageArgument
;
1183 data
->messageArgument
[0] |= (data
->messageArgument
[0] << 32);
1186 bcopy( messageArgument
, data
->messageArgument
, callerArgSize
);
1187 bzero((void *)(((uintptr_t) &data
->messageArgument
[0]) + callerArgSize
), argSize
- callerArgSize
);
1190 thisMsg
->notifyHeader
.type
= type
;
1191 thisMsg
->msgHdr
.msgh_size
= thisMsgSize
;
1193 providerPort
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT
);
1194 thisMsg
->ports
[0].name
= providerPort
;
1195 thisPort
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT
);
1196 thisMsg
->msgHdr
.msgh_local_port
= thisPort
;
1198 kr
= mach_msg_send_from_kernel_with_options( &thisMsg
->msgHdr
,
1199 thisMsg
->msgHdr
.msgh_size
,
1200 (MACH_SEND_MSG
| MACH_SEND_ALWAYS
| MACH_SEND_IMPORTANCE
),
1203 iokit_release_port( thisPort
);
1206 iokit_release_port( providerPort
);
1210 IOFree(allocMsg
, thisMsgSize
);
1213 if ((KERN_SUCCESS
!= kr
) && !ipcLogged
) {
1215 IOLog("%s: mach_msg_send_from_kernel_proper (0x%x)\n", __PRETTY_FUNCTION__
, kr
);
1218 return kIOReturnSuccess
;
1222 IOServiceMessageUserNotification::getNextObject()
1228 IOServiceMessageUserNotification::copyNextObject()
1233 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1236 #define super IOService
1237 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService
)
1239 IOLock
* gIOUserClientOwnersLock
;
1242 IOUserClient::initialize( void )
1244 gIOObjectPortLock
= IOLockAlloc();
1245 gIOUserClientOwnersLock
= IOLockAlloc();
1246 gIOUserServerLock
= IOLockAlloc();
1247 assert(gIOObjectPortLock
&& gIOUserClientOwnersLock
);
1250 IOTrackingQueueCollectUser(IOUserIterator::gMetaClass
.getTracking());
1251 IOTrackingQueueCollectUser(IOServiceMessageUserNotification::gMetaClass
.getTracking());
1252 IOTrackingQueueCollectUser(IOServiceUserNotification::gMetaClass
.getTracking());
1253 IOTrackingQueueCollectUser(IOUserClient::gMetaClass
.getTracking());
1254 IOTrackingQueueCollectUser(IOMachPort::gMetaClass
.getTracking());
1255 #endif /* IOTRACKING */
1260 __attribute__((__noreturn__
))
1262 IOUserClient::setAsyncReference(OSAsyncReference asyncRef
,
1263 mach_port_t wakePort
,
1264 void *callback
, void *refcon
)
1267 panic("setAsyncReference not valid for 64b");
1269 asyncRef
[kIOAsyncReservedIndex
] = ((uintptr_t) wakePort
)
1270 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1271 asyncRef
[kIOAsyncCalloutFuncIndex
] = (uintptr_t) callback
;
1272 asyncRef
[kIOAsyncCalloutRefconIndex
] = (uintptr_t) refcon
;
1277 IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1278 mach_port_t wakePort
,
1279 mach_vm_address_t callback
, io_user_reference_t refcon
)
1281 asyncRef
[kIOAsyncReservedIndex
] = ((io_user_reference_t
) wakePort
)
1282 | (kIOUCAsync0Flags
& asyncRef
[kIOAsyncReservedIndex
]);
1283 asyncRef
[kIOAsyncCalloutFuncIndex
] = (io_user_reference_t
) callback
;
1284 asyncRef
[kIOAsyncCalloutRefconIndex
] = refcon
;
1288 IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef
,
1289 mach_port_t wakePort
,
1290 mach_vm_address_t callback
, io_user_reference_t refcon
, task_t task
)
1292 setAsyncReference64(asyncRef
, wakePort
, callback
, refcon
);
1293 if (vm_map_is_64bit(get_task_map(task
))) {
1294 asyncRef
[kIOAsyncReservedIndex
] |= kIOUCAsync64Flag
;
1298 static OSDictionary
*
1299 CopyConsoleUser(UInt32 uid
)
1302 OSDictionary
* user
= NULL
;
1304 if ((array
= OSDynamicCast(OSArray
,
1305 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
)))) {
1306 for (unsigned int idx
= 0;
1307 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1311 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
)))
1312 && (uid
== num
->unsigned32BitValue())) {
1322 static OSDictionary
*
1323 CopyUserOnConsole(void)
1326 OSDictionary
* user
= NULL
;
1328 if ((array
= OSDynamicCast(OSArray
,
1329 IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
)))) {
1330 for (unsigned int idx
= 0;
1331 (user
= OSDynamicCast(OSDictionary
, array
->getObject(idx
)));
1333 if (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
)) {
1344 IOUserClient::clientHasAuthorization( task_t task
,
1345 IOService
* service
)
1349 p
= (proc_t
) get_bsdtask_info(task
);
1351 uint64_t authorizationID
;
1353 authorizationID
= proc_uniqueid(p
);
1354 if (authorizationID
) {
1355 if (service
->getAuthorizationID() == authorizationID
) {
1356 return kIOReturnSuccess
;
1361 return kIOReturnNotPermitted
;
1365 IOUserClient::clientHasPrivilege( void * securityToken
,
1366 const char * privilegeName
)
1369 security_token_t token
;
1370 mach_msg_type_number_t count
;
1372 OSDictionary
* user
;
1376 if (!strncmp(privilegeName
, kIOClientPrivilegeForeground
,
1377 sizeof(kIOClientPrivilegeForeground
))) {
1378 if (task_is_gpu_denied(current_task())) {
1379 return kIOReturnNotPrivileged
;
1381 return kIOReturnSuccess
;
1385 if (!strncmp(privilegeName
, kIOClientPrivilegeConsoleSession
,
1386 sizeof(kIOClientPrivilegeConsoleSession
))) {
1390 task
= (task_t
) securityToken
;
1392 task
= current_task();
1394 p
= (proc_t
) get_bsdtask_info(task
);
1395 kr
= kIOReturnNotPrivileged
;
1397 if (p
&& (cred
= kauth_cred_proc_ref(p
))) {
1398 user
= CopyUserOnConsole();
1401 if ((num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionAuditIDKey
)))
1402 && (cred
->cr_audit
.as_aia_p
->ai_asid
== (au_asid_t
) num
->unsigned32BitValue())) {
1403 kr
= kIOReturnSuccess
;
1407 kauth_cred_unref(&cred
);
1412 if ((secureConsole
= !strncmp(privilegeName
, kIOClientPrivilegeSecureConsoleProcess
,
1413 sizeof(kIOClientPrivilegeSecureConsoleProcess
)))) {
1414 task
= (task_t
)((IOUCProcessToken
*)securityToken
)->token
;
1416 task
= (task_t
)securityToken
;
1419 count
= TASK_SECURITY_TOKEN_COUNT
;
1420 kr
= task_info( task
, TASK_SECURITY_TOKEN
, (task_info_t
) &token
, &count
);
1422 if (KERN_SUCCESS
!= kr
) {
1423 } else if (!strncmp(privilegeName
, kIOClientPrivilegeAdministrator
,
1424 sizeof(kIOClientPrivilegeAdministrator
))) {
1425 if (0 != token
.val
[0]) {
1426 kr
= kIOReturnNotPrivileged
;
1428 } else if (!strncmp(privilegeName
, kIOClientPrivilegeLocalUser
,
1429 sizeof(kIOClientPrivilegeLocalUser
))) {
1430 user
= CopyConsoleUser(token
.val
[0]);
1434 kr
= kIOReturnNotPrivileged
;
1436 } else if (secureConsole
|| !strncmp(privilegeName
, kIOClientPrivilegeConsoleUser
,
1437 sizeof(kIOClientPrivilegeConsoleUser
))) {
1438 user
= CopyConsoleUser(token
.val
[0]);
1440 if (user
->getObject(gIOConsoleSessionOnConsoleKey
) != kOSBooleanTrue
) {
1441 kr
= kIOReturnNotPrivileged
;
1442 } else if (secureConsole
) {
1443 OSNumber
* pid
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionSecureInputPIDKey
));
1444 if (pid
&& pid
->unsigned32BitValue() != ((IOUCProcessToken
*)securityToken
)->pid
) {
1445 kr
= kIOReturnNotPrivileged
;
1450 kr
= kIOReturnNotPrivileged
;
1453 kr
= kIOReturnUnsupported
;
1458 #define MAX_ENTITLEMENTS_LEN (128 * 1024)
1461 IOUserClient::copyClientEntitlements(task_t task
)
1466 void *entitlements_blob
= NULL
;
1467 OSDictionary
*entitlements
= NULL
;
1469 p
= (proc_t
)get_bsdtask_info(task
);
1475 if (cs_entitlements_dictionary_copy(p
, (void **)&entitlements
) == 0) {
1477 return entitlements
;
1481 if (cs_entitlements_blob_get(p
, &entitlements_blob
, &len
) != 0) {
1484 return IOUserClient::copyEntitlementsFromBlob(entitlements_blob
, len
);
1488 IOUserClient::copyEntitlementsFromBlob(void *entitlements_blob
, size_t len
)
1490 char *entitlements_data
= NULL
;
1491 OSObject
*entitlements_obj
= NULL
;
1492 OSString
*errorString
= NULL
;
1493 OSDictionary
*entitlements
= NULL
;
1495 if (len
<= offsetof(CS_GenericBlob
, data
)) {
1500 * Per <rdar://problem/11593877>, enforce a limit on the amount of XML
1501 * we'll try to parse in the kernel.
1503 len
-= offsetof(CS_GenericBlob
, data
);
1504 if (len
> MAX_ENTITLEMENTS_LEN
) {
1505 IOLog("failed to parse entitlements: %lu bytes of entitlements exceeds maximum of %u\n",
1506 len
, MAX_ENTITLEMENTS_LEN
);
1511 * OSUnserializeXML() expects a nul-terminated string, but that isn't
1512 * what is stored in the entitlements blob. Copy the string and
1515 entitlements_data
= (char *)IOMalloc(len
+ 1);
1516 if (entitlements_data
== NULL
) {
1519 memcpy(entitlements_data
, ((CS_GenericBlob
*)entitlements_blob
)->data
, len
);
1520 entitlements_data
[len
] = '\0';
1522 entitlements_obj
= OSUnserializeXML(entitlements_data
, len
+ 1, &errorString
);
1523 if (errorString
!= NULL
) {
1524 IOLog("failed to parse entitlements: %s\n", errorString
->getCStringNoCopy());
1527 if (entitlements_obj
== NULL
) {
1531 entitlements
= OSDynamicCast(OSDictionary
, entitlements_obj
);
1532 if (entitlements
== NULL
) {
1535 entitlements_obj
= NULL
;
1538 if (entitlements_data
!= NULL
) {
1539 IOFree(entitlements_data
, len
+ 1);
1541 if (entitlements_obj
!= NULL
) {
1542 entitlements_obj
->release();
1544 if (errorString
!= NULL
) {
1545 errorString
->release();
1547 return entitlements
;
1551 IOUserClient::copyClientEntitlementsVnode(vnode_t vnode
, off_t offset
)
1554 void *entitlements_blob
= NULL
;
1556 if (cs_entitlements_blob_get_vnode(vnode
, offset
, &entitlements_blob
, &len
) != 0) {
1559 return IOUserClient::copyEntitlementsFromBlob(entitlements_blob
, len
);
1563 IOUserClient::copyClientEntitlement( task_t task
,
1564 const char * entitlement
)
1566 OSDictionary
*entitlements
;
1569 entitlements
= copyClientEntitlements(task
);
1570 if (entitlements
== NULL
) {
1574 /* Fetch the entitlement value from the dictionary. */
1575 value
= entitlements
->getObject(entitlement
);
1576 if (value
!= NULL
) {
1580 entitlements
->release();
1585 IOUserClient::copyClientEntitlementVnode(
1586 struct vnode
*vnode
,
1588 const char *entitlement
)
1590 OSDictionary
*entitlements
;
1593 entitlements
= copyClientEntitlementsVnode(vnode
, offset
);
1594 if (entitlements
== NULL
) {
1598 /* Fetch the entitlement value from the dictionary. */
1599 value
= entitlements
->getObject(entitlement
);
1600 if (value
!= NULL
) {
1604 entitlements
->release();
1609 IOUserClient::init()
1611 if (getPropertyTable() || super::init()) {
1619 IOUserClient::init(OSDictionary
* dictionary
)
1621 if (getPropertyTable() || super::init(dictionary
)) {
1629 IOUserClient::initWithTask(task_t owningTask
,
1633 if (getPropertyTable() || super::init()) {
1641 IOUserClient::initWithTask(task_t owningTask
,
1644 OSDictionary
* properties
)
1648 ok
= super::init( properties
);
1649 ok
&= initWithTask( owningTask
, securityID
, type
);
1655 IOUserClient::reserve()
1658 reserved
= IONewZero(ExpansionData
, 1);
1663 setTerminateDefer(NULL
, true);
1664 IOStatisticsRegisterCounter();
1669 struct IOUserClientOwner
{
1671 queue_chain_t taskLink
;
1673 queue_chain_t ucLink
;
1677 IOUserClient::registerOwner(task_t task
)
1679 IOUserClientOwner
* owner
;
1683 IOLockLock(gIOUserClientOwnersLock
);
1686 ret
= kIOReturnSuccess
;
1689 queue_init(&owners
);
1691 queue_iterate(&owners
, owner
, IOUserClientOwner
*, ucLink
)
1693 if (task
!= owner
->task
) {
1701 owner
= IONew(IOUserClientOwner
, 1);
1703 ret
= kIOReturnNoMemory
;
1707 queue_enter_first(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1708 queue_enter_first(task_io_user_clients(task
), owner
, IOUserClientOwner
*, taskLink
);
1709 if (messageAppSuspended
) {
1710 task_set_message_app_suspended(task
, true);
1715 IOLockUnlock(gIOUserClientOwnersLock
);
1721 IOUserClient::noMoreSenders(void)
1723 IOUserClientOwner
* owner
;
1724 IOUserClientOwner
* iter
;
1725 queue_head_t
* taskque
;
1726 bool hasMessageAppSuspended
;
1728 IOLockLock(gIOUserClientOwnersLock
);
1731 while (!queue_empty(&owners
)) {
1732 owner
= (IOUserClientOwner
*)(void *) queue_first(&owners
);
1733 taskque
= task_io_user_clients(owner
->task
);
1734 queue_remove(taskque
, owner
, IOUserClientOwner
*, taskLink
);
1735 hasMessageAppSuspended
= false;
1736 queue_iterate(taskque
, iter
, IOUserClientOwner
*, taskLink
) {
1737 hasMessageAppSuspended
= iter
->uc
->messageAppSuspended
;
1738 if (hasMessageAppSuspended
) {
1742 task_set_message_app_suspended(owner
->task
, hasMessageAppSuspended
);
1743 queue_remove(&owners
, owner
, IOUserClientOwner
*, ucLink
);
1744 IODelete(owner
, IOUserClientOwner
, 1);
1746 owners
.next
= owners
.prev
= NULL
;
1749 IOLockUnlock(gIOUserClientOwnersLock
);
1754 iokit_task_app_suspended_changed(task_t task
)
1756 queue_head_t
* taskque
;
1757 IOUserClientOwner
* owner
;
1760 IOLockLock(gIOUserClientOwnersLock
);
1762 taskque
= task_io_user_clients(task
);
1764 queue_iterate(taskque
, owner
, IOUserClientOwner
*, taskLink
) {
1765 if (!owner
->uc
->messageAppSuspended
) {
1769 set
= OSSet::withCapacity(4);
1774 set
->setObject(owner
->uc
);
1777 IOLockUnlock(gIOUserClientOwnersLock
);
1780 set
->iterateObjects(^bool (OSObject
* obj
) {
1783 uc
= (typeof(uc
))obj
;
1787 str
= IOCopyLogNameForPID(task_pid(task
));
1788 IOLog("iokit_task_app_suspended_changed(%s) %s %d\n", str
? str
->getCStringNoCopy() : "",
1789 uc
->getName(), task_is_app_suspended(task
));
1790 OSSafeReleaseNULL(str
);
1793 uc
->message(kIOMessageTaskAppSuspendedChange
, NULL
);
1801 extern "C" kern_return_t
1802 iokit_task_terminate(task_t task
)
1804 IOUserClientOwner
* owner
;
1805 IOUserClient
* dead
;
1807 queue_head_t
* taskque
;
1809 IOLockLock(gIOUserClientOwnersLock
);
1811 taskque
= task_io_user_clients(task
);
1813 while (!queue_empty(taskque
)) {
1814 owner
= (IOUserClientOwner
*)(void *) queue_first(taskque
);
1816 queue_remove(taskque
, owner
, IOUserClientOwner
*, taskLink
);
1817 queue_remove(&uc
->owners
, owner
, IOUserClientOwner
*, ucLink
);
1818 if (queue_empty(&uc
->owners
)) {
1820 IOLog("destroying out of band connect for %s\n", uc
->getName());
1821 // now using the uc queue head as a singly linked queue,
1822 // leaving .next as NULL to mark it empty
1823 uc
->owners
.next
= NULL
;
1824 uc
->owners
.prev
= (queue_entry_t
) dead
;
1827 IODelete(owner
, IOUserClientOwner
, 1);
1830 IOLockUnlock(gIOUserClientOwnersLock
);
1834 dead
= (IOUserClient
*)(void *) dead
->owners
.prev
;
1835 uc
->owners
.prev
= NULL
;
1836 if (uc
->sharedInstance
|| !uc
->closed
) {
1842 return KERN_SUCCESS
;
1845 struct IOUCFilterPolicy
{
1847 io_filter_policy_t filterPolicy
;
1848 IOUCFilterPolicy
* next
;
1852 IOUserClient::filterForTask(task_t task
, io_filter_policy_t addFilterPolicy
)
1854 IOUCFilterPolicy
* elem
;
1855 io_filter_policy_t filterPolicy
;
1858 IOLockLock(filterLock
);
1860 for (elem
= reserved
->filterPolicies
; elem
&& (elem
->task
!= task
); elem
= elem
->next
) {
1864 if (addFilterPolicy
) {
1865 assert(addFilterPolicy
== elem
->filterPolicy
);
1867 filterPolicy
= elem
->filterPolicy
;
1868 } else if (addFilterPolicy
) {
1869 elem
= IONewZero(IOUCFilterPolicy
, 1);
1872 elem
->filterPolicy
= addFilterPolicy
;
1873 elem
->next
= reserved
->filterPolicies
;
1874 reserved
->filterPolicies
= elem
;
1875 filterPolicy
= addFilterPolicy
;
1879 IOLockUnlock(filterLock
);
1880 return filterPolicy
;
1884 IOUserClient::free()
1887 mappings
->release();
1893 IOLockFree(filterLock
);
1896 IOStatisticsUnregisterCounter();
1898 assert(!owners
.next
);
1899 assert(!owners
.prev
);
1902 IOUCFilterPolicy
* elem
;
1903 IOUCFilterPolicy
* nextElem
;
1904 for (elem
= reserved
->filterPolicies
; elem
; elem
= nextElem
) {
1905 nextElem
= elem
->next
;
1906 if (elem
->filterPolicy
&& gIOUCFilterCallbacks
->io_filter_release
) {
1907 gIOUCFilterCallbacks
->io_filter_release(elem
->filterPolicy
);
1909 IODelete(elem
, IOUCFilterPolicy
, 1);
1911 IODelete(reserved
, ExpansionData
, 1);
1918 IOUserClient::clientDied( void )
1920 IOReturn ret
= kIOReturnNotReady
;
1922 if (sharedInstance
|| OSCompareAndSwap8(0, 1, &closed
)) {
1923 ret
= clientClose();
1930 IOUserClient::clientClose( void )
1932 return kIOReturnUnsupported
;
1936 IOUserClient::getService( void )
1942 IOUserClient::registerNotificationPort(
1943 mach_port_t
/* port */,
1945 UInt32
/* refCon */)
1947 return kIOReturnUnsupported
;
1951 IOUserClient::registerNotificationPort(
1954 io_user_reference_t refCon
)
1956 return registerNotificationPort(port
, type
, (UInt32
) refCon
);
1960 IOUserClient::getNotificationSemaphore( UInt32 notification_type
,
1961 semaphore_t
* semaphore
)
1963 return kIOReturnUnsupported
;
1967 IOUserClient::connectClient( IOUserClient
* /* client */ )
1969 return kIOReturnUnsupported
;
1973 IOUserClient::clientMemoryForType( UInt32 type
,
1974 IOOptionBits
* options
,
1975 IOMemoryDescriptor
** memory
)
1977 return kIOReturnUnsupported
;
1981 IOUserClient::clientMemoryForType( UInt32 type
,
1982 IOOptionBits
* options
,
1983 OSSharedPtr
<IOMemoryDescriptor
>& memory
)
1985 IOMemoryDescriptor
* memoryRaw
= nullptr;
1986 IOReturn result
= clientMemoryForType(type
, options
, &memoryRaw
);
1987 memory
.reset(memoryRaw
, OSNoRetain
);
1993 IOUserClient::mapClientMemory(
1996 IOOptionBits mapFlags
,
1997 IOVirtualAddress atAddress
)
2004 IOUserClient::mapClientMemory64(
2007 IOOptionBits mapFlags
,
2008 mach_vm_address_t atAddress
)
2011 IOOptionBits options
= 0;
2012 IOMemoryDescriptor
* memory
= NULL
;
2013 IOMemoryMap
* map
= NULL
;
2015 err
= clientMemoryForType((UInt32
) type
, &options
, &memory
);
2017 if (memory
&& (kIOReturnSuccess
== err
)) {
2018 FAKE_STACK_FRAME(getMetaClass());
2020 options
= (options
& ~kIOMapUserOptionsMask
)
2021 | (mapFlags
& kIOMapUserOptionsMask
);
2022 map
= memory
->createMappingInTask( task
, atAddress
, options
);
2025 FAKE_STACK_FRAME_END();
2032 IOUserClient::exportObjectToClient(task_t task
,
2033 OSObject
*obj
, io_object_t
*clientObj
)
2035 mach_port_name_t name
;
2037 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT
);
2039 *clientObj
= (io_object_t
)(uintptr_t) name
;
2045 return kIOReturnSuccess
;
2049 IOUserClient::copyPortNameForObjectInTask(task_t task
,
2050 OSObject
*obj
, mach_port_name_t
* port_name
)
2052 mach_port_name_t name
;
2054 name
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_IDENT
);
2056 *(mach_port_name_t
*) port_name
= name
;
2058 return kIOReturnSuccess
;
2062 IOUserClient::copyObjectForPortNameInTask(task_t task
, mach_port_name_t port_name
,
2067 object
= iokit_lookup_object_with_port_name(port_name
, IKOT_IOKIT_IDENT
, task
);
2071 return object
? kIOReturnSuccess
: kIOReturnIPCError
;
2075 IOUserClient::copyObjectForPortNameInTask(task_t task
, mach_port_name_t port_name
,
2076 OSSharedPtr
<OSObject
>& obj
)
2078 OSObject
* objRaw
= NULL
;
2079 IOReturn result
= copyObjectForPortNameInTask(task
, port_name
, &objRaw
);
2080 obj
.reset(objRaw
, OSNoRetain
);
2085 IOUserClient::adjustPortNameReferencesInTask(task_t task
, mach_port_name_t port_name
, mach_port_delta_t delta
)
2087 return iokit_mod_send_right(task
, port_name
, delta
);
2091 IOUserClient::getExternalMethodForIndex( UInt32
/* index */)
2096 IOExternalAsyncMethod
*
2097 IOUserClient::getExternalAsyncMethodForIndex( UInt32
/* index */)
2104 getExternalTrapForIndex(UInt32 index
)
2109 #pragma clang diagnostic push
2110 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2112 // Suppressing the deprecated-declarations warning. Avoiding the use of deprecated
2113 // functions can break clients of kexts implementing getExternalMethodForIndex()
2116 getTargetAndMethodForIndex(IOService
**targetP
, UInt32 index
)
2118 IOExternalMethod
*method
= getExternalMethodForIndex(index
);
2121 *targetP
= (IOService
*) method
->object
;
2129 getTargetAndMethodForIndex(OSSharedPtr
<IOService
>& targetP
, UInt32 index
)
2131 IOService
* targetPRaw
= NULL
;
2132 IOExternalMethod
* result
= getTargetAndMethodForIndex(&targetPRaw
, index
);
2133 targetP
.reset(targetPRaw
, OSRetain
);
2137 IOExternalAsyncMethod
*
2139 getAsyncTargetAndMethodForIndex(IOService
** targetP
, UInt32 index
)
2141 IOExternalAsyncMethod
*method
= getExternalAsyncMethodForIndex(index
);
2144 *targetP
= (IOService
*) method
->object
;
2150 IOExternalAsyncMethod
*
2152 getAsyncTargetAndMethodForIndex(OSSharedPtr
<IOService
>& targetP
, UInt32 index
)
2154 IOService
* targetPRaw
= NULL
;
2155 IOExternalAsyncMethod
* result
= getAsyncTargetAndMethodForIndex(&targetPRaw
, index
);
2156 targetP
.reset(targetPRaw
, OSRetain
);
2162 getTargetAndTrapForIndex(IOService
** targetP
, UInt32 index
)
2164 IOExternalTrap
*trap
= getExternalTrapForIndex(index
);
2167 *targetP
= trap
->object
;
2172 #pragma clang diagnostic pop
2175 IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference
)
2178 port
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
2180 if (MACH_PORT_NULL
!= port
) {
2181 iokit_release_port_send(port
);
2184 return kIOReturnSuccess
;
2188 IOUserClient::releaseNotificationPort(mach_port_t port
)
2190 if (MACH_PORT_NULL
!= port
) {
2191 iokit_release_port_send(port
);
2194 return kIOReturnSuccess
;
2198 IOUserClient::sendAsyncResult(OSAsyncReference reference
,
2199 IOReturn result
, void *args
[], UInt32 numArgs
)
2201 OSAsyncReference64 reference64
;
2202 io_user_reference_t args64
[kMaxAsyncArgs
];
2205 if (numArgs
> kMaxAsyncArgs
) {
2206 return kIOReturnMessageTooLarge
;
2209 for (idx
= 0; idx
< kOSAsyncRef64Count
; idx
++) {
2210 reference64
[idx
] = REF64(reference
[idx
]);
2213 for (idx
= 0; idx
< numArgs
; idx
++) {
2214 args64
[idx
] = REF64(args
[idx
]);
2217 return sendAsyncResult64(reference64
, result
, args64
, numArgs
);
2221 IOUserClient::sendAsyncResult64WithOptions(OSAsyncReference64 reference
,
2222 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
2224 return _sendAsyncResult64(reference
, result
, args
, numArgs
, options
);
2228 IOUserClient::sendAsyncResult64(OSAsyncReference64 reference
,
2229 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
)
2231 return _sendAsyncResult64(reference
, result
, args
, numArgs
, 0);
2235 IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference
,
2236 IOReturn result
, io_user_reference_t args
[], UInt32 numArgs
, IOOptionBits options
)
2239 mach_msg_header_t msgHdr
;
2242 OSNotificationHeader notifyHdr
;
2243 IOAsyncCompletionContent asyncContent
;
2244 uint32_t args
[kMaxAsyncArgs
];
2247 OSNotificationHeader64 notifyHdr
;
2248 IOAsyncCompletionContent asyncContent
;
2249 io_user_reference_t args
[kMaxAsyncArgs
] __attribute__ ((packed
));
2254 mach_port_t replyPort
;
2257 // If no reply port, do nothing.
2258 replyPort
= (mach_port_t
) (reference
[0] & ~kIOUCAsync0Flags
);
2259 if (replyPort
== MACH_PORT_NULL
) {
2260 return kIOReturnSuccess
;
2263 if (numArgs
> kMaxAsyncArgs
) {
2264 return kIOReturnMessageTooLarge
;
2267 bzero(&replyMsg
, sizeof(replyMsg
));
2268 replyMsg
.msgHdr
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
/*remote*/,
2270 replyMsg
.msgHdr
.msgh_remote_port
= replyPort
;
2271 replyMsg
.msgHdr
.msgh_local_port
= NULL
;
2272 replyMsg
.msgHdr
.msgh_id
= kOSNotificationMessageID
;
2273 if (kIOUCAsync64Flag
& reference
[0]) {
2274 replyMsg
.msgHdr
.msgh_size
=
2275 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg64
)
2276 - (kMaxAsyncArgs
- numArgs
) * sizeof(io_user_reference_t
);
2277 replyMsg
.m
.msg64
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
2278 + numArgs
* sizeof(io_user_reference_t
);
2279 replyMsg
.m
.msg64
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
2280 /* Copy reference except for reference[0], which is left as 0 from the earlier bzero */
2281 bcopy(&reference
[1], &replyMsg
.m
.msg64
.notifyHdr
.reference
[1], sizeof(OSAsyncReference64
) - sizeof(reference
[0]));
2283 replyMsg
.m
.msg64
.asyncContent
.result
= result
;
2285 bcopy(args
, replyMsg
.m
.msg64
.args
, numArgs
* sizeof(io_user_reference_t
));
2290 replyMsg
.msgHdr
.msgh_size
=
2291 sizeof(replyMsg
.msgHdr
) + sizeof(replyMsg
.m
.msg32
)
2292 - (kMaxAsyncArgs
- numArgs
) * sizeof(uint32_t);
2294 replyMsg
.m
.msg32
.notifyHdr
.size
= sizeof(IOAsyncCompletionContent
)
2295 + numArgs
* sizeof(uint32_t);
2296 replyMsg
.m
.msg32
.notifyHdr
.type
= kIOAsyncCompletionNotificationType
;
2298 /* Skip reference[0] which is left as 0 from the earlier bzero */
2299 for (idx
= 1; idx
< kOSAsyncRefCount
; idx
++) {
2300 replyMsg
.m
.msg32
.notifyHdr
.reference
[idx
] = REF32(reference
[idx
]);
2303 replyMsg
.m
.msg32
.asyncContent
.result
= result
;
2305 for (idx
= 0; idx
< numArgs
; idx
++) {
2306 replyMsg
.m
.msg32
.args
[idx
] = REF32(args
[idx
]);
2310 if ((options
& kIOUserNotifyOptionCanDrop
) != 0) {
2311 kr
= mach_msg_send_from_kernel_with_options( &replyMsg
.msgHdr
,
2312 replyMsg
.msgHdr
.msgh_size
, MACH_SEND_TIMEOUT
, MACH_MSG_TIMEOUT_NONE
);
2314 /* Fail on full queue. */
2315 kr
= mach_msg_send_from_kernel_proper( &replyMsg
.msgHdr
,
2316 replyMsg
.msgHdr
.msgh_size
);
2318 if ((KERN_SUCCESS
!= kr
) && (MACH_SEND_TIMED_OUT
!= kr
) && !(kIOUCAsyncErrorLoggedFlag
& reference
[0])) {
2319 reference
[0] |= kIOUCAsyncErrorLoggedFlag
;
2320 IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__
, kr
);
2326 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2329 #define CHECK(cls, obj, out) \
2331 if( !(out = OSDynamicCast( cls, obj))) \
2332 return( kIOReturnBadArgument )
2334 #define CHECKLOCKED(cls, obj, out) \
2335 IOUserIterator * oIter; \
2337 if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
2338 return (kIOReturnBadArgument); \
2339 if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
2340 return (kIOReturnBadArgument)
2342 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2344 // Create a vm_map_copy_t or kalloc'ed data for memory
2345 // to be copied out. ipc will free after the copyout.
2347 static kern_return_t
2348 copyoutkdata( const void * data
, vm_size_t len
,
2349 io_buf_ptr_t
* buf
)
2354 err
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
,
2355 false /* src_destroy */, ©
);
2357 assert( err
== KERN_SUCCESS
);
2358 if (err
== KERN_SUCCESS
) {
2359 *buf
= (char *) copy
;
2365 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2367 /* Routine io_server_version */
2369 is_io_server_version(
2370 mach_port_t master_port
,
2373 *version
= IOKIT_SERVER_VERSION
;
2374 return kIOReturnSuccess
;
2377 /* Routine io_object_get_class */
2379 is_io_object_get_class(
2381 io_name_t className
)
2383 const OSMetaClass
* my_obj
= NULL
;
2386 return kIOReturnBadArgument
;
2389 my_obj
= object
->getMetaClass();
2391 return kIOReturnNotFound
;
2394 strlcpy( className
, my_obj
->getClassName(), sizeof(io_name_t
));
2396 return kIOReturnSuccess
;
2399 /* Routine io_object_get_superclass */
2401 is_io_object_get_superclass(
2402 mach_port_t master_port
,
2404 io_name_t class_name
)
2407 const OSMetaClass
* meta
;
2408 const OSMetaClass
* super
;
2409 const OSSymbol
* name
;
2412 if (!obj_name
|| !class_name
) {
2413 return kIOReturnBadArgument
;
2415 if (master_port
!= master_device_port
) {
2416 return kIOReturnNotPrivileged
;
2419 ret
= kIOReturnNotFound
;
2422 name
= OSSymbol::withCString(obj_name
);
2426 meta
= OSMetaClass::copyMetaClassWithName(name
);
2430 super
= meta
->getSuperClass();
2434 cstr
= super
->getClassName();
2438 strlcpy(class_name
, cstr
, sizeof(io_name_t
));
2439 ret
= kIOReturnSuccess
;
2442 OSSafeReleaseNULL(name
);
2444 meta
->releaseMetaClass();
2450 /* Routine io_object_get_bundle_identifier */
2452 is_io_object_get_bundle_identifier(
2453 mach_port_t master_port
,
2455 io_name_t bundle_name
)
2458 const OSMetaClass
* meta
;
2459 const OSSymbol
* name
;
2460 const OSSymbol
* identifier
;
2463 if (!obj_name
|| !bundle_name
) {
2464 return kIOReturnBadArgument
;
2466 if (master_port
!= master_device_port
) {
2467 return kIOReturnNotPrivileged
;
2470 ret
= kIOReturnNotFound
;
2473 name
= OSSymbol::withCString(obj_name
);
2477 meta
= OSMetaClass::copyMetaClassWithName(name
);
2481 identifier
= meta
->getKmodName();
2485 cstr
= identifier
->getCStringNoCopy();
2489 strlcpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
));
2490 ret
= kIOReturnSuccess
;
2493 OSSafeReleaseNULL(name
);
2495 meta
->releaseMetaClass();
2501 /* Routine io_object_conforms_to */
2503 is_io_object_conforms_to(
2505 io_name_t className
,
2506 boolean_t
*conforms
)
2509 return kIOReturnBadArgument
;
2512 *conforms
= (NULL
!= object
->metaCast( className
));
2514 return kIOReturnSuccess
;
2517 /* Routine io_object_get_retain_count */
2519 is_io_object_get_retain_count(
2521 uint32_t *retainCount
)
2524 return kIOReturnBadArgument
;
2527 *retainCount
= object
->getRetainCount();
2528 return kIOReturnSuccess
;
2531 /* Routine io_iterator_next */
2533 is_io_iterator_next(
2534 io_object_t iterator
,
2535 io_object_t
*object
)
2540 IOUserIterator
* uiter
;
2542 if ((uiter
= OSDynamicCast(IOUserIterator
, iterator
))) {
2543 obj
= uiter
->copyNextObject();
2544 } else if ((iter
= OSDynamicCast(OSIterator
, iterator
))) {
2545 obj
= iter
->getNextObject();
2550 return kIOReturnBadArgument
;
2555 ret
= kIOReturnSuccess
;
2557 ret
= kIOReturnNoDevice
;
2563 /* Routine io_iterator_reset */
2565 is_io_iterator_reset(
2566 io_object_t iterator
)
2568 CHECK( OSIterator
, iterator
, iter
);
2572 return kIOReturnSuccess
;
2575 /* Routine io_iterator_is_valid */
2577 is_io_iterator_is_valid(
2578 io_object_t iterator
,
2579 boolean_t
*is_valid
)
2581 CHECK( OSIterator
, iterator
, iter
);
2583 *is_valid
= iter
->isValid();
2585 return kIOReturnSuccess
;
2588 static kern_return_t
2589 internal_io_service_match_property_table(
2590 io_service_t _service
,
2591 const char * matching
,
2592 mach_msg_type_number_t matching_size
,
2595 CHECK( IOService
, _service
, service
);
2599 OSDictionary
* dict
;
2601 assert(matching_size
);
2604 obj
= OSUnserializeXML(matching
, matching_size
);
2606 if ((dict
= OSDynamicCast( OSDictionary
, obj
))) {
2607 IOTaskRegistryCompatibilityMatching(current_task(), dict
);
2608 *matches
= service
->passiveMatch( dict
);
2609 kr
= kIOReturnSuccess
;
2611 kr
= kIOReturnBadArgument
;
2621 /* Routine io_service_match_property_table */
2623 is_io_service_match_property_table(
2624 io_service_t service
,
2625 io_string_t matching
,
2626 boolean_t
*matches
)
2628 return kIOReturnUnsupported
;
2632 /* Routine io_service_match_property_table_ool */
2634 is_io_service_match_property_table_ool(
2635 io_object_t service
,
2636 io_buf_ptr_t matching
,
2637 mach_msg_type_number_t matchingCnt
,
2638 kern_return_t
*result
,
2639 boolean_t
*matches
)
2643 vm_map_offset_t map_data
;
2645 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2646 data
= CAST_DOWN(vm_offset_t
, map_data
);
2648 if (KERN_SUCCESS
== kr
) {
2649 // must return success after vm_map_copyout() succeeds
2650 *result
= internal_io_service_match_property_table(service
,
2651 (const char *)data
, matchingCnt
, matches
);
2652 vm_deallocate( kernel_map
, data
, matchingCnt
);
2658 /* Routine io_service_match_property_table_bin */
2660 is_io_service_match_property_table_bin(
2661 io_object_t service
,
2662 io_struct_inband_t matching
,
2663 mach_msg_type_number_t matchingCnt
,
2666 return internal_io_service_match_property_table(service
, matching
, matchingCnt
, matches
);
2669 static kern_return_t
2670 internal_io_service_get_matching_services(
2671 mach_port_t master_port
,
2672 const char * matching
,
2673 mach_msg_type_number_t matching_size
,
2674 io_iterator_t
*existing
)
2678 OSDictionary
* dict
;
2680 if (master_port
!= master_device_port
) {
2681 return kIOReturnNotPrivileged
;
2684 assert(matching_size
);
2685 obj
= OSUnserializeXML(matching
, matching_size
);
2687 if ((dict
= OSDynamicCast( OSDictionary
, obj
))) {
2688 IOTaskRegistryCompatibilityMatching(current_task(), dict
);
2689 *existing
= IOUserIterator::withIterator(IOService::getMatchingServices( dict
));
2690 kr
= kIOReturnSuccess
;
2692 kr
= kIOReturnBadArgument
;
2702 /* Routine io_service_get_matching_services */
2704 is_io_service_get_matching_services(
2705 mach_port_t master_port
,
2706 io_string_t matching
,
2707 io_iterator_t
*existing
)
2709 return kIOReturnUnsupported
;
2712 /* Routine io_service_get_matching_services_ool */
2714 is_io_service_get_matching_services_ool(
2715 mach_port_t master_port
,
2716 io_buf_ptr_t matching
,
2717 mach_msg_type_number_t matchingCnt
,
2718 kern_return_t
*result
,
2719 io_object_t
*existing
)
2723 vm_map_offset_t map_data
;
2725 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2726 data
= CAST_DOWN(vm_offset_t
, map_data
);
2728 if (KERN_SUCCESS
== kr
) {
2729 // must return success after vm_map_copyout() succeeds
2730 // and mig will copy out objects on success
2732 *result
= internal_io_service_get_matching_services(master_port
,
2733 (const char *) data
, matchingCnt
, existing
);
2734 vm_deallocate( kernel_map
, data
, matchingCnt
);
2740 /* Routine io_service_get_matching_services_bin */
2742 is_io_service_get_matching_services_bin(
2743 mach_port_t master_port
,
2744 io_struct_inband_t matching
,
2745 mach_msg_type_number_t matchingCnt
,
2746 io_object_t
*existing
)
2748 return internal_io_service_get_matching_services(master_port
, matching
, matchingCnt
, existing
);
2752 static kern_return_t
2753 internal_io_service_get_matching_service(
2754 mach_port_t master_port
,
2755 const char * matching
,
2756 mach_msg_type_number_t matching_size
,
2757 io_service_t
*service
)
2761 OSDictionary
* dict
;
2763 if (master_port
!= master_device_port
) {
2764 return kIOReturnNotPrivileged
;
2767 assert(matching_size
);
2768 obj
= OSUnserializeXML(matching
, matching_size
);
2770 if ((dict
= OSDynamicCast( OSDictionary
, obj
))) {
2771 IOTaskRegistryCompatibilityMatching(current_task(), dict
);
2772 *service
= IOService::copyMatchingService( dict
);
2773 kr
= *service
? kIOReturnSuccess
: kIOReturnNotFound
;
2775 kr
= kIOReturnBadArgument
;
2785 /* Routine io_service_get_matching_service */
2787 is_io_service_get_matching_service(
2788 mach_port_t master_port
,
2789 io_string_t matching
,
2790 io_service_t
*service
)
2792 return kIOReturnUnsupported
;
2795 /* Routine io_service_get_matching_services_ool */
2797 is_io_service_get_matching_service_ool(
2798 mach_port_t master_port
,
2799 io_buf_ptr_t matching
,
2800 mach_msg_type_number_t matchingCnt
,
2801 kern_return_t
*result
,
2802 io_object_t
*service
)
2806 vm_map_offset_t map_data
;
2808 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
2809 data
= CAST_DOWN(vm_offset_t
, map_data
);
2811 if (KERN_SUCCESS
== kr
) {
2812 // must return success after vm_map_copyout() succeeds
2813 // and mig will copy out objects on success
2815 *result
= internal_io_service_get_matching_service(master_port
,
2816 (const char *) data
, matchingCnt
, service
);
2817 vm_deallocate( kernel_map
, data
, matchingCnt
);
2823 /* Routine io_service_get_matching_service_bin */
2825 is_io_service_get_matching_service_bin(
2826 mach_port_t master_port
,
2827 io_struct_inband_t matching
,
2828 mach_msg_type_number_t matchingCnt
,
2829 io_object_t
*service
)
2831 return internal_io_service_get_matching_service(master_port
, matching
, matchingCnt
, service
);
2834 static kern_return_t
2835 internal_io_service_add_notification(
2836 mach_port_t master_port
,
2837 io_name_t notification_type
,
2838 const char * matching
,
2839 size_t matching_size
,
2842 vm_size_t referenceSize
,
2844 io_object_t
* notification
)
2846 IOServiceUserNotification
* userNotify
= NULL
;
2847 IONotifier
* notify
= NULL
;
2848 const OSSymbol
* sym
;
2850 OSDictionary
* dict
;
2852 natural_t userMsgType
;
2854 if (master_port
!= master_device_port
) {
2855 return kIOReturnNotPrivileged
;
2859 err
= kIOReturnNoResources
;
2861 if (matching_size
> (sizeof(io_struct_inband_t
) * 1024)) {
2862 return kIOReturnMessageTooLarge
;
2865 if (!(sym
= OSSymbol::withCString( notification_type
))) {
2866 err
= kIOReturnNoResources
;
2869 assert(matching_size
);
2870 obj
= OSUnserializeXML(matching
, matching_size
);
2871 dict
= OSDynamicCast(OSDictionary
, obj
);
2873 err
= kIOReturnBadArgument
;
2876 IOTaskRegistryCompatibilityMatching(current_task(), dict
);
2878 if ((sym
== gIOPublishNotification
)
2879 || (sym
== gIOFirstPublishNotification
)) {
2880 userMsgType
= kIOServicePublishNotificationType
;
2881 } else if ((sym
== gIOMatchedNotification
)
2882 || (sym
== gIOFirstMatchNotification
)) {
2883 userMsgType
= kIOServiceMatchedNotificationType
;
2884 } else if ((sym
== gIOTerminatedNotification
)
2885 || (sym
== gIOWillTerminateNotification
)) {
2886 userMsgType
= kIOServiceTerminatedNotificationType
;
2888 userMsgType
= kLastIOKitNotificationType
;
2891 userNotify
= new IOServiceUserNotification
;
2893 if (userNotify
&& !userNotify
->init( port
, userMsgType
,
2894 reference
, referenceSize
, client64
)) {
2895 userNotify
->release();
2902 notify
= IOService::addMatchingNotification( sym
, dict
,
2903 &userNotify
->_handler
, userNotify
);
2905 *notification
= userNotify
;
2906 userNotify
->setNotification( notify
);
2907 err
= kIOReturnSuccess
;
2909 err
= kIOReturnUnsupported
;
2913 if ((kIOReturnSuccess
!= err
) && userNotify
) {
2914 userNotify
->invalidatePort();
2915 userNotify
->release();
2930 /* Routine io_service_add_notification */
2932 is_io_service_add_notification(
2933 mach_port_t master_port
,
2934 io_name_t notification_type
,
2935 io_string_t matching
,
2937 io_async_ref_t reference
,
2938 mach_msg_type_number_t referenceCnt
,
2939 io_object_t
* notification
)
2941 return kIOReturnUnsupported
;
2944 /* Routine io_service_add_notification_64 */
2946 is_io_service_add_notification_64(
2947 mach_port_t master_port
,
2948 io_name_t notification_type
,
2949 io_string_t matching
,
2950 mach_port_t wake_port
,
2951 io_async_ref64_t reference
,
2952 mach_msg_type_number_t referenceCnt
,
2953 io_object_t
*notification
)
2955 return kIOReturnUnsupported
;
2958 /* Routine io_service_add_notification_bin */
2960 is_io_service_add_notification_bin
2962 mach_port_t master_port
,
2963 io_name_t notification_type
,
2964 io_struct_inband_t matching
,
2965 mach_msg_type_number_t matchingCnt
,
2966 mach_port_t wake_port
,
2967 io_async_ref_t reference
,
2968 mach_msg_type_number_t referenceCnt
,
2969 io_object_t
*notification
)
2971 io_async_ref_t zreference
;
2973 if (referenceCnt
> ASYNC_REF_COUNT
) {
2974 return kIOReturnBadArgument
;
2976 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
2977 bzero(&zreference
[referenceCnt
], (ASYNC_REF_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
2979 return internal_io_service_add_notification(master_port
, notification_type
,
2980 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref_t
),
2981 false, notification
);
2984 /* Routine io_service_add_notification_bin_64 */
2986 is_io_service_add_notification_bin_64
2988 mach_port_t master_port
,
2989 io_name_t notification_type
,
2990 io_struct_inband_t matching
,
2991 mach_msg_type_number_t matchingCnt
,
2992 mach_port_t wake_port
,
2993 io_async_ref64_t reference
,
2994 mach_msg_type_number_t referenceCnt
,
2995 io_object_t
*notification
)
2997 io_async_ref64_t zreference
;
2999 if (referenceCnt
> ASYNC_REF64_COUNT
) {
3000 return kIOReturnBadArgument
;
3002 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
3003 bzero(&zreference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
3005 return internal_io_service_add_notification(master_port
, notification_type
,
3006 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref64_t
),
3007 true, notification
);
3010 static kern_return_t
3011 internal_io_service_add_notification_ool(
3012 mach_port_t master_port
,
3013 io_name_t notification_type
,
3014 io_buf_ptr_t matching
,
3015 mach_msg_type_number_t matchingCnt
,
3016 mach_port_t wake_port
,
3018 vm_size_t referenceSize
,
3020 kern_return_t
*result
,
3021 io_object_t
*notification
)
3025 vm_map_offset_t map_data
;
3027 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching
);
3028 data
= CAST_DOWN(vm_offset_t
, map_data
);
3030 if (KERN_SUCCESS
== kr
) {
3031 // must return success after vm_map_copyout() succeeds
3032 // and mig will copy out objects on success
3033 *notification
= NULL
;
3034 *result
= internal_io_service_add_notification( master_port
, notification_type
,
3035 (char *) data
, matchingCnt
, wake_port
, reference
, referenceSize
, client64
, notification
);
3036 vm_deallocate( kernel_map
, data
, matchingCnt
);
3042 /* Routine io_service_add_notification_ool */
3044 is_io_service_add_notification_ool(
3045 mach_port_t master_port
,
3046 io_name_t notification_type
,
3047 io_buf_ptr_t matching
,
3048 mach_msg_type_number_t matchingCnt
,
3049 mach_port_t wake_port
,
3050 io_async_ref_t reference
,
3051 mach_msg_type_number_t referenceCnt
,
3052 kern_return_t
*result
,
3053 io_object_t
*notification
)
3055 io_async_ref_t zreference
;
3057 if (referenceCnt
> ASYNC_REF_COUNT
) {
3058 return kIOReturnBadArgument
;
3060 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
3061 bzero(&zreference
[referenceCnt
], (ASYNC_REF_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
3063 return internal_io_service_add_notification_ool(master_port
, notification_type
,
3064 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref_t
),
3065 false, result
, notification
);
3068 /* Routine io_service_add_notification_ool_64 */
3070 is_io_service_add_notification_ool_64(
3071 mach_port_t master_port
,
3072 io_name_t notification_type
,
3073 io_buf_ptr_t matching
,
3074 mach_msg_type_number_t matchingCnt
,
3075 mach_port_t wake_port
,
3076 io_async_ref64_t reference
,
3077 mach_msg_type_number_t referenceCnt
,
3078 kern_return_t
*result
,
3079 io_object_t
*notification
)
3081 io_async_ref64_t zreference
;
3083 if (referenceCnt
> ASYNC_REF64_COUNT
) {
3084 return kIOReturnBadArgument
;
3086 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
3087 bzero(&zreference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
3089 return internal_io_service_add_notification_ool(master_port
, notification_type
,
3090 matching
, matchingCnt
, wake_port
, &zreference
[0], sizeof(io_async_ref64_t
),
3091 true, result
, notification
);
3094 /* Routine io_service_add_notification_old */
3096 is_io_service_add_notification_old(
3097 mach_port_t master_port
,
3098 io_name_t notification_type
,
3099 io_string_t matching
,
3101 // for binary compatibility reasons, this must be natural_t for ILP32
3103 io_object_t
* notification
)
3105 return is_io_service_add_notification( master_port
, notification_type
,
3106 matching
, port
, &ref
, 1, notification
);
3110 static kern_return_t
3111 internal_io_service_add_interest_notification(
3112 io_object_t _service
,
3113 io_name_t type_of_interest
,
3116 vm_size_t referenceSize
,
3118 io_object_t
* notification
)
3120 IOServiceMessageUserNotification
* userNotify
= NULL
;
3121 IONotifier
* notify
= NULL
;
3122 const OSSymbol
* sym
;
3125 CHECK( IOService
, _service
, service
);
3127 err
= kIOReturnNoResources
;
3128 if ((sym
= OSSymbol::withCString( type_of_interest
))) {
3130 userNotify
= new IOServiceMessageUserNotification
;
3132 if (userNotify
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
,
3133 reference
, referenceSize
,
3134 kIOUserNotifyMaxMessageSize
,
3136 userNotify
->release();
3143 notify
= service
->registerInterest( sym
,
3144 &userNotify
->_handler
, userNotify
);
3146 *notification
= userNotify
;
3147 userNotify
->setNotification( notify
);
3148 err
= kIOReturnSuccess
;
3150 err
= kIOReturnUnsupported
;
3157 if ((kIOReturnSuccess
!= err
) && userNotify
) {
3158 userNotify
->invalidatePort();
3159 userNotify
->release();
3166 /* Routine io_service_add_message_notification */
3168 is_io_service_add_interest_notification(
3169 io_object_t service
,
3170 io_name_t type_of_interest
,
3172 io_async_ref_t reference
,
3173 mach_msg_type_number_t referenceCnt
,
3174 io_object_t
* notification
)
3176 io_async_ref_t zreference
;
3178 if (referenceCnt
> ASYNC_REF_COUNT
) {
3179 return kIOReturnBadArgument
;
3181 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
3182 bzero(&zreference
[referenceCnt
], (ASYNC_REF_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
3184 return internal_io_service_add_interest_notification(service
, type_of_interest
,
3185 port
, &zreference
[0], sizeof(io_async_ref_t
), false, notification
);
3188 /* Routine io_service_add_interest_notification_64 */
3190 is_io_service_add_interest_notification_64(
3191 io_object_t service
,
3192 io_name_t type_of_interest
,
3193 mach_port_t wake_port
,
3194 io_async_ref64_t reference
,
3195 mach_msg_type_number_t referenceCnt
,
3196 io_object_t
*notification
)
3198 io_async_ref64_t zreference
;
3200 if (referenceCnt
> ASYNC_REF64_COUNT
) {
3201 return kIOReturnBadArgument
;
3203 bcopy(&reference
[0], &zreference
[0], referenceCnt
* sizeof(zreference
[0]));
3204 bzero(&zreference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(zreference
[0]));
3206 return internal_io_service_add_interest_notification(service
, type_of_interest
,
3207 wake_port
, &zreference
[0], sizeof(io_async_ref64_t
), true, notification
);
3211 /* Routine io_service_acknowledge_notification */
3213 is_io_service_acknowledge_notification(
3214 io_object_t _service
,
3215 natural_t notify_ref
,
3216 natural_t response
)
3218 CHECK( IOService
, _service
, service
);
3220 return service
->acknowledgeNotification((IONotificationRef
)(uintptr_t) notify_ref
,
3221 (IOOptionBits
) response
);
3224 /* Routine io_connect_get_semaphore */
3226 is_io_connect_get_notification_semaphore(
3227 io_connect_t connection
,
3228 natural_t notification_type
,
3229 semaphore_t
*semaphore
)
3232 CHECK( IOUserClient
, connection
, client
);
3234 IOStatisticsClientCall();
3235 IORWLockWrite(client
->lock
);
3236 ret
= client
->getNotificationSemaphore((UInt32
) notification_type
,
3238 IORWLockUnlock(client
->lock
);
3243 /* Routine io_registry_get_root_entry */
3245 is_io_registry_get_root_entry(
3246 mach_port_t master_port
,
3249 IORegistryEntry
* entry
;
3251 if (master_port
!= master_device_port
) {
3252 return kIOReturnNotPrivileged
;
3255 entry
= IORegistryEntry::getRegistryRoot();
3261 return kIOReturnSuccess
;
3264 /* Routine io_registry_create_iterator */
3266 is_io_registry_create_iterator(
3267 mach_port_t master_port
,
3270 io_object_t
*iterator
)
3272 if (master_port
!= master_device_port
) {
3273 return kIOReturnNotPrivileged
;
3276 *iterator
= IOUserIterator::withIterator(
3277 IORegistryIterator::iterateOver(
3278 IORegistryEntry::getPlane( plane
), options
));
3280 return *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
;
3283 /* Routine io_registry_entry_create_iterator */
3285 is_io_registry_entry_create_iterator(
3286 io_object_t registry_entry
,
3289 io_object_t
*iterator
)
3291 CHECK( IORegistryEntry
, registry_entry
, entry
);
3293 *iterator
= IOUserIterator::withIterator(
3294 IORegistryIterator::iterateOver( entry
,
3295 IORegistryEntry::getPlane( plane
), options
));
3297 return *iterator
? kIOReturnSuccess
: kIOReturnBadArgument
;
3300 /* Routine io_registry_iterator_enter */
3302 is_io_registry_iterator_enter_entry(
3303 io_object_t iterator
)
3305 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
3307 IOLockLock(oIter
->lock
);
3309 IOLockUnlock(oIter
->lock
);
3311 return kIOReturnSuccess
;
3314 /* Routine io_registry_iterator_exit */
3316 is_io_registry_iterator_exit_entry(
3317 io_object_t iterator
)
3321 CHECKLOCKED( IORegistryIterator
, iterator
, iter
);
3323 IOLockLock(oIter
->lock
);
3324 didIt
= iter
->exitEntry();
3325 IOLockUnlock(oIter
->lock
);
3327 return didIt
? kIOReturnSuccess
: kIOReturnNoDevice
;
3330 /* Routine io_registry_entry_from_path */
3332 is_io_registry_entry_from_path(
3333 mach_port_t master_port
,
3335 io_object_t
*registry_entry
)
3337 IORegistryEntry
* entry
;
3339 if (master_port
!= master_device_port
) {
3340 return kIOReturnNotPrivileged
;
3343 entry
= IORegistryEntry::fromPath( path
);
3345 if (!entry
&& IOTaskRegistryCompatibility(current_task())) {
3346 OSDictionary
* matching
;
3347 const OSObject
* objects
[2] = { kOSBooleanTrue
, NULL
};
3348 const OSSymbol
* keys
[2] = { gIOCompatibilityMatchKey
, gIOPathMatchKey
};
3350 objects
[1] = OSString::withCStringNoCopy(path
);
3351 matching
= OSDictionary::withObjects(objects
, keys
, 2, 2);
3353 entry
= IOService::copyMatchingService(matching
);
3355 OSSafeReleaseNULL(matching
);
3356 OSSafeReleaseNULL(objects
[1]);
3359 *registry_entry
= entry
;
3361 return kIOReturnSuccess
;
3365 /* Routine io_registry_entry_from_path */
3367 is_io_registry_entry_from_path_ool(
3368 mach_port_t master_port
,
3369 io_string_inband_t path
,
3370 io_buf_ptr_t path_ool
,
3371 mach_msg_type_number_t path_oolCnt
,
3372 kern_return_t
*result
,
3373 io_object_t
*registry_entry
)
3375 IORegistryEntry
* entry
;
3376 vm_map_offset_t map_data
;
3381 if (master_port
!= master_device_port
) {
3382 return kIOReturnNotPrivileged
;
3387 res
= err
= KERN_SUCCESS
;
3392 return kIOReturnBadArgument
;
3394 if (path_oolCnt
> (sizeof(io_struct_inband_t
) * 1024)) {
3395 return kIOReturnMessageTooLarge
;
3398 err
= vm_map_copyout(kernel_map
, &map_data
, (vm_map_copy_t
) path_ool
);
3399 if (KERN_SUCCESS
== err
) {
3400 // must return success to mig after vm_map_copyout() succeeds, so result is actual
3401 cpath
= CAST_DOWN(const char *, map_data
);
3402 if (cpath
[path_oolCnt
- 1]) {
3403 res
= kIOReturnBadArgument
;
3408 if ((KERN_SUCCESS
== err
) && (KERN_SUCCESS
== res
)) {
3409 entry
= IORegistryEntry::fromPath(cpath
);
3410 res
= entry
? kIOReturnSuccess
: kIOReturnNotFound
;
3414 vm_deallocate(kernel_map
, map_data
, path_oolCnt
);
3417 if (KERN_SUCCESS
!= err
) {
3420 *registry_entry
= entry
;
3427 /* Routine io_registry_entry_in_plane */
3429 is_io_registry_entry_in_plane(
3430 io_object_t registry_entry
,
3432 boolean_t
*inPlane
)
3434 CHECK( IORegistryEntry
, registry_entry
, entry
);
3436 *inPlane
= entry
->inPlane( IORegistryEntry::getPlane( plane
));
3438 return kIOReturnSuccess
;
3442 /* Routine io_registry_entry_get_path */
3444 is_io_registry_entry_get_path(
3445 io_object_t registry_entry
,
3450 CHECK( IORegistryEntry
, registry_entry
, entry
);
3452 length
= sizeof(io_string_t
);
3453 if (entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane
))) {
3454 return kIOReturnSuccess
;
3456 return kIOReturnBadArgument
;
3460 /* Routine io_registry_entry_get_path */
3462 is_io_registry_entry_get_path_ool(
3463 io_object_t registry_entry
,
3465 io_string_inband_t path
,
3466 io_buf_ptr_t
*path_ool
,
3467 mach_msg_type_number_t
*path_oolCnt
)
3469 enum { kMaxPath
= 16384 };
3474 CHECK( IORegistryEntry
, registry_entry
, entry
);
3478 length
= sizeof(io_string_inband_t
);
3479 if (entry
->getPath(path
, &length
, IORegistryEntry::getPlane(plane
))) {
3480 err
= kIOReturnSuccess
;
3483 buf
= IONew(char, length
);
3485 err
= kIOReturnNoMemory
;
3486 } else if (!entry
->getPath(buf
, &length
, IORegistryEntry::getPlane(plane
))) {
3487 err
= kIOReturnError
;
3489 *path_oolCnt
= length
;
3490 err
= copyoutkdata(buf
, length
, path_ool
);
3493 IODelete(buf
, char, kMaxPath
);
3501 /* Routine io_registry_entry_get_name */
3503 is_io_registry_entry_get_name(
3504 io_object_t registry_entry
,
3507 CHECK( IORegistryEntry
, registry_entry
, entry
);
3509 strncpy( name
, entry
->getName(), sizeof(io_name_t
));
3511 return kIOReturnSuccess
;
3514 /* Routine io_registry_entry_get_name_in_plane */
3516 is_io_registry_entry_get_name_in_plane(
3517 io_object_t registry_entry
,
3518 io_name_t planeName
,
3521 const IORegistryPlane
* plane
;
3522 CHECK( IORegistryEntry
, registry_entry
, entry
);
3525 plane
= IORegistryEntry::getPlane( planeName
);
3530 strncpy( name
, entry
->getName( plane
), sizeof(io_name_t
));
3532 return kIOReturnSuccess
;
3535 /* Routine io_registry_entry_get_location_in_plane */
3537 is_io_registry_entry_get_location_in_plane(
3538 io_object_t registry_entry
,
3539 io_name_t planeName
,
3540 io_name_t location
)
3542 const IORegistryPlane
* plane
;
3543 CHECK( IORegistryEntry
, registry_entry
, entry
);
3546 plane
= IORegistryEntry::getPlane( planeName
);
3551 const char * cstr
= entry
->getLocation( plane
);
3554 strncpy( location
, cstr
, sizeof(io_name_t
));
3555 return kIOReturnSuccess
;
3557 return kIOReturnNotFound
;
3561 /* Routine io_registry_entry_get_registry_entry_id */
3563 is_io_registry_entry_get_registry_entry_id(
3564 io_object_t registry_entry
,
3565 uint64_t *entry_id
)
3567 CHECK( IORegistryEntry
, registry_entry
, entry
);
3569 *entry_id
= entry
->getRegistryEntryID();
3571 return kIOReturnSuccess
;
3576 IOCopyPropertyCompatible(IORegistryEntry
* regEntry
, const char * name
)
3579 OSObject
* compatProps
;
3580 OSDictionary
* props
;
3582 obj
= regEntry
->copyProperty(name
);
3584 && IOTaskRegistryCompatibility(current_task())
3585 && (compatProps
= regEntry
->copyProperty(gIOCompatibilityPropertiesKey
))) {
3586 props
= OSDynamicCast(OSDictionary
, compatProps
);
3588 obj
= props
->getObject(name
);
3593 compatProps
->release();
3599 /* Routine io_registry_entry_get_property */
3601 is_io_registry_entry_get_property_bytes(
3602 io_object_t registry_entry
,
3603 io_name_t property_name
,
3604 io_struct_inband_t buf
,
3605 mach_msg_type_number_t
*dataCnt
)
3613 unsigned int len
= 0;
3614 const void * bytes
= NULL
;
3615 IOReturn ret
= kIOReturnSuccess
;
3617 CHECK( IORegistryEntry
, registry_entry
, entry
);
3620 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3621 return kIOReturnNotPermitted
;
3625 obj
= IOCopyPropertyCompatible(entry
, property_name
);
3627 return kIOReturnNoResources
;
3630 // One day OSData will be a common container base class
3632 if ((data
= OSDynamicCast( OSData
, obj
))) {
3633 len
= data
->getLength();
3634 bytes
= data
->getBytesNoCopy();
3635 if (!data
->isSerializable()) {
3638 } else if ((str
= OSDynamicCast( OSString
, obj
))) {
3639 len
= str
->getLength() + 1;
3640 bytes
= str
->getCStringNoCopy();
3641 } else if ((boo
= OSDynamicCast( OSBoolean
, obj
))) {
3642 len
= boo
->isTrue() ? sizeof("Yes") : sizeof("No");
3643 bytes
= boo
->isTrue() ? "Yes" : "No";
3644 } else if ((off
= OSDynamicCast( OSNumber
, obj
))) {
3645 offsetBytes
= off
->unsigned64BitValue();
3646 len
= off
->numberOfBytes();
3647 if (len
> sizeof(offsetBytes
)) {
3648 len
= sizeof(offsetBytes
);
3650 bytes
= &offsetBytes
;
3651 #ifdef __BIG_ENDIAN__
3652 bytes
= (const void *)
3653 (((UInt32
) bytes
) + (sizeof(UInt64
) - len
));
3656 ret
= kIOReturnBadArgument
;
3660 if (*dataCnt
< len
) {
3661 ret
= kIOReturnIPCError
;
3664 bcopy( bytes
, buf
, len
);
3673 /* Routine io_registry_entry_get_property */
3675 is_io_registry_entry_get_property(
3676 io_object_t registry_entry
,
3677 io_name_t property_name
,
3678 io_buf_ptr_t
*properties
,
3679 mach_msg_type_number_t
*propertiesCnt
)
3685 CHECK( IORegistryEntry
, registry_entry
, entry
);
3688 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3689 return kIOReturnNotPermitted
;
3693 obj
= IOCopyPropertyCompatible(entry
, property_name
);
3695 return kIOReturnNotFound
;
3698 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3701 return kIOReturnNoMemory
;
3704 if (obj
->serialize( s
)) {
3705 len
= s
->getLength();
3706 *propertiesCnt
= len
;
3707 err
= copyoutkdata( s
->text(), len
, properties
);
3709 err
= kIOReturnUnsupported
;
3718 /* Routine io_registry_entry_get_property_recursively */
3720 is_io_registry_entry_get_property_recursively(
3721 io_object_t registry_entry
,
3723 io_name_t property_name
,
3725 io_buf_ptr_t
*properties
,
3726 mach_msg_type_number_t
*propertiesCnt
)
3732 CHECK( IORegistryEntry
, registry_entry
, entry
);
3735 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3736 return kIOReturnNotPermitted
;
3740 obj
= entry
->copyProperty( property_name
,
3741 IORegistryEntry::getPlane( plane
), options
);
3743 return kIOReturnNotFound
;
3746 OSSerialize
* s
= OSSerialize::withCapacity(4096);
3749 return kIOReturnNoMemory
;
3752 if (obj
->serialize( s
)) {
3753 len
= s
->getLength();
3754 *propertiesCnt
= len
;
3755 err
= copyoutkdata( s
->text(), len
, properties
);
3757 err
= kIOReturnUnsupported
;
3766 /* Routine io_registry_entry_get_properties */
3768 is_io_registry_entry_get_properties(
3769 io_object_t registry_entry
,
3770 io_buf_ptr_t
*properties
,
3771 mach_msg_type_number_t
*propertiesCnt
)
3773 return kIOReturnUnsupported
;
3778 struct GetPropertiesEditorRef
{
3780 IORegistryEntry
* entry
;
3781 OSCollection
* root
;
3784 static const OSMetaClassBase
*
3785 GetPropertiesEditor(void * reference
,
3787 OSCollection
* container
,
3788 const OSSymbol
* name
,
3789 const OSMetaClassBase
* value
)
3791 GetPropertiesEditorRef
* ref
= (typeof(ref
))reference
;
3794 ref
->root
= container
;
3796 if (ref
->root
== container
) {
3797 if (0 != mac_iokit_check_get_property(ref
->cred
, ref
->entry
, name
->getCStringNoCopy())) {
3807 #endif /* CONFIG_MACF */
3809 /* Routine io_registry_entry_get_properties_bin_buf */
3811 is_io_registry_entry_get_properties_bin_buf(
3812 io_object_t registry_entry
,
3813 mach_vm_address_t buf
,
3814 mach_vm_size_t
*bufsize
,
3815 io_buf_ptr_t
*properties
,
3816 mach_msg_type_number_t
*propertiesCnt
)
3818 kern_return_t err
= kIOReturnSuccess
;
3820 OSObject
* compatProperties
;
3822 OSSerialize::Editor editor
= NULL
;
3823 void * editRef
= NULL
;
3825 CHECK(IORegistryEntry
, registry_entry
, entry
);
3828 GetPropertiesEditorRef ref
;
3829 if (mac_iokit_check_filter_properties(kauth_cred_get(), entry
)) {
3830 editor
= &GetPropertiesEditor
;
3832 ref
.cred
= kauth_cred_get();
3838 s
= OSSerialize::binaryWithCapacity(4096, editor
, editRef
);
3840 return kIOReturnNoMemory
;
3843 if (IOTaskRegistryCompatibility(current_task())
3844 && (compatProperties
= entry
->copyProperty(gIOCompatibilityPropertiesKey
))) {
3845 OSDictionary
* dict
;
3847 dict
= entry
->dictionaryWithProperties();
3849 err
= kIOReturnNoMemory
;
3851 dict
->removeObject(gIOCompatibilityPropertiesKey
);
3852 dict
->merge(OSDynamicCast(OSDictionary
, compatProperties
));
3853 if (!dict
->serialize(s
)) {
3854 err
= kIOReturnUnsupported
;
3858 compatProperties
->release();
3859 } else if (!entry
->serializeProperties(s
)) {
3860 err
= kIOReturnUnsupported
;
3863 if (kIOReturnSuccess
== err
) {
3864 len
= s
->getLength();
3865 if (buf
&& bufsize
&& len
<= *bufsize
) {
3868 *properties
= nullptr;
3869 if (copyout(s
->text(), buf
, len
)) {
3870 err
= kIOReturnVMError
;
3872 err
= kIOReturnSuccess
;
3878 *propertiesCnt
= len
;
3879 err
= copyoutkdata( s
->text(), len
, properties
);
3887 /* Routine io_registry_entry_get_properties_bin */
3889 is_io_registry_entry_get_properties_bin(
3890 io_object_t registry_entry
,
3891 io_buf_ptr_t
*properties
,
3892 mach_msg_type_number_t
*propertiesCnt
)
3894 return is_io_registry_entry_get_properties_bin_buf(registry_entry
,
3895 0, NULL
, properties
, propertiesCnt
);
3898 /* Routine io_registry_entry_get_property_bin_buf */
3900 is_io_registry_entry_get_property_bin_buf(
3901 io_object_t registry_entry
,
3903 io_name_t property_name
,
3905 mach_vm_address_t buf
,
3906 mach_vm_size_t
*bufsize
,
3907 io_buf_ptr_t
*properties
,
3908 mach_msg_type_number_t
*propertiesCnt
)
3913 const OSSymbol
* sym
;
3915 CHECK( IORegistryEntry
, registry_entry
, entry
);
3918 if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry
, property_name
)) {
3919 return kIOReturnNotPermitted
;
3923 sym
= OSSymbol::withCString(property_name
);
3925 return kIOReturnNoMemory
;
3928 if (gIORegistryEntryPropertyKeysKey
== sym
) {
3929 obj
= entry
->copyPropertyKeys();
3931 if ((kIORegistryIterateRecursively
& options
) && plane
[0]) {
3932 if (!IOTaskRegistryCompatibility(current_task())) {
3933 obj
= entry
->copyProperty(property_name
,
3934 IORegistryEntry::getPlane(plane
), options
);
3936 obj
= IOCopyPropertyCompatible(entry
, property_name
);
3937 if ((NULL
== obj
) && plane
&& (options
& kIORegistryIterateRecursively
)) {
3938 IORegistryIterator
* iter
;
3939 iter
= IORegistryIterator::iterateOver(entry
, IORegistryEntry::getPlane(plane
), options
);
3941 while ((NULL
== obj
) && (entry
= iter
->getNextObject())) {
3942 obj
= IOCopyPropertyCompatible(entry
, property_name
);
3949 obj
= IOCopyPropertyCompatible(entry
, property_name
);
3951 if (obj
&& gIORemoveOnReadProperties
->containsObject(sym
)) {
3952 entry
->removeProperty(sym
);
3958 return kIOReturnNotFound
;
3961 OSSerialize
* s
= OSSerialize::binaryWithCapacity(4096);
3964 return kIOReturnNoMemory
;
3967 if (obj
->serialize( s
)) {
3968 len
= s
->getLength();
3969 if (buf
&& bufsize
&& len
<= *bufsize
) {
3972 *properties
= nullptr;
3973 if (copyout(s
->text(), buf
, len
)) {
3974 err
= kIOReturnVMError
;
3976 err
= kIOReturnSuccess
;
3982 *propertiesCnt
= len
;
3983 err
= copyoutkdata( s
->text(), len
, properties
);
3986 err
= kIOReturnUnsupported
;
3995 /* Routine io_registry_entry_get_property_bin */
3997 is_io_registry_entry_get_property_bin(
3998 io_object_t registry_entry
,
4000 io_name_t property_name
,
4002 io_buf_ptr_t
*properties
,
4003 mach_msg_type_number_t
*propertiesCnt
)
4005 return is_io_registry_entry_get_property_bin_buf(registry_entry
, plane
,
4006 property_name
, options
, 0, NULL
, properties
, propertiesCnt
);
4010 /* Routine io_registry_entry_set_properties */
4012 is_io_registry_entry_set_properties
4014 io_object_t registry_entry
,
4015 io_buf_ptr_t properties
,
4016 mach_msg_type_number_t propertiesCnt
,
4017 kern_return_t
* result
)
4023 vm_map_offset_t map_data
;
4025 CHECK( IORegistryEntry
, registry_entry
, entry
);
4027 if (propertiesCnt
> sizeof(io_struct_inband_t
) * 1024) {
4028 return kIOReturnMessageTooLarge
;
4031 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
4032 data
= CAST_DOWN(vm_offset_t
, map_data
);
4034 if (KERN_SUCCESS
== err
) {
4035 FAKE_STACK_FRAME(entry
->getMetaClass());
4037 // must return success after vm_map_copyout() succeeds
4038 obj
= OSUnserializeXML((const char *) data
, propertiesCnt
);
4039 vm_deallocate( kernel_map
, data
, propertiesCnt
);
4042 res
= kIOReturnBadArgument
;
4045 else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
4046 registry_entry
, obj
)) {
4047 res
= kIOReturnNotPermitted
;
4051 res
= entry
->setProperties( obj
);
4058 FAKE_STACK_FRAME_END();
4067 /* Routine io_registry_entry_get_child_iterator */
4069 is_io_registry_entry_get_child_iterator(
4070 io_object_t registry_entry
,
4072 io_object_t
*iterator
)
4074 CHECK( IORegistryEntry
, registry_entry
, entry
);
4076 *iterator
= IOUserIterator::withIterator(entry
->getChildIterator(
4077 IORegistryEntry::getPlane( plane
)));
4079 return kIOReturnSuccess
;
4082 /* Routine io_registry_entry_get_parent_iterator */
4084 is_io_registry_entry_get_parent_iterator(
4085 io_object_t registry_entry
,
4087 io_object_t
*iterator
)
4089 CHECK( IORegistryEntry
, registry_entry
, entry
);
4091 *iterator
= IOUserIterator::withIterator(entry
->getParentIterator(
4092 IORegistryEntry::getPlane( plane
)));
4094 return kIOReturnSuccess
;
4097 /* Routine io_service_get_busy_state */
4099 is_io_service_get_busy_state(
4100 io_object_t _service
,
4101 uint32_t *busyState
)
4103 CHECK( IOService
, _service
, service
);
4105 *busyState
= service
->getBusyState();
4107 return kIOReturnSuccess
;
4110 /* Routine io_service_get_state */
4112 is_io_service_get_state(
4113 io_object_t _service
,
4115 uint32_t *busy_state
,
4116 uint64_t *accumulated_busy_time
)
4118 CHECK( IOService
, _service
, service
);
4120 *state
= service
->getState();
4121 *busy_state
= service
->getBusyState();
4122 *accumulated_busy_time
= service
->getAccumulatedBusyTime();
4124 return kIOReturnSuccess
;
4127 /* Routine io_service_wait_quiet */
4129 is_io_service_wait_quiet(
4130 io_object_t _service
,
4131 mach_timespec_t wait_time
)
4135 CHECK( IOService
, _service
, service
);
4137 timeoutNS
= wait_time
.tv_sec
;
4138 timeoutNS
*= kSecondScale
;
4139 timeoutNS
+= wait_time
.tv_nsec
;
4141 return service
->waitQuiet(timeoutNS
);
4144 /* Routine io_service_request_probe */
4146 is_io_service_request_probe(
4147 io_object_t _service
,
4150 CHECK( IOService
, _service
, service
);
4152 return service
->requestProbe( options
);
4155 /* Routine io_service_get_authorization_id */
4157 is_io_service_get_authorization_id(
4158 io_object_t _service
,
4159 uint64_t *authorization_id
)
4163 CHECK( IOService
, _service
, service
);
4165 kr
= IOUserClient::clientHasPrivilege((void *) current_task(),
4166 kIOClientPrivilegeAdministrator
);
4167 if (kIOReturnSuccess
!= kr
) {
4171 *authorization_id
= service
->getAuthorizationID();
4176 /* Routine io_service_set_authorization_id */
4178 is_io_service_set_authorization_id(
4179 io_object_t _service
,
4180 uint64_t authorization_id
)
4182 CHECK( IOService
, _service
, service
);
4184 return service
->setAuthorizationID( authorization_id
);
4187 /* Routine io_service_open_ndr */
4189 is_io_service_open_extended(
4190 io_object_t _service
,
4192 uint32_t connect_type
,
4194 io_buf_ptr_t properties
,
4195 mach_msg_type_number_t propertiesCnt
,
4196 kern_return_t
* result
,
4197 io_object_t
*connection
)
4199 IOUserClient
* client
= NULL
;
4200 kern_return_t err
= KERN_SUCCESS
;
4201 IOReturn res
= kIOReturnSuccess
;
4202 OSDictionary
* propertiesDict
= NULL
;
4204 bool disallowAccess
;
4206 CHECK( IOService
, _service
, service
);
4209 return kIOReturnBadArgument
;
4211 assert(owningTask
== current_task());
4212 if (owningTask
!= current_task()) {
4213 return kIOReturnBadArgument
;
4218 return kIOReturnUnsupported
;
4224 vm_map_offset_t map_data
;
4226 if (propertiesCnt
> sizeof(io_struct_inband_t
)) {
4227 return kIOReturnMessageTooLarge
;
4230 err
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties
);
4232 data
= CAST_DOWN(vm_offset_t
, map_data
);
4233 if (KERN_SUCCESS
== err
) {
4234 // must return success after vm_map_copyout() succeeds
4235 obj
= OSUnserializeXML((const char *) data
, propertiesCnt
);
4236 vm_deallocate( kernel_map
, data
, propertiesCnt
);
4237 propertiesDict
= OSDynamicCast(OSDictionary
, obj
);
4238 if (!propertiesDict
) {
4239 res
= kIOReturnBadArgument
;
4245 if (kIOReturnSuccess
!= res
) {
4250 crossEndian
= (ndr
.int_rep
!= NDR_record
.int_rep
);
4252 if (!propertiesDict
) {
4253 propertiesDict
= OSDictionary::withCapacity(4);
4255 OSData
* data
= OSData::withBytes(&ndr
, sizeof(ndr
));
4257 if (propertiesDict
) {
4258 propertiesDict
->setObject(kIOUserClientCrossEndianKey
, data
);
4264 res
= service
->newUserClient( owningTask
, (void *) owningTask
,
4265 connect_type
, propertiesDict
, &client
);
4267 if (propertiesDict
) {
4268 propertiesDict
->release();
4271 if (res
== kIOReturnSuccess
) {
4272 assert( OSDynamicCast(IOUserClient
, client
));
4273 if (!client
->reserved
) {
4274 if (!client
->reserve()) {
4275 client
->clientClose();
4276 OSSafeReleaseNULL(client
);
4277 res
= kIOReturnNoMemory
;
4282 if (res
== kIOReturnSuccess
) {
4283 client
->sharedInstance
= (NULL
!= client
->getProperty(kIOUserClientSharedInstanceKey
));
4284 if (client
->sharedInstance
) {
4285 IOLockLock(gIOUserClientOwnersLock
);
4287 if (!client
->lock
) {
4288 client
->lock
= IORWLockAlloc();
4289 client
->filterLock
= IOLockAlloc();
4291 client
->messageAppSuspended
= (NULL
!= client
->getProperty(kIOUserClientMessageAppSuspendedKey
));
4294 extern const OSSymbol
* gIOSurfaceIdentifier
;
4295 obj
= client
->getProperty(kIOUserClientDefaultLockingKey
);
4297 client
->defaultLocking
= (kOSBooleanFalse
!= client
->getProperty(kIOUserClientDefaultLockingKey
));
4299 const OSMetaClass
* meta
;
4301 meta
= client
->getMetaClass();
4302 kext
= meta
->getKext();
4303 if (!kext
|| !kext
->hasDependency(gIOSurfaceIdentifier
)) {
4304 client
->defaultLocking
= true;
4305 client
->setProperty(kIOUserClientDefaultLockingKey
, kOSBooleanTrue
);
4310 if (client
->sharedInstance
) {
4311 IOLockUnlock(gIOUserClientOwnersLock
);
4314 disallowAccess
= (crossEndian
4315 && (kOSBooleanTrue
!= service
->getProperty(kIOUserClientCrossEndianCompatibleKey
))
4316 && (kOSBooleanTrue
!= client
->getProperty(kIOUserClientCrossEndianCompatibleKey
)));
4317 if (disallowAccess
) {
4318 res
= kIOReturnUnsupported
;
4321 else if (0 != mac_iokit_check_open(kauth_cred_get(), client
, connect_type
)) {
4322 res
= kIOReturnNotPermitted
;
4326 if ((kIOReturnSuccess
== res
)
4327 && gIOUCFilterCallbacks
4328 && gIOUCFilterCallbacks
->io_filter_resolver
) {
4329 io_filter_policy_t filterPolicy
;
4330 filterPolicy
= client
->filterForTask(owningTask
, 0);
4331 if (!filterPolicy
) {
4332 res
= gIOUCFilterCallbacks
->io_filter_resolver(owningTask
, client
, connect_type
, &filterPolicy
);
4333 if (kIOReturnUnsupported
== res
) {
4334 res
= kIOReturnSuccess
;
4335 } else if (kIOReturnSuccess
== res
) {
4336 client
->filterForTask(owningTask
, filterPolicy
);
4341 if (kIOReturnSuccess
== res
) {
4342 res
= client
->registerOwner(owningTask
);
4345 if (kIOReturnSuccess
!= res
) {
4346 IOStatisticsClientCall();
4347 client
->clientClose();
4352 OSString
* creatorName
= IOCopyLogNameForPID(proc_selfpid());
4354 client
->setProperty(kIOUserClientCreatorKey
, creatorName
);
4355 creatorName
->release();
4357 client
->setTerminateDefer(service
, false);
4361 *connection
= client
;
4367 /* Routine io_service_close */
4369 is_io_service_close(
4370 io_object_t connection
)
4373 if ((mappings
= OSDynamicCast(OSSet
, connection
))) {
4374 return kIOReturnSuccess
;
4377 CHECK( IOUserClient
, connection
, client
);
4379 IOStatisticsClientCall();
4381 if (client
->sharedInstance
|| OSCompareAndSwap8(0, 1, &client
->closed
)) {
4382 IORWLockWrite(client
->lock
);
4383 client
->clientClose();
4384 IORWLockUnlock(client
->lock
);
4386 IOLog("ignored is_io_service_close(0x%qx,%s)\n",
4387 client
->getRegistryEntryID(), client
->getName());
4390 return kIOReturnSuccess
;
4393 /* Routine io_connect_get_service */
4395 is_io_connect_get_service(
4396 io_object_t connection
,
4397 io_object_t
*service
)
4399 IOService
* theService
;
4401 CHECK( IOUserClient
, connection
, client
);
4403 theService
= client
->getService();
4405 theService
->retain();
4408 *service
= theService
;
4410 return theService
? kIOReturnSuccess
: kIOReturnUnsupported
;
4413 /* Routine io_connect_set_notification_port */
4415 is_io_connect_set_notification_port(
4416 io_object_t connection
,
4417 uint32_t notification_type
,
4422 CHECK( IOUserClient
, connection
, client
);
4424 IOStatisticsClientCall();
4425 IORWLockWrite(client
->lock
);
4426 ret
= client
->registerNotificationPort( port
, notification_type
,
4427 (io_user_reference_t
) reference
);
4428 IORWLockUnlock(client
->lock
);
4432 /* Routine io_connect_set_notification_port */
4434 is_io_connect_set_notification_port_64(
4435 io_object_t connection
,
4436 uint32_t notification_type
,
4438 io_user_reference_t reference
)
4441 CHECK( IOUserClient
, connection
, client
);
4443 IOStatisticsClientCall();
4444 IORWLockWrite(client
->lock
);
4445 ret
= client
->registerNotificationPort( port
, notification_type
,
4447 IORWLockUnlock(client
->lock
);
4451 /* Routine io_connect_map_memory_into_task */
4453 is_io_connect_map_memory_into_task
4455 io_connect_t connection
,
4456 uint32_t memory_type
,
4458 mach_vm_address_t
*address
,
4459 mach_vm_size_t
*size
,
4466 CHECK( IOUserClient
, connection
, client
);
4469 return kIOReturnBadArgument
;
4472 IOStatisticsClientCall();
4473 if (client
->defaultLocking
) {
4474 IORWLockWrite(client
->lock
);
4476 map
= client
->mapClientMemory64( memory_type
, into_task
, flags
, *address
);
4477 if (client
->defaultLocking
) {
4478 IORWLockUnlock(client
->lock
);
4482 *address
= map
->getAddress();
4484 *size
= map
->getSize();
4487 if (client
->sharedInstance
4488 || (into_task
!= current_task())) {
4489 // push a name out to the task owning the map,
4490 // so we can clean up maps
4491 mach_port_name_t name __unused
=
4492 IOMachPort::makeSendRightForTask(
4493 into_task
, map
, IKOT_IOKIT_OBJECT
);
4496 // keep it with the user client
4497 IOLockLock( gIOObjectPortLock
);
4498 if (NULL
== client
->mappings
) {
4499 client
->mappings
= OSSet::withCapacity(2);
4501 if (client
->mappings
) {
4502 client
->mappings
->setObject( map
);
4504 IOLockUnlock( gIOObjectPortLock
);
4507 err
= kIOReturnSuccess
;
4509 err
= kIOReturnBadArgument
;
4515 /* Routine is_io_connect_map_memory */
4517 is_io_connect_map_memory(
4518 io_object_t connect
,
4526 mach_vm_address_t address
;
4527 mach_vm_size_t size
;
4529 address
= SCALAR64(*mapAddr
);
4530 size
= SCALAR64(*mapSize
);
4532 err
= is_io_connect_map_memory_into_task(connect
, type
, task
, &address
, &size
, flags
);
4534 *mapAddr
= SCALAR32(address
);
4535 *mapSize
= SCALAR32(size
);
4542 IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor
* mem
)
4545 IOMemoryMap
* map
= NULL
;
4547 IOLockLock(gIOObjectPortLock
);
4549 iter
= OSCollectionIterator::withCollection(mappings
);
4551 while ((map
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject()))) {
4552 if (mem
== map
->getMemoryDescriptor()) {
4554 mappings
->removeObject(map
);
4561 IOLockUnlock(gIOObjectPortLock
);
4567 /* Routine io_connect_unmap_memory_from_task */
4569 is_io_connect_unmap_memory_from_task
4571 io_connect_t connection
,
4572 uint32_t memory_type
,
4574 mach_vm_address_t address
)
4577 IOOptionBits options
= 0;
4578 IOMemoryDescriptor
* memory
= NULL
;
4581 CHECK( IOUserClient
, connection
, client
);
4584 return kIOReturnBadArgument
;
4587 IOStatisticsClientCall();
4588 if (client
->defaultLocking
) {
4589 IORWLockWrite(client
->lock
);
4591 err
= client
->clientMemoryForType((UInt32
) memory_type
, &options
, &memory
);
4592 if (client
->defaultLocking
) {
4593 IORWLockUnlock(client
->lock
);
4596 if (memory
&& (kIOReturnSuccess
== err
)) {
4597 options
= (options
& ~kIOMapUserOptionsMask
)
4598 | kIOMapAnywhere
| kIOMapReference
;
4600 map
= memory
->createMappingInTask( from_task
, address
, options
);
4603 IOLockLock( gIOObjectPortLock
);
4604 if (client
->mappings
) {
4605 client
->mappings
->removeObject( map
);
4607 IOLockUnlock( gIOObjectPortLock
);
4609 mach_port_name_t name
= 0;
4610 bool is_shared_instance_or_from_current_task
= from_task
!= current_task() || client
->sharedInstance
;
4611 if (is_shared_instance_or_from_current_task
) {
4612 name
= IOMachPort::makeSendRightForTask( from_task
, map
, IKOT_IOKIT_OBJECT
);
4617 map
->userClientUnmap();
4618 err
= iokit_mod_send_right( from_task
, name
, -2 );
4619 err
= kIOReturnSuccess
;
4621 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT
);
4623 if (!is_shared_instance_or_from_current_task
) {
4627 err
= kIOReturnBadArgument
;
4635 is_io_connect_unmap_memory(
4636 io_object_t connect
,
4642 mach_vm_address_t address
;
4644 address
= SCALAR64(mapAddr
);
4646 err
= is_io_connect_unmap_memory_from_task(connect
, type
, task
, mapAddr
);
4652 /* Routine io_connect_add_client */
4654 is_io_connect_add_client(
4655 io_object_t connection
,
4656 io_object_t connect_to
)
4658 CHECK( IOUserClient
, connection
, client
);
4659 CHECK( IOUserClient
, connect_to
, to
);
4663 IOStatisticsClientCall();
4664 if (client
->defaultLocking
) {
4665 IORWLockWrite(client
->lock
);
4667 ret
= client
->connectClient( to
);
4668 if (client
->defaultLocking
) {
4669 IORWLockUnlock(client
->lock
);
4675 /* Routine io_connect_set_properties */
4677 is_io_connect_set_properties(
4678 io_object_t connection
,
4679 io_buf_ptr_t properties
,
4680 mach_msg_type_number_t propertiesCnt
,
4681 kern_return_t
* result
)
4683 return is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result
);
4686 /* Routine io_user_client_method */
4688 is_io_connect_method_var_output
4690 io_connect_t connection
,
4692 io_scalar_inband64_t scalar_input
,
4693 mach_msg_type_number_t scalar_inputCnt
,
4694 io_struct_inband_t inband_input
,
4695 mach_msg_type_number_t inband_inputCnt
,
4696 mach_vm_address_t ool_input
,
4697 mach_vm_size_t ool_input_size
,
4698 io_struct_inband_t inband_output
,
4699 mach_msg_type_number_t
*inband_outputCnt
,
4700 io_scalar_inband64_t scalar_output
,
4701 mach_msg_type_number_t
*scalar_outputCnt
,
4702 io_buf_ptr_t
*var_output
,
4703 mach_msg_type_number_t
*var_outputCnt
4706 CHECK( IOUserClient
, connection
, client
);
4708 IOExternalMethodArguments args
;
4710 IOMemoryDescriptor
* inputMD
= NULL
;
4711 OSObject
* structureVariableOutputData
= NULL
;
4713 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4714 args
.__reservedA
= 0;
4715 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4717 args
.selector
= selector
;
4719 args
.asyncWakePort
= MACH_PORT_NULL
;
4720 args
.asyncReference
= NULL
;
4721 args
.asyncReferenceCount
= 0;
4722 args
.structureVariableOutputData
= &structureVariableOutputData
;
4724 args
.scalarInput
= scalar_input
;
4725 args
.scalarInputCount
= scalar_inputCnt
;
4726 args
.structureInput
= inband_input
;
4727 args
.structureInputSize
= inband_inputCnt
;
4729 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) {
4730 return kIOReturnIPCError
;
4734 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4735 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4739 args
.structureInputDescriptor
= inputMD
;
4741 args
.scalarOutput
= scalar_output
;
4742 args
.scalarOutputCount
= *scalar_outputCnt
;
4743 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4744 args
.structureOutput
= inband_output
;
4745 args
.structureOutputSize
= *inband_outputCnt
;
4746 args
.structureOutputDescriptor
= NULL
;
4747 args
.structureOutputDescriptorSize
= 0;
4749 IOStatisticsClientCall();
4750 ret
= kIOReturnSuccess
;
4752 io_filter_policy_t filterPolicy
= client
->filterForTask(current_task(), 0);
4753 if (filterPolicy
&& gIOUCFilterCallbacks
->io_filter_applier
) {
4754 ret
= gIOUCFilterCallbacks
->io_filter_applier(filterPolicy
, io_filter_type_external_method
, selector
);
4756 if (kIOReturnSuccess
== ret
) {
4757 if (client
->defaultLocking
) {
4758 IORWLockRead(client
->lock
);
4760 ret
= client
->externalMethod( selector
, &args
);
4761 if (client
->defaultLocking
) {
4762 IORWLockUnlock(client
->lock
);
4766 *scalar_outputCnt
= args
.scalarOutputCount
;
4767 *inband_outputCnt
= args
.structureOutputSize
;
4769 if (var_outputCnt
&& var_output
&& (kIOReturnSuccess
== ret
)) {
4770 OSSerialize
* serialize
;
4774 if ((serialize
= OSDynamicCast(OSSerialize
, structureVariableOutputData
))) {
4775 len
= serialize
->getLength();
4776 *var_outputCnt
= len
;
4777 ret
= copyoutkdata(serialize
->text(), len
, var_output
);
4778 } else if ((data
= OSDynamicCast(OSData
, structureVariableOutputData
))) {
4779 len
= data
->getLength();
4780 *var_outputCnt
= len
;
4781 ret
= copyoutkdata(data
->getBytesNoCopy(), len
, var_output
);
4783 ret
= kIOReturnUnderrun
;
4790 if (structureVariableOutputData
) {
4791 structureVariableOutputData
->release();
4797 /* Routine io_user_client_method */
4799 is_io_connect_method
4801 io_connect_t connection
,
4803 io_scalar_inband64_t scalar_input
,
4804 mach_msg_type_number_t scalar_inputCnt
,
4805 io_struct_inband_t inband_input
,
4806 mach_msg_type_number_t inband_inputCnt
,
4807 mach_vm_address_t ool_input
,
4808 mach_vm_size_t ool_input_size
,
4809 io_struct_inband_t inband_output
,
4810 mach_msg_type_number_t
*inband_outputCnt
,
4811 io_scalar_inband64_t scalar_output
,
4812 mach_msg_type_number_t
*scalar_outputCnt
,
4813 mach_vm_address_t ool_output
,
4814 mach_vm_size_t
*ool_output_size
4817 CHECK( IOUserClient
, connection
, client
);
4819 IOExternalMethodArguments args
;
4821 IOMemoryDescriptor
* inputMD
= NULL
;
4822 IOMemoryDescriptor
* outputMD
= NULL
;
4824 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4825 args
.__reservedA
= 0;
4826 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4828 args
.selector
= selector
;
4830 args
.asyncWakePort
= MACH_PORT_NULL
;
4831 args
.asyncReference
= NULL
;
4832 args
.asyncReferenceCount
= 0;
4833 args
.structureVariableOutputData
= NULL
;
4835 args
.scalarInput
= scalar_input
;
4836 args
.scalarInputCount
= scalar_inputCnt
;
4837 args
.structureInput
= inband_input
;
4838 args
.structureInputSize
= inband_inputCnt
;
4840 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) {
4841 return kIOReturnIPCError
;
4844 if (*ool_output_size
<= sizeof(io_struct_inband_t
)) {
4845 return kIOReturnIPCError
;
4847 if (*ool_output_size
> UINT_MAX
) {
4848 return kIOReturnIPCError
;
4853 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4854 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4858 args
.structureInputDescriptor
= inputMD
;
4860 args
.scalarOutput
= scalar_output
;
4861 args
.scalarOutputCount
= *scalar_outputCnt
;
4862 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4863 args
.structureOutput
= inband_output
;
4864 args
.structureOutputSize
= *inband_outputCnt
;
4866 if (ool_output
&& ool_output_size
) {
4867 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
4868 kIODirectionIn
, current_task());
4871 args
.structureOutputDescriptor
= outputMD
;
4872 args
.structureOutputDescriptorSize
= ool_output_size
4873 ? ((typeof(args
.structureOutputDescriptorSize
)) * ool_output_size
)
4876 IOStatisticsClientCall();
4877 ret
= kIOReturnSuccess
;
4878 io_filter_policy_t filterPolicy
= client
->filterForTask(current_task(), 0);
4879 if (filterPolicy
&& gIOUCFilterCallbacks
->io_filter_applier
) {
4880 ret
= gIOUCFilterCallbacks
->io_filter_applier(filterPolicy
, io_filter_type_external_method
, selector
);
4882 if (kIOReturnSuccess
== ret
) {
4883 if (client
->defaultLocking
) {
4884 IORWLockRead(client
->lock
);
4886 ret
= client
->externalMethod( selector
, &args
);
4887 if (client
->defaultLocking
) {
4888 IORWLockUnlock(client
->lock
);
4892 *scalar_outputCnt
= args
.scalarOutputCount
;
4893 *inband_outputCnt
= args
.structureOutputSize
;
4894 *ool_output_size
= args
.structureOutputDescriptorSize
;
4900 outputMD
->release();
4906 /* Routine io_async_user_client_method */
4908 is_io_connect_async_method
4910 io_connect_t connection
,
4911 mach_port_t wake_port
,
4912 io_async_ref64_t reference
,
4913 mach_msg_type_number_t referenceCnt
,
4915 io_scalar_inband64_t scalar_input
,
4916 mach_msg_type_number_t scalar_inputCnt
,
4917 io_struct_inband_t inband_input
,
4918 mach_msg_type_number_t inband_inputCnt
,
4919 mach_vm_address_t ool_input
,
4920 mach_vm_size_t ool_input_size
,
4921 io_struct_inband_t inband_output
,
4922 mach_msg_type_number_t
*inband_outputCnt
,
4923 io_scalar_inband64_t scalar_output
,
4924 mach_msg_type_number_t
*scalar_outputCnt
,
4925 mach_vm_address_t ool_output
,
4926 mach_vm_size_t
* ool_output_size
4929 CHECK( IOUserClient
, connection
, client
);
4931 IOExternalMethodArguments args
;
4933 IOMemoryDescriptor
* inputMD
= NULL
;
4934 IOMemoryDescriptor
* outputMD
= NULL
;
4936 if (referenceCnt
< 1) {
4937 return kIOReturnBadArgument
;
4940 bzero(&args
.__reserved
[0], sizeof(args
.__reserved
));
4941 args
.__reservedA
= 0;
4942 args
.version
= kIOExternalMethodArgumentsCurrentVersion
;
4944 reference
[0] = (io_user_reference_t
) wake_port
;
4945 if (vm_map_is_64bit(get_task_map(current_task()))) {
4946 reference
[0] |= kIOUCAsync64Flag
;
4949 args
.selector
= selector
;
4951 args
.asyncWakePort
= wake_port
;
4952 args
.asyncReference
= reference
;
4953 args
.asyncReferenceCount
= referenceCnt
;
4955 args
.structureVariableOutputData
= NULL
;
4957 args
.scalarInput
= scalar_input
;
4958 args
.scalarInputCount
= scalar_inputCnt
;
4959 args
.structureInput
= inband_input
;
4960 args
.structureInputSize
= inband_inputCnt
;
4962 if (ool_input
&& (ool_input_size
<= sizeof(io_struct_inband_t
))) {
4963 return kIOReturnIPCError
;
4966 if (*ool_output_size
<= sizeof(io_struct_inband_t
)) {
4967 return kIOReturnIPCError
;
4969 if (*ool_output_size
> UINT_MAX
) {
4970 return kIOReturnIPCError
;
4975 inputMD
= IOMemoryDescriptor::withAddressRange(ool_input
, ool_input_size
,
4976 kIODirectionOut
| kIOMemoryMapCopyOnWrite
,
4980 args
.structureInputDescriptor
= inputMD
;
4982 args
.scalarOutput
= scalar_output
;
4983 args
.scalarOutputCount
= *scalar_outputCnt
;
4984 bzero(&scalar_output
[0], *scalar_outputCnt
* sizeof(scalar_output
[0]));
4985 args
.structureOutput
= inband_output
;
4986 args
.structureOutputSize
= *inband_outputCnt
;
4989 outputMD
= IOMemoryDescriptor::withAddressRange(ool_output
, *ool_output_size
,
4990 kIODirectionIn
, current_task());
4993 args
.structureOutputDescriptor
= outputMD
;
4994 args
.structureOutputDescriptorSize
= ((typeof(args
.structureOutputDescriptorSize
)) * ool_output_size
);
4996 IOStatisticsClientCall();
4997 ret
= kIOReturnSuccess
;
4998 io_filter_policy_t filterPolicy
= client
->filterForTask(current_task(), 0);
4999 if (filterPolicy
&& gIOUCFilterCallbacks
->io_filter_applier
) {
5000 ret
= gIOUCFilterCallbacks
->io_filter_applier(filterPolicy
, io_filter_type_external_async_method
, selector
);
5002 if (kIOReturnSuccess
== ret
) {
5003 if (client
->defaultLocking
) {
5004 IORWLockRead(client
->lock
);
5006 ret
= client
->externalMethod( selector
, &args
);
5007 if (client
->defaultLocking
) {
5008 IORWLockUnlock(client
->lock
);
5012 *scalar_outputCnt
= args
.scalarOutputCount
;
5013 *inband_outputCnt
= args
.structureOutputSize
;
5014 *ool_output_size
= args
.structureOutputDescriptorSize
;
5020 outputMD
->release();
5026 /* Routine io_connect_method_scalarI_scalarO */
5028 is_io_connect_method_scalarI_scalarO(
5029 io_object_t connect
,
5031 io_scalar_inband_t input
,
5032 mach_msg_type_number_t inputCount
,
5033 io_scalar_inband_t output
,
5034 mach_msg_type_number_t
* outputCount
)
5038 io_scalar_inband64_t _input
;
5039 io_scalar_inband64_t _output
;
5041 mach_msg_type_number_t struct_outputCnt
= 0;
5042 mach_vm_size_t ool_output_size
= 0;
5044 bzero(&_output
[0], sizeof(_output
));
5045 for (i
= 0; i
< inputCount
; i
++) {
5046 _input
[i
] = SCALAR64(input
[i
]);
5049 err
= is_io_connect_method(connect
, index
,
5053 NULL
, &struct_outputCnt
,
5054 _output
, outputCount
,
5055 0, &ool_output_size
);
5057 for (i
= 0; i
< *outputCount
; i
++) {
5058 output
[i
] = SCALAR32(_output
[i
]);
5065 shim_io_connect_method_scalarI_scalarO(
5066 IOExternalMethod
* method
,
5068 const io_user_scalar_t
* input
,
5069 mach_msg_type_number_t inputCount
,
5070 io_user_scalar_t
* output
,
5071 mach_msg_type_number_t
* outputCount
)
5074 io_scalar_inband_t _output
;
5076 err
= kIOReturnBadArgument
;
5078 bzero(&_output
[0], sizeof(_output
));
5080 if (inputCount
!= method
->count0
) {
5081 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5082 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5085 if (*outputCount
!= method
->count1
) {
5086 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
5087 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5091 func
= method
->func
;
5093 switch (inputCount
) {
5095 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5096 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]));
5099 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5100 ARG32(input
[3]), ARG32(input
[4]),
5104 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5106 &_output
[0], &_output
[1] );
5109 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5110 &_output
[0], &_output
[1], &_output
[2] );
5113 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
5114 &_output
[0], &_output
[1], &_output
[2],
5118 err
= (object
->*func
)( ARG32(input
[0]),
5119 &_output
[0], &_output
[1], &_output
[2],
5120 &_output
[3], &_output
[4] );
5123 err
= (object
->*func
)( &_output
[0], &_output
[1], &_output
[2],
5124 &_output
[3], &_output
[4], &_output
[5] );
5128 IOLog("%s: Bad method table\n", object
->getName());
5133 for (i
= 0; i
< *outputCount
; i
++) {
5134 output
[i
] = SCALAR32(_output
[i
]);
5140 /* Routine io_async_method_scalarI_scalarO */
5142 is_io_async_method_scalarI_scalarO(
5143 io_object_t connect
,
5144 mach_port_t wake_port
,
5145 io_async_ref_t reference
,
5146 mach_msg_type_number_t referenceCnt
,
5148 io_scalar_inband_t input
,
5149 mach_msg_type_number_t inputCount
,
5150 io_scalar_inband_t output
,
5151 mach_msg_type_number_t
* outputCount
)
5155 io_scalar_inband64_t _input
;
5156 io_scalar_inband64_t _output
;
5157 io_async_ref64_t _reference
;
5159 if (referenceCnt
> ASYNC_REF64_COUNT
) {
5160 return kIOReturnBadArgument
;
5162 bzero(&_output
[0], sizeof(_output
));
5163 for (i
= 0; i
< referenceCnt
; i
++) {
5164 _reference
[i
] = REF64(reference
[i
]);
5166 bzero(&_reference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(_reference
[0]));
5168 mach_msg_type_number_t struct_outputCnt
= 0;
5169 mach_vm_size_t ool_output_size
= 0;
5171 for (i
= 0; i
< inputCount
; i
++) {
5172 _input
[i
] = SCALAR64(input
[i
]);
5175 err
= is_io_connect_async_method(connect
,
5176 wake_port
, _reference
, referenceCnt
,
5181 NULL
, &struct_outputCnt
,
5182 _output
, outputCount
,
5183 0, &ool_output_size
);
5185 for (i
= 0; i
< *outputCount
; i
++) {
5186 output
[i
] = SCALAR32(_output
[i
]);
5191 /* Routine io_async_method_scalarI_structureO */
5193 is_io_async_method_scalarI_structureO(
5194 io_object_t connect
,
5195 mach_port_t wake_port
,
5196 io_async_ref_t reference
,
5197 mach_msg_type_number_t referenceCnt
,
5199 io_scalar_inband_t input
,
5200 mach_msg_type_number_t inputCount
,
5201 io_struct_inband_t output
,
5202 mach_msg_type_number_t
* outputCount
)
5205 io_scalar_inband64_t _input
;
5206 io_async_ref64_t _reference
;
5208 if (referenceCnt
> ASYNC_REF64_COUNT
) {
5209 return kIOReturnBadArgument
;
5211 for (i
= 0; i
< referenceCnt
; i
++) {
5212 _reference
[i
] = REF64(reference
[i
]);
5214 bzero(&_reference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(_reference
[0]));
5216 mach_msg_type_number_t scalar_outputCnt
= 0;
5217 mach_vm_size_t ool_output_size
= 0;
5219 for (i
= 0; i
< inputCount
; i
++) {
5220 _input
[i
] = SCALAR64(input
[i
]);
5223 return is_io_connect_async_method(connect
,
5224 wake_port
, _reference
, referenceCnt
,
5229 output
, outputCount
,
5230 NULL
, &scalar_outputCnt
,
5231 0, &ool_output_size
);
5234 /* Routine io_async_method_scalarI_structureI */
5236 is_io_async_method_scalarI_structureI(
5237 io_connect_t connect
,
5238 mach_port_t wake_port
,
5239 io_async_ref_t reference
,
5240 mach_msg_type_number_t referenceCnt
,
5242 io_scalar_inband_t input
,
5243 mach_msg_type_number_t inputCount
,
5244 io_struct_inband_t inputStruct
,
5245 mach_msg_type_number_t inputStructCount
)
5248 io_scalar_inband64_t _input
;
5249 io_async_ref64_t _reference
;
5251 if (referenceCnt
> ASYNC_REF64_COUNT
) {
5252 return kIOReturnBadArgument
;
5254 for (i
= 0; i
< referenceCnt
; i
++) {
5255 _reference
[i
] = REF64(reference
[i
]);
5257 bzero(&_reference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(_reference
[0]));
5259 mach_msg_type_number_t scalar_outputCnt
= 0;
5260 mach_msg_type_number_t inband_outputCnt
= 0;
5261 mach_vm_size_t ool_output_size
= 0;
5263 for (i
= 0; i
< inputCount
; i
++) {
5264 _input
[i
] = SCALAR64(input
[i
]);
5267 return is_io_connect_async_method(connect
,
5268 wake_port
, _reference
, referenceCnt
,
5271 inputStruct
, inputStructCount
,
5273 NULL
, &inband_outputCnt
,
5274 NULL
, &scalar_outputCnt
,
5275 0, &ool_output_size
);
5278 /* Routine io_async_method_structureI_structureO */
5280 is_io_async_method_structureI_structureO(
5281 io_object_t connect
,
5282 mach_port_t wake_port
,
5283 io_async_ref_t reference
,
5284 mach_msg_type_number_t referenceCnt
,
5286 io_struct_inband_t input
,
5287 mach_msg_type_number_t inputCount
,
5288 io_struct_inband_t output
,
5289 mach_msg_type_number_t
* outputCount
)
5292 mach_msg_type_number_t scalar_outputCnt
= 0;
5293 mach_vm_size_t ool_output_size
= 0;
5294 io_async_ref64_t _reference
;
5296 if (referenceCnt
> ASYNC_REF64_COUNT
) {
5297 return kIOReturnBadArgument
;
5299 for (i
= 0; i
< referenceCnt
; i
++) {
5300 _reference
[i
] = REF64(reference
[i
]);
5302 bzero(&_reference
[referenceCnt
], (ASYNC_REF64_COUNT
- referenceCnt
) * sizeof(_reference
[0]));
5304 return is_io_connect_async_method(connect
,
5305 wake_port
, _reference
, referenceCnt
,
5310 output
, outputCount
,
5311 NULL
, &scalar_outputCnt
,
5312 0, &ool_output_size
);
5317 shim_io_async_method_scalarI_scalarO(
5318 IOExternalAsyncMethod
* method
,
5320 mach_port_t asyncWakePort
,
5321 io_user_reference_t
* asyncReference
,
5322 uint32_t asyncReferenceCount
,
5323 const io_user_scalar_t
* input
,
5324 mach_msg_type_number_t inputCount
,
5325 io_user_scalar_t
* output
,
5326 mach_msg_type_number_t
* outputCount
)
5330 io_scalar_inband_t _output
;
5332 io_async_ref_t reference
;
5334 bzero(&_output
[0], sizeof(_output
));
5335 for (i
= 0; i
< asyncReferenceCount
; i
++) {
5336 reference
[i
] = REF32(asyncReference
[i
]);
5339 err
= kIOReturnBadArgument
;
5342 if (inputCount
!= method
->count0
) {
5343 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5344 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5347 if (*outputCount
!= method
->count1
) {
5348 IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)*outputCount
, (uint64_t)method
->count1
);
5349 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5353 func
= method
->func
;
5355 switch (inputCount
) {
5357 err
= (object
->*func
)( reference
,
5358 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5359 ARG32(input
[3]), ARG32(input
[4]), ARG32(input
[5]));
5362 err
= (object
->*func
)( reference
,
5363 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5364 ARG32(input
[3]), ARG32(input
[4]),
5368 err
= (object
->*func
)( reference
,
5369 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5371 &_output
[0], &_output
[1] );
5374 err
= (object
->*func
)( reference
,
5375 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5376 &_output
[0], &_output
[1], &_output
[2] );
5379 err
= (object
->*func
)( reference
,
5380 ARG32(input
[0]), ARG32(input
[1]),
5381 &_output
[0], &_output
[1], &_output
[2],
5385 err
= (object
->*func
)( reference
,
5387 &_output
[0], &_output
[1], &_output
[2],
5388 &_output
[3], &_output
[4] );
5391 err
= (object
->*func
)( reference
,
5392 &_output
[0], &_output
[1], &_output
[2],
5393 &_output
[3], &_output
[4], &_output
[5] );
5397 IOLog("%s: Bad method table\n", object
->getName());
5401 for (i
= 0; i
< *outputCount
; i
++) {
5402 output
[i
] = SCALAR32(_output
[i
]);
5409 /* Routine io_connect_method_scalarI_structureO */
5411 is_io_connect_method_scalarI_structureO(
5412 io_object_t connect
,
5414 io_scalar_inband_t input
,
5415 mach_msg_type_number_t inputCount
,
5416 io_struct_inband_t output
,
5417 mach_msg_type_number_t
* outputCount
)
5420 io_scalar_inband64_t _input
;
5422 mach_msg_type_number_t scalar_outputCnt
= 0;
5423 mach_vm_size_t ool_output_size
= 0;
5425 for (i
= 0; i
< inputCount
; i
++) {
5426 _input
[i
] = SCALAR64(input
[i
]);
5429 return is_io_connect_method(connect
, index
,
5433 output
, outputCount
,
5434 NULL
, &scalar_outputCnt
,
5435 0, &ool_output_size
);
5439 shim_io_connect_method_scalarI_structureO(
5441 IOExternalMethod
* method
,
5443 const io_user_scalar_t
* input
,
5444 mach_msg_type_number_t inputCount
,
5445 io_struct_inband_t output
,
5446 IOByteCount
* outputCount
)
5451 err
= kIOReturnBadArgument
;
5454 if (inputCount
!= method
->count0
) {
5455 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5456 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5459 if ((kIOUCVariableStructureSize
!= method
->count1
)
5460 && (*outputCount
!= method
->count1
)) {
5461 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
);
5462 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5466 func
= method
->func
;
5468 switch (inputCount
) {
5470 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5471 ARG32(input
[3]), ARG32(input
[4]),
5475 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5477 output
, (void *)outputCount
);
5480 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5481 output
, (void *)outputCount
, NULL
);
5484 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
5485 output
, (void *)outputCount
, NULL
, NULL
);
5488 err
= (object
->*func
)( ARG32(input
[0]),
5489 output
, (void *)outputCount
, NULL
, NULL
, NULL
);
5492 err
= (object
->*func
)( output
, (void *)outputCount
, NULL
, NULL
, NULL
, NULL
);
5496 IOLog("%s: Bad method table\n", object
->getName());
5505 shim_io_async_method_scalarI_structureO(
5506 IOExternalAsyncMethod
* method
,
5508 mach_port_t asyncWakePort
,
5509 io_user_reference_t
* asyncReference
,
5510 uint32_t asyncReferenceCount
,
5511 const io_user_scalar_t
* input
,
5512 mach_msg_type_number_t inputCount
,
5513 io_struct_inband_t output
,
5514 mach_msg_type_number_t
* outputCount
)
5519 io_async_ref_t reference
;
5521 for (i
= 0; i
< asyncReferenceCount
; i
++) {
5522 reference
[i
] = REF32(asyncReference
[i
]);
5525 err
= kIOReturnBadArgument
;
5527 if (inputCount
!= method
->count0
) {
5528 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5529 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5532 if ((kIOUCVariableStructureSize
!= method
->count1
)
5533 && (*outputCount
!= method
->count1
)) {
5534 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
);
5535 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5539 func
= method
->func
;
5541 switch (inputCount
) {
5543 err
= (object
->*func
)( reference
,
5544 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5545 ARG32(input
[3]), ARG32(input
[4]),
5549 err
= (object
->*func
)( reference
,
5550 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5552 output
, (void *)outputCount
);
5555 err
= (object
->*func
)( reference
,
5556 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5557 output
, (void *)outputCount
, NULL
);
5560 err
= (object
->*func
)( reference
,
5561 ARG32(input
[0]), ARG32(input
[1]),
5562 output
, (void *)outputCount
, NULL
, NULL
);
5565 err
= (object
->*func
)( reference
,
5567 output
, (void *)outputCount
, NULL
, NULL
, NULL
);
5570 err
= (object
->*func
)( reference
,
5571 output
, (void *)outputCount
, NULL
, NULL
, NULL
, NULL
);
5575 IOLog("%s: Bad method table\n", object
->getName());
5582 /* Routine io_connect_method_scalarI_structureI */
5584 is_io_connect_method_scalarI_structureI(
5585 io_connect_t connect
,
5587 io_scalar_inband_t input
,
5588 mach_msg_type_number_t inputCount
,
5589 io_struct_inband_t inputStruct
,
5590 mach_msg_type_number_t inputStructCount
)
5593 io_scalar_inband64_t _input
;
5595 mach_msg_type_number_t scalar_outputCnt
= 0;
5596 mach_msg_type_number_t inband_outputCnt
= 0;
5597 mach_vm_size_t ool_output_size
= 0;
5599 for (i
= 0; i
< inputCount
; i
++) {
5600 _input
[i
] = SCALAR64(input
[i
]);
5603 return is_io_connect_method(connect
, index
,
5605 inputStruct
, inputStructCount
,
5607 NULL
, &inband_outputCnt
,
5608 NULL
, &scalar_outputCnt
,
5609 0, &ool_output_size
);
5613 shim_io_connect_method_scalarI_structureI(
5614 IOExternalMethod
* method
,
5616 const io_user_scalar_t
* input
,
5617 mach_msg_type_number_t inputCount
,
5618 io_struct_inband_t inputStruct
,
5619 mach_msg_type_number_t inputStructCount
)
5622 IOReturn err
= kIOReturnBadArgument
;
5625 if (inputCount
!= method
->count0
) {
5626 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5627 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5630 if ((kIOUCVariableStructureSize
!= method
->count1
)
5631 && (inputStructCount
!= method
->count1
)) {
5632 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
);
5633 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
5637 func
= method
->func
;
5639 switch (inputCount
) {
5641 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5642 ARG32(input
[3]), ARG32(input
[4]),
5646 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), (void *) input
[2],
5648 inputStruct
, (void *)(uintptr_t)inputStructCount
);
5651 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5652 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5656 err
= (object
->*func
)( ARG32(input
[0]), ARG32(input
[1]),
5657 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5661 err
= (object
->*func
)( ARG32(input
[0]),
5662 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5666 err
= (object
->*func
)( inputStruct
, (void *)(uintptr_t)inputStructCount
,
5667 NULL
, NULL
, NULL
, NULL
);
5671 IOLog("%s: Bad method table\n", object
->getName());
5679 shim_io_async_method_scalarI_structureI(
5680 IOExternalAsyncMethod
* method
,
5682 mach_port_t asyncWakePort
,
5683 io_user_reference_t
* asyncReference
,
5684 uint32_t asyncReferenceCount
,
5685 const io_user_scalar_t
* input
,
5686 mach_msg_type_number_t inputCount
,
5687 io_struct_inband_t inputStruct
,
5688 mach_msg_type_number_t inputStructCount
)
5692 IOReturn err
= kIOReturnBadArgument
;
5693 io_async_ref_t reference
;
5695 for (i
= 0; i
< asyncReferenceCount
; i
++) {
5696 reference
[i
] = REF32(asyncReference
[i
]);
5700 if (inputCount
!= method
->count0
) {
5701 IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__
, __LINE__
, object
->getName(), (uint64_t)inputCount
, (uint64_t)method
->count0
);
5702 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5705 if ((kIOUCVariableStructureSize
!= method
->count1
)
5706 && (inputStructCount
!= method
->count1
)) {
5707 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
);
5708 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputStructCount
, uint64_t, (uint64_t)method
->count1
);
5712 func
= method
->func
;
5714 switch (inputCount
) {
5716 err
= (object
->*func
)( reference
,
5717 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5718 ARG32(input
[3]), ARG32(input
[4]),
5722 err
= (object
->*func
)( reference
,
5723 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5725 inputStruct
, (void *)(uintptr_t)inputStructCount
);
5728 err
= (object
->*func
)( reference
,
5729 ARG32(input
[0]), ARG32(input
[1]), ARG32(input
[2]),
5730 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5734 err
= (object
->*func
)( reference
,
5735 ARG32(input
[0]), ARG32(input
[1]),
5736 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5740 err
= (object
->*func
)( reference
,
5742 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5746 err
= (object
->*func
)( reference
,
5747 inputStruct
, (void *)(uintptr_t)inputStructCount
,
5748 NULL
, NULL
, NULL
, NULL
);
5752 IOLog("%s: Bad method table\n", object
->getName());
5759 /* Routine io_connect_method_structureI_structureO */
5761 is_io_connect_method_structureI_structureO(
5762 io_object_t connect
,
5764 io_struct_inband_t input
,
5765 mach_msg_type_number_t inputCount
,
5766 io_struct_inband_t output
,
5767 mach_msg_type_number_t
* outputCount
)
5769 mach_msg_type_number_t scalar_outputCnt
= 0;
5770 mach_vm_size_t ool_output_size
= 0;
5772 return is_io_connect_method(connect
, index
,
5776 output
, outputCount
,
5777 NULL
, &scalar_outputCnt
,
5778 0, &ool_output_size
);
5782 shim_io_connect_method_structureI_structureO(
5783 IOExternalMethod
* method
,
5785 io_struct_inband_t input
,
5786 mach_msg_type_number_t inputCount
,
5787 io_struct_inband_t output
,
5788 IOByteCount
* outputCount
)
5791 IOReturn err
= kIOReturnBadArgument
;
5794 if ((kIOUCVariableStructureSize
!= method
->count0
)
5795 && (inputCount
!= method
->count0
)) {
5796 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
);
5797 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5800 if ((kIOUCVariableStructureSize
!= method
->count1
)
5801 && (*outputCount
!= method
->count1
)) {
5802 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
);
5803 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5807 func
= method
->func
;
5809 if (method
->count1
) {
5810 if (method
->count0
) {
5811 err
= (object
->*func
)( input
, output
,
5812 (void *)(uintptr_t)inputCount
, outputCount
, NULL
, NULL
);
5814 err
= (object
->*func
)( output
, outputCount
, NULL
, NULL
, NULL
, NULL
);
5817 err
= (object
->*func
)( input
, (void *)(uintptr_t)inputCount
, NULL
, NULL
, NULL
, NULL
);
5826 shim_io_async_method_structureI_structureO(
5827 IOExternalAsyncMethod
* method
,
5829 mach_port_t asyncWakePort
,
5830 io_user_reference_t
* asyncReference
,
5831 uint32_t asyncReferenceCount
,
5832 io_struct_inband_t input
,
5833 mach_msg_type_number_t inputCount
,
5834 io_struct_inband_t output
,
5835 mach_msg_type_number_t
* outputCount
)
5840 io_async_ref_t reference
;
5842 for (i
= 0; i
< asyncReferenceCount
; i
++) {
5843 reference
[i
] = REF32(asyncReference
[i
]);
5846 err
= kIOReturnBadArgument
;
5848 if ((kIOUCVariableStructureSize
!= method
->count0
)
5849 && (inputCount
!= method
->count0
)) {
5850 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
);
5851 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)inputCount
, uint64_t, (uint64_t)method
->count0
);
5854 if ((kIOUCVariableStructureSize
!= method
->count1
)
5855 && (*outputCount
!= method
->count1
)) {
5856 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
);
5857 DTRACE_IO2(iokit_count_mismatch
, uint64_t, (uint64_t)*outputCount
, uint64_t, (uint64_t)method
->count1
);
5861 func
= method
->func
;
5863 if (method
->count1
) {
5864 if (method
->count0
) {
5865 err
= (object
->*func
)( reference
,
5867 (void *)(uintptr_t)inputCount
, outputCount
, NULL
, NULL
);
5869 err
= (object
->*func
)( reference
,
5870 output
, outputCount
, NULL
, NULL
, NULL
, NULL
);
5873 err
= (object
->*func
)( reference
,
5874 input
, (void *)(uintptr_t)inputCount
, NULL
, NULL
, NULL
, NULL
);
5881 /* Routine io_catalog_send_data */
5883 is_io_catalog_send_data(
5884 mach_port_t master_port
,
5886 io_buf_ptr_t inData
,
5887 mach_msg_type_number_t inDataCount
,
5888 kern_return_t
* result
)
5891 return kIOReturnNotPrivileged
;
5892 #else /* NO_KEXTD */
5893 OSObject
* obj
= NULL
;
5895 kern_return_t kr
= kIOReturnError
;
5897 //printf("io_catalog_send_data called. flag: %d\n", flag);
5899 if (master_port
!= master_device_port
) {
5900 return kIOReturnNotPrivileged
;
5903 if ((flag
!= kIOCatalogRemoveKernelLinker__Removed
&&
5904 flag
!= kIOCatalogKextdActive
&&
5905 flag
!= kIOCatalogKextdFinishedLaunching
) &&
5906 (!inData
|| !inDataCount
)) {
5907 return kIOReturnBadArgument
;
5910 if (!IOTaskHasEntitlement(current_task(), kIOCatalogManagementEntitlement
)) {
5911 OSString
* taskName
= IOCopyLogNameForPID(proc_selfpid());
5912 IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName
? taskName
->getCStringNoCopy() : "");
5913 OSSafeReleaseNULL(taskName
);
5914 // For now, fake success to not break applications relying on this function succeeding.
5915 // See <rdar://problem/32554970> for more details.
5916 return kIOReturnSuccess
;
5920 vm_map_offset_t map_data
;
5922 if (inDataCount
> sizeof(io_struct_inband_t
) * 1024) {
5923 return kIOReturnMessageTooLarge
;
5926 kr
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
);
5927 data
= CAST_DOWN(vm_offset_t
, map_data
);
5929 if (kr
!= KERN_SUCCESS
) {
5933 // must return success after vm_map_copyout() succeeds
5936 obj
= (OSObject
*)OSUnserializeXML((const char *)data
, inDataCount
);
5937 vm_deallocate( kernel_map
, data
, inDataCount
);
5939 *result
= kIOReturnNoMemory
;
5940 return KERN_SUCCESS
;
5946 case kIOCatalogResetDrivers
:
5947 case kIOCatalogResetDriversNoMatch
: {
5950 array
= OSDynamicCast(OSArray
, obj
);
5952 if (!gIOCatalogue
->resetAndAddDrivers(array
,
5953 flag
== kIOCatalogResetDrivers
)) {
5954 kr
= kIOReturnError
;
5957 kr
= kIOReturnBadArgument
;
5962 case kIOCatalogAddDrivers
:
5963 case kIOCatalogAddDriversNoMatch
: {
5966 array
= OSDynamicCast(OSArray
, obj
);
5968 if (!gIOCatalogue
->addDrivers( array
,
5969 flag
== kIOCatalogAddDrivers
)) {
5970 kr
= kIOReturnError
;
5973 kr
= kIOReturnBadArgument
;
5978 case kIOCatalogRemoveDrivers
:
5979 case kIOCatalogRemoveDriversNoMatch
: {
5980 OSDictionary
* dict
;
5982 dict
= OSDynamicCast(OSDictionary
, obj
);
5984 if (!gIOCatalogue
->removeDrivers( dict
,
5985 flag
== kIOCatalogRemoveDrivers
)) {
5986 kr
= kIOReturnError
;
5989 kr
= kIOReturnBadArgument
;
5994 case kIOCatalogStartMatching__Removed
:
5995 case kIOCatalogRemoveKernelLinker__Removed
:
5996 case kIOCatalogKextdActive
:
5997 case kIOCatalogKextdFinishedLaunching
:
5998 kr
= KERN_NOT_SUPPORTED
;
6002 kr
= kIOReturnBadArgument
;
6011 return KERN_SUCCESS
;
6012 #endif /* NO_KEXTD */
6015 /* Routine io_catalog_terminate */
6017 is_io_catalog_terminate(
6018 mach_port_t master_port
,
6024 if (master_port
!= master_device_port
) {
6025 return kIOReturnNotPrivileged
;
6028 kr
= IOUserClient::clientHasPrivilege((void *) current_task(),
6029 kIOClientPrivilegeAdministrator
);
6030 if (kIOReturnSuccess
!= kr
) {
6035 #if !defined(SECURE_KERNEL)
6036 case kIOCatalogServiceTerminate
:
6037 kr
= gIOCatalogue
->terminateDrivers(NULL
, name
);
6040 case kIOCatalogModuleUnload
:
6041 case kIOCatalogModuleTerminate
:
6042 kr
= gIOCatalogue
->terminateDriversForModule(name
,
6043 flag
== kIOCatalogModuleUnload
);
6048 kr
= kIOReturnBadArgument
;
6055 /* Routine io_catalog_get_data */
6057 is_io_catalog_get_data(
6058 mach_port_t master_port
,
6060 io_buf_ptr_t
*outData
,
6061 mach_msg_type_number_t
*outDataCount
)
6063 kern_return_t kr
= kIOReturnSuccess
;
6066 if (master_port
!= master_device_port
) {
6067 return kIOReturnNotPrivileged
;
6070 //printf("io_catalog_get_data called. flag: %d\n", flag);
6072 s
= OSSerialize::withCapacity(4096);
6074 return kIOReturnNoMemory
;
6077 kr
= gIOCatalogue
->serializeData(flag
, s
);
6079 if (kr
== kIOReturnSuccess
) {
6084 size
= s
->getLength();
6085 kr
= vm_allocate_kernel(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
, VM_KERN_MEMORY_IOKIT
);
6086 if (kr
== kIOReturnSuccess
) {
6087 bcopy(s
->text(), (void *)data
, size
);
6088 kr
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
,
6090 *outData
= (char *)copy
;
6091 *outDataCount
= size
;
6100 /* Routine io_catalog_get_gen_count */
6102 is_io_catalog_get_gen_count(
6103 mach_port_t master_port
,
6106 if (master_port
!= master_device_port
) {
6107 return kIOReturnNotPrivileged
;
6110 //printf("io_catalog_get_gen_count called.\n");
6113 return kIOReturnBadArgument
;
6116 *genCount
= gIOCatalogue
->getGenerationCount();
6118 return kIOReturnSuccess
;
6121 /* Routine io_catalog_module_loaded.
6122 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
6125 is_io_catalog_module_loaded(
6126 mach_port_t master_port
,
6129 if (master_port
!= master_device_port
) {
6130 return kIOReturnNotPrivileged
;
6133 //printf("io_catalog_module_loaded called. name %s\n", name);
6136 return kIOReturnBadArgument
;
6139 gIOCatalogue
->moduleHasLoaded(name
);
6141 return kIOReturnSuccess
;
6145 is_io_catalog_reset(
6146 mach_port_t master_port
,
6149 if (master_port
!= master_device_port
) {
6150 return kIOReturnNotPrivileged
;
6154 case kIOCatalogResetDefault
:
6155 gIOCatalogue
->reset();
6159 return kIOReturnBadArgument
;
6162 return kIOReturnSuccess
;
6166 iokit_user_client_trap(struct iokit_user_client_trap_args
*args
)
6168 kern_return_t result
= kIOReturnBadArgument
;
6169 IOUserClient
* userClient
;
6173 ref
= (uintptr_t) args
->userClientRef
;
6174 if ((1ULL << 32) & ref
) {
6175 object
= iokit_lookup_uext_ref_current_task((mach_port_name_t
) ref
);
6177 result
= IOUserServerUEXTTrap(object
, args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
6179 OSSafeReleaseNULL(object
);
6180 } else if ((userClient
= OSDynamicCast(IOUserClient
, iokit_lookup_connect_ref_current_task((mach_port_name_t
) ref
)))) {
6181 IOExternalTrap
*trap
= NULL
;
6182 IOService
*target
= NULL
;
6184 result
= kIOReturnSuccess
;
6185 io_filter_policy_t filterPolicy
= userClient
->filterForTask(current_task(), 0);
6186 if (filterPolicy
&& gIOUCFilterCallbacks
->io_filter_applier
) {
6187 result
= gIOUCFilterCallbacks
->io_filter_applier(filterPolicy
, io_filter_type_trap
, args
->index
);
6189 if (kIOReturnSuccess
== result
) {
6190 trap
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
);
6192 if (trap
&& target
) {
6198 result
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
);
6202 iokit_remove_connect_reference(userClient
);
6208 /* Routine io_device_tree_entry_exists_with_name */
6210 is_io_device_tree_entry_exists_with_name(
6211 mach_port_t master_port
,
6215 OSCollectionIterator
*iter
;
6217 if (master_port
!= master_device_port
) {
6218 return kIOReturnNotPrivileged
;
6221 iter
= IODTFindMatchingEntries(IORegistryEntry::getRegistryRoot(), kIODTRecursive
, name
);
6222 *exists
= iter
&& iter
->getNextObject();
6223 OSSafeReleaseNULL(iter
);
6225 return kIOReturnSuccess
;
6230 IOUserClient::externalMethod( uint32_t selector
, IOExternalMethodArguments
* args
,
6231 IOExternalMethodDispatch
* dispatch
, OSObject
* target
, void * reference
)
6235 IOByteCount structureOutputSize
;
6239 count
= dispatch
->checkScalarInputCount
;
6240 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarInputCount
)) {
6241 return kIOReturnBadArgument
;
6244 count
= dispatch
->checkStructureInputSize
;
6245 if ((kIOUCVariableStructureSize
!= count
)
6246 && (count
!= ((args
->structureInputDescriptor
)
6247 ? args
->structureInputDescriptor
->getLength() : args
->structureInputSize
))) {
6248 return kIOReturnBadArgument
;
6251 count
= dispatch
->checkScalarOutputCount
;
6252 if ((kIOUCVariableStructureSize
!= count
) && (count
!= args
->scalarOutputCount
)) {
6253 return kIOReturnBadArgument
;
6256 count
= dispatch
->checkStructureOutputSize
;
6257 if ((kIOUCVariableStructureSize
!= count
)
6258 && (count
!= ((args
->structureOutputDescriptor
)
6259 ? args
->structureOutputDescriptor
->getLength() : args
->structureOutputSize
))) {
6260 return kIOReturnBadArgument
;
6263 if (dispatch
->function
) {
6264 err
= (*dispatch
->function
)(target
, reference
, args
);
6266 err
= kIOReturnNoCompletion
; /* implementator can dispatch */
6272 // pre-Leopard API's don't do ool structs
6273 if (args
->structureInputDescriptor
|| args
->structureOutputDescriptor
) {
6274 err
= kIOReturnIPCError
;
6278 structureOutputSize
= args
->structureOutputSize
;
6280 if (args
->asyncWakePort
) {
6281 IOExternalAsyncMethod
* method
;
6283 if (!(method
= getAsyncTargetAndMethodForIndex(&object
, selector
)) || !object
) {
6284 return kIOReturnUnsupported
;
6287 if (kIOUCForegroundOnly
& method
->flags
) {
6288 if (task_is_gpu_denied(current_task())) {
6289 return kIOReturnNotPermitted
;
6293 switch (method
->flags
& kIOUCTypeMask
) {
6294 case kIOUCScalarIStructI
:
6295 err
= shim_io_async_method_scalarI_structureI( method
, object
,
6296 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
6297 args
->scalarInput
, args
->scalarInputCount
,
6298 (char *)args
->structureInput
, args
->structureInputSize
);
6301 case kIOUCScalarIScalarO
:
6302 err
= shim_io_async_method_scalarI_scalarO( method
, object
,
6303 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
6304 args
->scalarInput
, args
->scalarInputCount
,
6305 args
->scalarOutput
, &args
->scalarOutputCount
);
6308 case kIOUCScalarIStructO
:
6309 err
= shim_io_async_method_scalarI_structureO( method
, object
,
6310 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
6311 args
->scalarInput
, args
->scalarInputCount
,
6312 (char *) args
->structureOutput
, &args
->structureOutputSize
);
6316 case kIOUCStructIStructO
:
6317 err
= shim_io_async_method_structureI_structureO( method
, object
,
6318 args
->asyncWakePort
, args
->asyncReference
, args
->asyncReferenceCount
,
6319 (char *)args
->structureInput
, args
->structureInputSize
,
6320 (char *) args
->structureOutput
, &args
->structureOutputSize
);
6324 err
= kIOReturnBadArgument
;
6328 IOExternalMethod
* method
;
6330 if (!(method
= getTargetAndMethodForIndex(&object
, selector
)) || !object
) {
6331 return kIOReturnUnsupported
;
6334 if (kIOUCForegroundOnly
& method
->flags
) {
6335 if (task_is_gpu_denied(current_task())) {
6336 return kIOReturnNotPermitted
;
6340 switch (method
->flags
& kIOUCTypeMask
) {
6341 case kIOUCScalarIStructI
:
6342 err
= shim_io_connect_method_scalarI_structureI( method
, object
,
6343 args
->scalarInput
, args
->scalarInputCount
,
6344 (char *) args
->structureInput
, args
->structureInputSize
);
6347 case kIOUCScalarIScalarO
:
6348 err
= shim_io_connect_method_scalarI_scalarO( method
, object
,
6349 args
->scalarInput
, args
->scalarInputCount
,
6350 args
->scalarOutput
, &args
->scalarOutputCount
);
6353 case kIOUCScalarIStructO
:
6354 err
= shim_io_connect_method_scalarI_structureO( method
, object
,
6355 args
->scalarInput
, args
->scalarInputCount
,
6356 (char *) args
->structureOutput
, &structureOutputSize
);
6360 case kIOUCStructIStructO
:
6361 err
= shim_io_connect_method_structureI_structureO( method
, object
,
6362 (char *) args
->structureInput
, args
->structureInputSize
,
6363 (char *) args
->structureOutput
, &structureOutputSize
);
6367 err
= kIOReturnBadArgument
;
6372 if (structureOutputSize
> UINT_MAX
) {
6373 structureOutputSize
= 0;
6374 err
= kIOReturnBadArgument
;
6377 args
->structureOutputSize
= ((typeof(args
->structureOutputSize
))structureOutputSize
);
6383 IOUserClient::registerFilterCallbacks(const struct io_filter_callbacks
*callbacks
, size_t size
)
6385 if (size
< sizeof(*callbacks
)) {
6386 return kIOReturnBadArgument
;
6388 if (!OSCompareAndSwapPtr(NULL
, __DECONST(void *, callbacks
), &gIOUCFilterCallbacks
)) {
6389 return kIOReturnBusy
;
6391 return kIOReturnSuccess
;
6395 OSMetaClassDefineReservedUnused(IOUserClient
, 0);
6396 OSMetaClassDefineReservedUnused(IOUserClient
, 1);
6398 OSMetaClassDefineReservedUsed(IOUserClient
, 0);
6399 OSMetaClassDefineReservedUsed(IOUserClient
, 1);
6401 OSMetaClassDefineReservedUnused(IOUserClient
, 2);
6402 OSMetaClassDefineReservedUnused(IOUserClient
, 3);
6403 OSMetaClassDefineReservedUnused(IOUserClient
, 4);
6404 OSMetaClassDefineReservedUnused(IOUserClient
, 5);
6405 OSMetaClassDefineReservedUnused(IOUserClient
, 6);
6406 OSMetaClassDefineReservedUnused(IOUserClient
, 7);
6407 OSMetaClassDefineReservedUnused(IOUserClient
, 8);
6408 OSMetaClassDefineReservedUnused(IOUserClient
, 9);
6409 OSMetaClassDefineReservedUnused(IOUserClient
, 10);
6410 OSMetaClassDefineReservedUnused(IOUserClient
, 11);
6411 OSMetaClassDefineReservedUnused(IOUserClient
, 12);
6412 OSMetaClassDefineReservedUnused(IOUserClient
, 13);
6413 OSMetaClassDefineReservedUnused(IOUserClient
, 14);
6414 OSMetaClassDefineReservedUnused(IOUserClient
, 15);