IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / zygote / zygote_main_linux.cc
blob8e91c2f17e5619e425f78e400cab0f67152af720
1 // Copyright (c) 2012 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.
5 #include "content/zygote/zygote_main.h"
7 #include <dlfcn.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <pthread.h>
11 #include <stdio.h>
12 #include <sys/socket.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <unistd.h>
18 #include "base/basictypes.h"
19 #include "base/bind.h"
20 #include "base/callback.h"
21 #include "base/command_line.h"
22 #include "base/linux_util.h"
23 #include "base/native_library.h"
24 #include "base/pickle.h"
25 #include "base/posix/unix_domain_socket_linux.h"
26 #include "base/rand_util.h"
27 #include "base/sys_info.h"
28 #include "build/build_config.h"
29 #include "content/common/child_process_sandbox_support_impl_linux.h"
30 #include "content/common/font_config_ipc_linux.h"
31 #include "content/common/pepper_plugin_list.h"
32 #include "content/common/sandbox_linux/sandbox_linux.h"
33 #include "content/common/zygote_commands_linux.h"
34 #include "content/public/common/content_switches.h"
35 #include "content/public/common/main_function_params.h"
36 #include "content/public/common/pepper_plugin_info.h"
37 #include "content/public/common/sandbox_linux.h"
38 #include "content/public/common/zygote_fork_delegate_linux.h"
39 #include "content/zygote/zygote_linux.h"
40 #include "crypto/nss_util.h"
41 #include "sandbox/linux/services/libc_urandom_override.h"
42 #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
43 #include "third_party/icu/source/i18n/unicode/timezone.h"
44 #include "third_party/skia/include/ports/SkFontConfigInterface.h"
46 #if defined(OS_LINUX)
47 #include <sys/epoll.h>
48 #include <sys/prctl.h>
49 #include <sys/signal.h>
50 #else
51 #include <signal.h>
52 #endif
54 #if defined(ENABLE_WEBRTC)
55 #include "third_party/libjingle/overrides/init_webrtc.h"
56 #endif
58 namespace content {
60 // See http://code.google.com/p/chromium/wiki/LinuxZygote
62 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output,
63 char* timezone_out,
64 size_t timezone_out_len) {
65 Pickle request;
66 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME);
67 request.WriteString(
68 std::string(reinterpret_cast<char*>(&input), sizeof(input)));
70 uint8_t reply_buf[512];
71 const ssize_t r = UnixDomainSocket::SendRecvMsg(
72 GetSandboxFD(), reply_buf, sizeof(reply_buf), NULL,
73 request);
74 if (r == -1) {
75 memset(output, 0, sizeof(struct tm));
76 return;
79 Pickle reply(reinterpret_cast<char*>(reply_buf), r);
80 PickleIterator iter(reply);
81 std::string result, timezone;
82 if (!reply.ReadString(&iter, &result) ||
83 !reply.ReadString(&iter, &timezone) ||
84 result.size() != sizeof(struct tm)) {
85 memset(output, 0, sizeof(struct tm));
86 return;
89 memcpy(output, result.data(), sizeof(struct tm));
90 if (timezone_out_len) {
91 const size_t copy_len = std::min(timezone_out_len - 1, timezone.size());
92 memcpy(timezone_out, timezone.data(), copy_len);
93 timezone_out[copy_len] = 0;
94 output->tm_zone = timezone_out;
95 } else {
96 output->tm_zone = NULL;
100 static bool g_am_zygote_or_renderer = false;
102 // Sandbox interception of libc calls.
104 // Because we are running in a sandbox certain libc calls will fail (localtime
105 // being the motivating example - it needs to read /etc/localtime). We need to
106 // intercept these calls and proxy them to the browser. However, these calls
107 // may come from us or from our libraries. In some cases we can't just change
108 // our code.
110 // It's for these cases that we have the following setup:
112 // We define global functions for those functions which we wish to override.
113 // Since we will be first in the dynamic resolution order, the dynamic linker
114 // will point callers to our versions of these functions. However, we have the
115 // same binary for both the browser and the renderers, which means that our
116 // overrides will apply in the browser too.
118 // The global |g_am_zygote_or_renderer| is true iff we are in a zygote or
119 // renderer process. It's set in ZygoteMain and inherited by the renderers when
120 // they fork. (This means that it'll be incorrect for global constructor
121 // functions and before ZygoteMain is called - beware).
123 // Our replacement functions can check this global and either proxy
124 // the call to the browser over the sandbox IPC
125 // (http://code.google.com/p/chromium/wiki/LinuxSandboxIPC) or they can use
126 // dlsym with RTLD_NEXT to resolve the symbol, ignoring any symbols in the
127 // current module.
129 // Other avenues:
131 // Our first attempt involved some assembly to patch the GOT of the current
132 // module. This worked, but was platform specific and doesn't catch the case
133 // where a library makes a call rather than current module.
135 // We also considered patching the function in place, but this would again by
136 // platform specific and the above technique seems to work well enough.
138 typedef struct tm* (*LocaltimeFunction)(const time_t* timep);
139 typedef struct tm* (*LocaltimeRFunction)(const time_t* timep,
140 struct tm* result);
142 static pthread_once_t g_libc_localtime_funcs_guard = PTHREAD_ONCE_INIT;
143 static LocaltimeFunction g_libc_localtime;
144 static LocaltimeFunction g_libc_localtime64;
145 static LocaltimeRFunction g_libc_localtime_r;
146 static LocaltimeRFunction g_libc_localtime64_r;
148 static void InitLibcLocaltimeFunctions() {
149 g_libc_localtime = reinterpret_cast<LocaltimeFunction>(
150 dlsym(RTLD_NEXT, "localtime"));
151 g_libc_localtime64 = reinterpret_cast<LocaltimeFunction>(
152 dlsym(RTLD_NEXT, "localtime64"));
153 g_libc_localtime_r = reinterpret_cast<LocaltimeRFunction>(
154 dlsym(RTLD_NEXT, "localtime_r"));
155 g_libc_localtime64_r = reinterpret_cast<LocaltimeRFunction>(
156 dlsym(RTLD_NEXT, "localtime64_r"));
158 if (!g_libc_localtime || !g_libc_localtime_r) {
159 // http://code.google.com/p/chromium/issues/detail?id=16800
161 // Nvidia's libGL.so overrides dlsym for an unknown reason and replaces
162 // it with a version which doesn't work. In this case we'll get a NULL
163 // result. There's not a lot we can do at this point, so we just bodge it!
164 LOG(ERROR) << "Your system is broken: dlsym doesn't work! This has been "
165 "reported to be caused by Nvidia's libGL. You should expect"
166 " time related functions to misbehave. "
167 "http://code.google.com/p/chromium/issues/detail?id=16800";
170 if (!g_libc_localtime)
171 g_libc_localtime = gmtime;
172 if (!g_libc_localtime64)
173 g_libc_localtime64 = g_libc_localtime;
174 if (!g_libc_localtime_r)
175 g_libc_localtime_r = gmtime_r;
176 if (!g_libc_localtime64_r)
177 g_libc_localtime64_r = g_libc_localtime_r;
180 // Define localtime_override() function with asm name "localtime", so that all
181 // references to localtime() will resolve to this function. Notice that we need
182 // to set visibility attribute to "default" to export the symbol, as it is set
183 // to "hidden" by default in chrome per build/common.gypi.
184 __attribute__ ((__visibility__("default")))
185 struct tm* localtime_override(const time_t* timep) __asm__ ("localtime");
187 __attribute__ ((__visibility__("default")))
188 struct tm* localtime_override(const time_t* timep) {
189 if (g_am_zygote_or_renderer) {
190 static struct tm time_struct;
191 static char timezone_string[64];
192 ProxyLocaltimeCallToBrowser(*timep, &time_struct, timezone_string,
193 sizeof(timezone_string));
194 return &time_struct;
195 } else {
196 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard,
197 InitLibcLocaltimeFunctions));
198 return g_libc_localtime(timep);
202 // Use same trick to override localtime64(), localtime_r() and localtime64_r().
203 __attribute__ ((__visibility__("default")))
204 struct tm* localtime64_override(const time_t* timep) __asm__ ("localtime64");
206 __attribute__ ((__visibility__("default")))
207 struct tm* localtime64_override(const time_t* timep) {
208 if (g_am_zygote_or_renderer) {
209 static struct tm time_struct;
210 static char timezone_string[64];
211 ProxyLocaltimeCallToBrowser(*timep, &time_struct, timezone_string,
212 sizeof(timezone_string));
213 return &time_struct;
214 } else {
215 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard,
216 InitLibcLocaltimeFunctions));
217 return g_libc_localtime64(timep);
221 __attribute__ ((__visibility__("default")))
222 struct tm* localtime_r_override(const time_t* timep,
223 struct tm* result) __asm__ ("localtime_r");
225 __attribute__ ((__visibility__("default")))
226 struct tm* localtime_r_override(const time_t* timep, struct tm* result) {
227 if (g_am_zygote_or_renderer) {
228 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0);
229 return result;
230 } else {
231 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard,
232 InitLibcLocaltimeFunctions));
233 return g_libc_localtime_r(timep, result);
237 __attribute__ ((__visibility__("default")))
238 struct tm* localtime64_r_override(const time_t* timep,
239 struct tm* result) __asm__ ("localtime64_r");
241 __attribute__ ((__visibility__("default")))
242 struct tm* localtime64_r_override(const time_t* timep, struct tm* result) {
243 if (g_am_zygote_or_renderer) {
244 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0);
245 return result;
246 } else {
247 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard,
248 InitLibcLocaltimeFunctions));
249 return g_libc_localtime64_r(timep, result);
253 #if defined(ENABLE_PLUGINS)
254 // Loads the (native) libraries but does not initialize them (i.e., does not
255 // call PPP_InitializeModule). This is needed by the zygote on Linux to get
256 // access to the plugins before entering the sandbox.
257 void PreloadPepperPlugins() {
258 std::vector<PepperPluginInfo> plugins;
259 ComputePepperPluginList(&plugins);
260 for (size_t i = 0; i < plugins.size(); ++i) {
261 if (!plugins[i].is_internal && plugins[i].is_sandboxed) {
262 std::string error;
263 base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path,
264 &error);
265 VLOG_IF(1, !library) << "Unable to load plugin "
266 << plugins[i].path.value() << " "
267 << error;
269 (void)library; // Prevent release-mode warning.
273 #endif
275 // This function triggers the static and lazy construction of objects that need
276 // to be created before imposing the sandbox.
277 static void PreSandboxInit() {
278 base::RandUint64();
280 base::SysInfo::AmountOfPhysicalMemory();
281 base::SysInfo::MaxSharedMemorySize();
282 base::SysInfo::NumberOfProcessors();
284 // ICU DateFormat class (used in base/time_format.cc) needs to get the
285 // Olson timezone ID by accessing the zoneinfo files on disk. After
286 // TimeZone::createDefault is called once here, the timezone ID is
287 // cached and there's no more need to access the file system.
288 scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
290 #if defined(USE_NSS)
291 // NSS libraries are loaded before sandbox is activated. This is to allow
292 // successful initialization of NSS which tries to load extra library files.
293 crypto::LoadNSSLibraries();
294 #elif defined(USE_OPENSSL)
295 // OpenSSL is intentionally not supported in the sandboxed processes, see
296 // http://crbug.com/99163. If that ever changes we'll likely need to init
297 // OpenSSL here (at least, load the library and error strings).
298 #else
299 // It's possible that another hypothetical crypto stack would not require
300 // pre-sandbox init, but more likely this is just a build configuration error.
301 #error Which SSL library are you using?
302 #endif
303 #if defined(ENABLE_PLUGINS)
304 // Ensure access to the Pepper plugins before the sandbox is turned on.
305 PreloadPepperPlugins();
306 #endif
307 #if defined(ENABLE_WEBRTC)
308 InitializeWebRtcModule();
309 #endif
310 SkFontConfigInterface::SetGlobal(
311 new FontConfigIPC(GetSandboxFD()))->unref();
314 static void CloseFdAndHandleEintr(int fd) {
315 close(fd);
318 // This will set the *using_suid_sandbox variable to true if the SUID sandbox
319 // is enabled. This does not necessarily exclude other types of sandboxing.
320 static bool EnterSuidSandbox(LinuxSandbox* linux_sandbox,
321 bool* using_suid_sandbox,
322 bool* has_started_new_init) {
323 *using_suid_sandbox = false;
324 *has_started_new_init = false;
326 sandbox::SetuidSandboxClient* setuid_sandbox =
327 linux_sandbox->setuid_sandbox_client();
329 if (!setuid_sandbox)
330 return false;
332 PreSandboxInit();
334 // Check that the pre-sandbox initialization didn't spawn threads.
335 DCHECK(linux_sandbox->IsSingleThreaded());
337 if (setuid_sandbox->IsSuidSandboxChild()) {
338 // Use the SUID sandbox. This still allows the seccomp sandbox to
339 // be enabled by the process later.
340 *using_suid_sandbox = true;
342 if (!setuid_sandbox->IsSuidSandboxUpToDate()) {
343 LOG(WARNING) << "You are using a wrong version of the setuid binary!\n"
344 "Please read "
345 "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment."
346 "\n\n";
349 if (!setuid_sandbox->ChrootMe())
350 return false;
352 if (getpid() == 1) {
353 // The setuid sandbox has created a new PID namespace and we need
354 // to assume the role of init.
355 // This "magic" socket must only appear in one process, so make sure
356 // it gets closed in the parent after fork().
357 base::Closure zygoteid_fd_closer =
358 base::Bind(CloseFdAndHandleEintr, kZygoteIdFd);
359 const bool init_created =
360 setuid_sandbox->CreateInitProcessReaper(&zygoteid_fd_closer);
361 if (!init_created) {
362 LOG(ERROR) << "Error creating an init process to reap zombies";
363 return false;
365 *has_started_new_init = true;
368 #if !defined(OS_OPENBSD)
369 // Previously, we required that the binary be non-readable. This causes the
370 // kernel to mark the process as non-dumpable at startup. The thinking was
371 // that, although we were putting the renderers into a PID namespace (with
372 // the SUID sandbox), they would nonetheless be in the /same/ PID
373 // namespace. So they could ptrace each other unless they were non-dumpable.
375 // If the binary was readable, then there would be a window between process
376 // startup and the point where we set the non-dumpable flag in which a
377 // compromised renderer could ptrace attach.
379 // However, now that we have a zygote model, only the (trusted) zygote
380 // exists at this point and we can set the non-dumpable flag which is
381 // inherited by all our renderer children.
383 // Note: a non-dumpable process can't be debugged. To debug sandbox-related
384 // issues, one can specify --allow-sandbox-debugging to let the process be
385 // dumpable.
386 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
387 if (!command_line.HasSwitch(switches::kAllowSandboxDebugging)) {
388 prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
389 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
390 LOG(ERROR) << "Failed to set non-dumpable flag";
391 return false;
394 #endif
397 return true;
400 bool ZygoteMain(const MainFunctionParams& params,
401 ZygoteForkDelegate* forkdelegate) {
402 g_am_zygote_or_renderer = true;
403 sandbox::InitLibcUrandomOverrides();
405 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
406 // This will pre-initialize the various sandboxes that need it.
407 linux_sandbox->PreinitializeSandbox();
409 if (forkdelegate != NULL) {
410 VLOG(1) << "ZygoteMain: initializing fork delegate";
411 forkdelegate->Init(GetSandboxFD());
412 } else {
413 VLOG(1) << "ZygoteMain: fork delegate is NULL";
416 // Turn on the sandbox.
417 bool using_suid_sandbox = false;
418 bool has_started_new_init = false;
420 if (!EnterSuidSandbox(linux_sandbox,
421 &using_suid_sandbox,
422 &has_started_new_init)) {
423 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: "
424 << errno << ")";
425 return false;
428 sandbox::SetuidSandboxClient* setuid_sandbox =
429 linux_sandbox->setuid_sandbox_client();
431 if (setuid_sandbox->IsInNewPIDNamespace() && !has_started_new_init) {
432 LOG(ERROR) << "The SUID sandbox created a new PID namespace but Zygote "
433 "is not the init process. Please, make sure the SUID "
434 "binary is up to date.";
437 int sandbox_flags = linux_sandbox->GetStatus();
439 Zygote zygote(sandbox_flags, forkdelegate);
440 // This function call can return multiple times, once per fork().
441 return zygote.ProcessRequests();
444 } // namespace content