VirtualBox

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

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