VirtualBox

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

Last change on this file since 54890 was 52949, checked in by vboxsync, 10 years ago

SUP: Do the early init thing on the stub process too.

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