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

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: Follow #define conventions 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 99a773556ff960383693cdc3e3fe7a0d1ae05ce2..8e5a007fbf658d12100391bc9cfea43426dfbe33 100644
--- a/content/browser/zygote_main_linux.cc
+++ b/content/browser/zygote_main_linux.cc
@@ -37,9 +37,11 @@
#include "content/common/sandbox_methods_linux.h"
#include "content/common/set_process_title.h"
#include "content/common/unix_domain_socket_posix.h"
+#include "content/common/zygote_fork_delegate_linux.h"
#include "seccompsandbox/sandbox.h"
#include "skia/ext/SkFontHost_fontconfig_control.h"
#include "unicode/timezone.h"
+#include "ipc/ipc_switches.h"
#if defined(OS_LINUX)
#include <sys/epoll.h>
@@ -92,13 +94,26 @@ static void SELinuxTransitionToTypeOrDie(const char* type) {
}
#endif // CHROMIUM_SELINUX
+static std::string ExtractArg(std::vector<std::string> args,
Evan Martin 2011/06/24 18:57:33 Use namespace{} instead of static Why no comments
Brad Chen 2011/06/25 22:14:51 Comments added. Given the consistent use of "stat
+ const std::string swtch) {
Evan Martin 2011/06/24 18:57:33 Pass by reference, not by copying
Brad Chen 2011/06/25 22:14:51 Done.
+ const std::string key = "--" + swtch + "=";
+ int len = key.length();
+ for (size_t i = 0; i < args.size(); i++) {
+ if (key.compare(0, len, args[i], 0, len) == 0) {
+ return args[i];
+ }
+ }
+ return "";
+}
+
// This is the object which implements the zygote. The ZygoteMain function,
// which is called from ChromeMain, simply constructs one of these objects and
// runs it.
class Zygote {
public:
- explicit Zygote(int sandbox_flags)
- : sandbox_flags_(sandbox_flags) {
+ explicit Zygote(int sandbox_flags, ZygoteForkDelegate* helper)
+ : sandbox_flags_(sandbox_flags),
+ helper_(helper) {
}
bool ProcessRequests() {
@@ -160,11 +175,14 @@ class Zygote {
void* iter = NULL;
int kind;
+ std::string process_type;
if (pickle.ReadInt(&iter, &kind)) {
switch (kind) {
case ZygoteHost::kCmdFork:
// This function call can return multiple times, once per fork().
- return HandleForkRequest(fd, pickle, iter, fds);
+ pickle.ReadString(&iter, &process_type);
+ return HandleForkRequest(fd, pickle, iter, fds, process_type);
Evan Martin 2011/06/24 18:57:33 Since HandleForkRequest reaches into the pickle an
Brad Chen 2011/06/25 22:14:51 Done.
+
case ZygoteHost::kCmdReap:
if (!fds.empty())
break;
@@ -247,9 +265,12 @@ class Zygote {
// 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)
+ int ForkWithRealPid(const std::string process_type, std::vector<int>& fds,
+ const std::string channel_switch) {
+ const bool use_helper = (helper_ && helper_->CanHelp(process_type));
+ if (!(use_helper || g_suid_sandbox_active)) {
return fork();
+ }
int dummy_fd;
ino_t dummy_inode;
@@ -270,7 +291,13 @@ class Zygote {
goto error;
}
- pid = fork();
+ if (use_helper) {
+ fds.push_back(dummy_fd);
+ fds.push_back(pipe_fds[0]);
+ pid = helper_->Fork(fds);
+ } else {
+ pid = fork();
+ }
if (pid < 0) {
goto error;
} else if (pid == 0) {
@@ -294,33 +321,43 @@ 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);
- request.WriteUInt64(dummy_inode);
-
- const ssize_t r = UnixDomainSocket::SendRecvMsg(
- kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL,
- request);
- if (r == -1) {
- LOG(ERROR) << "Failed to get child process's real PID";
- goto error;
- }
-
base::ProcessId real_pid;
- Pickle reply(reinterpret_cast<char*>(reply_buf), r);
- void* iter2 = NULL;
- if (!reply.ReadInt(&iter2, &real_pid))
- goto error;
- if (real_pid <= 0) {
- // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already?
- LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed";
- goto error;
+ if (g_suid_sandbox_active) {
+ uint8_t reply_buf[512];
+ Pickle request;
+ request.WriteInt(LinuxSandbox::METHOD_GET_CHILD_WITH_INODE);
+ request.WriteUInt64(dummy_inode);
+
+ const ssize_t r = UnixDomainSocket::SendRecvMsg(
+ kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL,
+ request);
+ if (r == -1) {
+ LOG(ERROR) << "Failed to get child process's real PID";
+ goto error;
+ }
+
+ Pickle reply(reinterpret_cast<char*>(reply_buf), r);
+ void* iter2 = NULL;
+ if (!reply.ReadInt(&iter2, &real_pid))
+ goto error;
+ if (real_pid <= 0) {
+ // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already?
+ LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed";
+ goto error;
+ }
+ real_pids_to_sandbox_pids[real_pid] = pid;
}
- real_pids_to_sandbox_pids[real_pid] = pid;
- if (HANDLE_EINTR(write(pipe_fds[1], "x", 1)) != 1) {
- LOG(ERROR) << "Failed to synchronise with child process";
- goto error;
+ if (use_helper) {
+ real_pid = pid;
+ if (!helper_->AckChild(pipe_fds[1], channel_switch)) {
+ LOG(ERROR) << "Failed to synchronise with NaCl child process";
+ goto error;
+ }
+ } else {
+ if (HANDLE_EINTR(write(pipe_fds[1], "x", 1)) != 1) {
+ LOG(ERROR) << "Failed to synchronise with child process";
+ goto error;
+ }
}
close(pipe_fds[1]);
return real_pid;
@@ -342,8 +379,9 @@ 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) {
+ bool HandleForkRequest(int fd, const Pickle& pickle,
+ void* iter, std::vector<int>& fds,
+ const std::string process_type) {
Evan Martin 2011/06/24 18:57:33 Pass by reference, not copy
Brad Chen 2011/06/25 22:14:51 As per your suggestion I'm no longer passing proce
std::vector<std::string> args;
int argc, numfds;
base::GlobalDescriptors::Mapping mapping;
@@ -374,7 +412,8 @@ class Zygote {
mapping.push_back(std::make_pair(
static_cast<uint32_t>(kSandboxIPCChannel), kMagicSandboxIPCDescriptor));
- child = ForkWithRealPid();
+ child = ForkWithRealPid(process_type, fds,
+ ExtractArg(args, switches::kProcessChannelID));
if (!child) {
#if defined(SECCOMP_SANDBOX)
@@ -447,6 +486,7 @@ class Zygote {
ProcessMap real_pids_to_sandbox_pids;
const int sandbox_flags_;
+ ZygoteForkDelegate* helper_;
};
// With SELinux we can carve out a precise sandbox, so we don't have to play
@@ -705,7 +745,8 @@ static bool EnterSandbox() {
#endif // CHROMIUM_SELINUX
-bool ZygoteMain(const MainFunctionParams& params) {
+bool ZygoteMain(const MainFunctionParams& params,
+ ZygoteForkDelegate* forkdelegate) {
#if !defined(CHROMIUM_SELINUX)
g_am_zygote_or_renderer = true;
#endif
@@ -724,6 +765,11 @@ bool ZygoteMain(const MainFunctionParams& params) {
}
#endif // SECCOMP_SANDBOX
+ // initialize the fork helper
Evan Martin 2011/06/24 18:57:33 This comment is uninformative. I suggest deleting
Brad Chen 2011/06/25 22:14:51 Done.
+ VLOG(1) << "initializing fork delegate";
+ forkdelegate->Init(getenv("SBX_D") != NULL, // g_suid_sandbox_active,
+ kBrowserDescriptor, kMagicSandboxIPCDescriptor);
+
// Turn on the SELinux or SUID sandbox
if (!EnterSandbox()) {
LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: "
@@ -760,7 +806,7 @@ bool ZygoteMain(const MainFunctionParams& params) {
}
#endif // SECCOMP_SANDBOX
- Zygote zygote(sandbox_flags);
+ Zygote zygote(sandbox_flags, forkdelegate);
// This function call can return multiple times, once per fork().
return zygote.ProcessRequests();
}

Powered by Google App Engine
This is Rietveld 408576698