LCOV - code coverage report
Current view: top level - source/common/signal - signal_action.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 0 85 0.0 %
Date: 2024-01-05 06:35:25 Functions: 0 7 0.0 %

          Line data    Source code
       1             : #include "source/common/signal/signal_action.h"
       2             : 
       3             : #include <sys/mman.h>
       4             : 
       5             : #include <csignal>
       6             : 
       7             : #include "source/common/common/assert.h"
       8             : #include "source/common/signal/fatal_action.h"
       9             : #include "source/common/version/version.h"
      10             : 
      11             : namespace Envoy {
      12             : 
      13             : constexpr int SignalAction::FATAL_SIGS[];
      14             : 
      15           0 : void SignalAction::sigHandler(int sig, siginfo_t* info, void* context) {
      16           0 :   BackwardsTrace tracer;
      17             : 
      18           0 :   tracer.logFault(strsignal(sig), info->si_addr);
      19           0 :   if (context != nullptr) {
      20           0 :     tracer.captureFrom(context);
      21           0 :   } else {
      22           0 :     tracer.capture();
      23           0 :   }
      24           0 :   tracer.logTrace();
      25             : 
      26             :   // Finally after logging the stack trace, call the crash handlers
      27             :   // in order from safe to unsafe.
      28           0 :   auto status = FatalErrorHandler::runSafeActions();
      29             : 
      30           0 :   switch (status) {
      31           0 :   case FatalAction::Status::Success:
      32           0 :     FatalErrorHandler::callFatalErrorHandlers(std::cerr);
      33           0 :     FatalErrorHandler::runUnsafeActions();
      34           0 :     break;
      35           0 :   case FatalAction::Status::ActionManagerUnset:
      36           0 :     FatalErrorHandler::callFatalErrorHandlers(std::cerr);
      37           0 :     break;
      38           0 :   case FatalAction::Status::RunningOnAnotherThread: {
      39             :     // We should wait for some duration for the other thread to finish
      40             :     // running. We should add support for this scenario, even though the
      41             :     // probability of it occurring is low.
      42             :     // TODO(kbaichoo): Implement a configurable call to sleep
      43           0 :     PANIC("not implemented");
      44           0 :     break;
      45           0 :   }
      46           0 :   case FatalAction::Status::AlreadyRanOnThisThread:
      47             :     // We caused another fatal signal to be raised.
      48           0 :     std::cerr << "Our FatalActions triggered a fatal signal.\n";
      49           0 :     break;
      50           0 :   }
      51             : 
      52           0 :   signal(sig, SIG_DFL);
      53           0 :   raise(sig);
      54           0 : }
      55             : 
      56           0 : void SignalAction::installSigHandlers() {
      57             :   // sigaltstack and backtrace() are incompatible on Apple platforms
      58             :   // https://reviews.llvm.org/D28265
      59           0 : #if !defined(__APPLE__)
      60           0 :   stack_t stack;
      61           0 :   stack.ss_sp = altstack_ + guard_size_; // Guard page at one end ...
      62           0 :   stack.ss_size = altstack_size_;        // ... guard page at the other
      63           0 :   stack.ss_flags = 0;
      64             : 
      65           0 :   RELEASE_ASSERT(sigaltstack(&stack, &previous_altstack_) == 0, "");
      66           0 : #endif
      67             : 
      68             :   // Make sure VersionInfo::version() is initialized so we don't allocate std::string in signal
      69             :   // handlers.
      70           0 :   RELEASE_ASSERT(!VersionInfo::version().empty(), "");
      71             : 
      72           0 :   int hidx = 0;
      73           0 :   for (const auto& sig : FATAL_SIGS) {
      74           0 :     struct sigaction saction;
      75           0 :     std::memset(&saction, 0, sizeof(saction));
      76           0 :     sigemptyset(&saction.sa_mask);
      77           0 :     saction.sa_flags = (SA_SIGINFO | SA_ONSTACK | SA_RESETHAND | SA_NODEFER);
      78           0 :     saction.sa_sigaction = sigHandler;
      79           0 :     auto* handler = &previous_handlers_[hidx++];
      80           0 :     RELEASE_ASSERT(sigaction(sig, &saction, handler) == 0, "");
      81           0 :   }
      82           0 : }
      83             : 
      84           0 : void SignalAction::removeSigHandlers() {
      85             : // sigaltstack and backtrace() are incompatible on Apple platforms
      86             : // https://reviews.llvm.org/D28265
      87           0 : #if !defined(__APPLE__)
      88           0 :   RELEASE_ASSERT(sigaltstack(&previous_altstack_, nullptr) == 0, "");
      89           0 : #endif
      90             : 
      91           0 :   int hidx = 0;
      92           0 :   for (const auto& sig : FATAL_SIGS) {
      93           0 :     auto* handler = &previous_handlers_[hidx++];
      94           0 :     RELEASE_ASSERT(sigaction(sig, handler, nullptr) == 0, "");
      95           0 :   }
      96           0 : }
      97             : 
      98             : #if defined(__APPLE__) && !defined(MAP_STACK)
      99             : #define MAP_STACK (0)
     100             : #endif
     101             : 
     102           0 : void SignalAction::mapAndProtectStackMemory() {
     103             :   // Per docs MAP_STACK doesn't actually do anything today but provides a
     104             :   // library hint that might be used in the future.
     105           0 :   altstack_ = static_cast<char*>(mmap(nullptr, mapSizeWithGuards(), PROT_READ | PROT_WRITE,
     106           0 :                                       MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0));
     107           0 :   RELEASE_ASSERT(altstack_, "");
     108           0 :   RELEASE_ASSERT(mprotect(altstack_, guard_size_, PROT_NONE) == 0, "");
     109           0 :   RELEASE_ASSERT(mprotect(altstack_ + guard_size_ + altstack_size_, guard_size_, PROT_NONE) == 0,
     110           0 :                  "");
     111           0 : }
     112             : 
     113           0 : void SignalAction::unmapStackMemory() { munmap(altstack_, mapSizeWithGuards()); }
     114             : 
     115           0 : void SignalAction::doGoodAccessForTest() {
     116           0 :   volatile char* altaltstack = altstack_;
     117           0 :   for (size_t i = 0; i < altstack_size_; ++i) {
     118           0 :     *(altaltstack + guard_size_ + i) = 42;
     119           0 :   }
     120           0 :   for (size_t i = 0; i < altstack_size_; ++i) {
     121           0 :     ASSERT(*(altaltstack + guard_size_ + i) == 42);
     122           0 :   }
     123           0 : }
     124             : 
     125           0 : void SignalAction::tryEvilAccessForTest(bool end) {
     126           0 :   volatile char* altaltstack = altstack_;
     127           0 :   if (end) {
     128             :     // One byte past the valid region
     129             :     // http://oeis.org/A001969
     130           0 :     *(altaltstack + guard_size_ + altstack_size_) = 43;
     131           0 :   } else {
     132             :     // One byte before the valid region
     133           0 :     *(altaltstack + guard_size_ - 1) = 43;
     134           0 :   }
     135           0 : }
     136             : } // namespace Envoy

Generated by: LCOV version 1.15