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 <signal.h>
     24 #include <sys/types.h>
     25 #include <sys/wait.h>
     26 #include <grp.h>
     27 #include <errno.h>
     28 
     29 #if defined(HAVE_PRCTL)
     30 # include <sys/prctl.h>
     31 #endif
     32 
     33 #define ZYGOTE_LOG_TAG "Zygote"
     34 
     35 /* must match values in dalvik.system.Zygote */
     36 enum {
     37     DEBUG_ENABLE_DEBUGGER           = 1,
     38     DEBUG_ENABLE_CHECKJNI           = 1 << 1,
     39     DEBUG_ENABLE_ASSERT             = 1 << 2,
     40     DEBUG_ENABLE_SAFEMODE           = 1 << 3,
     41 };
     42 
     43 /*
     44  * This signal handler is for zygote mode, since the zygote
     45  * must reap its children
     46  */
     47 static void sigchldHandler(int s)
     48 {
     49     pid_t pid;
     50     int status;
     51 
     52     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
     53         /* Log process-death status that we care about.  In general it is not
     54            safe to call LOG(...) from a signal handler because of possible
     55            reentrancy.  However, we know a priori that the current implementation
     56            of LOG() is safe to call from a SIGCHLD handler in the zygote process.
     57            If the LOG() implementation changes its locking strategy or its use
     58            of syscalls within the lazy-init critical section, its use here may
     59            become unsafe. */
     60         if (WIFEXITED(status)) {
     61             if (WEXITSTATUS(status)) {
     62                 LOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)\n",
     63                     (int) pid, WEXITSTATUS(status));
     64             } else {
     65                 IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) {
     66                     LOG(LOG_VERBOSE, ZYGOTE_LOG_TAG,
     67                         "Process %d exited cleanly (%d)\n",
     68                         (int) pid, WEXITSTATUS(status));
     69                 }
     70             }
     71         } else if (WIFSIGNALED(status)) {
     72             if (WTERMSIG(status) != SIGKILL) {
     73                 LOG(LOG_DEBUG, ZYGOTE_LOG_TAG,
     74                     "Process %d terminated by signal (%d)\n",
     75                     (int) pid, WTERMSIG(status));
     76             } else {
     77                 IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) {
     78                     LOG(LOG_VERBOSE, ZYGOTE_LOG_TAG,
     79                         "Process %d terminated by signal (%d)\n",
     80                         (int) pid, WTERMSIG(status));
     81                 }
     82             }
     83 #ifdef WCOREDUMP
     84             if (WCOREDUMP(status)) {
     85                 LOG(LOG_INFO, ZYGOTE_LOG_TAG, "Process %d dumped core\n",
     86                     (int) pid);
     87             }
     88 #endif /* ifdef WCOREDUMP */
     89         }
     90 
     91         /*
     92          * If the just-crashed process is the system_server, bring down zygote
     93          * so that it is restarted by init and system server will be restarted
     94          * from there.
     95          */
     96         if (pid == gDvm.systemServerPid) {
     97             LOG(LOG_INFO, ZYGOTE_LOG_TAG,
     98                 "Exit zygote because system server (%d) has terminated\n",
     99                 (int) pid);
    100             kill(getpid(), SIGKILL);
    101         }
    102     }
    103 
    104     if (pid < 0) {
    105         LOG(LOG_WARN, ZYGOTE_LOG_TAG,
    106             "Zygote SIGCHLD error (%d) in waitpid\n",errno);
    107     }
    108 }
    109 
    110 /*
    111  * configure sigchld handler for the zygote process
    112  * This is configured very late, because earlier in the dalvik lifecycle
    113  * we can fork() and exec() for the verifier/optimizer, and we
    114  * want to waitpid() for those rather than have them be harvested immediately.
    115  *
    116  * This ends up being called repeatedly before each fork(), but there's
    117  * no real harm in that.
    118  */
    119 static void setSignalHandler()
    120 {
    121     int err;
    122     struct sigaction sa;
    123 
    124     memset(&sa, 0, sizeof(sa));
    125 
    126     sa.sa_handler = sigchldHandler;
    127 
    128     err = sigaction (SIGCHLD, &sa, NULL);
    129 
    130     if (err < 0) {
    131         LOGW("Error setting SIGCHLD handler errno: %d", errno);
    132     }
    133 }
    134 
    135 /*
    136  * Set the SIGCHLD handler back to default behavior in zygote children
    137  */
    138 static void unsetSignalHandler()
    139 {
    140     int err;
    141     struct sigaction sa;
    142 
    143     memset(&sa, 0, sizeof(sa));
    144 
    145     sa.sa_handler = SIG_DFL;
    146 
    147     err = sigaction (SIGCHLD, &sa, NULL);
    148 
    149     if (err < 0) {
    150         LOGW("Error unsetting SIGCHLD handler errno: %d", errno);
    151     }
    152 }
    153 
    154 /*
    155  * Calls POSIX setgroups() using the int[] object as an argument.
    156  * A NULL argument is tolerated.
    157  */
    158 
    159 static int setgroupsIntarray(ArrayObject* gidArray)
    160 {
    161     gid_t *gids;
    162     u4 i;
    163     s4 *contents;
    164 
    165     if (gidArray == NULL) {
    166         return 0;
    167     }
    168 
    169     /* just in case gid_t and u4 are different... */
    170     gids = alloca(sizeof(gid_t) * gidArray->length);
    171     contents = (s4 *)gidArray->contents;
    172 
    173     for (i = 0 ; i < gidArray->length ; i++) {
    174         gids[i] = (gid_t) contents[i];
    175     }
    176 
    177     return setgroups((size_t) gidArray->length, gids);
    178 }
    179 
    180 /*
    181  * Sets the resource limits via setrlimit(2) for the values in the
    182  * two-dimensional array of integers that's passed in. The second dimension
    183  * contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
    184  * treated as an empty array.
    185  *
    186  * -1 is returned on error.
    187  */
    188 static int setrlimitsFromArray(ArrayObject* rlimits)
    189 {
    190     u4 i;
    191     struct rlimit rlim;
    192 
    193     if (rlimits == NULL) {
    194         return 0;
    195     }
    196 
    197     memset (&rlim, 0, sizeof(rlim));
    198 
    199     ArrayObject** tuples = (ArrayObject **)(rlimits->contents);
    200 
    201     for (i = 0; i < rlimits->length; i++) {
    202         ArrayObject * rlimit_tuple = tuples[i];
    203         s4* contents = (s4 *)rlimit_tuple->contents;
    204         int err;
    205 
    206         if (rlimit_tuple->length != 3) {
    207             LOGE("rlimits array must have a second dimension of size 3");
    208             return -1;
    209         }
    210 
    211         rlim.rlim_cur = contents[1];
    212         rlim.rlim_max = contents[2];
    213 
    214         err = setrlimit(contents[0], &rlim);
    215 
    216         if (err < 0) {
    217             return -1;
    218         }
    219     }
    220 
    221     return 0;
    222 }
    223 
    224 /* native public static int fork(); */
    225 static void Dalvik_dalvik_system_Zygote_fork(const u4* args, JValue* pResult)
    226 {
    227     pid_t pid;
    228     int err;
    229 
    230     if (!gDvm.zygote) {
    231         dvmThrowException("Ljava/lang/IllegalStateException;",
    232             "VM instance not started with -Xzygote");
    233 
    234         RETURN_VOID();
    235     }
    236 
    237     if (!dvmGcPreZygoteFork()) {
    238         LOGE("pre-fork heap failed\n");
    239         dvmAbort();
    240     }
    241 
    242     setSignalHandler();
    243 
    244     dvmDumpLoaderStats("zygote");
    245     pid = fork();
    246 
    247 #ifdef HAVE_ANDROID_OS
    248     if (pid == 0) {
    249         /* child process */
    250         extern int gMallocLeakZygoteChild;
    251         gMallocLeakZygoteChild = 1;
    252     }
    253 #endif
    254 
    255     RETURN_INT(pid);
    256 }
    257 
    258 /*
    259  * Enable/disable debug features requested by the caller.
    260  *
    261  * debugger
    262  *   If set, enable debugging; if not set, disable debugging.  This is
    263  *   easy to handle, because the JDWP thread isn't started until we call
    264  *   dvmInitAfterZygote().
    265  * checkjni
    266  *   If set, make sure "check JNI" is eabled.  This is a little weird,
    267  *   because we already have the JNIEnv for the main thread set up.  However,
    268  *   since we only have one thread at this point, it's easy to patch up.
    269  * assert
    270  *   If set, make sure assertions are enabled.  This gets fairly weird,
    271  *   because it affects the result of a method called by class initializers,
    272  *   and hence can't affect pre-loaded/initialized classes.
    273  * safemode
    274  *   If set, operates the VM in the safe mode. The definition of "safe mode" is
    275  *   implementation dependent and currently only the JIT compiler is disabled.
    276  *   This is easy to handle because the compiler thread and associated resources
    277  *   are not requested until we call dvmInitAfterZygote().
    278  */
    279 static void enableDebugFeatures(u4 debugFlags)
    280 {
    281     LOGV("debugFlags is 0x%02x\n", debugFlags);
    282 
    283     gDvm.jdwpAllowed = ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0);
    284 
    285     if ((debugFlags & DEBUG_ENABLE_CHECKJNI) != 0) {
    286         /* turn it on if it's not already enabled */
    287         dvmLateEnableCheckedJni();
    288     }
    289 
    290     if ((debugFlags & DEBUG_ENABLE_ASSERT) != 0) {
    291         /* turn it on if it's not already enabled */
    292         dvmLateEnableAssertions();
    293     }
    294 
    295     if ((debugFlags & DEBUG_ENABLE_SAFEMODE) != 0) {
    296 #if defined(WITH_JIT)
    297         /* turn off the jit if it is explicitly requested by the app */
    298         if (gDvm.executionMode == kExecutionModeJit)
    299             gDvm.executionMode = kExecutionModeInterpFast;
    300 #endif
    301     }
    302 
    303 #if HAVE_ANDROID_OS
    304     if ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0) {
    305         /* To let a non-privileged gdbserver attach to this
    306          * process, we must set its dumpable bit flag. However
    307          * we are not interested in generating a coredump in
    308          * case of a crash, so also set the coredump size to 0
    309          * to disable that
    310          */
    311         if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
    312             LOGE("could not set dumpable bit flag for pid %d, errno=%d",
    313                  getpid(), errno);
    314         } else {
    315             struct rlimit rl;
    316             rl.rlim_cur = 0;
    317             rl.rlim_max = RLIM_INFINITY;
    318             if (setrlimit(RLIMIT_CORE, &rl) < 0) {
    319                 LOGE("could not disable core file generation "
    320                      "for pid %d, errno=%d", getpid(), errno);
    321             }
    322         }
    323     }
    324 #endif
    325 }
    326 
    327 /*
    328  * Utility routine to fork zygote and specialize the child process.
    329  */
    330 static pid_t forkAndSpecializeCommon(const u4* args)
    331 {
    332     pid_t pid;
    333 
    334     uid_t uid = (uid_t) args[0];
    335     gid_t gid = (gid_t) args[1];
    336     ArrayObject* gids = (ArrayObject *)args[2];
    337     u4 debugFlags = args[3];
    338     ArrayObject *rlimits = (ArrayObject *)args[4];
    339 
    340     if (!gDvm.zygote) {
    341         dvmThrowException("Ljava/lang/IllegalStateException;",
    342             "VM instance not started with -Xzygote");
    343 
    344         return -1;
    345     }
    346 
    347     if (!dvmGcPreZygoteFork()) {
    348         LOGE("pre-fork heap failed\n");
    349         dvmAbort();
    350     }
    351 
    352     setSignalHandler();
    353 
    354     dvmDumpLoaderStats("zygote");
    355     pid = fork();
    356 
    357     if (pid == 0) {
    358         int err;
    359         /* The child process */
    360 
    361 #ifdef HAVE_ANDROID_OS
    362         extern int gMallocLeakZygoteChild;
    363         gMallocLeakZygoteChild = 1;
    364 
    365         /* keep caps across UID change, unless we're staying root */
    366         if (uid != 0) {
    367             err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
    368 
    369             if (err < 0) {
    370                 LOGW("cannot PR_SET_KEEPCAPS errno: %d", errno);
    371             }
    372         }
    373 
    374 #endif /* HAVE_ANDROID_OS */
    375 
    376         err = setgroupsIntarray(gids);
    377 
    378         if (err < 0) {
    379             LOGW("cannot setgroups() errno: %d", errno);
    380         }
    381 
    382         err = setrlimitsFromArray(rlimits);
    383 
    384         if (err < 0) {
    385             LOGW("cannot setrlimit() errno: %d", errno);
    386         }
    387 
    388         err = setgid(gid);
    389         if (err < 0) {
    390             LOGW("cannot setgid(%d) errno: %d", gid, errno);
    391         }
    392 
    393         err = setuid(uid);
    394         if (err < 0) {
    395             LOGW("cannot setuid(%d) errno: %d", uid, errno);
    396         }
    397 
    398         /*
    399          * Our system thread ID has changed.  Get the new one.
    400          */
    401         Thread* thread = dvmThreadSelf();
    402         thread->systemTid = dvmGetSysThreadId();
    403 
    404         /* configure additional debug options */
    405         enableDebugFeatures(debugFlags);
    406 
    407         unsetSignalHandler();
    408         gDvm.zygote = false;
    409         if (!dvmInitAfterZygote()) {
    410             LOGE("error in post-zygote initialization\n");
    411             dvmAbort();
    412         }
    413     } else if (pid > 0) {
    414         /* the parent process */
    415     }
    416 
    417     return pid;
    418 }
    419 
    420 /* native public static int forkAndSpecialize(int uid, int gid,
    421  *     int[] gids, int debugFlags);
    422  */
    423 static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args,
    424     JValue* pResult)
    425 {
    426     pid_t pid;
    427 
    428     pid = forkAndSpecializeCommon(args);
    429 
    430     RETURN_INT(pid);
    431 }
    432 
    433 /* native public static int forkSystemServer(int uid, int gid,
    434  *     int[] gids, int debugFlags);
    435  */
    436 static void Dalvik_dalvik_system_Zygote_forkSystemServer(
    437         const u4* args, JValue* pResult)
    438 {
    439     pid_t pid;
    440     pid = forkAndSpecializeCommon(args);
    441 
    442     /* The zygote process checks whether the child process has died or not. */
    443     if (pid > 0) {
    444         int status;
    445 
    446         LOGI("System server process %d has been created", pid);
    447         gDvm.systemServerPid = pid;
    448         /* There is a slight window that the system server process has crashed
    449          * but it went unnoticed because we haven't published its pid yet. So
    450          * we recheck here just to make sure that all is well.
    451          */
    452         if (waitpid(pid, &status, WNOHANG) == pid) {
    453             LOGE("System server process %d has died. Restarting Zygote!", pid);
    454             kill(getpid(), SIGKILL);
    455         }
    456     }
    457     RETURN_INT(pid);
    458 }
    459 
    460 const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
    461     { "fork",            "()I",
    462         Dalvik_dalvik_system_Zygote_fork },
    463     { "forkAndSpecialize",            "(II[II[[I)I",
    464         Dalvik_dalvik_system_Zygote_forkAndSpecialize },
    465     { "forkSystemServer",            "(II[II[[I)I",
    466         Dalvik_dalvik_system_Zygote_forkSystemServer },
    467     { NULL, NULL, NULL },
    468 };
    469