VirtualBox

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

Last change on this file since 81784 was 81369, checked in by vboxsync, 5 years ago

*: doxygen fixes

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