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