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