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