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

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: NaCl helper for Chrome Linux zygote 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..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: "

Powered by Google App Engine
This is Rietveld 408576698