VirtualBox

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

Last change on this file since 67954 was 62677, checked in by vboxsync, 8 years ago

SUPHardNt: -Wall warnings.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use