Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / zygote / zygote_main_linux.cc
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.
4
5 #include "content/zygote/zygote_main.h"
6
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>
17
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"
48
49 #if defined(OS_LINUX)
50 #include <sys/epoll.h>
51 #include <sys/prctl.h>
52 #include <sys/signal.h>
53 #else
54 #include <signal.h>
55 #endif
56
57 #if defined(ENABLE_WEBRTC)
58 #include "third_party/libjingle/overrides/init_webrtc.h"
59 #endif
60
61 namespace content {
62
63 // See http://code.google.com/p/chromium/wiki/LinuxZygote
64
65 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output,
66                                         char* timezone_out,
67                                         size_t timezone_out_len) {
68   Pickle request;
69   request.WriteInt(LinuxSandbox::METHOD_LOCALTIME);
70   request.WriteString(
71       std::string(reinterpret_cast<char*>(&input), sizeof(input)));
72
73   uint8_t reply_buf[512];
74   const ssize_t r = UnixDomainSocket::SendRecvMsg(
75       GetSandboxFD(), reply_buf, sizeof(reply_buf), NULL,
76       request);
77   if (r == -1) {
78     memset(output, 0, sizeof(struct tm));
79     return;
80   }
81
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));
89     return;
90   }
91
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;
98   } else {
99     output->tm_zone = NULL;
100   }
101 }
102
103 static bool g_am_zygote_or_renderer = false;
104
105 // Sandbox interception of libc calls.
106 //
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
111 // our code.
112 //
113 // It's for these cases that we have the following setup:
114 //
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.
120 //
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).
125 //
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
130 // current module.
131 //
132 // Other avenues:
133 //
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.
137 //
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.
140
141 typedef struct tm* (*LocaltimeFunction)(const time_t* timep);
142 typedef struct tm* (*LocaltimeRFunction)(const time_t* timep,
143                                          struct tm* result);
144
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;
150
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"));
160
161   if (!g_libc_localtime || !g_libc_localtime_r) {
162     // http://code.google.com/p/chromium/issues/detail?id=16800
163     //
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";
171   }
172
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;
181 }
182
183 #if defined(MEMORY_SANITIZER)
184 void msan_unpoison_string(const char *s) {
185   if (!s) return;
186   // Can't call strlen() on an uninitialized string. Instead, unpoison byte by
187   // byte until the string is over.
188   do {
189     __msan_unpoison(s, sizeof(*s));
190   } while(*(s++));
191 }
192 #endif
193
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");
200
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));
208     return &time_struct;
209   } else {
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);
216 #endif
217     return res;
218   }
219 }
220
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");
224
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));
232     return &time_struct;
233   } else {
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);
240 #endif
241     return res;
242   }
243 }
244
245 __attribute__ ((__visibility__("default")))
246 struct tm* localtime_r_override(const time_t* timep,
247                                 struct tm* result) __asm__ ("localtime_r");
248
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);
253     return result;
254   } else {
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);
261 #endif
262     return res;
263   }
264 }
265
266 __attribute__ ((__visibility__("default")))
267 struct tm* localtime64_r_override(const time_t* timep,
268                                   struct tm* result) __asm__ ("localtime64_r");
269
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);
274     return result;
275   } else {
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);
282 #endif
283     return res;
284   }
285 }
286
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,
298                                                             &error);
299       VLOG_IF(1, !library) << "Unable to load plugin "
300                            << plugins[i].path.value() << " "
301                            << error.ToString();
302
303       (void)library;  // Prevent release-mode warning.
304     }
305   }
306 }
307 #endif
308
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() {
312   base::RandUint64();
313
314   base::SysInfo::AmountOfPhysicalMemory();
315   base::SysInfo::MaxSharedMemorySize();
316   base::SysInfo::NumberOfProcessors();
317
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());
323
324 #if defined(USE_NSS)
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).
332 #else
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?
336 #endif
337 #if defined(ENABLE_PLUGINS)
338   // Ensure access to the Pepper plugins before the sandbox is turned on.
339   PreloadPepperPlugins();
340 #endif
341 #if defined(ENABLE_WEBRTC)
342   InitializeWebRtcModule();
343 #endif
344   SkFontConfigInterface::SetGlobal(
345       new FontConfigIPC(GetSandboxFD()))->unref();
346 }
347
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);
352   if (!init_created) {
353     LOG(ERROR) << "Error creating an init process to reap zombies";
354     return false;
355   }
356   return true;
357 }
358
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());
364
365   // Use the SUID sandbox.  This still allows the seccomp sandbox to
366   // be enabled by the process later.
367
368   if (!setuid_sandbox->IsSuidSandboxUpToDate()) {
369     LOG(WARNING) <<
370         "You are using a wrong version of the setuid binary!\n"
371         "Please read "
372         "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment."
373         "\n\n";
374   }
375
376   if (!setuid_sandbox->ChrootMe())
377     return false;
378
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.";
384   }
385
386   if (getpid() == 1) {
387     // The setuid sandbox has created a new PID namespace and we need
388     // to assume the role of init.
389     CHECK(CreateInitProcessReaper());
390   }
391
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.
398   //
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.
402   //
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.
406   //
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
409   // dumpable.
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";
415       return false;
416     }
417   }
418 #endif
419
420   return true;
421 }
422
423 // If |is_suid_sandbox_child|, then make sure that the setuid sandbox is
424 // engaged.
425 static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox,
426                                  bool is_suid_sandbox_child) {
427   DCHECK(linux_sandbox);
428
429   ZygotePreSandboxInit();
430
431   // Check that the pre-sandbox initialization didn't spawn threads.
432 #if !defined(THREAD_SANITIZER)
433   DCHECK(linux_sandbox->IsSingleThreaded());
434 #endif
435
436   sandbox::SetuidSandboxClient* setuid_sandbox =
437       linux_sandbox->setuid_sandbox_client();
438
439   if (is_suid_sandbox_child) {
440     CHECK(EnterSuidSandbox(setuid_sandbox)) << "Failed to enter setuid sandbox";
441   }
442 }
443
444 bool ZygoteMain(const MainFunctionParams& params,
445                 ZygoteForkDelegate* forkdelegate) {
446   g_am_zygote_or_renderer = true;
447   sandbox::InitLibcUrandomOverrides();
448
449   LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
450   // This will pre-initialize the various sandboxes that need it.
451   linux_sandbox->PreinitializeSandbox();
452
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();
457
458     // Let the ZygoteHost know we're booting up.
459     CHECK(UnixDomainSocket::SendMsg(kZygoteSocketPairFd,
460                                     kZygoteBootMessage,
461                                     sizeof(kZygoteBootMessage),
462                                     std::vector<int>()));
463   }
464
465   if (forkdelegate != NULL) {
466     VLOG(1) << "ZygoteMain: initializing fork delegate";
467     forkdelegate->Init(GetSandboxFD(), must_enable_setuid_sandbox);
468   } else {
469     VLOG(1) << "ZygoteMain: fork delegate is NULL";
470   }
471
472   // Turn on the first layer of the sandbox if the configuration warrants it.
473   EnterLayerOneSandbox(linux_sandbox, must_enable_setuid_sandbox);
474
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);
478
479   Zygote zygote(sandbox_flags, forkdelegate);
480   // This function call can return multiple times, once per fork().
481   return zygote.ProcessRequests();
482 }
483
484 }  // namespace content