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

Side by Side Diff: chrome/nacl/nacl_helper_linux.cc

Issue 6995121: New NaCl zygote implementation 2 (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Use IPC::Channel directly instead of ChildProcess 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // A mini-zygote specifically for Native Client.
6
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/socket.h>
11 #include <sys/types.h>
12
13 #include <vector>
14
15 #include "base/at_exit.h"
16 #include "base/command_line.h"
17 #include "base/eintr_wrapper.h"
18 #include "base/logging.h"
19 #include "base/message_loop.h"
20 #include "base/rand_util.h"
21 #include "ipc/ipc_channel.h"
22 #include "chrome/common/nacl_helper_linux.h"
23 #include "chrome/nacl/nacl_listener.h"
24 #include "content/common/main_function_params.h"
25 #include "content/common/unix_domain_socket_posix.h"
26
27 #if defined(NDEBUG)
28 #define DEBUG(s) do { if (0) { s; } } while (0)
jam 2011/06/21 20:54:08 you already use stuff from base, why can't you use
Brad Chen 2011/06/21 23:43:48 Done. On 2011/06/21 20:54:08, John Abd-El-Malek w
29 #else
30 #define DEBUG(s) s
31 #endif
32
33 static bool g_suid_sandbox_active;
34
35 // The child must mimic the behavior of zygote_main_linux.cc on the child
36 // side of the fork. See zygote_main_linux.cc:HandleForkRequest from
37 // if (!child) {
38 // Note: this code doesn't attempt to support SELINUX or the SECCOMP sandbox.
39 static void BecomeNaClLoader(const std::vector<int>& child_fds) {
40 DEBUG(fprintf(stderr, "NaCl loader: setting up IPC descriptor\n"));
41 close(kNaClZygoteDescriptor); // don't need this any more
42 // Set up browser descriptor as expected by Chrome on fd 3
43 // The zygote takes care of putting the sandbox IPC channel on fd 5
44 int zfd = dup2(child_fds[kNaClBrowserFDIndex], kNaClBrowserDescriptor);
45 if (zfd != kNaClBrowserDescriptor) {
46 fprintf(stderr, "Could not initialize kNaClBrowserDescriptor (%d)\n", zfd);
47 _exit(-1);
48 }
49
50 MessageLoopForIO main_message_loop;
51 NaClListener listener;
52 IPC::Channel chan(kNaClListenerHandle, IPC::Channel::MODE_CLIENT, &listener);
53 CHECK(chan.Connect());
54 #if 0
jam 2011/06/21 20:54:08 not needed anymore right?
Brad Chen 2011/06/21 23:43:48 Done.
55 // This code is useful for testing NaClLauncherThread. Using
56 // NaClLauncherThread instead of NaClListener increases the
57 // helper release binary size by about 14MB.
58 ChildProcess nacl_process;
59 nacl_process.set_main_thread(new NaClLauncherThread(false));
60 #endif
61 MessageLoop::current()->Run();
62 _exit(0);
63 }
64
65 // Some of this code was lifted from
66 // content/browser/zygote_main_linux.cc:ForkWithRealPid()
67 static void HandleForkRequest(const std::vector<int>& child_fds) {
68 DEBUG(fprintf(stderr, "nacl_helper: forking\n"));
69 pid_t childpid = fork();
70 if (childpid < 0) {
71 perror("fork");
72 fprintf(stderr, "*** HandleForkRequest failed\n");
jam 2011/06/21 20:54:08 nit: please use chrome logging instead of printfs
Brad Chen 2011/06/21 23:43:48 Done.
73 // fall through to parent case below
74 } else if (childpid == 0) { // In the child process.
75 if (g_suid_sandbox_active) {
76 char buffer[1];
77 // Wait until the parent process has discovered our PID. We
78 // should not fork any child processes (which the seccomp
79 // sandbox does) until then, because that can interfere with the
80 // parent's discovery of our PID.
81 int nread = HANDLE_EINTR(read(child_fds[kNaClParentFDIndex], buffer, 1));
82 if (nread != 1 || buffer[0] != 'x') {
83 if (nread < 0) {
84 perror("read");
85 }
86 fprintf(stderr, "Failed to synch with zygote (%d:%d)\n",
87 nread, buffer[0]);
88 } else {
89 DEBUG(fprintf(stderr,
90 "NaCl loader is synchronised with Chrome zygote\n"));
91 }
92 }
93 close(child_fds[kNaClDummyFDIndex]);
94 close(child_fds[kNaClParentFDIndex]);
95 BecomeNaClLoader(child_fds);
96 // NOTREACHED
97 return;
98 }
99 // I am the parent.
100 // First, close the dummy_fd so the sandbox won't find me when
101 // looking for the child's pid in /proc. Also close other fds.
102 for (size_t i = 0; i < child_fds.size(); i++) {
103 close(child_fds[i]);
104 }
105 DEBUG(fprintf(stderr, "nacl_helper: childpid is %d\n", childpid));
106 // Now tell childpid to the Chrome zygote.
107 if (HANDLE_EINTR(send(kNaClZygoteDescriptor,
108 &childpid, sizeof(childpid), MSG_EOR))
109 != sizeof(childpid)) {
110 fprintf(stderr, "*** send() to zygote failed");
111 }
112 }
113
114 int main(int argc, char *argv[]) {
115 CommandLine::Init(argc, argv);
116 base::AtExitManager exit_manager;
117 base::RandUint64(); // acquire /dev/urandom fd before sandbox is raised
118 std::vector<int> empty; // for SendMsg() calls
119
120 g_suid_sandbox_active = (NULL != getenv("SBX_D"));
121
122 // Send the zygote a message to let it know we are ready to help
123 if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor,
124 kNaClHelperStartupAck,
125 sizeof(kNaClHelperStartupAck), empty)) {
126 fprintf(stderr, "*** send() to zygote failed");
127 }
128
129 while (true) {
130 int badpid = -1;
131 std::vector<int> fds;
132 static const unsigned kMaxMessageLength = 2048;
133 char buf[kMaxMessageLength];
134 const ssize_t msglen = UnixDomainSocket::RecvMsg(kNaClZygoteDescriptor,
135 &buf, sizeof(buf), &fds);
136 if (msglen == 0 || (msglen == -1 && errno == ECONNRESET)) {
137 // EOF from the browser. Goodbye!
138 _exit(0);
139 }
140 if (msglen == sizeof(kNaClForkRequest) &&
141 memcmp(buf, kNaClForkRequest, msglen) == 0) {
142 if (kNaClBrowserFDIndex + 1 == fds.size() ||
143 kNaClParentFDIndex + 1 == fds.size()) {
144 HandleForkRequest(fds);
145 continue; // fork succeeded. Note: child does not return
146 } else {
147 fprintf(stderr, "nacl_helper: unexpected number of fds, got %d\n",
148 int(fds.size()));
149 }
150 } else {
151 if (msglen != 0) {
152 fprintf(stderr, "nacl_helper unrecognized request: %s:%d\n",
153 buf, msglen);
154 _exit(-1);
155 }
156 }
157 // if fork fails, send PID=-1 to zygote
158 if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor, &badpid,
159 sizeof(badpid), empty)) {
160 fprintf(stderr, "*** send() to zygote failed");
161 }
162 }
163 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698