Index: content/browser/zygote_main_linux.cc |
diff --git a/content/browser/zygote_main_linux.cc b/content/browser/zygote_main_linux.cc |
index ef9dd0be039ba4e78c3f8936ccdde8b1e0b32aa7..9f1ca396d6f8469a07f234f8fab832aff43fa0e2 100644 |
--- a/content/browser/zygote_main_linux.cc |
+++ b/content/browser/zygote_main_linux.cc |
@@ -38,6 +38,7 @@ |
#include "crypto/nss_util.h" |
#include "chrome/common/chrome_paths.h" |
#include "chrome/common/chrome_switches.h" |
+#include "chrome/nacl/nacl_helper_linux.h" |
#include "content/common/chrome_descriptors.h" |
#include "content/common/font_config_ipc_linux.h" |
#include "content/common/main_function_params.h" |
@@ -68,6 +69,8 @@ static bool g_suid_sandbox_active = false; |
#if defined(SECCOMP_SANDBOX) |
// |g_proc_fd| is used only by the seccomp sandbox. |
static int g_proc_fd = -1; |
+static int g_nacl_helper_fd = -1; |
+static base::ProcessId g_naclpid = -1; |
#endif |
#if defined(CHROMIUM_SELINUX) |
@@ -161,8 +164,10 @@ class Zygote { |
if (pickle.ReadInt(&iter, &kind)) { |
switch (kind) { |
case ZygoteHost::kCmdFork: |
+ case ZygoteHost::kCmdNaClFork: |
// This function call can return multiple times, once per fork(). |
- return HandleForkRequest(fd, pickle, iter, fds); |
+ return HandleForkRequest(fd, pickle, iter, fds, |
+ kind == ZygoteHost::kCmdNaClFork); |
case ZygoteHost::kCmdReap: |
if (!fds.empty()) |
break; |
@@ -241,13 +246,42 @@ class Zygote { |
PLOG(ERROR) << "write"; |
} |
+ base::ProcessId ForkNaClLauncher(std::vector<int>& fds) { |
+ base::ProcessId naclchild; |
+ DLOG(INFO) << "ForkNaClLauncher"; |
+ |
+ if (!UnixDomainSocket::SendMsg(g_nacl_helper_fd, kNaClForkRequest, |
+ sizeof(kNaClForkRequest), fds)) { |
+ perror("ForkNaClLauncher: send failed"); |
+ return -1; |
+ } |
+ if (read(g_nacl_helper_fd, &naclchild, sizeof(naclchild)) |
+ != sizeof(naclchild)) { |
+ perror("ForkNaClLauncher: read failed"); |
+ return -1; |
+ } |
+ DLOG(INFO) << "nacl_child is " << naclchild; |
+ return naclchild; |
+ } |
+ |
// This is equivalent to fork(), except that, when using the SUID |
// sandbox, it returns the real PID of the child process as it |
// appears outside the sandbox, rather than returning the PID inside |
// the sandbox. |
- int ForkWithRealPid() { |
- if (!g_suid_sandbox_active) |
- return fork(); |
+ int ForkWithRealPid(const bool naclfork, std::vector<int>& fds) { |
+ // If we didn't start a nacl helper, don't use it to fork. |
+ // TODO(bradchen): remove this once nacl helper is debugged |
+ bool isnaclfork = naclfork && (g_naclpid != -1); |
+ |
+ if (!g_suid_sandbox_active) { |
+ DLOG(INFO) << "suid sandbox NOT active"; |
agl
2011/06/10 17:28:03
This debugging should probably be removed before l
Brad Chen
2011/06/14 00:16:01
Is there a way to leave some code on longer-term f
agl
2011/06/14 14:38:36
Yes, VLOG(1) is suitable for this. See base/loggin
Brad Chen
2011/06/14 22:14:01
Done.
|
+ DLOG(INFO) << "fds.size() is " << fds.size(); |
+ if (isnaclfork) { |
+ return ForkNaClLauncher(fds); |
+ } else { |
+ return fork(); |
+ } |
+ } |
int dummy_fd; |
ino_t dummy_inode; |
@@ -268,7 +302,13 @@ class Zygote { |
goto error; |
} |
- pid = fork(); |
+ if (isnaclfork) { |
+ fds.push_back(dummy_fd); |
+ fds.push_back(pipe_fds[0]); |
+ pid = ForkNaClLauncher(fds); |
+ } else { |
+ pid = fork(); |
+ } |
if (pid < 0) { |
goto error; |
} else if (pid == 0) { |
@@ -292,6 +332,7 @@ class Zygote { |
dummy_fd = -1; |
close(pipe_fds[0]); |
pipe_fds[0] = -1; |
+ |
uint8_t reply_buf[512]; |
Pickle request; |
request.WriteInt(LinuxSandbox::METHOD_GET_CHILD_WITH_INODE); |
@@ -341,7 +382,7 @@ class Zygote { |
// Handle a 'fork' request from the browser: this means that the browser |
// wishes to start a new renderer. |
bool HandleForkRequest(int fd, const Pickle& pickle, void* iter, |
- std::vector<int>& fds) { |
+ std::vector<int>& fds, const bool isnaclfork) { |
std::vector<std::string> args; |
int argc, numfds; |
base::GlobalDescriptors::Mapping mapping; |
@@ -372,7 +413,7 @@ class Zygote { |
mapping.push_back(std::make_pair( |
static_cast<uint32_t>(kSandboxIPCChannel), kMagicSandboxIPCDescriptor)); |
- child = ForkWithRealPid(); |
+ child = ForkWithRealPid(isnaclfork, fds); |
if (!child) { |
#if defined(SECCOMP_SANDBOX) |
@@ -447,6 +488,44 @@ class Zygote { |
const int sandbox_flags_; |
}; |
+static void LaunchNaClHelper() { |
+ DLOG(INFO) << "LaunchNaClHelper"; |
agl
2011/06/10 17:28:03
This debugging should probably be removed before l
Brad Chen
2011/06/14 22:14:01
Replaced with VLOG(1)
On 2011/06/10 17:28:03, agl
|
+ int fds[2]; |
+ |
+ CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0); |
+ base::file_handle_mapping_vector fds_to_map; |
+ fds_to_map.push_back(std::make_pair(fds[1], 3)); |
+ |
+ char* nacl_zygote_exe = getenv("NACL_NEW_ZYGOTE"); |
agl
2011/06/10 17:28:03
const
Brad Chen
2011/06/14 00:16:01
Done.
|
+ g_naclpid = -1; |
+ if (NULL != nacl_zygote_exe) { |
+ CommandLine::StringVector argv = CommandLine::ForCurrentProcess()->argv(); |
+ argv[0] = nacl_zygote_exe; |
+ base::LaunchAppWithClone(argv, fds_to_map, false, &g_naclpid, |
+ CLONE_FS | SIGCHLD); |
+ } |
+ close(fds[1]); |
+ if (g_naclpid > 0) { |
+ const int kExpectedLength = sizeof(kNaClHelperMagic); |
+ char buf[kExpectedLength]; |
+ int nread; |
+ |
+ DLOG(INFO) << "NaCl Launcher PID is " << g_naclpid; |
agl
2011/06/10 17:28:03
ditto.
Brad Chen
2011/06/14 22:14:01
Replaced with VLOG(1)
On 2011/06/10 17:28:03, agl
|
+ nread = read(fds[0], buf, sizeof(buf)); |
agl
2011/06/10 17:28:03
nread can be declared here.
Brad Chen
2011/06/14 00:16:01
Done.
|
+ DCHECK(nread == kExpectedLength) << "Incorrect NaCl helper magic length"; |
+ DCHECK(0 == strcmp(buf, kNaClHelperMagic)) << "Incorrect nacl helper magic"; |
+ // all is well |
+ g_nacl_helper_fd = fds[0]; |
+ return; |
+ } |
+ DLOG(INFO) << "Could not launch NaCl helper"; |
+ g_naclpid = -1; |
+ g_nacl_helper_fd = -1; |
+ close(fds[0]); |
+ |
+ return; |
+} |
+ |
// With SELinux we can carve out a precise sandbox, so we don't have to play |
// with intercepting libc calls. |
#if !defined(CHROMIUM_SELINUX) |
@@ -728,6 +807,9 @@ bool ZygoteMain(const MainFunctionParams& params) { |
} |
#endif // SECCOMP_SANDBOX |
+ // launch Native Client helper before entering the sandbox |
+ LaunchNaClHelper(); |
+ |
// Turn on the SELinux or SUID sandbox |
if (!EnterSandbox()) { |
LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " |