Home | History | Annotate | Download | only in native
      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 target_user[PATH_MAX];
    275 
    276         // /mnt/shell/emulated/0
    277         snprintf(source_user, PATH_MAX, "%s/%d", source, userid);
    278         // /storage/emulated/0
    279         snprintf(target_user, PATH_MAX, "%s/%d", target, userid);
    280 
    281         if (fs_prepare_dir(source_user, 0000, 0, 0) == -1
    282                 || fs_prepare_dir(target_user, 0000, 0, 0) == -1) {
    283             return -1;
    284         }
    285 
    286         if (mountMode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
    287             // Mount entire external storage tree for all users
    288             if (mount(source, target, NULL, MS_BIND, NULL) == -1) {
    289                 ALOGE("Failed to mount %s to %s: %s", source, target, strerror(errno));
    290                 return -1;
    291             }
    292         } else {
    293             // Only mount user-specific external storage
    294             if (mount(source_user, target_user, NULL, MS_BIND, NULL) == -1) {
    295                 ALOGE("Failed to mount %s to %s: %s", source_user, target_user, strerror(errno));
    296                 return -1;
    297             }
    298         }
    299 
    300         if (fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
    301             return -1;
    302         }
    303 
    304         // Finally, mount user-specific path into place for legacy users
    305         if (mount(target_user, legacy, NULL, MS_BIND | MS_REC, NULL) == -1) {
    306             ALOGE("Failed to mount %s to %s: %s", target_user, legacy, strerror(errno));
    307             return -1;
    308         }
    309 
    310     } else {
    311         ALOGE("Mount mode %d unsupported", mountMode);
    312         return -1;
    313     }
    314 
    315     return 0;
    316 }
    317 
    318 /* native public static int fork(); */
    319 static void Dalvik_dalvik_system_Zygote_fork(const u4* args, JValue* pResult)
    320 {
    321     pid_t pid;
    322 
    323     if (!gDvm.zygote) {
    324         dvmThrowIllegalStateException(
    325             "VM instance not started with -Xzygote");
    326 
    327         RETURN_VOID();
    328     }
    329 
    330     if (!dvmGcPreZygoteFork()) {
    331         ALOGE("pre-fork heap failed");
    332         dvmAbort();
    333     }
    334 
    335     setSignalHandler();
    336 
    337     dvmDumpLoaderStats("zygote");
    338     pid = fork();
    339 
    340 #ifdef HAVE_ANDROID_OS
    341     if (pid == 0) {
    342         /* child process */
    343         extern int gMallocLeakZygoteChild;
    344         gMallocLeakZygoteChild = 1;
    345     }
    346 #endif
    347 
    348     RETURN_INT(pid);
    349 }
    350 
    351 /*
    352  * Enable/disable debug features requested by the caller.
    353  *
    354  * debugger
    355  *   If set, enable debugging; if not set, disable debugging.  This is
    356  *   easy to handle, because the JDWP thread isn't started until we call
    357  *   dvmInitAfterZygote().
    358  * checkjni
    359  *   If set, make sure "check JNI" is enabled.
    360  * assert
    361  *   If set, make sure assertions are enabled.  This gets fairly weird,
    362  *   because it affects the result of a method called by class initializers,
    363  *   and hence can't affect pre-loaded/initialized classes.
    364  * safemode
    365  *   If set, operates the VM in the safe mode. The definition of "safe mode" is
    366  *   implementation dependent and currently only the JIT compiler is disabled.
    367  *   This is easy to handle because the compiler thread and associated resources
    368  *   are not requested until we call dvmInitAfterZygote().
    369  */
    370 static void enableDebugFeatures(u4 debugFlags)
    371 {
    372     ALOGV("debugFlags is 0x%02x", debugFlags);
    373 
    374     gDvm.jdwpAllowed = ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0);
    375 
    376     if ((debugFlags & DEBUG_ENABLE_CHECKJNI) != 0) {
    377         /* turn it on if it's not already enabled */
    378         dvmLateEnableCheckedJni();
    379     }
    380 
    381     if ((debugFlags & DEBUG_ENABLE_JNI_LOGGING) != 0) {
    382         gDvmJni.logThirdPartyJni = true;
    383     }
    384 
    385     if ((debugFlags & DEBUG_ENABLE_ASSERT) != 0) {
    386         /* turn it on if it's not already enabled */
    387         dvmLateEnableAssertions();
    388     }
    389 
    390     if ((debugFlags & DEBUG_ENABLE_SAFEMODE) != 0) {
    391 #if defined(WITH_JIT)
    392         /* turn off the jit if it is explicitly requested by the app */
    393         if (gDvm.executionMode == kExecutionModeJit)
    394             gDvm.executionMode = kExecutionModeInterpFast;
    395 #endif
    396     }
    397 
    398 #ifdef HAVE_ANDROID_OS
    399     if ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0) {
    400         /* To let a non-privileged gdbserver attach to this
    401          * process, we must set its dumpable bit flag. However
    402          * we are not interested in generating a coredump in
    403          * case of a crash, so also set the coredump size to 0
    404          * to disable that
    405          */
    406         if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
    407             ALOGE("could not set dumpable bit flag for pid %d: %s",
    408                  getpid(), strerror(errno));
    409         } else {
    410             struct rlimit rl;
    411             rl.rlim_cur = 0;
    412             rl.rlim_max = RLIM_INFINITY;
    413             if (setrlimit(RLIMIT_CORE, &rl) < 0) {
    414                 ALOGE("could not disable core file generation for pid %d: %s",
    415                     getpid(), strerror(errno));
    416             }
    417         }
    418     }
    419 #endif
    420 }
    421 
    422 /*
    423  * Set Linux capability flags.
    424  *
    425  * Returns 0 on success, errno on failure.
    426  */
    427 static int setCapabilities(int64_t permitted, int64_t effective)
    428 {
    429 #ifdef HAVE_ANDROID_OS
    430     struct __user_cap_header_struct capheader;
    431     struct __user_cap_data_struct capdata;
    432 
    433     memset(&capheader, 0, sizeof(capheader));
    434     memset(&capdata, 0, sizeof(capdata));
    435 
    436     capheader.version = _LINUX_CAPABILITY_VERSION;
    437     capheader.pid = 0;
    438 
    439     capdata.effective = effective;
    440     capdata.permitted = permitted;
    441 
    442     ALOGV("CAPSET perm=%llx eff=%llx", permitted, effective);
    443     if (capset(&capheader, &capdata) != 0)
    444         return errno;
    445 #endif /*HAVE_ANDROID_OS*/
    446 
    447     return 0;
    448 }
    449 
    450 /*
    451  * Set SELinux security context.
    452  *
    453  * Returns 0 on success, -1 on failure.
    454  */
    455 static int setSELinuxContext(uid_t uid, bool isSystemServer,
    456                              const char *seInfo, const char *niceName)
    457 {
    458 #ifdef HAVE_ANDROID_OS
    459     return selinux_android_setcontext(uid, isSystemServer, seInfo, niceName);
    460 #else
    461     return 0;
    462 #endif
    463 }
    464 
    465 static bool needsNoRandomizeWorkaround() {
    466 #if !defined(__arm__)
    467     return false;
    468 #else
    469     int major;
    470     int minor;
    471     struct utsname uts;
    472     if (uname(&uts) == -1) {
    473         return false;
    474     }
    475 
    476     if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
    477         return false;
    478     }
    479 
    480     // Kernels before 3.4.* need the workaround.
    481     return (major < 3) || ((major == 3) && (minor < 4));
    482 #endif
    483 }
    484 
    485 /*
    486  * Utility routine to fork zygote and specialize the child process.
    487  */
    488 static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
    489 {
    490     pid_t pid;
    491 
    492     uid_t uid = (uid_t) args[0];
    493     gid_t gid = (gid_t) args[1];
    494     ArrayObject* gids = (ArrayObject *)args[2];
    495     u4 debugFlags = args[3];
    496     ArrayObject *rlimits = (ArrayObject *)args[4];
    497     u4 mountMode = MOUNT_EXTERNAL_NONE;
    498     int64_t permittedCapabilities, effectiveCapabilities;
    499     char *seInfo = NULL;
    500     char *niceName = NULL;
    501 
    502     if (isSystemServer) {
    503         /*
    504          * Don't use GET_ARG_LONG here for now.  gcc is generating code
    505          * that uses register d8 as a temporary, and that's coming out
    506          * scrambled in the child process.  b/3138621
    507          */
    508         //permittedCapabilities = GET_ARG_LONG(args, 5);
    509         //effectiveCapabilities = GET_ARG_LONG(args, 7);
    510         permittedCapabilities = args[5] | (int64_t) args[6] << 32;
    511         effectiveCapabilities = args[7] | (int64_t) args[8] << 32;
    512     } else {
    513         mountMode = args[5];
    514         permittedCapabilities = effectiveCapabilities = 0;
    515         StringObject* seInfoObj = (StringObject*)args[6];
    516         if (seInfoObj) {
    517             seInfo = dvmCreateCstrFromString(seInfoObj);
    518             if (!seInfo) {
    519                 ALOGE("seInfo dvmCreateCstrFromString failed");
    520                 dvmAbort();
    521             }
    522         }
    523         StringObject* niceNameObj = (StringObject*)args[7];
    524         if (niceNameObj) {
    525             niceName = dvmCreateCstrFromString(niceNameObj);
    526             if (!niceName) {
    527                 ALOGE("niceName dvmCreateCstrFromString failed");
    528                 dvmAbort();
    529             }
    530         }
    531     }
    532 
    533     if (!gDvm.zygote) {
    534         dvmThrowIllegalStateException(
    535             "VM instance not started with -Xzygote");
    536 
    537         return -1;
    538     }
    539 
    540     if (!dvmGcPreZygoteFork()) {
    541         ALOGE("pre-fork heap failed");
    542         dvmAbort();
    543     }
    544 
    545     setSignalHandler();
    546 
    547     dvmDumpLoaderStats("zygote");
    548     pid = fork();
    549 
    550     if (pid == 0) {
    551         int err;
    552         /* The child process */
    553 
    554 #ifdef HAVE_ANDROID_OS
    555         extern int gMallocLeakZygoteChild;
    556         gMallocLeakZygoteChild = 1;
    557 
    558         /* keep caps across UID change, unless we're staying root */
    559         if (uid != 0) {
    560             err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
    561 
    562             if (err < 0) {
    563                 ALOGE("cannot PR_SET_KEEPCAPS: %s", strerror(errno));
    564                 dvmAbort();
    565             }
    566         }
    567 
    568         for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
    569             err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
    570             if (err < 0) {
    571                 if (errno == EINVAL) {
    572                     ALOGW("PR_CAPBSET_DROP %d failed: %s. "
    573                           "Please make sure your kernel is compiled with "
    574                           "file capabilities support enabled.",
    575                           i, strerror(errno));
    576                 } else {
    577                     ALOGE("PR_CAPBSET_DROP %d failed: %s.", i, strerror(errno));
    578                     dvmAbort();
    579                 }
    580             }
    581         }
    582 
    583 #endif /* HAVE_ANDROID_OS */
    584 
    585         if (mountMode != MOUNT_EXTERNAL_NONE) {
    586             err = mountEmulatedStorage(uid, mountMode);
    587             if (err < 0) {
    588                 ALOGE("cannot mountExternalStorage(): %s", strerror(errno));
    589 
    590                 if (errno == ENOTCONN || errno == EROFS) {
    591                     // When device is actively encrypting, we get ENOTCONN here
    592                     // since FUSE was mounted before the framework restarted.
    593                     // When encrypted device is booting, we get EROFS since
    594                     // FUSE hasn't been created yet by init.
    595                     // In either case, continue without external storage.
    596                 } else {
    597                     dvmAbort();
    598                 }
    599             }
    600         }
    601 
    602         err = setgroupsIntarray(gids);
    603         if (err < 0) {
    604             ALOGE("cannot setgroups(): %s", strerror(errno));
    605             dvmAbort();
    606         }
    607 
    608         err = setrlimitsFromArray(rlimits);
    609         if (err < 0) {
    610             ALOGE("cannot setrlimit(): %s", strerror(errno));
    611             dvmAbort();
    612         }
    613 
    614         err = setresgid(gid, gid, gid);
    615         if (err < 0) {
    616             ALOGE("cannot setresgid(%d): %s", gid, strerror(errno));
    617             dvmAbort();
    618         }
    619 
    620         err = setresuid(uid, uid, uid);
    621         if (err < 0) {
    622             ALOGE("cannot setresuid(%d): %s", uid, strerror(errno));
    623             dvmAbort();
    624         }
    625 
    626         if (needsNoRandomizeWorkaround()) {
    627             int current = personality(0xffffFFFF);
    628             int success = personality((ADDR_NO_RANDOMIZE | current));
    629             if (success == -1) {
    630                 ALOGW("Personality switch failed. current=%d error=%d\n", current, errno);
    631             }
    632         }
    633 
    634         err = setCapabilities(permittedCapabilities, effectiveCapabilities);
    635         if (err != 0) {
    636             ALOGE("cannot set capabilities (%llx,%llx): %s",
    637                 permittedCapabilities, effectiveCapabilities, strerror(err));
    638             dvmAbort();
    639         }
    640 
    641         err = set_sched_policy(0, SP_DEFAULT);
    642         if (err < 0) {
    643             ALOGE("cannot set_sched_policy(0, SP_DEFAULT): %s", strerror(-err));
    644             dvmAbort();
    645         }
    646 
    647         err = setSELinuxContext(uid, isSystemServer, seInfo, niceName);
    648         if (err < 0) {
    649             ALOGE("cannot set SELinux context: %s\n", strerror(errno));
    650             dvmAbort();
    651         }
    652         // These free(3) calls are safe because we know we're only ever forking
    653         // a single-threaded process, so we know no other thread held the heap
    654         // lock when we forked.
    655         free(seInfo);
    656         free(niceName);
    657 
    658         /*
    659          * Our system thread ID has changed.  Get the new one.
    660          */
    661         Thread* thread = dvmThreadSelf();
    662         thread->systemTid = dvmGetSysThreadId();
    663 
    664         /* configure additional debug options */
    665         enableDebugFeatures(debugFlags);
    666 
    667         unsetSignalHandler();
    668         gDvm.zygote = false;
    669         if (!dvmInitAfterZygote()) {
    670             ALOGE("error in post-zygote initialization");
    671             dvmAbort();
    672         }
    673     } else if (pid > 0) {
    674         /* the parent process */
    675         free(seInfo);
    676         free(niceName);
    677     }
    678 
    679     return pid;
    680 }
    681 
    682 /*
    683  * native public static int nativeForkAndSpecialize(int uid, int gid,
    684  *     int[] gids, int debugFlags, int[][] rlimits, int mountExternal,
    685  *     String seInfo, String niceName);
    686  */
    687 static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args,
    688     JValue* pResult)
    689 {
    690     pid_t pid;
    691 
    692     pid = forkAndSpecializeCommon(args, false);
    693 
    694     RETURN_INT(pid);
    695 }
    696 
    697 /*
    698  * native public static int nativeForkSystemServer(int uid, int gid,
    699  *     int[] gids, int debugFlags, int[][] rlimits,
    700  *     long permittedCapabilities, long effectiveCapabilities);
    701  */
    702 static void Dalvik_dalvik_system_Zygote_forkSystemServer(
    703         const u4* args, JValue* pResult)
    704 {
    705     pid_t pid;
    706     pid = forkAndSpecializeCommon(args, true);
    707 
    708     /* The zygote process checks whether the child process has died or not. */
    709     if (pid > 0) {
    710         int status;
    711 
    712         ALOGI("System server process %d has been created", pid);
    713         gDvm.systemServerPid = pid;
    714         /* There is a slight window that the system server process has crashed
    715          * but it went unnoticed because we haven't published its pid yet. So
    716          * we recheck here just to make sure that all is well.
    717          */
    718         if (waitpid(pid, &status, WNOHANG) == pid) {
    719             ALOGE("System server process %d has died. Restarting Zygote!", pid);
    720             kill(getpid(), SIGKILL);
    721         }
    722     }
    723     RETURN_INT(pid);
    724 }
    725 
    726 const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
    727     { "nativeFork", "()I",
    728       Dalvik_dalvik_system_Zygote_fork },
    729     { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I",
    730       Dalvik_dalvik_system_Zygote_forkAndSpecialize },
    731     { "nativeForkSystemServer", "(II[II[[IJJ)I",
    732       Dalvik_dalvik_system_Zygote_forkSystemServer },
    733     { NULL, NULL, NULL },
    734 };
    735