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