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