1*e3723e1fSApple OSS Distributions /*
2*e3723e1fSApple OSS Distributions * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
3*e3723e1fSApple OSS Distributions *
4*e3723e1fSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*e3723e1fSApple OSS Distributions *
6*e3723e1fSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*e3723e1fSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*e3723e1fSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*e3723e1fSApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*e3723e1fSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*e3723e1fSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*e3723e1fSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*e3723e1fSApple OSS Distributions * terms of an Apple operating system software license agreement.
14*e3723e1fSApple OSS Distributions *
15*e3723e1fSApple OSS Distributions * Please obtain a copy of the License at
16*e3723e1fSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*e3723e1fSApple OSS Distributions *
18*e3723e1fSApple OSS Distributions * The Original Code and all software distributed under the License are
19*e3723e1fSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*e3723e1fSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*e3723e1fSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*e3723e1fSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*e3723e1fSApple OSS Distributions * Please see the License for the specific language governing rights and
24*e3723e1fSApple OSS Distributions * limitations under the License.
25*e3723e1fSApple OSS Distributions *
26*e3723e1fSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*e3723e1fSApple OSS Distributions */
28*e3723e1fSApple OSS Distributions
29*e3723e1fSApple OSS Distributions extern "C" {
30*e3723e1fSApple OSS Distributions #include <libkern/OSKextLibPrivate.h>
31*e3723e1fSApple OSS Distributions #include <libkern/mkext.h>
32*e3723e1fSApple OSS Distributions };
33*e3723e1fSApple OSS Distributions
34*e3723e1fSApple OSS Distributions #include <kern/telemetry.h>
35*e3723e1fSApple OSS Distributions #include <libkern/c++/OSContainers.h>
36*e3723e1fSApple OSS Distributions #include <libkern/c++/OSKext.h>
37*e3723e1fSApple OSS Distributions #include <libkern/OSKextLib.h>
38*e3723e1fSApple OSS Distributions #include <libkern/OSKextLibPrivate.h>
39*e3723e1fSApple OSS Distributions #include <vm/vm_kern_xnu.h>
40*e3723e1fSApple OSS Distributions #include <vm/vm_map_xnu.h>
41*e3723e1fSApple OSS Distributions
42*e3723e1fSApple OSS Distributions extern "C" {
43*e3723e1fSApple OSS Distributions #if PRAGMA_MARK
44*e3723e1fSApple OSS Distributions #pragma mark C-based kext interface (loading/loaded kexts only)
45*e3723e1fSApple OSS Distributions #endif
46*e3723e1fSApple OSS Distributions /*********************************************************************
47*e3723e1fSApple OSS Distributions *********************************************************************/
48*e3723e1fSApple OSS Distributions kern_return_t
OSKextLoadKextWithIdentifier(const char * bundle_id)49*e3723e1fSApple OSS Distributions OSKextLoadKextWithIdentifier(const char * bundle_id)
50*e3723e1fSApple OSS Distributions {
51*e3723e1fSApple OSS Distributions return OSKext::loadKextWithIdentifier(bundle_id);
52*e3723e1fSApple OSS Distributions }
53*e3723e1fSApple OSS Distributions
54*e3723e1fSApple OSS Distributions uint32_t OSKextGetLoadTagForIdentifier(const char * kextIdentifier);
55*e3723e1fSApple OSS Distributions /*********************************************************************
56*e3723e1fSApple OSS Distributions *********************************************************************/
57*e3723e1fSApple OSS Distributions uint32_t
OSKextGetLoadTagForIdentifier(const char * kextIdentifier)58*e3723e1fSApple OSS Distributions OSKextGetLoadTagForIdentifier(const char * kextIdentifier)
59*e3723e1fSApple OSS Distributions {
60*e3723e1fSApple OSS Distributions uint32_t result = kOSKextInvalidLoadTag;
61*e3723e1fSApple OSS Distributions OSKext * theKext = NULL; // must release
62*e3723e1fSApple OSS Distributions
63*e3723e1fSApple OSS Distributions if (!kextIdentifier) {
64*e3723e1fSApple OSS Distributions goto finish;
65*e3723e1fSApple OSS Distributions }
66*e3723e1fSApple OSS Distributions
67*e3723e1fSApple OSS Distributions theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
68*e3723e1fSApple OSS Distributions if (theKext && theKext->isLoaded()) {
69*e3723e1fSApple OSS Distributions result = theKext->getLoadTag();
70*e3723e1fSApple OSS Distributions }
71*e3723e1fSApple OSS Distributions finish:
72*e3723e1fSApple OSS Distributions if (theKext) {
73*e3723e1fSApple OSS Distributions theKext->release();
74*e3723e1fSApple OSS Distributions }
75*e3723e1fSApple OSS Distributions return result;
76*e3723e1fSApple OSS Distributions }
77*e3723e1fSApple OSS Distributions
78*e3723e1fSApple OSS Distributions /*********************************************************************
79*e3723e1fSApple OSS Distributions *********************************************************************/
80*e3723e1fSApple OSS Distributions
81*e3723e1fSApple OSS Distributions // FIXME: Implementation of this function is hidden from the static analyzer.
82*e3723e1fSApple OSS Distributions // The analyzer is worried about the lack of release and suggests
83*e3723e1fSApple OSS Distributions // refactoring the code into the typical non-owning container pattern.
84*e3723e1fSApple OSS Distributions // Feel free to remove the #ifndef and address the warning!
85*e3723e1fSApple OSS Distributions #ifndef __clang_analyzer__
86*e3723e1fSApple OSS Distributions OSReturn
OSKextRetainKextWithLoadTag(uint32_t loadTag)87*e3723e1fSApple OSS Distributions OSKextRetainKextWithLoadTag(uint32_t loadTag)
88*e3723e1fSApple OSS Distributions {
89*e3723e1fSApple OSS Distributions OSReturn result = kOSKextReturnNotFound;
90*e3723e1fSApple OSS Distributions OSKext * theKext = NULL;// do not release; as this function is a retain
91*e3723e1fSApple OSS Distributions
92*e3723e1fSApple OSS Distributions if (loadTag == kOSKextInvalidLoadTag) {
93*e3723e1fSApple OSS Distributions result = kOSKextReturnInvalidArgument;
94*e3723e1fSApple OSS Distributions goto finish;
95*e3723e1fSApple OSS Distributions }
96*e3723e1fSApple OSS Distributions theKext = OSKext::lookupKextWithLoadTag(loadTag);
97*e3723e1fSApple OSS Distributions if (theKext) {
98*e3723e1fSApple OSS Distributions result = kOSReturnSuccess;
99*e3723e1fSApple OSS Distributions
100*e3723e1fSApple OSS Distributions OSKextLog(theKext,
101*e3723e1fSApple OSS Distributions kOSKextLogDebugLevel |
102*e3723e1fSApple OSS Distributions kOSKextLogKextBookkeepingFlag,
103*e3723e1fSApple OSS Distributions "Kext %s (load tag %d) has been retained.",
104*e3723e1fSApple OSS Distributions theKext->getIdentifierCString(),
105*e3723e1fSApple OSS Distributions loadTag);
106*e3723e1fSApple OSS Distributions
107*e3723e1fSApple OSS Distributions /* Call this after so a log message about autounload comes second.
108*e3723e1fSApple OSS Distributions */
109*e3723e1fSApple OSS Distributions theKext->setAutounloadEnabled(true);
110*e3723e1fSApple OSS Distributions } else {
111*e3723e1fSApple OSS Distributions OSKextLog(theKext,
112*e3723e1fSApple OSS Distributions kOSKextLogErrorLevel |
113*e3723e1fSApple OSS Distributions kOSKextLogKextBookkeepingFlag,
114*e3723e1fSApple OSS Distributions "Can't retain kext with load tag %d - no such kext is loaded.",
115*e3723e1fSApple OSS Distributions loadTag);
116*e3723e1fSApple OSS Distributions }
117*e3723e1fSApple OSS Distributions finish:
118*e3723e1fSApple OSS Distributions return result;
119*e3723e1fSApple OSS Distributions }
120*e3723e1fSApple OSS Distributions #endif // __clang_analyzer__
121*e3723e1fSApple OSS Distributions
122*e3723e1fSApple OSS Distributions /*********************************************************************
123*e3723e1fSApple OSS Distributions *********************************************************************/
124*e3723e1fSApple OSS Distributions
125*e3723e1fSApple OSS Distributions // FIXME: Implementation of this function is hidden from the static analyzer.
126*e3723e1fSApple OSS Distributions // The analyzer is worried about the double release and suggests
127*e3723e1fSApple OSS Distributions // refactoring the code into the typical non-owning container pattern.
128*e3723e1fSApple OSS Distributions // Feel free to remove the #ifndef and address the warning!
129*e3723e1fSApple OSS Distributions #ifndef __clang_analyzer__
130*e3723e1fSApple OSS Distributions OSReturn
OSKextReleaseKextWithLoadTag(uint32_t loadTag)131*e3723e1fSApple OSS Distributions OSKextReleaseKextWithLoadTag(uint32_t loadTag)
132*e3723e1fSApple OSS Distributions {
133*e3723e1fSApple OSS Distributions OSReturn result = kOSKextReturnNotFound;
134*e3723e1fSApple OSS Distributions OSKext * theKext = NULL; // must release twice!
135*e3723e1fSApple OSS Distributions
136*e3723e1fSApple OSS Distributions if (loadTag == kOSKextInvalidLoadTag) {
137*e3723e1fSApple OSS Distributions result = kOSKextReturnInvalidArgument;
138*e3723e1fSApple OSS Distributions goto finish;
139*e3723e1fSApple OSS Distributions }
140*e3723e1fSApple OSS Distributions theKext = OSKext::lookupKextWithLoadTag(loadTag);
141*e3723e1fSApple OSS Distributions if (theKext) {
142*e3723e1fSApple OSS Distributions result = kOSReturnSuccess;
143*e3723e1fSApple OSS Distributions OSKext::considerUnloads(); // schedule autounload pass
144*e3723e1fSApple OSS Distributions theKext->release(); // do the release the caller wants
145*e3723e1fSApple OSS Distributions theKext->release(); // now do the release on the lookup
146*e3723e1fSApple OSS Distributions OSKextLog(theKext,
147*e3723e1fSApple OSS Distributions kOSKextLogDebugLevel |
148*e3723e1fSApple OSS Distributions kOSKextLogKextBookkeepingFlag,
149*e3723e1fSApple OSS Distributions "Kext %s (load tag %d) has been released.",
150*e3723e1fSApple OSS Distributions theKext->getIdentifierCString(),
151*e3723e1fSApple OSS Distributions loadTag);
152*e3723e1fSApple OSS Distributions } else {
153*e3723e1fSApple OSS Distributions OSKextLog(theKext,
154*e3723e1fSApple OSS Distributions kOSKextLogErrorLevel |
155*e3723e1fSApple OSS Distributions kOSKextLogKextBookkeepingFlag,
156*e3723e1fSApple OSS Distributions "Can't release kext with load tag %d - no such kext is loaded.",
157*e3723e1fSApple OSS Distributions loadTag);
158*e3723e1fSApple OSS Distributions }
159*e3723e1fSApple OSS Distributions
160*e3723e1fSApple OSS Distributions // xxx - should I check that the refcount of the OSKext is above the lower bound?
161*e3723e1fSApple OSS Distributions // xxx - do we want a OSKextGetRetainCountOfKextWithLoadTag()?
162*e3723e1fSApple OSS Distributions finish:
163*e3723e1fSApple OSS Distributions return result;
164*e3723e1fSApple OSS Distributions }
165*e3723e1fSApple OSS Distributions #endif // __clang_analyzer__
166*e3723e1fSApple OSS Distributions
167*e3723e1fSApple OSS Distributions /*********************************************************************
168*e3723e1fSApple OSS Distributions * Not to be called by the kext being unloaded!
169*e3723e1fSApple OSS Distributions *********************************************************************/
170*e3723e1fSApple OSS Distributions OSReturn
OSKextUnloadKextWithLoadTag(uint32_t loadTag)171*e3723e1fSApple OSS Distributions OSKextUnloadKextWithLoadTag(uint32_t loadTag)
172*e3723e1fSApple OSS Distributions {
173*e3723e1fSApple OSS Distributions return OSKext::removeKextWithLoadTag(loadTag,
174*e3723e1fSApple OSS Distributions /* terminateServicesAndRemovePersonalitiesFlag */ false);
175*e3723e1fSApple OSS Distributions }
176*e3723e1fSApple OSS Distributions
177*e3723e1fSApple OSS Distributions
178*e3723e1fSApple OSS Distributions #if PRAGMA_MARK
179*e3723e1fSApple OSS Distributions #pragma mark Kext Requests
180*e3723e1fSApple OSS Distributions #endif
181*e3723e1fSApple OSS Distributions /*********************************************************************
182*e3723e1fSApple OSS Distributions * Kext Requests
183*e3723e1fSApple OSS Distributions *********************************************************************/
184*e3723e1fSApple OSS Distributions OSReturn
OSKextRequestResource(const char * kextIdentifier,const char * resourceName,OSKextRequestResourceCallback callback,void * context,OSKextRequestTag * requestTagOut)185*e3723e1fSApple OSS Distributions OSKextRequestResource(
186*e3723e1fSApple OSS Distributions const char * kextIdentifier,
187*e3723e1fSApple OSS Distributions const char * resourceName,
188*e3723e1fSApple OSS Distributions OSKextRequestResourceCallback callback,
189*e3723e1fSApple OSS Distributions void * context,
190*e3723e1fSApple OSS Distributions OSKextRequestTag * requestTagOut)
191*e3723e1fSApple OSS Distributions {
192*e3723e1fSApple OSS Distributions return OSKext::requestResource(kextIdentifier, resourceName,
193*e3723e1fSApple OSS Distributions callback, context, requestTagOut);
194*e3723e1fSApple OSS Distributions }
195*e3723e1fSApple OSS Distributions
196*e3723e1fSApple OSS Distributions /*********************************************************************
197*e3723e1fSApple OSS Distributions *********************************************************************/
198*e3723e1fSApple OSS Distributions OSReturn
OSKextCancelRequest(OSKextRequestTag requestTag,void ** contextOut)199*e3723e1fSApple OSS Distributions OSKextCancelRequest(
200*e3723e1fSApple OSS Distributions OSKextRequestTag requestTag,
201*e3723e1fSApple OSS Distributions void ** contextOut)
202*e3723e1fSApple OSS Distributions {
203*e3723e1fSApple OSS Distributions return OSKext::cancelRequest(requestTag, contextOut);
204*e3723e1fSApple OSS Distributions }
205*e3723e1fSApple OSS Distributions
206*e3723e1fSApple OSS Distributions #if PRAGMA_MARK
207*e3723e1fSApple OSS Distributions #pragma mark MIG Functions & Wrappers
208*e3723e1fSApple OSS Distributions #endif
209*e3723e1fSApple OSS Distributions /*********************************************************************
210*e3723e1fSApple OSS Distributions * IMPORTANT: vm_map_copyout_size() consumes the requestIn copy
211*e3723e1fSApple OSS Distributions * object on success. Therefore once it has been invoked successfully,
212*e3723e1fSApple OSS Distributions * this routine *must* return KERN_SUCCESS, regardless of our actual
213*e3723e1fSApple OSS Distributions * result. Our contract with the caller is that requestIn must be
214*e3723e1fSApple OSS Distributions * caller-deallocated if we return an error. We use op_result to return
215*e3723e1fSApple OSS Distributions * the real result of our work.
216*e3723e1fSApple OSS Distributions *********************************************************************/
217*e3723e1fSApple OSS Distributions kern_return_t
kext_request(host_priv_t hostPriv,uint32_t clientLogSpec,vm_offset_t requestIn,mach_msg_type_number_t requestLengthIn,vm_offset_t * responseOut,mach_msg_type_number_t * responseLengthOut,vm_offset_t * logDataOut,mach_msg_type_number_t * logDataLengthOut,kern_return_t * op_result)218*e3723e1fSApple OSS Distributions kext_request(
219*e3723e1fSApple OSS Distributions host_priv_t hostPriv,
220*e3723e1fSApple OSS Distributions /* in only */ uint32_t clientLogSpec,
221*e3723e1fSApple OSS Distributions /* in only */ vm_offset_t requestIn,
222*e3723e1fSApple OSS Distributions /* in only */ mach_msg_type_number_t requestLengthIn,
223*e3723e1fSApple OSS Distributions /* out only */ vm_offset_t * responseOut,
224*e3723e1fSApple OSS Distributions /* out only */ mach_msg_type_number_t * responseLengthOut,
225*e3723e1fSApple OSS Distributions /* out only */ vm_offset_t * logDataOut,
226*e3723e1fSApple OSS Distributions /* out only */ mach_msg_type_number_t * logDataLengthOut,
227*e3723e1fSApple OSS Distributions /* out only */ kern_return_t * op_result)
228*e3723e1fSApple OSS Distributions {
229*e3723e1fSApple OSS Distributions kern_return_t result = KERN_FAILURE;
230*e3723e1fSApple OSS Distributions vm_map_address_t map_addr = 0; // do not free/deallocate
231*e3723e1fSApple OSS Distributions char * request = NULL;// must vm_deallocate
232*e3723e1fSApple OSS Distributions
233*e3723e1fSApple OSS Distributions mkext2_header * mkextHeader = NULL;// do not release
234*e3723e1fSApple OSS Distributions bool isMkext = false;
235*e3723e1fSApple OSS Distributions
236*e3723e1fSApple OSS Distributions char * response = NULL;// must kmem_free
237*e3723e1fSApple OSS Distributions uint32_t responseLength = 0;
238*e3723e1fSApple OSS Distributions char * logData = NULL;// must kmem_free
239*e3723e1fSApple OSS Distributions uint32_t logDataLength = 0;
240*e3723e1fSApple OSS Distributions
241*e3723e1fSApple OSS Distributions /* MIG doesn't pass "out" parameters as empty, so clear them immediately
242*e3723e1fSApple OSS Distributions * just in case, or MIG will try to copy out bogus data.
243*e3723e1fSApple OSS Distributions */
244*e3723e1fSApple OSS Distributions *op_result = KERN_FAILURE;
245*e3723e1fSApple OSS Distributions *responseOut = 0;
246*e3723e1fSApple OSS Distributions *responseLengthOut = 0;
247*e3723e1fSApple OSS Distributions *logDataOut = 0;
248*e3723e1fSApple OSS Distributions *logDataLengthOut = 0;
249*e3723e1fSApple OSS Distributions
250*e3723e1fSApple OSS Distributions /* Check for input. Don't discard what isn't there, though.
251*e3723e1fSApple OSS Distributions */
252*e3723e1fSApple OSS Distributions if (!requestLengthIn || !requestIn) {
253*e3723e1fSApple OSS Distributions OSKextLog(/* kext */ NULL,
254*e3723e1fSApple OSS Distributions kOSKextLogErrorLevel |
255*e3723e1fSApple OSS Distributions kOSKextLogIPCFlag,
256*e3723e1fSApple OSS Distributions "Invalid request from user space (no data).");
257*e3723e1fSApple OSS Distributions *op_result = KERN_INVALID_ARGUMENT;
258*e3723e1fSApple OSS Distributions goto finish;
259*e3723e1fSApple OSS Distributions }
260*e3723e1fSApple OSS Distributions
261*e3723e1fSApple OSS Distributions result = vm_map_copyout_size(kernel_map, &map_addr, (vm_map_copy_t)requestIn, requestLengthIn);
262*e3723e1fSApple OSS Distributions if (result != KERN_SUCCESS) {
263*e3723e1fSApple OSS Distributions OSKextLog(/* kext */ NULL,
264*e3723e1fSApple OSS Distributions kOSKextLogErrorLevel |
265*e3723e1fSApple OSS Distributions kOSKextLogIPCFlag,
266*e3723e1fSApple OSS Distributions "vm_map_copyout() failed for request from user space.");
267*e3723e1fSApple OSS Distributions /*
268*e3723e1fSApple OSS Distributions * If we return an error it is our caller's responsibility to
269*e3723e1fSApple OSS Distributions * deallocate the requestIn copy object, so do not deallocate it
270*e3723e1fSApple OSS Distributions * here. See comment above.
271*e3723e1fSApple OSS Distributions */
272*e3723e1fSApple OSS Distributions goto finish;
273*e3723e1fSApple OSS Distributions }
274*e3723e1fSApple OSS Distributions request = CAST_DOWN(char *, map_addr);
275*e3723e1fSApple OSS Distributions
276*e3723e1fSApple OSS Distributions /* Check if request is an mkext; this is always a load request
277*e3723e1fSApple OSS Distributions * and requires root access. If it isn't an mkext, see if it's
278*e3723e1fSApple OSS Distributions * an XML request, and check the request to see if that requires
279*e3723e1fSApple OSS Distributions * root access.
280*e3723e1fSApple OSS Distributions */
281*e3723e1fSApple OSS Distributions if (requestLengthIn > sizeof(mkext2_header)) {
282*e3723e1fSApple OSS Distributions mkextHeader = (mkext2_header *)request;
283*e3723e1fSApple OSS Distributions if (MKEXT_GET_MAGIC(mkextHeader) == MKEXT_MAGIC &&
284*e3723e1fSApple OSS Distributions MKEXT_GET_SIGNATURE(mkextHeader) == MKEXT_SIGN) {
285*e3723e1fSApple OSS Distributions isMkext = true;
286*e3723e1fSApple OSS Distributions }
287*e3723e1fSApple OSS Distributions }
288*e3723e1fSApple OSS Distributions
289*e3723e1fSApple OSS Distributions if (isMkext) {
290*e3723e1fSApple OSS Distributions #if defined(SECURE_KERNEL) || !CONFIG_KXLD
291*e3723e1fSApple OSS Distributions // xxx - something tells me if we have a secure kernel we don't even
292*e3723e1fSApple OSS Distributions // xxx - want to log a message here. :-)
293*e3723e1fSApple OSS Distributions *op_result = KERN_NOT_SUPPORTED;
294*e3723e1fSApple OSS Distributions goto finish;
295*e3723e1fSApple OSS Distributions #else
296*e3723e1fSApple OSS Distributions // xxx - can we find out if calling task is kextd?
297*e3723e1fSApple OSS Distributions // xxx - can we find the name of the calling task?
298*e3723e1fSApple OSS Distributions if (hostPriv == HOST_PRIV_NULL) {
299*e3723e1fSApple OSS Distributions OSKextLog(/* kext */ NULL,
300*e3723e1fSApple OSS Distributions kOSKextLogErrorLevel |
301*e3723e1fSApple OSS Distributions kOSKextLogLoadFlag | kOSKextLogIPCFlag,
302*e3723e1fSApple OSS Distributions "Attempt by non-root process to load a kext.");
303*e3723e1fSApple OSS Distributions *op_result = kOSKextReturnNotPrivileged;
304*e3723e1fSApple OSS Distributions goto finish;
305*e3723e1fSApple OSS Distributions }
306*e3723e1fSApple OSS Distributions
307*e3723e1fSApple OSS Distributions *op_result = OSKext::loadFromMkext((OSKextLogSpec)clientLogSpec,
308*e3723e1fSApple OSS Distributions request, requestLengthIn,
309*e3723e1fSApple OSS Distributions &logData, &logDataLength);
310*e3723e1fSApple OSS Distributions
311*e3723e1fSApple OSS Distributions #endif /* defined(SECURE_KERNEL) */
312*e3723e1fSApple OSS Distributions } else {
313*e3723e1fSApple OSS Distributions /* If the request isn't an mkext, then is should be XML. Parse it
314*e3723e1fSApple OSS Distributions * if possible and hand the request over to OSKext.
315*e3723e1fSApple OSS Distributions */
316*e3723e1fSApple OSS Distributions *op_result = OSKext::handleRequest(hostPriv,
317*e3723e1fSApple OSS Distributions (OSKextLogSpec)clientLogSpec,
318*e3723e1fSApple OSS Distributions request, requestLengthIn,
319*e3723e1fSApple OSS Distributions &response, &responseLength,
320*e3723e1fSApple OSS Distributions &logData, &logDataLength);
321*e3723e1fSApple OSS Distributions }
322*e3723e1fSApple OSS Distributions
323*e3723e1fSApple OSS Distributions if (response && responseLength > 0) {
324*e3723e1fSApple OSS Distributions kern_return_t copyin_result;
325*e3723e1fSApple OSS Distributions
326*e3723e1fSApple OSS Distributions copyin_result = vm_map_copyin(kernel_map,
327*e3723e1fSApple OSS Distributions CAST_USER_ADDR_T(response), responseLength,
328*e3723e1fSApple OSS Distributions /* src_destroy */ false, (vm_map_copy_t *)responseOut);
329*e3723e1fSApple OSS Distributions if (copyin_result == KERN_SUCCESS) {
330*e3723e1fSApple OSS Distributions *responseLengthOut = responseLength;
331*e3723e1fSApple OSS Distributions } else {
332*e3723e1fSApple OSS Distributions OSKextLog(/* kext */ NULL,
333*e3723e1fSApple OSS Distributions kOSKextLogErrorLevel |
334*e3723e1fSApple OSS Distributions kOSKextLogIPCFlag,
335*e3723e1fSApple OSS Distributions "Failed to copy response to request from user space.");
336*e3723e1fSApple OSS Distributions *op_result = copyin_result; // xxx - should we map to our own code?
337*e3723e1fSApple OSS Distributions *responseOut = 0;
338*e3723e1fSApple OSS Distributions *responseLengthOut = 0;
339*e3723e1fSApple OSS Distributions goto finish;
340*e3723e1fSApple OSS Distributions }
341*e3723e1fSApple OSS Distributions }
342*e3723e1fSApple OSS Distributions
343*e3723e1fSApple OSS Distributions if (logData && logDataLength > 0) {
344*e3723e1fSApple OSS Distributions kern_return_t copyin_result;
345*e3723e1fSApple OSS Distributions
346*e3723e1fSApple OSS Distributions copyin_result = vm_map_copyin(kernel_map,
347*e3723e1fSApple OSS Distributions CAST_USER_ADDR_T(logData), logDataLength,
348*e3723e1fSApple OSS Distributions /* src_destroy */ false, (vm_map_copy_t *)logDataOut);
349*e3723e1fSApple OSS Distributions if (copyin_result == KERN_SUCCESS) {
350*e3723e1fSApple OSS Distributions *logDataLengthOut = logDataLength;
351*e3723e1fSApple OSS Distributions } else {
352*e3723e1fSApple OSS Distributions OSKextLog(/* kext */ NULL,
353*e3723e1fSApple OSS Distributions kOSKextLogErrorLevel |
354*e3723e1fSApple OSS Distributions kOSKextLogIPCFlag,
355*e3723e1fSApple OSS Distributions "Failed to copy log data for request from user space.");
356*e3723e1fSApple OSS Distributions *op_result = copyin_result; // xxx - should we map to our own code?
357*e3723e1fSApple OSS Distributions *logDataOut = 0;
358*e3723e1fSApple OSS Distributions *logDataLengthOut = 0;
359*e3723e1fSApple OSS Distributions goto finish;
360*e3723e1fSApple OSS Distributions }
361*e3723e1fSApple OSS Distributions }
362*e3723e1fSApple OSS Distributions
363*e3723e1fSApple OSS Distributions finish:
364*e3723e1fSApple OSS Distributions if (request) {
365*e3723e1fSApple OSS Distributions (void)vm_deallocate(kernel_map, (vm_offset_t)request, requestLengthIn);
366*e3723e1fSApple OSS Distributions }
367*e3723e1fSApple OSS Distributions if (response) {
368*e3723e1fSApple OSS Distributions /* 11981737 - clear uninitialized data in last page */
369*e3723e1fSApple OSS Distributions kmem_free(kernel_map, (vm_offset_t)response, round_page(responseLength));
370*e3723e1fSApple OSS Distributions }
371*e3723e1fSApple OSS Distributions if (logData) {
372*e3723e1fSApple OSS Distributions /* 11981737 - clear uninitialized data in last page */
373*e3723e1fSApple OSS Distributions kmem_free(kernel_map, (vm_offset_t)logData, round_page(logDataLength));
374*e3723e1fSApple OSS Distributions }
375*e3723e1fSApple OSS Distributions
376*e3723e1fSApple OSS Distributions return result;
377*e3723e1fSApple OSS Distributions }
378*e3723e1fSApple OSS Distributions
379*e3723e1fSApple OSS Distributions /*********************************************************************
380*e3723e1fSApple OSS Distributions * Gets the vm_map for the current kext
381*e3723e1fSApple OSS Distributions *********************************************************************/
382*e3723e1fSApple OSS Distributions extern vm_offset_t segPRELINKTEXTB;
383*e3723e1fSApple OSS Distributions extern vm_offset_t segLINKB;
384*e3723e1fSApple OSS Distributions extern unsigned long segSizePRELINKTEXT;
385*e3723e1fSApple OSS Distributions
386*e3723e1fSApple OSS Distributions vm_map_t
kext_get_vm_map(kmod_info_t * info)387*e3723e1fSApple OSS Distributions kext_get_vm_map(kmod_info_t *info)
388*e3723e1fSApple OSS Distributions {
389*e3723e1fSApple OSS Distributions vm_map_t kext_map = NULL;
390*e3723e1fSApple OSS Distributions kc_format_t kcformat;
391*e3723e1fSApple OSS Distributions
392*e3723e1fSApple OSS Distributions if (PE_get_primary_kc_format(&kcformat) && kcformat == KCFormatFileset) {
393*e3723e1fSApple OSS Distributions /* Check if the kext is from the boot KC */
394*e3723e1fSApple OSS Distributions assert(segLINKB >= (segPRELINKTEXTB + segSizePRELINKTEXT));
395*e3723e1fSApple OSS Distributions if ((info->address >= segPRELINKTEXTB) &&
396*e3723e1fSApple OSS Distributions (info->address < segLINKB)) {
397*e3723e1fSApple OSS Distributions kext_map = kernel_map;
398*e3723e1fSApple OSS Distributions } else {
399*e3723e1fSApple OSS Distributions kext_map = g_kext_map;
400*e3723e1fSApple OSS Distributions }
401*e3723e1fSApple OSS Distributions } else {
402*e3723e1fSApple OSS Distributions if ((info->address >= segPRELINKTEXTB) &&
403*e3723e1fSApple OSS Distributions (info->address < (segPRELINKTEXTB + segSizePRELINKTEXT))) {
404*e3723e1fSApple OSS Distributions kext_map = kernel_map;
405*e3723e1fSApple OSS Distributions } else {
406*e3723e1fSApple OSS Distributions kext_map = g_kext_map;
407*e3723e1fSApple OSS Distributions }
408*e3723e1fSApple OSS Distributions }
409*e3723e1fSApple OSS Distributions
410*e3723e1fSApple OSS Distributions return kext_map;
411*e3723e1fSApple OSS Distributions }
412*e3723e1fSApple OSS Distributions
413*e3723e1fSApple OSS Distributions
414*e3723e1fSApple OSS Distributions #if PRAGMA_MARK
415*e3723e1fSApple OSS Distributions /********************************************************************/
416*e3723e1fSApple OSS Distributions #pragma mark Weak linking support
417*e3723e1fSApple OSS Distributions /********************************************************************/
418*e3723e1fSApple OSS Distributions #endif
419*e3723e1fSApple OSS Distributions void
kext_weak_symbol_referenced(void)420*e3723e1fSApple OSS Distributions kext_weak_symbol_referenced(void)
421*e3723e1fSApple OSS Distributions {
422*e3723e1fSApple OSS Distributions panic("A kext referenced an unresolved weak symbol");
423*e3723e1fSApple OSS Distributions }
424*e3723e1fSApple OSS Distributions
425*e3723e1fSApple OSS Distributions const void * const gOSKextUnresolved = (const void *)&kext_weak_symbol_referenced;
426*e3723e1fSApple OSS Distributions
427*e3723e1fSApple OSS Distributions #if PRAGMA_MARK
428*e3723e1fSApple OSS Distributions #pragma mark Kernel-Internal C Functions
429*e3723e1fSApple OSS Distributions #endif
430*e3723e1fSApple OSS Distributions /*********************************************************************
431*e3723e1fSApple OSS Distributions * Called from startup.c.
432*e3723e1fSApple OSS Distributions *********************************************************************/
433*e3723e1fSApple OSS Distributions void
OSKextRemoveKextBootstrap(void)434*e3723e1fSApple OSS Distributions OSKextRemoveKextBootstrap(void)
435*e3723e1fSApple OSS Distributions {
436*e3723e1fSApple OSS Distributions OSKext::removeKextBootstrap();
437*e3723e1fSApple OSS Distributions return;
438*e3723e1fSApple OSS Distributions }
439*e3723e1fSApple OSS Distributions
440*e3723e1fSApple OSS Distributions #if CONFIG_DTRACE
441*e3723e1fSApple OSS Distributions /*********************************************************************
442*e3723e1fSApple OSS Distributions *********************************************************************/
443*e3723e1fSApple OSS Distributions void
OSKextRegisterKextsWithDTrace(void)444*e3723e1fSApple OSS Distributions OSKextRegisterKextsWithDTrace(void)
445*e3723e1fSApple OSS Distributions {
446*e3723e1fSApple OSS Distributions OSKext::registerKextsWithDTrace();
447*e3723e1fSApple OSS Distributions return;
448*e3723e1fSApple OSS Distributions }
449*e3723e1fSApple OSS Distributions #endif /* CONFIG_DTRACE */
450*e3723e1fSApple OSS Distributions
451*e3723e1fSApple OSS Distributions /*********************************************************************
452*e3723e1fSApple OSS Distributions *********************************************************************/
453*e3723e1fSApple OSS Distributions void
kext_dump_panic_lists(int (* printf_func)(const char * fmt,...))454*e3723e1fSApple OSS Distributions kext_dump_panic_lists(int (*printf_func)(const char * fmt, ...))
455*e3723e1fSApple OSS Distributions {
456*e3723e1fSApple OSS Distributions OSKext::printKextPanicLists(printf_func);
457*e3723e1fSApple OSS Distributions return;
458*e3723e1fSApple OSS Distributions }
459*e3723e1fSApple OSS Distributions
460*e3723e1fSApple OSS Distributions #if PRAGMA_MARK
461*e3723e1fSApple OSS Distributions #pragma mark Kmod Compatibility Functions
462*e3723e1fSApple OSS Distributions #endif
463*e3723e1fSApple OSS Distributions /*********************************************************************
464*e3723e1fSApple OSS Distributions **********************************************************************
465*e3723e1fSApple OSS Distributions * KMOD COMPATIBILITY FUNCTIONS *
466*e3723e1fSApple OSS Distributions * (formerly in kmod.c, or C++ bridges from) *
467*e3723e1fSApple OSS Distributions **********************************************************************
468*e3723e1fSApple OSS Distributions **********************************************************************
469*e3723e1fSApple OSS Distributions * These two functions are used in various places in the kernel, but
470*e3723e1fSApple OSS Distributions * are not exported. We might rename them at some point to start with
471*e3723e1fSApple OSS Distributions * kext_ or OSKext.
472*e3723e1fSApple OSS Distributions *
473*e3723e1fSApple OSS Distributions * kmod_panic_dump() must not be called outside of a panic context.
474*e3723e1fSApple OSS Distributions * kmod_dump_log() must not be called in a panic context.
475*e3723e1fSApple OSS Distributions *********************************************************************/
476*e3723e1fSApple OSS Distributions void
kmod_panic_dump(vm_offset_t * addr,unsigned int cnt)477*e3723e1fSApple OSS Distributions kmod_panic_dump(vm_offset_t * addr, unsigned int cnt)
478*e3723e1fSApple OSS Distributions {
479*e3723e1fSApple OSS Distributions extern int paniclog_append_noflush(const char *format, ...) __printflike(1, 2);
480*e3723e1fSApple OSS Distributions
481*e3723e1fSApple OSS Distributions OSKext::printKextsInBacktrace(addr, cnt, &paniclog_append_noflush, 0);
482*e3723e1fSApple OSS Distributions
483*e3723e1fSApple OSS Distributions return;
484*e3723e1fSApple OSS Distributions }
485*e3723e1fSApple OSS Distributions
486*e3723e1fSApple OSS Distributions void
telemetry_backtrace_add_kexts(char * buf,size_t buflen,uintptr_t * frames,uint32_t framecnt)487*e3723e1fSApple OSS Distributions telemetry_backtrace_add_kexts(
488*e3723e1fSApple OSS Distributions char *buf,
489*e3723e1fSApple OSS Distributions size_t buflen,
490*e3723e1fSApple OSS Distributions uintptr_t *frames,
491*e3723e1fSApple OSS Distributions uint32_t framecnt)
492*e3723e1fSApple OSS Distributions {
493*e3723e1fSApple OSS Distributions __block size_t pos = 0;
494*e3723e1fSApple OSS Distributions
495*e3723e1fSApple OSS Distributions OSKext::foreachKextInBacktrace(frames, framecnt, OSKext::kPrintKextsLock,
496*e3723e1fSApple OSS Distributions ^(OSKextLoadedKextSummary *summary, uint32_t index __unused){
497*e3723e1fSApple OSS Distributions uuid_string_t uuid;
498*e3723e1fSApple OSS Distributions uint64_t tmpAddr;
499*e3723e1fSApple OSS Distributions uint64_t tmpSize;
500*e3723e1fSApple OSS Distributions
501*e3723e1fSApple OSS Distributions (void) uuid_unparse(summary->uuid, uuid);
502*e3723e1fSApple OSS Distributions
503*e3723e1fSApple OSS Distributions #if defined(__arm__) || defined(__arm64__)
504*e3723e1fSApple OSS Distributions tmpAddr = summary->text_exec_address;
505*e3723e1fSApple OSS Distributions tmpSize = summary->text_exec_size;
506*e3723e1fSApple OSS Distributions #else
507*e3723e1fSApple OSS Distributions tmpAddr = summary->address;
508*e3723e1fSApple OSS Distributions tmpSize = summary->size;
509*e3723e1fSApple OSS Distributions #endif
510*e3723e1fSApple OSS Distributions tmpAddr -= vm_kernel_stext;
511*e3723e1fSApple OSS Distributions pos += scnprintf(buf + pos, buflen - pos, "%s@%llx:%llx\n",
512*e3723e1fSApple OSS Distributions uuid, tmpAddr, tmpAddr + tmpSize - 1);
513*e3723e1fSApple OSS Distributions });
514*e3723e1fSApple OSS Distributions }
515*e3723e1fSApple OSS Distributions
516*e3723e1fSApple OSS Distributions /********************************************************************/
517*e3723e1fSApple OSS Distributions void kmod_dump_log(vm_offset_t *addr, unsigned int cnt, boolean_t doUnslide);
518*e3723e1fSApple OSS Distributions
519*e3723e1fSApple OSS Distributions void
kmod_dump_log(vm_offset_t * addr,unsigned int cnt,boolean_t doUnslide)520*e3723e1fSApple OSS Distributions kmod_dump_log(
521*e3723e1fSApple OSS Distributions vm_offset_t * addr,
522*e3723e1fSApple OSS Distributions unsigned int cnt,
523*e3723e1fSApple OSS Distributions boolean_t doUnslide)
524*e3723e1fSApple OSS Distributions {
525*e3723e1fSApple OSS Distributions uint32_t flags = OSKext::kPrintKextsLock;
526*e3723e1fSApple OSS Distributions if (doUnslide) {
527*e3723e1fSApple OSS Distributions flags |= OSKext::kPrintKextsUnslide;
528*e3723e1fSApple OSS Distributions }
529*e3723e1fSApple OSS Distributions OSKext::printKextsInBacktrace(addr, cnt, &printf, flags);
530*e3723e1fSApple OSS Distributions }
531*e3723e1fSApple OSS Distributions
532*e3723e1fSApple OSS Distributions void *
OSKextKextForAddress(const void * addr)533*e3723e1fSApple OSS Distributions OSKextKextForAddress(const void *addr)
534*e3723e1fSApple OSS Distributions {
535*e3723e1fSApple OSS Distributions return OSKext::kextForAddress(addr);
536*e3723e1fSApple OSS Distributions }
537*e3723e1fSApple OSS Distributions
538*e3723e1fSApple OSS Distributions kern_return_t
OSKextGetLoadedKextSummaryForAddress(const void * addr,OSKextLoadedKextSummary * summary)539*e3723e1fSApple OSS Distributions OSKextGetLoadedKextSummaryForAddress(
540*e3723e1fSApple OSS Distributions const void * addr,
541*e3723e1fSApple OSS Distributions OSKextLoadedKextSummary * summary)
542*e3723e1fSApple OSS Distributions {
543*e3723e1fSApple OSS Distributions return OSKext::summaryForAddressExt(addr, summary);
544*e3723e1fSApple OSS Distributions }
545*e3723e1fSApple OSS Distributions
546*e3723e1fSApple OSS Distributions /*********************************************************************
547*e3723e1fSApple OSS Distributions * Compatibility implementation for kmod_get_info() host_priv routine.
548*e3723e1fSApple OSS Distributions * Only supported on old 32-bit architectures.
549*e3723e1fSApple OSS Distributions *********************************************************************/
550*e3723e1fSApple OSS Distributions
551*e3723e1fSApple OSS Distributions #if PRAGMA_MARK
552*e3723e1fSApple OSS Distributions #pragma mark Loaded Kext Summary
553*e3723e1fSApple OSS Distributions #endif
554*e3723e1fSApple OSS Distributions
555*e3723e1fSApple OSS Distributions void
OSKextLoadedKextSummariesUpdated(void)556*e3723e1fSApple OSS Distributions OSKextLoadedKextSummariesUpdated(void)
557*e3723e1fSApple OSS Distributions {
558*e3723e1fSApple OSS Distributions // Do nothing.
559*e3723e1fSApple OSS Distributions }
560*e3723e1fSApple OSS Distributions };
561