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