xref: /xnu-8020.140.41/iokit/IOKit/IOUserClient.h (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
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 typedef IOReturn (*IOExternalMethodAction)(OSObject * target, void * reference,
156     IOExternalMethodArguments * arguments);
157 struct IOExternalMethodDispatch {
158 	IOExternalMethodAction function;
159 	uint32_t               checkScalarInputCount;
160 	uint32_t               checkStructureInputSize;
161 	uint32_t               checkScalarOutputCount;
162 	uint32_t               checkStructureOutputSize;
163 };
164 
165 enum {
166 #define IO_EXTERNAL_METHOD_ARGUMENTS_CURRENT_VERSION    2
167 	kIOExternalMethodArgumentsCurrentVersion = IO_EXTERNAL_METHOD_ARGUMENTS_CURRENT_VERSION
168 };
169 
170 #if PRIVATE
171 typedef uintptr_t io_filter_policy_t __kernel_ptr_semantics;
172 enum io_filter_type_t {
173 	io_filter_type_external_method       = 1,
174 	io_filter_type_external_async_method = 2,
175 	io_filter_type_trap                  = 3,
176 };
177 
178 typedef IOReturn (*io_filter_resolver_t) (task_t task, IOUserClient * client, uint32_t type, io_filter_policy_t *filterp);
179 typedef IOReturn (*io_filter_applier_t) (IOUserClient * client, io_filter_policy_t filter, io_filter_type_t type, uint32_t selector);
180 typedef void (*io_filter_release_t) (io_filter_policy_t filter);
181 struct io_filter_callbacks {
182 	const io_filter_resolver_t      io_filter_resolver;
183 	const io_filter_applier_t       io_filter_applier;
184 	const io_filter_release_t       io_filter_release;
185 };
186 struct IOUCFilterPolicy;
187 #endif /* PRIVATE */
188 
189 /*!
190  *   @class IOUserClient
191  *   @abstract   Provides a basis for communication between client applications and I/O Kit objects.
192  */
193 
194 class IOUserClient : public IOService
195 {
196 	OSDeclareAbstractStructorsWithDispatch(IOUserClient);
197 #if IOKITSTATS
198 	friend class IOStatistics;
199 #endif
200 
201 #if XNU_KERNEL_PRIVATE
202 public:
203 #else /* XNU_KERNEL_PRIVATE */
204 protected:
205 #endif /* !XNU_KERNEL_PRIVATE */
206 /*! @struct ExpansionData
207  *   @discussion This structure will be used to expand the capablilties of this class in the future.
208  */
209 	struct ExpansionData {
210 #if IOKITSTATS
211 		IOUserClientCounter *counter;
212 #else
213 		void *iokitstatsReserved;
214 #endif
215 #if PRIVATE
216 		IOUCFilterPolicy * filterPolicies;
217 #else
218 		void *iokitFilterReserved;
219 #endif
220 	};
221 
222 /*! @var reserved
223  *   Reserved for future use.  (Internal use only)
224  */
225 	APPLE_KEXT_WSHADOW_PUSH;
226 	ExpansionData * reserved;
227 	APPLE_KEXT_WSHADOW_POP;
228 
229 	bool reserve();
230 
231 #ifdef XNU_KERNEL_PRIVATE
232 
233 public:
234 	OSSet * mappings;
235 	UInt8   sharedInstance;
236 	UInt8   closed;
237 	UInt8   __ipcFinal;
238 	UInt8   messageAppSuspended:1,
239 	    defaultLocking:1,
240 	    __reservedA:6;
241 	volatile SInt32 __ipc;
242 	queue_head_t owners;
243 	IORWLock * lock;
244 	IOLock   * filterLock;
245 #if __LP64__
246 	void  * __reserved[3];
247 #else
248 	void  * __reserved[2];
249 #endif
250 
251 #else /* XNU_KERNEL_PRIVATE */
252 private:
253 	void  * __reserved[9];
254 #endif /* XNU_KERNEL_PRIVATE */
255 
256 public:
257 	MIG_SERVER_ROUTINE virtual IOReturn
258 	externalMethod(uint32_t selector, IOExternalMethodArguments *arguments,
259 	    IOExternalMethodDispatch *dispatch = NULL,
260 	    OSObject *target = NULL, void *reference = NULL);
261 
262 	MIG_SERVER_ROUTINE virtual IOReturn registerNotificationPort(
263 		mach_port_t port, UInt32 type, io_user_reference_t refCon);
264 
265 private:
266 #if __LP64__
267 	OSMetaClassDeclareReservedUnused(IOUserClient, 0);
268 	OSMetaClassDeclareReservedUnused(IOUserClient, 1);
269 #else
270 	OSMetaClassDeclareReservedUsedX86(IOUserClient, 0);
271 	OSMetaClassDeclareReservedUsedX86(IOUserClient, 1);
272 #endif
273 	OSMetaClassDeclareReservedUnused(IOUserClient, 2);
274 	OSMetaClassDeclareReservedUnused(IOUserClient, 3);
275 	OSMetaClassDeclareReservedUnused(IOUserClient, 4);
276 	OSMetaClassDeclareReservedUnused(IOUserClient, 5);
277 	OSMetaClassDeclareReservedUnused(IOUserClient, 6);
278 	OSMetaClassDeclareReservedUnused(IOUserClient, 7);
279 	OSMetaClassDeclareReservedUnused(IOUserClient, 8);
280 	OSMetaClassDeclareReservedUnused(IOUserClient, 9);
281 	OSMetaClassDeclareReservedUnused(IOUserClient, 10);
282 	OSMetaClassDeclareReservedUnused(IOUserClient, 11);
283 	OSMetaClassDeclareReservedUnused(IOUserClient, 12);
284 	OSMetaClassDeclareReservedUnused(IOUserClient, 13);
285 	OSMetaClassDeclareReservedUnused(IOUserClient, 14);
286 	OSMetaClassDeclareReservedUnused(IOUserClient, 15);
287 
288 #ifdef XNU_KERNEL_PRIVATE
289 
290 /* Available within xnu source only */
291 public:
292 	static void initialize( void );
293 	static void destroyUserReferences( OSObject * obj );
294 	static bool finalizeUserReferences( OSObject * obj );
295 	OSPtr<IOMemoryMap>  mapClientMemory64( IOOptionBits type,
296 	    task_t task,
297 	    IOOptionBits mapFlags = kIOMapAnywhere,
298 	    mach_vm_address_t atAddress = 0 );
299 	IOReturn registerOwner(task_t task);
300 	void     noMoreSenders(void);
301 	io_filter_policy_t filterForTask(task_t task, io_filter_policy_t addFilterPolicy);
302 #endif /* XNU_KERNEL_PRIVATE */
303 
304 #if PRIVATE
305 public:
306 	static IOReturn registerFilterCallbacks(const struct io_filter_callbacks *callbacks, size_t size);
307 #endif /* PRIVATE */
308 
309 protected:
310 	static IOReturn sendAsyncResult(OSAsyncReference reference,
311 	    IOReturn result, void *args[], UInt32 numArgs);
312 	static void setAsyncReference(OSAsyncReference asyncRef,
313 	    mach_port_t wakePort,
314 	    void *callback, void *refcon);
315 
316 	static IOReturn sendAsyncResult64(OSAsyncReference64 reference,
317 	    IOReturn result, io_user_reference_t args[], UInt32 numArgs);
318 
319 /*!
320  *   @function sendAsyncResult64WithOptions
321  *   @abstract Send a notification as with sendAsyncResult, but with finite queueing.
322  *   @discussion IOUserClient::sendAsyncResult64() will infitely queue messages if the client
323  *           is not processing them in a timely fashion.  This variant will not, for simple
324  *           handling of situations where clients may be expected to stop processing messages.
325  */
326 	static IOReturn sendAsyncResult64WithOptions(OSAsyncReference64 reference,
327 	    IOReturn result, io_user_reference_t args[], UInt32 numArgs,
328 	    IOOptionBits options);
329 
330 	static void setAsyncReference64(OSAsyncReference64 asyncRef,
331 	    mach_port_t wakePort,
332 	    mach_vm_address_t callback, io_user_reference_t refcon);
333 
334 	static void setAsyncReference64(OSAsyncReference64 asyncRef,
335 	    mach_port_t wakePort,
336 	    mach_vm_address_t callback, io_user_reference_t refcon,
337 	    task_t task);
338 
339 public:
340 
341 	static IOReturn clientHasAuthorization( task_t task,
342 	    IOService * service );
343 
344 	static IOReturn clientHasPrivilege( void * securityToken,
345 	    const char * privilegeName );
346 
347 	static OSPtr<OSObject>  copyClientEntitlement(task_t task, const char *entitlement);
348 	static OSPtr<OSObject>  copyClientEntitlementVnode(struct vnode *vnode, off_t offset, const char *entitlement);
349 
350 	static OSPtr<OSDictionary>  copyClientEntitlements(task_t task);
351 	static OSPtr<OSDictionary>  copyClientEntitlementsVnode(struct vnode *vnode, off_t offset);
352 
353 /*!
354  *   @function releaseAsyncReference64
355  *   @abstract Release the mach_port_t reference held within the OSAsyncReference64 structure.
356  *   @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.
357  *   @param reference The reference passed to the subclass IOAsyncMethod, or externalMethod() in the IOExternalMethodArguments.asyncReference field.
358  *   @result A return code.
359  */
360 	static IOReturn releaseAsyncReference64(OSAsyncReference64 reference);
361 /*!
362  *   @function releaseNotificationPort
363  *   @abstract Release the mach_port_t passed to registerNotificationPort().
364  *   @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.
365  *   @param port The mach_port_t argument previously passed to the subclass implementation of registerNotificationPort().
366  *   @result A return code.
367  */
368 	static IOReturn releaseNotificationPort(mach_port_t port);
369 
370 	virtual bool init() APPLE_KEXT_OVERRIDE;
371 	virtual bool init( OSDictionary * dictionary ) APPLE_KEXT_OVERRIDE;
372 // Currently ignores the all args, just passes up to IOService::init()
373 	virtual bool initWithTask(
374 		task_t owningTask, void * securityToken, UInt32 type,
375 		OSDictionary * properties);
376 
377 	virtual bool initWithTask(
378 		task_t owningTask, void * securityToken, UInt32 type);
379 
380 	virtual void free() APPLE_KEXT_OVERRIDE;
381 
382 	virtual IOReturn clientClose( void );
383 	virtual IOReturn clientDied( void );
384 
385 	virtual IOService * getService( void );
386 
387 	MIG_SERVER_ROUTINE virtual IOReturn registerNotificationPort(
388 		mach_port_t port, UInt32 type, UInt32 refCon );
389 
390 	MIG_SERVER_ROUTINE virtual IOReturn getNotificationSemaphore( UInt32 notification_type,
391 	    semaphore_t * semaphore );
392 
393 	virtual IOReturn connectClient( IOUserClient * client );
394 
395 // memory will be released by user client when last map is destroyed
396 	virtual IOReturn clientMemoryForType( UInt32 type,
397 	    IOOptionBits * options,
398 	    IOMemoryDescriptor ** memory );
399 
400 	IOReturn clientMemoryForType( UInt32 type,
401 	    IOOptionBits * options,
402 	    OSSharedPtr<IOMemoryDescriptor>& memory );
403 
404 #if !__LP64__
405 private:
406 	APPLE_KEXT_COMPATIBILITY_VIRTUAL
407 	OSPtr<IOMemoryMap>  mapClientMemory( IOOptionBits type,
408 	    task_t task,
409 	    IOOptionBits mapFlags = kIOMapAnywhere,
410 	    IOVirtualAddress atAddress = 0 );
411 #endif
412 
413 	static IOReturn _sendAsyncResult64(OSAsyncReference64 reference,
414 	    IOReturn result, io_user_reference_t args[], UInt32 numArgs, IOOptionBits options);
415 public:
416 
417 /*!
418  *   @function removeMappingForDescriptor
419  *   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.
420  *   @param memory The memory descriptor instance previously returned by the implementation of clientMemoryForType().
421  *   @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.
422  */
423 	OSPtr<IOMemoryMap>  removeMappingForDescriptor(IOMemoryDescriptor * memory);
424 
425 /*!
426  *   @function exportObjectToClient
427  *   Make an arbitrary OSObject available to the client task.
428  *   @param task The task.
429  *   @param obj The object we want to export to the client.
430  *   @param clientObj Returned value is the client's port name.
431  */
432 	virtual IOReturn exportObjectToClient(task_t task,
433 	    LIBKERN_CONSUMED OSObject *obj, io_object_t *clientObj);
434 
435 #if KERNEL_PRIVATE
436 
437 /*!
438  *   @function copyPortNameForObjectInTask
439  *   Make an arbitrary OSObject available to the client task as a port name.
440  *   The port does not respond to any IOKit IPC calls.
441  *   @param task The task.
442  *   @param object The object we want to export to the client.
443  *   The port holds a reference on the object, this function does not consume any reference on the object.
444  *   @param port_name Returned value is the task's port name. It has one send right created by this function.
445  *   @result A return code.
446  */
447 	static IOReturn copyPortNameForObjectInTask(task_t task, OSObject *object,
448 	    mach_port_name_t * port_name);
449 
450 /*!
451  *   @function copyObjectForPortNameInTask
452  *   Look up an OSObject given a task's port name created with copyPortNameForObjectInTask().
453  *   @param task The task.
454  *   @param port_name The task's port name. This function does not consume any reference on the port name.
455  *   @param object If the port name is valid, a reference to the object is returned. It should be released by the caller.
456  *   @result A return code.
457  */
458 	static IOReturn copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name,
459 	    OSObject **object);
460 
461 	static IOReturn copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name,
462 	    OSSharedPtr<OSObject>& object);
463 
464 /*!
465  *   @function adjustPortNameReferencesInTask
466  *   Adjust the send rights for a port name created with copyPortNameForObjectInTask().
467  *   @param task The task.
468  *   @param port_name The task's port name.
469  *   @param delta Signed value change to the number of user references.
470  *   @result A return code.
471  */
472 	static IOReturn adjustPortNameReferencesInTask(task_t task, mach_port_name_t port_name, mach_port_delta_t delta);
473 
474 #define IOUC_COPYPORTNAMEFOROBJECTINTASK    1
475 
476 #endif /* KERNEL_PRIVATE */
477 
478 // Old methods for accessing method vector backward compatiblility only
479 	virtual IOExternalMethod *
480 	getExternalMethodForIndex( UInt32 index )
481 	APPLE_KEXT_DEPRECATED;
482 	virtual IOExternalAsyncMethod *
483 	getExternalAsyncMethodForIndex( UInt32 index )
484 	APPLE_KEXT_DEPRECATED;
485 
486 // Methods for accessing method vector.
487 	virtual IOExternalMethod *
488 	getTargetAndMethodForIndex(
489 		LIBKERN_RETURNS_NOT_RETAINED IOService ** targetP, UInt32 index );
490 	virtual IOExternalAsyncMethod *
491 	getAsyncTargetAndMethodForIndex(
492 		LIBKERN_RETURNS_NOT_RETAINED IOService ** targetP, UInt32 index );
493 	IOExternalMethod *
494 	getTargetAndMethodForIndex(
495 		OSSharedPtr<IOService>& targetP, UInt32 index );
496 	IOExternalAsyncMethod *
497 	getAsyncTargetAndMethodForIndex(
498 		OSSharedPtr<IOService>& targetP, UInt32 index );
499 
500 // Methods for accessing trap vector - old and new style
501 	virtual IOExternalTrap *
502 	getExternalTrapForIndex( UInt32 index )
503 	APPLE_KEXT_DEPRECATED;
504 
505 	virtual IOExternalTrap *
506 	getTargetAndTrapForIndex(
507 		LIBKERN_RETURNS_NOT_RETAINED IOService **targetP, UInt32 index );
508 };
509 
510 #ifdef XNU_KERNEL_PRIVATE
511 extern "C" void IOMachPortDestroyUserReferences(OSObject * obj, natural_t type);
512 
513 class IOUserIterator : public OSIterator
514 {
515 	OSDeclareDefaultStructors(IOUserIterator);
516 public:
517 	OSObject    *       userIteratorObject;
518 	IOLock      *       lock;
519 
520 	static IOUserIterator * withIterator(LIBKERN_CONSUMED OSIterator * iter);
521 	virtual bool init( void ) APPLE_KEXT_OVERRIDE;
522 	virtual void free() APPLE_KEXT_OVERRIDE;
523 
524 	virtual void reset() APPLE_KEXT_OVERRIDE;
525 	virtual bool isValid() APPLE_KEXT_OVERRIDE;
526 	virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
527 	virtual OSObject * copyNextObject();
528 };
529 
530 class IOUserNotification : public IOUserIterator
531 {
532 	OSDeclareDefaultStructors(IOUserNotification);
533 
534 public:
535 
536 	virtual void free() APPLE_KEXT_OVERRIDE;
537 
538 	virtual void setNotification( IONotifier * obj );
539 
540 	virtual void reset() APPLE_KEXT_OVERRIDE;
541 	virtual bool isValid() APPLE_KEXT_OVERRIDE;
542 };
543 
544 #endif /* XNU_KERNEL_PRIVATE */
545 
546 #endif /* ! _IOKIT_IOUSERCLIENT_H */
547