VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/SUPLib.cpp@ 20953

Last change on this file since 20953 was 20866, checked in by vboxsync, 16 years ago

SUP: Removed two obsolete allocation APIs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 72.3 KB
Line 
1/* $Id: SUPLib.cpp 20866 2009-06-23 19:33:23Z vboxsync $ */
2/** @file
3 * VirtualBox Support Library - Common code.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/** @page pg_sup SUP - The Support Library
32 *
33 * The support library is responsible for providing facilities to load
34 * VMM Host Ring-0 code, to call Host VMM Ring-0 code from Ring-3 Host
35 * code, to pin down physical memory, and more.
36 *
37 * The VMM Host Ring-0 code can be combined in the support driver if
38 * permitted by kernel module license policies. If it is not combined
39 * it will be externalized in a .r0 module that will be loaded using
40 * the IPRT loader.
41 *
42 * The Ring-0 calling is done thru a generic SUP interface which will
43 * tranfer an argument set and call a predefined entry point in the Host
44 * VMM Ring-0 code.
45 *
46 * See @ref grp_sup "SUP - Support APIs" for API details.
47 */
48
49/*******************************************************************************
50* Header Files *
51*******************************************************************************/
52#define LOG_GROUP LOG_GROUP_SUP
53#include <VBox/sup.h>
54#include <VBox/err.h>
55#include <VBox/param.h>
56#include <VBox/vmm.h>
57#include <VBox/log.h>
58#include <VBox/x86.h>
59
60#include <iprt/assert.h>
61#include <iprt/alloc.h>
62#include <iprt/alloca.h>
63#include <iprt/ldr.h>
64#include <iprt/asm.h>
65#include <iprt/mp.h>
66#include <iprt/cpuset.h>
67#include <iprt/thread.h>
68#include <iprt/process.h>
69#include <iprt/path.h>
70#include <iprt/string.h>
71#include <iprt/env.h>
72#include <iprt/rand.h>
73
74#include "SUPLibInternal.h"
75#include "SUPDrvIOC.h"
76
77
78/*******************************************************************************
79* Defined Constants And Macros *
80*******************************************************************************/
81/** R0 VMM module name. */
82#define VMMR0_NAME "VMMR0"
83
84
85/*******************************************************************************
86* Structures and Typedefs *
87*******************************************************************************/
88typedef DECLCALLBACK(int) FNCALLVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg);
89typedef FNCALLVMMR0 *PFNCALLVMMR0;
90
91
92/*******************************************************************************
93* Global Variables *
94*******************************************************************************/
95/** Init counter. */
96static uint32_t g_cInits = 0;
97/** Whether we've been preinitied. */
98static bool g_fPreInited = false;
99/** The SUPLib instance data.
100 * Well, at least parts of it, specificly the parts that are being handed over
101 * via the pre-init mechanism from the hardened executable stub. */
102SUPLIBDATA g_supLibData =
103{
104 NIL_RTFILE
105#if defined(RT_OS_DARWIN)
106 , NULL
107#elif defined(RT_OS_LINUX)
108 , false
109#endif
110};
111
112/** Pointer to the Global Information Page.
113 *
114 * This pointer is valid as long as SUPLib has a open session. Anyone using
115 * the page must treat this pointer as higly volatile and not trust it beyond
116 * one transaction.
117 *
118 * @todo This will probably deserve it's own session or some other good solution...
119 */
120DECLEXPORT(PSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage;
121/** Address of the ring-0 mapping of the GIP. */
122static PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPageR0;
123/** The physical address of the GIP. */
124static RTHCPHYS g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS;
125
126/** The negotiated cookie. */
127uint32_t g_u32Cookie = 0;
128/** The negotiated session cookie. */
129uint32_t g_u32SessionCookie;
130/** Session handle. */
131PSUPDRVSESSION g_pSession;
132/** R0 SUP Functions used for resolving referenced to the SUPR0 module. */
133static PSUPQUERYFUNCS g_pFunctions;
134
135/** VMMR0 Load Address. */
136static RTR0PTR g_pvVMMR0 = NIL_RTR0PTR;
137/** PAGE_ALLOC_EX sans kernel mapping support indicator. */
138static bool g_fSupportsPageAllocNoKernel = true;
139/** Fake mode indicator. (~0 at first, 0 or 1 after first test) */
140static uint32_t g_u32FakeMode = ~0;
141
142
143/*******************************************************************************
144* Internal Functions *
145*******************************************************************************/
146static int supInitFake(PSUPDRVSESSION *ppSession);
147static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase);
148static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
149
150
151SUPR3DECL(int) SUPR3Install(void)
152{
153 return suplibOsInstall();
154}
155
156
157SUPR3DECL(int) SUPR3Uninstall(void)
158{
159 return suplibOsUninstall();
160}
161
162
163DECLEXPORT(int) supR3PreInit(PSUPPREINITDATA pPreInitData, uint32_t fFlags)
164{
165 /*
166 * The caller is kind of trustworthy, just perform some basic checks.
167 *
168 * Note! Do not do any fancy stuff here because IPRT has NOT been
169 * initialized at this point.
170 */
171 if (!VALID_PTR(pPreInitData))
172 return VERR_INVALID_POINTER;
173 if (g_fPreInited || g_cInits > 0)
174 return VERR_WRONG_ORDER;
175
176 if ( pPreInitData->u32Magic != SUPPREINITDATA_MAGIC
177 || pPreInitData->u32EndMagic != SUPPREINITDATA_MAGIC)
178 return VERR_INVALID_MAGIC;
179 if ( !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
180 && pPreInitData->Data.hDevice == NIL_RTFILE)
181 return VERR_INVALID_HANDLE;
182 if ( (fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
183 && pPreInitData->Data.hDevice != NIL_RTFILE)
184 return VERR_INVALID_PARAMETER;
185
186 /*
187 * Hand out the data.
188 */
189 int rc = supR3HardenedRecvPreInitData(pPreInitData);
190 if (RT_FAILURE(rc))
191 return rc;
192
193 /** @todo This may need some small restructuring later, it doesn't quite work with a root service flag... */
194 if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
195 {
196 g_supLibData = pPreInitData->Data;
197 g_fPreInited = true;
198 }
199
200 return VINF_SUCCESS;
201}
202
203
204SUPR3DECL(int) SUPR3Init(PSUPDRVSESSION *ppSession)
205{
206 /*
207 * Perform some sanity checks.
208 * (Got some trouble with compile time member alignment assertions.)
209 */
210 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, u64NanoTSLastUpdateHz) & 0x7));
211 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs) & 0x1f));
212 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[1]) & 0x1f));
213 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64NanoTS) & 0x7));
214 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64TSC) & 0x7));
215 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64CpuHz) & 0x7));
216
217 /*
218 * Check if already initialized.
219 */
220 if (ppSession)
221 *ppSession = g_pSession;
222 if (g_cInits++ > 0)
223 return VINF_SUCCESS;
224
225 /*
226 * Check for fake mode.
227 *
228 * Fake mode is used when we're doing smoke testing and debugging.
229 * It's also useful on platforms where we haven't root access or which
230 * we haven't ported the support driver to.
231 */
232 if (g_u32FakeMode == ~0U)
233 {
234 const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE");
235 if (psz && !strcmp(psz, "fake"))
236 ASMAtomicCmpXchgU32(&g_u32FakeMode, 1, ~0U);
237 else
238 ASMAtomicCmpXchgU32(&g_u32FakeMode, 0, ~0U);
239 }
240 if (RT_UNLIKELY(g_u32FakeMode))
241 return supInitFake(ppSession);
242
243 /*
244 * Open the support driver.
245 */
246 int rc = suplibOsInit(&g_supLibData, g_fPreInited);
247 if (RT_SUCCESS(rc))
248 {
249 /*
250 * Negotiate the cookie.
251 */
252 SUPCOOKIE CookieReq;
253 memset(&CookieReq, 0xff, sizeof(CookieReq));
254 CookieReq.Hdr.u32Cookie = SUPCOOKIE_INITIAL_COOKIE;
255 CookieReq.Hdr.u32SessionCookie = RTRandU32();
256 CookieReq.Hdr.cbIn = SUP_IOCTL_COOKIE_SIZE_IN;
257 CookieReq.Hdr.cbOut = SUP_IOCTL_COOKIE_SIZE_OUT;
258 CookieReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
259 CookieReq.Hdr.rc = VERR_INTERNAL_ERROR;
260 strcpy(CookieReq.u.In.szMagic, SUPCOOKIE_MAGIC);
261 CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
262 const uint32_t MinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x000d0000
263 ? 0x000d0001
264 : SUPDRV_IOC_VERSION & 0xffff0000;
265 CookieReq.u.In.u32MinVersion = MinVersion;
266 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_COOKIE, &CookieReq, SUP_IOCTL_COOKIE_SIZE);
267 if ( RT_SUCCESS(rc)
268 && RT_SUCCESS(CookieReq.Hdr.rc))
269 {
270 if ( (CookieReq.u.Out.u32SessionVersion & 0xffff0000) == (SUPDRV_IOC_VERSION & 0xffff0000)
271 && CookieReq.u.Out.u32SessionVersion >= MinVersion)
272 {
273 /*
274 * Query the functions.
275 */
276 PSUPQUERYFUNCS pFuncsReq = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(CookieReq.u.Out.cFunctions));
277 if (pFuncsReq)
278 {
279 pFuncsReq->Hdr.u32Cookie = CookieReq.u.Out.u32Cookie;
280 pFuncsReq->Hdr.u32SessionCookie = CookieReq.u.Out.u32SessionCookie;
281 pFuncsReq->Hdr.cbIn = SUP_IOCTL_QUERY_FUNCS_SIZE_IN;
282 pFuncsReq->Hdr.cbOut = SUP_IOCTL_QUERY_FUNCS_SIZE_OUT(CookieReq.u.Out.cFunctions);
283 pFuncsReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
284 pFuncsReq->Hdr.rc = VERR_INTERNAL_ERROR;
285 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_QUERY_FUNCS(CookieReq.u.Out.cFunctions), pFuncsReq, SUP_IOCTL_QUERY_FUNCS_SIZE(CookieReq.u.Out.cFunctions));
286 if (RT_SUCCESS(rc))
287 rc = pFuncsReq->Hdr.rc;
288 if (RT_SUCCESS(rc))
289 {
290 /*
291 * Map the GIP into userspace.
292 */
293 Assert(!g_pSUPGlobalInfoPage);
294 SUPGIPMAP GipMapReq;
295 GipMapReq.Hdr.u32Cookie = CookieReq.u.Out.u32Cookie;
296 GipMapReq.Hdr.u32SessionCookie = CookieReq.u.Out.u32SessionCookie;
297 GipMapReq.Hdr.cbIn = SUP_IOCTL_GIP_MAP_SIZE_IN;
298 GipMapReq.Hdr.cbOut = SUP_IOCTL_GIP_MAP_SIZE_OUT;
299 GipMapReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
300 GipMapReq.Hdr.rc = VERR_INTERNAL_ERROR;
301 GipMapReq.u.Out.HCPhysGip = NIL_RTHCPHYS;
302 GipMapReq.u.Out.pGipR0 = NIL_RTR0PTR;
303 GipMapReq.u.Out.pGipR3 = NULL;
304 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GIP_MAP, &GipMapReq, SUP_IOCTL_GIP_MAP_SIZE);
305 if (RT_SUCCESS(rc))
306 rc = GipMapReq.Hdr.rc;
307 if (RT_SUCCESS(rc))
308 {
309 AssertRelease(GipMapReq.u.Out.pGipR3->u32Magic == SUPGLOBALINFOPAGE_MAGIC);
310 AssertRelease(GipMapReq.u.Out.pGipR3->u32Version >= SUPGLOBALINFOPAGE_VERSION);
311
312 /*
313 * Set the globals and return success.
314 */
315 ASMAtomicXchgSize(&g_HCPhysSUPGlobalInfoPage, GipMapReq.u.Out.HCPhysGip);
316 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPage, GipMapReq.u.Out.pGipR3, NULL);
317 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPageR0, (void *)GipMapReq.u.Out.pGipR0, NULL);
318
319 g_u32Cookie = CookieReq.u.Out.u32Cookie;
320 g_u32SessionCookie = CookieReq.u.Out.u32SessionCookie;
321 g_pSession = CookieReq.u.Out.pSession;
322 g_pFunctions = pFuncsReq;
323 if (ppSession)
324 *ppSession = CookieReq.u.Out.pSession;
325 return VINF_SUCCESS;
326 }
327 }
328
329 /* bailout */
330 RTMemFree(pFuncsReq);
331 }
332 else
333 rc = VERR_NO_MEMORY;
334 }
335 else
336 {
337 LogRel(("Support driver version mismatch: SessionVersion=%#x DriverVersion=%#x ClientVersion=%#x MinVersion=%#x\n",
338 CookieReq.u.Out.u32SessionVersion, CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, MinVersion));
339 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
340 }
341 }
342 else
343 {
344 if (RT_SUCCESS(rc))
345 {
346 rc = CookieReq.Hdr.rc;
347 LogRel(("Support driver version mismatch: DriverVersion=%#x ClientVersion=%#x rc=%Rrc\n",
348 CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, rc));
349 if (rc != VERR_VM_DRIVER_VERSION_MISMATCH)
350 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
351 }
352 else
353 {
354 /* for pre 0x00060000 drivers */
355 LogRel(("Support driver version mismatch: DriverVersion=too-old ClientVersion=%#x\n", SUPDRV_IOC_VERSION));
356 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
357 }
358 }
359
360 suplibOsTerm(&g_supLibData);
361 }
362 g_cInits--;
363
364 return rc;
365}
366
367/**
368 * Fake mode init.
369 */
370static int supInitFake(PSUPDRVSESSION *ppSession)
371{
372 Log(("SUP: Fake mode!\n"));
373 static const SUPFUNC s_aFakeFunctions[] =
374 {
375 /* name function */
376 { "SUPR0AbsIs64bit", 0 },
377 { "SUPR0Abs64bitKernelCS", 0 },
378 { "SUPR0Abs64bitKernelSS", 0 },
379 { "SUPR0Abs64bitKernelDS", 0 },
380 { "SUPR0AbsKernelCS", 8 },
381 { "SUPR0AbsKernelSS", 16 },
382 { "SUPR0AbsKernelDS", 16 },
383 { "SUPR0AbsKernelES", 16 },
384 { "SUPR0AbsKernelFS", 24 },
385 { "SUPR0AbsKernelGS", 32 },
386 { "SUPR0ComponentRegisterFactory", 0xefeefffd },
387 { "SUPR0ComponentDeregisterFactory", 0xefeefffe },
388 { "SUPR0ComponentQueryFactory", 0xefeeffff },
389 { "SUPR0ObjRegister", 0xefef0000 },
390 { "SUPR0ObjAddRef", 0xefef0001 },
391 { "SUPR0ObjAddRefEx", 0xefef0001 },
392 { "SUPR0ObjRelease", 0xefef0002 },
393 { "SUPR0ObjVerifyAccess", 0xefef0003 },
394 { "SUPR0LockMem", 0xefef0004 },
395 { "SUPR0UnlockMem", 0xefef0005 },
396 { "SUPR0ContAlloc", 0xefef0006 },
397 { "SUPR0ContFree", 0xefef0007 },
398 { "SUPR0MemAlloc", 0xefef0008 },
399 { "SUPR0MemGetPhys", 0xefef0009 },
400 { "SUPR0MemFree", 0xefef000a },
401 { "SUPR0Printf", 0xefef000b },
402 { "SUPR0GetPagingMode", 0xefef000c },
403 { "SUPR0EnableVTx", 0xefef000c },
404 { "RTMemAlloc", 0xefef000d },
405 { "RTMemAllocZ", 0xefef000e },
406 { "RTMemFree", 0xefef000f },
407 { "RTR0MemObjAddress", 0xefef0010 },
408 { "RTR0MemObjAddressR3", 0xefef0011 },
409 { "RTR0MemObjAllocPage", 0xefef0012 },
410 { "RTR0MemObjAllocPhysNC", 0xefef0013 },
411 { "RTR0MemObjAllocLow", 0xefef0014 },
412 { "RTR0MemObjEnterPhys", 0xefef0014 },
413 { "RTR0MemObjFree", 0xefef0015 },
414 { "RTR0MemObjGetPagePhysAddr", 0xefef0016 },
415 { "RTR0MemObjMapUser", 0xefef0017 },
416 { "RTR0MemObjMapKernel", 0xefef0017 },
417 { "RTR0MemObjMapKernelEx", 0xefef0017 },
418 { "RTProcSelf", 0xefef0038 },
419 { "RTR0ProcHandleSelf", 0xefef0039 },
420 { "RTSemEventCreate", 0xefef0018 },
421 { "RTSemEventSignal", 0xefef0019 },
422 { "RTSemEventWait", 0xefef001a },
423 { "RTSemEventWaitNoResume", 0xefef001b },
424 { "RTSemEventDestroy", 0xefef001c },
425 { "RTSemEventMultiCreate", 0xefef001d },
426 { "RTSemEventMultiSignal", 0xefef001e },
427 { "RTSemEventMultiReset", 0xefef001f },
428 { "RTSemEventMultiWait", 0xefef0020 },
429 { "RTSemEventMultiWaitNoResume", 0xefef0021 },
430 { "RTSemEventMultiDestroy", 0xefef0022 },
431 { "RTSemFastMutexCreate", 0xefef0023 },
432 { "RTSemFastMutexDestroy", 0xefef0024 },
433 { "RTSemFastMutexRequest", 0xefef0025 },
434 { "RTSemFastMutexRelease", 0xefef0026 },
435 { "RTSpinlockCreate", 0xefef0027 },
436 { "RTSpinlockDestroy", 0xefef0028 },
437 { "RTSpinlockAcquire", 0xefef0029 },
438 { "RTSpinlockRelease", 0xefef002a },
439 { "RTSpinlockAcquireNoInts", 0xefef002b },
440 { "RTSpinlockReleaseNoInts", 0xefef002c },
441 { "RTTimeNanoTS", 0xefef002d },
442 { "RTTimeMillieTS", 0xefef002e },
443 { "RTTimeSystemNanoTS", 0xefef002f },
444 { "RTTimeSystemMillieTS", 0xefef0030 },
445 { "RTThreadNativeSelf", 0xefef0031 },
446 { "RTThreadSleep", 0xefef0032 },
447 { "RTThreadYield", 0xefef0033 },
448 { "RTLogDefaultInstance", 0xefef0034 },
449 { "RTLogRelDefaultInstance", 0xefef0035 },
450 { "RTLogSetDefaultInstanceThread", 0xefef0036 },
451 { "RTLogLogger", 0xefef0037 },
452 { "RTLogLoggerEx", 0xefef0038 },
453 { "RTLogLoggerExV", 0xefef0039 },
454 { "AssertMsg1", 0xefef003a },
455 { "AssertMsg2", 0xefef003b },
456 { "RTAssertMsg1", 0xefef003c },
457 { "RTAssertMsg2", 0xefef003d },
458 { "RTAssertMsg2V", 0xefef003e },
459 };
460
461 /* fake r0 functions. */
462 g_pFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));
463 if (g_pFunctions)
464 {
465 g_pFunctions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions);
466 memcpy(&g_pFunctions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions));
467 g_pSession = (PSUPDRVSESSION)(void *)g_pFunctions;
468 if (ppSession)
469 *ppSession = g_pSession;
470
471 /* fake the GIP. */
472 g_pSUPGlobalInfoPage = (PSUPGLOBALINFOPAGE)RTMemPageAllocZ(PAGE_SIZE);
473 if (g_pSUPGlobalInfoPage)
474 {
475 g_pSUPGlobalInfoPageR0 = g_pSUPGlobalInfoPage;
476 g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS & ~(RTHCPHYS)PAGE_OFFSET_MASK;
477 /* the page is supposed to be invalid, so don't set the magic. */
478 return VINF_SUCCESS;
479 }
480
481 RTMemFree(g_pFunctions);
482 g_pFunctions = NULL;
483 }
484 return VERR_NO_MEMORY;
485}
486
487
488SUPR3DECL(int) SUPR3Term(bool fForced)
489{
490 /*
491 * Verify state.
492 */
493 AssertMsg(g_cInits > 0, ("SUPR3Term() is called before SUPR3Init()!\n"));
494 if (g_cInits == 0)
495 return VERR_WRONG_ORDER;
496 if (g_cInits == 1 || fForced)
497 {
498 /*
499 * NULL the GIP pointer.
500 */
501 if (g_pSUPGlobalInfoPage)
502 {
503 ASMAtomicXchgPtr((void * volatile *)&g_pSUPGlobalInfoPage, NULL);
504 ASMAtomicXchgPtr((void * volatile *)&g_pSUPGlobalInfoPageR0, NULL);
505 ASMAtomicXchgSize(&g_HCPhysSUPGlobalInfoPage, NIL_RTHCPHYS);
506 /* just a little safe guard against threads using the page. */
507 RTThreadSleep(50);
508 }
509
510 /*
511 * Close the support driver.
512 */
513 int rc = suplibOsTerm(&g_supLibData);
514 if (rc)
515 return rc;
516
517 g_u32Cookie = 0;
518 g_u32SessionCookie = 0;
519 g_cInits = 0;
520 }
521 else
522 g_cInits--;
523
524 return 0;
525}
526
527
528SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void)
529{
530 /* fake */
531 if (RT_UNLIKELY(g_u32FakeMode))
532#ifdef RT_ARCH_AMD64
533 return SUPPAGINGMODE_AMD64_GLOBAL_NX;
534#else
535 return SUPPAGINGMODE_32_BIT_GLOBAL;
536#endif
537
538 /*
539 * Issue IOCtl to the SUPDRV kernel module.
540 */
541 SUPGETPAGINGMODE Req;
542 Req.Hdr.u32Cookie = g_u32Cookie;
543 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
544 Req.Hdr.cbIn = SUP_IOCTL_GET_PAGING_MODE_SIZE_IN;
545 Req.Hdr.cbOut = SUP_IOCTL_GET_PAGING_MODE_SIZE_OUT;
546 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
547 Req.Hdr.rc = VERR_INTERNAL_ERROR;
548 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GET_PAGING_MODE, &Req, SUP_IOCTL_GET_PAGING_MODE_SIZE);
549 if ( RT_FAILURE(rc)
550 || RT_FAILURE(Req.Hdr.rc))
551 {
552 LogRel(("SUPR3GetPagingMode: %Rrc %Rrc\n", rc, Req.Hdr.rc));
553 Req.u.Out.enmMode = SUPPAGINGMODE_INVALID;
554 }
555
556 return Req.u.Out.enmMode;
557}
558
559
560/**
561 * For later.
562 */
563static int supCallVMMR0ExFake(PVMR0 pVMR0, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
564{
565 AssertMsgFailed(("%d\n", uOperation));
566 return VERR_NOT_SUPPORTED;
567}
568
569
570SUPR3DECL(int) SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu)
571{
572 if (RT_LIKELY(uOperation == SUP_VMMR0_DO_RAW_RUN))
573 return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_RAW_RUN, idCpu);
574 if (RT_LIKELY(uOperation == SUP_VMMR0_DO_HWACC_RUN))
575 return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_HWACC_RUN, idCpu);
576 if (RT_LIKELY(uOperation == SUP_VMMR0_DO_NOP))
577 return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_NOP, idCpu);
578
579 AssertMsgFailed(("%#x\n", uOperation));
580 return VERR_INTERNAL_ERROR;
581}
582
583
584SUPR3DECL(int) SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
585{
586 /*
587 * The following operations don't belong here.
588 */
589 AssertMsgReturn( uOperation != SUP_VMMR0_DO_RAW_RUN
590 && uOperation != SUP_VMMR0_DO_HWACC_RUN
591 && uOperation != SUP_VMMR0_DO_NOP,
592 ("%#x\n", uOperation),
593 VERR_INTERNAL_ERROR);
594
595 /* fake */
596 if (RT_UNLIKELY(g_u32FakeMode))
597 return supCallVMMR0ExFake(pVMR0, uOperation, u64Arg, pReqHdr);
598
599 int rc;
600 if (!pReqHdr)
601 {
602 /* no data. */
603 SUPCALLVMMR0 Req;
604 Req.Hdr.u32Cookie = g_u32Cookie;
605 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
606 Req.Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_SIZE_IN(0);
607 Req.Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_SIZE_OUT(0);
608 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
609 Req.Hdr.rc = VERR_INTERNAL_ERROR;
610 Req.u.In.pVMR0 = pVMR0;
611 Req.u.In.idCpu = idCpu;
612 Req.u.In.uOperation = uOperation;
613 Req.u.In.u64Arg = u64Arg;
614 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(0), &Req, SUP_IOCTL_CALL_VMMR0_SIZE(0));
615 if (RT_SUCCESS(rc))
616 rc = Req.Hdr.rc;
617 }
618 else if (SUP_IOCTL_CALL_VMMR0_SIZE(pReqHdr->cbReq) < _4K) /* FreeBSD won't copy more than 4K. */
619 {
620 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
621 AssertReturn(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);
622 const size_t cbReq = pReqHdr->cbReq;
623
624 PSUPCALLVMMR0 pReq = (PSUPCALLVMMR0)alloca(SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));
625 pReq->Hdr.u32Cookie = g_u32Cookie;
626 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
627 pReq->Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_SIZE_IN(cbReq);
628 pReq->Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_SIZE_OUT(cbReq);
629 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
630 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
631 pReq->u.In.pVMR0 = pVMR0;
632 pReq->u.In.idCpu = idCpu;
633 pReq->u.In.uOperation = uOperation;
634 pReq->u.In.u64Arg = u64Arg;
635 memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);
636 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(cbReq), pReq, SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));
637 if (RT_SUCCESS(rc))
638 rc = pReq->Hdr.rc;
639 memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);
640 }
641 else /** @todo may have to remove the size limits one this request... */
642 AssertMsgFailedReturn(("cbReq=%#x\n", pReqHdr->cbReq), VERR_INTERNAL_ERROR);
643 return rc;
644}
645
646
647SUPR3DECL(int) SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg)
648{
649 /*
650 * The following operations don't belong here.
651 */
652 AssertMsgReturn( uOperation != SUP_VMMR0_DO_RAW_RUN
653 && uOperation != SUP_VMMR0_DO_HWACC_RUN
654 && uOperation != SUP_VMMR0_DO_NOP,
655 ("%#x\n", uOperation),
656 VERR_INTERNAL_ERROR);
657 return SUPR3CallVMMR0Ex(pVMR0, idCpu, uOperation, (uintptr_t)pvArg, NULL);
658}
659
660
661SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0)
662{
663 if (RT_UNLIKELY(g_u32FakeMode))
664 return VINF_SUCCESS;
665
666 SUPSETVMFORFAST Req;
667 Req.Hdr.u32Cookie = g_u32Cookie;
668 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
669 Req.Hdr.cbIn = SUP_IOCTL_SET_VM_FOR_FAST_SIZE_IN;
670 Req.Hdr.cbOut = SUP_IOCTL_SET_VM_FOR_FAST_SIZE_OUT;
671 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
672 Req.Hdr.rc = VERR_INTERNAL_ERROR;
673 Req.u.In.pVMR0 = pVMR0;
674 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SET_VM_FOR_FAST, &Req, SUP_IOCTL_SET_VM_FOR_FAST_SIZE);
675 if (RT_SUCCESS(rc))
676 rc = Req.Hdr.rc;
677 return rc;
678}
679
680
681SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
682{
683 AssertReturn(cchService < RT_SIZEOFMEMB(SUPCALLSERVICE, u.In.szName), VERR_INVALID_PARAMETER);
684 Assert(strlen(pszService) == cchService);
685
686 /* fake */
687 if (RT_UNLIKELY(g_u32FakeMode))
688 return VERR_NOT_SUPPORTED;
689
690 int rc;
691 if (!pReqHdr)
692 {
693 /* no data. */
694 SUPCALLSERVICE Req;
695 Req.Hdr.u32Cookie = g_u32Cookie;
696 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
697 Req.Hdr.cbIn = SUP_IOCTL_CALL_SERVICE_SIZE_IN(0);
698 Req.Hdr.cbOut = SUP_IOCTL_CALL_SERVICE_SIZE_OUT(0);
699 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
700 Req.Hdr.rc = VERR_INTERNAL_ERROR;
701 memcpy(Req.u.In.szName, pszService, cchService);
702 Req.u.In.szName[cchService] = '\0';
703 Req.u.In.uOperation = uOperation;
704 Req.u.In.u64Arg = u64Arg;
705 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(0), &Req, SUP_IOCTL_CALL_SERVICE_SIZE(0));
706 if (RT_SUCCESS(rc))
707 rc = Req.Hdr.rc;
708 }
709 else if (SUP_IOCTL_CALL_SERVICE_SIZE(pReqHdr->cbReq) < _4K) /* FreeBSD won't copy more than 4K. */
710 {
711 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
712 AssertReturn(pReqHdr->u32Magic == SUPR0SERVICEREQHDR_MAGIC, VERR_INVALID_MAGIC);
713 const size_t cbReq = pReqHdr->cbReq;
714
715 PSUPCALLSERVICE pReq = (PSUPCALLSERVICE)alloca(SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));
716 pReq->Hdr.u32Cookie = g_u32Cookie;
717 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
718 pReq->Hdr.cbIn = SUP_IOCTL_CALL_SERVICE_SIZE_IN(cbReq);
719 pReq->Hdr.cbOut = SUP_IOCTL_CALL_SERVICE_SIZE_OUT(cbReq);
720 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
721 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
722 memcpy(pReq->u.In.szName, pszService, cchService);
723 pReq->u.In.szName[cchService] = '\0';
724 pReq->u.In.uOperation = uOperation;
725 pReq->u.In.u64Arg = u64Arg;
726 memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);
727 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(cbReq), pReq, SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));
728 if (RT_SUCCESS(rc))
729 rc = pReq->Hdr.rc;
730 memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);
731 }
732 else /** @todo may have to remove the size limits one this request... */
733 AssertMsgFailedReturn(("cbReq=%#x\n", pReqHdr->cbReq), VERR_INTERNAL_ERROR);
734 return rc;
735}
736
737
738/**
739 * Worker for the SUPR3Logger* APIs.
740 *
741 * @returns VBox status code.
742 * @param enmWhich Which logger.
743 * @param fWhat What to do with the logger.
744 * @param pszFlags The flags settings.
745 * @param pszGroups The groups settings.
746 * @param pszDest The destionation specificier.
747 */
748static int supR3LoggerSettings(SUPLOGGER enmWhich, uint32_t fWhat, const char *pszFlags, const char *pszGroups, const char *pszDest)
749{
750 uint32_t const cchFlags = pszFlags ? (uint32_t)strlen(pszFlags) : 0;
751 uint32_t const cchGroups = pszGroups ? (uint32_t)strlen(pszGroups) : 0;
752 uint32_t const cchDest = pszDest ? (uint32_t)strlen(pszDest) : 0;
753 uint32_t const cbStrTab = cchFlags + !!cchFlags
754 + cchGroups + !!cchGroups
755 + cchDest + !!cchDest
756 + (!cchFlags && !cchGroups && !cchDest);
757
758 PSUPLOGGERSETTINGS pReq = (PSUPLOGGERSETTINGS)alloca(SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));
759 pReq->Hdr.u32Cookie = g_u32Cookie;
760 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
761 pReq->Hdr.cbIn = SUP_IOCTL_LOGGER_SETTINGS_SIZE_IN(cbStrTab);
762 pReq->Hdr.cbOut = SUP_IOCTL_LOGGER_SETTINGS_SIZE_OUT;
763 pReq->Hdr.fFlags= SUPREQHDR_FLAGS_DEFAULT;
764 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
765 switch (enmWhich)
766 {
767 case SUPLOGGER_DEBUG: pReq->u.In.fWhich = SUPLOGGERSETTINGS_WHICH_DEBUG; break;
768 case SUPLOGGER_RELEASE: pReq->u.In.fWhich = SUPLOGGERSETTINGS_WHICH_RELEASE; break;
769 default:
770 return VERR_INVALID_PARAMETER;
771 }
772 pReq->u.In.fWhat = fWhat;
773
774 uint32_t off = 0;
775 if (cchFlags)
776 {
777 pReq->u.In.offFlags = off;
778 memcpy(&pReq->u.In.szStrings[off], pszFlags, cchFlags + 1);
779 off += cchFlags + 1;
780 }
781 else
782 pReq->u.In.offFlags = cbStrTab - 1;
783
784 if (cchGroups)
785 {
786 pReq->u.In.offGroups = off;
787 memcpy(&pReq->u.In.szStrings[off], pszGroups, cchGroups + 1);
788 off += cchGroups + 1;
789 }
790 else
791 pReq->u.In.offGroups = cbStrTab - 1;
792
793 if (cchDest)
794 {
795 pReq->u.In.offDestination = off;
796 memcpy(&pReq->u.In.szStrings[off], pszDest, cchDest + 1);
797 off += cchDest + 1;
798 }
799 else
800 pReq->u.In.offDestination = cbStrTab - 1;
801
802 if (!off)
803 {
804 pReq->u.In.szStrings[0] = '\0';
805 off++;
806 }
807 Assert(off == cbStrTab);
808 Assert(pReq->u.In.szStrings[cbStrTab - 1] == '\0');
809
810
811 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOGGER_SETTINGS(cbStrTab), pReq, SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));
812 if (RT_SUCCESS(rc))
813 rc = pReq->Hdr.rc;
814 return rc;
815}
816
817
818SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)
819{
820 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_SETTINGS, pszFlags, pszGroups, pszDest);
821}
822
823
824SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)
825{
826 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_CREATE, pszFlags, pszGroups, pszDest);
827}
828
829
830SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich)
831{
832 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_DESTROY, NULL, NULL, NULL);
833}
834
835
836SUPR3DECL(int) SUPR3PageAlloc(size_t cPages, void **ppvPages)
837{
838 /*
839 * Validate.
840 */
841 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
842 *ppvPages = NULL;
843 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
844
845 /*
846 * Call OS specific worker.
847 */
848 return suplibOsPageAlloc(&g_supLibData, cPages, ppvPages);
849}
850
851
852SUPR3DECL(int) SUPR3PageFree(void *pvPages, size_t cPages)
853{
854 /*
855 * Validate.
856 */
857 AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
858 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
859
860 /*
861 * Call OS specific worker.
862 */
863 return suplibOsPageFree(&g_supLibData, pvPages, cPages);
864}
865
866
867/**
868 * Locks down the physical memory backing a virtual memory
869 * range in the current process.
870 *
871 * @returns VBox status code.
872 * @param pvStart Start of virtual memory range.
873 * Must be page aligned.
874 * @param cPages Number of pages.
875 * @param paPages Where to store the physical page addresses returned.
876 * On entry this will point to an array of with cbMemory >> PAGE_SHIFT entries.
877 */
878SUPR3DECL(int) supR3PageLock(void *pvStart, size_t cPages, PSUPPAGE paPages)
879{
880 /*
881 * Validate.
882 */
883 AssertPtr(pvStart);
884 AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
885 AssertPtr(paPages);
886
887 /* fake */
888 if (RT_UNLIKELY(g_u32FakeMode))
889 {
890 RTHCPHYS Phys = (uintptr_t)pvStart + PAGE_SIZE * 1024;
891 size_t iPage = cPages;
892 while (iPage-- > 0)
893 paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);
894 return VINF_SUCCESS;
895 }
896
897 /*
898 * Issue IOCtl to the SUPDRV kernel module.
899 */
900 int rc;
901 PSUPPAGELOCK pReq = (PSUPPAGELOCK)RTMemTmpAllocZ(SUP_IOCTL_PAGE_LOCK_SIZE(cPages));
902 if (RT_LIKELY(pReq))
903 {
904 pReq->Hdr.u32Cookie = g_u32Cookie;
905 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
906 pReq->Hdr.cbIn = SUP_IOCTL_PAGE_LOCK_SIZE_IN;
907 pReq->Hdr.cbOut = SUP_IOCTL_PAGE_LOCK_SIZE_OUT(cPages);
908 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
909 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
910 pReq->u.In.pvR3 = pvStart;
911 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
912 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_LOCK, pReq, SUP_IOCTL_PAGE_LOCK_SIZE(cPages));
913 if (RT_SUCCESS(rc))
914 rc = pReq->Hdr.rc;
915 if (RT_SUCCESS(rc))
916 {
917 for (uint32_t iPage = 0; iPage < cPages; iPage++)
918 {
919 paPages[iPage].uReserved = 0;
920 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
921 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
922 }
923 }
924 RTMemTmpFree(pReq);
925 }
926 else
927 rc = VERR_NO_TMP_MEMORY;
928
929 return rc;
930}
931
932
933/**
934 * Releases locked down pages.
935 *
936 * @returns VBox status code.
937 * @param pvStart Start of virtual memory range previously locked
938 * down by SUPPageLock().
939 */
940SUPR3DECL(int) supR3PageUnlock(void *pvStart)
941{
942 /*
943 * Validate.
944 */
945 AssertPtr(pvStart);
946 AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
947
948 /* fake */
949 if (RT_UNLIKELY(g_u32FakeMode))
950 return VINF_SUCCESS;
951
952 /*
953 * Issue IOCtl to the SUPDRV kernel module.
954 */
955 SUPPAGEUNLOCK Req;
956 Req.Hdr.u32Cookie = g_u32Cookie;
957 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
958 Req.Hdr.cbIn = SUP_IOCTL_PAGE_UNLOCK_SIZE_IN;
959 Req.Hdr.cbOut = SUP_IOCTL_PAGE_UNLOCK_SIZE_OUT;
960 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
961 Req.Hdr.rc = VERR_INTERNAL_ERROR;
962 Req.u.In.pvR3 = pvStart;
963 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_UNLOCK, &Req, SUP_IOCTL_PAGE_UNLOCK_SIZE);
964 if (RT_SUCCESS(rc))
965 rc = Req.Hdr.rc;
966 return rc;
967}
968
969
970/**
971 * Fallback for SUPR3PageAllocEx on systems where RTR0MemObjPhysAllocNC isn't
972 * supported.
973 */
974static int supPagePageAllocNoKernelFallback(size_t cPages, void **ppvPages, PSUPPAGE paPages)
975{
976 int rc = suplibOsPageAlloc(&g_supLibData, cPages, ppvPages);
977 if (RT_SUCCESS(rc))
978 {
979 if (!paPages)
980 paPages = (PSUPPAGE)alloca(sizeof(paPages[0]) * cPages);
981 rc = supR3PageLock(*ppvPages, cPages, paPages);
982 if (RT_FAILURE(rc))
983 suplibOsPageFree(&g_supLibData, *ppvPages, cPages);
984 }
985 return rc;
986}
987
988
989SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages)
990{
991 /*
992 * Validate.
993 */
994 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
995 *ppvPages = NULL;
996 AssertPtrNullReturn(pR0Ptr, VERR_INVALID_POINTER);
997 if (pR0Ptr)
998 *pR0Ptr = NIL_RTR0PTR;
999 AssertPtrNullReturn(paPages, VERR_INVALID_POINTER);
1000 AssertMsgReturn(cPages > 0 && cPages <= VBOX_MAX_ALLOC_PAGE_COUNT, ("cPages=%zu\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);
1001
1002 /* fake */
1003 if (RT_UNLIKELY(g_u32FakeMode))
1004 {
1005 void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
1006 if (!pv)
1007 return VERR_NO_MEMORY;
1008 *ppvPages = pv;
1009 if (pR0Ptr)
1010 *pR0Ptr = (RTR0PTR)pv;
1011 if (paPages)
1012 for (size_t iPage = 0; iPage < cPages; iPage++)
1013 {
1014 paPages[iPage].uReserved = 0;
1015 paPages[iPage].Phys = (iPage + 4321) << PAGE_SHIFT;
1016 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
1017 }
1018 return VINF_SUCCESS;
1019 }
1020
1021 /*
1022 * Use fallback for non-R0 mapping?
1023 */
1024 if ( !pR0Ptr
1025 && !g_fSupportsPageAllocNoKernel)
1026 return supPagePageAllocNoKernelFallback(cPages, ppvPages, paPages);
1027
1028 /*
1029 * Issue IOCtl to the SUPDRV kernel module.
1030 */
1031 int rc;
1032 PSUPPAGEALLOCEX pReq = (PSUPPAGEALLOCEX)RTMemTmpAllocZ(SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));
1033 if (pReq)
1034 {
1035 pReq->Hdr.u32Cookie = g_u32Cookie;
1036 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
1037 pReq->Hdr.cbIn = SUP_IOCTL_PAGE_ALLOC_EX_SIZE_IN;
1038 pReq->Hdr.cbOut = SUP_IOCTL_PAGE_ALLOC_EX_SIZE_OUT(cPages);
1039 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
1040 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
1041 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
1042 pReq->u.In.fKernelMapping = pR0Ptr != NULL;
1043 pReq->u.In.fUserMapping = true;
1044 pReq->u.In.fReserved0 = false;
1045 pReq->u.In.fReserved1 = false;
1046 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_ALLOC_EX, pReq, SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));
1047 if (RT_SUCCESS(rc))
1048 {
1049 rc = pReq->Hdr.rc;
1050 if (RT_SUCCESS(rc))
1051 {
1052 *ppvPages = pReq->u.Out.pvR3;
1053 if (pR0Ptr)
1054 *pR0Ptr = pReq->u.Out.pvR0;
1055 if (paPages)
1056 for (size_t iPage = 0; iPage < cPages; iPage++)
1057 {
1058 paPages[iPage].uReserved = 0;
1059 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
1060 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
1061 }
1062 }
1063 else if ( rc == VERR_NOT_SUPPORTED
1064 && !pR0Ptr)
1065 {
1066 g_fSupportsPageAllocNoKernel = false;
1067 rc = supPagePageAllocNoKernelFallback(cPages, ppvPages, paPages);
1068 }
1069 }
1070
1071 RTMemTmpFree(pReq);
1072 }
1073 else
1074 rc = VERR_NO_TMP_MEMORY;
1075 return rc;
1076
1077}
1078
1079
1080SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr)
1081{
1082 /*
1083 * Validate.
1084 */
1085 AssertPtrReturn(pvR3, VERR_INVALID_POINTER);
1086 AssertPtrReturn(pR0Ptr, VERR_INVALID_POINTER);
1087 Assert(!(off & PAGE_OFFSET_MASK));
1088 Assert(!(cb & PAGE_OFFSET_MASK) && cb);
1089 Assert(!fFlags);
1090 *pR0Ptr = NIL_RTR0PTR;
1091
1092 /* fake */
1093 if (RT_UNLIKELY(g_u32FakeMode))
1094 return VERR_NOT_SUPPORTED;
1095
1096 /*
1097 * Issue IOCtl to the SUPDRV kernel module.
1098 */
1099 SUPPAGEMAPKERNEL Req;
1100 Req.Hdr.u32Cookie = g_u32Cookie;
1101 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1102 Req.Hdr.cbIn = SUP_IOCTL_PAGE_MAP_KERNEL_SIZE_IN;
1103 Req.Hdr.cbOut = SUP_IOCTL_PAGE_MAP_KERNEL_SIZE_OUT;
1104 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1105 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1106 Req.u.In.pvR3 = pvR3;
1107 Req.u.In.offSub = off;
1108 Req.u.In.cbSub = cb;
1109 Req.u.In.fFlags = fFlags;
1110 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_MAP_KERNEL, &Req, SUP_IOCTL_PAGE_MAP_KERNEL_SIZE);
1111 if (RT_SUCCESS(rc))
1112 rc = Req.Hdr.rc;
1113 if (RT_SUCCESS(rc))
1114 *pR0Ptr = Req.u.Out.pvR0;
1115 return rc;
1116}
1117
1118
1119SUPR3DECL(int) SUPR3PageProtect(void *pvR3, RTR0PTR R0Ptr, uint32_t off, uint32_t cb, uint32_t fProt)
1120{
1121 /*
1122 * Validate.
1123 */
1124 AssertPtrReturn(pvR3, VERR_INVALID_POINTER);
1125 Assert(!(off & PAGE_OFFSET_MASK));
1126 Assert(!(cb & PAGE_OFFSET_MASK) && cb);
1127 AssertReturn(!(fProt & ~(RTMEM_PROT_NONE | RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);
1128
1129 /* fake */
1130 if (RT_UNLIKELY(g_u32FakeMode))
1131 return RTMemProtect((uint8_t *)pvR3 + off, cb, fProt);
1132
1133 /*
1134 * Some OSes can do this from ring-3, so try that before we
1135 * issue the IOCtl to the SUPDRV kernel module.
1136 * (Yea, this isn't very nice, but just try get the job done for now.)
1137 */
1138#if !defined(RT_OS_SOLARIS)
1139 RTMemProtect((uint8_t *)pvR3 + off, cb, fProt);
1140#endif
1141
1142 SUPPAGEPROTECT Req;
1143 Req.Hdr.u32Cookie = g_u32Cookie;
1144 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1145 Req.Hdr.cbIn = SUP_IOCTL_PAGE_PROTECT_SIZE_IN;
1146 Req.Hdr.cbOut = SUP_IOCTL_PAGE_PROTECT_SIZE_OUT;
1147 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1148 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1149 Req.u.In.pvR3 = pvR3;
1150 Req.u.In.pvR0 = R0Ptr;
1151 Req.u.In.offSub = off;
1152 Req.u.In.cbSub = cb;
1153 Req.u.In.fProt = fProt;
1154 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_PROTECT, &Req, SUP_IOCTL_PAGE_PROTECT_SIZE);
1155 if (RT_SUCCESS(rc))
1156 rc = Req.Hdr.rc;
1157 return rc;
1158}
1159
1160
1161SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages)
1162{
1163 /*
1164 * Validate.
1165 */
1166 AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
1167 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
1168
1169 /* fake */
1170 if (RT_UNLIKELY(g_u32FakeMode))
1171 {
1172 RTMemPageFree(pvPages);
1173 return VINF_SUCCESS;
1174 }
1175
1176 /*
1177 * Try normal free first, then if it fails check if we're using the fallback .
1178 * for the allocations without kernel mappings and attempt unlocking it.
1179 */
1180 NOREF(cPages);
1181 SUPPAGEFREE Req;
1182 Req.Hdr.u32Cookie = g_u32Cookie;
1183 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1184 Req.Hdr.cbIn = SUP_IOCTL_PAGE_FREE_SIZE_IN;
1185 Req.Hdr.cbOut = SUP_IOCTL_PAGE_FREE_SIZE_OUT;
1186 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1187 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1188 Req.u.In.pvR3 = pvPages;
1189 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_FREE, &Req, SUP_IOCTL_PAGE_FREE_SIZE);
1190 if (RT_SUCCESS(rc))
1191 {
1192 rc = Req.Hdr.rc;
1193 if ( rc == VERR_INVALID_PARAMETER
1194 && !g_fSupportsPageAllocNoKernel)
1195 {
1196 int rc2 = supR3PageUnlock(pvPages);
1197 if (RT_SUCCESS(rc2))
1198 rc = suplibOsPageFree(&g_supLibData, pvPages, cPages);
1199 }
1200 }
1201 return rc;
1202}
1203
1204
1205SUPR3DECL(void *) SUPR3ContAlloc(size_t cPages, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys)
1206{
1207 /*
1208 * Validate.
1209 */
1210 AssertPtrReturn(pHCPhys, NULL);
1211 *pHCPhys = NIL_RTHCPHYS;
1212 AssertPtrNullReturn(pR0Ptr, NULL);
1213 if (pR0Ptr)
1214 *pR0Ptr = NIL_RTR0PTR;
1215 AssertPtrNullReturn(pHCPhys, NULL);
1216 AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), NULL);
1217
1218 /* fake */
1219 if (RT_UNLIKELY(g_u32FakeMode))
1220 {
1221 void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
1222 if (pR0Ptr)
1223 *pR0Ptr = (RTR0PTR)pv;
1224 if (pHCPhys)
1225 *pHCPhys = (uintptr_t)pv + (PAGE_SHIFT * 1024);
1226 return pv;
1227 }
1228
1229 /*
1230 * Issue IOCtl to the SUPDRV kernel module.
1231 */
1232 SUPCONTALLOC Req;
1233 Req.Hdr.u32Cookie = g_u32Cookie;
1234 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1235 Req.Hdr.cbIn = SUP_IOCTL_CONT_ALLOC_SIZE_IN;
1236 Req.Hdr.cbOut = SUP_IOCTL_CONT_ALLOC_SIZE_OUT;
1237 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1238 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1239 Req.u.In.cPages = (uint32_t)cPages;
1240 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CONT_ALLOC, &Req, SUP_IOCTL_CONT_ALLOC_SIZE);
1241 if ( RT_SUCCESS(rc)
1242 && RT_SUCCESS(Req.Hdr.rc))
1243 {
1244 *pHCPhys = Req.u.Out.HCPhys;
1245 if (pR0Ptr)
1246 *pR0Ptr = Req.u.Out.pvR0;
1247 return Req.u.Out.pvR3;
1248 }
1249
1250 return NULL;
1251}
1252
1253
1254SUPR3DECL(int) SUPR3ContFree(void *pv, size_t cPages)
1255{
1256 /*
1257 * Validate.
1258 */
1259 if (!pv)
1260 return VINF_SUCCESS;
1261 AssertPtrReturn(pv, VERR_INVALID_POINTER);
1262 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
1263
1264 /* fake */
1265 if (RT_UNLIKELY(g_u32FakeMode))
1266 {
1267 RTMemPageFree(pv);
1268 return VINF_SUCCESS;
1269 }
1270
1271 /*
1272 * Issue IOCtl to the SUPDRV kernel module.
1273 */
1274 SUPCONTFREE Req;
1275 Req.Hdr.u32Cookie = g_u32Cookie;
1276 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1277 Req.Hdr.cbIn = SUP_IOCTL_CONT_FREE_SIZE_IN;
1278 Req.Hdr.cbOut = SUP_IOCTL_CONT_FREE_SIZE_OUT;
1279 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1280 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1281 Req.u.In.pvR3 = pv;
1282 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CONT_FREE, &Req, SUP_IOCTL_CONT_FREE_SIZE);
1283 if (RT_SUCCESS(rc))
1284 rc = Req.Hdr.rc;
1285 return rc;
1286}
1287
1288
1289SUPR3DECL(int) SUPR3LowAlloc(size_t cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages)
1290{
1291 /*
1292 * Validate.
1293 */
1294 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
1295 *ppvPages = NULL;
1296 AssertPtrReturn(paPages, VERR_INVALID_POINTER);
1297 AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);
1298
1299 /* fake */
1300 if (RT_UNLIKELY(g_u32FakeMode))
1301 {
1302 *ppvPages = RTMemPageAllocZ((size_t)cPages * PAGE_SIZE);
1303 if (!*ppvPages)
1304 return VERR_NO_LOW_MEMORY;
1305
1306 /* fake physical addresses. */
1307 RTHCPHYS Phys = (uintptr_t)*ppvPages + PAGE_SIZE * 1024;
1308 size_t iPage = cPages;
1309 while (iPage-- > 0)
1310 paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);
1311 return VINF_SUCCESS;
1312 }
1313
1314 /*
1315 * Issue IOCtl to the SUPDRV kernel module.
1316 */
1317 int rc;
1318 PSUPLOWALLOC pReq = (PSUPLOWALLOC)RTMemTmpAllocZ(SUP_IOCTL_LOW_ALLOC_SIZE(cPages));
1319 if (pReq)
1320 {
1321 pReq->Hdr.u32Cookie = g_u32Cookie;
1322 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
1323 pReq->Hdr.cbIn = SUP_IOCTL_LOW_ALLOC_SIZE_IN;
1324 pReq->Hdr.cbOut = SUP_IOCTL_LOW_ALLOC_SIZE_OUT(cPages);
1325 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
1326 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
1327 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
1328 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOW_ALLOC, pReq, SUP_IOCTL_LOW_ALLOC_SIZE(cPages));
1329 if (RT_SUCCESS(rc))
1330 rc = pReq->Hdr.rc;
1331 if (RT_SUCCESS(rc))
1332 {
1333 *ppvPages = pReq->u.Out.pvR3;
1334 if (ppvPagesR0)
1335 *ppvPagesR0 = pReq->u.Out.pvR0;
1336 if (paPages)
1337 for (size_t iPage = 0; iPage < cPages; iPage++)
1338 {
1339 paPages[iPage].uReserved = 0;
1340 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
1341 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
1342 Assert(paPages[iPage].Phys <= UINT32_C(0xfffff000));
1343 }
1344 }
1345 RTMemTmpFree(pReq);
1346 }
1347 else
1348 rc = VERR_NO_TMP_MEMORY;
1349
1350 return rc;
1351}
1352
1353
1354SUPR3DECL(int) SUPR3LowFree(void *pv, size_t cPages)
1355{
1356 /*
1357 * Validate.
1358 */
1359 if (!pv)
1360 return VINF_SUCCESS;
1361 AssertPtrReturn(pv, VERR_INVALID_POINTER);
1362 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
1363
1364 /* fake */
1365 if (RT_UNLIKELY(g_u32FakeMode))
1366 {
1367 RTMemPageFree(pv);
1368 return VINF_SUCCESS;
1369 }
1370
1371 /*
1372 * Issue IOCtl to the SUPDRV kernel module.
1373 */
1374 SUPCONTFREE Req;
1375 Req.Hdr.u32Cookie = g_u32Cookie;
1376 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1377 Req.Hdr.cbIn = SUP_IOCTL_LOW_FREE_SIZE_IN;
1378 Req.Hdr.cbOut = SUP_IOCTL_LOW_FREE_SIZE_OUT;
1379 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1380 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1381 Req.u.In.pvR3 = pv;
1382 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOW_FREE, &Req, SUP_IOCTL_LOW_FREE_SIZE);
1383 if (RT_SUCCESS(rc))
1384 rc = Req.Hdr.rc;
1385 return rc;
1386}
1387
1388
1389SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszMsg, PRTFILE phFile)
1390{
1391 /*
1392 * Quick input validation.
1393 */
1394 AssertPtr(pszFilename);
1395 AssertPtr(pszMsg);
1396 AssertReturn(!phFile, VERR_NOT_IMPLEMENTED); /** @todo Implement this. The deal is that we make sure the
1397 file is the same we verified after opening it. */
1398
1399 /*
1400 * Only do the actual check in hardened builds.
1401 */
1402#ifdef VBOX_WITH_HARDENING
1403 int rc = supR3HardenedVerifyFile(pszFilename, false /* fFatal */);
1404 if (RT_FAILURE(rc))
1405 LogRel(("SUPR3HardenedVerifyFile: %s: Verification of \"%s\" failed, rc=%Rrc\n", pszMsg, pszFilename, rc));
1406 return rc;
1407#else
1408 return VINF_SUCCESS;
1409#endif
1410}
1411
1412
1413SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase)
1414{
1415 int rc = VINF_SUCCESS;
1416#ifdef VBOX_WITH_HARDENING
1417 /*
1418 * Check that the module can be trusted.
1419 */
1420 rc = supR3HardenedVerifyFile(pszFilename, false /* fFatal */);
1421#endif
1422 if (RT_SUCCESS(rc))
1423 rc = supLoadModule(pszFilename, pszModule, NULL, ppvImageBase);
1424 else
1425 LogRel(("SUPR3LoadModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
1426 return rc;
1427}
1428
1429
1430SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
1431 const char *pszSrvReqHandler, void **ppvImageBase)
1432{
1433 int rc = VINF_SUCCESS;
1434 AssertPtrReturn(pszSrvReqHandler, VERR_INVALID_PARAMETER);
1435
1436#ifdef VBOX_WITH_HARDENING
1437 /*
1438 * Check that the module can be trusted.
1439 */
1440 rc = supR3HardenedVerifyFile(pszFilename, false /* fFatal */);
1441#endif
1442 if (RT_SUCCESS(rc))
1443 rc = supLoadModule(pszFilename, pszModule, pszSrvReqHandler, ppvImageBase);
1444 else
1445 LogRel(("SUPR3LoadServiceModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
1446 return rc;
1447}
1448
1449
1450/**
1451 * Resolve an external symbol during RTLdrGetBits().
1452 *
1453 * @returns VBox status code.
1454 * @param hLdrMod The loader module handle.
1455 * @param pszModule Module name.
1456 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
1457 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
1458 * @param pValue Where to store the symbol value (address).
1459 * @param pvUser User argument.
1460 */
1461static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule,
1462 const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
1463{
1464 AssertPtr(pValue);
1465 AssertPtr(pvUser);
1466
1467 /*
1468 * Only SUPR0 and VMMR0.r0
1469 */
1470 if ( pszModule
1471 && *pszModule
1472 && strcmp(pszModule, "SUPR0.dll")
1473 && strcmp(pszModule, "VMMR0.r0"))
1474 {
1475 AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitiv)\n", pvUser, pszModule));
1476 return VERR_SYMBOL_NOT_FOUND;
1477 }
1478
1479 /*
1480 * No ordinals.
1481 */
1482 if (pszSymbol < (const char*)0x10000)
1483 {
1484 AssertMsgFailed(("%s is importing by ordinal (ord=%d)\n", pvUser, (int)(uintptr_t)pszSymbol));
1485 return VERR_SYMBOL_NOT_FOUND;
1486 }
1487
1488 /*
1489 * Lookup symbol.
1490 */
1491 /* skip the 64-bit ELF import prefix first. */
1492 if (!strncmp(pszSymbol, "SUPR0$", sizeof("SUPR0$") - 1))
1493 pszSymbol += sizeof("SUPR0$") - 1;
1494
1495 /*
1496 * Check the VMMR0.r0 module if loaded.
1497 */
1498 /** @todo call the SUPR3LoadModule caller.... */
1499 /** @todo proper reference counting and such. */
1500 if (g_pvVMMR0 != NIL_RTR0PTR)
1501 {
1502 void *pvValue;
1503 if (!SUPR3GetSymbolR0((void *)g_pvVMMR0, pszSymbol, &pvValue))
1504 {
1505 *pValue = (uintptr_t)pvValue;
1506 return VINF_SUCCESS;
1507 }
1508 }
1509
1510 /* iterate the function table. */
1511 int c = g_pFunctions->u.Out.cFunctions;
1512 PSUPFUNC pFunc = &g_pFunctions->u.Out.aFunctions[0];
1513 while (c-- > 0)
1514 {
1515 if (!strcmp(pFunc->szName, pszSymbol))
1516 {
1517 *pValue = (uintptr_t)pFunc->pfn;
1518 return VINF_SUCCESS;
1519 }
1520 pFunc++;
1521 }
1522
1523 /*
1524 * The GIP.
1525 */
1526 /** @todo R0 mapping? */
1527 if ( pszSymbol
1528 && g_pSUPGlobalInfoPage
1529 && g_pSUPGlobalInfoPageR0
1530 && !strcmp(pszSymbol, "g_SUPGlobalInfoPage"))
1531 {
1532 *pValue = (uintptr_t)g_pSUPGlobalInfoPageR0;
1533 return VINF_SUCCESS;
1534 }
1535
1536 /*
1537 * Despair.
1538 */
1539 c = g_pFunctions->u.Out.cFunctions;
1540 pFunc = &g_pFunctions->u.Out.aFunctions[0];
1541 while (c-- > 0)
1542 {
1543 AssertMsg2("%d: %s\n", g_pFunctions->u.Out.cFunctions - c, pFunc->szName);
1544 pFunc++;
1545 }
1546
1547 AssertMsg2("%s is importing %s which we couldn't find\n", pvUser, pszSymbol);
1548 AssertMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol));
1549 if (g_u32FakeMode)
1550 {
1551 *pValue = 0xdeadbeef;
1552 return VINF_SUCCESS;
1553 }
1554 return VERR_SYMBOL_NOT_FOUND;
1555}
1556
1557
1558/** Argument package for supLoadModuleCalcSizeCB. */
1559typedef struct SUPLDRCALCSIZEARGS
1560{
1561 size_t cbStrings;
1562 uint32_t cSymbols;
1563 size_t cbImage;
1564} SUPLDRCALCSIZEARGS, *PSUPLDRCALCSIZEARGS;
1565
1566/**
1567 * Callback used to calculate the image size.
1568 * @return VINF_SUCCESS
1569 */
1570static DECLCALLBACK(int) supLoadModuleCalcSizeCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
1571{
1572 PSUPLDRCALCSIZEARGS pArgs = (PSUPLDRCALCSIZEARGS)pvUser;
1573 if ( pszSymbol != NULL
1574 && *pszSymbol
1575 && Value <= pArgs->cbImage)
1576 {
1577 pArgs->cSymbols++;
1578 pArgs->cbStrings += strlen(pszSymbol) + 1;
1579 }
1580 return VINF_SUCCESS;
1581}
1582
1583
1584/** Argument package for supLoadModuleCreateTabsCB. */
1585typedef struct SUPLDRCREATETABSARGS
1586{
1587 size_t cbImage;
1588 PSUPLDRSYM pSym;
1589 char *pszBase;
1590 char *psz;
1591} SUPLDRCREATETABSARGS, *PSUPLDRCREATETABSARGS;
1592
1593/**
1594 * Callback used to calculate the image size.
1595 * @return VINF_SUCCESS
1596 */
1597static DECLCALLBACK(int) supLoadModuleCreateTabsCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
1598{
1599 PSUPLDRCREATETABSARGS pArgs = (PSUPLDRCREATETABSARGS)pvUser;
1600 if ( pszSymbol != NULL
1601 && *pszSymbol
1602 && Value <= pArgs->cbImage)
1603 {
1604 pArgs->pSym->offSymbol = (uint32_t)Value;
1605 pArgs->pSym->offName = pArgs->psz - pArgs->pszBase;
1606 pArgs->pSym++;
1607
1608 size_t cbCopy = strlen(pszSymbol) + 1;
1609 memcpy(pArgs->psz, pszSymbol, cbCopy);
1610 pArgs->psz += cbCopy;
1611 }
1612 return VINF_SUCCESS;
1613}
1614
1615
1616/**
1617 * Worker for SUPR3LoadModule().
1618 *
1619 * @returns VBox status code.
1620 * @param pszFilename Name of the VMMR0 image file
1621 */
1622static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase)
1623{
1624 /*
1625 * Validate input.
1626 */
1627 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
1628 AssertPtrReturn(pszModule, VERR_INVALID_PARAMETER);
1629 AssertPtrReturn(ppvImageBase, VERR_INVALID_PARAMETER);
1630 AssertReturn(strlen(pszModule) < RT_SIZEOFMEMB(SUPLDROPEN, u.In.szName), VERR_FILENAME_TOO_LONG);
1631
1632 const bool fIsVMMR0 = !strcmp(pszModule, "VMMR0.r0");
1633 AssertReturn(!pszSrvReqHandler || !fIsVMMR0, VERR_INTERNAL_ERROR);
1634 *ppvImageBase = NULL;
1635
1636 /*
1637 * Open image file and figure its size.
1638 */
1639 RTLDRMOD hLdrMod;
1640 int rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_HOST, &hLdrMod);
1641 if (!RT_SUCCESS(rc))
1642 return rc;
1643
1644 SUPLDRCALCSIZEARGS CalcArgs;
1645 CalcArgs.cbStrings = 0;
1646 CalcArgs.cSymbols = 0;
1647 CalcArgs.cbImage = RTLdrSize(hLdrMod);
1648 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCalcSizeCB, &CalcArgs);
1649 if (RT_SUCCESS(rc))
1650 {
1651 const uint32_t offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
1652 const uint32_t offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
1653 const uint32_t cbImage = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);
1654
1655 /*
1656 * Open the R0 image.
1657 */
1658 SUPLDROPEN OpenReq;
1659 OpenReq.Hdr.u32Cookie = g_u32Cookie;
1660 OpenReq.Hdr.u32SessionCookie = g_u32SessionCookie;
1661 OpenReq.Hdr.cbIn = SUP_IOCTL_LDR_OPEN_SIZE_IN;
1662 OpenReq.Hdr.cbOut = SUP_IOCTL_LDR_OPEN_SIZE_OUT;
1663 OpenReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1664 OpenReq.Hdr.rc = VERR_INTERNAL_ERROR;
1665 OpenReq.u.In.cbImage = cbImage;
1666 strcpy(OpenReq.u.In.szName, pszModule);
1667 if (!g_u32FakeMode)
1668 {
1669 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);
1670 if (RT_SUCCESS(rc))
1671 rc = OpenReq.Hdr.rc;
1672 }
1673 else
1674 {
1675 OpenReq.u.Out.fNeedsLoading = true;
1676 OpenReq.u.Out.pvImageBase = 0xef423420;
1677 }
1678 *ppvImageBase = (void *)OpenReq.u.Out.pvImageBase;
1679 if ( RT_SUCCESS(rc)
1680 && OpenReq.u.Out.fNeedsLoading)
1681 {
1682 /*
1683 * We need to load it.
1684 * Allocate memory for the image bits.
1685 */
1686 PSUPLDRLOAD pLoadReq = (PSUPLDRLOAD)RTMemTmpAlloc(SUP_IOCTL_LDR_LOAD_SIZE(cbImage));
1687 if (pLoadReq)
1688 {
1689 /*
1690 * Get the image bits.
1691 */
1692 rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
1693 supLoadModuleResolveImport, (void *)pszModule);
1694
1695 if (RT_SUCCESS(rc))
1696 {
1697 /*
1698 * Get the entry points.
1699 */
1700 RTUINTPTR VMMR0EntryInt = 0;
1701 RTUINTPTR VMMR0EntryFast = 0;
1702 RTUINTPTR VMMR0EntryEx = 0;
1703 RTUINTPTR SrvReqHandler = 0;
1704 RTUINTPTR ModuleInit = 0;
1705 RTUINTPTR ModuleTerm = 0;
1706 if (fIsVMMR0)
1707 {
1708 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryInt", &VMMR0EntryInt);
1709 if (RT_SUCCESS(rc))
1710 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryFast", &VMMR0EntryFast);
1711 if (RT_SUCCESS(rc))
1712 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryEx", &VMMR0EntryEx);
1713 }
1714 else if (pszSrvReqHandler)
1715 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, pszSrvReqHandler, &SrvReqHandler);
1716 if (RT_SUCCESS(rc))
1717 {
1718 int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleInit", &ModuleInit);
1719 if (RT_FAILURE(rc2))
1720 ModuleInit = 0;
1721
1722 rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleTerm", &ModuleTerm);
1723 if (RT_FAILURE(rc2))
1724 ModuleTerm = 0;
1725 }
1726 if (RT_SUCCESS(rc))
1727 {
1728 /*
1729 * Create the symbol and string tables.
1730 */
1731 SUPLDRCREATETABSARGS CreateArgs;
1732 CreateArgs.cbImage = CalcArgs.cbImage;
1733 CreateArgs.pSym = (PSUPLDRSYM)&pLoadReq->u.In.achImage[offSymTab];
1734 CreateArgs.pszBase = (char *)&pLoadReq->u.In.achImage[offStrTab];
1735 CreateArgs.psz = CreateArgs.pszBase;
1736 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);
1737 if (RT_SUCCESS(rc))
1738 {
1739 AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= CalcArgs.cbStrings);
1740 AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.achImage[offSymTab]) <= CalcArgs.cSymbols);
1741
1742 /*
1743 * Upload the image.
1744 */
1745 pLoadReq->Hdr.u32Cookie = g_u32Cookie;
1746 pLoadReq->Hdr.u32SessionCookie = g_u32SessionCookie;
1747 pLoadReq->Hdr.cbIn = SUP_IOCTL_LDR_LOAD_SIZE_IN(cbImage);
1748 pLoadReq->Hdr.cbOut = SUP_IOCTL_LDR_LOAD_SIZE_OUT;
1749 pLoadReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_IN;
1750 pLoadReq->Hdr.rc = VERR_INTERNAL_ERROR;
1751
1752 pLoadReq->u.In.pfnModuleInit = (RTR0PTR)ModuleInit;
1753 pLoadReq->u.In.pfnModuleTerm = (RTR0PTR)ModuleTerm;
1754 if (fIsVMMR0)
1755 {
1756 pLoadReq->u.In.eEPType = SUPLDRLOADEP_VMMR0;
1757 pLoadReq->u.In.EP.VMMR0.pvVMMR0 = OpenReq.u.Out.pvImageBase;
1758 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryInt = (RTR0PTR)VMMR0EntryInt;
1759 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryFast= (RTR0PTR)VMMR0EntryFast;
1760 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryEx = (RTR0PTR)VMMR0EntryEx;
1761 }
1762 else if (pszSrvReqHandler)
1763 {
1764 pLoadReq->u.In.eEPType = SUPLDRLOADEP_SERVICE;
1765 pLoadReq->u.In.EP.Service.pfnServiceReq = (RTR0PTR)SrvReqHandler;
1766 pLoadReq->u.In.EP.Service.apvReserved[0] = NIL_RTR0PTR;
1767 pLoadReq->u.In.EP.Service.apvReserved[1] = NIL_RTR0PTR;
1768 pLoadReq->u.In.EP.Service.apvReserved[2] = NIL_RTR0PTR;
1769 }
1770 else
1771 pLoadReq->u.In.eEPType = SUPLDRLOADEP_NOTHING;
1772 pLoadReq->u.In.offStrTab = offStrTab;
1773 pLoadReq->u.In.cbStrTab = (uint32_t)CalcArgs.cbStrings;
1774 AssertRelease(pLoadReq->u.In.cbStrTab == CalcArgs.cbStrings);
1775 pLoadReq->u.In.offSymbols = offSymTab;
1776 pLoadReq->u.In.cSymbols = CalcArgs.cSymbols;
1777 pLoadReq->u.In.cbImage = cbImage;
1778 pLoadReq->u.In.pvImageBase = OpenReq.u.Out.pvImageBase;
1779 if (!g_u32FakeMode)
1780 {
1781 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImage));
1782 if (RT_SUCCESS(rc))
1783 rc = pLoadReq->Hdr.rc;
1784 }
1785 else
1786 rc = VINF_SUCCESS;
1787 if ( RT_SUCCESS(rc)
1788 || rc == VERR_ALREADY_LOADED /* A competing process. */
1789 )
1790 {
1791 LogRel(("SUP: Loaded %s (%s) at %#p - ModuleInit at %RTptr and ModuleTerm at %RTptr\n", pszModule, pszFilename,
1792 OpenReq.u.Out.pvImageBase, ModuleInit, ModuleTerm));
1793 if (fIsVMMR0)
1794 {
1795 g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
1796 LogRel(("SUP: VMMR0EntryEx located at %RTptr, VMMR0EntryFast at %RTptr and VMMR0EntryInt at %RTptr\n",
1797 VMMR0EntryEx, VMMR0EntryFast, VMMR0EntryInt));
1798 }
1799#ifdef RT_OS_WINDOWS
1800 LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
1801#endif
1802
1803 RTMemTmpFree(pLoadReq);
1804 RTLdrClose(hLdrMod);
1805 return VINF_SUCCESS;
1806 }
1807 }
1808 }
1809 }
1810 RTMemTmpFree(pLoadReq);
1811 }
1812 else
1813 {
1814 AssertMsgFailed(("failed to allocated %d bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImage)));
1815 rc = VERR_NO_TMP_MEMORY;
1816 }
1817 }
1818 else if (RT_SUCCESS(rc))
1819 {
1820 if (fIsVMMR0)
1821 g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
1822 LogRel(("SUP: Opened %s (%s) at %#p.\n", pszModule, pszFilename, OpenReq.u.Out.pvImageBase));
1823#ifdef RT_OS_WINDOWS
1824 LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
1825#endif
1826 }
1827 }
1828 RTLdrClose(hLdrMod);
1829 return rc;
1830}
1831
1832
1833SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase)
1834{
1835 /* fake */
1836 if (RT_UNLIKELY(g_u32FakeMode))
1837 {
1838 g_pvVMMR0 = NIL_RTR0PTR;
1839 return VINF_SUCCESS;
1840 }
1841
1842 /*
1843 * Free the requested module.
1844 */
1845 SUPLDRFREE Req;
1846 Req.Hdr.u32Cookie = g_u32Cookie;
1847 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1848 Req.Hdr.cbIn = SUP_IOCTL_LDR_FREE_SIZE_IN;
1849 Req.Hdr.cbOut = SUP_IOCTL_LDR_FREE_SIZE_OUT;
1850 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1851 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1852 Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
1853 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_FREE, &Req, SUP_IOCTL_LDR_FREE_SIZE);
1854 if (RT_SUCCESS(rc))
1855 rc = Req.Hdr.rc;
1856 if ( RT_SUCCESS(rc)
1857 && (RTR0PTR)pvImageBase == g_pvVMMR0)
1858 g_pvVMMR0 = NIL_RTR0PTR;
1859 return rc;
1860}
1861
1862
1863SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue)
1864{
1865 *ppvValue = NULL;
1866
1867 /* fake */
1868 if (RT_UNLIKELY(g_u32FakeMode))
1869 {
1870 *ppvValue = (void *)(uintptr_t)0xdeadf00d;
1871 return VINF_SUCCESS;
1872 }
1873
1874 /*
1875 * Do ioctl.
1876 */
1877 SUPLDRGETSYMBOL Req;
1878 Req.Hdr.u32Cookie = g_u32Cookie;
1879 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1880 Req.Hdr.cbIn = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_IN;
1881 Req.Hdr.cbOut = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_OUT;
1882 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1883 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1884 Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
1885 size_t cchSymbol = strlen(pszSymbol);
1886 if (cchSymbol >= sizeof(Req.u.In.szSymbol))
1887 return VERR_SYMBOL_NOT_FOUND;
1888 memcpy(Req.u.In.szSymbol, pszSymbol, cchSymbol + 1);
1889 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_GET_SYMBOL, &Req, SUP_IOCTL_LDR_GET_SYMBOL_SIZE);
1890 if (RT_SUCCESS(rc))
1891 rc = Req.Hdr.rc;
1892 if (RT_SUCCESS(rc))
1893 *ppvValue = (void *)Req.u.Out.pvSymbol;
1894 return rc;
1895}
1896
1897
1898SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename)
1899{
1900 void *pvImageBase;
1901 return SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase);
1902}
1903
1904
1905SUPR3DECL(int) SUPR3UnloadVMM(void)
1906{
1907 return SUPR3FreeModule((void*)g_pvVMMR0);
1908}
1909
1910
1911SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys)
1912{
1913 if (g_pSUPGlobalInfoPage)
1914 {
1915 *pHCPhys = g_HCPhysSUPGlobalInfoPage;
1916 return VINF_SUCCESS;
1917 }
1918 *pHCPhys = NIL_RTHCPHYS;
1919 return VERR_WRONG_ORDER;
1920}
1921
1922
1923/**
1924 * Worker for SUPR3HardenedLdrLoad and SUPR3HardenedLdrLoadAppPriv.
1925 *
1926 * @returns iprt status code.
1927 * @param pszFilename The full file name.
1928 * @param phLdrMod Where to store the handle to the loaded module.
1929 */
1930static int supR3HardenedLdrLoadIt(const char *pszFilename, PRTLDRMOD phLdrMod)
1931{
1932#ifdef VBOX_WITH_HARDENING
1933 /*
1934 * Verify the image file.
1935 */
1936 int rc = supR3HardenedVerifyFile(pszFilename, false /* fFatal */);
1937 if (RT_FAILURE(rc))
1938 {
1939 LogRel(("supR3HardenedLdrLoadIt: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
1940 return rc;
1941 }
1942#endif
1943
1944 /*
1945 * Try load it.
1946 */
1947 return RTLdrLoad(pszFilename, phLdrMod);
1948}
1949
1950
1951SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod)
1952{
1953 /*
1954 * Validate input.
1955 */
1956 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
1957 AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
1958 *phLdrMod = NIL_RTLDRMOD;
1959 AssertReturn(RTPathHavePath(pszFilename), VERR_INVALID_PARAMETER);
1960
1961 /*
1962 * Add the default extension if it's missing.
1963 */
1964 if (!RTPathHaveExt(pszFilename))
1965 {
1966 const char *pszSuff = RTLdrGetSuff();
1967 size_t cchSuff = strlen(pszSuff);
1968 size_t cchFilename = strlen(pszFilename);
1969 char *psz = (char *)alloca(cchFilename + cchSuff + 1);
1970 AssertReturn(psz, VERR_NO_TMP_MEMORY);
1971 memcpy(psz, pszFilename, cchFilename);
1972 memcpy(psz + cchFilename, pszSuff, cchSuff + 1);
1973 pszFilename = psz;
1974 }
1975
1976 /*
1977 * Pass it on to the common library loader.
1978 */
1979 return supR3HardenedLdrLoadIt(pszFilename, phLdrMod);
1980}
1981
1982
1983SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod)
1984{
1985 LogFlow(("SUPR3HardenedLdrLoadAppPriv: pszFilename=%p:{%s} phLdrMod=%p\n", pszFilename, pszFilename, phLdrMod));
1986
1987 /*
1988 * Validate input.
1989 */
1990 AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
1991 *phLdrMod = NIL_RTLDRMOD;
1992 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
1993 AssertMsgReturn(!RTPathHavePath(pszFilename), ("%s\n", pszFilename), VERR_INVALID_PARAMETER);
1994
1995 /*
1996 * Check the filename.
1997 */
1998 size_t cchFilename = strlen(pszFilename);
1999 AssertMsgReturn(cchFilename < (RTPATH_MAX / 4) * 3, ("%zu\n", cchFilename), VERR_INVALID_PARAMETER);
2000
2001 const char *pszExt = "";
2002 size_t cchExt = 0;
2003 if (!RTPathHaveExt(pszFilename))
2004 {
2005 pszExt = RTLdrGetSuff();
2006 cchExt = strlen(pszExt);
2007 }
2008
2009 /*
2010 * Construct the private arch path and check if the file exists.
2011 */
2012 char szPath[RTPATH_MAX];
2013 int rc = RTPathAppPrivateArch(szPath, sizeof(szPath) - 1 - cchExt - cchFilename);
2014 AssertRCReturn(rc, rc);
2015
2016 char *psz = strchr(szPath, '\0');
2017 *psz++ = RTPATH_SLASH;
2018 memcpy(psz, pszFilename, cchFilename);
2019 psz += cchFilename;
2020 memcpy(psz, pszExt, cchExt + 1);
2021
2022 if (!RTPathExists(szPath))
2023 {
2024 LogRel(("SUPR3HardenedLdrLoadAppPriv: \"%s\" not found\n", szPath));
2025 return VERR_FILE_NOT_FOUND;
2026 }
2027
2028 /*
2029 * Pass it on to SUPR3HardenedLdrLoad.
2030 */
2031 rc = SUPR3HardenedLdrLoad(szPath, phLdrMod);
2032
2033 LogFlow(("SUPR3HardenedLdrLoadAppPriv: returns %Rrc\n", rc));
2034 return rc;
2035}
2036
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