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