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