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/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" 45 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 53 54 #if defined(ENABLE_WEBRTC) 55 #include "third_party/libjingle/overrides/init_webrtc.h" 56 #endif 57 58 namespace content { 59 60 // See http://code.google.com/p/chromium/wiki/LinuxZygote 61 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))); 69 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; 77 } 78 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; 87 } 88 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; 97 } 98 } 99 100 static bool g_am_zygote_or_renderer = false; 101 102 // Sandbox interception of libc calls. 103 // 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. 109 // 110 // It's for these cases that we have the following setup: 111 // 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. 117 // 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). 122 // 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. 128 // 129 // Other avenues: 130 // 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. 134 // 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. 137 138 typedef struct tm* (*LocaltimeFunction)(const time_t* timep); 139 typedef struct tm* (*LocaltimeRFunction)(const time_t* timep, 140 struct tm* result); 141 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; 147 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")); 157 158 if (!g_libc_localtime || !g_libc_localtime_r) { 159 // http://code.google.com/p/chromium/issues/detail?id=16800 160 // 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"; 168 } 169 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; 178 } 179 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"); 186 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); 199 } 200 } 201 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"); 205 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); 218 } 219 } 220 221 __attribute__ ((__visibility__("default"))) 222 struct tm* localtime_r_override(const time_t* timep, 223 struct tm* result) __asm__ ("localtime_r"); 224 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); 234 } 235 } 236 237 __attribute__ ((__visibility__("default"))) 238 struct tm* localtime64_r_override(const time_t* timep, 239 struct tm* result) __asm__ ("localtime64_r"); 240 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); 250 } 251 } 252 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; 268 269 (void)library; // Prevent release-mode warning. 270 } 271 } 272 } 273 #endif 274 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(); 279 280 base::SysInfo::AmountOfPhysicalMemory(); 281 base::SysInfo::MaxSharedMemorySize(); 282 base::SysInfo::NumberOfProcessors(); 283 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()); 289 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(); 312 } 313 314 static void CloseFdAndHandleEintr(int fd) { 315 close(fd); 316 } 317 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; 325 326 sandbox::SetuidSandboxClient* setuid_sandbox = 327 linux_sandbox->setuid_sandbox_client(); 328 329 if (!setuid_sandbox) 330 return false; 331 332 PreSandboxInit(); 333 334 // Check that the pre-sandbox initialization didn't spawn threads. 335 DCHECK(linux_sandbox->IsSingleThreaded()); 336 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; 341 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"; 347 } 348 349 if (!setuid_sandbox->ChrootMe()) 350 return false; 351 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; 364 } 365 *has_started_new_init = true; 366 } 367 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. 374 // 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. 378 // 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. 382 // 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; 392 } 393 } 394 #endif 395 } 396 397 return true; 398 } 399 400 bool ZygoteMain(const MainFunctionParams& params, 401 ZygoteForkDelegate* forkdelegate) { 402 g_am_zygote_or_renderer = true; 403 sandbox::InitLibcUrandomOverrides(); 404 405 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); 406 // This will pre-initialize the various sandboxes that need it. 407 linux_sandbox->PreinitializeSandbox(); 408 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"; 414 } 415 416 // Turn on the sandbox. 417 bool using_suid_sandbox = false; 418 bool has_started_new_init = false; 419 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; 426 } 427 428 sandbox::SetuidSandboxClient* setuid_sandbox = 429 linux_sandbox->setuid_sandbox_client(); 430 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."; 435 } 436 437 int sandbox_flags = linux_sandbox->GetStatus(); 438 439 Zygote zygote(sandbox_flags, forkdelegate); 440 // This function call can return multiple times, once per fork(). 441 return zygote.ProcessRequests(); 442 } 443 444 } // namespace content 445