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