Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(815)

Unified Diff: content/browser/zygote_main_linux.cc

Issue 6995121: New NaCl zygote implementation 2 (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Fixing includes for checkdeps.py Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..090ae548c2f289e0c82bbbe30bdac167674fdde3 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/common/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,47 @@ class Zygote {
PLOG(ERROR) << "write";
}
+ base::ProcessId ForkNaClLauncher(std::vector<int>& fds) {
+ base::ProcessId naclchild;
+ VLOG(1) << "ForkNaClLauncher";
+
+ if (g_suid_sandbox_active) {
+ DCHECK(fds.size() == kNaClParentFDIndex + 1);
+ } else {
+ DCHECK(fds.size() == kNaClSandboxFDIndex + 1);
+ }
+ 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");
Mark Seaborn 2011/06/15 16:09:04 You're calling perror() even if read() didn't retu
Brad Chen 2011/06/15 18:47:47 Done.
+ return -1;
Mark Seaborn 2011/06/15 16:09:04 If the read() fails, don't you need to abandon the
Brad Chen 2011/06/15 18:47:47 Let's talk face-to-face about what makes sense in
+ }
+ VLOG(1) << "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) {
+ VLOG(1) << "suid sandbox NOT active";
+ VLOG(1) << "fds.size() is " << fds.size();
+ if (isnaclfork) {
+ return ForkNaClLauncher(fds);
+ } else {
+ return fork();
+ }
+ }
int dummy_fd;
ino_t dummy_inode;
@@ -268,7 +307,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) {
@@ -341,7 +386,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 +417,10 @@ class Zygote {
mapping.push_back(std::make_pair(
static_cast<uint32_t>(kSandboxIPCChannel), kMagicSandboxIPCDescriptor));
- child = ForkWithRealPid();
+ if (isnaclfork) {
+ fds.push_back(kMagicSandboxIPCDescriptor);
+ }
+ child = ForkWithRealPid(isnaclfork, fds);
if (!child) {
#if defined(SECCOMP_SANDBOX)
@@ -447,6 +495,50 @@ class Zygote {
const int sandbox_flags_;
};
+static void LaunchNaClHelper() {
+ VLOG(1) << "LaunchNaClHelper";
+ int fds[2];
+
+ // Confirm a couple hard-wired assumptions.
+ // The NaCl constants are from chrome/nacl/nacl_linux_helper.h
+ DCHECK(kNaClZygoteDescriptor == kBrowserDescriptor);
+ DCHECK(kNaClSandboxDescriptor == kMagicSandboxIPCDescriptor);
+
+ 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));
+
+ const char* nacl_zygote_exe = getenv("NACL_NEW_ZYGOTE");
+ 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,
Mark Seaborn 2011/06/15 16:09:04 If this takes fds_to_map, and you're passing CLONE
Brad Chen 2011/06/15 18:47:47 This code works, which suggests I might not be mes
+ CLONE_FS | SIGCHLD);
+ }
+ close(fds[1]);
+ if (g_naclpid > 0) {
+ const int kExpectedLength = sizeof(kNaClHelperMagic);
+ char buf[kExpectedLength];
+
+ VLOG(1) << "NaCl Launcher PID is " << g_naclpid;
+ int nread = read(fds[0], buf, sizeof(buf));
Mark Seaborn 2011/06/15 16:09:04 Please add a comment saying why you are waiting fo
Brad Chen 2011/06/15 18:47:47 Done.
+ DCHECK(nread == kExpectedLength) << "Incorrect NaCl helper magic length";
+ DCHECK(0 == strcmp(buf, kNaClHelperMagic)) << "Incorrect nacl helper magic";
Mark Seaborn 2011/06/15 16:09:04 memcmp(), surely? The buffer is not null-terminat
Brad Chen 2011/06/15 18:47:47 Done.
+ // all is well
+ g_nacl_helper_fd = fds[0];
+ return;
+ }
+ // TODO(bradchen): Make this LOG(ERROR) when the NaCl helper
+ // becomes the default.
+ VLOG(1) << "Could not launch NaCl helper";
+ g_naclpid = -1;
+ g_nacl_helper_fd = -1;
+ close(fds[0]);
+
+ return;
Mark Seaborn 2011/06/15 16:09:04 Not needed.
Brad Chen 2011/06/15 18:47:47 Done.
+}
+
// 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 +820,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: "

Powered by Google App Engine
This is Rietveld 408576698