VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp@ 54551

Last change on this file since 54551 was 53624, checked in by vboxsync, 10 years ago

scm automatic cleanups.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.2 KB
Line 
1/* $Id: SUPLibLdr.cpp 53624 2014-12-31 14:59:44Z vboxsync $ */
2/** @file
3 * VirtualBox Support Library - Loader related bits.
4 */
5
6/*
7 * Copyright (C) 2006-2013 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/** @page pg_sup SUP - The Support Library
28 *
29 * The support library is responsible for providing facilities to load
30 * VMM Host Ring-0 code, to call Host VMM Ring-0 code from Ring-3 Host
31 * code, to pin down physical memory, and more.
32 *
33 * The VMM Host Ring-0 code can be combined in the support driver if
34 * permitted by kernel module license policies. If it is not combined
35 * it will be externalized in a .r0 module that will be loaded using
36 * the IPRT loader.
37 *
38 * The Ring-0 calling is done thru a generic SUP interface which will
39 * transfer an argument set and call a predefined entry point in the Host
40 * VMM Ring-0 code.
41 *
42 * See @ref grp_sup "SUP - Support APIs" for API details.
43 */
44
45/*******************************************************************************
46* Header Files *
47*******************************************************************************/
48#define LOG_GROUP LOG_GROUP_SUP
49#include <VBox/sup.h>
50#include <VBox/err.h>
51#include <VBox/param.h>
52#include <VBox/log.h>
53#include <VBox/VBoxTpG.h>
54
55#include <iprt/assert.h>
56#include <iprt/alloc.h>
57#include <iprt/alloca.h>
58#include <iprt/ldr.h>
59#include <iprt/asm.h>
60#include <iprt/mp.h>
61#include <iprt/cpuset.h>
62#include <iprt/thread.h>
63#include <iprt/process.h>
64#include <iprt/path.h>
65#include <iprt/string.h>
66#include <iprt/env.h>
67#include <iprt/rand.h>
68#include <iprt/x86.h>
69
70#include "SUPDrvIOC.h"
71#include "SUPLibInternal.h"
72
73
74/*******************************************************************************
75* Defined Constants And Macros *
76*******************************************************************************/
77/** R0 VMM module name. */
78#define VMMR0_NAME "VMMR0"
79
80
81/*******************************************************************************
82* Structures and Typedefs *
83*******************************************************************************/
84typedef DECLCALLBACK(int) FNCALLVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg);
85typedef FNCALLVMMR0 *PFNCALLVMMR0;
86
87
88/*******************************************************************************
89* Global Variables *
90*******************************************************************************/
91/** VMMR0 Load Address. */
92static RTR0PTR g_pvVMMR0 = NIL_RTR0PTR;
93
94
95/*******************************************************************************
96* Internal Functions *
97*******************************************************************************/
98static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase);
99static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
100
101
102SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo)
103{
104 /*
105 * Check that the module can be trusted.
106 */
107 int rc = SUPR3HardenedVerifyPlugIn(pszFilename, pErrInfo);
108 if (RT_SUCCESS(rc))
109 {
110 rc = supLoadModule(pszFilename, pszModule, NULL, ppvImageBase);
111 if (RT_FAILURE(rc))
112 RTErrInfoSetF(pErrInfo, rc, "SUPR3LoadModule: supLoadModule returned %Rrc", rc);
113 }
114 return rc;
115}
116
117
118SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
119 const char *pszSrvReqHandler, void **ppvImageBase)
120{
121 AssertPtrReturn(pszSrvReqHandler, VERR_INVALID_PARAMETER);
122
123 /*
124 * Check that the module can be trusted.
125 */
126 int rc = SUPR3HardenedVerifyPlugIn(pszFilename, NULL /*pErrInfo*/);
127 if (RT_SUCCESS(rc))
128 rc = supLoadModule(pszFilename, pszModule, pszSrvReqHandler, ppvImageBase);
129 else
130 LogRel(("SUPR3LoadServiceModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
131 return rc;
132}
133
134
135/**
136 * Resolve an external symbol during RTLdrGetBits().
137 *
138 * @returns VBox status code.
139 * @param hLdrMod The loader module handle.
140 * @param pszModule Module name.
141 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
142 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
143 * @param pValue Where to store the symbol value (address).
144 * @param pvUser User argument.
145 */
146static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule,
147 const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
148{
149 NOREF(hLdrMod); NOREF(pvUser); NOREF(uSymbol);
150 AssertPtr(pValue);
151 AssertPtr(pvUser);
152
153 /*
154 * Only SUPR0 and VMMR0.r0
155 */
156 if ( pszModule
157 && *pszModule
158 && strcmp(pszModule, "VBoxDrv.sys")
159 && strcmp(pszModule, "VMMR0.r0"))
160 {
161 AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitive)\n", pvUser, pszModule));
162 return VERR_SYMBOL_NOT_FOUND;
163 }
164
165 /*
166 * No ordinals.
167 */
168 if (pszSymbol < (const char*)0x10000)
169 {
170 AssertMsgFailed(("%s is importing by ordinal (ord=%d)\n", pvUser, (int)(uintptr_t)pszSymbol));
171 return VERR_SYMBOL_NOT_FOUND;
172 }
173
174 /*
175 * Lookup symbol.
176 */
177 /** @todo is this actually used??? */
178 /* skip the 64-bit ELF import prefix first. */
179 if (!strncmp(pszSymbol, RT_STR_TUPLE("SUPR0$")))
180 pszSymbol += sizeof("SUPR0$") - 1;
181
182 /*
183 * Check the VMMR0.r0 module if loaded.
184 */
185 /** @todo call the SUPR3LoadModule caller.... */
186 /** @todo proper reference counting and such. */
187 if (g_pvVMMR0 != NIL_RTR0PTR)
188 {
189 void *pvValue;
190 if (!SUPR3GetSymbolR0((void *)g_pvVMMR0, pszSymbol, &pvValue))
191 {
192 *pValue = (uintptr_t)pvValue;
193 return VINF_SUCCESS;
194 }
195 }
196
197 /* iterate the function table. */
198 int c = g_pSupFunctions->u.Out.cFunctions;
199 PSUPFUNC pFunc = &g_pSupFunctions->u.Out.aFunctions[0];
200 while (c-- > 0)
201 {
202 if (!strcmp(pFunc->szName, pszSymbol))
203 {
204 *pValue = (uintptr_t)pFunc->pfn;
205 return VINF_SUCCESS;
206 }
207 pFunc++;
208 }
209
210 /*
211 * The GIP.
212 */
213 if ( pszSymbol
214 && g_pSUPGlobalInfoPage
215 && g_pSUPGlobalInfoPageR0
216 && !strcmp(pszSymbol, "g_SUPGlobalInfoPage")
217 )
218 {
219 *pValue = (uintptr_t)g_pSUPGlobalInfoPageR0;
220 return VINF_SUCCESS;
221 }
222
223 /*
224 * Symbols that are undefined by convention.
225 */
226#ifdef RT_OS_SOLARIS
227 static const char * const s_apszConvSyms[] =
228 {
229 "", "mod_getctl",
230 "", "mod_install",
231 "", "mod_remove",
232 "", "mod_info",
233 "", "mod_miscops",
234 };
235 for (unsigned i = 0; i < RT_ELEMENTS(s_apszConvSyms); i += 2)
236 {
237 if ( !RTStrCmp(s_apszConvSyms[i], pszModule)
238 && !RTStrCmp(s_apszConvSyms[i + 1], pszSymbol))
239 {
240 *pValue = ~(uintptr_t)0;
241 return VINF_SUCCESS;
242 }
243 }
244#endif
245
246 /*
247 * Despair.
248 */
249 c = g_pSupFunctions->u.Out.cFunctions;
250 pFunc = &g_pSupFunctions->u.Out.aFunctions[0];
251 while (c-- > 0)
252 {
253 RTAssertMsg2Weak("%d: %s\n", g_pSupFunctions->u.Out.cFunctions - c, pFunc->szName);
254 pFunc++;
255 }
256
257 AssertLogRelMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol));
258 if (g_uSupFakeMode)
259 {
260 *pValue = 0xdeadbeef;
261 return VINF_SUCCESS;
262 }
263 return VERR_SYMBOL_NOT_FOUND;
264}
265
266
267/** Argument package for supLoadModuleCalcSizeCB. */
268typedef struct SUPLDRCALCSIZEARGS
269{
270 size_t cbStrings;
271 uint32_t cSymbols;
272 size_t cbImage;
273} SUPLDRCALCSIZEARGS, *PSUPLDRCALCSIZEARGS;
274
275/**
276 * Callback used to calculate the image size.
277 * @return VINF_SUCCESS
278 */
279static DECLCALLBACK(int) supLoadModuleCalcSizeCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
280{
281 PSUPLDRCALCSIZEARGS pArgs = (PSUPLDRCALCSIZEARGS)pvUser;
282 if ( pszSymbol != NULL
283 && *pszSymbol
284 && Value <= pArgs->cbImage)
285 {
286 pArgs->cSymbols++;
287 pArgs->cbStrings += strlen(pszSymbol) + 1;
288 }
289 NOREF(hLdrMod); NOREF(uSymbol);
290 return VINF_SUCCESS;
291}
292
293
294/** Argument package for supLoadModuleCreateTabsCB. */
295typedef struct SUPLDRCREATETABSARGS
296{
297 size_t cbImage;
298 PSUPLDRSYM pSym;
299 char *pszBase;
300 char *psz;
301} SUPLDRCREATETABSARGS, *PSUPLDRCREATETABSARGS;
302
303/**
304 * Callback used to calculate the image size.
305 * @return VINF_SUCCESS
306 */
307static DECLCALLBACK(int) supLoadModuleCreateTabsCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
308{
309 PSUPLDRCREATETABSARGS pArgs = (PSUPLDRCREATETABSARGS)pvUser;
310 if ( pszSymbol != NULL
311 && *pszSymbol
312 && Value <= pArgs->cbImage)
313 {
314 pArgs->pSym->offSymbol = (uint32_t)Value;
315 pArgs->pSym->offName = pArgs->psz - pArgs->pszBase;
316 pArgs->pSym++;
317
318 size_t cbCopy = strlen(pszSymbol) + 1;
319 memcpy(pArgs->psz, pszSymbol, cbCopy);
320 pArgs->psz += cbCopy;
321 }
322 NOREF(hLdrMod); NOREF(uSymbol);
323 return VINF_SUCCESS;
324}
325
326
327/**
328 * Worker for SUPR3LoadModule().
329 *
330 * @returns VBox status code.
331 * @param pszFilename Name of the VMMR0 image file
332 */
333static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase)
334{
335 int rc;
336
337 /*
338 * Validate input.
339 */
340 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
341 AssertPtrReturn(pszModule, VERR_INVALID_PARAMETER);
342 AssertPtrReturn(ppvImageBase, VERR_INVALID_PARAMETER);
343 AssertReturn(strlen(pszModule) < RT_SIZEOFMEMB(SUPLDROPEN, u.In.szName), VERR_FILENAME_TOO_LONG);
344 char szAbsFilename[RT_SIZEOFMEMB(SUPLDROPEN, u.In.szFilename)];
345 rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));
346 if (RT_FAILURE(rc))
347 return rc;
348 pszFilename = szAbsFilename;
349
350 const bool fIsVMMR0 = !strcmp(pszModule, "VMMR0.r0");
351 AssertReturn(!pszSrvReqHandler || !fIsVMMR0, VERR_INTERNAL_ERROR);
352 *ppvImageBase = NULL;
353
354 /*
355 * Open image file and figure its size.
356 */
357 RTLDRMOD hLdrMod;
358 rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_HOST, &hLdrMod);
359 if (!RT_SUCCESS(rc))
360 {
361 LogRel(("SUP: RTLdrOpen failed for %s (%s)\n", pszModule, pszFilename, rc));
362 return rc;
363 }
364
365 SUPLDRCALCSIZEARGS CalcArgs;
366 CalcArgs.cbStrings = 0;
367 CalcArgs.cSymbols = 0;
368 CalcArgs.cbImage = RTLdrSize(hLdrMod);
369 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCalcSizeCB, &CalcArgs);
370 if (RT_SUCCESS(rc))
371 {
372 const uint32_t offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
373 const uint32_t offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
374 const uint32_t cbImageWithTabs = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);
375
376 /*
377 * Open the R0 image.
378 */
379 SUPLDROPEN OpenReq;
380 OpenReq.Hdr.u32Cookie = g_u32Cookie;
381 OpenReq.Hdr.u32SessionCookie = g_u32SessionCookie;
382 OpenReq.Hdr.cbIn = SUP_IOCTL_LDR_OPEN_SIZE_IN;
383 OpenReq.Hdr.cbOut = SUP_IOCTL_LDR_OPEN_SIZE_OUT;
384 OpenReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
385 OpenReq.Hdr.rc = VERR_INTERNAL_ERROR;
386 OpenReq.u.In.cbImageWithTabs = cbImageWithTabs;
387 OpenReq.u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;
388 strcpy(OpenReq.u.In.szName, pszModule);
389 strcpy(OpenReq.u.In.szFilename, pszFilename);
390 if (!g_uSupFakeMode)
391 {
392 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);
393 if (RT_SUCCESS(rc))
394 rc = OpenReq.Hdr.rc;
395 }
396 else
397 {
398 OpenReq.u.Out.fNeedsLoading = true;
399 OpenReq.u.Out.pvImageBase = 0xef423420;
400 }
401 *ppvImageBase = (void *)OpenReq.u.Out.pvImageBase;
402 if ( RT_SUCCESS(rc)
403 && OpenReq.u.Out.fNeedsLoading)
404 {
405 /*
406 * We need to load it.
407 * Allocate memory for the image bits.
408 */
409 PSUPLDRLOAD pLoadReq = (PSUPLDRLOAD)RTMemTmpAlloc(SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
410 if (pLoadReq)
411 {
412 /*
413 * Get the image bits.
414 */
415 rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
416 supLoadModuleResolveImport, (void *)pszModule);
417
418 if (RT_SUCCESS(rc))
419 {
420 /*
421 * Get the entry points.
422 */
423 RTUINTPTR VMMR0EntryInt = 0;
424 RTUINTPTR VMMR0EntryFast = 0;
425 RTUINTPTR VMMR0EntryEx = 0;
426 RTUINTPTR SrvReqHandler = 0;
427 RTUINTPTR ModuleInit = 0;
428 RTUINTPTR ModuleTerm = 0;
429 if (fIsVMMR0)
430 {
431 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "VMMR0EntryInt", &VMMR0EntryInt);
432 if (RT_SUCCESS(rc))
433 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "VMMR0EntryFast", &VMMR0EntryFast);
434 if (RT_SUCCESS(rc))
435 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "VMMR0EntryEx", &VMMR0EntryEx);
436 }
437 else if (pszSrvReqHandler)
438 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, pszSrvReqHandler, &SrvReqHandler);
439 if (RT_SUCCESS(rc))
440 {
441 int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "ModuleInit", &ModuleInit);
442 if (RT_FAILURE(rc2))
443 ModuleInit = 0;
444
445 rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "ModuleTerm", &ModuleTerm);
446 if (RT_FAILURE(rc2))
447 ModuleTerm = 0;
448 }
449 if (RT_SUCCESS(rc))
450 {
451 /*
452 * Create the symbol and string tables.
453 */
454 SUPLDRCREATETABSARGS CreateArgs;
455 CreateArgs.cbImage = CalcArgs.cbImage;
456 CreateArgs.pSym = (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab];
457 CreateArgs.pszBase = (char *)&pLoadReq->u.In.abImage[offStrTab];
458 CreateArgs.psz = CreateArgs.pszBase;
459 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);
460 if (RT_SUCCESS(rc))
461 {
462 AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= CalcArgs.cbStrings);
463 AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab]) <= CalcArgs.cSymbols);
464
465 /*
466 * Upload the image.
467 */
468 pLoadReq->Hdr.u32Cookie = g_u32Cookie;
469 pLoadReq->Hdr.u32SessionCookie = g_u32SessionCookie;
470 pLoadReq->Hdr.cbIn = SUP_IOCTL_LDR_LOAD_SIZE_IN(cbImageWithTabs);
471 pLoadReq->Hdr.cbOut = SUP_IOCTL_LDR_LOAD_SIZE_OUT;
472 pLoadReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_IN;
473 pLoadReq->Hdr.rc = VERR_INTERNAL_ERROR;
474
475 pLoadReq->u.In.pfnModuleInit = (RTR0PTR)ModuleInit;
476 pLoadReq->u.In.pfnModuleTerm = (RTR0PTR)ModuleTerm;
477 if (fIsVMMR0)
478 {
479 pLoadReq->u.In.eEPType = SUPLDRLOADEP_VMMR0;
480 pLoadReq->u.In.EP.VMMR0.pvVMMR0 = OpenReq.u.Out.pvImageBase;
481 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryInt = (RTR0PTR)VMMR0EntryInt;
482 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryFast= (RTR0PTR)VMMR0EntryFast;
483 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryEx = (RTR0PTR)VMMR0EntryEx;
484 }
485 else if (pszSrvReqHandler)
486 {
487 pLoadReq->u.In.eEPType = SUPLDRLOADEP_SERVICE;
488 pLoadReq->u.In.EP.Service.pfnServiceReq = (RTR0PTR)SrvReqHandler;
489 pLoadReq->u.In.EP.Service.apvReserved[0] = NIL_RTR0PTR;
490 pLoadReq->u.In.EP.Service.apvReserved[1] = NIL_RTR0PTR;
491 pLoadReq->u.In.EP.Service.apvReserved[2] = NIL_RTR0PTR;
492 }
493 else
494 pLoadReq->u.In.eEPType = SUPLDRLOADEP_NOTHING;
495 pLoadReq->u.In.offStrTab = offStrTab;
496 pLoadReq->u.In.cbStrTab = (uint32_t)CalcArgs.cbStrings;
497 AssertRelease(pLoadReq->u.In.cbStrTab == CalcArgs.cbStrings);
498 pLoadReq->u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;
499 pLoadReq->u.In.offSymbols = offSymTab;
500 pLoadReq->u.In.cSymbols = CalcArgs.cSymbols;
501 pLoadReq->u.In.cbImageWithTabs = cbImageWithTabs;
502 pLoadReq->u.In.pvImageBase = OpenReq.u.Out.pvImageBase;
503 if (!g_uSupFakeMode)
504 {
505 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
506 if (RT_SUCCESS(rc))
507 rc = pLoadReq->Hdr.rc;
508 else
509 LogRel(("SUP: SUP_IOCTL_LDR_LOAD ioctl for %s (%s) failed rc=%Rrc\n", pszModule, pszFilename, rc));
510 }
511 else
512 rc = VINF_SUCCESS;
513 if ( RT_SUCCESS(rc)
514 || rc == VERR_ALREADY_LOADED /* A competing process. */
515 )
516 {
517 LogRel(("SUP: Loaded %s (%s) at %#p - ModuleInit at %RTptr and ModuleTerm at %RTptr%s\n",
518 pszModule, pszFilename, OpenReq.u.Out.pvImageBase, ModuleInit, ModuleTerm,
519 OpenReq.u.Out.fNativeLoader ? " using the native ring-0 loader" : ""));
520 if (fIsVMMR0)
521 {
522 g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
523 LogRel(("SUP: VMMR0EntryEx located at %RTptr, VMMR0EntryFast at %RTptr and VMMR0EntryInt at %RTptr\n",
524 VMMR0EntryEx, VMMR0EntryFast, VMMR0EntryInt));
525 }
526#ifdef RT_OS_WINDOWS
527 LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
528#endif
529
530 RTMemTmpFree(pLoadReq);
531 RTLdrClose(hLdrMod);
532 return VINF_SUCCESS;
533 }
534 else
535 LogRel(("SUP: Loading failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
536 }
537 else
538 LogRel(("SUP: RTLdrEnumSymbols failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
539 }
540 else
541 LogRel(("SUP: Failed to get entry points for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
542 }
543 else
544 LogRel(("SUP: RTLdrGetBits failed for %s (%s). rc=%Rrc\n", pszModule, pszFilename, rc));
545 RTMemTmpFree(pLoadReq);
546 }
547 else
548 {
549 AssertMsgFailed(("failed to allocated %u bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs)));
550 rc = VERR_NO_TMP_MEMORY;
551 }
552 }
553 else if (RT_SUCCESS(rc))
554 {
555 if (fIsVMMR0)
556 g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
557 LogRel(("SUP: Opened %s (%s) at %#p.\n", pszModule, pszFilename, OpenReq.u.Out.pvImageBase,
558 OpenReq.u.Out.fNativeLoader ? " loaded by the native ring-0 loader" : ""));
559#ifdef RT_OS_WINDOWS
560 LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
561#endif
562 }
563 }
564 RTLdrClose(hLdrMod);
565 return rc;
566}
567
568
569SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase)
570{
571 /* fake */
572 if (RT_UNLIKELY(g_uSupFakeMode))
573 {
574 g_pvVMMR0 = NIL_RTR0PTR;
575 return VINF_SUCCESS;
576 }
577
578 /*
579 * Free the requested module.
580 */
581 SUPLDRFREE Req;
582 Req.Hdr.u32Cookie = g_u32Cookie;
583 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
584 Req.Hdr.cbIn = SUP_IOCTL_LDR_FREE_SIZE_IN;
585 Req.Hdr.cbOut = SUP_IOCTL_LDR_FREE_SIZE_OUT;
586 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
587 Req.Hdr.rc = VERR_INTERNAL_ERROR;
588 Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
589 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_FREE, &Req, SUP_IOCTL_LDR_FREE_SIZE);
590 if (RT_SUCCESS(rc))
591 rc = Req.Hdr.rc;
592 if ( RT_SUCCESS(rc)
593 && (RTR0PTR)pvImageBase == g_pvVMMR0)
594 g_pvVMMR0 = NIL_RTR0PTR;
595 return rc;
596}
597
598
599SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue)
600{
601 *ppvValue = NULL;
602
603 /* fake */
604 if (RT_UNLIKELY(g_uSupFakeMode))
605 {
606 *ppvValue = (void *)(uintptr_t)0xdeadf00d;
607 return VINF_SUCCESS;
608 }
609
610 /*
611 * Do ioctl.
612 */
613 SUPLDRGETSYMBOL Req;
614 Req.Hdr.u32Cookie = g_u32Cookie;
615 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
616 Req.Hdr.cbIn = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_IN;
617 Req.Hdr.cbOut = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_OUT;
618 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
619 Req.Hdr.rc = VERR_INTERNAL_ERROR;
620 Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
621 size_t cchSymbol = strlen(pszSymbol);
622 if (cchSymbol >= sizeof(Req.u.In.szSymbol))
623 return VERR_SYMBOL_NOT_FOUND;
624 memcpy(Req.u.In.szSymbol, pszSymbol, cchSymbol + 1);
625 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_GET_SYMBOL, &Req, SUP_IOCTL_LDR_GET_SYMBOL_SIZE);
626 if (RT_SUCCESS(rc))
627 rc = Req.Hdr.rc;
628 if (RT_SUCCESS(rc))
629 *ppvValue = (void *)Req.u.Out.pvSymbol;
630 return rc;
631}
632
633
634SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename)
635{
636 void *pvImageBase;
637 return SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase, NULL /*pErrInfo*/);
638}
639
640
641SUPR3DECL(int) SUPR3UnloadVMM(void)
642{
643 return SUPR3FreeModule((void*)g_pvVMMR0);
644}
645
646
647/**
648 * Worker for SUPR3HardenedLdrLoad and SUPR3HardenedLdrLoadAppPriv.
649 *
650 * @returns iprt status code.
651 * @param pszFilename The full file name.
652 * @param phLdrMod Where to store the handle to the loaded module.
653 * @param fFlags See RTLDFLAGS_.
654 * @param pErrInfo Where to return extended error information.
655 * Optional.
656 *
657 */
658static int supR3HardenedLdrLoadIt(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
659{
660#ifdef VBOX_WITH_HARDENING
661 /*
662 * Verify the image file.
663 */
664 int rc = SUPR3HardenedVerifyInit();
665 if (RT_FAILURE(rc))
666 rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */);
667 if (RT_FAILURE(rc))
668 {
669 LogRel(("supR3HardenedLdrLoadIt: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
670 return RTErrInfoSet(pErrInfo, rc, "supR3HardenedVerifyFixedFile failed");
671 }
672#endif
673
674 /*
675 * Try load it.
676 */
677 return RTLdrLoadEx(pszFilename, phLdrMod, fFlags, pErrInfo);
678}
679
680
681SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
682{
683 /*
684 * Validate input.
685 */
686 RTErrInfoClear(pErrInfo);
687 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
688 AssertPtrReturn(phLdrMod, VERR_INVALID_POINTER);
689 *phLdrMod = NIL_RTLDRMOD;
690 AssertReturn(RTPathHavePath(pszFilename), VERR_INVALID_PARAMETER);
691
692 /*
693 * Add the default extension if it's missing.
694 */
695 if (!RTPathHasSuffix(pszFilename))
696 {
697 const char *pszSuff = RTLdrGetSuff();
698 size_t cchSuff = strlen(pszSuff);
699 size_t cchFilename = strlen(pszFilename);
700 char *psz = (char *)alloca(cchFilename + cchSuff + 1);
701 AssertReturn(psz, VERR_NO_TMP_MEMORY);
702 memcpy(psz, pszFilename, cchFilename);
703 memcpy(psz + cchFilename, pszSuff, cchSuff + 1);
704 pszFilename = psz;
705 }
706
707 /*
708 * Pass it on to the common library loader.
709 */
710 return supR3HardenedLdrLoadIt(pszFilename, phLdrMod, fFlags, pErrInfo);
711}
712
713
714SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
715{
716 LogFlow(("SUPR3HardenedLdrLoadAppPriv: pszFilename=%p:{%s} phLdrMod=%p fFlags=%08x pErrInfo=%p\n", pszFilename, pszFilename, phLdrMod, fFlags, pErrInfo));
717
718 /*
719 * Validate input.
720 */
721 RTErrInfoClear(pErrInfo);
722 AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
723 *phLdrMod = NIL_RTLDRMOD;
724 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
725 AssertMsgReturn(!RTPathHavePath(pszFilename), ("%s\n", pszFilename), VERR_INVALID_PARAMETER);
726
727 /*
728 * Check the filename.
729 */
730 size_t cchFilename = strlen(pszFilename);
731 AssertMsgReturn(cchFilename < (RTPATH_MAX / 4) * 3, ("%zu\n", cchFilename), VERR_INVALID_PARAMETER);
732
733 const char *pszExt = "";
734 size_t cchExt = 0;
735 if (!RTPathHasSuffix(pszFilename))
736 {
737 pszExt = RTLdrGetSuff();
738 cchExt = strlen(pszExt);
739 }
740
741 /*
742 * Construct the private arch path and check if the file exists.
743 */
744 char szPath[RTPATH_MAX];
745 int rc = RTPathAppPrivateArch(szPath, sizeof(szPath) - 1 - cchExt - cchFilename);
746 AssertRCReturn(rc, rc);
747
748 char *psz = strchr(szPath, '\0');
749 *psz++ = RTPATH_SLASH;
750 memcpy(psz, pszFilename, cchFilename);
751 psz += cchFilename;
752 memcpy(psz, pszExt, cchExt + 1);
753
754 if (!RTPathExists(szPath))
755 {
756 LogRel(("SUPR3HardenedLdrLoadAppPriv: \"%s\" not found\n", szPath));
757 return VERR_FILE_NOT_FOUND;
758 }
759
760 /*
761 * Pass it on to SUPR3HardenedLdrLoad.
762 */
763 rc = SUPR3HardenedLdrLoad(szPath, phLdrMod, fFlags, pErrInfo);
764
765 LogFlow(("SUPR3HardenedLdrLoadAppPriv: returns %Rrc\n", rc));
766 return rc;
767}
768
769
770SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
771{
772 /*
773 * Validate input.
774 */
775 RTErrInfoClear(pErrInfo);
776 AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
777 *phLdrMod = NIL_RTLDRMOD;
778 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
779 AssertReturn(RTPathStartsWithRoot(pszFilename), VERR_INVALID_PARAMETER);
780
781#ifdef VBOX_WITH_HARDENING
782 /*
783 * Verify the image file.
784 */
785 int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, true /*fMaybe3rdParty*/, pErrInfo);
786 if (RT_FAILURE(rc))
787 {
788 if (!RTErrInfoIsSet(pErrInfo))
789 LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
790 return rc;
791 }
792#endif
793
794 /*
795 * Try load it.
796 */
797 return RTLdrLoadEx(pszFilename, phLdrMod, RTLDRLOAD_FLAGS_LOCAL, pErrInfo);
798}
799
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