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
43enum{
44 kIOKitUserServerClientType = 0x99000003,
45};
46
47enum{
48 kIOUserServerMethodRegisterClass = 0x0001000,
49 kIOUserServerMethodStart = 0x0001001,
50 kIOUserServerMethodRegister = 0x0001002,
51};
52
53
54/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
55
56#define OSObject_Instantiate_ID 0x0000000100000001ULL
57
58enum {
59 kOSObjectRPCRemote = 0x00000001,
60 kOSObjectRPCKernel = 0x00000002,
61};
62
63struct OSObject_Instantiate_Msg_Content {
64 IORPCMessage __hdr;
65 OSObjectRef __object;
66};
67
68#pragma pack(push, 4)
69struct 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)
80struct OSObject_Instantiate_Msg {
81 IORPCMessageMach mach;
82 mach_msg_port_descriptor_t __object__descriptor;
83 OSObject_Instantiate_Msg_Content content;
84};
85struct OSObject_Instantiate_Rpl {
86 IORPCMessageMach mach;
87 OSObject_Instantiate_Rpl_Content content;
88};
89#pragma pack()
90
91typedef 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>
108class IOUserServer;
109class OSUserMetaClass;
110class OSObject;
111class IODispatchQueue;
112class IODispatchSource;
113class IOInterruptDispatchSource;
114class IOTimerDispatchSource;
115class IOUserServerCheckInToken;
116struct IOPStrings;
117
118struct 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
139extern IOLock * gIOUserServerLock;
140
141typedef struct ipc_kmsg * ipc_kmsg_t;
142
143/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
144
145namespace IOServicePH
146{
147void serverAdd(IOUserServer * server);
148void serverRemove(IOUserServer * server);
149void serverAck(IOUserServer * server);
150bool serverSlept(void);
151void systemHalt(int howto);
152bool checkPMReady(void);
153};
154
155/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
156
157class 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;
176public:
177 kern_allocation_name_t fAllocationName;
178 task_t fOwningTask;
179 os_reason_t fTaskCrashReason;
180
181public:
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
273typedef void (*IOUserServerCheckInCancellationHandler)(class IOUserServerCheckInToken*, void*);
274
275// OSObject wrapper around IOUserServerCheckInCancellationHandler
276class _IOUserServerCheckInCancellationHandler : public OSObject {
277 OSDeclareDefaultStructors(_IOUserServerCheckInCancellationHandler);
278public:
279 static _IOUserServerCheckInCancellationHandler *
280 withHandler(IOUserServerCheckInCancellationHandler handler, void * args);
281
282 void call(IOUserServerCheckInToken * token);
283private:
284 IOUserServerCheckInCancellationHandler fHandler;
285 void * fHandlerArgs;
286};
287
288class IOUserServerCheckInToken : public OSObject
289{
290 enum State {
291 kIOUserServerCheckInPending,
292 kIOUserServerCheckInCanceled,
293 kIOUserServerCheckInComplete,
294 };
295
296 OSDeclareDefaultStructors(IOUserServerCheckInToken);
297public:
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
330private:
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
339private:
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
350extern "C" kern_return_t
351IOUserServerUEXTTrap(OSObject * object, void * p1, void * p2, void * p3, void * p4, void * p5, void * p6);
352
353extern "C" void
354IOUserServerRecordExitReason(task_t task, os_reason_t reason);
355
356#endif /* XNU_KERNEL_PRIVATE */
357#endif /* _IOUSERSERVER_H */
358