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