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

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: Dropping mods to content/browser/DEPS 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 <string.h>
11 #include <sys/socket.h>
12 #include <sys/stat.h> // for debugging
13 #include <sys/types.h>
14 #include <unistd.h>
15
16 #include <vector>
17
18 #include "base/at_exit.h"
19 #include "base/command_line.h"
20 #include "base/eintr_wrapper.h"
21 #include "base/mac/scoped_nsautorelease_pool.h"
22 #include "base/rand_util.h"
23 #include "base/rand_util_c.h"
24 #include "chrome/common/nacl_helper_linux.h"
25 #include "content/common/main_function_params.h"
26 #include "content/common/unix_domain_socket_posix.h"
27
28 #include "base/message_loop.h"
29 #include "content/common/child_process.h"
30 #include "chrome/nacl/nacl_launcher_thread.h"
31 #undef DCHECK
32
33 // We define DCHECK internally instead of including base/logging.h
34 // from Chromium, in hopes of avoiding a large dependency tree. The
35 // goal is to make the nacl_helper binary small, as it is a new
36 // binary in the Chrome Linux distribution.
37 #if defined(NDEBUG)
38 #define DCHECK(condition) {}
39 #define DEBUG(s) do { if (0) { s; } } while (0)
40 #else
41 #define DCHECK(condition) \
42 { if (!condition) fprintf(stderr, "Check failed: %s.\n", #condition); }
43 #define DEBUG(s) s
44 #endif
45
46 #if !defined(NDEBUG)
47 class GURL;
48 // This is another attempt to reduce binary size by pruning dependencies.
49 // These two symbols from webkit_glue are being referenced someplace
50 // in debug builds but apparently are not being called. I do not know
51 // from where they are referenced, but as long as it's not in release
52 // builds this seems okay.
53 namespace webkit_glue {
54
55 bool FindProxyForUrl(const GURL& url, std::string* proxy_list) {
56 fprintf(stderr, "Who is calling FindProxyForUrl?");
57 _exit(-1);
58 return false;
59 }
60
61 std::string GetProductVersion() {
62 fprintf(stderr, "Who is calling GetProductVersion?");
63 _exit(-1);
64 return "";
65 }
66
67 } // namespace webkit_glue
68 #endif // NDEBUG
69
70 #if !defined(NDEBUG)
71 static void PrintFDMap() {
72 printf("FD map:\n");
73 for (int i = 0; i < 100; i++) {
74 struct stat ss;
75 if (fstat(i, &ss) >= 0) {
76 printf(" %2d: %llx:%o\n", i, ss.st_ino, ss.st_mode);
77 }
78 }
79 }
80 #endif
81
82 static bool g_suid_sandbox_active;
83 extern int NaClMain(const MainFunctionParams&);
84 typedef int NaClHandle;
85 extern "C" int NaClMainForChromium(int handle_count,
86 const NaClHandle* handles,
87 int debug);
88
89 // The child must mimic the behavior of zygote_main_linux.cc on the child
90 // side of the fork. See zygote_main_linux.cc:HandleForkRequest from
91 // if (!child) {
92 // Note: this code doesn't attempt to support SELINUX or the SECCOMP sandbox.
93 static void BecomeNaClLoader(const std::vector<int>& child_fds) {
94 DEBUG(fprintf(stderr, "NaCl loader: setting up IPC descriptor\n"));
95 close(kNaClZygoteDescriptor); // don't need this any more
96 // Set up browser descriptor as expected by Chrome on fd 3
97 // The zygote takes care of putting the sandbox IPC channel on fd 5
98 int zfd = dup2(child_fds[kNaClBrowserFDIndex], kNaClBrowserDescriptor);
99 if (zfd != kNaClBrowserDescriptor) {
100 fprintf(stderr, "Could not initialize kNaClBrowserDescriptor (%d)\n", zfd);
101 _exit(-1);
102 }
103
104 #if 0
105 // this is the code that actually works
106 base::mac::ScopedNSAutoreleasePool autorelease_pool;
agl 2011/06/20 17:28:55 It's odd to see "base::mac::" in a _linux file.
Brad Chen 2011/06/20 22:09:47 Agreed! In the next revision NaClMain() has been d
107 SandboxInitWrapper sandbox_wrapper;
108 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
109 const MainFunctionParams mainparams(command_line,
110 sandbox_wrapper,
111 &autorelease_pool);
112 DEBUG(fprintf(stderr, "calling NaClMain\n"));
113 NaClMain(mainparams);
114 _exit(0);
115 #endif
116 // debugging code below; it works
117 {
118 // deconstructed NaClMain
119 PrintFDMap();
120 MessageLoopForIO main_message_loop;
121 PrintFDMap();
122 ChildProcess nacl_process;
123 nacl_process.set_main_thread(new NaClLauncherThread(false /* debug */));
124 PrintFDMap();
125 MessageLoop::current()->Run();
126 _exit(0);
127 }
128 // NaClMainForChromium(0, NULL, 0);
129 }
130
131 // Some of this code was lifted from
132 // content/browser/zygote_main_linux.cc:ForkWithRealPid()
133 static void HandleForkRequest(const std::vector<int>& child_fds) {
134 DEBUG(fprintf(stderr, "nacl_helper: forking\n"));
135 pid_t childpid = fork();
136 if (childpid < 0) {
137 perror("fork");
138 fprintf(stderr, "*** HandleForkRequest failed\n");
139 // fall through to parent case below
140 } else if (childpid == 0) { // In the child process.
141 if (g_suid_sandbox_active) {
142 char buffer[1];
143 // Wait until the parent process has discovered our PID. We
144 // should not fork any child processes (which the seccomp
145 // sandbox does) until then, because that can interfere with the
146 // parent's discovery of our PID.
147 int nread = HANDLE_EINTR(read(child_fds[kNaClParentFDIndex], buffer, 1));
148 if (nread != 1 || buffer[0] != 'x') {
149 if (nread < 0) {
150 perror("read");
151 }
152 fprintf(stderr, "Failed to synch with zygote (%d:%d)\n",
153 nread, buffer[0]);
154 } else {
155 DEBUG(fprintf(stderr,
156 "NaCl loader is synchronised with Chrome zygote\n"));
157 }
158 }
159 close(child_fds[kNaClDummyFDIndex]);
160 close(child_fds[kNaClParentFDIndex]);
161 BecomeNaClLoader(child_fds);
162 // NOTREACHED
163 return;
164 }
165 // I am the parent.
166 // First, close the dummy_fd so the sandbox won't find me when
167 // looking for the child's pid in /proc. Also close other fds.
168 for (size_t i = 0; i < child_fds.size(); i++) {
169 close(child_fds[i]);
170 }
171 fprintf(stderr, "nacl_helper: childpid is %d\n", childpid);
172 // Now tell childpid to the Chrome zygote.
173 if (HANDLE_EINTR(send(kNaClZygoteDescriptor,
174 &childpid, sizeof(childpid), MSG_EOR))
175 != sizeof(childpid)) {
176 fprintf(stderr, "*** send() to zygote failed");
177 }
178 }
179
180 int main(int argc, char *argv[]) {
181 CommandLine::Init(argc, argv);
182 base::AtExitManager exit_manager;
183 base::RandUint64(); // acquire /dev/urandom fd before sandbox is raised
184 std::vector<int> empty; // for SendMsg() calls
185
186 g_suid_sandbox_active = (NULL != getenv("SBX_D"));
187
188 // Send the zygote a message to let it know we are ready to help
189 if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor,
190 kNaClHelperStartupAck,
191 sizeof(kNaClHelperStartupAck), empty)) {
192 fprintf(stderr, "*** send() to zygote failed");
193 }
194 DEBUG(fprintf(stderr, "nacl_helper: ready to help\n"));
195 DEBUG(fprintf(stderr, " /dev/urandom is on fd %d\n", GetUrandomFD()));
196
197 while (true) {
198 int badpid = -1;
199 std::vector<int> fds;
200 static const unsigned kMaxMessageLength = 2048;
201 char buf[kMaxMessageLength];
202 const ssize_t msglen = UnixDomainSocket::RecvMsg(kNaClZygoteDescriptor,
203 &buf, sizeof(buf), &fds);
204 if (msglen == -1) {
205 fprintf(stderr, "NaCl helper: error reading message from zygote\n");
206 _exit(-1);
207 }
208 // fork request
209 if (msglen == sizeof(kNaClForkRequest) &&
210 memcmp(buf, kNaClForkRequest, msglen) == 0) {
211 if (kNaClBrowserFDIndex + 1 == fds.size() ||
212 kNaClParentFDIndex + 1 == fds.size()) {
213 HandleForkRequest(fds);
214 continue; // fork succeeded. Note: child does not return
215 } else {
216 fprintf(stderr, "nacl_helper: unexpected number of fds, got %d\n",
217 int(fds.size()));
218 }
219 } else {
220 fprintf(stderr, "nacl_helper unrecognized request: %s:%d\n", buf, msglen);
221 _exit(-1);
222 }
223 // if fork fails, send PID=-1 to zygote
224 if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor, &badpid,
225 sizeof(badpid), empty)) {
226 fprintf(stderr, "*** send() to zygote failed");
227 }
228 }
229 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698