VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp@ 84052

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

SUPHardNt: Define RTMEM_NO_WRAP_TO_EF_APIS for hardened exec stubs, won't link with RTMEM_WRAP_TO_EF_APIS enabled (windows at least).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.7 KB
Line 
1/* $Id: SUPR3HardenedNoCrt-win.cpp 84052 2020-04-28 15:58:56Z vboxsync $ */
2/** @file
3 * VirtualBox Support Library - Hardened main(), windows bits.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/nt/nt-and-windows.h>
32#include <AccCtrl.h>
33#include <AclApi.h>
34#ifndef PROCESS_SET_LIMITED_INFORMATION
35# define PROCESS_SET_LIMITED_INFORMATION 0x2000
36#endif
37
38#include <VBox/sup.h>
39#include <iprt/errcore.h>
40#include <iprt/assert.h>
41#include <iprt/ctype.h>
42#include <iprt/heap.h>
43#include <iprt/string.h>
44#include <iprt/initterm.h>
45#include <iprt/param.h>
46#include <iprt/path.h>
47#include <iprt/mem.h>
48#include <iprt/utf16.h>
49
50#include "SUPLibInternal.h"
51#include "win/SUPHardenedVerify-win.h"
52
53
54/*
55 * assert.cpp
56 */
57
58RTDATADECL(char) g_szRTAssertMsg1[1024];
59RTDATADECL(char) g_szRTAssertMsg2[4096];
60RTDATADECL(const char * volatile) g_pszRTAssertExpr;
61RTDATADECL(const char * volatile) g_pszRTAssertFile;
62RTDATADECL(uint32_t volatile) g_u32RTAssertLine;
63RTDATADECL(const char * volatile) g_pszRTAssertFunction;
64
65RTDECL(bool) RTAssertMayPanic(void)
66{
67 return true;
68}
69
70
71RTDECL(void) RTAssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
72{
73 /*
74 * Fill in the globals.
75 */
76 g_pszRTAssertExpr = pszExpr;
77 g_pszRTAssertFile = pszFile;
78 g_pszRTAssertFunction = pszFunction;
79 g_u32RTAssertLine = uLine;
80 RTStrPrintf(g_szRTAssertMsg1, sizeof(g_szRTAssertMsg1),
81 "\n!!Assertion Failed!!\n"
82 "Expression: %s\n"
83 "Location : %s(%d) %s\n",
84 pszExpr, pszFile, uLine, pszFunction);
85}
86
87
88RTDECL(void) RTAssertMsg2V(const char *pszFormat, va_list va)
89{
90 RTStrPrintfV(g_szRTAssertMsg2, sizeof(g_szRTAssertMsg2), pszFormat, va);
91 if (g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_CALLED_TRUSTED_MAIN)
92 supR3HardenedFatalMsg(g_pszRTAssertExpr, kSupInitOp_Misc, VERR_INTERNAL_ERROR,
93 "%s%s", g_szRTAssertMsg1, g_szRTAssertMsg2);
94 else
95 supR3HardenedError(VERR_INTERNAL_ERROR, false/*fFatal*/, "%s%s", g_szRTAssertMsg1, g_szRTAssertMsg2);
96}
97
98
99/*
100 * Memory allocator.
101 */
102
103/** The handle of the heap we're using. */
104static HANDLE g_hSupR3HardenedHeap = NULL;
105/** Number of heaps used during early process init. */
106static uint32_t g_cSupR3HardenedEarlyHeaps = 0;
107/** Early process init heaps. */
108static struct
109{
110 /** The heap handle. */
111 RTHEAPSIMPLE hHeap;
112 /** The heap block pointer. */
113 void *pvBlock;
114 /** The size of the heap block. */
115 size_t cbBlock;
116 /** Number of active allocations on this heap. */
117 size_t cAllocations;
118} g_aSupR3HardenedEarlyHeaps[8];
119
120
121static uint32_t supR3HardenedEarlyFind(void *pv)
122{
123 uint32_t iHeap = g_cSupR3HardenedEarlyHeaps;
124 while (iHeap-- > 0)
125 if ((uintptr_t)pv - (uintptr_t)g_aSupR3HardenedEarlyHeaps[iHeap].pvBlock < g_aSupR3HardenedEarlyHeaps[iHeap].cbBlock)
126 return iHeap;
127 return UINT32_MAX;
128}
129
130
131static void supR3HardenedEarlyCompact(void)
132{
133 uint32_t iHeap = g_cSupR3HardenedEarlyHeaps;
134 while (iHeap-- > 0)
135 if (g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations == 0)
136 {
137 PVOID pvMem = g_aSupR3HardenedEarlyHeaps[iHeap].pvBlock;
138 SIZE_T cbMem = g_aSupR3HardenedEarlyHeaps[iHeap].cbBlock;
139 if (iHeap + 1 < g_cSupR3HardenedEarlyHeaps)
140 g_aSupR3HardenedEarlyHeaps[iHeap] = g_aSupR3HardenedEarlyHeaps[g_cSupR3HardenedEarlyHeaps - 1];
141 g_cSupR3HardenedEarlyHeaps--;
142
143 NTSTATUS rcNt = NtFreeVirtualMemory(NtCurrentProcess(), &pvMem, &cbMem, MEM_RELEASE);
144 Assert(NT_SUCCESS(rcNt)); RT_NOREF_PV(rcNt);
145 SUP_DPRINTF(("supR3HardenedEarlyCompact: Removed heap %#u (%#p LB %#zx)\n", iHeap, pvMem, cbMem));
146 }
147}
148
149
150static void *supR3HardenedEarlyAlloc(size_t cb, bool fZero)
151{
152 /*
153 * Try allocate on existing heaps.
154 */
155 void *pv;
156 uint32_t iHeap = 0;
157 while (iHeap < g_cSupR3HardenedEarlyHeaps)
158 {
159 if (fZero)
160 pv = RTHeapSimpleAllocZ(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, cb, 0);
161 else
162 pv = RTHeapSimpleAlloc(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, cb, 0);
163 if (pv)
164 {
165 g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations++;
166#ifdef SUPR3HARDENED_EARLY_HEAP_TRACE
167 SUP_DPRINTF(("Early heap: %p LB %#zx - alloc\n", pv, cb));
168#endif
169 return pv;
170 }
171 iHeap++;
172 }
173
174 /*
175 * Add another heap.
176 */
177 if (iHeap == RT_ELEMENTS(g_aSupR3HardenedEarlyHeaps))
178 supR3HardenedFatal("Early heap table is full (cb=%#zx).\n", cb);
179 SIZE_T cbBlock = iHeap == 0 ? _1M : g_aSupR3HardenedEarlyHeaps[iHeap - 1].cbBlock * 2;
180 while (cbBlock <= cb * 2)
181 cbBlock *= 2;
182
183 PVOID pvBlock = NULL;
184 NTSTATUS rcNt = NtAllocateVirtualMemory(NtCurrentProcess(), &pvBlock, 0 /*ZeroBits*/, &cbBlock, MEM_COMMIT, PAGE_READWRITE);
185 if (!NT_SUCCESS(rcNt))
186 supR3HardenedFatal("NtAllocateVirtualMemory(,,,%#zx,,) failed: rcNt=%#x\n", cbBlock, rcNt);
187 SUP_DPRINTF(("New simple heap: #%u %p LB %#zx (for %zu allocation)\n", iHeap, pvBlock, cbBlock, cb));
188
189 RTHEAPSIMPLE hHeap;
190 int rc = RTHeapSimpleInit(&hHeap, pvBlock, cbBlock);
191 if (RT_FAILURE(rc))
192 supR3HardenedFatal("RTHeapSimpleInit(,%p,%#zx) failed: rc=%#x\n", pvBlock, cbBlock, rc);
193
194 if (fZero)
195 pv = RTHeapSimpleAllocZ(hHeap, cb, 0);
196 else
197 pv = RTHeapSimpleAlloc(hHeap, cb, 0);
198 if (!pv)
199 supR3HardenedFatal("RTHeapSimpleAlloc[Z] failed allocating %#zx bytes on a %#zu heap.\n", cb, cbBlock);
200
201 g_aSupR3HardenedEarlyHeaps[iHeap].pvBlock = pvBlock;
202 g_aSupR3HardenedEarlyHeaps[iHeap].cbBlock = cbBlock;
203 g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations = 1;
204 g_aSupR3HardenedEarlyHeaps[iHeap].hHeap = hHeap;
205
206 Assert(g_cSupR3HardenedEarlyHeaps == iHeap);
207 g_cSupR3HardenedEarlyHeaps = iHeap + 1;
208
209#ifdef SUPR3HARDENED_EARLY_HEAP_TRACE
210 SUP_DPRINTF(("Early heap: %p LB %#zx - alloc\n", pv, cb));
211#endif
212 return pv;
213}
214
215
216/**
217 * Lazy heap initialization function.
218 *
219 * @returns Heap handle.
220 */
221static HANDLE supR3HardenedHeapInit(void)
222{
223 Assert(g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED);
224 HANDLE hHeap = RtlCreateHeap(HEAP_GROWABLE | HEAP_CLASS_PRIVATE, NULL /*HeapBase*/,
225 0 /*ReserveSize*/, 0 /*CommitSize*/, NULL /*Lock*/, NULL /*Parameters*/);
226 if (hHeap)
227 {
228 g_hSupR3HardenedHeap = hHeap;
229 return hHeap;
230 }
231
232 supR3HardenedFatal("RtlCreateHeap failed.\n");
233 /* not reached */
234}
235
236
237/**
238 * Compacts the heaps before enter wait for parent/child.
239 */
240DECLHIDDEN(void) supR3HardenedWinCompactHeaps(void)
241{
242 if (g_hSupR3HardenedHeap)
243 RtlCompactHeap(g_hSupR3HardenedHeap, 0 /*dwFlags*/);
244 RtlCompactHeap(GetProcessHeap(), 0 /*dwFlags*/);
245 supR3HardenedEarlyCompact();
246}
247
248
249
250#undef RTMemTmpAllocTag
251RTDECL(void *) RTMemTmpAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
252{
253 return RTMemAllocTag(cb, pszTag);
254}
255
256
257#undef RTMemTmpAllocZTag
258RTDECL(void *) RTMemTmpAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
259{
260 return RTMemAllocZTag(cb, pszTag);
261}
262
263
264#undef RTMemTmpFree
265RTDECL(void) RTMemTmpFree(void *pv) RT_NO_THROW_DEF
266{
267 RTMemFree(pv);
268}
269
270
271#undef RTMemAllocTag
272RTDECL(void *) RTMemAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
273{
274 RT_NOREF1(pszTag);
275 HANDLE hHeap = g_hSupR3HardenedHeap;
276 if (!hHeap)
277 {
278 if ( g_fSupEarlyProcessInit
279 && g_enmSupR3HardenedMainState <= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED)
280 return supR3HardenedEarlyAlloc(cb, false /*fZero*/);
281 hHeap = supR3HardenedHeapInit();
282 }
283
284 void *pv = RtlAllocateHeap(hHeap, 0 /*fFlags*/, cb);
285 if (!pv)
286 supR3HardenedFatal("RtlAllocateHeap failed to allocate %zu bytes.\n", cb);
287 return pv;
288}
289
290
291#undef RTMemAllocZTag
292RTDECL(void *) RTMemAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
293{
294 RT_NOREF1(pszTag);
295 HANDLE hHeap = g_hSupR3HardenedHeap;
296 if (!hHeap)
297 {
298 if ( g_fSupEarlyProcessInit
299 && g_enmSupR3HardenedMainState <= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED)
300 return supR3HardenedEarlyAlloc(cb, true /*fZero*/);
301 hHeap = supR3HardenedHeapInit();
302 }
303
304 void *pv = RtlAllocateHeap(hHeap, HEAP_ZERO_MEMORY, cb);
305 if (!pv)
306 supR3HardenedFatal("RtlAllocateHeap failed to allocate %zu bytes.\n", cb);
307 return pv;
308}
309
310
311#undef RTMemAllocVarTag
312RTDECL(void *) RTMemAllocVarTag(size_t cbUnaligned, const char *pszTag) RT_NO_THROW_DEF
313{
314 size_t cbAligned;
315 if (cbUnaligned >= 16)
316 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
317 else
318 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
319 return RTMemAllocTag(cbAligned, pszTag);
320}
321
322
323#undef RTMemAllocZVarTag
324RTDECL(void *) RTMemAllocZVarTag(size_t cbUnaligned, const char *pszTag) RT_NO_THROW_DEF
325{
326 size_t cbAligned;
327 if (cbUnaligned >= 16)
328 cbAligned = RT_ALIGN_Z(cbUnaligned, 16);
329 else
330 cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *));
331 return RTMemAllocZTag(cbAligned, pszTag);
332}
333
334
335#undef RTMemReallocTag
336RTDECL(void *) RTMemReallocTag(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW_DEF
337{
338 if (!pvOld)
339 return RTMemAllocZTag(cbNew, pszTag);
340
341 void *pv;
342 if (g_fSupEarlyProcessInit)
343 {
344 uint32_t iHeap = supR3HardenedEarlyFind(pvOld);
345 if (iHeap != UINT32_MAX)
346 {
347#if 0 /* RTHeapSimpleRealloc is not implemented */
348 /* If this is before we can use a regular heap, we try resize
349 within the simple heap. (There are a lot of array growing in
350 the ASN.1 code.) */
351 if (g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED)
352 {
353 pv = RTHeapSimpleRealloc(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pvOld, cbNew, 0);
354 if (pv)
355 {
356# ifdef SUPR3HARDENED_EARLY_HEAP_TRACE
357 SUP_DPRINTF(("Early heap: %p LB %#zx, was %p - realloc\n", pvNew, cbNew, pvOld));
358# endif
359 return pv;
360 }
361 }
362#endif
363
364 /* Either we can't reallocate it on the same simple heap, or we're
365 past hardened main and wish to migrate everything over on the
366 real heap. */
367 size_t cbOld = RTHeapSimpleSize(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pvOld);
368 pv = RTMemAllocTag(cbNew, pszTag);
369 if (pv)
370 {
371 memcpy(pv, pvOld, RT_MIN(cbOld, cbNew));
372 RTHeapSimpleFree(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pvOld);
373 if (g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations)
374 g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations--;
375 if ( !g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations
376 && g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED)
377 supR3HardenedEarlyCompact();
378 }
379# ifdef SUPR3HARDENED_EARLY_HEAP_TRACE
380 SUP_DPRINTF(("Early heap: %p LB %#zx, was %p %LB %#zx - realloc\n", pv, cbNew, pvOld, cbOld));
381# endif
382 return pv;
383 }
384 Assert(g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED);
385 }
386
387 /* Allocate from the regular heap. */
388 HANDLE hHeap = g_hSupR3HardenedHeap;
389 Assert(hHeap != NULL);
390 pv = RtlReAllocateHeap(hHeap, 0 /*dwFlags*/, pvOld, cbNew);
391 if (!pv)
392 supR3HardenedFatal("RtlReAllocateHeap failed to allocate %zu bytes.\n", cbNew);
393 return pv;
394}
395
396
397#undef RTMemFree
398RTDECL(void) RTMemFree(void *pv) RT_NO_THROW_DEF
399{
400 if (pv)
401 {
402 if (g_fSupEarlyProcessInit)
403 {
404 uint32_t iHeap = supR3HardenedEarlyFind(pv);
405 if (iHeap != UINT32_MAX)
406 {
407#ifdef SUPR3HARDENED_EARLY_HEAP_TRACE
408 SUP_DPRINTF(("Early heap: %p - free\n", pv));
409#endif
410 RTHeapSimpleFree(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pv);
411 if (g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations)
412 g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations--;
413 if ( !g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations
414 && g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED)
415 supR3HardenedEarlyCompact();
416 return;
417 }
418 Assert(g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED);
419 }
420
421 HANDLE hHeap = g_hSupR3HardenedHeap;
422 Assert(hHeap != NULL);
423 RtlFreeHeap(hHeap, 0 /* dwFlags*/, pv);
424 }
425}
426
427
428/*
429 * Simplified version of RTMemWipeThoroughly that avoids dragging in the
430 * random number code.
431 */
432
433RTDECL(void) RTMemWipeThoroughly(void *pv, size_t cb, size_t cMinPasses) RT_NO_THROW_DEF
434{
435 size_t cPasses = RT_MIN(cMinPasses, 6);
436 static const uint32_t s_aPatterns[] = { 0x00, 0xaa, 0x55, 0xff, 0xf0, 0x0f, 0xcc, 0x3c, 0xc3 };
437 uint32_t iPattern = 0;
438 do
439 {
440 memset(pv, s_aPatterns[iPattern], cb);
441 iPattern = (iPattern + 1) % RT_ELEMENTS(s_aPatterns);
442 ASMMemoryFence();
443
444 memset(pv, s_aPatterns[iPattern], cb);
445 iPattern = (iPattern + 1) % RT_ELEMENTS(s_aPatterns);
446 ASMMemoryFence();
447
448 memset(pv, s_aPatterns[iPattern], cb);
449 iPattern = (iPattern + 1) % RT_ELEMENTS(s_aPatterns);
450 ASMMemoryFence();
451 } while (cPasses-- > 0);
452
453 memset(pv, 0xff, cb);
454 ASMMemoryFence();
455}
456
457
458
459/*
460 * path-win.cpp
461 */
462
463RTDECL(int) RTPathGetCurrent(char *pszPath, size_t cbPath)
464{
465 int rc;
466 if (g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED)
467/** @todo Rainy day: improve this by checking the process parameter block
468 * (needs to be normalized). */
469 rc = RTStrCopy(pszPath, cbPath, "C:\\");
470 else
471 {
472 /*
473 * GetCurrentDirectory may in some cases omit the drive letter, according
474 * to MSDN, thus the GetFullPathName call.
475 */
476 RTUTF16 wszCurPath[RTPATH_MAX];
477 if (GetCurrentDirectoryW(RTPATH_MAX, wszCurPath))
478 {
479 RTUTF16 wszFullPath[RTPATH_MAX];
480 if (GetFullPathNameW(wszCurPath, RTPATH_MAX, wszFullPath, NULL))
481 rc = RTUtf16ToUtf8Ex(&wszFullPath[0], RTSTR_MAX, &pszPath, cbPath, NULL);
482 else
483 rc = RTErrConvertFromWin32(RtlGetLastWin32Error());
484 }
485 else
486 rc = RTErrConvertFromWin32(RtlGetLastWin32Error());
487 }
488 return rc;
489}
490
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