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