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

Side by Side Diff: chrome/browser/zygote_main_linux.cc

Issue 359001: Revert 30938 - Add support for getting the real process id from within the su... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 1 month 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
« no previous file with comments | « chrome/browser/zygote_host_linux.cc ('k') | chrome/chrome.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <dlfcn.h> 5 #include <dlfcn.h>
6 #include <unistd.h>
6 #include <sys/epoll.h> 7 #include <sys/epoll.h>
8 #include <sys/types.h>
9 #include <sys/socket.h>
10 #include <sys/signal.h>
7 #include <sys/prctl.h> 11 #include <sys/prctl.h>
8 #include <sys/signal.h>
9 #include <sys/socket.h>
10 #include <sys/types.h>
11 #include <sys/wait.h> 12 #include <sys/wait.h>
12 #include <unistd.h>
13
14 #if defined(CHROMIUM_SELINUX)
15 #include <selinux/selinux.h>
16 #include <selinux/context.h>
17 #endif
18 13
19 #include "base/basictypes.h" 14 #include "base/basictypes.h"
20 #include "base/command_line.h" 15 #include "base/command_line.h"
21 #include "base/eintr_wrapper.h" 16 #include "base/eintr_wrapper.h"
22 #include "base/global_descriptors_posix.h" 17 #include "base/global_descriptors_posix.h"
23 #include "base/hash_tables.h"
24 #include "base/linux_util.h"
25 #include "base/path_service.h" 18 #include "base/path_service.h"
26 #include "base/pickle.h" 19 #include "base/pickle.h"
27 #include "base/rand_util.h" 20 #include "base/rand_util.h"
28 #include "base/scoped_ptr.h" 21 #include "base/scoped_ptr.h"
29 #include "base/sys_info.h" 22 #include "base/sys_info.h"
30 #include "base/unix_domain_socket_posix.h" 23 #include "base/unix_domain_socket_posix.h"
31 24
32 #include "chrome/browser/zygote_host_linux.h" 25 #include "chrome/browser/zygote_host_linux.h"
33 #include "chrome/common/chrome_descriptors.h" 26 #include "chrome/common/chrome_descriptors.h"
34 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
35 #include "chrome/common/main_function_params.h" 28 #include "chrome/common/main_function_params.h"
36 #include "chrome/common/process_watcher.h" 29 #include "chrome/common/process_watcher.h"
37 #include "chrome/common/sandbox_methods_linux.h" 30 #include "chrome/common/sandbox_methods_linux.h"
38 31
39 #include "media/base/media.h" 32 #include "media/base/media.h"
40 33
41 #include "skia/ext/SkFontHost_fontconfig_control.h" 34 #include "skia/ext/SkFontHost_fontconfig_control.h"
42 35
36 #if defined(CHROMIUM_SELINUX)
37 #include <selinux/selinux.h>
38 #include <selinux/context.h>
39 #endif
40
43 #include "unicode/timezone.h" 41 #include "unicode/timezone.h"
44 42
45 // http://code.google.com/p/chromium/wiki/LinuxZygote 43 // http://code.google.com/p/chromium/wiki/LinuxZygote
46 44
47 static const int kBrowserDescriptor = 3;
48 static const int kMagicSandboxIPCDescriptor = 5; 45 static const int kMagicSandboxIPCDescriptor = 5;
49 static const int kZygoteIdDescriptor = 7;
50 static bool g_suid_sandbox_active = false;
51 46
52 // This is the object which implements the zygote. The ZygoteMain function, 47 // This is the object which implements the zygote. The ZygoteMain function,
53 // which is called from ChromeMain, at the the bottom and simple constructs one 48 // which is called from ChromeMain, at the the bottom and simple constructs one
54 // of these objects and runs it. 49 // of these objects and runs it.
55 class Zygote { 50 class Zygote {
56 public: 51 public:
57 bool ProcessRequests() { 52 bool ProcessRequests() {
58 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the 53 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the
59 // browser on it. 54 // browser on it.
60 // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel. 55 // A SOCK_DGRAM is installed in fd 4. This is the sandbox IPC channel.
61 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC 56 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
62 57
63 // We need to accept SIGCHLD, even though our handler is a no-op because 58 // We need to accept SIGCHLD, even though our handler is a no-op because
64 // otherwise we cannot wait on children. (According to POSIX 2001.) 59 // otherwise we cannot wait on children. (According to POSIX 2001.)
65 struct sigaction action; 60 struct sigaction action;
66 memset(&action, 0, sizeof(action)); 61 memset(&action, 0, sizeof(action));
67 action.sa_handler = SIGCHLDHandler; 62 action.sa_handler = SIGCHLDHandler;
68 CHECK(sigaction(SIGCHLD, &action, NULL) == 0); 63 CHECK(sigaction(SIGCHLD, &action, NULL) == 0);
69 64
70 if (g_suid_sandbox_active) {
71 // Let the ZygoteHost know we are ready to go.
72 // The receiving code is in chrome/browser/zygote_host_linux.cc.
73 std::vector<int> empty;
74 bool r = base::SendMsg(kBrowserDescriptor, kZygoteMagic,
75 sizeof(kZygoteMagic), empty);
76 CHECK(r) << "Sending zygote magic failed";
77 }
78
79 for (;;) { 65 for (;;) {
80 if (HandleRequestFromBrowser(kBrowserDescriptor)) 66 if (HandleRequestFromBrowser(3))
81 return true; 67 return true;
82 } 68 }
83 } 69 }
84 70
85 private: 71 private:
86 // See comment below, where sigaction is called. 72 // See comment below, where sigaction is called.
87 static void SIGCHLDHandler(int signal) { } 73 static void SIGCHLDHandler(int signal) { }
88 74
89 // --------------------------------------------------------------------------- 75 // ---------------------------------------------------------------------------
90 // Requests from the browser... 76 // Requests from the browser...
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 } 115 }
130 } 116 }
131 117
132 LOG(WARNING) << "Error parsing message from browser"; 118 LOG(WARNING) << "Error parsing message from browser";
133 for (std::vector<int>::const_iterator 119 for (std::vector<int>::const_iterator
134 i = fds.begin(); i != fds.end(); ++i) 120 i = fds.begin(); i != fds.end(); ++i)
135 close(*i); 121 close(*i);
136 return false; 122 return false;
137 } 123 }
138 124
139 bool HandleReapRequest(int fd, const Pickle& pickle, void* iter) { 125 bool HandleReapRequest(int fd, Pickle& pickle, void* iter) {
140 base::ProcessId child; 126 pid_t child;
141 base::ProcessId actual_child;
142 127
143 if (!pickle.ReadInt(&iter, &child)) { 128 if (!pickle.ReadInt(&iter, &child)) {
144 LOG(WARNING) << "Error parsing reap request from browser"; 129 LOG(WARNING) << "Error parsing reap request from browser";
145 return false; 130 return false;
146 } 131 }
147 132
148 if (g_suid_sandbox_active) { 133 ProcessWatcher::EnsureProcessTerminated(child);
149 actual_child = real_pids_to_sandbox_pids[child];
150 if (!actual_child)
151 return false;
152 real_pids_to_sandbox_pids.erase(child);
153 } else {
154 actual_child = child;
155 }
156
157 ProcessWatcher::EnsureProcessTerminated(actual_child);
158 134
159 return false; 135 return false;
160 } 136 }
161 137
162 bool HandleDidProcessCrash(int fd, const Pickle& pickle, void* iter) { 138 bool HandleDidProcessCrash(int fd, Pickle& pickle, void* iter) {
163 base::ProcessHandle child; 139 base::ProcessHandle child;
164 140
165 if (!pickle.ReadInt(&iter, &child)) { 141 if (!pickle.ReadInt(&iter, &child)) {
166 LOG(WARNING) << "Error parsing DidProcessCrash request from browser"; 142 LOG(WARNING) << "Error parsing DidProcessCrash request from browser";
167 return false; 143 return false;
168 } 144 }
169 145
170 bool child_exited; 146 bool child_exited;
171 bool did_crash; 147 bool did_crash = base::DidProcessCrash(&child_exited, child);
172 if (g_suid_sandbox_active)
173 child = real_pids_to_sandbox_pids[child];
174 if (child)
175 did_crash = base::DidProcessCrash(&child_exited, child);
176 else
177 did_crash = child_exited = false;
178 148
179 Pickle write_pickle; 149 Pickle write_pickle;
180 write_pickle.WriteBool(did_crash); 150 write_pickle.WriteBool(did_crash);
181 write_pickle.WriteBool(child_exited); 151 write_pickle.WriteBool(child_exited);
182 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); 152 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size()));
183 153
184 return false; 154 return false;
185 } 155 }
186 156
187 // Handle a 'fork' request from the browser: this means that the browser 157 // Handle a 'fork' request from the browser: this means that the browser
188 // wishes to start a new renderer. 158 // wishes to start a new renderer.
189 bool HandleForkRequest(int fd, const Pickle& pickle, void* iter, 159 bool HandleForkRequest(int fd, Pickle& pickle, void* iter,
190 std::vector<int>& fds) { 160 std::vector<int>& fds) {
191 std::vector<std::string> args; 161 std::vector<std::string> args;
192 int argc, numfds; 162 int argc, numfds;
193 base::GlobalDescriptors::Mapping mapping; 163 base::GlobalDescriptors::Mapping mapping;
194 base::ProcessId child; 164 pid_t child;
195 uint64_t dummy_inode = 0;
196 int dummy_fd = -1;
197 165
198 if (!pickle.ReadInt(&iter, &argc)) 166 if (!pickle.ReadInt(&iter, &argc))
199 goto error; 167 goto error;
200 168
201 for (int i = 0; i < argc; ++i) { 169 for (int i = 0; i < argc; ++i) {
202 std::string arg; 170 std::string arg;
203 if (!pickle.ReadString(&iter, &arg)) 171 if (!pickle.ReadString(&iter, &arg))
204 goto error; 172 goto error;
205 args.push_back(arg); 173 args.push_back(arg);
206 } 174 }
207 175
208 if (!pickle.ReadInt(&iter, &numfds)) 176 if (!pickle.ReadInt(&iter, &numfds))
209 goto error; 177 goto error;
210 if (numfds != static_cast<int>(fds.size())) 178 if (numfds != static_cast<int>(fds.size()))
211 goto error; 179 goto error;
212 180
213 for (int i = 0; i < numfds; ++i) { 181 for (int i = 0; i < numfds; ++i) {
214 base::GlobalDescriptors::Key key; 182 base::GlobalDescriptors::Key key;
215 if (!pickle.ReadUInt32(&iter, &key)) 183 if (!pickle.ReadUInt32(&iter, &key))
216 goto error; 184 goto error;
217 mapping.push_back(std::make_pair(key, fds[i])); 185 mapping.push_back(std::make_pair(key, fds[i]));
218 } 186 }
219 187
220 mapping.push_back(std::make_pair( 188 mapping.push_back(std::make_pair(
221 static_cast<uint32_t>(kSandboxIPCChannel), kMagicSandboxIPCDescriptor)); 189 static_cast<uint32_t>(kSandboxIPCChannel), 5));
222
223 if (g_suid_sandbox_active) {
224 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0);
225 if (dummy_fd < 0)
226 goto error;
227
228 if (!base::FileDescriptorGetInode(&dummy_inode, dummy_fd))
229 goto error;
230 }
231 190
232 child = fork(); 191 child = fork();
233 192
234 if (!child) { 193 if (!child) {
235 close(kBrowserDescriptor); // our socket from the browser 194 close(3); // our socket from the browser is in fd 3
236 close(kZygoteIdDescriptor); // another socket from the browser
237 Singleton<base::GlobalDescriptors>()->Reset(mapping); 195 Singleton<base::GlobalDescriptors>()->Reset(mapping);
238 196
239 // Reset the process-wide command line to our new command line. 197 // Reset the process-wide command line to our new command line.
240 CommandLine::Reset(); 198 CommandLine::Reset();
241 CommandLine::Init(0, NULL); 199 CommandLine::Init(0, NULL);
242 CommandLine::ForCurrentProcess()->InitFromArgv(args); 200 CommandLine::ForCurrentProcess()->InitFromArgv(args);
243 CommandLine::SetProcTitle(); 201 CommandLine::SetProcTitle();
244 return true; 202 return true;
245 } else if (child < 0) {
246 LOG(ERROR) << "Zygote could not fork";
247 goto error;
248 } 203 }
249 204
250 {
251 base::ProcessId proc_id;
252 if (g_suid_sandbox_active) {
253 close(dummy_fd);
254 dummy_fd = -1;
255 uint8_t reply_buf[512];
256 Pickle request;
257 request.WriteInt(LinuxSandbox::METHOD_GET_CHILD_WITH_INODE);
258 request.WriteUInt64(dummy_inode);
259
260 const ssize_t r = base::SendRecvMsg(kMagicSandboxIPCDescriptor,
261 reply_buf, sizeof(reply_buf),
262 NULL, request);
263 if (r == -1)
264 goto error;
265
266 Pickle reply(reinterpret_cast<char*>(reply_buf), r);
267 void* iter2 = NULL;
268 if (!reply.ReadInt(&iter2, &proc_id))
269 goto error;
270 real_pids_to_sandbox_pids[proc_id] = child;
271 } else {
272 proc_id = child;
273 }
274
275 for (std::vector<int>::const_iterator
276 i = fds.begin(); i != fds.end(); ++i)
277 close(*i);
278
279 HANDLE_EINTR(write(fd, &proc_id, sizeof(proc_id)));
280 return false;
281 }
282
283 error:
284 LOG(ERROR) << "Error parsing fork request from browser";
285 for (std::vector<int>::const_iterator 205 for (std::vector<int>::const_iterator
286 i = fds.begin(); i != fds.end(); ++i) 206 i = fds.begin(); i != fds.end(); ++i)
287 close(*i); 207 close(*i);
288 if (dummy_fd >= 0) 208
289 close(dummy_fd); 209 HANDLE_EINTR(write(fd, &child, sizeof(child)));
210 return false;
211
212 error:
213 LOG(WARNING) << "Error parsing fork request from browser";
214 for (std::vector<int>::const_iterator
215 i = fds.begin(); i != fds.end(); ++i)
216 close(*i);
290 return false; 217 return false;
291 } 218 }
292
293 // In the SUID sandbox, we try to use a new PID namespace. Thus the PIDs
294 // fork() returns are not the real PIDs, so we need to map the Real PIDS
295 // into the sandbox PID namespace.
296 typedef base::hash_map<base::ProcessHandle, base::ProcessHandle> ProcessMap;
297 ProcessMap real_pids_to_sandbox_pids;
298 }; 219 };
299 220
300 // With SELinux we can carve out a precise sandbox, so we don't have to play 221 // With SELinux we can carve out a precise sandbox, so we don't have to play
301 // with intercepting libc calls. 222 // with intercepting libc calls.
302 #if !defined(CHROMIUM_SELINUX) 223 #if !defined(CHROMIUM_SELINUX)
303 224
304 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, 225 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output,
305 char* timezone_out, 226 char* timezone_out,
306 size_t timezone_out_len) { 227 size_t timezone_out_len) {
307 Pickle request; 228 Pickle request;
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 } 395 }
475 396
476 #if !defined(CHROMIUM_SELINUX) 397 #if !defined(CHROMIUM_SELINUX)
477 static bool EnterSandbox() { 398 static bool EnterSandbox() {
478 const char* const sandbox_fd_string = getenv("SBX_D"); 399 const char* const sandbox_fd_string = getenv("SBX_D");
479 if (sandbox_fd_string) { 400 if (sandbox_fd_string) {
480 // The SUID sandbox sets this environment variable to a file descriptor 401 // The SUID sandbox sets this environment variable to a file descriptor
481 // over which we can signal that we have completed our startup and can be 402 // over which we can signal that we have completed our startup and can be
482 // chrooted. 403 // chrooted.
483 404
484 g_suid_sandbox_active = true;
485
486 char* endptr; 405 char* endptr;
487 const long fd_long = strtol(sandbox_fd_string, &endptr, 10); 406 const long fd_long = strtol(sandbox_fd_string, &endptr, 10);
488 if (!*sandbox_fd_string || *endptr || fd_long < 0 || fd_long > INT_MAX) 407 if (!*sandbox_fd_string || *endptr || fd_long < 0 || fd_long > INT_MAX)
489 return false; 408 return false;
490 const int fd = fd_long; 409 const int fd = fd_long;
491 410
492 PreSandboxInit(); 411 PreSandboxInit();
493 412
494 static const char kChrootMe = 'C'; 413 static const char kChrootMe = 'C';
495 static const char kChrootMeSuccess = 'O'; 414 static const char kChrootMeSuccess = 'O';
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 502
584 if (!EnterSandbox()) { 503 if (!EnterSandbox()) {
585 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " 504 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: "
586 << errno << ")"; 505 << errno << ")";
587 return false; 506 return false;
588 } 507 }
589 508
590 Zygote zygote; 509 Zygote zygote;
591 return zygote.ProcessRequests(); 510 return zygote.ProcessRequests();
592 } 511 }
OLDNEW
« no previous file with comments | « chrome/browser/zygote_host_linux.cc ('k') | chrome/chrome.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698