• 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     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