Chromium Code Reviews| 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: " |