xref: /xnu-11215/iokit/IOKit/IOUserClient.h (revision 94d3b452)
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 	UInt8        __opaque_start[0];
247 
248 	OSSet * mappings;
249 	UInt8   sharedInstance;
250 	UInt8   closed;
251 	UInt8   __ipcFinal;
252 	UInt8   messageAppSuspended:1,
253 	    uc2022:1,
254 	    defaultLocking:1,
255 	    defaultLockingSingleThreadExternalMethod:1,
256 	    defaultLockingSetProperties:1,
257 	    opened:1,
258 	    __reservedA:2;
259 	volatile SInt32 __ipc;
260 	queue_head_t owners;
261 	IORWLock     lock;
262 	IOLock       filterLock;
263 	void        *__reserved[1];
264 
265 	UInt8        __opaque_end[0];
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 	void ipcEnter(int locking);
306 	void ipcExit(int locking);
307 	OSPtr<IOMemoryMap>  mapClientMemory64( IOOptionBits type,
308 	    task_t task,
309 	    IOOptionBits mapFlags = kIOMapAnywhere,
310 	    mach_vm_address_t atAddress = 0 );
311 	IOReturn registerOwner(task_t task);
312 	void     noMoreSenders(void);
313 	io_filter_policy_t filterForTask(task_t task, io_filter_policy_t addFilterPolicy);
314 	MIG_SERVER_ROUTINE IOReturn
315 	callExternalMethod(uint32_t selector, IOExternalMethodArguments * arguments);
316 
317 #endif /* XNU_KERNEL_PRIVATE */
318 
319 #if PRIVATE
320 public:
321 	static IOReturn registerFilterCallbacks(const struct io_filter_callbacks *callbacks, size_t size);
322 #endif /* PRIVATE */
323 
324 protected:
325 	static IOReturn sendAsyncResult(OSAsyncReference reference,
326 	    IOReturn result, void *args[], UInt32 numArgs);
327 	static void setAsyncReference(OSAsyncReference asyncRef,
328 	    mach_port_t wakePort,
329 	    void *callback, void *refcon);
330 
331 	static IOReturn sendAsyncResult64(OSAsyncReference64 reference,
332 	    IOReturn result, io_user_reference_t args[], UInt32 numArgs);
333 
334 /*!
335  *   @function sendAsyncResult64WithOptions
336  *   @abstract Send a notification as with sendAsyncResult, but with finite queueing.
337  *   @discussion IOUserClient::sendAsyncResult64() will infitely queue messages if the client
338  *           is not processing them in a timely fashion.  This variant will not, for simple
339  *           handling of situations where clients may be expected to stop processing messages.
340  */
341 	static IOReturn sendAsyncResult64WithOptions(OSAsyncReference64 reference,
342 	    IOReturn result, io_user_reference_t args[], UInt32 numArgs,
343 	    IOOptionBits options);
344 
345 	static void setAsyncReference64(OSAsyncReference64 asyncRef,
346 	    mach_port_t wakePort,
347 	    mach_vm_address_t callback, io_user_reference_t refcon);
348 
349 	static void setAsyncReference64(OSAsyncReference64 asyncRef,
350 	    mach_port_t wakePort,
351 	    mach_vm_address_t callback, io_user_reference_t refcon,
352 	    task_t task);
353 
354 public:
355 
356 	static IOReturn clientHasAuthorization( task_t task,
357 	    IOService * service );
358 
359 	static IOReturn clientHasPrivilege( void * securityToken,
360 	    const char * privilegeName );
361 
362 	static OSPtr<OSObject>  copyClientEntitlement(task_t task, const char *entitlement);
363 	static OSPtr<OSObject>  copyClientEntitlementVnode(struct vnode *vnode, off_t offset, const char *entitlement);
364 
365 	static OSPtr<OSDictionary>  copyClientEntitlements(task_t task);
366 	static OSPtr<OSDictionary>  copyClientEntitlementsVnode(struct vnode *vnode, off_t offset);
367 
368 /*!
369  *   @function releaseAsyncReference64
370  *   @abstract Release the mach_port_t reference held within the OSAsyncReference64 structure.
371  *   @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.
372  *   @param reference The reference passed to the subclass IOAsyncMethod, or externalMethod() in the IOExternalMethodArguments.asyncReference field.
373  *   @result A return code.
374  */
375 	static IOReturn releaseAsyncReference64(OSAsyncReference64 reference);
376 /*!
377  *   @function releaseNotificationPort
378  *   @abstract Release the mach_port_t passed to registerNotificationPort().
379  *   @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.
380  *   @param port The mach_port_t argument previously passed to the subclass implementation of registerNotificationPort().
381  *   @result A return code.
382  */
383 	static IOReturn releaseNotificationPort(mach_port_t port);
384 
385 	virtual bool init() APPLE_KEXT_OVERRIDE;
386 	virtual bool init( OSDictionary * dictionary ) APPLE_KEXT_OVERRIDE;
387 // Currently ignores the all args, just passes up to IOService::init()
388 	virtual bool initWithTask(
389 		task_t owningTask, void * securityToken, UInt32 type,
390 		OSDictionary * properties);
391 
392 	virtual bool initWithTask(
393 		task_t owningTask, void * securityToken, UInt32 type);
394 
395 	virtual void free() APPLE_KEXT_OVERRIDE;
396 
397 	virtual IOReturn clientClose( void );
398 	virtual IOReturn clientDied( void );
399 
400 	virtual IOService * getService( void );
401 
402 	MIG_SERVER_ROUTINE virtual IOReturn registerNotificationPort(
403 		mach_port_t port, UInt32 type, UInt32 refCon );
404 
405 	MIG_SERVER_ROUTINE virtual IOReturn getNotificationSemaphore( UInt32 notification_type,
406 	    semaphore_t * semaphore );
407 
408 	virtual IOReturn connectClient( IOUserClient * client );
409 
410 // memory will be released by user client when last map is destroyed
411 	virtual IOReturn clientMemoryForType( UInt32 type,
412 	    IOOptionBits * options,
413 	    IOMemoryDescriptor ** memory );
414 
415 	IOReturn clientMemoryForType( UInt32 type,
416 	    IOOptionBits * options,
417 	    OSSharedPtr<IOMemoryDescriptor>& memory );
418 
419 #if !__LP64__
420 private:
421 	APPLE_KEXT_COMPATIBILITY_VIRTUAL
422 	OSPtr<IOMemoryMap>  mapClientMemory( IOOptionBits type,
423 	    task_t task,
424 	    IOOptionBits mapFlags = kIOMapAnywhere,
425 	    IOVirtualAddress atAddress = 0 );
426 #endif
427 
428 	static IOReturn _sendAsyncResult64(OSAsyncReference64 reference,
429 	    IOReturn result, io_user_reference_t args[], UInt32 numArgs, IOOptionBits options);
430 public:
431 
432 /*!
433  *   @function removeMappingForDescriptor
434  *   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.
435  *   @param memory The memory descriptor instance previously returned by the implementation of clientMemoryForType().
436  *   @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.
437  */
438 	OSPtr<IOMemoryMap>  removeMappingForDescriptor(IOMemoryDescriptor * memory);
439 
440 /*!
441  *   @function exportObjectToClient
442  *   Make an arbitrary OSObject available to the client task.
443  *   @param task The task.
444  *   @param obj The object we want to export to the client.
445  *   @param clientObj Returned value is the client's port name.
446  */
447 	virtual IOReturn exportObjectToClient(task_t task,
448 	    LIBKERN_CONSUMED OSObject *obj, io_object_t *clientObj);
449 
450 #if KERNEL_PRIVATE
451 
452 /*!
453  *   @function copyPortNameForObjectInTask
454  *   Make an arbitrary OSObject available to the client task as a port name.
455  *   The port does not respond to any IOKit IPC calls.
456  *   @param task The task.
457  *   @param object The object we want to export to the client.
458  *   The port holds a reference on the object, this function does not consume any reference on the object.
459  *   @param port_name Returned value is the task's port name. It has one send right created by this function.
460  *   @result A return code.
461  */
462 	static IOReturn copyPortNameForObjectInTask(task_t task, OSObject *object,
463 	    mach_port_name_t * port_name);
464 
465 /*!
466  *   @function copyObjectForPortNameInTask
467  *   Look up an OSObject given a task's port name created with copyPortNameForObjectInTask().
468  *   @param task The task.
469  *   @param port_name The task's port name. This function does not consume any reference on the port name.
470  *   @param object If the port name is valid, a reference to the object is returned. It should be released by the caller.
471  *   @result A return code.
472  */
473 	static IOReturn copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name,
474 	    OSObject **object);
475 
476 	static IOReturn copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name,
477 	    OSSharedPtr<OSObject>& object);
478 
479 /*!
480  *   @function adjustPortNameReferencesInTask
481  *   Adjust the send rights for a port name created with copyPortNameForObjectInTask().
482  *   @param task The task.
483  *   @param port_name The task's port name.
484  *   @param delta Signed value change to the number of user references.
485  *   @result A return code.
486  */
487 	static IOReturn adjustPortNameReferencesInTask(task_t task, mach_port_name_t port_name, mach_port_delta_t delta);
488 
489 #define IOUC_COPYPORTNAMEFOROBJECTINTASK    1
490 
491 #endif /* KERNEL_PRIVATE */
492 
493 // Old methods for accessing method vector backward compatiblility only
494 	virtual IOExternalMethod *
495 	getExternalMethodForIndex( UInt32 index )
496 	APPLE_KEXT_DEPRECATED;
497 	virtual IOExternalAsyncMethod *
498 	getExternalAsyncMethodForIndex( UInt32 index )
499 	APPLE_KEXT_DEPRECATED;
500 
501 // Methods for accessing method vector.
502 	virtual IOExternalMethod *
503 	getTargetAndMethodForIndex(
504 		LIBKERN_RETURNS_NOT_RETAINED IOService ** targetP, UInt32 index );
505 	virtual IOExternalAsyncMethod *
506 	getAsyncTargetAndMethodForIndex(
507 		LIBKERN_RETURNS_NOT_RETAINED IOService ** targetP, UInt32 index );
508 	IOExternalMethod *
509 	getTargetAndMethodForIndex(
510 		OSSharedPtr<IOService>& targetP, UInt32 index );
511 	IOExternalAsyncMethod *
512 	getAsyncTargetAndMethodForIndex(
513 		OSSharedPtr<IOService>& targetP, UInt32 index );
514 
515 // Methods for accessing trap vector - old and new style
516 	virtual IOExternalTrap *
517 	getExternalTrapForIndex( UInt32 index )
518 	APPLE_KEXT_DEPRECATED;
519 
520 	virtual IOExternalTrap *
521 	getTargetAndTrapForIndex(
522 		LIBKERN_RETURNS_NOT_RETAINED IOService **targetP, UInt32 index );
523 };
524 
525 #if KERNEL_PRIVATE
526 
527 #define IOUSERCLIENT2022_SUPPORTED      1
528 
529 /*
530  *  IOUserClient2022 is a new superclass for an IOUserClient implementation to opt-in to
531  *  several security related best practices. The changes in behavior are:
532  *  - these properties must be present after ::start completes to control default single
533  *  threading calls to the IOUC from clients. It is recommended to set all values to true.
534  *
535  *  kIOUserClientDefaultLockingKey if kOSBooleanTrue
536  *  IOConnectMapMemory, IOConnectUnmapMemory, IOConnectAddClient, IOServiceClose
537  *  are single threaded and will not allow externalMethod to run concurrently.
538  *  Multiple threads can call externalMethod concurrently however.
539  *
540  *  kIOUserClientDefaultLockingSetPropertiesKey if kOSBooleanTrue
541  *  IORegistrySetProperties is also single threaded as above.
542  *
543  *  kIOUserClientDefaultLockingSingleThreadExternalMethodKey if kOSBooleanTrue
544  *  Only one thread may call externalMethod concurrently.
545  *
546  *  kIOUserClientEntitlementsKey
547  *  Entitlements required for a process to open the IOUC (see the key description).
548  *  It is recommended to require an entitlement if all calling processes are from Apple.
549  *
550  *  - the externalMethod override is required and must call dispatchExternalMethod() to
551  *  do basic argument checking before calling subclass code to implement the method.
552  *  dispatchExternalMethod() is called with an array of IOExternalMethodDispatch2022
553  *  elements and will index into the array for the given selector. The selector should
554  *  be adjusted accordingly, if needed, in the subclass' externalMethod().
555  *  The allowAsync field of IOExternalMethodDispatch2022 must be true to allow the
556  *  IOConnectCallAsyncMethod(etc) APIs to be used with the method.
557  *  If the checkEntitlement field of IOExternalMethodDispatch2022 is non-NULL, then
558  *  the calling process must have the named entitlement key, with a value of boolean true,
559  *  or kIOReturnNotPrivileged is returned. This should be used when per-selector entitlement
560  *  checks are required.  If you only need to check at the time the connection is created,
561  *  use kIOUserClientEntitlementsKey instead.
562  */
563 
564 class IOUserClient2022 : public IOUserClient
565 {
566 	OSDeclareDefaultStructors(IOUserClient2022);
567 
568 private:
569 	MIG_SERVER_ROUTINE virtual IOReturn
570 	externalMethod(uint32_t selector, IOExternalMethodArguments * arguments,
571 	    IOExternalMethodDispatch *dispatch = NULL,
572 	    OSObject *target = NULL, void *reference = NULL) APPLE_KEXT_OVERRIDE;
573 
574 protected:
575 	IOReturn
576 	dispatchExternalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * arguments,
577 	    const IOExternalMethodDispatch2022 dispatchArray[], size_t dispatchArrayCount,
578 	    OSObject * target, void * reference);
579 
580 public:
581 
582 	MIG_SERVER_ROUTINE virtual IOReturn
583 	externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * arguments) = 0;
584 
585 
586 	OSMetaClassDeclareReservedUnused(IOUserClient2022, 0);
587 	OSMetaClassDeclareReservedUnused(IOUserClient2022, 1);
588 	OSMetaClassDeclareReservedUnused(IOUserClient2022, 2);
589 	OSMetaClassDeclareReservedUnused(IOUserClient2022, 3);
590 };
591 
592 #endif /* KERNEL_PRIVATE */
593 
594 #ifdef XNU_KERNEL_PRIVATE
595 
596 class IOUserIterator : public OSIterator
597 {
598 	OSDeclareDefaultStructors(IOUserIterator);
599 public:
600 	OSObject    *       userIteratorObject;
601 	IOLock              lock;
602 
603 	static IOUserIterator * withIterator(LIBKERN_CONSUMED OSIterator * iter);
604 	virtual bool init( void ) APPLE_KEXT_OVERRIDE;
605 	virtual void free() APPLE_KEXT_OVERRIDE;
606 
607 	virtual void reset() APPLE_KEXT_OVERRIDE;
608 	virtual bool isValid() APPLE_KEXT_OVERRIDE;
609 	virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
610 	virtual OSObject * copyNextObject();
611 };
612 
613 class IOUserNotification : public IOUserIterator
614 {
615 	OSDeclareDefaultStructors(IOUserNotification);
616 
617 public:
618 
619 	virtual void free() APPLE_KEXT_OVERRIDE;
620 
621 	virtual void setNotification( IONotifier * obj );
622 
623 	virtual void reset() APPLE_KEXT_OVERRIDE;
624 	virtual bool isValid() APPLE_KEXT_OVERRIDE;
625 };
626 
627 #endif /* XNU_KERNEL_PRIVATE */
628 
629 #endif /* ! _IOKIT_IOUSERCLIENT_H */
630