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