1 // Copyright 2018 The BoringSSL Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "abi_test.h"
16
17 #include <stdarg.h>
18 #include <stdio.h>
19
20 #include <algorithm>
21 #include <array>
22
23 #include <openssl/mem.h>
24 #include <openssl/rand.h>
25 #include <openssl/span.h>
26
27 #if defined(OPENSSL_X86_64) && defined(SUPPORTS_ABI_TEST)
28 #if defined(OPENSSL_LINUX) && defined(BORINGSSL_HAVE_LIBUNWIND)
29 #define SUPPORTS_UNWIND_TEST
30 #define UNW_LOCAL_ONLY
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <libunwind.h>
34 #include <pthread.h>
35 #include <signal.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41 #elif defined(OPENSSL_WINDOWS)
42 #define SUPPORTS_UNWIND_TEST
43 #include <windows.h>
44 #include <dbghelp.h>
45 #endif
46 #endif // X86_64 && SUPPORTS_ABI_TEST
47
48 // FIPS mode breaks unwind tests. See https://crbug.com/boringssl/289.
49 #if defined(BORINGSSL_FIPS)
50 #undef SUPPORTS_UNWIND_TEST
51 #endif
52
53
54 namespace abi_test {
55
56 namespace internal {
57
58 static bool g_unwind_tests_enabled = false;
59
FixVAArgsString(const char * str)60 std::string FixVAArgsString(const char *str) {
61 std::string ret = str;
62 size_t idx = ret.find(',');
63 if (idx == std::string::npos) {
64 return ret + "()";
65 }
66 size_t idx2 = idx + 1;
67 while (idx2 < ret.size() && ret[idx2] == ' ') {
68 idx2++;
69 }
70 while (idx > 0 && ret[idx - 1] == ' ') {
71 idx--;
72 }
73 return ret.substr(0, idx) + "(" + ret.substr(idx2) + ")";
74 }
75
76 #if defined(SUPPORTS_ABI_TEST)
77 // ForEachMismatch calls |func| for each register where |a| and |b| differ.
78 template <typename Func>
ForEachMismatch(const CallerState & a,const CallerState & b,const Func & func)79 static void ForEachMismatch(const CallerState &a, const CallerState &b,
80 const Func &func) {
81 #define CALLER_STATE_REGISTER(type, name) \
82 if (a.name != b.name) { \
83 func(#name); \
84 }
85 LOOP_CALLER_STATE_REGISTERS()
86 #undef CALLER_STATE_REGISTER
87 }
88 #endif // SUPPORTS_ABI_TEST
89
90 #if defined(SUPPORTS_UNWIND_TEST)
91 // We test unwind metadata by running the function under test with the trap flag
92 // set. This results in |SIGTRAP| and |EXCEPTION_SINGLE_STEP| on Linux and
93 // Windows, respectively. We hande these and verify libunwind or the Windows
94 // unwind APIs unwind successfully.
95
96 // IsAncestorStackFrame returns true if |a_sp| is an ancestor stack frame of
97 // |b_sp|.
IsAncestorStackFrame(crypto_word_t a_sp,crypto_word_t b_sp)98 static bool IsAncestorStackFrame(crypto_word_t a_sp, crypto_word_t b_sp) {
99 #if defined(OPENSSL_X86_64)
100 // The stack grows down, so ancestor stack frames have higher addresses.
101 return a_sp > b_sp;
102 #else
103 #error "unknown architecture"
104 #endif
105 }
106
107 // Implement some string formatting utilties. Ideally we would use |snprintf|,
108 // but this is called in a signal handler and |snprintf| is not async-signal-
109 // safe.
110
111 #if !defined(OPENSSL_WINDOWS)
WordToDecimal(crypto_word_t v)112 static std::array<char, DECIMAL_SIZE(crypto_word_t) + 1> WordToDecimal(
113 crypto_word_t v) {
114 std::array<char, DECIMAL_SIZE(crypto_word_t) + 1> ret;
115 size_t len = 0;
116 do {
117 ret[len++] = '0' + v % 10;
118 v /= 10;
119 } while (v != 0);
120 for (size_t i = 0; i < len / 2; i++) {
121 std::swap(ret[i], ret[len - 1 - i]);
122 }
123 ret[len] = '\0';
124 return ret;
125 }
126 #endif // !OPENSSL_WINDOWS
127
WordToHex(crypto_word_t v)128 static std::array<char, sizeof(crypto_word_t) * 2 + 1> WordToHex(
129 crypto_word_t v) {
130 static const char kHex[] = "0123456789abcdef";
131 std::array<char, sizeof(crypto_word_t) * 2 + 1> ret;
132 for (size_t i = sizeof(crypto_word_t) - 1; i < sizeof(crypto_word_t); i--) {
133 uint8_t b = v & 0xff;
134 v >>= 8;
135 ret[i * 2] = kHex[b >> 4];
136 ret[i * 2 + 1] = kHex[b & 0xf];
137 }
138 ret[sizeof(crypto_word_t) * 2] = '\0';
139 return ret;
140 }
141
StrCatSignalSafeImpl(bssl::Span<char> out)142 static void StrCatSignalSafeImpl(bssl::Span<char> out) {}
143
144 template <typename... Args>
StrCatSignalSafeImpl(bssl::Span<char> out,const char * str,Args...args)145 static void StrCatSignalSafeImpl(bssl::Span<char> out, const char *str,
146 Args... args) {
147 OPENSSL_strlcat(out.data(), str, out.size());
148 StrCatSignalSafeImpl(out, args...);
149 }
150
151 template <typename... Args>
StrCatSignalSafe(bssl::Span<char> out,Args...args)152 static void StrCatSignalSafe(bssl::Span<char> out, Args... args) {
153 if (out.empty()) {
154 return;
155 }
156 out[0] = '\0';
157 StrCatSignalSafeImpl(out, args...);
158 }
159
160 template <typename... Args>
FatalError(Args...args)161 [[noreturn]] static void FatalError(Args... args) {
162 // We cannot use |snprintf| here because it is not async-signal-safe.
163 char buf[512];
164 StrCatSignalSafe(buf, args..., "\n");
165 #if defined(OPENSSL_WINDOWS)
166 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
167 if (stderr_handle != INVALID_HANDLE_VALUE) {
168 DWORD unused;
169 WriteFile(stderr_handle, buf, strlen(buf), &unused, nullptr);
170 }
171 #else
172 ssize_t ret = write(STDERR_FILENO, buf, strlen(buf));
173 // We'll abort soon anyway, so if we fail to write the message, there's
174 // nothing to do.
175 (void)ret;
176 #endif
177 abort();
178 }
179
180 class UnwindStatus {
181 public:
UnwindStatus()182 UnwindStatus() : err_(nullptr) {}
UnwindStatus(const char * err)183 explicit UnwindStatus(const char *err) : err_(err) {}
184
ok() const185 bool ok() const { return err_ == nullptr; }
Error() const186 const char *Error() const { return err_; }
187
188 private:
189 const char *err_;
190 };
191
192 template<typename T>
193 class UnwindStatusOr {
194 public:
UnwindStatusOr(UnwindStatus status)195 UnwindStatusOr(UnwindStatus status) : status_(status) {
196 assert(!status_.ok());
197 }
198
UnwindStatusOr(const T & value)199 UnwindStatusOr(const T &value) : status_(UnwindStatus()), value_(value) {}
200
ok() const201 bool ok() const { return status_.ok(); }
Error() const202 const char *Error() const { return status_.Error(); }
203
ValueOrDie(const char * msg="Unexpected error") const204 const T &ValueOrDie(const char *msg = "Unexpected error") const {
205 if (!ok()) {
206 FatalError(msg, ": ", Error());
207 }
208 return value_;
209 }
210
211 private:
212 UnwindStatus status_;
213 T value_;
214 };
215
216 // UnwindCursor abstracts between libunwind and Windows unwind APIs. It is
217 // async-signal-safe.
218 #if defined(OPENSSL_WINDOWS)
219 class UnwindCursor {
220 public:
UnwindCursor(const CONTEXT & ctx)221 explicit UnwindCursor(const CONTEXT &ctx) : ctx_(ctx) {
222 starting_ip_ = ctx_.Rip;
223 }
224
starting_ip() const225 crypto_word_t starting_ip() const { return starting_ip_; }
226
227 // Step unwinds the cursor by one frame. On success, it returns whether there
228 // were more frames to unwind.
Step()229 UnwindStatusOr<bool> Step() {
230 bool is_top = is_top_;
231 is_top_ = false;
232
233 DWORD64 image_base;
234 RUNTIME_FUNCTION *entry =
235 RtlLookupFunctionEntry(ctx_.Rip, &image_base, nullptr);
236 if (entry == nullptr) {
237 // This is a leaf function. Leaf functions do not touch stack or
238 // callee-saved registers, so they may be unwound by simulating a ret.
239 if (!is_top) {
240 return UnwindStatus("leaf function found below the top frame");
241 }
242 memcpy(&ctx_.Rip, reinterpret_cast<const void *>(ctx_.Rsp),
243 sizeof(ctx_.Rip));
244 ctx_.Rsp += 8;
245 return true;
246 }
247
248 // This is a frame function. Call into the Windows unwinder.
249 void *handler_data;
250 DWORD64 establisher_frame;
251 RtlVirtualUnwind(UNW_FLAG_NHANDLER, image_base, ctx_.Rip, entry, &ctx_,
252 &handler_data, &establisher_frame, nullptr);
253 return ctx_.Rip != 0;
254 }
255
256 // GetIP returns the instruction pointer at the current frame.
GetIP()257 UnwindStatusOr<crypto_word_t> GetIP() { return ctx_.Rip; }
258
259 // GetSP returns the stack pointer at the current frame.
GetSP()260 UnwindStatusOr<crypto_word_t> GetSP() { return ctx_.Rsp; }
261
262 // GetCallerState returns the callee-saved registers at the current frame.
GetCallerState()263 UnwindStatusOr<CallerState> GetCallerState() {
264 CallerState state;
265 state.rbx = ctx_.Rbx;
266 state.rbp = ctx_.Rbp;
267 state.rdi = ctx_.Rdi;
268 state.rsi = ctx_.Rsi;
269 state.r12 = ctx_.R12;
270 state.r13 = ctx_.R13;
271 state.r14 = ctx_.R14;
272 state.r15 = ctx_.R15;
273 memcpy(&state.xmm6, &ctx_.Xmm6, sizeof(Reg128));
274 memcpy(&state.xmm7, &ctx_.Xmm7, sizeof(Reg128));
275 memcpy(&state.xmm8, &ctx_.Xmm8, sizeof(Reg128));
276 memcpy(&state.xmm9, &ctx_.Xmm9, sizeof(Reg128));
277 memcpy(&state.xmm10, &ctx_.Xmm10, sizeof(Reg128));
278 memcpy(&state.xmm11, &ctx_.Xmm11, sizeof(Reg128));
279 memcpy(&state.xmm12, &ctx_.Xmm12, sizeof(Reg128));
280 memcpy(&state.xmm13, &ctx_.Xmm13, sizeof(Reg128));
281 memcpy(&state.xmm14, &ctx_.Xmm14, sizeof(Reg128));
282 memcpy(&state.xmm15, &ctx_.Xmm15, sizeof(Reg128));
283 return state;
284 }
285
286 // ToString returns a human-readable representation of the address the cursor
287 // started at.
ToString()288 const char *ToString() {
289 StrCatSignalSafe(starting_ip_buf_, "0x", WordToHex(starting_ip_).data());
290 return starting_ip_buf_;
291 }
292
293 private:
294 CONTEXT ctx_;
295 crypto_word_t starting_ip_;
296 char starting_ip_buf_[64];
297 bool is_top_ = true;
298 };
299 #else // !OPENSSL_WINDOWS
300 class UnwindCursor {
301 public:
UnwindCursor(unw_context_t * ctx)302 explicit UnwindCursor(unw_context_t *ctx) : ctx_(ctx) {
303 int ret = unw_init_local2(&cursor_, ctx_, UNW_INIT_SIGNAL_FRAME);
304 if (ret < 0) {
305 FatalError("Error getting unwind context: ", unw_strerror(ret));
306 }
307 starting_ip_ = GetIP().ValueOrDie("Error getting instruction pointer");
308 }
309
310 // Step unwinds the cursor by one frame. On success, it returns whether there
311 // were more frames to unwind.
Step()312 UnwindStatusOr<bool> Step() {
313 int ret = unw_step(&cursor_);
314 if (ret < 0) {
315 return UNWError(ret);
316 }
317 return ret != 0;
318 }
319
320 // GetIP returns the instruction pointer at the current frame.
GetIP()321 UnwindStatusOr<crypto_word_t> GetIP() {
322 crypto_word_t ip;
323 int ret = GetReg(&ip, UNW_REG_IP);
324 if (ret < 0) {
325 return UNWError(ret);
326 }
327 return ip;
328 }
329
330 // GetSP returns the stack pointer at the current frame.
GetSP()331 UnwindStatusOr<crypto_word_t> GetSP() {
332 crypto_word_t sp;
333 int ret = GetReg(&sp, UNW_REG_SP);
334 if (ret < 0) {
335 return UNWError(ret);
336 }
337 return sp;
338 }
339
340 // GetCallerState returns the callee-saved registers at the current frame.
GetCallerState()341 UnwindStatusOr<CallerState> GetCallerState() {
342 CallerState state;
343 int ret = 0;
344 #if defined(OPENSSL_X86_64)
345 ret = ret < 0 ? ret : GetReg(&state.rbx, UNW_X86_64_RBX);
346 ret = ret < 0 ? ret : GetReg(&state.rbp, UNW_X86_64_RBP);
347 ret = ret < 0 ? ret : GetReg(&state.r12, UNW_X86_64_R12);
348 ret = ret < 0 ? ret : GetReg(&state.r13, UNW_X86_64_R13);
349 ret = ret < 0 ? ret : GetReg(&state.r14, UNW_X86_64_R14);
350 ret = ret < 0 ? ret : GetReg(&state.r15, UNW_X86_64_R15);
351 #else
352 #error "unknown architecture"
353 #endif
354 if (ret < 0) {
355 return UNWError(ret);
356 }
357 return state;
358 }
359
360 // ToString returns a human-readable representation of the address the cursor
361 // started at, using debug information if available.
ToString()362 const char *ToString() {
363 // Use a new cursor. |cursor_| has already been unwound, and
364 // |unw_get_proc_name| is slow so we do not sample it unconditionally in the
365 // constructor.
366 unw_cursor_t cursor;
367 unw_word_t off;
368 if (unw_init_local2(&cursor, ctx_, UNW_INIT_SIGNAL_FRAME) != 0 ||
369 unw_get_proc_name(&cursor, starting_ip_buf_, sizeof(starting_ip_buf_),
370 &off) != 0) {
371 StrCatSignalSafe(starting_ip_buf_, "0x", WordToHex(starting_ip_).data());
372 return starting_ip_buf_;
373 }
374 size_t len = strlen(starting_ip_buf_);
375 // Print the offset in decimal, to match gdb's disassembly output and ease
376 // debugging.
377 StrCatSignalSafe(bssl::Span<char>(starting_ip_buf_).subspan(len), "+",
378 WordToDecimal(off).data(), " (0x",
379 WordToHex(starting_ip_).data(), ")");
380 return starting_ip_buf_;
381 }
382
383 private:
UNWError(int ret)384 static UnwindStatus UNWError(int ret) {
385 assert(ret < 0);
386 const char *msg = unw_strerror(ret);
387 return UnwindStatus(msg == nullptr ? "unknown error" : msg);
388 }
389
GetReg(crypto_word_t * out,unw_regnum_t reg)390 int GetReg(crypto_word_t *out, unw_regnum_t reg) {
391 unw_word_t val;
392 int ret = unw_get_reg(&cursor_, reg, &val);
393 if (ret >= 0) {
394 static_assert(sizeof(crypto_word_t) == sizeof(unw_word_t),
395 "crypto_word_t and unw_word_t are inconsistent");
396 *out = val;
397 }
398 return ret;
399 }
400
401 unw_context_t *ctx_;
402 unw_cursor_t cursor_;
403 crypto_word_t starting_ip_;
404 char starting_ip_buf_[64];
405 };
406 #endif // OPENSSL_WINDOWS
407
408 // g_in_trampoline is true if we are in an instrumented |abi_test_trampoline|
409 // call, in the region that triggers |SIGTRAP|.
410 static bool g_in_trampoline = false;
411 // g_unwind_function_done, if |g_in_trampoline| is true, is whether the function
412 // under test has returned. It is undefined otherwise.
413 static bool g_unwind_function_done;
414 // g_trampoline_state, during an unwind-enabled ABI test, is the state the
415 // function under test must preserve. It is undefined otherwise.
416 static CallerState g_trampoline_state;
417 // g_trampoline_sp, if |g_in_trampoline| is true, is the stack pointer of the
418 // trampoline frame. It is undefined otherwise.
419 static crypto_word_t g_trampoline_sp;
420
421 // kMaxUnwindErrors is the maximum number of unwind errors reported per
422 // function. If a function's unwind tables are wrong, we are otherwise likely to
423 // repeat the same error at multiple addresses.
424 static constexpr size_t kMaxUnwindErrors = 10;
425
426 // Errors are saved in a signal handler. We use a static buffer to avoid
427 // allocation.
428 static size_t g_num_unwind_errors = 0;
429
430 struct UnwindError {
431 #if defined(OPENSSL_WINDOWS)
432 crypto_word_t ip;
433 #endif
434 char str[512];
435 };
436
437 static UnwindError g_unwind_errors[kMaxUnwindErrors];
438
439 template <typename... Args>
AddUnwindError(UnwindCursor * cursor,Args...args)440 static void AddUnwindError(UnwindCursor *cursor, Args... args) {
441 if (g_num_unwind_errors >= kMaxUnwindErrors) {
442 return;
443 }
444 #if defined(OPENSSL_WINDOWS)
445 // Windows symbol functions should not be called when handling an
446 // exception. Stash the instruction pointer, to be symbolized later.
447 g_unwind_errors[g_num_unwind_errors].ip = cursor->starting_ip();
448 StrCatSignalSafe(g_unwind_errors[g_num_unwind_errors].str, args...);
449 #else
450 StrCatSignalSafe(g_unwind_errors[g_num_unwind_errors].str,
451 "unwinding at ", cursor->ToString(), ": ", args...);
452 #endif
453 g_num_unwind_errors++;
454 }
455
CheckUnwind(UnwindCursor * cursor)456 static void CheckUnwind(UnwindCursor *cursor) {
457 const crypto_word_t kStartAddress =
458 reinterpret_cast<crypto_word_t>(&abi_test_unwind_start);
459 const crypto_word_t kReturnAddress =
460 reinterpret_cast<crypto_word_t>(&abi_test_unwind_return);
461 const crypto_word_t kStopAddress =
462 reinterpret_cast<crypto_word_t>(&abi_test_unwind_stop);
463
464 crypto_word_t sp = cursor->GetSP().ValueOrDie("Error getting stack pointer");
465 crypto_word_t ip =
466 cursor->GetIP().ValueOrDie("Error getting instruction pointer");
467 if (!g_in_trampoline) {
468 if (ip != kStartAddress) {
469 FatalError("Unexpected SIGTRAP at ", cursor->ToString());
470 }
471
472 // Save the current state and begin.
473 g_in_trampoline = true;
474 g_unwind_function_done = false;
475 g_trampoline_sp = sp;
476 } else {
477 if (sp == g_trampoline_sp || g_unwind_function_done) {
478 // |g_unwind_function_done| should imply |sp| is |g_trampoline_sp|, but
479 // clearing the trap flag in x86 briefly displaces the stack pointer.
480 //
481 // Also note we check both |ip| and |sp| below, in case the function under
482 // test is also |abi_test_trampoline|.
483 if (ip == kReturnAddress && sp == g_trampoline_sp) {
484 g_unwind_function_done = true;
485 }
486 if (ip == kStopAddress && sp == g_trampoline_sp) {
487 // |SIGTRAP| is fatal again.
488 g_in_trampoline = false;
489 }
490 } else if (IsAncestorStackFrame(sp, g_trampoline_sp)) {
491 // This should never happen. We went past |g_trampoline_sp| without
492 // stopping at |kStopAddress|.
493 AddUnwindError(cursor, "stack frame is before caller");
494 g_in_trampoline = false;
495 } else if (g_num_unwind_errors < kMaxUnwindErrors) {
496 for (;;) {
497 UnwindStatusOr<bool> step_ret = cursor->Step();
498 if (!step_ret.ok()) {
499 AddUnwindError(cursor, "error unwinding: ", step_ret.Error());
500 break;
501 }
502 // |Step| returns whether there was a frame to unwind.
503 if (!step_ret.ValueOrDie()) {
504 AddUnwindError(cursor, "could not unwind to starting frame");
505 break;
506 }
507
508 UnwindStatusOr<crypto_word_t> cur_sp = cursor->GetSP();
509 if (!cur_sp.ok()) {
510 AddUnwindError(cursor,
511 "error recovering stack pointer: ", cur_sp.Error());
512 break;
513 }
514 if (IsAncestorStackFrame(cur_sp.ValueOrDie(), g_trampoline_sp)) {
515 AddUnwindError(cursor, "unwound past starting frame");
516 break;
517 }
518 if (cur_sp.ValueOrDie() == g_trampoline_sp) {
519 // We found the parent frame. Check the return address.
520 UnwindStatusOr<crypto_word_t> cur_ip = cursor->GetIP();
521 if (!cur_ip.ok()) {
522 AddUnwindError(cursor,
523 "error recovering return address: ", cur_ip.Error());
524 } else if (cur_ip.ValueOrDie() != kReturnAddress) {
525 AddUnwindError(cursor, "wrong return address");
526 }
527
528 // Check the remaining registers.
529 UnwindStatusOr<CallerState> state = cursor->GetCallerState();
530 if (!state.ok()) {
531 AddUnwindError(cursor,
532 "error recovering registers: ", state.Error());
533 } else {
534 ForEachMismatch(state.ValueOrDie(), g_trampoline_state,
535 [&](const char *reg) {
536 AddUnwindError(cursor, reg, " was not recovered");
537 });
538 }
539 break;
540 }
541 }
542 }
543 }
544 }
545
546 // ReadUnwindResult adds the results of the most recent unwind test to |out|.
ReadUnwindResult(Result * out)547 static void ReadUnwindResult(Result *out) {
548 for (size_t i = 0; i < g_num_unwind_errors; i++) {
549 #if defined(OPENSSL_WINDOWS)
550 const crypto_word_t ip = g_unwind_errors[i].ip;
551 char buf[256];
552 DWORD64 displacement;
553 struct {
554 SYMBOL_INFO info;
555 char name_buf[128];
556 } symbol;
557 memset(&symbol, 0, sizeof(symbol));
558 symbol.info.SizeOfStruct = sizeof(symbol.info);
559 symbol.info.MaxNameLen = sizeof(symbol.name_buf);
560 if (SymFromAddr(GetCurrentProcess(), ip, &displacement, &symbol.info)) {
561 snprintf(buf, sizeof(buf), "unwinding at %s+%llu (0x%s): %s",
562 symbol.info.Name, displacement, WordToHex(ip).data(),
563 g_unwind_errors[i].str);
564 } else {
565 snprintf(buf, sizeof(buf), "unwinding at 0x%s: %s",
566 WordToHex(ip).data(), g_unwind_errors[i].str);
567 }
568 out->errors.emplace_back(buf);
569 #else
570 out->errors.emplace_back(g_unwind_errors[i].str);
571 #endif
572 }
573 if (g_num_unwind_errors == kMaxUnwindErrors) {
574 out->errors.emplace_back("(additional errors omitted)");
575 }
576 g_num_unwind_errors = 0;
577 }
578
579 #if defined(OPENSSL_WINDOWS)
580 static DWORD g_main_thread;
581
ExceptionHandler(EXCEPTION_POINTERS * info)582 static long ExceptionHandler(EXCEPTION_POINTERS *info) {
583 if (info->ExceptionRecord->ExceptionCode != EXCEPTION_SINGLE_STEP ||
584 GetCurrentThreadId() != g_main_thread) {
585 return EXCEPTION_CONTINUE_SEARCH;
586 }
587
588 UnwindCursor cursor(*info->ContextRecord);
589 CheckUnwind(&cursor);
590 if (g_in_trampoline) {
591 // Windows clears the trap flag, so we must restore it.
592 info->ContextRecord->EFlags |= 0x100;
593 }
594 return EXCEPTION_CONTINUE_EXECUTION;
595 }
596
EnableUnwindTestsImpl()597 static void EnableUnwindTestsImpl() {
598 if (IsDebuggerPresent()) {
599 // Unwind tests drive logic via |EXCEPTION_SINGLE_STEP|, which conflicts with
600 // debuggers.
601 fprintf(stderr, "Debugger detected. Disabling unwind tests.\n");
602 return;
603 }
604
605 g_main_thread = GetCurrentThreadId();
606
607 SymSetOptions(SYMOPT_DEFERRED_LOADS);
608 if (!SymInitialize(GetCurrentProcess(), nullptr, TRUE)) {
609 fprintf(stderr, "Could not initialize symbols.\n");
610 }
611
612 if (AddVectoredExceptionHandler(0, ExceptionHandler) == nullptr) {
613 fprintf(stderr, "Error installing exception handler.\n");
614 abort();
615 }
616
617 g_unwind_tests_enabled = true;
618 }
619 #else // !OPENSSL_WINDOWS
620 // HandleEINTR runs |func| and returns the result, retrying the operation on
621 // |EINTR|.
622 template <typename Func>
HandleEINTR(const Func & func)623 static auto HandleEINTR(const Func &func) -> decltype(func()) {
624 decltype(func()) ret;
625 do {
626 ret = func();
627 } while (ret < 0 && errno == EINTR);
628 return ret;
629 }
630
ReadFileToString(std::string * out,const char * path)631 static bool ReadFileToString(std::string *out, const char *path) {
632 out->clear();
633
634 int fd = HandleEINTR([&] { return open(path, O_RDONLY); });
635 if (fd < 0) {
636 return false;
637 }
638
639 for (;;) {
640 char buf[1024];
641 ssize_t ret = HandleEINTR([&] { return read(fd, buf, sizeof(buf)); });
642 if (ret < 0) {
643 close(fd);
644 return false;
645 }
646 if (ret == 0) {
647 close(fd);
648 return true;
649 }
650 out->append(buf, static_cast<size_t>(ret));
651 }
652 }
653
IsBeingDebugged()654 static bool IsBeingDebugged() {
655 std::string status;
656 if (!ReadFileToString(&status, "/proc/self/status")) {
657 perror("error reading /proc/self/status");
658 return false;
659 }
660 std::string key = "\nTracerPid:\t";
661 size_t idx = status.find(key);
662 if (idx == std::string::npos) {
663 return false;
664 }
665 idx += key.size();
666 return idx < status.size() && status[idx] != '0';
667 }
668
669 static pthread_t g_main_thread;
670
TrapHandler(int sig,siginfo_t * info,void * ucontext_v)671 static void TrapHandler(int sig, siginfo_t *info, void *ucontext_v) {
672 // Note this is a signal handler, so only async-signal-safe functions may be
673 // used here. See signal-safety(7). libunwind promises local unwind is
674 // async-signal-safe.
675 ucontext_t *ucontext = static_cast<ucontext_t*>(ucontext_v);
676
677 // |pthread_equal| is not listed as async-signal-safe, but this is clearly an
678 // oversight.
679 if (!pthread_equal(g_main_thread, pthread_self())) {
680 FatalError("SIGTRAP on background thread");
681 }
682
683 UnwindCursor cursor(ucontext);
684 CheckUnwind(&cursor);
685 }
686
EnableUnwindTestsImpl()687 static void EnableUnwindTestsImpl() {
688 if (IsBeingDebugged()) {
689 // Unwind tests drive logic via |SIGTRAP|, which conflicts with debuggers.
690 fprintf(stderr, "Debugger detected. Disabling unwind tests.\n");
691 return;
692 }
693
694 g_main_thread = pthread_self();
695
696 struct sigaction trap_action;
697 OPENSSL_memset(&trap_action, 0, sizeof(trap_action));
698 sigemptyset(&trap_action.sa_mask);
699 trap_action.sa_flags = SA_SIGINFO;
700 trap_action.sa_sigaction = TrapHandler;
701 if (sigaction(SIGTRAP, &trap_action, NULL) != 0) {
702 perror("sigaction");
703 abort();
704 }
705
706 g_unwind_tests_enabled = true;
707 }
708 #endif // OPENSSL_WINDOWS
709
710 #else // !SUPPORTS_UNWIND_TEST
711
712 #if defined(SUPPORTS_ABI_TEST)
ReadUnwindResult(Result *)713 static void ReadUnwindResult(Result *) {}
714 #endif
EnableUnwindTestsImpl()715 static void EnableUnwindTestsImpl() {}
716
717 #endif // SUPPORTS_UNWIND_TEST
718
719 #if defined(SUPPORTS_ABI_TEST)
RunTrampoline(Result * out,crypto_word_t func,const crypto_word_t * argv,size_t argc,bool unwind)720 crypto_word_t RunTrampoline(Result *out, crypto_word_t func,
721 const crypto_word_t *argv, size_t argc,
722 bool unwind) {
723 CallerState state;
724 RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state));
725
726 unwind &= g_unwind_tests_enabled;
727 #if defined(SUPPORTS_UNWIND_TEST)
728 if (unwind) {
729 // Save the caller state for the unwind tester to check for.
730 g_trampoline_state = state;
731 }
732 #endif
733 CallerState state2 = state;
734 crypto_word_t ret = abi_test_trampoline(func, &state2, argv, argc, unwind);
735 #if defined(OPENSSL_X86_64) || defined(OPENSSL_X86)
736 // Query and clear the direction flag early, so negative tests do not
737 // interfere with |malloc|.
738 bool direction_flag = abi_test_get_and_clear_direction_flag();
739 #endif // OPENSSL_X86_64 || OPENSSL_X86
740
741 *out = Result();
742 ForEachMismatch(state, state2, [&](const char *reg) {
743 out->errors.push_back(std::string(reg) + " was not restored after return");
744 });
745 #if defined(OPENSSL_X86_64) || defined(OPENSSL_X86)
746 // Linux and Windows ABIs for x86 require the direction flag be cleared on
747 // return. (Some OpenSSL assembly preserves it, which is stronger, but we only
748 // require what is specified by the ABI so |CHECK_ABI| works with C compiler
749 // output.)
750 if (direction_flag) {
751 out->errors.emplace_back("Direction flag set after return");
752 }
753 #endif // OPENSSL_X86_64 || OPENSSL_X86
754 if (unwind) {
755 ReadUnwindResult(out);
756 }
757 return ret;
758 }
759 #endif // SUPPORTS_ABI_TEST
760
761 } // namespace internal
762
EnableUnwindTests()763 void EnableUnwindTests() { internal::EnableUnwindTestsImpl(); }
764
UnwindTestsEnabled()765 bool UnwindTestsEnabled() { return internal::g_unwind_tests_enabled; }
766
767 } // namespace abi_test
768