• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <selinux/android.h>
24 
25 #include <signal.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <grp.h>
29 #include <errno.h>
30 #include <paths.h>
31 #include <sys/personality.h>
32 #include <sys/stat.h>
33 #include <sys/mount.h>
34 #include <linux/fs.h>
35 #include <cutils/fs.h>
36 #include <cutils/sched_policy.h>
37 #include <cutils/multiuser.h>
38 #include <sched.h>
39 #include <sys/utsname.h>
40 #include <sys/capability.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 */
49 enum {
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 */
58 enum {
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  */
sigchldHandler(int s)69 static 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  */
setSignalHandler()141 static 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  */
unsetSignalHandler()160 static 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 
setgroupsIntarray(ArrayObject * gidArray)181 static 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  */
setrlimitsFromArray(ArrayObject * rlimits)210 static 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  */
mountEmulatedStorage(uid_t uid,u4 mountMode)250 static 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         ALOGE("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             ALOGE("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         char target_user[PATH_MAX];
276 
277         // /mnt/shell/emulated/0
278         snprintf(source_user, PATH_MAX, "%s/%d", source, userid);
279         // /mnt/shell/emulated/obb
280         snprintf(source_obb, PATH_MAX, "%s/obb", source);
281         // /storage/emulated/0
282         snprintf(target_user, PATH_MAX, "%s/%d", target, userid);
283 
284         if (fs_prepare_dir(source_user, 0000, 0, 0) == -1
285                 || fs_prepare_dir(source_obb, 0000, 0, 0) == -1
286                 || fs_prepare_dir(target_user, 0000, 0, 0) == -1) {
287             return -1;
288         }
289 
290         if (mountMode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
291             // Mount entire external storage tree for all users
292             if (mount(source, target, NULL, MS_BIND, NULL) == -1) {
293                 ALOGE("Failed to mount %s to %s: %s", source, target, strerror(errno));
294                 return -1;
295             }
296         } else {
297             // Only mount user-specific external storage
298             if (mount(source_user, target_user, NULL, MS_BIND, NULL) == -1) {
299                 ALOGE("Failed to mount %s to %s: %s", source_user, target_user, strerror(errno));
300                 return -1;
301             }
302         }
303 
304         // Now that user is mounted, prepare and mount OBB storage
305         // into place for current user
306         char target_android[PATH_MAX];
307         char target_obb[PATH_MAX];
308 
309         // /storage/emulated/0/Android
310         snprintf(target_android, PATH_MAX, "%s/%d/Android", target, userid);
311         // /storage/emulated/0/Android/obb
312         snprintf(target_obb, PATH_MAX, "%s/%d/Android/obb", target, userid);
313 
314         if (fs_prepare_dir(target_android, 0000, 0, 0) == -1
315                 || fs_prepare_dir(target_obb, 0000, 0, 0) == -1
316                 || fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
317             return -1;
318         }
319         if (mount(source_obb, target_obb, NULL, MS_BIND, NULL) == -1) {
320             ALOGE("Failed to mount %s to %s: %s", source_obb, target_obb, strerror(errno));
321             return -1;
322         }
323 
324         // Finally, mount user-specific path into place for legacy users
325         if (mount(target_user, legacy, NULL, MS_BIND | MS_REC, NULL) == -1) {
326             ALOGE("Failed to mount %s to %s: %s", target_user, legacy, strerror(errno));
327             return -1;
328         }
329 
330     } else {
331         ALOGE("Mount mode %d unsupported", mountMode);
332         return -1;
333     }
334 
335     return 0;
336 }
337 
338 /* native public static int fork(); */
Dalvik_dalvik_system_Zygote_fork(const u4 * args,JValue * pResult)339 static void Dalvik_dalvik_system_Zygote_fork(const u4* args, JValue* pResult)
340 {
341     pid_t pid;
342 
343     if (!gDvm.zygote) {
344         dvmThrowIllegalStateException(
345             "VM instance not started with -Xzygote");
346 
347         RETURN_VOID();
348     }
349 
350     if (!dvmGcPreZygoteFork()) {
351         ALOGE("pre-fork heap failed");
352         dvmAbort();
353     }
354 
355     setSignalHandler();
356 
357     dvmDumpLoaderStats("zygote");
358     pid = fork();
359 
360 #ifdef HAVE_ANDROID_OS
361     if (pid == 0) {
362         /* child process */
363         extern int gMallocLeakZygoteChild;
364         gMallocLeakZygoteChild = 1;
365     }
366 #endif
367 
368     RETURN_INT(pid);
369 }
370 
371 /*
372  * Enable/disable debug features requested by the caller.
373  *
374  * debugger
375  *   If set, enable debugging; if not set, disable debugging.  This is
376  *   easy to handle, because the JDWP thread isn't started until we call
377  *   dvmInitAfterZygote().
378  * checkjni
379  *   If set, make sure "check JNI" is enabled.
380  * assert
381  *   If set, make sure assertions are enabled.  This gets fairly weird,
382  *   because it affects the result of a method called by class initializers,
383  *   and hence can't affect pre-loaded/initialized classes.
384  * safemode
385  *   If set, operates the VM in the safe mode. The definition of "safe mode" is
386  *   implementation dependent and currently only the JIT compiler is disabled.
387  *   This is easy to handle because the compiler thread and associated resources
388  *   are not requested until we call dvmInitAfterZygote().
389  */
enableDebugFeatures(u4 debugFlags)390 static void enableDebugFeatures(u4 debugFlags)
391 {
392     ALOGV("debugFlags is 0x%02x", debugFlags);
393 
394     gDvm.jdwpAllowed = ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0);
395 
396     if ((debugFlags & DEBUG_ENABLE_CHECKJNI) != 0) {
397         /* turn it on if it's not already enabled */
398         dvmLateEnableCheckedJni();
399     }
400 
401     if ((debugFlags & DEBUG_ENABLE_JNI_LOGGING) != 0) {
402         gDvmJni.logThirdPartyJni = true;
403     }
404 
405     if ((debugFlags & DEBUG_ENABLE_ASSERT) != 0) {
406         /* turn it on if it's not already enabled */
407         dvmLateEnableAssertions();
408     }
409 
410     if ((debugFlags & DEBUG_ENABLE_SAFEMODE) != 0) {
411 #if defined(WITH_JIT)
412         /* turn off the jit if it is explicitly requested by the app */
413         if (gDvm.executionMode == kExecutionModeJit)
414             gDvm.executionMode = kExecutionModeInterpFast;
415 #endif
416     }
417 
418 #ifdef HAVE_ANDROID_OS
419     if ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0) {
420         /* To let a non-privileged gdbserver attach to this
421          * process, we must set its dumpable bit flag. However
422          * we are not interested in generating a coredump in
423          * case of a crash, so also set the coredump size to 0
424          * to disable that
425          */
426         if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
427             ALOGE("could not set dumpable bit flag for pid %d: %s",
428                  getpid(), strerror(errno));
429         } else {
430             struct rlimit rl;
431             rl.rlim_cur = 0;
432             rl.rlim_max = RLIM_INFINITY;
433             if (setrlimit(RLIMIT_CORE, &rl) < 0) {
434                 ALOGE("could not disable core file generation for pid %d: %s",
435                     getpid(), strerror(errno));
436             }
437         }
438     }
439 #endif
440 }
441 
442 /*
443  * Set Linux capability flags.
444  *
445  * Returns 0 on success, errno on failure.
446  */
setCapabilities(int64_t permitted,int64_t effective)447 static int setCapabilities(int64_t permitted, int64_t effective)
448 {
449 #ifdef HAVE_ANDROID_OS
450     struct __user_cap_header_struct capheader;
451     struct __user_cap_data_struct capdata;
452 
453     memset(&capheader, 0, sizeof(capheader));
454     memset(&capdata, 0, sizeof(capdata));
455 
456     capheader.version = _LINUX_CAPABILITY_VERSION;
457     capheader.pid = 0;
458 
459     capdata.effective = effective;
460     capdata.permitted = permitted;
461 
462     ALOGV("CAPSET perm=%llx eff=%llx", permitted, effective);
463     if (capset(&capheader, &capdata) != 0)
464         return errno;
465 #endif /*HAVE_ANDROID_OS*/
466 
467     return 0;
468 }
469 
470 /*
471  * Set SELinux security context.
472  *
473  * Returns 0 on success, -1 on failure.
474  */
setSELinuxContext(uid_t uid,bool isSystemServer,const char * seInfo,const char * niceName)475 static int setSELinuxContext(uid_t uid, bool isSystemServer,
476                              const char *seInfo, const char *niceName)
477 {
478 #ifdef HAVE_ANDROID_OS
479     return selinux_android_setcontext(uid, isSystemServer, seInfo, niceName);
480 #else
481     return 0;
482 #endif
483 }
484 
needsNoRandomizeWorkaround()485 static bool needsNoRandomizeWorkaround() {
486 #if !defined(__arm__)
487     return false;
488 #else
489     int major;
490     int minor;
491     struct utsname uts;
492     if (uname(&uts) == -1) {
493         return false;
494     }
495 
496     if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
497         return false;
498     }
499 
500     // Kernels before 3.4.* need the workaround.
501     return (major < 3) || ((major == 3) && (minor < 4));
502 #endif
503 }
504 
505 /*
506  * Utility routine to fork zygote and specialize the child process.
507  */
forkAndSpecializeCommon(const u4 * args,bool isSystemServer)508 static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
509 {
510     pid_t pid;
511 
512     uid_t uid = (uid_t) args[0];
513     gid_t gid = (gid_t) args[1];
514     ArrayObject* gids = (ArrayObject *)args[2];
515     u4 debugFlags = args[3];
516     ArrayObject *rlimits = (ArrayObject *)args[4];
517     u4 mountMode = MOUNT_EXTERNAL_NONE;
518     int64_t permittedCapabilities, effectiveCapabilities;
519     char *seInfo = NULL;
520     char *niceName = NULL;
521 
522     if (isSystemServer) {
523         /*
524          * Don't use GET_ARG_LONG here for now.  gcc is generating code
525          * that uses register d8 as a temporary, and that's coming out
526          * scrambled in the child process.  b/3138621
527          */
528         //permittedCapabilities = GET_ARG_LONG(args, 5);
529         //effectiveCapabilities = GET_ARG_LONG(args, 7);
530         permittedCapabilities = args[5] | (int64_t) args[6] << 32;
531         effectiveCapabilities = args[7] | (int64_t) args[8] << 32;
532     } else {
533         mountMode = args[5];
534         permittedCapabilities = effectiveCapabilities = 0;
535         StringObject* seInfoObj = (StringObject*)args[6];
536         if (seInfoObj) {
537             seInfo = dvmCreateCstrFromString(seInfoObj);
538             if (!seInfo) {
539                 ALOGE("seInfo dvmCreateCstrFromString failed");
540                 dvmAbort();
541             }
542         }
543         StringObject* niceNameObj = (StringObject*)args[7];
544         if (niceNameObj) {
545             niceName = dvmCreateCstrFromString(niceNameObj);
546             if (!niceName) {
547                 ALOGE("niceName dvmCreateCstrFromString failed");
548                 dvmAbort();
549             }
550         }
551     }
552 
553     if (!gDvm.zygote) {
554         dvmThrowIllegalStateException(
555             "VM instance not started with -Xzygote");
556 
557         return -1;
558     }
559 
560     if (!dvmGcPreZygoteFork()) {
561         ALOGE("pre-fork heap failed");
562         dvmAbort();
563     }
564 
565     setSignalHandler();
566 
567     dvmDumpLoaderStats("zygote");
568     pid = fork();
569 
570     if (pid == 0) {
571         int err;
572         /* The child process */
573 
574 #ifdef HAVE_ANDROID_OS
575         extern int gMallocLeakZygoteChild;
576         gMallocLeakZygoteChild = 1;
577 
578         /* keep caps across UID change, unless we're staying root */
579         if (uid != 0) {
580             err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
581 
582             if (err < 0) {
583                 ALOGE("cannot PR_SET_KEEPCAPS: %s", strerror(errno));
584                 dvmAbort();
585             }
586         }
587 
588         for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
589             err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
590             if (err < 0) {
591                 if (errno == EINVAL) {
592                     ALOGW("PR_CAPBSET_DROP %d failed: %s. "
593                           "Please make sure your kernel is compiled with "
594                           "file capabilities support enabled.",
595                           i, strerror(errno));
596                 } else {
597                     ALOGE("PR_CAPBSET_DROP %d failed: %s.", i, strerror(errno));
598                     dvmAbort();
599                 }
600             }
601         }
602 
603 #endif /* HAVE_ANDROID_OS */
604 
605         if (mountMode != MOUNT_EXTERNAL_NONE) {
606             err = mountEmulatedStorage(uid, mountMode);
607             if (err < 0) {
608                 ALOGE("cannot mountExternalStorage(): %s", strerror(errno));
609 
610                 if (errno == ENOTCONN || errno == EROFS) {
611                     // When device is actively encrypting, we get ENOTCONN here
612                     // since FUSE was mounted before the framework restarted.
613                     // When encrypted device is booting, we get EROFS since
614                     // FUSE hasn't been created yet by init.
615                     // In either case, continue without external storage.
616                 } else {
617                     dvmAbort();
618                 }
619             }
620         }
621 
622         err = setgroupsIntarray(gids);
623         if (err < 0) {
624             ALOGE("cannot setgroups(): %s", strerror(errno));
625             dvmAbort();
626         }
627 
628         err = setrlimitsFromArray(rlimits);
629         if (err < 0) {
630             ALOGE("cannot setrlimit(): %s", strerror(errno));
631             dvmAbort();
632         }
633 
634         err = setresgid(gid, gid, gid);
635         if (err < 0) {
636             ALOGE("cannot setresgid(%d): %s", gid, strerror(errno));
637             dvmAbort();
638         }
639 
640         err = setresuid(uid, uid, uid);
641         if (err < 0) {
642             ALOGE("cannot setresuid(%d): %s", uid, strerror(errno));
643             dvmAbort();
644         }
645 
646         if (needsNoRandomizeWorkaround()) {
647             int current = personality(0xffffFFFF);
648             int success = personality((ADDR_NO_RANDOMIZE | current));
649             if (success == -1) {
650                 ALOGW("Personality switch failed. current=%d error=%d\n", current, errno);
651             }
652         }
653 
654         err = setCapabilities(permittedCapabilities, effectiveCapabilities);
655         if (err != 0) {
656             ALOGE("cannot set capabilities (%llx,%llx): %s",
657                 permittedCapabilities, effectiveCapabilities, strerror(err));
658             dvmAbort();
659         }
660 
661         err = set_sched_policy(0, SP_DEFAULT);
662         if (err < 0) {
663             ALOGE("cannot set_sched_policy(0, SP_DEFAULT): %s", strerror(-err));
664             dvmAbort();
665         }
666 
667         err = setSELinuxContext(uid, isSystemServer, seInfo, niceName);
668         if (err < 0) {
669             ALOGE("cannot set SELinux context: %s\n", strerror(errno));
670             dvmAbort();
671         }
672         // These free(3) calls are safe because we know we're only ever forking
673         // a single-threaded process, so we know no other thread held the heap
674         // lock when we forked.
675         free(seInfo);
676         free(niceName);
677 
678         /*
679          * Our system thread ID has changed.  Get the new one.
680          */
681         Thread* thread = dvmThreadSelf();
682         thread->systemTid = dvmGetSysThreadId();
683 
684         /* configure additional debug options */
685         enableDebugFeatures(debugFlags);
686 
687         unsetSignalHandler();
688         gDvm.zygote = false;
689         if (!dvmInitAfterZygote()) {
690             ALOGE("error in post-zygote initialization");
691             dvmAbort();
692         }
693     } else if (pid > 0) {
694         /* the parent process */
695         free(seInfo);
696         free(niceName);
697     }
698 
699     return pid;
700 }
701 
702 /*
703  * native public static int nativeForkAndSpecialize(int uid, int gid,
704  *     int[] gids, int debugFlags, int[][] rlimits, int mountExternal,
705  *     String seInfo, String niceName);
706  */
Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4 * args,JValue * pResult)707 static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args,
708     JValue* pResult)
709 {
710     pid_t pid;
711 
712     pid = forkAndSpecializeCommon(args, false);
713 
714     RETURN_INT(pid);
715 }
716 
717 /*
718  * native public static int nativeForkSystemServer(int uid, int gid,
719  *     int[] gids, int debugFlags, int[][] rlimits,
720  *     long permittedCapabilities, long effectiveCapabilities);
721  */
Dalvik_dalvik_system_Zygote_forkSystemServer(const u4 * args,JValue * pResult)722 static void Dalvik_dalvik_system_Zygote_forkSystemServer(
723         const u4* args, JValue* pResult)
724 {
725     pid_t pid;
726     pid = forkAndSpecializeCommon(args, true);
727 
728     /* The zygote process checks whether the child process has died or not. */
729     if (pid > 0) {
730         int status;
731 
732         ALOGI("System server process %d has been created", pid);
733         gDvm.systemServerPid = pid;
734         /* There is a slight window that the system server process has crashed
735          * but it went unnoticed because we haven't published its pid yet. So
736          * we recheck here just to make sure that all is well.
737          */
738         if (waitpid(pid, &status, WNOHANG) == pid) {
739             ALOGE("System server process %d has died. Restarting Zygote!", pid);
740             kill(getpid(), SIGKILL);
741         }
742     }
743     RETURN_INT(pid);
744 }
745 
746 const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
747     { "nativeFork", "()I",
748       Dalvik_dalvik_system_Zygote_fork },
749     { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I",
750       Dalvik_dalvik_system_Zygote_forkAndSpecialize },
751     { "nativeForkSystemServer", "(II[II[[IJJ)I",
752       Dalvik_dalvik_system_Zygote_forkSystemServer },
753     { NULL, NULL, NULL },
754 };
755