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