1 | /* |
2 | * Copyright (c) 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 | #ifndef _IOUSERSERVER_H |
31 | #define _IOUSERSERVER_H |
32 | |
33 | #include <IOKit/IORPC.h> |
34 | |
35 | #define kIOUserServerClassKey "IOUserServer" |
36 | #define kIOUserServerNameKey "IOUserServerName" |
37 | #define kIOUserServerTagKey "IOUserServerTag" |
38 | // the expected cdhash value of the userspace driver executable |
39 | #define kIOUserServerCDHashKey "IOUserServerCDHash" |
40 | |
41 | #if DRIVERKIT_PRIVATE |
42 | |
43 | enum{ |
44 | kIOKitUserServerClientType = 0x99000003, |
45 | }; |
46 | |
47 | enum{ |
48 | kIOUserServerMethodRegisterClass = 0x0001000, |
49 | kIOUserServerMethodStart = 0x0001001, |
50 | kIOUserServerMethodRegister = 0x0001002, |
51 | }; |
52 | |
53 | |
54 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
55 | |
56 | #define OSObject_Instantiate_ID 0x0000000100000001ULL |
57 | |
58 | enum { |
59 | kOSObjectRPCRemote = 0x00000001, |
60 | kOSObjectRPCKernel = 0x00000002, |
61 | }; |
62 | |
63 | struct OSObject_Instantiate_Msg_Content { |
64 | IORPCMessage __hdr; |
65 | OSObjectRef __object; |
66 | }; |
67 | |
68 | #pragma pack(push, 4) |
69 | struct OSObject_Instantiate_Rpl_Content { |
70 | IORPCMessage __hdr; |
71 | kern_return_t __result; |
72 | uint32_t __pad; |
73 | uint64_t flags; |
74 | char classname[128]; |
75 | uint64_t methods[0]; |
76 | }; |
77 | #pragma pack(pop) |
78 | |
79 | #pragma pack(4) |
80 | struct OSObject_Instantiate_Msg { |
81 | IORPCMessageMach mach; |
82 | mach_msg_port_descriptor_t __object__descriptor; |
83 | OSObject_Instantiate_Msg_Content content; |
84 | }; |
85 | struct OSObject_Instantiate_Rpl { |
86 | IORPCMessageMach mach; |
87 | OSObject_Instantiate_Rpl_Content content; |
88 | }; |
89 | #pragma pack() |
90 | |
91 | typedef uint64_t IOTrapMessageBuffer[256]; |
92 | |
93 | #endif /* DRIVERKIT_PRIVATE */ |
94 | |
95 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
96 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
97 | |
98 | #ifdef XNU_KERNEL_PRIVATE |
99 | |
100 | #include <IOKit/IOService.h> |
101 | #include <IOKit/IOUserClient.h> |
102 | #include <DriverKit/IOUserServer.h> |
103 | #include <libkern/c++/OSPtr.h> |
104 | #include <libkern/c++/OSKext.h> |
105 | #include <libkern/c++/OSBoundedArray.h> |
106 | #include <libkern/c++/OSBoundedArrayRef.h> |
107 | #include <sys/reason.h> |
108 | class IOUserServer; |
109 | class OSUserMetaClass; |
110 | class OSObject; |
111 | class IODispatchQueue; |
112 | class IODispatchSource; |
113 | class IOInterruptDispatchSource; |
114 | class IOTimerDispatchSource; |
115 | class IOUserServerCheckInToken; |
116 | struct IOPStrings; |
117 | |
118 | struct OSObjectUserVars { |
119 | IOUserServer * userServer; |
120 | OSBoundedArrayRef<IODispatchQueue *> queueArray; |
121 | OSUserMetaClass * userMeta; |
122 | OSArray * openProviders; |
123 | IOService * controllingDriver; |
124 | unsigned long willPowerState; |
125 | bool willTerminate; |
126 | bool didTerminate; |
127 | bool serverDied; |
128 | bool started; |
129 | bool stopped; |
130 | bool userServerPM; |
131 | bool willPower; |
132 | bool powerState; |
133 | bool resetPowerOnWake; |
134 | bool deferredRegisterService; |
135 | uint32_t powerOverride; |
136 | IOLock * uvarsLock; |
137 | }; |
138 | |
139 | extern IOLock * gIOUserServerLock; |
140 | |
141 | typedef struct ipc_kmsg * ipc_kmsg_t; |
142 | |
143 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
144 | |
145 | namespace IOServicePH |
146 | { |
147 | void serverAdd(IOUserServer * server); |
148 | void serverRemove(IOUserServer * server); |
149 | void serverAck(IOUserServer * server); |
150 | bool serverSlept(void); |
151 | void systemHalt(int howto); |
152 | bool checkPMReady(void); |
153 | }; |
154 | |
155 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
156 | |
157 | class IOUserServer : public IOUserClient2022 |
158 | { |
159 | OSDeclareDefaultStructorsWithDispatch(IOUserServer); |
160 | |
161 | IOLock * fLock; |
162 | IOSimpleLock * fInterruptLock; |
163 | OSDictionary * fEntitlements; |
164 | OSDictionary * fClasses; |
165 | IODispatchQueue * fRootQueue; |
166 | OSArray * fServices; |
167 | |
168 | uint8_t fRootNotifier; |
169 | uint8_t fSystemPowerAck; |
170 | uint8_t fSystemOff; |
171 | IOUserServerCheckInToken * fCheckInToken; |
172 | OSDextStatistics * fStatistics; |
173 | bool fPlatformDriver; |
174 | OSString * fTeamIdentifier; |
175 | unsigned int fCSValidationCategory; |
176 | public: |
177 | kern_allocation_name_t fAllocationName; |
178 | task_t fOwningTask; |
179 | os_reason_t fTaskCrashReason; |
180 | |
181 | public: |
182 | |
183 | /* |
184 | * Launch a dext with the specified bundle ID, server name, and server tag. If reuseIfExists is true, this will attempt to find an existing IOUserServer instance or |
185 | * a pending dext launch with the same server name. |
186 | * |
187 | * Returns a IOUserServer instance if one was found, or a token to track the pending dext launch. If both are NULL, then launching the dext failed. |
188 | */ |
189 | static IOUserServer * launchUserServer(OSString * bundleID, const OSSymbol * serverName, OSNumber * serverTag, bool reuseIfExists, IOUserServerCheckInToken ** token, OSData *serverDUI); |
190 | static IOUserClient * withTask(task_t owningTask); |
191 | virtual IOReturn clientClose(void) APPLE_KEXT_OVERRIDE; |
192 | virtual bool finalize(IOOptionBits options) APPLE_KEXT_OVERRIDE; |
193 | virtual void stop(IOService * provider) APPLE_KEXT_OVERRIDE; |
194 | virtual void free() APPLE_KEXT_OVERRIDE; |
195 | |
196 | virtual IOReturn setProperties(OSObject * properties) APPLE_KEXT_OVERRIDE; |
197 | virtual IOReturn externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * args) APPLE_KEXT_OVERRIDE; |
198 | static IOReturn externalMethodStart(OSObject * target, void * reference, IOExternalMethodArguments * arguments); |
199 | static IOReturn externalMethodRegisterClass(OSObject * target, void * reference, IOExternalMethodArguments * arguments); |
200 | |
201 | virtual IOExternalTrap * getTargetAndTrapForIndex(IOService ** targetP, UInt32 index) APPLE_KEXT_OVERRIDE; |
202 | |
203 | IOReturn serviceAttach(IOService * service, IOService * provider); |
204 | IOReturn serviceStop(IOService * service, IOService * provider); |
205 | void serviceFree(IOService * service); |
206 | IOReturn serviceStarted(IOService * service, IOService * provider, bool result); |
207 | static void serviceWillTerminate(IOService * client, IOService * provider, IOOptionBits options); |
208 | static void serviceDidTerminate(IOService * client, IOService * provider, IOOptionBits options, bool * defer); |
209 | static void serviceDidStop(IOService * client, IOService * provider); |
210 | IOReturn serviceOpen(IOService * provider, IOService * client); |
211 | IOReturn serviceClose(IOService * provider, IOService * client); |
212 | IOReturn serviceJoinPMTree(IOService * service); |
213 | IOReturn serviceSetPowerState(IOService * controllingDriver, IOService * service, IOPMPowerFlags flags, IOPMPowerStateIndex powerState); |
214 | IOReturn serviceNewUserClient(IOService * service, task_t owningTask, void * securityID, |
215 | uint32_t type, OSDictionary * properties, IOUserClient ** handler); |
216 | IOReturn serviceNewUserClient(IOService * service, task_t owningTask, void * securityID, |
217 | uint32_t type, OSDictionary * properties, OSSharedPtr<IOUserClient>& handler); |
218 | IOReturn exit(const char * reason); |
219 | IOReturn kill(const char * reason); |
220 | |
221 | bool serviceMatchesCheckInToken(IOUserServerCheckInToken *token); |
222 | bool checkEntitlements(IOService * provider, IOService * dext); |
223 | bool checkEntitlements(LIBKERN_CONSUMED OSObject * prop, |
224 | IOService * provider, IOService * dext); |
225 | static bool checkEntitlements(OSDictionary * entitlements, LIBKERN_CONSUMED OSObject * prop, |
226 | IOService * provider, IOService * dext); |
227 | |
228 | void setTaskLoadTag(OSKext *kext); |
229 | void setDriverKitUUID(OSKext *kext); |
230 | void setDriverKitStatistics(OSKext *kext); |
231 | void setCheckInToken(IOUserServerCheckInToken *token); |
232 | void systemPower(bool powerOff); |
233 | void systemHalt(int howto); |
234 | static void powerSourceChanged(bool acAttached); |
235 | bool checkPMReady(); |
236 | |
237 | IOReturn setPowerState(unsigned long state, IOService * service) APPLE_KEXT_OVERRIDE; |
238 | IOReturn powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service) APPLE_KEXT_OVERRIDE; |
239 | IOReturn powerStateDidChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service) APPLE_KEXT_OVERRIDE; |
240 | |
241 | IOPStrings * copyInStringArray(const char * string, uint32_t userSize); |
242 | uint32_t stringArrayIndex(IOPStrings * array, const char * look); |
243 | IOReturn registerClass(OSClassDescription * desc, uint32_t size, OSUserMetaClass ** cls); |
244 | IOReturn registerClass(OSClassDescription * desc, uint32_t size, OSSharedPtr<OSUserMetaClass>& cls); |
245 | IOReturn setRootQueue(IODispatchQueue * queue); |
246 | |
247 | OSObjectUserVars * varsForObject(OSObject * obj); |
248 | LIBKERN_RETURNS_NOT_RETAINED IODispatchQueue * queueForObject(OSObject * obj, uint64_t msgid); |
249 | |
250 | static ipc_port_t copySendRightForObject(OSObject * object, natural_t /* ipc_kobject_type_t */ type); |
251 | static OSObject * copyObjectForSendRight(ipc_port_t port, natural_t /* ipc_kobject_type_t */ type); |
252 | |
253 | IOReturn copyOutObjects(IORPCMessageMach * mach, IORPCMessage * message, |
254 | size_t size, bool consume); |
255 | IOReturn copyInObjects(IORPCMessageMach * mach, IORPCMessage * message, |
256 | size_t size, bool copyObjects, bool consumePorts); |
257 | |
258 | IOReturn consumeObjects(IORPCMessage * message, size_t messageSize); |
259 | |
260 | IOReturn objectInstantiate(OSObject * obj, IORPC rpc, IORPCMessage * message); |
261 | IOReturn kernelDispatch(OSObject * obj, IORPC rpc); |
262 | static OSObject * target(OSAction * action, IORPCMessage * message); |
263 | |
264 | IOReturn rpc(IORPC rpc); |
265 | IOReturn server(ipc_kmsg_t requestkmsg, IORPCMessage * message, ipc_kmsg_t * preply); |
266 | kern_return_t waitInterruptTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6); |
267 | static bool shouldLeakObjects(); |
268 | static void beginLeakingObjects(); |
269 | bool isPlatformDriver(); |
270 | int getCSValidationCategory(); |
271 | }; |
272 | |
273 | typedef void (*IOUserServerCheckInCancellationHandler)(class IOUserServerCheckInToken*, void*); |
274 | |
275 | // OSObject wrapper around IOUserServerCheckInCancellationHandler |
276 | class _IOUserServerCheckInCancellationHandler : public OSObject { |
277 | OSDeclareDefaultStructors(_IOUserServerCheckInCancellationHandler); |
278 | public: |
279 | static _IOUserServerCheckInCancellationHandler * |
280 | withHandler(IOUserServerCheckInCancellationHandler handler, void * args); |
281 | |
282 | void call(IOUserServerCheckInToken * token); |
283 | private: |
284 | IOUserServerCheckInCancellationHandler fHandler; |
285 | void * fHandlerArgs; |
286 | }; |
287 | |
288 | class IOUserServerCheckInToken : public OSObject |
289 | { |
290 | enum State { |
291 | kIOUserServerCheckInPending, |
292 | kIOUserServerCheckInCanceled, |
293 | kIOUserServerCheckInComplete, |
294 | }; |
295 | |
296 | OSDeclareDefaultStructors(IOUserServerCheckInToken); |
297 | public: |
298 | virtual void free() APPLE_KEXT_OVERRIDE; |
299 | |
300 | /* |
301 | * Cancel all pending dext launches. |
302 | */ |
303 | static void cancelAll(); |
304 | |
305 | /* |
306 | * Set handler to be invoked when launch is cancelled. Returns an wrapper object for the handler to be released by the caller. |
307 | * The handler always runs under the lock for this IOUserServerCheckInToken. |
308 | * The returned object can be used with removeCancellationHandler(). |
309 | */ |
310 | _IOUserServerCheckInCancellationHandler * setCancellationHandler(IOUserServerCheckInCancellationHandler handler, void *handlerArgs); |
311 | |
312 | /* |
313 | * Remove previously set cancellation handler. |
314 | */ |
315 | void removeCancellationHandler(_IOUserServerCheckInCancellationHandler * handler); |
316 | |
317 | /* |
318 | * Cancel the launch |
319 | */ |
320 | void cancel(); |
321 | |
322 | /* |
323 | * Mark launch as completed. |
324 | */ |
325 | void complete(); |
326 | |
327 | const OSSymbol * copyServerName() const; |
328 | OSNumber * copyServerTag() const; |
329 | |
330 | private: |
331 | static IOUserServerCheckInToken * findExistingToken(const OSSymbol * serverName); |
332 | bool init(const OSSymbol * userServerName, OSNumber * serverTag, OSKext *driverKext, OSData *serverDUI); |
333 | bool dextTerminate(void); |
334 | |
335 | friend class IOUserServer; |
336 | |
337 | |
338 | |
339 | private: |
340 | IOUserServerCheckInToken::State fState; |
341 | size_t fPendingCount; |
342 | const OSSymbol * fServerName; |
343 | const OSSymbol * fExecutableName; |
344 | OSNumber * fServerTag; |
345 | OSSet * fHandlers; |
346 | OSString * fKextBundleID; |
347 | bool fNeedDextDec; |
348 | }; |
349 | |
350 | extern "C" kern_return_t |
351 | IOUserServerUEXTTrap(OSObject * object, void * p1, void * p2, void * p3, void * p4, void * p5, void * p6); |
352 | |
353 | extern "C" void |
354 | IOUserServerRecordExitReason(task_t task, os_reason_t reason); |
355 | |
356 | #endif /* XNU_KERNEL_PRIVATE */ |
357 | #endif /* _IOUSERSERVER_H */ |
358 | |