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