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