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