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