dalvik_system_Zygote.cpp revision 1663a6c12fdf4732d7ea0a0406af6085b3c408e4
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* 18 * dalvik.system.Zygote 19 */ 20#include "Dalvik.h" 21#include "native/InternalNativePriv.h" 22 23#include <signal.h> 24#include <sys/types.h> 25#include <sys/wait.h> 26#include <grp.h> 27#include <errno.h> 28#include <paths.h> 29 30#if defined(HAVE_PRCTL) 31# include <sys/prctl.h> 32#endif 33 34#define ZYGOTE_LOG_TAG "Zygote" 35 36/* must match values in dalvik.system.Zygote */ 37enum { 38 DEBUG_ENABLE_DEBUGGER = 1, 39 DEBUG_ENABLE_CHECKJNI = 1 << 1, 40 DEBUG_ENABLE_ASSERT = 1 << 2, 41 DEBUG_ENABLE_SAFEMODE = 1 << 3, 42 DEBUG_ENABLE_JNI_LOGGING = 1 << 4, 43}; 44 45/* 46 * This signal handler is for zygote mode, since the zygote 47 * must reap its children 48 */ 49static void sigchldHandler(int s) 50{ 51 pid_t pid; 52 int status; 53 54 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 55 /* Log process-death status that we care about. In general it is not 56 safe to call ALOG(...) from a signal handler because of possible 57 reentrancy. However, we know a priori that the current implementation 58 of ALOG() is safe to call from a SIGCHLD handler in the zygote process. 59 If the ALOG() implementation changes its locking strategy or its use 60 of syscalls within the lazy-init critical section, its use here may 61 become unsafe. */ 62 if (WIFEXITED(status)) { 63 if (WEXITSTATUS(status)) { 64 ALOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)", 65 (int) pid, WEXITSTATUS(status)); 66 } else { 67 IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) { 68 ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, 69 "Process %d exited cleanly (%d)", 70 (int) pid, WEXITSTATUS(status)); 71 } 72 } 73 } else if (WIFSIGNALED(status)) { 74 if (WTERMSIG(status) != SIGKILL) { 75 ALOG(LOG_DEBUG, ZYGOTE_LOG_TAG, 76 "Process %d terminated by signal (%d)", 77 (int) pid, WTERMSIG(status)); 78 } else { 79 IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) { 80 ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, 81 "Process %d terminated by signal (%d)", 82 (int) pid, WTERMSIG(status)); 83 } 84 } 85#ifdef WCOREDUMP 86 if (WCOREDUMP(status)) { 87 ALOG(LOG_INFO, ZYGOTE_LOG_TAG, "Process %d dumped core", 88 (int) pid); 89 } 90#endif /* ifdef WCOREDUMP */ 91 } 92 93 /* 94 * If the just-crashed process is the system_server, bring down zygote 95 * so that it is restarted by init and system server will be restarted 96 * from there. 97 */ 98 if (pid == gDvm.systemServerPid) { 99 ALOG(LOG_INFO, ZYGOTE_LOG_TAG, 100 "Exit zygote because system server (%d) has terminated", 101 (int) pid); 102 kill(getpid(), SIGKILL); 103 } 104 } 105 106 if (pid < 0) { 107 ALOG(LOG_WARN, ZYGOTE_LOG_TAG, 108 "Zygote SIGCHLD error in waitpid: %s",strerror(errno)); 109 } 110} 111 112/* 113 * configure sigchld handler for the zygote process 114 * This is configured very late, because earlier in the dalvik lifecycle 115 * we can fork() and exec() for the verifier/optimizer, and we 116 * want to waitpid() for those rather than have them be harvested immediately. 117 * 118 * This ends up being called repeatedly before each fork(), but there's 119 * no real harm in that. 120 */ 121static void setSignalHandler() 122{ 123 int err; 124 struct sigaction sa; 125 126 memset(&sa, 0, sizeof(sa)); 127 128 sa.sa_handler = sigchldHandler; 129 130 err = sigaction (SIGCHLD, &sa, NULL); 131 132 if (err < 0) { 133 LOGW("Error setting SIGCHLD handler: %s", strerror(errno)); 134 } 135} 136 137/* 138 * Set the SIGCHLD handler back to default behavior in zygote children 139 */ 140static void unsetSignalHandler() 141{ 142 int err; 143 struct sigaction sa; 144 145 memset(&sa, 0, sizeof(sa)); 146 147 sa.sa_handler = SIG_DFL; 148 149 err = sigaction (SIGCHLD, &sa, NULL); 150 151 if (err < 0) { 152 LOGW("Error unsetting SIGCHLD handler: %s", strerror(errno)); 153 } 154} 155 156/* 157 * Calls POSIX setgroups() using the int[] object as an argument. 158 * A NULL argument is tolerated. 159 */ 160 161static int setgroupsIntarray(ArrayObject* gidArray) 162{ 163 gid_t *gids; 164 u4 i; 165 s4 *contents; 166 167 if (gidArray == NULL) { 168 return 0; 169 } 170 171 /* just in case gid_t and u4 are different... */ 172 gids = (gid_t *)alloca(sizeof(gid_t) * gidArray->length); 173 contents = (s4 *)(void *)gidArray->contents; 174 175 for (i = 0 ; i < gidArray->length ; i++) { 176 gids[i] = (gid_t) contents[i]; 177 } 178 179 return setgroups((size_t) gidArray->length, gids); 180} 181 182/* 183 * Sets the resource limits via setrlimit(2) for the values in the 184 * two-dimensional array of integers that's passed in. The second dimension 185 * contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is 186 * treated as an empty array. 187 * 188 * -1 is returned on error. 189 */ 190static int setrlimitsFromArray(ArrayObject* rlimits) 191{ 192 u4 i; 193 struct rlimit rlim; 194 195 if (rlimits == NULL) { 196 return 0; 197 } 198 199 memset (&rlim, 0, sizeof(rlim)); 200 201 ArrayObject** tuples = (ArrayObject **)(void *)rlimits->contents; 202 203 for (i = 0; i < rlimits->length; i++) { 204 ArrayObject * rlimit_tuple = tuples[i]; 205 s4* contents = (s4 *)(void *)rlimit_tuple->contents; 206 int err; 207 208 if (rlimit_tuple->length != 3) { 209 LOGE("rlimits array must have a second dimension of size 3"); 210 return -1; 211 } 212 213 rlim.rlim_cur = contents[1]; 214 rlim.rlim_max = contents[2]; 215 216 err = setrlimit(contents[0], &rlim); 217 218 if (err < 0) { 219 return -1; 220 } 221 } 222 223 return 0; 224} 225 226/* native public static int fork(); */ 227static void Dalvik_dalvik_system_Zygote_fork(const u4* args, JValue* pResult) 228{ 229 pid_t pid; 230 231 if (!gDvm.zygote) { 232 dvmThrowIllegalStateException( 233 "VM instance not started with -Xzygote"); 234 235 RETURN_VOID(); 236 } 237 238 if (!dvmGcPreZygoteFork()) { 239 LOGE("pre-fork heap failed"); 240 dvmAbort(); 241 } 242 243 setSignalHandler(); 244 245 dvmDumpLoaderStats("zygote"); 246 pid = fork(); 247 248#ifdef HAVE_ANDROID_OS 249 if (pid == 0) { 250 /* child process */ 251 extern int gMallocLeakZygoteChild; 252 gMallocLeakZygoteChild = 1; 253 } 254#endif 255 256 RETURN_INT(pid); 257} 258 259/* 260 * Enable/disable debug features requested by the caller. 261 * 262 * debugger 263 * If set, enable debugging; if not set, disable debugging. This is 264 * easy to handle, because the JDWP thread isn't started until we call 265 * dvmInitAfterZygote(). 266 * checkjni 267 * If set, make sure "check JNI" is enabled. 268 * assert 269 * If set, make sure assertions are enabled. This gets fairly weird, 270 * because it affects the result of a method called by class initializers, 271 * and hence can't affect pre-loaded/initialized classes. 272 * safemode 273 * If set, operates the VM in the safe mode. The definition of "safe mode" is 274 * implementation dependent and currently only the JIT compiler is disabled. 275 * This is easy to handle because the compiler thread and associated resources 276 * are not requested until we call dvmInitAfterZygote(). 277 */ 278static void enableDebugFeatures(u4 debugFlags) 279{ 280 LOGV("debugFlags is 0x%02x", debugFlags); 281 282 gDvm.jdwpAllowed = ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0); 283 284 if ((debugFlags & DEBUG_ENABLE_CHECKJNI) != 0) { 285 /* turn it on if it's not already enabled */ 286 dvmLateEnableCheckedJni(); 287 } 288 289 if ((debugFlags & DEBUG_ENABLE_JNI_LOGGING) != 0) { 290 gDvmJni.logThirdPartyJni = true; 291 } 292 293 if ((debugFlags & DEBUG_ENABLE_ASSERT) != 0) { 294 /* turn it on if it's not already enabled */ 295 dvmLateEnableAssertions(); 296 } 297 298 if ((debugFlags & DEBUG_ENABLE_SAFEMODE) != 0) { 299#if defined(WITH_JIT) 300 /* turn off the jit if it is explicitly requested by the app */ 301 if (gDvm.executionMode == kExecutionModeJit) 302 gDvm.executionMode = kExecutionModeInterpFast; 303#endif 304 } 305 306#ifdef HAVE_ANDROID_OS 307 if ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0) { 308 /* To let a non-privileged gdbserver attach to this 309 * process, we must set its dumpable bit flag. However 310 * we are not interested in generating a coredump in 311 * case of a crash, so also set the coredump size to 0 312 * to disable that 313 */ 314 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) { 315 LOGE("could not set dumpable bit flag for pid %d: %s", 316 getpid(), strerror(errno)); 317 } else { 318 struct rlimit rl; 319 rl.rlim_cur = 0; 320 rl.rlim_max = RLIM_INFINITY; 321 if (setrlimit(RLIMIT_CORE, &rl) < 0) { 322 LOGE("could not disable core file generation for pid %d: %s", 323 getpid(), strerror(errno)); 324 } 325 } 326 } 327#endif 328} 329 330/* 331 * Set Linux capability flags. 332 * 333 * Returns 0 on success, errno on failure. 334 */ 335static int setCapabilities(int64_t permitted, int64_t effective) 336{ 337#ifdef HAVE_ANDROID_OS 338 struct __user_cap_header_struct capheader; 339 struct __user_cap_data_struct capdata; 340 341 memset(&capheader, 0, sizeof(capheader)); 342 memset(&capdata, 0, sizeof(capdata)); 343 344 capheader.version = _LINUX_CAPABILITY_VERSION; 345 capheader.pid = 0; 346 347 capdata.effective = effective; 348 capdata.permitted = permitted; 349 350 LOGV("CAPSET perm=%llx eff=%llx", permitted, effective); 351 if (capset(&capheader, &capdata) != 0) 352 return errno; 353#endif /*HAVE_ANDROID_OS*/ 354 355 return 0; 356} 357 358/* 359 * Utility routine to fork zygote and specialize the child process. 360 */ 361static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) 362{ 363 pid_t pid; 364 365 uid_t uid = (uid_t) args[0]; 366 gid_t gid = (gid_t) args[1]; 367 ArrayObject* gids = (ArrayObject *)args[2]; 368 u4 debugFlags = args[3]; 369 ArrayObject *rlimits = (ArrayObject *)args[4]; 370 int64_t permittedCapabilities, effectiveCapabilities; 371 372 if (isSystemServer) { 373 /* 374 * Don't use GET_ARG_LONG here for now. gcc is generating code 375 * that uses register d8 as a temporary, and that's coming out 376 * scrambled in the child process. b/3138621 377 */ 378 //permittedCapabilities = GET_ARG_LONG(args, 5); 379 //effectiveCapabilities = GET_ARG_LONG(args, 7); 380 permittedCapabilities = args[5] | (int64_t) args[6] << 32; 381 effectiveCapabilities = args[7] | (int64_t) args[8] << 32; 382 } else { 383 permittedCapabilities = effectiveCapabilities = 0; 384 } 385 386 if (!gDvm.zygote) { 387 dvmThrowIllegalStateException( 388 "VM instance not started with -Xzygote"); 389 390 return -1; 391 } 392 393 if (!dvmGcPreZygoteFork()) { 394 LOGE("pre-fork heap failed"); 395 dvmAbort(); 396 } 397 398 setSignalHandler(); 399 400 dvmDumpLoaderStats("zygote"); 401 pid = fork(); 402 403 if (pid == 0) { 404 int err; 405 /* The child process */ 406 407#ifdef HAVE_ANDROID_OS 408 extern int gMallocLeakZygoteChild; 409 gMallocLeakZygoteChild = 1; 410 411 /* keep caps across UID change, unless we're staying root */ 412 if (uid != 0) { 413 err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 414 415 if (err < 0) { 416 LOGE("cannot PR_SET_KEEPCAPS: %s", strerror(errno)); 417 dvmAbort(); 418 } 419 } 420 421#endif /* HAVE_ANDROID_OS */ 422 423 err = setgroupsIntarray(gids); 424 425 if (err < 0) { 426 LOGE("cannot setgroups(): %s", strerror(errno)); 427 dvmAbort(); 428 } 429 430 err = setrlimitsFromArray(rlimits); 431 432 if (err < 0) { 433 LOGE("cannot setrlimit(): %s", strerror(errno)); 434 dvmAbort(); 435 } 436 437 err = setgid(gid); 438 if (err < 0) { 439 LOGE("cannot setgid(%d): %s", gid, strerror(errno)); 440 dvmAbort(); 441 } 442 443 err = setuid(uid); 444 if (err < 0) { 445 LOGE("cannot setuid(%d): %s", uid, strerror(errno)); 446 dvmAbort(); 447 } 448 449 err = setCapabilities(permittedCapabilities, effectiveCapabilities); 450 if (err != 0) { 451 LOGE("cannot set capabilities (%llx,%llx): %s", 452 permittedCapabilities, effectiveCapabilities, strerror(err)); 453 dvmAbort(); 454 } 455 456 /* 457 * Our system thread ID has changed. Get the new one. 458 */ 459 Thread* thread = dvmThreadSelf(); 460 thread->systemTid = dvmGetSysThreadId(); 461 462 /* configure additional debug options */ 463 enableDebugFeatures(debugFlags); 464 465 unsetSignalHandler(); 466 gDvm.zygote = false; 467 if (!dvmInitAfterZygote()) { 468 LOGE("error in post-zygote initialization"); 469 dvmAbort(); 470 } 471 } else if (pid > 0) { 472 /* the parent process */ 473 } 474 475 return pid; 476} 477 478/* native public static int forkAndSpecialize(int uid, int gid, 479 * int[] gids, int debugFlags); 480 */ 481static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args, 482 JValue* pResult) 483{ 484 pid_t pid; 485 486 pid = forkAndSpecializeCommon(args, false); 487 488 RETURN_INT(pid); 489} 490 491/* native public static int forkSystemServer(int uid, int gid, 492 * int[] gids, int debugFlags, long permittedCapabilities, 493 * long effectiveCapabilities); 494 */ 495static void Dalvik_dalvik_system_Zygote_forkSystemServer( 496 const u4* args, JValue* pResult) 497{ 498 pid_t pid; 499 pid = forkAndSpecializeCommon(args, true); 500 501 /* The zygote process checks whether the child process has died or not. */ 502 if (pid > 0) { 503 int status; 504 505 LOGI("System server process %d has been created", pid); 506 gDvm.systemServerPid = pid; 507 /* There is a slight window that the system server process has crashed 508 * but it went unnoticed because we haven't published its pid yet. So 509 * we recheck here just to make sure that all is well. 510 */ 511 if (waitpid(pid, &status, WNOHANG) == pid) { 512 LOGE("System server process %d has died. Restarting Zygote!", pid); 513 kill(getpid(), SIGKILL); 514 } 515 } 516 RETURN_INT(pid); 517} 518 519/* native private static void nativeExecShell(String command); 520 */ 521static void Dalvik_dalvik_system_Zygote_execShell( 522 const u4* args, JValue* pResult) 523{ 524 StringObject* command = (StringObject*)args[0]; 525 526 const char *argp[] = {_PATH_BSHELL, "-c", NULL, NULL}; 527 argp[2] = dvmCreateCstrFromString(command); 528 529 LOGI("Exec: %s %s %s", argp[0], argp[1], argp[2]); 530 531 execv(_PATH_BSHELL, (char**)argp); 532 exit(127); 533} 534 535const DalvikNativeMethod dvm_dalvik_system_Zygote[] = { 536 { "nativeFork", "()I", 537 Dalvik_dalvik_system_Zygote_fork }, 538 { "nativeForkAndSpecialize", "(II[II[[I)I", 539 Dalvik_dalvik_system_Zygote_forkAndSpecialize }, 540 { "nativeForkSystemServer", "(II[II[[IJJ)I", 541 Dalvik_dalvik_system_Zygote_forkSystemServer }, 542 { "nativeExecShell", "(Ljava/lang/String;)V", 543 Dalvik_dalvik_system_Zygote_execShell }, 544 { NULL, NULL, NULL }, 545}; 546