VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/compiler/vcc/stacksup-vcc.cpp@ 96573

最後變更 在這個檔案從96573是 96573,由 vboxsync 提交於 3 年 前

IPRT/nocrt: Fail fast and safer stack corruption. bugref:10261

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 10.4 KB
 
1/* $Id: stacksup-vcc.cpp 96573 2022-09-02 02:04:12Z vboxsync $ */
2/** @file
3 * IPRT - Visual C++ Compiler - Stack Checking C/C++ Support.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.alldomusa.eu.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include "internal/nocrt.h"
42
43#include <iprt/asm.h>
44#include <iprt/asm-amd64-x86.h>
45#ifndef IPRT_NOCRT_WITHOUT_FATAL_WRITE
46# include <iprt/assert.h>
47#endif
48
49#include "internal/compiler-vcc.h"
50#ifdef IN_RING3
51# include <iprt/win/windows.h>
52# include "../../../r3/win/internal-r3-win.h" /* ugly, but need some windows API function pointers */
53#endif
54
55
56/*********************************************************************************************************************************
57* Structures and Typedefs *
58*********************************************************************************************************************************/
59/** Variable descriptor. */
60typedef struct RTC_VAR_DESC_T
61{
62 int32_t offFrame;
63 uint32_t cbVar;
64 const char *pszName;
65} RTC_VAR_DESC_T;
66
67/** Frame descriptor. */
68typedef struct RTC_FRAME_DESC_T
69{
70 uint32_t cVars;
71 RTC_VAR_DESC_T const *paVars;
72} RTC_FRAME_DESC_T;
73
74#define VARIABLE_MARKER_PRE 0xcccccccc
75#define VARIABLE_MARKER_POST 0xcccccccc
76
77
78/**
79 * Alloca allocation entry.
80 * @note For whatever reason the pNext and cb members are misaligned on 64-bit
81 * targets. 32-bit targets OTOH adds padding to keep the structure size
82 * and pNext + cb offsets the same.
83 */
84#pragma pack(4)
85typedef struct RTC_ALLOC_ENTRY
86{
87 uint32_t uGuard1;
88 RTC_ALLOC_ENTRY *pNext;
89#if ARCH_BITS == 32
90 uint32_t pNextPad;
91#endif
92 size_t cb;
93#if ARCH_BITS == 32
94 uint32_t cbPad;
95#endif
96 uint32_t auGuard2[3];
97} RTC_ALLOC_ENTRY;
98#pragma pack()
99
100#define ALLOCA_FILLER_BYTE 0xcc
101#define ALLOCA_FILLER_32 0xcccccccc
102
103
104/*********************************************************************************************************************************
105* External Symbols *
106*********************************************************************************************************************************/
107extern "C" void __fastcall _RTC_CheckStackVars(uint8_t *pbFrame, RTC_VAR_DESC_T const *pVar); /* nocrt-stack.asm */
108extern "C" uintptr_t __security_cookie;
109
110
111/**
112 * Initializes the security cookie value.
113 *
114 * This must be called as the first thing by the startup code. We must also no
115 * do anything fancy here.
116 */
117void rtVccInitSecurityCookie(void) RT_NOEXCEPT
118{
119 __security_cookie = (uintptr_t)ASMReadTSC() ^ (uintptr_t)&__security_cookie;
120}
121
122
123/**
124 * Reports a security error.
125 *
126 * @param uFastFailCode The fast fail code.
127 * @param pCpuCtx The CPU context at the failure location.
128 */
129static DECL_NO_RETURN(void) rtVccFatalSecurityErrorWithCtx(uint32_t uFastFailCode, PCONTEXT pCpuCtx)
130{
131#ifdef IN_RING3
132 /*
133 * Use the __fastfail() approach if available, it is more secure than the stuff below:
134 */
135 if (g_pfnIsProcessorFeaturePresent && g_pfnIsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE))
136 __fastfail(uFastFailCode);
137
138 /*
139 * Fallback for legacy systems.
140 */
141 if (g_pfnIsDebuggerPresent && g_pfnIsDebuggerPresent())
142 __debugbreak();
143
144 /* If we can, clear the unhandled exception filter and report and unhandled exception. */
145 if (g_pfnSetUnhandledExceptionFilter && g_pfnUnhandledExceptionFilter)
146 {
147 g_pfnSetUnhandledExceptionFilter(NULL);
148
149 EXCEPTION_RECORD XcptRec =
150 {
151 /* .ExceptionCode = */ STATUS_STACK_BUFFER_OVERRUN,
152 /* .ExceptionFlags = */ EXCEPTION_NONCONTINUABLE,
153 /* .ExceptionRecord = */ NULL,
154# ifdef RT_ARCH_AMD64
155 /* .ExceptionAddress = */ (void *)pCpuCtx->Rip,
156# elif defined(RT_ARCH_X86)
157 /* .ExceptionAddress = */ (void *)pCpuCtx->Eip,
158# else
159# error "Port me!"
160# endif
161 /* .NumberParameters = */ 1,
162 /* .ExceptionInformation = */ { uFastFailCode, }
163 };
164
165 EXCEPTION_POINTERS XcptPtrs = { &XcptRec, pCpuCtx };
166 g_pfnUnhandledExceptionFilter(&XcptPtrs);
167 }
168
169 for (;;)
170 TerminateProcess(GetCurrentProcess(), STATUS_STACK_BUFFER_OVERRUN);
171
172#else
173# error "Port ME!"
174#endif
175}
176
177
178DECLASM(void) rtVccStackVarCorrupted(uint8_t *pbFrame, RTC_VAR_DESC_T const *pVar, PCONTEXT pCpuCtx)
179{
180#ifdef IPRT_NOCRT_WITHOUT_FATAL_WRITE
181 RTAssertMsg2("\n\n!!Stack corruption!!\n\n"
182 "%p LB %#x - %s\n",
183 pbFrame + pVar->offFrame, pVar->cbVar, pVar->pszName);
184#else
185 rtNoCrtFatalWriteBegin(RT_STR_TUPLE("\r\n\r\n!!Stack corruption!!\r\n\r\n"));
186 rtNoCrtFatalWritePtr(pbFrame + pVar->offFrame);
187 rtNoCrtFatalWrite(RT_STR_TUPLE(" LB "));
188 rtNoCrtFatalWriteX32(pVar->cbVar);
189 rtNoCrtFatalWrite(RT_STR_TUPLE(" - "));
190 rtNoCrtFatalWriteStr(pVar->pszName);
191 rtNoCrtFatalWriteEnd(RT_STR_TUPLE("\r\n"));
192#endif
193 rtVccFatalSecurityErrorWithCtx(FAST_FAIL_INCORRECT_STACK, pCpuCtx);
194}
195
196
197DECLASM(void) rtVccSecurityCookieMismatch(uintptr_t uCookie, PCONTEXT pCpuCtx)
198{
199#ifdef IPRT_NOCRT_WITHOUT_FATAL_WRITE
200 RTAssertMsg2("\n\n!!Stack cookie corruption!!\n\n"
201 "expected %p, found %p\n",
202 __security_cookie, uCookie);
203#else
204 rtNoCrtFatalWriteBegin(RT_STR_TUPLE("\r\n\r\n!!Stack cookie corruption!!\r\n\r\n"
205 "expected"));
206 rtNoCrtFatalWritePtr((void *)__security_cookie);
207 rtNoCrtFatalWrite(RT_STR_TUPLE(", found "));
208 rtNoCrtFatalWritePtr((void *)uCookie);
209 rtNoCrtFatalWriteEnd(RT_STR_TUPLE("\r\n"));
210#endif
211 rtVccFatalSecurityErrorWithCtx(FAST_FAIL_STACK_COOKIE_CHECK_FAILURE, pCpuCtx);
212}
213
214
215#ifdef RT_ARCH_X86
216DECLASM(void) rtVccCheckEspFailed(PCONTEXT pCpuCtx)
217{
218# ifdef IPRT_NOCRT_WITHOUT_FATAL_WRITE
219 RTAssertMsg2("\n\n!!ESP check failed!!\n\n"
220 "eip=%p esp=%p ebp=%p\n",
221 pCpuCtx->Eip, pCpuCtx->Esp, pCpuCtx->Ebp);
222# else
223 rtNoCrtFatalWriteBegin(RT_STR_TUPLE("\r\n\r\n!!ESP check failed!!\r\n\r\n"
224 "eip="));
225 rtNoCrtFatalWritePtr((void *)pCpuCtx->Eip);
226 rtNoCrtFatalWrite(RT_STR_TUPLE(" esp="));
227 rtNoCrtFatalWritePtr((void *)pCpuCtx->Esp);
228 rtNoCrtFatalWrite(RT_STR_TUPLE(" ebp="));
229 rtNoCrtFatalWritePtr((void *)pCpuCtx->Ebp);
230 rtNoCrtFatalWriteEnd(RT_STR_TUPLE("\r\n"));
231# endif
232 rtVccFatalSecurityErrorWithCtx(FAST_FAIL_INCORRECT_STACK, pCpuCtx);
233}
234#endif
235
236
237/** @todo reimplement in assembly (feeling too lazy right now). */
238extern "C" void __fastcall _RTC_CheckStackVars2(uint8_t *pbFrame, RTC_VAR_DESC_T const *pVar, RTC_ALLOC_ENTRY *pHead)
239{
240 while (pHead)
241 {
242 if ( pHead->uGuard1 == ALLOCA_FILLER_32
243#if 1 && ARCH_BITS == 32
244 && pHead->pNextPad == ALLOCA_FILLER_32
245 && pHead->cbPad == ALLOCA_FILLER_32
246#endif
247 && pHead->auGuard2[0] == ALLOCA_FILLER_32
248 && pHead->auGuard2[1] == ALLOCA_FILLER_32
249 && pHead->auGuard2[2] == ALLOCA_FILLER_32
250 && *(uint32_t const *)((uint8_t const *)pHead + pHead->cb - sizeof(uint32_t)) == ALLOCA_FILLER_32)
251 { /* likely */ }
252 else
253 {
254#ifdef IPRT_NOCRT_WITHOUT_FATAL_WRITE
255 RTAssertMsg2("\n\n!!Stack corruption (alloca)!!\n\n"
256 "%p LB %#x\n",
257 pHead, pHead->cb);
258#else
259 rtNoCrtFatalWriteBegin(RT_STR_TUPLE("\r\n\r\n!!Stack corruption (alloca)!!\r\n\r\n"));
260 rtNoCrtFatalWritePtr(pHead);
261 rtNoCrtFatalWrite(RT_STR_TUPLE(" LB "));
262 rtNoCrtFatalWriteX64(pHead->cb);
263 rtNoCrtFatalWriteEnd(RT_STR_TUPLE("\r\n"));
264#endif
265#ifdef IN_RING3
266 if (g_pfnIsDebuggerPresent && g_pfnIsDebuggerPresent())
267#endif
268 RT_BREAKPOINT();
269 }
270 pHead = pHead->pNext;
271 }
272
273 _RTC_CheckStackVars(pbFrame, pVar);
274}
275
276
277
278
279/** Whether or not this should be a fatal issue remains to be seen. See
280 * explanation in stack-vcc.asm. */
281#if 0
282DECLASM(void) rtVccUninitializedVariableUse(const char *pszVar, PCONTEXT pCpuCtx)
283#else
284extern "C" void __cdecl _RTC_UninitUse(const char *pszVar)
285#endif
286{
287#ifdef IPRT_NOCRT_WITHOUT_FATAL_WRITE
288 RTAssertMsg2("\n\n!!Used uninitialized variable %s at %p!!\n\n",
289 pszVar ? pszVar : "", ASMReturnAddress());
290#else
291 rtNoCrtFatalWriteBegin(RT_STR_TUPLE("\r\n\r\n!!Used uninitialized variable "));
292 rtNoCrtFatalWriteStr(pszVar);
293 rtNoCrtFatalWrite(RT_STR_TUPLE(" at "));
294 rtNoCrtFatalWritePtr(ASMReturnAddress());
295 rtNoCrtFatalWriteEnd(RT_STR_TUPLE("!!\r\n\r\n"));
296#endif
297#if 0
298 rtVccFatalSecurityErrorWithCtx(FAST_FAIL_FATAL_APP_EXIT, pCpuCtx);
299#else
300# ifdef IN_RING3
301 if (g_pfnIsDebuggerPresent && g_pfnIsDebuggerPresent())
302# endif
303 RT_BREAKPOINT();
304#endif
305}
306
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette