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 <selinux/android.h> 24 25 #include <signal.h> 26 #include <sys/types.h> 27 #include <sys/wait.h> 28 #include <grp.h> 29 #include <errno.h> 30 #include <paths.h> 31 #include <sys/personality.h> 32 #include <sys/stat.h> 33 #include <sys/mount.h> 34 #include <linux/fs.h> 35 #include <cutils/fs.h> 36 #include <cutils/sched_policy.h> 37 #include <cutils/multiuser.h> 38 #include <sched.h> 39 #include <sys/utsname.h> 40 #include <sys/capability.h> 41 42 #if defined(HAVE_PRCTL) 43 # include <sys/prctl.h> 44 #endif 45 46 #define ZYGOTE_LOG_TAG "Zygote" 47 48 /* must match values in dalvik.system.Zygote */ 49 enum { 50 DEBUG_ENABLE_DEBUGGER = 1, 51 DEBUG_ENABLE_CHECKJNI = 1 << 1, 52 DEBUG_ENABLE_ASSERT = 1 << 2, 53 DEBUG_ENABLE_SAFEMODE = 1 << 3, 54 DEBUG_ENABLE_JNI_LOGGING = 1 << 4, 55 }; 56 57 /* must match values in dalvik.system.Zygote */ 58 enum { 59 MOUNT_EXTERNAL_NONE = 0, 60 MOUNT_EXTERNAL_SINGLEUSER = 1, 61 MOUNT_EXTERNAL_MULTIUSER = 2, 62 MOUNT_EXTERNAL_MULTIUSER_ALL = 3, 63 }; 64 65 /* 66 * This signal handler is for zygote mode, since the zygote 67 * must reap its children 68 */ 69 static void sigchldHandler(int s) 70 { 71 pid_t pid; 72 int status; 73 74 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 75 /* Log process-death status that we care about. In general it is not 76 safe to call ALOG(...) from a signal handler because of possible 77 reentrancy. However, we know a priori that the current implementation 78 of ALOG() is safe to call from a SIGCHLD handler in the zygote process. 79 If the ALOG() implementation changes its locking strategy or its use 80 of syscalls within the lazy-init critical section, its use here may 81 become unsafe. */ 82 if (WIFEXITED(status)) { 83 if (WEXITSTATUS(status)) { 84 ALOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)", 85 (int) pid, WEXITSTATUS(status)); 86 } else { 87 IF_ALOGV(/*should use ZYGOTE_LOG_TAG*/) { 88 ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, 89 "Process %d exited cleanly (%d)", 90 (int) pid, WEXITSTATUS(status)); 91 } 92 } 93 } else if (WIFSIGNALED(status)) { 94 if (WTERMSIG(status) != SIGKILL) { 95 ALOG(LOG_DEBUG, ZYGOTE_LOG_TAG, 96 "Process %d terminated by signal (%d)", 97 (int) pid, WTERMSIG(status)); 98 } else { 99 IF_ALOGV(/*should use ZYGOTE_LOG_TAG*/) { 100 ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, 101 "Process %d terminated by signal (%d)", 102 (int) pid, WTERMSIG(status)); 103 } 104 } 105 #ifdef WCOREDUMP 106 if (WCOREDUMP(status)) { 107 ALOG(LOG_INFO, ZYGOTE_LOG_TAG, "Process %d dumped core", 108 (int) pid); 109 } 110 #endif /* ifdef WCOREDUMP */ 111 } 112 113 /* 114 * If the just-crashed process is the system_server, bring down zygote 115 * so that it is restarted by init and system server will be restarted 116 * from there. 117 */ 118 if (pid == gDvm.systemServerPid) { 119 ALOG(LOG_INFO, ZYGOTE_LOG_TAG, 120 "Exit zygote because system server (%d) has terminated", 121 (int) pid); 122 kill(getpid(), SIGKILL); 123 } 124 } 125 126 if (pid < 0) { 127 ALOG(LOG_WARN, ZYGOTE_LOG_TAG, 128 "Zygote SIGCHLD error in waitpid: %s",strerror(errno)); 129 } 130 } 131 132 /* 133 * configure sigchld handler for the zygote process 134 * This is configured very late, because earlier in the dalvik lifecycle 135 * we can fork() and exec() for the verifier/optimizer, and we 136 * want to waitpid() for those rather than have them be harvested immediately. 137 * 138 * This ends up being called repeatedly before each fork(), but there's 139 * no real harm in that. 140 */ 141 static void setSignalHandler() 142 { 143 int err; 144 struct sigaction sa; 145 146 memset(&sa, 0, sizeof(sa)); 147 148 sa.sa_handler = sigchldHandler; 149 150 err = sigaction (SIGCHLD, &sa, NULL); 151 152 if (err < 0) { 153 ALOGW("Error setting SIGCHLD handler: %s", strerror(errno)); 154 } 155 } 156 157 /* 158 * Set the SIGCHLD handler back to default behavior in zygote children 159 */ 160 static void unsetSignalHandler() 161 { 162 int err; 163 struct sigaction sa; 164 165 memset(&sa, 0, sizeof(sa)); 166 167 sa.sa_handler = SIG_DFL; 168 169 err = sigaction (SIGCHLD, &sa, NULL); 170 171 if (err < 0) { 172 ALOGW("Error unsetting SIGCHLD handler: %s", strerror(errno)); 173 } 174 } 175 176 /* 177 * Calls POSIX setgroups() using the int[] object as an argument. 178 * A NULL argument is tolerated. 179 */ 180 181 static int setgroupsIntarray(ArrayObject* gidArray) 182 { 183 gid_t *gids; 184 u4 i; 185 s4 *contents; 186 187 if (gidArray == NULL) { 188 return 0; 189 } 190 191 /* just in case gid_t and u4 are different... */ 192 gids = (gid_t *)alloca(sizeof(gid_t) * gidArray->length); 193 contents = (s4 *)(void *)gidArray->contents; 194 195 for (i = 0 ; i < gidArray->length ; i++) { 196 gids[i] = (gid_t) contents[i]; 197 } 198 199 return setgroups((size_t) gidArray->length, gids); 200 } 201 202 /* 203 * Sets the resource limits via setrlimit(2) for the values in the 204 * two-dimensional array of integers that's passed in. The second dimension 205 * contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is 206 * treated as an empty array. 207 * 208 * -1 is returned on error. 209 */ 210 static int setrlimitsFromArray(ArrayObject* rlimits) 211 { 212 u4 i; 213 struct rlimit rlim; 214 215 if (rlimits == NULL) { 216 return 0; 217 } 218 219 memset (&rlim, 0, sizeof(rlim)); 220 221 ArrayObject** tuples = (ArrayObject **)(void *)rlimits->contents; 222 223 for (i = 0; i < rlimits->length; i++) { 224 ArrayObject * rlimit_tuple = tuples[i]; 225 s4* contents = (s4 *)(void *)rlimit_tuple->contents; 226 int err; 227 228 if (rlimit_tuple->length != 3) { 229 ALOGE("rlimits array must have a second dimension of size 3"); 230 return -1; 231 } 232 233 rlim.rlim_cur = contents[1]; 234 rlim.rlim_max = contents[2]; 235 236 err = setrlimit(contents[0], &rlim); 237 238 if (err < 0) { 239 return -1; 240 } 241 } 242 243 return 0; 244 } 245 246 /* 247 * Create a private mount namespace and bind mount appropriate emulated 248 * storage for the given user. 249 */ 250 static int mountEmulatedStorage(uid_t uid, u4 mountMode) { 251 // See storage config details at http://source.android.com/tech/storage/ 252 userid_t userid = multiuser_get_user_id(uid); 253 254 // Create a second private mount namespace for our process 255 if (unshare(CLONE_NEWNS) == -1) { 256 ALOGE("Failed to unshare(): %s", strerror(errno)); 257 return -1; 258 } 259 260 // Create bind mounts to expose external storage 261 if (mountMode == MOUNT_EXTERNAL_MULTIUSER 262 || mountMode == MOUNT_EXTERNAL_MULTIUSER_ALL) { 263 // These paths must already be created by init.rc 264 const char* source = getenv("EMULATED_STORAGE_SOURCE"); 265 const char* target = getenv("EMULATED_STORAGE_TARGET"); 266 const char* legacy = getenv("EXTERNAL_STORAGE"); 267 if (source == NULL || target == NULL || legacy == NULL) { 268 ALOGE("Storage environment undefined; unable to provide external storage"); 269 return -1; 270 } 271 272 // Prepare source paths 273 char source_user[PATH_MAX]; 274 char source_obb[PATH_MAX]; 275 char target_user[PATH_MAX]; 276 277 // /mnt/shell/emulated/0 278 snprintf(source_user, PATH_MAX, "%s/%d", source, userid); 279 // /mnt/shell/emulated/obb 280 snprintf(source_obb, PATH_MAX, "%s/obb", source); 281 // /storage/emulated/0 282 snprintf(target_user, PATH_MAX, "%s/%d", target, userid); 283 284 if (fs_prepare_dir(source_user, 0000, 0, 0) == -1 285 || fs_prepare_dir(source_obb, 0000, 0, 0) == -1 286 || fs_prepare_dir(target_user, 0000, 0, 0) == -1) { 287 return -1; 288 } 289 290 if (mountMode == MOUNT_EXTERNAL_MULTIUSER_ALL) { 291 // Mount entire external storage tree for all users 292 if (mount(source, target, NULL, MS_BIND, NULL) == -1) { 293 ALOGE("Failed to mount %s to %s: %s", source, target, strerror(errno)); 294 return -1; 295 } 296 } else { 297 // Only mount user-specific external storage 298 if (mount(source_user, target_user, NULL, MS_BIND, NULL) == -1) { 299 ALOGE("Failed to mount %s to %s: %s", source_user, target_user, strerror(errno)); 300 return -1; 301 } 302 } 303 304 // Now that user is mounted, prepare and mount OBB storage 305 // into place for current user 306 char target_android[PATH_MAX]; 307 char target_obb[PATH_MAX]; 308 309 // /storage/emulated/0/Android 310 snprintf(target_android, PATH_MAX, "%s/%d/Android", target, userid); 311 // /storage/emulated/0/Android/obb 312 snprintf(target_obb, PATH_MAX, "%s/%d/Android/obb", target, userid); 313 314 if (fs_prepare_dir(target_android, 0000, 0, 0) == -1 315 || fs_prepare_dir(target_obb, 0000, 0, 0) == -1 316 || fs_prepare_dir(legacy, 0000, 0, 0) == -1) { 317 return -1; 318 } 319 if (mount(source_obb, target_obb, NULL, MS_BIND, NULL) == -1) { 320 ALOGE("Failed to mount %s to %s: %s", source_obb, target_obb, strerror(errno)); 321 return -1; 322 } 323 324 // Finally, mount user-specific path into place for legacy users 325 if (mount(target_user, legacy, NULL, MS_BIND | MS_REC, NULL) == -1) { 326 ALOGE("Failed to mount %s to %s: %s", target_user, legacy, strerror(errno)); 327 return -1; 328 } 329 330 } else { 331 ALOGE("Mount mode %d unsupported", mountMode); 332 return -1; 333 } 334 335 return 0; 336 } 337 338 /* native public static int fork(); */ 339 static void Dalvik_dalvik_system_Zygote_fork(const u4* args, JValue* pResult) 340 { 341 pid_t pid; 342 343 if (!gDvm.zygote) { 344 dvmThrowIllegalStateException( 345 "VM instance not started with -Xzygote"); 346 347 RETURN_VOID(); 348 } 349 350 if (!dvmGcPreZygoteFork()) { 351 ALOGE("pre-fork heap failed"); 352 dvmAbort(); 353 } 354 355 setSignalHandler(); 356 357 dvmDumpLoaderStats("zygote"); 358 pid = fork(); 359 360 #ifdef HAVE_ANDROID_OS 361 if (pid == 0) { 362 /* child process */ 363 extern int gMallocLeakZygoteChild; 364 gMallocLeakZygoteChild = 1; 365 } 366 #endif 367 368 RETURN_INT(pid); 369 } 370 371 /* 372 * Enable/disable debug features requested by the caller. 373 * 374 * debugger 375 * If set, enable debugging; if not set, disable debugging. This is 376 * easy to handle, because the JDWP thread isn't started until we call 377 * dvmInitAfterZygote(). 378 * checkjni 379 * If set, make sure "check JNI" is enabled. 380 * assert 381 * If set, make sure assertions are enabled. This gets fairly weird, 382 * because it affects the result of a method called by class initializers, 383 * and hence can't affect pre-loaded/initialized classes. 384 * safemode 385 * If set, operates the VM in the safe mode. The definition of "safe mode" is 386 * implementation dependent and currently only the JIT compiler is disabled. 387 * This is easy to handle because the compiler thread and associated resources 388 * are not requested until we call dvmInitAfterZygote(). 389 */ 390 static void enableDebugFeatures(u4 debugFlags) 391 { 392 ALOGV("debugFlags is 0x%02x", debugFlags); 393 394 gDvm.jdwpAllowed = ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0); 395 396 if ((debugFlags & DEBUG_ENABLE_CHECKJNI) != 0) { 397 /* turn it on if it's not already enabled */ 398 dvmLateEnableCheckedJni(); 399 } 400 401 if ((debugFlags & DEBUG_ENABLE_JNI_LOGGING) != 0) { 402 gDvmJni.logThirdPartyJni = true; 403 } 404 405 if ((debugFlags & DEBUG_ENABLE_ASSERT) != 0) { 406 /* turn it on if it's not already enabled */ 407 dvmLateEnableAssertions(); 408 } 409 410 if ((debugFlags & DEBUG_ENABLE_SAFEMODE) != 0) { 411 #if defined(WITH_JIT) 412 /* turn off the jit if it is explicitly requested by the app */ 413 if (gDvm.executionMode == kExecutionModeJit) 414 gDvm.executionMode = kExecutionModeInterpFast; 415 #endif 416 } 417 418 #ifdef HAVE_ANDROID_OS 419 if ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0) { 420 /* To let a non-privileged gdbserver attach to this 421 * process, we must set its dumpable bit flag. However 422 * we are not interested in generating a coredump in 423 * case of a crash, so also set the coredump size to 0 424 * to disable that 425 */ 426 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) { 427 ALOGE("could not set dumpable bit flag for pid %d: %s", 428 getpid(), strerror(errno)); 429 } else { 430 struct rlimit rl; 431 rl.rlim_cur = 0; 432 rl.rlim_max = RLIM_INFINITY; 433 if (setrlimit(RLIMIT_CORE, &rl) < 0) { 434 ALOGE("could not disable core file generation for pid %d: %s", 435 getpid(), strerror(errno)); 436 } 437 } 438 } 439 #endif 440 } 441 442 /* 443 * Set Linux capability flags. 444 * 445 * Returns 0 on success, errno on failure. 446 */ 447 static int setCapabilities(int64_t permitted, int64_t effective) 448 { 449 #ifdef HAVE_ANDROID_OS 450 struct __user_cap_header_struct capheader; 451 struct __user_cap_data_struct capdata; 452 453 memset(&capheader, 0, sizeof(capheader)); 454 memset(&capdata, 0, sizeof(capdata)); 455 456 capheader.version = _LINUX_CAPABILITY_VERSION; 457 capheader.pid = 0; 458 459 capdata.effective = effective; 460 capdata.permitted = permitted; 461 462 ALOGV("CAPSET perm=%llx eff=%llx", permitted, effective); 463 if (capset(&capheader, &capdata) != 0) 464 return errno; 465 #endif /*HAVE_ANDROID_OS*/ 466 467 return 0; 468 } 469 470 /* 471 * Set SELinux security context. 472 * 473 * Returns 0 on success, -1 on failure. 474 */ 475 static int setSELinuxContext(uid_t uid, bool isSystemServer, 476 const char *seInfo, const char *niceName) 477 { 478 #ifdef HAVE_ANDROID_OS 479 return selinux_android_setcontext(uid, isSystemServer, seInfo, niceName); 480 #else 481 return 0; 482 #endif 483 } 484 485 static bool needsNoRandomizeWorkaround() { 486 #if !defined(__arm__) 487 return false; 488 #else 489 int major; 490 int minor; 491 struct utsname uts; 492 if (uname(&uts) == -1) { 493 return false; 494 } 495 496 if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) { 497 return false; 498 } 499 500 // Kernels before 3.4.* need the workaround. 501 return (major < 3) || ((major == 3) && (minor < 4)); 502 #endif 503 } 504 505 /* 506 * Utility routine to fork zygote and specialize the child process. 507 */ 508 static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) 509 { 510 pid_t pid; 511 512 uid_t uid = (uid_t) args[0]; 513 gid_t gid = (gid_t) args[1]; 514 ArrayObject* gids = (ArrayObject *)args[2]; 515 u4 debugFlags = args[3]; 516 ArrayObject *rlimits = (ArrayObject *)args[4]; 517 u4 mountMode = MOUNT_EXTERNAL_NONE; 518 int64_t permittedCapabilities, effectiveCapabilities; 519 char *seInfo = NULL; 520 char *niceName = NULL; 521 522 if (isSystemServer) { 523 /* 524 * Don't use GET_ARG_LONG here for now. gcc is generating code 525 * that uses register d8 as a temporary, and that's coming out 526 * scrambled in the child process. b/3138621 527 */ 528 //permittedCapabilities = GET_ARG_LONG(args, 5); 529 //effectiveCapabilities = GET_ARG_LONG(args, 7); 530 permittedCapabilities = args[5] | (int64_t) args[6] << 32; 531 effectiveCapabilities = args[7] | (int64_t) args[8] << 32; 532 } else { 533 mountMode = args[5]; 534 permittedCapabilities = effectiveCapabilities = 0; 535 StringObject* seInfoObj = (StringObject*)args[6]; 536 if (seInfoObj) { 537 seInfo = dvmCreateCstrFromString(seInfoObj); 538 if (!seInfo) { 539 ALOGE("seInfo dvmCreateCstrFromString failed"); 540 dvmAbort(); 541 } 542 } 543 StringObject* niceNameObj = (StringObject*)args[7]; 544 if (niceNameObj) { 545 niceName = dvmCreateCstrFromString(niceNameObj); 546 if (!niceName) { 547 ALOGE("niceName dvmCreateCstrFromString failed"); 548 dvmAbort(); 549 } 550 } 551 } 552 553 if (!gDvm.zygote) { 554 dvmThrowIllegalStateException( 555 "VM instance not started with -Xzygote"); 556 557 return -1; 558 } 559 560 if (!dvmGcPreZygoteFork()) { 561 ALOGE("pre-fork heap failed"); 562 dvmAbort(); 563 } 564 565 setSignalHandler(); 566 567 dvmDumpLoaderStats("zygote"); 568 pid = fork(); 569 570 if (pid == 0) { 571 int err; 572 /* The child process */ 573 574 #ifdef HAVE_ANDROID_OS 575 extern int gMallocLeakZygoteChild; 576 gMallocLeakZygoteChild = 1; 577 578 /* keep caps across UID change, unless we're staying root */ 579 if (uid != 0) { 580 err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 581 582 if (err < 0) { 583 ALOGE("cannot PR_SET_KEEPCAPS: %s", strerror(errno)); 584 dvmAbort(); 585 } 586 } 587 588 for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) { 589 err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); 590 if (err < 0) { 591 if (errno == EINVAL) { 592 ALOGW("PR_CAPBSET_DROP %d failed: %s. " 593 "Please make sure your kernel is compiled with " 594 "file capabilities support enabled.", 595 i, strerror(errno)); 596 } else { 597 ALOGE("PR_CAPBSET_DROP %d failed: %s.", i, strerror(errno)); 598 dvmAbort(); 599 } 600 } 601 } 602 603 #endif /* HAVE_ANDROID_OS */ 604 605 if (mountMode != MOUNT_EXTERNAL_NONE) { 606 err = mountEmulatedStorage(uid, mountMode); 607 if (err < 0) { 608 ALOGE("cannot mountExternalStorage(): %s", strerror(errno)); 609 610 if (errno == ENOTCONN || errno == EROFS) { 611 // When device is actively encrypting, we get ENOTCONN here 612 // since FUSE was mounted before the framework restarted. 613 // When encrypted device is booting, we get EROFS since 614 // FUSE hasn't been created yet by init. 615 // In either case, continue without external storage. 616 } else { 617 dvmAbort(); 618 } 619 } 620 } 621 622 err = setgroupsIntarray(gids); 623 if (err < 0) { 624 ALOGE("cannot setgroups(): %s", strerror(errno)); 625 dvmAbort(); 626 } 627 628 err = setrlimitsFromArray(rlimits); 629 if (err < 0) { 630 ALOGE("cannot setrlimit(): %s", strerror(errno)); 631 dvmAbort(); 632 } 633 634 err = setresgid(gid, gid, gid); 635 if (err < 0) { 636 ALOGE("cannot setresgid(%d): %s", gid, strerror(errno)); 637 dvmAbort(); 638 } 639 640 err = setresuid(uid, uid, uid); 641 if (err < 0) { 642 ALOGE("cannot setresuid(%d): %s", uid, strerror(errno)); 643 dvmAbort(); 644 } 645 646 if (needsNoRandomizeWorkaround()) { 647 int current = personality(0xffffFFFF); 648 int success = personality((ADDR_NO_RANDOMIZE | current)); 649 if (success == -1) { 650 ALOGW("Personality switch failed. current=%d error=%d\n", current, errno); 651 } 652 } 653 654 err = setCapabilities(permittedCapabilities, effectiveCapabilities); 655 if (err != 0) { 656 ALOGE("cannot set capabilities (%llx,%llx): %s", 657 permittedCapabilities, effectiveCapabilities, strerror(err)); 658 dvmAbort(); 659 } 660 661 err = set_sched_policy(0, SP_DEFAULT); 662 if (err < 0) { 663 ALOGE("cannot set_sched_policy(0, SP_DEFAULT): %s", strerror(-err)); 664 dvmAbort(); 665 } 666 667 err = setSELinuxContext(uid, isSystemServer, seInfo, niceName); 668 if (err < 0) { 669 ALOGE("cannot set SELinux context: %s\n", strerror(errno)); 670 dvmAbort(); 671 } 672 // These free(3) calls are safe because we know we're only ever forking 673 // a single-threaded process, so we know no other thread held the heap 674 // lock when we forked. 675 free(seInfo); 676 free(niceName); 677 678 /* 679 * Our system thread ID has changed. Get the new one. 680 */ 681 Thread* thread = dvmThreadSelf(); 682 thread->systemTid = dvmGetSysThreadId(); 683 684 /* configure additional debug options */ 685 enableDebugFeatures(debugFlags); 686 687 unsetSignalHandler(); 688 gDvm.zygote = false; 689 if (!dvmInitAfterZygote()) { 690 ALOGE("error in post-zygote initialization"); 691 dvmAbort(); 692 } 693 } else if (pid > 0) { 694 /* the parent process */ 695 free(seInfo); 696 free(niceName); 697 } 698 699 return pid; 700 } 701 702 /* 703 * native public static int nativeForkAndSpecialize(int uid, int gid, 704 * int[] gids, int debugFlags, int[][] rlimits, int mountExternal, 705 * String seInfo, String niceName); 706 */ 707 static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args, 708 JValue* pResult) 709 { 710 pid_t pid; 711 712 pid = forkAndSpecializeCommon(args, false); 713 714 RETURN_INT(pid); 715 } 716 717 /* 718 * native public static int nativeForkSystemServer(int uid, int gid, 719 * int[] gids, int debugFlags, int[][] rlimits, 720 * long permittedCapabilities, long effectiveCapabilities); 721 */ 722 static void Dalvik_dalvik_system_Zygote_forkSystemServer( 723 const u4* args, JValue* pResult) 724 { 725 pid_t pid; 726 pid = forkAndSpecializeCommon(args, true); 727 728 /* The zygote process checks whether the child process has died or not. */ 729 if (pid > 0) { 730 int status; 731 732 ALOGI("System server process %d has been created", pid); 733 gDvm.systemServerPid = pid; 734 /* There is a slight window that the system server process has crashed 735 * but it went unnoticed because we haven't published its pid yet. So 736 * we recheck here just to make sure that all is well. 737 */ 738 if (waitpid(pid, &status, WNOHANG) == pid) { 739 ALOGE("System server process %d has died. Restarting Zygote!", pid); 740 kill(getpid(), SIGKILL); 741 } 742 } 743 RETURN_INT(pid); 744 } 745 746 const DalvikNativeMethod dvm_dalvik_system_Zygote[] = { 747 { "nativeFork", "()I", 748 Dalvik_dalvik_system_Zygote_fork }, 749 { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I", 750 Dalvik_dalvik_system_Zygote_forkAndSpecialize }, 751 { "nativeForkSystemServer", "(II[II[[IJJ)I", 752 Dalvik_dalvik_system_Zygote_forkSystemServer }, 753 { NULL, NULL, NULL }, 754 }; 755