• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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