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