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