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