Index: content/zygote/zygote_main_linux.cc |
diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc |
index b4da14eee8e726ba13cea0c3789e9a44d28b03e3..b111cfc9e9dfba562ea7e228bf4821d55e711274 100644 |
--- a/content/zygote/zygote_main_linux.cc |
+++ b/content/zygote/zygote_main_linux.cc |
@@ -5,8 +5,10 @@ |
#include "content/zygote/zygote_main.h" |
#include <dlfcn.h> |
+#include <fcntl.h> |
#include <pthread.h> |
#include <string.h> |
+#include <sys/socket.h> |
#include <sys/types.h> |
#include <unistd.h> |
@@ -17,6 +19,7 @@ |
#include "base/memory/scoped_vector.h" |
#include "base/native_library.h" |
#include "base/pickle.h" |
+#include "base/posix/eintr_wrapper.h" |
#include "base/posix/unix_domain_socket_linux.h" |
#include "base/rand_util.h" |
#include "base/sys_info.h" |
@@ -47,6 +50,10 @@ |
#include "third_party/libjingle/overrides/init_webrtc.h" |
#endif |
+#if defined(ADDRESS_SANITIZER) |
+#include <sanitizer/asan_interface.h> |
+#endif |
+ |
namespace content { |
// See http://code.google.com/p/chromium/wiki/LinuxZygote |
@@ -398,6 +405,53 @@ static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox) { |
return true; |
} |
+#if defined(ADDRESS_SANITIZER) |
+const size_t kSanitizerMaxMessageLength = 1 * 1024 * 1024; |
+ |
+static void SanitizerCoverageHelper(int socket_fd, int file_fd) { |
+ scoped_ptr<char[]> buffer(new char[kSanitizerMaxMessageLength]); |
+ while (true) { |
+ ssize_t received_size = HANDLE_EINTR( |
+ recv(socket_fd, buffer.get(), kSanitizerMaxMessageLength, 0)); |
jln (very slow on Chromium)
2014/05/21 01:07:37
Once the all renderers have exited and the Zygote
|
+ PCHECK(received_size >= 0); |
+ if (received_size > 0) { |
+ PCHECK(file_fd >= 0); |
+ ssize_t written_size = 0; |
+ while (written_size < received_size) { |
+ ssize_t write_res = |
+ HANDLE_EINTR(write(file_fd, buffer.get() + written_size, |
+ received_size - written_size)); |
+ PCHECK(write_res >= 0); |
+ written_size += write_res; |
+ } |
+ PCHECK(0 == HANDLE_EINTR(fsync(file_fd))); |
+ } |
+ } |
+} |
+ |
+// fds[0] is the read end, fds[1] is the write end. |
+static void CreateSanitizerCoverageSocketPair(int fds[2]) { |
jln (very slow on Chromium)
2014/05/21 01:07:37
How are you handling this socketpair on the *SAN s
|
+ PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds)); |
+ PCHECK(0 == shutdown(fds[0], SHUT_WR)); |
+ PCHECK(0 == shutdown(fds[1], SHUT_RD)); |
+} |
+ |
+static void ForkSanitizerCoverageHelper(int child_fd, int parent_fd, |
+ base::ScopedFD file_fd) { |
+ pid_t pid = fork(); |
+ PCHECK(pid >= 0); |
+ if (pid == 0) { |
+ // In the child. |
+ PCHECK(0 == IGNORE_EINTR(close(parent_fd))); |
+ SanitizerCoverageHelper(child_fd, file_fd.get()); |
+ _exit(0); |
+ } else { |
+ // In the parent. |
jln (very slow on Chromium)
2014/05/21 01:07:37
Could you add a note along the lines of:
- We wil
|
+ PCHECK(0 == IGNORE_EINTR(close(child_fd))); |
+ } |
+} |
+#endif |
jln (very slow on Chromium)
2014/05/21 01:07:37
// defined(...)
|
+ |
// If |is_suid_sandbox_child|, then make sure that the setuid sandbox is |
// engaged. |
static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox, |
@@ -425,6 +479,17 @@ bool ZygoteMain(const MainFunctionParams& params, |
sandbox::InitLibcUrandomOverrides(); |
LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); |
+ |
+#if defined(ADDRESS_SANITIZER) |
+ base::ScopedFD sancov_file_fd(__sanitizer_maybe_open_cov_file("zygote")); |
+ int sancov_socket_fds[2] = {-1, -1}; |
+ CreateSanitizerCoverageSocketPair(sancov_socket_fds); |
+ linux_sandbox->sanitizer_args()->coverage_sandboxed = 1; |
+ linux_sandbox->sanitizer_args()->coverage_fd = sancov_socket_fds[1]; |
+ linux_sandbox->sanitizer_args()->coverage_max_block_size = |
+ kSanitizerMaxMessageLength; |
+#endif |
jln (very slow on Chromium)
2014/05/21 01:07:37
// defined(ADDRESS_SANITIZER)
|
+ |
// This will pre-initialize the various sandboxes that need it. |
linux_sandbox->PreinitializeSandbox(); |
@@ -451,6 +516,11 @@ bool ZygoteMain(const MainFunctionParams& params, |
// Turn on the first layer of the sandbox if the configuration warrants it. |
EnterLayerOneSandbox(linux_sandbox, must_enable_setuid_sandbox); |
+#if defined(ADDRESS_SANITIZER) |
+ ForkSanitizerCoverageHelper(sancov_socket_fds[0], sancov_socket_fds[1], |
+ sancov_file_fd.Pass()); |
+#endif |
+ |
int sandbox_flags = linux_sandbox->GetStatus(); |
bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID; |
CHECK_EQ(must_enable_setuid_sandbox, setuid_sandbox_engaged); |