VirtualBox

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

Last change on this file since 25308 was 25278, checked in by vboxsync, 15 years ago

SUPDrv: Major IOC version change - preparing to use the native ring-0 loader on windwos.

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