VirtualBox

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

Last change on this file since 68246 was 67284, checked in by vboxsync, 8 years ago

Runtime: Start hacking on API to query information about loaded kernel modules on the host

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 KB
Line 
1/* $Id: krnlmod-darwin.cpp 67284 2017-06-07 19:35:17Z vboxsync $ */
2/** @file
3 * IPRT - Kernel module, Darwin.
4 */
5
6/*
7 * Copyright (C) 2017 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#include <iprt/asm.h>
34#include <iprt/assert.h>
35#include <iprt/err.h>
36#include <iprt/mem.h>
37#include <iprt/string.h>
38#include <iprt/types.h>
39
40#include <CoreFoundation/CoreFoundation.h>
41#include <IOKit/IOKitLib.h>
42
43/**
44 * Internal kernel information record state.
45 */
46typedef struct RTKRNLMODINFOINT
47{
48 /** Reference counter. */
49 volatile uint32_t cRefs;
50 /** The dictionary containing our data. */
51 CFDictionaryRef hDictKext;
52} RTKRNLMODINFOINT;
53/** Pointer to the internal kernel module information record. */
54typedef RTKRNLMODINFOINT *PRTKRNLMODINFOINT;
55/** Pointer to a const internal kernel module information record. */
56typedef const RTKRNLMODINFOINT *PCRTKRNLMODINFOINT;
57
58/**
59 * The declarations are not exposed so we have to define them ourselves.
60 */
61extern "C"
62{
63 extern CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef);
64}
65
66#ifndef kOSBundleRetainCountKey
67# define kOSBundleRetainCountKey CFSTR("OSBundleRetainCount")
68#endif
69
70#ifndef kOSBundleLoadSizeKey
71# define kOSBundleLoadSizeKey CFSTR("OSBundleLoadSize")
72#endif
73
74#ifndef kOSBundleLoadAddressKey
75# define kOSBundleLoadAddressKey CFSTR("OSBundleLoadAddress")
76#endif
77
78/**
79 * Returns the kext information dictionary structure matching the given name.
80 *
81 * @returns Pointer to the matching module information record on success or NULL if not found.
82 * @param pszName The name to look for.
83 */
84static CFDictionaryRef rtKrnlModDarwinGetKextInfoByName(const char *pszName)
85{
86 CFDictionaryRef hDictKext = NULL;
87 CFStringRef hKextName = CFStringCreateWithCString(kCFAllocatorDefault, pszName, kCFStringEncodingUTF8);
88 if (hKextName)
89 {
90 CFArrayRef hArrKextIdRef = CFArrayCreate(kCFAllocatorDefault, (const void **)&hKextName, 1, &kCFTypeArrayCallBacks);
91 if (hArrKextIdRef)
92 {
93 CFDictionaryRef hLoadedKexts = OSKextCopyLoadedKextInfo(hArrKextIdRef, NULL /* all info */);
94 if (hLoadedKexts)
95 {
96 if (CFDictionaryGetCount(hLoadedKexts) > 0)
97 {
98 hDictKext = (CFDictionaryRef)CFDictionaryGetValue(hLoadedKexts, hKextName);
99 CFRetain(hDictKext);
100 }
101
102 CFRelease(hLoadedKexts);
103 }
104 CFRelease(hArrKextIdRef);
105 }
106 CFRelease(hKextName);
107 }
108
109 return hDictKext;
110}
111
112/**
113 * Destroy the given kernel module information record.
114 *
115 * @returns nothing.
116 * @param pThis The record to destroy.
117 */
118static void rtKrnlModInfoDestroy(PRTKRNLMODINFOINT pThis)
119{
120 CFRelease(pThis->hDictKext);
121 RTMemFree(pThis);
122}
123
124
125RTDECL(int) RTKrnlModQueryLoaded(const char *pszName, bool *pfLoaded)
126{
127 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
128 AssertPtrReturn(pfLoaded, VERR_INVALID_POINTER);
129
130 CFDictionaryRef hDictKext = rtKrnlModDarwinGetKextInfoByName(pszName);
131 *pfLoaded = hDictKext != NULL;
132 if (hDictKext)
133 CFRelease(hDictKext);
134
135 return VINF_SUCCESS;
136}
137
138
139RTDECL(int) RTKrnlModLoadedQueryInfo(const char *pszName, PRTKRNLMODINFO phKrnlModInfo)
140{
141 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
142 AssertPtrReturn(phKrnlModInfo, VERR_INVALID_POINTER);
143
144 int rc = VINF_SUCCESS;
145 CFDictionaryRef hDictKext = rtKrnlModDarwinGetKextInfoByName(pszName);
146 if (hDictKext)
147 {
148 PRTKRNLMODINFOINT pThis = (PRTKRNLMODINFOINT)RTMemAllocZ(sizeof(RTKRNLMODINFOINT));
149 if (pThis)
150 {
151 pThis->cRefs = 1;
152 pThis->hDictKext = hDictKext;
153
154 *phKrnlModInfo = pThis;
155 }
156 else
157 rc = VERR_NO_MEMORY;
158 }
159 else
160 rc = VERR_NOT_FOUND;
161
162 return rc;
163}
164
165
166RTDECL(uint32_t) RTKrnlModLoadedGetCount()
167{
168 uint32_t cLoadedKexts = 0;
169 CFDictionaryRef hLoadedKexts = OSKextCopyLoadedKextInfo(NULL, NULL /* all info */);
170 if (hLoadedKexts)
171 {
172 cLoadedKexts = CFDictionaryGetCount(hLoadedKexts);
173 CFRelease(hLoadedKexts);
174 }
175
176 return cLoadedKexts;
177}
178
179
180RTDECL(int) RTKrnlModLoadedQueryInfoAll(PRTKRNLMODINFO pahKrnlModInfo, uint32_t cEntriesMax,
181 uint32_t *pcEntries)
182{
183 AssertReturn(VALID_PTR(pahKrnlModInfo) || cEntriesMax == 0, VERR_INVALID_PARAMETER);
184
185 int rc = VINF_SUCCESS;
186 CFDictionaryRef hLoadedKexts = OSKextCopyLoadedKextInfo(NULL, NULL /* all info */);
187 if (hLoadedKexts)
188 {
189 uint32_t cLoadedKexts = CFDictionaryGetCount(hLoadedKexts);
190 if (cLoadedKexts <= cEntriesMax)
191 {
192 CFDictionaryRef *pahDictKext = (CFDictionaryRef *)RTMemTmpAllocZ(cLoadedKexts * sizeof(CFDictionaryRef));
193 if (pahDictKext)
194 {
195 CFDictionaryGetKeysAndValues(hLoadedKexts, NULL, (const void **)pahDictKext);
196 for (uint32_t i = 0; i < cLoadedKexts; i++)
197 {
198 PRTKRNLMODINFOINT pThis = (PRTKRNLMODINFOINT)RTMemAllocZ(sizeof(RTKRNLMODINFOINT));
199 if (RT_LIKELY(pThis))
200 {
201 pThis->cRefs = 1;
202 pThis->hDictKext = pahDictKext[i];
203 CFRetain(pThis->hDictKext);
204 pahKrnlModInfo[i] = pThis;
205 }
206 else
207 {
208 rc = VERR_NO_MEMORY;
209 /* Rollback. */
210 while (i-- > 0)
211 {
212 CFRelease(pahKrnlModInfo[i]->hDictKext);
213 RTMemFree(pahKrnlModInfo[i]);
214 }
215 }
216 }
217
218 if ( RT_SUCCESS(rc)
219 && pcEntries)
220 *pcEntries = cLoadedKexts;
221
222 RTMemTmpFree(pahDictKext);
223 }
224 else
225 rc = VERR_NO_MEMORY;
226 }
227 else
228 {
229 rc = VERR_BUFFER_OVERFLOW;
230
231 if (pcEntries)
232 *pcEntries = cLoadedKexts;
233 }
234
235 CFRelease(hLoadedKexts);
236 }
237 else
238 rc = VERR_NOT_SUPPORTED;
239
240 return rc;
241}
242
243
244RTDECL(uint32_t) RTKrnlModInfoRetain(RTKRNLMODINFO hKrnlModInfo)
245{
246 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
247 AssertPtrReturn(pThis, UINT32_MAX);
248
249 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
250 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
251 return cRefs;
252}
253
254
255RTDECL(uint32_t) RTKrnlModInfoRelease(RTKRNLMODINFO hKrnlModInfo)
256{
257 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
258 if (!pThis)
259 return 0;
260 AssertPtrReturn(pThis, UINT32_MAX);
261
262 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
263 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
264 if (cRefs == 0)
265 rtKrnlModInfoDestroy(pThis);
266 return cRefs;
267}
268
269
270RTDECL(uint32_t) RTKrnlModInfoGetRefCnt(RTKRNLMODINFO hKrnlModInfo)
271{
272 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
273 AssertPtrReturn(pThis, 0);
274
275 uint32_t cRefCnt = 0;
276 CFNumberRef hRetainCnt = (CFNumberRef)CFDictionaryGetValue(pThis->hDictKext,
277 kOSBundleRetainCountKey);
278 if (hRetainCnt)
279 CFNumberGetValue(hRetainCnt, kCFNumberSInt32Type, &cRefCnt);
280
281 return cRefCnt;
282}
283
284
285RTDECL(const char *) RTKrnlModInfoGetName(RTKRNLMODINFO hKrnlModInfo)
286{
287 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
288 AssertPtrReturn(pThis, NULL);
289
290 const char *pszName = NULL;
291 CFStringRef hBundleId = (CFStringRef)CFDictionaryGetValue(pThis->hDictKext,
292 kCFBundleIdentifierKey);
293 if (hBundleId)
294 pszName = CFStringGetCStringPtr(hBundleId, kCFStringEncodingUTF8);
295
296 return pszName;
297}
298
299
300RTDECL(const char *) RTKrnlModInfoGetFilePath(RTKRNLMODINFO hKrnlModInfo)
301{
302 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
303 AssertPtrReturn(pThis, NULL);
304
305 return NULL;
306}
307
308
309RTDECL(size_t) RTKrnlModInfoGetSize(RTKRNLMODINFO hKrnlModInfo)
310{
311 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
312 AssertPtrReturn(pThis, 0);
313
314 size_t cbKrnlMod = 0;
315 CFNumberRef hKrnlModSize = (CFNumberRef)CFDictionaryGetValue(pThis->hDictKext,
316 kOSBundleLoadSizeKey);
317 if (hKrnlModSize)
318 {
319 uint32_t cbTmp = 0;
320 CFNumberGetValue(hKrnlModSize, kCFNumberSInt32Type, &cbTmp);
321 cbKrnlMod = cbTmp;
322 }
323
324 return cbKrnlMod;
325}
326
327
328RTDECL(RTR0UINTPTR) RTKrnlModInfoGetLoadAddr(RTKRNLMODINFO hKrnlModInfo)
329{
330 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
331 AssertPtrReturn(pThis, 0);
332
333 RTR0UINTPTR uKrnlModLoadAddr = 0;
334 CFNumberRef hKrnlModLoadAddr = (CFNumberRef)CFDictionaryGetValue(pThis->hDictKext,
335 kOSBundleLoadAddressKey);
336 if (hKrnlModLoadAddr)
337 {
338 uint64_t uAddrTmp = 0;
339 CFNumberGetValue(hKrnlModLoadAddr, kCFNumberSInt64Type, &uAddrTmp);
340 uKrnlModLoadAddr = uAddrTmp;
341 }
342
343 return uKrnlModLoadAddr;
344}
345
346
347RTDECL(int) RTKrnlModInfoQueryRefModInfo(RTKRNLMODINFO hKrnlModInfo, uint32_t idx,
348 PRTKRNLMODINFO phKrnlModInfoRef)
349{
350 RT_NOREF3(hKrnlModInfo, idx, phKrnlModInfoRef);
351 return VERR_NOT_IMPLEMENTED;
352}
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