tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SandboxCrash.cpp (4179B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 // This file needs to be linked into libxul, so it can access the JS
      8 // stack and the crash reporter.  Everything else in this directory
      9 // should be able to be linked into its own shared library, in order
     10 // to be able to isolate sandbox/chromium from ipc/chromium.
     11 
     12 #include "SandboxInternal.h"
     13 
     14 #include "SandboxLogging.h"
     15 
     16 #include <unistd.h>
     17 #include <sys/syscall.h>
     18 
     19 #include "mozilla/StackWalk.h"
     20 #include "mozilla/dom/Exceptions.h"
     21 #include "nsContentUtils.h"
     22 #include "nsExceptionHandler.h"
     23 #include "nsIException.h"  // for nsIStackFrame
     24 #include "nsString.h"
     25 #include "nsThreadUtils.h"
     26 
     27 namespace mozilla {
     28 
     29 // Log JS stack info in the same place as the sandbox violation
     30 // message.  Useful in case the responsible code is JS and all we have
     31 // are logs and a minidump with the C++ stacks (e.g., on TBPL).
     32 static void SandboxLogJSStack(void) {
     33  if (!NS_IsMainThread()) {
     34    // This might be a worker thread... or it might be a non-JS
     35    // thread, or a non-NSPR thread.  There's isn't a good API for
     36    // dealing with this, yet.
     37    return;
     38  }
     39  if (!nsContentUtils::XPConnect()) {
     40    // There is no content (e.g., the process is a media plugin), in
     41    // which case this will probably crash and definitely not work.
     42    return;
     43  }
     44  nsCOMPtr<nsIStackFrame> frame = dom::GetCurrentJSStack();
     45  // If we got a stack, we must have a current JSContext.  This is icky.  :(
     46  // Would be better if GetCurrentJSStack() handed out the JSContext it ended up
     47  // using or something.
     48  JSContext* cx = frame ? nsContentUtils::GetCurrentJSContext() : nullptr;
     49  for (int i = 0; frame != nullptr; ++i) {
     50    nsAutoCString fileName;
     51    nsAutoString funName;
     52    int32_t lineNumber;
     53 
     54    // Don't stop unwinding if an attribute can't be read.
     55    fileName.SetIsVoid(true);
     56    frame->GetFilename(cx, fileName);
     57    lineNumber = frame->GetLineNumber(cx);
     58    funName.SetIsVoid(true);
     59    frame->GetName(cx, funName);
     60 
     61    if (!funName.IsVoid() || !fileName.IsVoid()) {
     62      SANDBOX_LOG("JS frame %d: %s %s line %d", i,
     63                  funName.IsVoid() ? "(anonymous)"
     64                                   : NS_ConvertUTF16toUTF8(funName).get(),
     65                  fileName.IsVoid() ? "(no file)" : fileName.get(), lineNumber);
     66    }
     67 
     68    frame = frame->GetCaller(cx);
     69  }
     70 }
     71 
     72 static void SandboxPrintStackFrame(uint32_t aFrameNumber, void* aPC, void* aSP,
     73                                   void* aClosure) {
     74  char buf[1024];
     75  MozCodeAddressDetails details;
     76 
     77  MozDescribeCodeAddress(aPC, &details);
     78  MozFormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
     79  SANDBOX_LOG("frame %s", buf);
     80 }
     81 
     82 static void SandboxLogCStack(const void* aFirstFramePC) {
     83  // Warning: this might not print any stack frames.  MozStackWalk
     84  // can't walk past the signal trampoline on ARM (bug 968531), and
     85  // x86 frame pointer walking may or may not work (bug 1082276).
     86 
     87  MozStackWalk(SandboxPrintStackFrame, aFirstFramePC, /* max */ 0, nullptr);
     88  SANDBOX_LOG("end of stack.");
     89 }
     90 
     91 static void SandboxCrash(int nr, siginfo_t* info, void* void_context,
     92                         const void* aFirstFramePC) {
     93  pid_t pid = getpid(), tid = syscall(__NR_gettid);
     94  bool dumped = CrashReporter::WriteMinidumpForSigInfo(nr, info, void_context);
     95 
     96  if (!dumped) {
     97    SANDBOX_LOG(
     98        "crash reporter is disabled (or failed);"
     99        " trying stack trace:");
    100    SandboxLogCStack(aFirstFramePC);
    101  }
    102 
    103  // Do this last, in case it crashes or deadlocks.
    104  SandboxLogJSStack();
    105 
    106  // Try to reraise, so the parent sees that this process crashed.
    107  // (If tgkill is forbidden, then seccomp will raise SIGSYS, which
    108  // also accomplishes that goal.)
    109  signal(SIGSYS, SIG_DFL);
    110  syscall(__NR_tgkill, pid, tid, nr);
    111 }
    112 
    113 static void __attribute__((constructor)) SandboxSetCrashFunc() {
    114  gSandboxCrashFunc = SandboxCrash;
    115 }
    116 
    117 }  // namespace mozilla