From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../Support/win/SUPR3HardenedNoCrt-win.cpp | 501 +++++++++++++++++++++ 1 file changed, 501 insertions(+) create mode 100644 src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp (limited to 'src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp') diff --git a/src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp b/src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp new file mode 100644 index 00000000..711c6077 --- /dev/null +++ b/src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp @@ -0,0 +1,501 @@ +/* $Id: SUPR3HardenedNoCrt-win.cpp $ */ +/** @file + * VirtualBox Support Library - Hardened main(), windows bits. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include +#include +#include +#ifndef PROCESS_SET_LIMITED_INFORMATION +# define PROCESS_SET_LIMITED_INFORMATION 0x2000 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SUPLibInternal.h" +#include "win/SUPHardenedVerify-win.h" + + +/* + * assert.cpp + */ + +RTDATADECL(char) g_szRTAssertMsg1[1024]; +RTDATADECL(char) g_szRTAssertMsg2[4096]; +RTDATADECL(const char * volatile) g_pszRTAssertExpr; +RTDATADECL(const char * volatile) g_pszRTAssertFile; +RTDATADECL(uint32_t volatile) g_u32RTAssertLine; +RTDATADECL(const char * volatile) g_pszRTAssertFunction; + + +RTDECL(bool) RTAssertMayPanic(void) +{ + return true; +} + + +RTDECL(void) RTAssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction) +{ + /* + * Fill in the globals. + */ + g_pszRTAssertExpr = pszExpr; + g_pszRTAssertFile = pszFile; + g_pszRTAssertFunction = pszFunction; + g_u32RTAssertLine = uLine; + RTStrPrintf(g_szRTAssertMsg1, sizeof(g_szRTAssertMsg1), + "\n!!Assertion Failed!!\n" + "Expression: %s\n" + "Location : %s(%d) %s\n", + pszExpr, pszFile, uLine, pszFunction); +} + + +RTDECL(void) RTAssertMsg2V(const char *pszFormat, va_list va) +{ + RTStrPrintfV(g_szRTAssertMsg2, sizeof(g_szRTAssertMsg2), pszFormat, va); + if (g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_CALLED_TRUSTED_MAIN) + supR3HardenedFatalMsg(g_pszRTAssertExpr, kSupInitOp_Misc, VERR_INTERNAL_ERROR, + "%s%s", g_szRTAssertMsg1, g_szRTAssertMsg2); + else + supR3HardenedError(VERR_INTERNAL_ERROR, false/*fFatal*/, "%s%s", g_szRTAssertMsg1, g_szRTAssertMsg2); +} + + +/* + * Memory allocator. + */ + +/** The handle of the heap we're using. */ +static HANDLE g_hSupR3HardenedHeap = NULL; +/** Number of heaps used during early process init. */ +static uint32_t g_cSupR3HardenedEarlyHeaps = 0; +/** Early process init heaps. */ +static struct +{ + /** The heap handle. */ + RTHEAPSIMPLE hHeap; + /** The heap block pointer. */ + void *pvBlock; + /** The size of the heap block. */ + size_t cbBlock; + /** Number of active allocations on this heap. */ + size_t cAllocations; +} g_aSupR3HardenedEarlyHeaps[8]; + + +static uint32_t supR3HardenedEarlyFind(void *pv) RT_NOTHROW_DEF +{ + uint32_t iHeap = g_cSupR3HardenedEarlyHeaps; + while (iHeap-- > 0) + if ((uintptr_t)pv - (uintptr_t)g_aSupR3HardenedEarlyHeaps[iHeap].pvBlock < g_aSupR3HardenedEarlyHeaps[iHeap].cbBlock) + return iHeap; + return UINT32_MAX; +} + + +static void supR3HardenedEarlyCompact(void) RT_NOTHROW_DEF +{ + uint32_t iHeap = g_cSupR3HardenedEarlyHeaps; + while (iHeap-- > 0) + if (g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations == 0) + { + PVOID pvMem = g_aSupR3HardenedEarlyHeaps[iHeap].pvBlock; + SIZE_T cbMem = g_aSupR3HardenedEarlyHeaps[iHeap].cbBlock; + if (iHeap + 1 < g_cSupR3HardenedEarlyHeaps) + g_aSupR3HardenedEarlyHeaps[iHeap] = g_aSupR3HardenedEarlyHeaps[g_cSupR3HardenedEarlyHeaps - 1]; + g_cSupR3HardenedEarlyHeaps--; + + NTSTATUS rcNt = NtFreeVirtualMemory(NtCurrentProcess(), &pvMem, &cbMem, MEM_RELEASE); + Assert(NT_SUCCESS(rcNt)); RT_NOREF_PV(rcNt); + SUP_DPRINTF(("supR3HardenedEarlyCompact: Removed heap %#u (%#p LB %#zx)\n", iHeap, pvMem, cbMem)); + } +} + + +static void *supR3HardenedEarlyAlloc(size_t cb, bool fZero) RT_NOTHROW_DEF +{ + /* + * Try allocate on existing heaps. + */ + void *pv; + uint32_t iHeap = 0; + while (iHeap < g_cSupR3HardenedEarlyHeaps) + { + if (fZero) + pv = RTHeapSimpleAllocZ(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, cb, 0); + else + pv = RTHeapSimpleAlloc(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, cb, 0); + if (pv) + { + g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations++; +#ifdef SUPR3HARDENED_EARLY_HEAP_TRACE + SUP_DPRINTF(("Early heap: %p LB %#zx - alloc\n", pv, cb)); +#endif + return pv; + } + iHeap++; + } + + /* + * Add another heap. + */ + if (iHeap == RT_ELEMENTS(g_aSupR3HardenedEarlyHeaps)) + supR3HardenedFatal("Early heap table is full (cb=%#zx).\n", cb); + SIZE_T cbBlock = iHeap == 0 ? _1M : g_aSupR3HardenedEarlyHeaps[iHeap - 1].cbBlock * 2; + while (cbBlock <= cb * 2) + cbBlock *= 2; + + PVOID pvBlock = NULL; + NTSTATUS rcNt = NtAllocateVirtualMemory(NtCurrentProcess(), &pvBlock, 0 /*ZeroBits*/, &cbBlock, MEM_COMMIT, PAGE_READWRITE); + if (!NT_SUCCESS(rcNt)) + supR3HardenedFatal("NtAllocateVirtualMemory(,,,%#zx,,) failed: rcNt=%#x\n", cbBlock, rcNt); + SUP_DPRINTF(("New simple heap: #%u %p LB %#zx (for %zu allocation)\n", iHeap, pvBlock, cbBlock, cb)); + + RTHEAPSIMPLE hHeap; + int rc = RTHeapSimpleInit(&hHeap, pvBlock, cbBlock); + if (RT_FAILURE(rc)) + supR3HardenedFatal("RTHeapSimpleInit(,%p,%#zx) failed: rc=%#x\n", pvBlock, cbBlock, rc); + + if (fZero) + pv = RTHeapSimpleAllocZ(hHeap, cb, 0); + else + pv = RTHeapSimpleAlloc(hHeap, cb, 0); + if (!pv) + supR3HardenedFatal("RTHeapSimpleAlloc[Z] failed allocating %#zx bytes on a %#zu heap.\n", cb, cbBlock); + + g_aSupR3HardenedEarlyHeaps[iHeap].pvBlock = pvBlock; + g_aSupR3HardenedEarlyHeaps[iHeap].cbBlock = cbBlock; + g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations = 1; + g_aSupR3HardenedEarlyHeaps[iHeap].hHeap = hHeap; + + Assert(g_cSupR3HardenedEarlyHeaps == iHeap); + g_cSupR3HardenedEarlyHeaps = iHeap + 1; + +#ifdef SUPR3HARDENED_EARLY_HEAP_TRACE + SUP_DPRINTF(("Early heap: %p LB %#zx - alloc\n", pv, cb)); +#endif + return pv; +} + + +/** + * Lazy heap initialization function. + * + * @returns Heap handle. + */ +static HANDLE supR3HardenedHeapInit(void) RT_NOTHROW_DEF +{ + Assert(g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED); + HANDLE hHeap = RtlCreateHeap(HEAP_GROWABLE | HEAP_CLASS_PRIVATE, NULL /*HeapBase*/, + 0 /*ReserveSize*/, 0 /*CommitSize*/, NULL /*Lock*/, NULL /*Parameters*/); + if (hHeap) + { + g_hSupR3HardenedHeap = hHeap; + return hHeap; + } + + supR3HardenedFatal("RtlCreateHeap failed.\n"); + /* not reached */ +} + + +/** + * Compacts the heaps before enter wait for parent/child. + */ +DECLHIDDEN(void) supR3HardenedWinCompactHeaps(void) +{ + if (g_hSupR3HardenedHeap) + RtlCompactHeap(g_hSupR3HardenedHeap, 0 /*dwFlags*/); + RtlCompactHeap(GetProcessHeap(), 0 /*dwFlags*/); + supR3HardenedEarlyCompact(); +} + + + +#undef RTMemTmpAllocTag +RTDECL(void *) RTMemTmpAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF +{ + return RTMemAllocTag(cb, pszTag); +} + + +#undef RTMemTmpAllocZTag +RTDECL(void *) RTMemTmpAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF +{ + return RTMemAllocZTag(cb, pszTag); +} + + +#undef RTMemTmpFree +RTDECL(void) RTMemTmpFree(void *pv) RT_NO_THROW_DEF +{ + RTMemFree(pv); +} + + +#undef RTMemAllocTag +RTDECL(void *) RTMemAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF +{ + RT_NOREF1(pszTag); + HANDLE hHeap = g_hSupR3HardenedHeap; + if (!hHeap) + { + if ( g_fSupEarlyProcessInit + && g_enmSupR3HardenedMainState <= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED) + return supR3HardenedEarlyAlloc(cb, false /*fZero*/); + hHeap = supR3HardenedHeapInit(); + } + + void *pv = RtlAllocateHeap(hHeap, 0 /*fFlags*/, cb); + if (!pv) + supR3HardenedFatal("RtlAllocateHeap failed to allocate %zu bytes.\n", cb); + return pv; +} + + +#undef RTMemAllocZTag +RTDECL(void *) RTMemAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF +{ + RT_NOREF1(pszTag); + HANDLE hHeap = g_hSupR3HardenedHeap; + if (!hHeap) + { + if ( g_fSupEarlyProcessInit + && g_enmSupR3HardenedMainState <= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED) + return supR3HardenedEarlyAlloc(cb, true /*fZero*/); + hHeap = supR3HardenedHeapInit(); + } + + void *pv = RtlAllocateHeap(hHeap, HEAP_ZERO_MEMORY, cb); + if (!pv) + supR3HardenedFatal("RtlAllocateHeap failed to allocate %zu bytes.\n", cb); + return pv; +} + + +#undef RTMemAllocVarTag +RTDECL(void *) RTMemAllocVarTag(size_t cbUnaligned, const char *pszTag) RT_NO_THROW_DEF +{ + size_t cbAligned; + if (cbUnaligned >= 16) + cbAligned = RT_ALIGN_Z(cbUnaligned, 16); + else + cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *)); + return RTMemAllocTag(cbAligned, pszTag); +} + + +#undef RTMemAllocZVarTag +RTDECL(void *) RTMemAllocZVarTag(size_t cbUnaligned, const char *pszTag) RT_NO_THROW_DEF +{ + size_t cbAligned; + if (cbUnaligned >= 16) + cbAligned = RT_ALIGN_Z(cbUnaligned, 16); + else + cbAligned = RT_ALIGN_Z(cbUnaligned, sizeof(void *)); + return RTMemAllocZTag(cbAligned, pszTag); +} + + +#undef RTMemReallocTag +RTDECL(void *) RTMemReallocTag(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW_DEF +{ + if (!pvOld) + return RTMemAllocZTag(cbNew, pszTag); + + void *pv; + if (g_fSupEarlyProcessInit) + { + uint32_t iHeap = supR3HardenedEarlyFind(pvOld); + if (iHeap != UINT32_MAX) + { +#if 0 /* RTHeapSimpleRealloc is not implemented */ + /* If this is before we can use a regular heap, we try resize + within the simple heap. (There are a lot of array growing in + the ASN.1 code.) */ + if (g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) + { + pv = RTHeapSimpleRealloc(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pvOld, cbNew, 0); + if (pv) + { +# ifdef SUPR3HARDENED_EARLY_HEAP_TRACE + SUP_DPRINTF(("Early heap: %p LB %#zx, was %p - realloc\n", pvNew, cbNew, pvOld)); +# endif + return pv; + } + } +#endif + + /* Either we can't reallocate it on the same simple heap, or we're + past hardened main and wish to migrate everything over on the + real heap. */ + size_t cbOld = RTHeapSimpleSize(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pvOld); + pv = RTMemAllocTag(cbNew, pszTag); + if (pv) + { + memcpy(pv, pvOld, RT_MIN(cbOld, cbNew)); + RTHeapSimpleFree(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pvOld); + if (g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations) + g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations--; + if ( !g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations + && g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) + supR3HardenedEarlyCompact(); + } +# ifdef SUPR3HARDENED_EARLY_HEAP_TRACE + SUP_DPRINTF(("Early heap: %p LB %#zx, was %p %LB %#zx - realloc\n", pv, cbNew, pvOld, cbOld)); +# endif + return pv; + } + Assert(g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED); + } + + /* Allocate from the regular heap. */ + HANDLE hHeap = g_hSupR3HardenedHeap; + Assert(hHeap != NULL); + pv = RtlReAllocateHeap(hHeap, 0 /*dwFlags*/, pvOld, cbNew); + if (!pv) + supR3HardenedFatal("RtlReAllocateHeap failed to allocate %zu bytes.\n", cbNew); + return pv; +} + + +#undef RTMemFree +RTDECL(void) RTMemFree(void *pv) RT_NO_THROW_DEF +{ + if (pv) + { + if (g_fSupEarlyProcessInit) + { + uint32_t iHeap = supR3HardenedEarlyFind(pv); + if (iHeap != UINT32_MAX) + { +#ifdef SUPR3HARDENED_EARLY_HEAP_TRACE + SUP_DPRINTF(("Early heap: %p - free\n", pv)); +#endif + RTHeapSimpleFree(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pv); + if (g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations) + g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations--; + if ( !g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations + && g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) + supR3HardenedEarlyCompact(); + return; + } + Assert(g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED); + } + + HANDLE hHeap = g_hSupR3HardenedHeap; + Assert(hHeap != NULL); + RtlFreeHeap(hHeap, 0 /* dwFlags*/, pv); + } +} + + +/* + * Simplified version of RTMemWipeThoroughly that avoids dragging in the + * random number code. + */ + +RTDECL(void) RTMemWipeThoroughly(void *pv, size_t cb, size_t cMinPasses) RT_NO_THROW_DEF +{ + size_t cPasses = RT_MIN(cMinPasses, 6); + static const uint32_t s_aPatterns[] = { 0x00, 0xaa, 0x55, 0xff, 0xf0, 0x0f, 0xcc, 0x3c, 0xc3 }; + uint32_t iPattern = 0; + do + { + memset(pv, s_aPatterns[iPattern], cb); + iPattern = (iPattern + 1) % RT_ELEMENTS(s_aPatterns); + ASMMemoryFence(); + + memset(pv, s_aPatterns[iPattern], cb); + iPattern = (iPattern + 1) % RT_ELEMENTS(s_aPatterns); + ASMMemoryFence(); + + memset(pv, s_aPatterns[iPattern], cb); + iPattern = (iPattern + 1) % RT_ELEMENTS(s_aPatterns); + ASMMemoryFence(); + } while (cPasses-- > 0); + + memset(pv, 0xff, cb); + ASMMemoryFence(); +} + + + +/* + * path-win.cpp + */ + +RTDECL(int) RTPathGetCurrent(char *pszPath, size_t cbPath) +{ + int rc; + if (g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) +/** @todo Rainy day: improve this by checking the process parameter block + * (needs to be normalized). */ + rc = RTStrCopy(pszPath, cbPath, "C:\\"); + else + { + /* + * GetCurrentDirectory may in some cases omit the drive letter, according + * to MSDN, thus the GetFullPathName call. + */ + RTUTF16 wszCurPath[RTPATH_MAX]; + if (GetCurrentDirectoryW(RTPATH_MAX, wszCurPath)) + { + RTUTF16 wszFullPath[RTPATH_MAX]; + if (GetFullPathNameW(wszCurPath, RTPATH_MAX, wszFullPath, NULL)) + rc = RTUtf16ToUtf8Ex(&wszFullPath[0], RTSTR_MAX, &pszPath, cbPath, NULL); + else + rc = RTErrConvertFromWin32(RtlGetLastWin32Error()); + } + else + rc = RTErrConvertFromWin32(RtlGetLastWin32Error()); + } + return rc; +} + -- cgit v1.2.3