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