VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/darwin/krnlmod-darwin.cpp@ 79727

Last change on this file since 79727 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1/* $Id: krnlmod-darwin.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * IPRT - Kernel module, Darwin.
4 */
5
6/*
7 * Copyright (C) 2017-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_SYSTEM
32#include <iprt/krnlmod.h>
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/errcore.h>
37#include <iprt/ldr.h>
38#include <iprt/mem.h>
39#include <iprt/once.h>
40#include <iprt/string.h>
41#include <iprt/types.h>
42
43#include <CoreFoundation/CoreFoundation.h>
44#include <IOKit/IOKitLib.h>
45
46
47/** @name Missing/private IOKitLib declarations and definitions.
48 * @{ */
49/** OSKextCopyLoadedKextInfo in IOKit. */
50typedef CFDictionaryRef (* PFNOSKEXTCOPYLOADEDKEXTINFO)(CFArrayRef, CFArrayRef);
51
52#ifndef kOSBundleRetainCountKey
53# define kOSBundleRetainCountKey CFSTR("OSBundleRetainCount")
54#endif
55#ifndef kOSBundleLoadSizeKey
56# define kOSBundleLoadSizeKey CFSTR("OSBundleLoadSize")
57#endif
58#ifndef kOSBundleLoadAddressKey
59# define kOSBundleLoadAddressKey CFSTR("OSBundleLoadAddress")
60#endif
61/** @} */
62
63
64/*********************************************************************************************************************************
65* Structures and Typedefs *
66*********************************************************************************************************************************/
67/**
68 * Internal kernel information record state.
69 */
70typedef struct RTKRNLMODINFOINT
71{
72 /** Reference counter. */
73 volatile uint32_t cRefs;
74 /** The dictionary containing our data. */
75 CFDictionaryRef hDictKext;
76} RTKRNLMODINFOINT;
77/** Pointer to the internal kernel module information record. */
78typedef RTKRNLMODINFOINT *PRTKRNLMODINFOINT;
79/** Pointer to a const internal kernel module information record. */
80typedef const RTKRNLMODINFOINT *PCRTKRNLMODINFOINT;
81
82
83/*********************************************************************************************************************************
84* Global Variables *
85*********************************************************************************************************************************/
86static RTONCE g_GetIoKitApisOnce = RTONCE_INITIALIZER;
87static PFNOSKEXTCOPYLOADEDKEXTINFO g_pfnOSKextCopyLoadedKextInfo = NULL;
88
89/** Do-once callback for setting g_pfnOSKextCopyLoadedKextInfo. */
90static DECLCALLBACK(int) rtKrnlModDarwinResolveIoKitApis(void *pvUser)
91{
92 RTLDRMOD hMod;
93// int rc = RTLdrLoad("/System/Library/Frameworks/IOKit.framework/Versions/Current/IOKit", &hMod);
94 int rc = RTLdrLoadEx("/System/Library/Frameworks/IOKit.framework/Versions/Current/IOKit", &hMod, RTLDRLOAD_FLAGS_NO_SUFFIX, NULL);
95 if (RT_SUCCESS(rc))
96 RTLdrGetSymbol(hMod, "OSKextCopyLoadedKextInfo", (void **)&g_pfnOSKextCopyLoadedKextInfo);
97
98 RT_NOREF(pvUser);
99 return VINF_SUCCESS;
100}
101
102/**
103 * Returns the kext information dictionary structure matching the given name.
104 *
105 * @returns Pointer to the matching module information record on success or NULL if not found.
106 * @param pszName The name to look for.
107 */
108static CFDictionaryRef rtKrnlModDarwinGetKextInfoByName(const char *pszName)
109{
110 CFDictionaryRef hDictKext = NULL;
111
112 RTOnce(&g_GetIoKitApisOnce, rtKrnlModDarwinResolveIoKitApis, NULL);
113 if (g_pfnOSKextCopyLoadedKextInfo)
114 {
115 CFStringRef hKextName = CFStringCreateWithCString(kCFAllocatorDefault, pszName, kCFStringEncodingUTF8);
116 if (hKextName)
117 {
118 CFArrayRef hArrKextIdRef = CFArrayCreate(kCFAllocatorDefault, (const void **)&hKextName, 1, &kCFTypeArrayCallBacks);
119 if (hArrKextIdRef)
120 {
121 CFDictionaryRef hLoadedKexts = g_pfnOSKextCopyLoadedKextInfo(hArrKextIdRef, NULL /* all info */);
122 if (hLoadedKexts)
123 {
124 if (CFDictionaryGetCount(hLoadedKexts) > 0)
125 {
126 hDictKext = (CFDictionaryRef)CFDictionaryGetValue(hLoadedKexts, hKextName);
127 CFRetain(hDictKext);
128 }
129
130 CFRelease(hLoadedKexts);
131 }
132 CFRelease(hArrKextIdRef);
133 }
134 CFRelease(hKextName);
135 }
136 }
137
138 return hDictKext;
139}
140
141/**
142 * Destroy the given kernel module information record.
143 *
144 * @returns nothing.
145 * @param pThis The record to destroy.
146 */
147static void rtKrnlModInfoDestroy(PRTKRNLMODINFOINT pThis)
148{
149 CFRelease(pThis->hDictKext);
150 RTMemFree(pThis);
151}
152
153
154RTDECL(int) RTKrnlModQueryLoaded(const char *pszName, bool *pfLoaded)
155{
156 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
157 AssertPtrReturn(pfLoaded, VERR_INVALID_POINTER);
158
159 CFDictionaryRef hDictKext = rtKrnlModDarwinGetKextInfoByName(pszName);
160 *pfLoaded = hDictKext != NULL;
161 if (hDictKext)
162 CFRelease(hDictKext);
163
164 return VINF_SUCCESS;
165}
166
167
168RTDECL(int) RTKrnlModLoadedQueryInfo(const char *pszName, PRTKRNLMODINFO phKrnlModInfo)
169{
170 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
171 AssertPtrReturn(phKrnlModInfo, VERR_INVALID_POINTER);
172
173 int rc = VINF_SUCCESS;
174 CFDictionaryRef hDictKext = rtKrnlModDarwinGetKextInfoByName(pszName);
175 if (hDictKext)
176 {
177 PRTKRNLMODINFOINT pThis = (PRTKRNLMODINFOINT)RTMemAllocZ(sizeof(RTKRNLMODINFOINT));
178 if (pThis)
179 {
180 pThis->cRefs = 1;
181 pThis->hDictKext = hDictKext;
182
183 *phKrnlModInfo = pThis;
184 }
185 else
186 rc = VERR_NO_MEMORY;
187 }
188 else
189 rc = VERR_NOT_FOUND;
190
191 return rc;
192}
193
194
195RTDECL(uint32_t) RTKrnlModLoadedGetCount(void)
196{
197 uint32_t cLoadedKexts = 0;
198 RTOnce(&g_GetIoKitApisOnce, rtKrnlModDarwinResolveIoKitApis, NULL);
199 if (g_pfnOSKextCopyLoadedKextInfo)
200 {
201 CFDictionaryRef hLoadedKexts = g_pfnOSKextCopyLoadedKextInfo(NULL, NULL /* all info */);
202 if (hLoadedKexts)
203 {
204 cLoadedKexts = CFDictionaryGetCount(hLoadedKexts);
205 CFRelease(hLoadedKexts);
206 }
207 }
208
209 return cLoadedKexts;
210}
211
212
213RTDECL(int) RTKrnlModLoadedQueryInfoAll(PRTKRNLMODINFO pahKrnlModInfo, uint32_t cEntriesMax,
214 uint32_t *pcEntries)
215{
216 AssertReturn(VALID_PTR(pahKrnlModInfo) || cEntriesMax == 0, VERR_INVALID_PARAMETER);
217
218 int rc = VINF_SUCCESS;
219 RTOnce(&g_GetIoKitApisOnce, rtKrnlModDarwinResolveIoKitApis, NULL);
220 if (g_pfnOSKextCopyLoadedKextInfo)
221 {
222 CFDictionaryRef hLoadedKexts = g_pfnOSKextCopyLoadedKextInfo(NULL, NULL /* all info */);
223 if (hLoadedKexts)
224 {
225 uint32_t cLoadedKexts = CFDictionaryGetCount(hLoadedKexts);
226 if (cLoadedKexts <= cEntriesMax)
227 {
228 CFDictionaryRef *pahDictKext = (CFDictionaryRef *)RTMemTmpAllocZ(cLoadedKexts * sizeof(CFDictionaryRef));
229 if (pahDictKext)
230 {
231 CFDictionaryGetKeysAndValues(hLoadedKexts, NULL, (const void **)pahDictKext);
232 for (uint32_t i = 0; i < cLoadedKexts; i++)
233 {
234 PRTKRNLMODINFOINT pThis = (PRTKRNLMODINFOINT)RTMemAllocZ(sizeof(RTKRNLMODINFOINT));
235 if (RT_LIKELY(pThis))
236 {
237 pThis->cRefs = 1;
238 pThis->hDictKext = pahDictKext[i];
239 CFRetain(pThis->hDictKext);
240 pahKrnlModInfo[i] = pThis;
241 }
242 else
243 {
244 rc = VERR_NO_MEMORY;
245 /* Rollback. */
246 while (i-- > 0)
247 {
248 CFRelease(pahKrnlModInfo[i]->hDictKext);
249 RTMemFree(pahKrnlModInfo[i]);
250 }
251 }
252 }
253
254 if ( RT_SUCCESS(rc)
255 && pcEntries)
256 *pcEntries = cLoadedKexts;
257
258 RTMemTmpFree(pahDictKext);
259 }
260 else
261 rc = VERR_NO_MEMORY;
262 }
263 else
264 {
265 rc = VERR_BUFFER_OVERFLOW;
266
267 if (pcEntries)
268 *pcEntries = cLoadedKexts;
269 }
270
271 CFRelease(hLoadedKexts);
272 }
273 else
274 rc = VERR_NOT_SUPPORTED;
275 }
276 else
277 rc = VERR_NOT_SUPPORTED;
278
279 return rc;
280}
281
282
283RTDECL(uint32_t) RTKrnlModInfoRetain(RTKRNLMODINFO hKrnlModInfo)
284{
285 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
286 AssertPtrReturn(pThis, UINT32_MAX);
287
288 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
289 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
290 return cRefs;
291}
292
293
294RTDECL(uint32_t) RTKrnlModInfoRelease(RTKRNLMODINFO hKrnlModInfo)
295{
296 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
297 if (!pThis)
298 return 0;
299 AssertPtrReturn(pThis, UINT32_MAX);
300
301 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
302 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
303 if (cRefs == 0)
304 rtKrnlModInfoDestroy(pThis);
305 return cRefs;
306}
307
308
309RTDECL(uint32_t) RTKrnlModInfoGetRefCnt(RTKRNLMODINFO hKrnlModInfo)
310{
311 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
312 AssertPtrReturn(pThis, 0);
313
314 uint32_t cRefCnt = 0;
315 CFNumberRef hRetainCnt = (CFNumberRef)CFDictionaryGetValue(pThis->hDictKext,
316 kOSBundleRetainCountKey);
317 if (hRetainCnt)
318 CFNumberGetValue(hRetainCnt, kCFNumberSInt32Type, &cRefCnt);
319
320 return cRefCnt;
321}
322
323
324RTDECL(const char *) RTKrnlModInfoGetName(RTKRNLMODINFO hKrnlModInfo)
325{
326 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
327 AssertPtrReturn(pThis, NULL);
328
329 const char *pszName = NULL;
330 CFStringRef hBundleId = (CFStringRef)CFDictionaryGetValue(pThis->hDictKext,
331 kCFBundleIdentifierKey);
332 if (hBundleId)
333 pszName = CFStringGetCStringPtr(hBundleId, kCFStringEncodingUTF8);
334
335 return pszName;
336}
337
338
339RTDECL(const char *) RTKrnlModInfoGetFilePath(RTKRNLMODINFO hKrnlModInfo)
340{
341 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
342 AssertPtrReturn(pThis, NULL);
343
344 return NULL;
345}
346
347
348RTDECL(size_t) RTKrnlModInfoGetSize(RTKRNLMODINFO hKrnlModInfo)
349{
350 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
351 AssertPtrReturn(pThis, 0);
352
353 size_t cbKrnlMod = 0;
354 CFNumberRef hKrnlModSize = (CFNumberRef)CFDictionaryGetValue(pThis->hDictKext,
355 kOSBundleLoadSizeKey);
356 if (hKrnlModSize)
357 {
358 uint32_t cbTmp = 0;
359 CFNumberGetValue(hKrnlModSize, kCFNumberSInt32Type, &cbTmp);
360 cbKrnlMod = cbTmp;
361 }
362
363 return cbKrnlMod;
364}
365
366
367RTDECL(RTR0UINTPTR) RTKrnlModInfoGetLoadAddr(RTKRNLMODINFO hKrnlModInfo)
368{
369 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
370 AssertPtrReturn(pThis, 0);
371
372 RTR0UINTPTR uKrnlModLoadAddr = 0;
373 CFNumberRef hKrnlModLoadAddr = (CFNumberRef)CFDictionaryGetValue(pThis->hDictKext,
374 kOSBundleLoadAddressKey);
375 if (hKrnlModLoadAddr)
376 {
377 uint64_t uAddrTmp = 0;
378 CFNumberGetValue(hKrnlModLoadAddr, kCFNumberSInt64Type, &uAddrTmp);
379 uKrnlModLoadAddr = uAddrTmp;
380 }
381
382 return uKrnlModLoadAddr;
383}
384
385
386RTDECL(int) RTKrnlModInfoQueryRefModInfo(RTKRNLMODINFO hKrnlModInfo, uint32_t idx,
387 PRTKRNLMODINFO phKrnlModInfoRef)
388{
389 RT_NOREF3(hKrnlModInfo, idx, phKrnlModInfoRef);
390 return VERR_NOT_IMPLEMENTED;
391}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette