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"
12 #include <sys/socket.h>
14 #include <sys/types.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/compiler_specific.h"
23 #include "base/linux_util.h"
24 #include "base/native_library.h"
25 #include "base/pickle.h"
26 #include "base/posix/eintr_wrapper.h"
27 #include "base/posix/unix_domain_socket_linux.h"
28 #include "base/rand_util.h"
29 #include "base/sys_info.h"
30 #include "build/build_config.h"
31 #include "content/common/child_process_sandbox_support_impl_linux.h"
32 #include "content/common/font_config_ipc_linux.h"
33 #include "content/common/pepper_plugin_list.h"
34 #include "content/common/sandbox_linux/sandbox_linux.h"
35 #include "content/common/zygote_commands_linux.h"
36 #include "content/public/common/content_switches.h"
37 #include "content/public/common/main_function_params.h"
38 #include "content/public/common/pepper_plugin_info.h"
39 #include "content/public/common/sandbox_linux.h"
40 #include "content/public/common/zygote_fork_delegate_linux.h"
41 #include "content/zygote/zygote_linux.h"
42 #include "crypto/nss_util.h"
43 #include "sandbox/linux/services/init_process_reaper.h"
44 #include "sandbox/linux/services/libc_urandom_override.h"
45 #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
46 #include "third_party/icu/source/i18n/unicode/timezone.h"
47 #include "third_party/skia/include/ports/SkFontConfigInterface.h"
50 #include <sys/epoll.h>
51 #include <sys/prctl.h>
52 #include <sys/signal.h>
57 #if defined(ENABLE_WEBRTC)
58 #include "third_party/libjingle/overrides/init_webrtc.h"
63 // See http://code.google.com/p/chromium/wiki/LinuxZygote
65 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output,
67 size_t timezone_out_len) {
69 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME);
71 std::string(reinterpret_cast<char*>(&input), sizeof(input)));
73 uint8_t reply_buf[512];
74 const ssize_t r = UnixDomainSocket::SendRecvMsg(
75 GetSandboxFD(), reply_buf, sizeof(reply_buf), NULL,
78 memset(output, 0, sizeof(struct tm));
82 Pickle reply(reinterpret_cast<char*>(reply_buf), r);
83 PickleIterator iter(reply);
84 std::string result, timezone;
85 if (!reply.ReadString(&iter, &result) ||
86 !reply.ReadString(&iter, &timezone) ||
87 result.size() != sizeof(struct tm)) {
88 memset(output, 0, sizeof(struct tm));
92 memcpy(output, result.data(), sizeof(struct tm));
93 if (timezone_out_len) {
94 const size_t copy_len = std::min(timezone_out_len - 1, timezone.size());
95 memcpy(timezone_out, timezone.data(), copy_len);
96 timezone_out[copy_len] = 0;
97 output->tm_zone = timezone_out;
99 output->tm_zone = NULL;
103 static bool g_am_zygote_or_renderer = false;
105 // Sandbox interception of libc calls.
107 // Because we are running in a sandbox certain libc calls will fail (localtime
108 // being the motivating example - it needs to read /etc/localtime). We need to
109 // intercept these calls and proxy them to the browser. However, these calls
110 // may come from us or from our libraries. In some cases we can't just change
113 // It's for these cases that we have the following setup:
115 // We define global functions for those functions which we wish to override.
116 // Since we will be first in the dynamic resolution order, the dynamic linker
117 // will point callers to our versions of these functions. However, we have the
118 // same binary for both the browser and the renderers, which means that our
119 // overrides will apply in the browser too.
121 // The global |g_am_zygote_or_renderer| is true iff we are in a zygote or
122 // renderer process. It's set in ZygoteMain and inherited by the renderers when
123 // they fork. (This means that it'll be incorrect for global constructor
124 // functions and before ZygoteMain is called - beware).
126 // Our replacement functions can check this global and either proxy
127 // the call to the browser over the sandbox IPC
128 // (http://code.google.com/p/chromium/wiki/LinuxSandboxIPC) or they can use
129 // dlsym with RTLD_NEXT to resolve the symbol, ignoring any symbols in the
134 // Our first attempt involved some assembly to patch the GOT of the current
135 // module. This worked, but was platform specific and doesn't catch the case
136 // where a library makes a call rather than current module.
138 // We also considered patching the function in place, but this would again by
139 // platform specific and the above technique seems to work well enough.
141 typedef struct tm* (*LocaltimeFunction)(const time_t* timep);
142 typedef struct tm* (*LocaltimeRFunction)(const time_t* timep,
145 static pthread_once_t g_libc_localtime_funcs_guard = PTHREAD_ONCE_INIT;
146 static LocaltimeFunction g_libc_localtime;
147 static LocaltimeFunction g_libc_localtime64;
148 static LocaltimeRFunction g_libc_localtime_r;
149 static LocaltimeRFunction g_libc_localtime64_r;
151 static void InitLibcLocaltimeFunctions() {
152 g_libc_localtime = reinterpret_cast<LocaltimeFunction>(
153 dlsym(RTLD_NEXT, "localtime"));
154 g_libc_localtime64 = reinterpret_cast<LocaltimeFunction>(
155 dlsym(RTLD_NEXT, "localtime64"));
156 g_libc_localtime_r = reinterpret_cast<LocaltimeRFunction>(
157 dlsym(RTLD_NEXT, "localtime_r"));
158 g_libc_localtime64_r = reinterpret_cast<LocaltimeRFunction>(
159 dlsym(RTLD_NEXT, "localtime64_r"));
161 if (!g_libc_localtime || !g_libc_localtime_r) {
162 // http://code.google.com/p/chromium/issues/detail?id=16800
164 // Nvidia's libGL.so overrides dlsym for an unknown reason and replaces
165 // it with a version which doesn't work. In this case we'll get a NULL
166 // result. There's not a lot we can do at this point, so we just bodge it!
167 LOG(ERROR) << "Your system is broken: dlsym doesn't work! This has been "
168 "reported to be caused by Nvidia's libGL. You should expect"
169 " time related functions to misbehave. "
170 "http://code.google.com/p/chromium/issues/detail?id=16800";
173 if (!g_libc_localtime)
174 g_libc_localtime = gmtime;
175 if (!g_libc_localtime64)
176 g_libc_localtime64 = g_libc_localtime;
177 if (!g_libc_localtime_r)
178 g_libc_localtime_r = gmtime_r;
179 if (!g_libc_localtime64_r)
180 g_libc_localtime64_r = g_libc_localtime_r;
183 #if defined(MEMORY_SANITIZER)
184 void msan_unpoison_string(const char *s) {
186 // Can't call strlen() on an uninitialized string. Instead, unpoison byte by
187 // byte until the string is over.
189 __msan_unpoison(s, sizeof(*s));
194 // Define localtime_override() function with asm name "localtime", so that all
195 // references to localtime() will resolve to this function. Notice that we need
196 // to set visibility attribute to "default" to export the symbol, as it is set
197 // to "hidden" by default in chrome per build/common.gypi.
198 __attribute__ ((__visibility__("default")))
199 struct tm* localtime_override(const time_t* timep) __asm__ ("localtime");
201 __attribute__ ((__visibility__("default")))
202 struct tm* localtime_override(const time_t* timep) {
203 if (g_am_zygote_or_renderer) {
204 static struct tm time_struct;
205 static char timezone_string[64];
206 ProxyLocaltimeCallToBrowser(*timep, &time_struct, timezone_string,
207 sizeof(timezone_string));
210 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard,
211 InitLibcLocaltimeFunctions));
212 struct tm* res = g_libc_localtime(timep);
213 #if defined(MEMORY_SANITIZER)
214 if (res) __msan_unpoison(res, sizeof(*res));
215 if (res->tm_zone) msan_unpoison_string(res->tm_zone);
221 // Use same trick to override localtime64(), localtime_r() and localtime64_r().
222 __attribute__ ((__visibility__("default")))
223 struct tm* localtime64_override(const time_t* timep) __asm__ ("localtime64");
225 __attribute__ ((__visibility__("default")))
226 struct tm* localtime64_override(const time_t* timep) {
227 if (g_am_zygote_or_renderer) {
228 static struct tm time_struct;
229 static char timezone_string[64];
230 ProxyLocaltimeCallToBrowser(*timep, &time_struct, timezone_string,
231 sizeof(timezone_string));
234 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard,
235 InitLibcLocaltimeFunctions));
236 struct tm* res = g_libc_localtime64(timep);
237 #if defined(MEMORY_SANITIZER)
238 if (res) __msan_unpoison(res, sizeof(*res));
239 if (res->tm_zone) msan_unpoison_string(res->tm_zone);
245 __attribute__ ((__visibility__("default")))
246 struct tm* localtime_r_override(const time_t* timep,
247 struct tm* result) __asm__ ("localtime_r");
249 __attribute__ ((__visibility__("default")))
250 struct tm* localtime_r_override(const time_t* timep, struct tm* result) {
251 if (g_am_zygote_or_renderer) {
252 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0);
255 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard,
256 InitLibcLocaltimeFunctions));
257 struct tm* res = g_libc_localtime_r(timep, result);
258 #if defined(MEMORY_SANITIZER)
259 if (res) __msan_unpoison(res, sizeof(*res));
260 if (res->tm_zone) msan_unpoison_string(res->tm_zone);
266 __attribute__ ((__visibility__("default")))
267 struct tm* localtime64_r_override(const time_t* timep,
268 struct tm* result) __asm__ ("localtime64_r");
270 __attribute__ ((__visibility__("default")))
271 struct tm* localtime64_r_override(const time_t* timep, struct tm* result) {
272 if (g_am_zygote_or_renderer) {
273 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0);
276 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard,
277 InitLibcLocaltimeFunctions));
278 struct tm* res = g_libc_localtime64_r(timep, result);
279 #if defined(MEMORY_SANITIZER)
280 if (res) __msan_unpoison(res, sizeof(*res));
281 if (res->tm_zone) msan_unpoison_string(res->tm_zone);
287 #if defined(ENABLE_PLUGINS)
288 // Loads the (native) libraries but does not initialize them (i.e., does not
289 // call PPP_InitializeModule). This is needed by the zygote on Linux to get
290 // access to the plugins before entering the sandbox.
291 void PreloadPepperPlugins() {
292 std::vector<PepperPluginInfo> plugins;
293 ComputePepperPluginList(&plugins);
294 for (size_t i = 0; i < plugins.size(); ++i) {
295 if (!plugins[i].is_internal && plugins[i].is_sandboxed) {
296 base::NativeLibraryLoadError error;
297 base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path,
299 VLOG_IF(1, !library) << "Unable to load plugin "
300 << plugins[i].path.value() << " "
303 (void)library; // Prevent release-mode warning.
309 // This function triggers the static and lazy construction of objects that need
310 // to be created before imposing the sandbox.
311 static void ZygotePreSandboxInit() {
314 base::SysInfo::AmountOfPhysicalMemory();
315 base::SysInfo::MaxSharedMemorySize();
316 base::SysInfo::NumberOfProcessors();
318 // ICU DateFormat class (used in base/time_format.cc) needs to get the
319 // Olson timezone ID by accessing the zoneinfo files on disk. After
320 // TimeZone::createDefault is called once here, the timezone ID is
321 // cached and there's no more need to access the file system.
322 scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
325 // NSS libraries are loaded before sandbox is activated. This is to allow
326 // successful initialization of NSS which tries to load extra library files.
327 crypto::LoadNSSLibraries();
328 #elif defined(USE_OPENSSL)
329 // OpenSSL is intentionally not supported in the sandboxed processes, see
330 // http://crbug.com/99163. If that ever changes we'll likely need to init
331 // OpenSSL here (at least, load the library and error strings).
333 // It's possible that another hypothetical crypto stack would not require
334 // pre-sandbox init, but more likely this is just a build configuration error.
335 #error Which SSL library are you using?
337 #if defined(ENABLE_PLUGINS)
338 // Ensure access to the Pepper plugins before the sandbox is turned on.
339 PreloadPepperPlugins();
341 #if defined(ENABLE_WEBRTC)
342 InitializeWebRtcModule();
344 SkFontConfigInterface::SetGlobal(
345 new FontConfigIPC(GetSandboxFD()))->unref();
348 static bool CreateInitProcessReaper() {
349 // The current process becomes init(1), this function returns from a
350 // newly created process.
351 const bool init_created = sandbox::CreateInitProcessReaper(NULL);
353 LOG(ERROR) << "Error creating an init process to reap zombies";
359 // Enter the setuid sandbox. This requires the current process to have been
360 // created through the setuid sandbox.
361 static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox) {
362 DCHECK(setuid_sandbox);
363 DCHECK(setuid_sandbox->IsSuidSandboxChild());
365 // Use the SUID sandbox. This still allows the seccomp sandbox to
366 // be enabled by the process later.
368 if (!setuid_sandbox->IsSuidSandboxUpToDate()) {
370 "You are using a wrong version of the setuid binary!\n"
372 "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment."
376 if (!setuid_sandbox->ChrootMe())
379 if (setuid_sandbox->IsInNewPIDNamespace()) {
380 CHECK_EQ(1, getpid())
381 << "The SUID sandbox created a new PID namespace but Zygote "
382 "is not the init process. Please, make sure the SUID "
383 "binary is up to date.";
387 // The setuid sandbox has created a new PID namespace and we need
388 // to assume the role of init.
389 CHECK(CreateInitProcessReaper());
392 #if !defined(OS_OPENBSD)
393 // Previously, we required that the binary be non-readable. This causes the
394 // kernel to mark the process as non-dumpable at startup. The thinking was
395 // that, although we were putting the renderers into a PID namespace (with
396 // the SUID sandbox), they would nonetheless be in the /same/ PID
397 // namespace. So they could ptrace each other unless they were non-dumpable.
399 // If the binary was readable, then there would be a window between process
400 // startup and the point where we set the non-dumpable flag in which a
401 // compromised renderer could ptrace attach.
403 // However, now that we have a zygote model, only the (trusted) zygote
404 // exists at this point and we can set the non-dumpable flag which is
405 // inherited by all our renderer children.
407 // Note: a non-dumpable process can't be debugged. To debug sandbox-related
408 // issues, one can specify --allow-sandbox-debugging to let the process be
410 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
411 if (!command_line.HasSwitch(switches::kAllowSandboxDebugging)) {
412 prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
413 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
414 LOG(ERROR) << "Failed to set non-dumpable flag";
423 // If |is_suid_sandbox_child|, then make sure that the setuid sandbox is
425 static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox,
426 bool is_suid_sandbox_child) {
427 DCHECK(linux_sandbox);
429 ZygotePreSandboxInit();
431 // Check that the pre-sandbox initialization didn't spawn threads.
432 #if !defined(THREAD_SANITIZER)
433 DCHECK(linux_sandbox->IsSingleThreaded());
436 sandbox::SetuidSandboxClient* setuid_sandbox =
437 linux_sandbox->setuid_sandbox_client();
439 if (is_suid_sandbox_child) {
440 CHECK(EnterSuidSandbox(setuid_sandbox)) << "Failed to enter setuid sandbox";
444 bool ZygoteMain(const MainFunctionParams& params,
445 ZygoteForkDelegate* forkdelegate) {
446 g_am_zygote_or_renderer = true;
447 sandbox::InitLibcUrandomOverrides();
449 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
450 // This will pre-initialize the various sandboxes that need it.
451 linux_sandbox->PreinitializeSandbox();
453 const bool must_enable_setuid_sandbox =
454 linux_sandbox->setuid_sandbox_client()->IsSuidSandboxChild();
455 if (must_enable_setuid_sandbox) {
456 linux_sandbox->setuid_sandbox_client()->CloseDummyFile();
458 // Let the ZygoteHost know we're booting up.
459 CHECK(UnixDomainSocket::SendMsg(kZygoteSocketPairFd,
461 sizeof(kZygoteBootMessage),
462 std::vector<int>()));
465 if (forkdelegate != NULL) {
466 VLOG(1) << "ZygoteMain: initializing fork delegate";
467 forkdelegate->Init(GetSandboxFD(), must_enable_setuid_sandbox);
469 VLOG(1) << "ZygoteMain: fork delegate is NULL";
472 // Turn on the first layer of the sandbox if the configuration warrants it.
473 EnterLayerOneSandbox(linux_sandbox, must_enable_setuid_sandbox);
475 int sandbox_flags = linux_sandbox->GetStatus();
476 bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID;
477 CHECK_EQ(must_enable_setuid_sandbox, setuid_sandbox_engaged);
479 Zygote zygote(sandbox_flags, forkdelegate);
480 // This function call can return multiple times, once per fork().
481 return zygote.ProcessRequests();
484 } // namespace content