Index: content/common/sandbox_linux/sandbox_debug_handling_linux.cc |
diff --git a/content/common/sandbox_linux/sandbox_debug_handling_linux.cc b/content/common/sandbox_linux/sandbox_debug_handling_linux.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0bf8799f0489cf222b690d0723c8e6f64878f3d7 |
--- /dev/null |
+++ b/content/common/sandbox_linux/sandbox_debug_handling_linux.cc |
@@ -0,0 +1,79 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/common/sandbox_linux/sandbox_debug_handling_linux.h" |
+ |
+#include <errno.h> |
+#include <signal.h> |
+#include <sys/prctl.h> |
+#include <unistd.h> |
+ |
+#include "base/command_line.h" |
+#include "base/logging.h" |
+#include "base/macros.h" |
+#include "base/strings/safe_sprintf.h" |
+#include "content/public/common/content_switches.h" |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+void DoChrootSignalHandler(int) { |
+ const int old_errno = errno; |
+ const char kFirstMessage[] = "Chroot signal handler called.\n"; |
+ ignore_result(write(STDERR_FILENO, kFirstMessage, sizeof(kFirstMessage) - 1)); |
+ |
+ const int chroot_ret = chroot("/"); |
+ |
+ char kSecondMessage[100]; |
+ const ssize_t printed = base::strings::SafeSPrintf( |
+ kSecondMessage, "chroot() returned %d. Errno is %d.\n", chroot_ret, |
+ errno); |
+ if (printed > 0 && printed < static_cast<ssize_t>(sizeof(kSecondMessage))) { |
+ ignore_result(write(STDERR_FILENO, kSecondMessage, printed)); |
+ } |
+ errno = old_errno; |
+} |
+ |
+// This is a quick hack to allow testing sandbox crash reports in production |
+// binaries. |
+// This installs a signal handler for SIGUSR2 that performs a chroot(). |
+// In most of our BPF policies, it is a "watched" system call which will |
+// trigger a SIGSYS signal whose handler will crash. |
+// This has been added during the investigation of https://crbug.com/415842. |
+void InstallCrashTestHandler() { |
+ struct sigaction act = {}; |
+ act.sa_handler = DoChrootSignalHandler; |
+ CHECK_EQ(0, sigemptyset(&act.sa_mask)); |
+ act.sa_flags = 0; |
+ |
+ PCHECK(0 == sigaction(SIGUSR2, &act, NULL)); |
+} |
+ |
+bool IsSandboxDebuggingEnabled() { |
+ const base::CommandLine& command_line = |
+ *base::CommandLine::ForCurrentProcess(); |
+ return command_line.HasSwitch(switches::kAllowSandboxDebugging); |
+} |
+ |
+} // namespace |
+ |
+// static |
+bool SandboxDebugHandling::SetDumpableStatusAndHandlers() { |
+ if (IsSandboxDebuggingEnabled()) { |
+ // If sandbox debugging is allowed, install a handler for sandbox-related |
+ // crash testing. |
+ InstallCrashTestHandler(); |
+ return true; |
+ } |
+ |
+ if (prctl(PR_SET_DUMPABLE, 0) != 0) { |
+ PLOG(ERROR) << "Failed to set non-dumpable flag"; |
+ return false; |
+ } |
+ |
+ return prctl(PR_GET_DUMPABLE) == 0; |
+} |
+ |
+} // namespace content |