xref: /xnu-8792.41.9/iokit/IOKit/IOUserClient.h (revision 5c2921b07a2480ab43ec66f5b9e41cb872bc554f)
1 /*
2  * Copyright (c) 1998-2019 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 /*
30  * Changes to this API are expected.
31  */
32 
33 #ifndef _IOKIT_IOUSERCLIENT_H
34 #define _IOKIT_IOUSERCLIENT_H
35 
36 #include <IOKit/IOTypes.h>
37 #include <IOKit/IOService.h>
38 #include <IOKit/OSMessageNotification.h>
39 #include <DriverKit/IOUserClient.h>
40 #include <libkern/c++/OSPtr.h>
41 
42 #if IOKITSTATS
43 #include <IOKit/IOStatisticsPrivate.h>
44 #endif
45 
46 #define _IOUSERCLIENT_SENDASYNCRESULT64WITHOPTIONS_             1
47 
48 enum {
49 	kIOUCTypeMask       = 0x0000000f,
50 	kIOUCScalarIScalarO = 0,
51 	kIOUCScalarIStructO = 2,
52 	kIOUCStructIStructO = 3,
53 	kIOUCScalarIStructI = 4,
54 
55 	kIOUCForegroundOnly = 0x00000010,
56 };
57 
58 /*! @enum
59  *   @abstract Constant to denote a variable length structure argument to IOUserClient.
60  *   @constant kIOUCVariableStructureSize Use in the structures IOExternalMethod, IOExternalAsyncMethod, IOExternalMethodDispatch to specify the size of the structure is variable.
61  */
62 enum {
63 	kIOUCVariableStructureSize = 0xffffffff
64 };
65 
66 
67 typedef IOReturn (IOService::*IOMethod)(void * p1, void * p2, void * p3,
68     void * p4, void * p5, void * p6 );
69 
70 typedef IOReturn (IOService::*IOAsyncMethod)(OSAsyncReference asyncRef,
71     void * p1, void * p2, void * p3,
72     void * p4, void * p5, void * p6 );
73 
74 typedef IOReturn (IOService::*IOTrap)(void * p1, void * p2, void * p3,
75     void * p4, void * p5, void * p6 );
76 
77 struct IOExternalMethod {
78 	IOService *         object;
79 	IOMethod            func;
80 	IOOptionBits        flags;
81 	IOByteCount         count0;
82 	IOByteCount         count1;
83 };
84 
85 struct IOExternalAsyncMethod {
86 	IOService *         object;
87 	IOAsyncMethod       func;
88 	IOOptionBits        flags;
89 	IOByteCount         count0;
90 	IOByteCount         count1;
91 };
92 
93 struct IOExternalTrap {
94 	IOService *         object;
95 	IOTrap              func;
96 };
97 
98 enum {
99 	kIOUserNotifyMaxMessageSize = 64
100 };
101 
102 enum {
103 	kIOUserNotifyOptionCanDrop = 0x1 /* Fail if queue is full, rather than infinitely queuing. */
104 };
105 
106 // keys for clientHasPrivilege
107 #define kIOClientPrivilegeAdministrator "root"
108 #define kIOClientPrivilegeLocalUser     "local"
109 #define kIOClientPrivilegeForeground    "foreground"
110 
111 /*! @enum
112  *   @abstract Constants to specify the maximum number of scalar arguments in the IOExternalMethodArguments structure. These constants are documentary since the scalarInputCount, scalarOutputCount fields reflect the actual number passed.
113  *   @constant kIOExternalMethodScalarInputCountMax The maximum number of scalars able to passed on input.
114  *   @constant kIOExternalMethodScalarOutputCountMax The maximum number of scalars able to passed on output.
115  */
116 enum {
117 	kIOExternalMethodScalarInputCountMax  = 16,
118 	kIOExternalMethodScalarOutputCountMax = 16,
119 };
120 
121 
122 struct IOExternalMethodArguments {
123 	uint32_t            version;
124 
125 	uint32_t            selector;
126 
127 	mach_port_t           asyncWakePort;
128 	io_user_reference_t * asyncReference;
129 	uint32_t              asyncReferenceCount;
130 
131 	const uint64_t *    scalarInput;
132 	uint32_t            scalarInputCount;
133 
134 	const void *        structureInput;
135 	uint32_t            structureInputSize;
136 
137 	IOMemoryDescriptor * structureInputDescriptor;
138 
139 	uint64_t *          scalarOutput;
140 	uint32_t            scalarOutputCount;
141 
142 	void *              structureOutput;
143 	uint32_t            structureOutputSize;
144 
145 	IOMemoryDescriptor * structureOutputDescriptor;
146 	uint32_t             structureOutputDescriptorSize;
147 
148 	uint32_t            __reservedA;
149 
150 	OSObject **         structureVariableOutputData;
151 
152 	uint32_t            __reserved[30];
153 };
154 
155 struct IOExternalMethodArgumentsOpaque;
156 
157 typedef IOReturn (*IOExternalMethodAction)(OSObject * target, void * reference,
158     IOExternalMethodArguments * arguments);
159 
160 struct IOExternalMethodDispatch {
161 	IOExternalMethodAction function;
162 	uint32_t               checkScalarInputCount;
163 	uint32_t               checkStructureInputSize;
164 	uint32_t               checkScalarOutputCount;
165 	uint32_t               checkStructureOutputSize;
166 };
167 
168 struct IOExternalMethodDispatch2022 {
169 	IOExternalMethodAction function;
170 	uint32_t               checkScalarInputCount;
171 	uint32_t               checkStructureInputSize;
172 	uint32_t               checkScalarOutputCount;
173 	uint32_t               checkStructureOutputSize;
174 	uint8_t                allowAsync;
175 	const char*            checkEntitlement;
176 };
177 
178 enum {
179 #define IO_EXTERNAL_METHOD_ARGUMENTS_CURRENT_VERSION    2
180 	kIOExternalMethodArgumentsCurrentVersion = IO_EXTERNAL_METHOD_ARGUMENTS_CURRENT_VERSION
181 };
182 
183 #if PRIVATE
184 typedef uintptr_t io_filter_policy_t __kernel_ptr_semantics;
185 enum io_filter_type_t {
186 	io_filter_type_external_method       = 1,
187 	io_filter_type_external_async_method = 2,
188 	io_filter_type_trap                  = 3,
189 };
190 
191 typedef IOReturn (*io_filter_resolver_t) (task_t task, IOUserClient * client, uint32_t type, io_filter_policy_t *filterp);
192 typedef IOReturn (*io_filter_applier_t) (IOUserClient * client, io_filter_policy_t filter, io_filter_type_t type, uint32_t selector);
193 typedef void (*io_filter_release_t) (io_filter_policy_t filter);
194 struct io_filter_callbacks {
195 	const io_filter_resolver_t      io_filter_resolver;
196 	const io_filter_applier_t       io_filter_applier;
197 	const io_filter_release_t       io_filter_release;
198 };
199 struct IOUCFilterPolicy;
200 #endif /* PRIVATE */
201 
202 /*!
203  *   @class IOUserClient
204  *   @abstract   Provides a basis for communication between client applications and I/O Kit objects.
205  */
206 class IOUserClient : public IOService
207 {
208 	OSDeclareAbstractStructorsWithDispatch(IOUserClient);
209 #if IOKITSTATS
210 	friend class IOStatistics;
211 #endif
212 
213 #if XNU_KERNEL_PRIVATE
214 public:
215 #else /* XNU_KERNEL_PRIVATE */
216 protected:
217 #endif /* !XNU_KERNEL_PRIVATE */
218 /*! @struct ExpansionData
219  *   @discussion This structure will be used to expand the capablilties of this class in the future.
220  */
221 	struct ExpansionData {
222 #if IOKITSTATS
223 		IOUserClientCounter *counter;
224 #else
225 		void *iokitstatsReserved;
226 #endif
227 #if PRIVATE
228 		IOUCFilterPolicy * filterPolicies;
229 #else
230 		void *iokitFilterReserved;
231 #endif
232 	};
233 
234 /*! @var reserved
235  *   Reserved for future use.  (Internal use only)
236  */
237 	APPLE_KEXT_WSHADOW_PUSH;
238 	ExpansionData * reserved;
239 	APPLE_KEXT_WSHADOW_POP;
240 
241 	bool reserve();
242 
243 #ifdef XNU_KERNEL_PRIVATE
244 
245 public:
246 	OSSet * mappings;
247 	UInt8   sharedInstance;
248 	UInt8   closed;
249 	UInt8   __ipcFinal;
250 	UInt8   messageAppSuspended:1,
251 	    uc2022:1,
252 	    defaultLocking:1,
253 	    defaultLockingSingleThreadExternalMethod:1,
254 	    defaultLockingSetProperties:1,
255 	    __reservedA:3;
256 	volatile SInt32 __ipc;
257 	queue_head_t owners;
258 	IORWLock * lock;
259 	IOLock   * filterLock;
260 #if __LP64__
261 	void  * __reserved[3];
262 #else
263 	void  * __reserved[2];
264 #endif
265 
266 #else /* XNU_KERNEL_PRIVATE */
267 private:
268 	void  * __reserved[9];
269 #endif /* XNU_KERNEL_PRIVATE */
270 
271 public:
272 	MIG_SERVER_ROUTINE virtual IOReturn
273 	externalMethod(uint32_t selector, IOExternalMethodArguments * arguments,
274 	    IOExternalMethodDispatch *dispatch = NULL,
275 	    OSObject *target = NULL, void *reference = NULL);
276 
277 	MIG_SERVER_ROUTINE virtual IOReturn registerNotificationPort(
278 		mach_port_t port, UInt32 type, io_user_reference_t refCon);
279 
280 private:
281 	OSMetaClassDeclareReservedUnused(IOUserClient, 0);
282 	OSMetaClassDeclareReservedUnused(IOUserClient, 1);
283 	OSMetaClassDeclareReservedUnused(IOUserClient, 2);
284 	OSMetaClassDeclareReservedUnused(IOUserClient, 3);
285 	OSMetaClassDeclareReservedUnused(IOUserClient, 4);
286 	OSMetaClassDeclareReservedUnused(IOUserClient, 5);
287 	OSMetaClassDeclareReservedUnused(IOUserClient, 6);
288 	OSMetaClassDeclareReservedUnused(IOUserClient, 7);
289 	OSMetaClassDeclareReservedUnused(IOUserClient, 8);
290 	OSMetaClassDeclareReservedUnused(IOUserClient, 9);
291 	OSMetaClassDeclareReservedUnused(IOUserClient, 10);
292 	OSMetaClassDeclareReservedUnused(IOUserClient, 11);
293 	OSMetaClassDeclareReservedUnused(IOUserClient, 12);
294 	OSMetaClassDeclareReservedUnused(IOUserClient, 13);
295 	OSMetaClassDeclareReservedUnused(IOUserClient, 14);
296 	OSMetaClassDeclareReservedUnused(IOUserClient, 15);
297 
298 #ifdef XNU_KERNEL_PRIVATE
299 
300 /* Available within xnu source only */
301 public:
302 	static void initialize( void );
303 	static void destroyUserReferences( OSObject * obj );
304 	static bool finalizeUserReferences( OSObject * obj );
305 	OSPtr<IOMemoryMap>  mapClientMemory64( IOOptionBits type,
306 	    task_t task,
307 	    IOOptionBits mapFlags = kIOMapAnywhere,
308 	    mach_vm_address_t atAddress = 0 );
309 	IOReturn registerOwner(task_t task);
310 	void     noMoreSenders(void);
311 	io_filter_policy_t filterForTask(task_t task, io_filter_policy_t addFilterPolicy);
312 	MIG_SERVER_ROUTINE IOReturn
313 	callExternalMethod(uint32_t selector, IOExternalMethodArguments * arguments);
314 
315 #endif /* XNU_KERNEL_PRIVATE */
316 
317 #if PRIVATE
318 public:
319 	static IOReturn registerFilterCallbacks(const struct io_filter_callbacks *callbacks, size_t size);
320 #endif /* PRIVATE */
321 
322 protected:
323 	static IOReturn sendAsyncResult(OSAsyncReference reference,
324 	    IOReturn result, void *args[], UInt32 numArgs);
325 	static void setAsyncReference(OSAsyncReference asyncRef,
326 	    mach_port_t wakePort,
327 	    void *callback, void *refcon);
328 
329 	static IOReturn sendAsyncResult64(OSAsyncReference64 reference,
330 	    IOReturn result, io_user_reference_t args[], UInt32 numArgs);
331 
332 /*!
333  *   @function sendAsyncResult64WithOptions
334  *   @abstract Send a notification as with sendAsyncResult, but with finite queueing.
335  *   @discussion IOUserClient::sendAsyncResult64() will infitely queue messages if the client
336  *           is not processing them in a timely fashion.  This variant will not, for simple
337  *           handling of situations where clients may be expected to stop processing messages.
338  */
339 	static IOReturn sendAsyncResult64WithOptions(OSAsyncReference64 reference,
340 	    IOReturn result, io_user_reference_t args[], UInt32 numArgs,
341 	    IOOptionBits options);
342 
343 	static void setAsyncReference64(OSAsyncReference64 asyncRef,
344 	    mach_port_t wakePort,
345 	    mach_vm_address_t callback, io_user_reference_t refcon);
346 
347 	static void setAsyncReference64(OSAsyncReference64 asyncRef,
348 	    mach_port_t wakePort,
349 	    mach_vm_address_t callback, io_user_reference_t refcon,
350 	    task_t task);
351 
352 public:
353 
354 	static IOReturn clientHasAuthorization( task_t task,
355 	    IOService * service );
356 
357 	static IOReturn clientHasPrivilege( void * securityToken,
358 	    const char * privilegeName );
359 
360 	static OSPtr<OSObject>  copyClientEntitlement(task_t task, const char *entitlement);
361 	static OSPtr<OSObject>  copyClientEntitlementVnode(struct vnode *vnode, off_t offset, const char *entitlement);
362 
363 	static OSPtr<OSDictionary>  copyClientEntitlements(task_t task);
364 	static OSPtr<OSDictionary>  copyClientEntitlementsVnode(struct vnode *vnode, off_t offset);
365 
366 /*!
367  *   @function releaseAsyncReference64
368  *   @abstract Release the mach_port_t reference held within the OSAsyncReference64 structure.
369  *   @discussion The OSAsyncReference64 structure passed to async methods holds a reference to the wakeup mach port, which should be released to balance each async method call. Behavior is undefined if these calls are not correctly balanced.
370  *   @param reference The reference passed to the subclass IOAsyncMethod, or externalMethod() in the IOExternalMethodArguments.asyncReference field.
371  *   @result A return code.
372  */
373 	static IOReturn releaseAsyncReference64(OSAsyncReference64 reference);
374 /*!
375  *   @function releaseNotificationPort
376  *   @abstract Release the mach_port_t passed to registerNotificationPort().
377  *   @discussion The mach_port_t passed to the registerNotificationPort() methods should be released to balance each call to registerNotificationPort(). Behavior is undefined if these calls are not correctly balanced.
378  *   @param port The mach_port_t argument previously passed to the subclass implementation of registerNotificationPort().
379  *   @result A return code.
380  */
381 	static IOReturn releaseNotificationPort(mach_port_t port);
382 
383 	virtual bool init() APPLE_KEXT_OVERRIDE;
384 	virtual bool init( OSDictionary * dictionary ) APPLE_KEXT_OVERRIDE;
385 // Currently ignores the all args, just passes up to IOService::init()
386 	virtual bool initWithTask(
387 		task_t owningTask, void * securityToken, UInt32 type,
388 		OSDictionary * properties);
389 
390 	virtual bool initWithTask(
391 		task_t owningTask, void * securityToken, UInt32 type);
392 
393 	virtual void free() APPLE_KEXT_OVERRIDE;
394 
395 	virtual IOReturn clientClose( void );
396 	virtual IOReturn clientDied( void );
397 
398 	virtual IOService * getService( void );
399 
400 	MIG_SERVER_ROUTINE virtual IOReturn registerNotificationPort(
401 		mach_port_t port, UInt32 type, UInt32 refCon );
402 
403 	MIG_SERVER_ROUTINE virtual IOReturn getNotificationSemaphore( UInt32 notification_type,
404 	    semaphore_t * semaphore );
405 
406 	virtual IOReturn connectClient( IOUserClient * client );
407 
408 // memory will be released by user client when last map is destroyed
409 	virtual IOReturn clientMemoryForType( UInt32 type,
410 	    IOOptionBits * options,
411 	    IOMemoryDescriptor ** memory );
412 
413 	IOReturn clientMemoryForType( UInt32 type,
414 	    IOOptionBits * options,
415 	    OSSharedPtr<IOMemoryDescriptor>& memory );
416 
417 #if !__LP64__
418 private:
419 	APPLE_KEXT_COMPATIBILITY_VIRTUAL
420 	OSPtr<IOMemoryMap>  mapClientMemory( IOOptionBits type,
421 	    task_t task,
422 	    IOOptionBits mapFlags = kIOMapAnywhere,
423 	    IOVirtualAddress atAddress = 0 );
424 #endif
425 
426 	static IOReturn _sendAsyncResult64(OSAsyncReference64 reference,
427 	    IOReturn result, io_user_reference_t args[], UInt32 numArgs, IOOptionBits options);
428 public:
429 
430 /*!
431  *   @function removeMappingForDescriptor
432  *   Remove the first mapping created from the memory descriptor returned by clientMemoryForType() from IOUserClient's list of mappings. If such a mapping exists, it is retained and the reference currently held by IOUserClient is returned to the caller.
433  *   @param memory The memory descriptor instance previously returned by the implementation of clientMemoryForType().
434  *   @result A reference to the first IOMemoryMap instance found in the list of mappings created by IOUserClient from that passed memory descriptor is returned, or zero if none exist. The caller should release this reference.
435  */
436 	OSPtr<IOMemoryMap>  removeMappingForDescriptor(IOMemoryDescriptor * memory);
437 
438 /*!
439  *   @function exportObjectToClient
440  *   Make an arbitrary OSObject available to the client task.
441  *   @param task The task.
442  *   @param obj The object we want to export to the client.
443  *   @param clientObj Returned value is the client's port name.
444  */
445 	virtual IOReturn exportObjectToClient(task_t task,
446 	    LIBKERN_CONSUMED OSObject *obj, io_object_t *clientObj);
447 
448 #if KERNEL_PRIVATE
449 
450 /*!
451  *   @function copyPortNameForObjectInTask
452  *   Make an arbitrary OSObject available to the client task as a port name.
453  *   The port does not respond to any IOKit IPC calls.
454  *   @param task The task.
455  *   @param object The object we want to export to the client.
456  *   The port holds a reference on the object, this function does not consume any reference on the object.
457  *   @param port_name Returned value is the task's port name. It has one send right created by this function.
458  *   @result A return code.
459  */
460 	static IOReturn copyPortNameForObjectInTask(task_t task, OSObject *object,
461 	    mach_port_name_t * port_name);
462 
463 /*!
464  *   @function copyObjectForPortNameInTask
465  *   Look up an OSObject given a task's port name created with copyPortNameForObjectInTask().
466  *   @param task The task.
467  *   @param port_name The task's port name. This function does not consume any reference on the port name.
468  *   @param object If the port name is valid, a reference to the object is returned. It should be released by the caller.
469  *   @result A return code.
470  */
471 	static IOReturn copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name,
472 	    OSObject **object);
473 
474 	static IOReturn copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name,
475 	    OSSharedPtr<OSObject>& object);
476 
477 /*!
478  *   @function adjustPortNameReferencesInTask
479  *   Adjust the send rights for a port name created with copyPortNameForObjectInTask().
480  *   @param task The task.
481  *   @param port_name The task's port name.
482  *   @param delta Signed value change to the number of user references.
483  *   @result A return code.
484  */
485 	static IOReturn adjustPortNameReferencesInTask(task_t task, mach_port_name_t port_name, mach_port_delta_t delta);
486 
487 #define IOUC_COPYPORTNAMEFOROBJECTINTASK    1
488 
489 #endif /* KERNEL_PRIVATE */
490 
491 // Old methods for accessing method vector backward compatiblility only
492 	virtual IOExternalMethod *
493 	getExternalMethodForIndex( UInt32 index )
494 	APPLE_KEXT_DEPRECATED;
495 	virtual IOExternalAsyncMethod *
496 	getExternalAsyncMethodForIndex( UInt32 index )
497 	APPLE_KEXT_DEPRECATED;
498 
499 // Methods for accessing method vector.
500 	virtual IOExternalMethod *
501 	getTargetAndMethodForIndex(
502 		LIBKERN_RETURNS_NOT_RETAINED IOService ** targetP, UInt32 index );
503 	virtual IOExternalAsyncMethod *
504 	getAsyncTargetAndMethodForIndex(
505 		LIBKERN_RETURNS_NOT_RETAINED IOService ** targetP, UInt32 index );
506 	IOExternalMethod *
507 	getTargetAndMethodForIndex(
508 		OSSharedPtr<IOService>& targetP, UInt32 index );
509 	IOExternalAsyncMethod *
510 	getAsyncTargetAndMethodForIndex(
511 		OSSharedPtr<IOService>& targetP, UInt32 index );
512 
513 // Methods for accessing trap vector - old and new style
514 	virtual IOExternalTrap *
515 	getExternalTrapForIndex( UInt32 index )
516 	APPLE_KEXT_DEPRECATED;
517 
518 	virtual IOExternalTrap *
519 	getTargetAndTrapForIndex(
520 		LIBKERN_RETURNS_NOT_RETAINED IOService **targetP, UInt32 index );
521 };
522 
523 #if KERNEL_PRIVATE
524 
525 #define IOUSERCLIENT2022_SUPPORTED      1
526 
527 /*
528  *  IOUserClient2022 is a new superclass for an IOUserClient implementation to opt-in to
529  *  several security related best practices. The changes in behavior are:
530  *  - these properties must be present after ::start completes to control default single
531  *  threading calls to the IOUC from clients. It is recommended to set all values to true.
532  *
533  *  kIOUserClientDefaultLockingKey if kOSBooleanTrue
534  *  IOConnectMapMemory, IOConnectUnmapMemory, IOConnectAddClient, IOServiceClose
535  *  are single threaded and will not allow externalMethod to run concurrently.
536  *  Multiple threads can call externalMethod concurrently however.
537  *
538  *  kIOUserClientDefaultLockingSetPropertiesKey if kOSBooleanTrue
539  *  IORegistrySetProperties is also single threaded as above.
540  *
541  *  kIOUserClientDefaultLockingSingleThreadExternalMethodKey if kOSBooleanTrue
542  *  Only one thread may call externalMethod concurrently.
543  *
544  *  kIOUserClientEntitlementsKey
545  *  Entitlements required for a process to open the IOUC (see the key description).
546  *  It is recommended to require an entitlement if all calling processes are from Apple.
547  *
548  *  - the externalMethod override is required and must call dispatchExternalMethod() to
549  *  do basic argument checking before calling subclass code to implement the method.
550  *  dispatchExternalMethod() is called with an array of IOExternalMethodDispatch2022
551  *  elements and will index into the array for the given selector. The selector should
552  *  be adjusted accordingly, if needed, in the subclass' externalMethod().
553  *  The allowAsync field of IOExternalMethodDispatch2022 must be true to allow the
554  *  IOConnectCallAsyncMethod(etc) APIs to be used with the method.
555  *  If the checkEntitlement field of IOExternalMethodDispatch2022 is non-NULL, then
556  *  the calling process must have the named entitlement key, with a value of boolean true,
557  *  or kIOReturnNotPrivileged is returned. This should be used when per-selector entitlement
558  *  checks are required.  If you only need to check at the time the connection is created,
559  *  use kIOUserClientEntitlementsKey instead.
560  */
561 
562 class IOUserClient2022 : public IOUserClient
563 {
564 	OSDeclareDefaultStructors(IOUserClient2022);
565 
566 private:
567 	MIG_SERVER_ROUTINE virtual IOReturn
568 	externalMethod(uint32_t selector, IOExternalMethodArguments * arguments,
569 	    IOExternalMethodDispatch *dispatch = NULL,
570 	    OSObject *target = NULL, void *reference = NULL) APPLE_KEXT_OVERRIDE;
571 
572 protected:
573 	IOReturn
574 	dispatchExternalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * arguments,
575 	    const IOExternalMethodDispatch2022 dispatchArray[], size_t dispatchArrayCount,
576 	    OSObject * target, void * reference);
577 
578 public:
579 
580 	MIG_SERVER_ROUTINE virtual IOReturn
581 	externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * arguments) = 0;
582 
583 
584 	OSMetaClassDeclareReservedUnused(IOUserClient2022, 0);
585 	OSMetaClassDeclareReservedUnused(IOUserClient2022, 1);
586 	OSMetaClassDeclareReservedUnused(IOUserClient2022, 2);
587 	OSMetaClassDeclareReservedUnused(IOUserClient2022, 3);
588 };
589 
590 #endif /* KERNEL_PRIVATE */
591 
592 #ifdef XNU_KERNEL_PRIVATE
593 extern "C" void IOMachPortDestroyUserReferences(OSObject * obj, natural_t type);
594 
595 class IOUserIterator : public OSIterator
596 {
597 	OSDeclareDefaultStructors(IOUserIterator);
598 public:
599 	OSObject    *       userIteratorObject;
600 	IOLock      *       lock;
601 
602 	static IOUserIterator * withIterator(LIBKERN_CONSUMED OSIterator * iter);
603 	virtual bool init( void ) APPLE_KEXT_OVERRIDE;
604 	virtual void free() APPLE_KEXT_OVERRIDE;
605 
606 	virtual void reset() APPLE_KEXT_OVERRIDE;
607 	virtual bool isValid() APPLE_KEXT_OVERRIDE;
608 	virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
609 	virtual OSObject * copyNextObject();
610 };
611 
612 class IOUserNotification : public IOUserIterator
613 {
614 	OSDeclareDefaultStructors(IOUserNotification);
615 
616 public:
617 
618 	virtual void free() APPLE_KEXT_OVERRIDE;
619 
620 	virtual void setNotification( IONotifier * obj );
621 
622 	virtual void reset() APPLE_KEXT_OVERRIDE;
623 	virtual bool isValid() APPLE_KEXT_OVERRIDE;
624 };
625 
626 #endif /* XNU_KERNEL_PRIVATE */
627 
628 #endif /* ! _IOKIT_IOUSERCLIENT_H */
629