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 };
41
42 /*
43 * This signal handler is for zygote mode, since the zygote
44 * must reap its children
45 */
sigchldHandler(int s)46 static void sigchldHandler(int s)
47 {
48 pid_t pid;
49 int status;
50
51 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
52 /* Log process-death status that we care about. In general it is not
53 safe to call LOG(...) from a signal handler because of possible
54 reentrancy. However, we know a priori that the current implementation
55 of LOG() is safe to call from a SIGCHLD handler in the zygote process.
56 If the LOG() implementation changes its locking strategy or its use
57 of syscalls within the lazy-init critical section, its use here may
58 become unsafe. */
59 if (WIFEXITED(status)) {
60 if (WEXITSTATUS(status)) {
61 LOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)\n",
62 (int) pid, WEXITSTATUS(status));
63 } else {
64 IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) {
65 LOG(LOG_VERBOSE, ZYGOTE_LOG_TAG,
66 "Process %d exited cleanly (%d)\n",
67 (int) pid, WEXITSTATUS(status));
68 }
69 }
70 } else if (WIFSIGNALED(status)) {
71 if (WTERMSIG(status) != SIGKILL) {
72 LOG(LOG_DEBUG, ZYGOTE_LOG_TAG,
73 "Process %d terminated by signal (%d)\n",
74 (int) pid, WTERMSIG(status));
75 } else {
76 IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) {
77 LOG(LOG_VERBOSE, ZYGOTE_LOG_TAG,
78 "Process %d terminated by signal (%d)\n",
79 (int) pid, WTERMSIG(status));
80 }
81 }
82 #ifdef WCOREDUMP
83 if (WCOREDUMP(status)) {
84 LOG(LOG_INFO, ZYGOTE_LOG_TAG, "Process %d dumped core\n",
85 (int) pid);
86 }
87 #endif /* ifdef WCOREDUMP */
88 }
89
90 /*
91 * If the just-crashed process is the system_server, bring down zygote
92 * so that it is restarted by init and system server will be restarted
93 * from there.
94 */
95 if (pid == gDvm.systemServerPid) {
96 LOG(LOG_INFO, ZYGOTE_LOG_TAG,
97 "Exit zygote because system server (%d) has terminated\n",
98 (int) pid);
99 kill(getpid(), SIGKILL);
100 }
101 }
102
103 if (pid < 0) {
104 LOG(LOG_WARN, ZYGOTE_LOG_TAG,
105 "Zygote SIGCHLD error (%d) in waitpid\n",errno);
106 }
107 }
108
109 /*
110 * configure sigchld handler for the zygote process
111 * This is configured very late, because earlier in the dalvik lifecycle
112 * we can fork() and exec() for the verifier/optimizer, and we
113 * want to waitpid() for those rather than have them be harvested immediately.
114 *
115 * This ends up being called repeatedly before each fork(), but there's
116 * no real harm in that.
117 */
setSignalHandler()118 static void setSignalHandler()
119 {
120 int err;
121 struct sigaction sa;
122
123 memset(&sa, 0, sizeof(sa));
124
125 sa.sa_handler = sigchldHandler;
126
127 err = sigaction (SIGCHLD, &sa, NULL);
128
129 if (err < 0) {
130 LOGW("Error setting SIGCHLD handler errno: %d", errno);
131 }
132 }
133
134 /*
135 * Set the SIGCHLD handler back to default behavior in zygote children
136 */
unsetSignalHandler()137 static void unsetSignalHandler()
138 {
139 int err;
140 struct sigaction sa;
141
142 memset(&sa, 0, sizeof(sa));
143
144 sa.sa_handler = SIG_DFL;
145
146 err = sigaction (SIGCHLD, &sa, NULL);
147
148 if (err < 0) {
149 LOGW("Error unsetting SIGCHLD handler errno: %d", errno);
150 }
151 }
152
153 /*
154 * Calls POSIX setgroups() using the int[] object as an argument.
155 * A NULL argument is tolerated.
156 */
157
setgroupsIntarray(ArrayObject * gidArray)158 static int setgroupsIntarray(ArrayObject* gidArray)
159 {
160 gid_t *gids;
161 u4 i;
162 s4 *contents;
163
164 if (gidArray == NULL) {
165 return 0;
166 }
167
168 /* just in case gid_t and u4 are different... */
169 gids = alloca(sizeof(gid_t) * gidArray->length);
170 contents = (s4 *)gidArray->contents;
171
172 for (i = 0 ; i < gidArray->length ; i++) {
173 gids[i] = (gid_t) contents[i];
174 }
175
176 return setgroups((size_t) gidArray->length, gids);
177 }
178
179 /*
180 * Sets the resource limits via setrlimit(2) for the values in the
181 * two-dimensional array of integers that's passed in. The second dimension
182 * contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
183 * treated as an empty array.
184 *
185 * -1 is returned on error.
186 */
setrlimitsFromArray(ArrayObject * rlimits)187 static int setrlimitsFromArray(ArrayObject* rlimits)
188 {
189 u4 i;
190 struct rlimit rlim;
191
192 if (rlimits == NULL) {
193 return 0;
194 }
195
196 memset (&rlim, 0, sizeof(rlim));
197
198 ArrayObject** tuples = (ArrayObject **)(rlimits->contents);
199
200 for (i = 0; i < rlimits->length; i++) {
201 ArrayObject * rlimit_tuple = tuples[i];
202 s4* contents = (s4 *)rlimit_tuple->contents;
203 int err;
204
205 if (rlimit_tuple->length != 3) {
206 LOGE("rlimits array must have a second dimension of size 3");
207 return -1;
208 }
209
210 rlim.rlim_cur = contents[1];
211 rlim.rlim_max = contents[2];
212
213 err = setrlimit(contents[0], &rlim);
214
215 if (err < 0) {
216 return -1;
217 }
218 }
219
220 return 0;
221 }
222
223 /* native public static int fork(); */
Dalvik_dalvik_system_Zygote_fork(const u4 * args,JValue * pResult)224 static void Dalvik_dalvik_system_Zygote_fork(const u4* args, JValue* pResult)
225 {
226 pid_t pid;
227 int err;
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 */
enableDebugFeatures(u4 debugFlags)273 static void enableDebugFeatures(u4 debugFlags)
274 {
275 LOGV("debugFlags is 0x%02x\n", debugFlags);
276
277 gDvm.jdwpAllowed = ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0);
278
279 if ((debugFlags & DEBUG_ENABLE_CHECKJNI) != 0) {
280 /* turn it on if it's not already enabled */
281 dvmLateEnableCheckedJni();
282 }
283
284 if ((debugFlags & DEBUG_ENABLE_ASSERT) != 0) {
285 /* turn it on if it's not already enabled */
286 dvmLateEnableAssertions();
287 }
288 }
289
290 /*
291 * Utility routine to fork zygote and specialize the child process.
292 */
forkAndSpecializeCommon(const u4 * args)293 static pid_t forkAndSpecializeCommon(const u4* args)
294 {
295 pid_t pid;
296
297 uid_t uid = (uid_t) args[0];
298 gid_t gid = (gid_t) args[1];
299 ArrayObject* gids = (ArrayObject *)args[2];
300 u4 debugFlags = args[3];
301 ArrayObject *rlimits = (ArrayObject *)args[4];
302
303 if (!gDvm.zygote) {
304 dvmThrowException("Ljava/lang/IllegalStateException;",
305 "VM instance not started with -Xzygote");
306
307 return -1;
308 }
309
310 if (!dvmGcPreZygoteFork()) {
311 LOGE("pre-fork heap failed\n");
312 dvmAbort();
313 }
314
315 setSignalHandler();
316
317 dvmDumpLoaderStats("zygote");
318 pid = fork();
319
320 if (pid == 0) {
321 int err;
322 /* The child process */
323
324 #ifdef HAVE_ANDROID_OS
325 extern int gMallocLeakZygoteChild;
326 gMallocLeakZygoteChild = 1;
327
328 /* keep caps across UID change, unless we're staying root */
329 if (uid != 0) {
330 err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
331
332 if (err < 0) {
333 LOGW("cannot PR_SET_KEEPCAPS errno: %d", errno);
334 }
335 }
336
337 #endif /* HAVE_ANDROID_OS */
338
339 err = setgroupsIntarray(gids);
340
341 if (err < 0) {
342 LOGW("cannot setgroups() errno: %d", errno);
343 }
344
345 err = setrlimitsFromArray(rlimits);
346
347 if (err < 0) {
348 LOGW("cannot setrlimit() errno: %d", errno);
349 }
350
351 err = setgid(gid);
352 if (err < 0) {
353 LOGW("cannot setgid(%d) errno: %d", gid, errno);
354 }
355
356 err = setuid(uid);
357 if (err < 0) {
358 LOGW("cannot setuid(%d) errno: %d", uid, errno);
359 }
360
361 /*
362 * Our system thread ID has changed. Get the new one.
363 */
364 Thread* thread = dvmThreadSelf();
365 thread->systemTid = dvmGetSysThreadId();
366
367 /* configure additional debug options */
368 enableDebugFeatures(debugFlags);
369
370 unsetSignalHandler();
371 gDvm.zygote = false;
372 if (!dvmInitAfterZygote()) {
373 LOGE("error in post-zygote initialization\n");
374 dvmAbort();
375 }
376 } else if (pid > 0) {
377 /* the parent process */
378 }
379
380 return pid;
381 }
382
383 /* native public static int forkAndSpecialize(int uid, int gid,
384 * int[] gids, int debugFlags);
385 */
Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4 * args,JValue * pResult)386 static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args,
387 JValue* pResult)
388 {
389 pid_t pid;
390
391 pid = forkAndSpecializeCommon(args);
392
393 RETURN_INT(pid);
394 }
395
396 /* native public static int forkSystemServer(int uid, int gid,
397 * int[] gids, int debugFlags);
398 */
Dalvik_dalvik_system_Zygote_forkSystemServer(const u4 * args,JValue * pResult)399 static void Dalvik_dalvik_system_Zygote_forkSystemServer(
400 const u4* args, JValue* pResult)
401 {
402 pid_t pid;
403 pid = forkAndSpecializeCommon(args);
404
405 /* The zygote process checks whether the child process has died or not. */
406 if (pid > 0) {
407 int status;
408
409 LOGI("System server process %d has been created", pid);
410 gDvm.systemServerPid = pid;
411 /* There is a slight window that the system server process has crashed
412 * but it went unnoticed because we haven't published its pid yet. So
413 * we recheck here just to make sure that all is well.
414 */
415 if (waitpid(pid, &status, WNOHANG) == pid) {
416 LOGE("System server process %d has died. Restarting Zygote!", pid);
417 kill(getpid(), SIGKILL);
418 }
419 }
420 RETURN_INT(pid);
421 }
422
423 const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
424 { "fork", "()I",
425 Dalvik_dalvik_system_Zygote_fork },
426 { "forkAndSpecialize", "(II[II[[I)I",
427 Dalvik_dalvik_system_Zygote_forkAndSpecialize },
428 { "forkSystemServer", "(II[II[[I)I",
429 Dalvik_dalvik_system_Zygote_forkSystemServer },
430 { NULL, NULL, NULL },
431 };
432
433