com_android_internal_os_Zygote.cpp revision 6a4d2369e5493cea86817634eceb0be46ba7d7a6
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#define LOG_TAG "Zygote"
18
19// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
20#include <sys/mount.h>
21#include <linux/fs.h>
22
23#include <grp.h>
24#include <fcntl.h>
25#include <paths.h>
26#include <signal.h>
27#include <stdlib.h>
28#include <unistd.h>
29#include <sys/capability.h>
30#include <sys/personality.h>
31#include <sys/prctl.h>
32#include <sys/resource.h>
33#include <sys/stat.h>
34#include <sys/types.h>
35#include <sys/utsname.h>
36#include <sys/wait.h>
37
38
39#include <cutils/fs.h>
40#include <cutils/multiuser.h>
41#include <cutils/sched_policy.h>
42#include <utils/String8.h>
43#include <selinux/android.h>
44
45#include "android_runtime/AndroidRuntime.h"
46#include "JNIHelp.h"
47#include "ScopedLocalRef.h"
48#include "ScopedPrimitiveArray.h"
49#include "ScopedUtfChars.h"
50
51#include "nativebridge/native_bridge.h"
52
53namespace {
54
55using android::String8;
56
57static pid_t gSystemServerPid = 0;
58
59static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
60static jclass gZygoteClass;
61static jmethodID gCallPostForkChildHooks;
62
63// Must match values in com.android.internal.os.Zygote.
64enum MountExternalKind {
65  MOUNT_EXTERNAL_NONE = 0,
66  MOUNT_EXTERNAL_SINGLEUSER = 1,
67  MOUNT_EXTERNAL_MULTIUSER = 2,
68  MOUNT_EXTERNAL_MULTIUSER_ALL = 3,
69};
70
71static void RuntimeAbort(JNIEnv* env) {
72  env->FatalError("RuntimeAbort");
73}
74
75// This signal handler is for zygote mode, since the zygote must reap its children
76static void SigChldHandler(int /*signal_number*/) {
77  pid_t pid;
78  int status;
79
80  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
81     // Log process-death status that we care about.  In general it is
82     // not safe to call LOG(...) from a signal handler because of
83     // possible reentrancy.  However, we know a priori that the
84     // current implementation of LOG() is safe to call from a SIGCHLD
85     // handler in the zygote process.  If the LOG() implementation
86     // changes its locking strategy or its use of syscalls within the
87     // lazy-init critical section, its use here may become unsafe.
88    if (WIFEXITED(status)) {
89      if (WEXITSTATUS(status)) {
90        ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
91      }
92    } else if (WIFSIGNALED(status)) {
93      if (WTERMSIG(status) != SIGKILL) {
94        ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
95      }
96      if (WCOREDUMP(status)) {
97        ALOGI("Process %d dumped core.", pid);
98      }
99    }
100
101    // If the just-crashed process is the system_server, bring down zygote
102    // so that it is restarted by init and system server will be restarted
103    // from there.
104    if (pid == gSystemServerPid) {
105      ALOGE("Exit zygote because system server (%d) has terminated");
106      kill(getpid(), SIGKILL);
107    }
108  }
109
110  // Note that we shouldn't consider ECHILD an error because
111  // the secondary zygote might have no children left to wait for.
112  if (pid < 0 && errno != ECHILD) {
113    ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno));
114  }
115}
116
117// Configures the SIGCHLD handler for the zygote process. This is configured
118// very late, because earlier in the runtime we may fork() and exec()
119// other processes, and we want to waitpid() for those rather than
120// have them be harvested immediately.
121//
122// This ends up being called repeatedly before each fork(), but there's
123// no real harm in that.
124static void SetSigChldHandler() {
125  struct sigaction sa;
126  memset(&sa, 0, sizeof(sa));
127  sa.sa_handler = SigChldHandler;
128
129  int err = sigaction(SIGCHLD, &sa, NULL);
130  if (err < 0) {
131    ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
132  }
133}
134
135// Sets the SIGCHLD handler back to default behavior in zygote children.
136static void UnsetSigChldHandler() {
137  struct sigaction sa;
138  memset(&sa, 0, sizeof(sa));
139  sa.sa_handler = SIG_DFL;
140
141  int err = sigaction(SIGCHLD, &sa, NULL);
142  if (err < 0) {
143    ALOGW("Error unsetting SIGCHLD handler: %s", strerror(errno));
144  }
145}
146
147// Calls POSIX setgroups() using the int[] object as an argument.
148// A NULL argument is tolerated.
149static void SetGids(JNIEnv* env, jintArray javaGids) {
150  if (javaGids == NULL) {
151    return;
152  }
153
154  ScopedIntArrayRO gids(env, javaGids);
155  if (gids.get() == NULL) {
156      RuntimeAbort(env);
157  }
158  int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
159  if (rc == -1) {
160    ALOGE("setgroups failed");
161    RuntimeAbort(env);
162  }
163}
164
165// Sets the resource limits via setrlimit(2) for the values in the
166// two-dimensional array of integers that's passed in. The second dimension
167// contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
168// treated as an empty array.
169static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
170  if (javaRlimits == NULL) {
171    return;
172  }
173
174  rlimit rlim;
175  memset(&rlim, 0, sizeof(rlim));
176
177  for (int i = 0; i < env->GetArrayLength(javaRlimits); ++i) {
178    ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
179    ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
180    if (javaRlimit.size() != 3) {
181      ALOGE("rlimits array must have a second dimension of size 3");
182      RuntimeAbort(env);
183    }
184
185    rlim.rlim_cur = javaRlimit[1];
186    rlim.rlim_max = javaRlimit[2];
187
188    int rc = setrlimit(javaRlimit[0], &rlim);
189    if (rc == -1) {
190      ALOGE("setrlimit(%d, {%d, %d}) failed", javaRlimit[0], rlim.rlim_cur, rlim.rlim_max);
191      RuntimeAbort(env);
192    }
193  }
194}
195
196// The debug malloc library needs to know whether it's the zygote or a child.
197extern "C" int gMallocLeakZygoteChild;
198
199static void EnableKeepCapabilities(JNIEnv* env) {
200  int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
201  if (rc == -1) {
202    ALOGE("prctl(PR_SET_KEEPCAPS) failed");
203    RuntimeAbort(env);
204  }
205}
206
207static void DropCapabilitiesBoundingSet(JNIEnv* env) {
208  for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
209    int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
210    if (rc == -1) {
211      if (errno == EINVAL) {
212        ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
213              "your kernel is compiled with file capabilities support");
214      } else {
215        ALOGE("prctl(PR_CAPBSET_DROP) failed");
216        RuntimeAbort(env);
217      }
218    }
219  }
220}
221
222static void SetCapabilities(JNIEnv* env, int64_t permitted, int64_t effective) {
223  __user_cap_header_struct capheader;
224  memset(&capheader, 0, sizeof(capheader));
225  capheader.version = _LINUX_CAPABILITY_VERSION_3;
226  capheader.pid = 0;
227
228  __user_cap_data_struct capdata[2];
229  memset(&capdata, 0, sizeof(capdata));
230  capdata[0].effective = effective;
231  capdata[1].effective = effective >> 32;
232  capdata[0].permitted = permitted;
233  capdata[1].permitted = permitted >> 32;
234
235  if (capset(&capheader, &capdata[0]) == -1) {
236    ALOGE("capset(%lld, %lld) failed", permitted, effective);
237    RuntimeAbort(env);
238  }
239}
240
241static void SetSchedulerPolicy(JNIEnv* env) {
242  errno = -set_sched_policy(0, SP_DEFAULT);
243  if (errno != 0) {
244    ALOGE("set_sched_policy(0, SP_DEFAULT) failed");
245    RuntimeAbort(env);
246  }
247}
248
249// Create a private mount namespace and bind mount appropriate emulated
250// storage for the given user.
251static bool MountEmulatedStorage(uid_t uid, jint mount_mode, bool force_mount_namespace) {
252  if (mount_mode == MOUNT_EXTERNAL_NONE && !force_mount_namespace) {
253    return true;
254  }
255
256  // Create a second private mount namespace for our process
257  if (unshare(CLONE_NEWNS) == -1) {
258      ALOGW("Failed to unshare(): %s", strerror(errno));
259      return false;
260  }
261
262  if (mount_mode == MOUNT_EXTERNAL_NONE) {
263    return true;
264  }
265
266  // See storage config details at http://source.android.com/tech/storage/
267  userid_t user_id = multiuser_get_user_id(uid);
268
269  // Create bind mounts to expose external storage
270  if (mount_mode == MOUNT_EXTERNAL_MULTIUSER || mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
271    // These paths must already be created by init.rc
272    const char* source = getenv("EMULATED_STORAGE_SOURCE");
273    const char* target = getenv("EMULATED_STORAGE_TARGET");
274    const char* legacy = getenv("EXTERNAL_STORAGE");
275    if (source == NULL || target == NULL || legacy == NULL) {
276      ALOGW("Storage environment undefined; unable to provide external storage");
277      return false;
278    }
279
280    // Prepare source paths
281
282    // /mnt/shell/emulated/0
283    const String8 source_user(String8::format("%s/%d", source, user_id));
284    // /storage/emulated/0
285    const String8 target_user(String8::format("%s/%d", target, user_id));
286
287    if (fs_prepare_dir(source_user.string(), 0000, 0, 0) == -1
288        || fs_prepare_dir(target_user.string(), 0000, 0, 0) == -1) {
289      return false;
290    }
291
292    if (mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
293      // Mount entire external storage tree for all users
294      if (TEMP_FAILURE_RETRY(mount(source, target, NULL, MS_BIND, NULL)) == -1) {
295        ALOGW("Failed to mount %s to %s: %s", source, target, strerror(errno));
296        return false;
297      }
298    } else {
299      // Only mount user-specific external storage
300      if (TEMP_FAILURE_RETRY(mount(source_user.string(), target_user.string(), NULL,
301                                   MS_BIND, NULL)) == -1) {
302        ALOGW("Failed to mount %s to %s: %s", source_user.string(), target_user.string(),
303              strerror(errno));
304        return false;
305      }
306    }
307
308    if (fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
309        return false;
310    }
311
312    // Finally, mount user-specific path into place for legacy users
313    if (TEMP_FAILURE_RETRY(
314            mount(target_user.string(), legacy, NULL, MS_BIND | MS_REC, NULL)) == -1) {
315      ALOGW("Failed to mount %s to %s: %s", target_user.string(), legacy, strerror(errno));
316      return false;
317    }
318  } else {
319    ALOGW("Mount mode %d unsupported", mount_mode);
320    return false;
321  }
322
323  return true;
324}
325
326static bool NeedsNoRandomizeWorkaround() {
327#if !defined(__arm__)
328    return false;
329#else
330    int major;
331    int minor;
332    struct utsname uts;
333    if (uname(&uts) == -1) {
334        return false;
335    }
336
337    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
338        return false;
339    }
340
341    // Kernels before 3.4.* need the workaround.
342    return (major < 3) || ((major == 3) && (minor < 4));
343#endif
344}
345
346// Utility to close down the Zygote socket file descriptors while
347// the child is still running as root with Zygote's privileges.  Each
348// descriptor (if any) is closed via dup2(), replacing it with a valid
349// (open) descriptor to /dev/null.
350
351static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) {
352  if (!fdsToClose) {
353    return;
354  }
355  jsize count = env->GetArrayLength(fdsToClose);
356  jint *ar = env->GetIntArrayElements(fdsToClose, 0);
357  if (!ar) {
358      ALOGE("Bad fd array");
359      RuntimeAbort(env);
360  }
361  jsize i;
362  int devnull;
363  for (i = 0; i < count; i++) {
364    devnull = open("/dev/null", O_RDWR);
365    if (devnull < 0) {
366      ALOGE("Failed to open /dev/null: %s", strerror(errno));
367      RuntimeAbort(env);
368      continue;
369    }
370    ALOGV("Switching descriptor %d to /dev/null: %s", ar[i], strerror(errno));
371    if (dup2(devnull, ar[i]) < 0) {
372      ALOGE("Failed dup2() on descriptor %d: %s", ar[i], strerror(errno));
373      RuntimeAbort(env);
374    }
375    close(devnull);
376  }
377}
378
379void SetThreadName(const char* thread_name) {
380  bool hasAt = false;
381  bool hasDot = false;
382  const char* s = thread_name;
383  while (*s) {
384    if (*s == '.') {
385      hasDot = true;
386    } else if (*s == '@') {
387      hasAt = true;
388    }
389    s++;
390  }
391  const int len = s - thread_name;
392  if (len < 15 || hasAt || !hasDot) {
393    s = thread_name;
394  } else {
395    s = thread_name + len - 15;
396  }
397  // pthread_setname_np fails rather than truncating long strings.
398  char buf[16];       // MAX_TASK_COMM_LEN=16 is hard-coded into bionic
399  strlcpy(buf, s, sizeof(buf)-1);
400  errno = pthread_setname_np(pthread_self(), buf);
401  if (errno != 0) {
402    ALOGW("Unable to set the name of current thread to '%s': %s", buf, strerror(errno));
403  }
404}
405
406// Utility routine to fork zygote and specialize the child process.
407static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
408                                     jint debug_flags, jobjectArray javaRlimits,
409                                     jlong permittedCapabilities, jlong effectiveCapabilities,
410                                     jint mount_external,
411                                     jstring java_se_info, jstring java_se_name,
412                                     bool is_system_server, jintArray fdsToClose,
413                                     jstring instructionSet, jstring dataDir) {
414  SetSigChldHandler();
415
416  pid_t pid = fork();
417
418  if (pid == 0) {
419    // The child process.
420    gMallocLeakZygoteChild = 1;
421
422    // Clean up any descriptors which must be closed immediately
423    DetachDescriptors(env, fdsToClose);
424
425    // Keep capabilities across UID change, unless we're staying root.
426    if (uid != 0) {
427      EnableKeepCapabilities(env);
428    }
429
430    DropCapabilitiesBoundingSet(env);
431
432    bool use_native_bridge = !is_system_server && (instructionSet != NULL)
433        && android::NativeBridgeAvailable();
434    if (use_native_bridge) {
435      ScopedUtfChars isa_string(env, instructionSet);
436      use_native_bridge = android::NeedsNativeBridge(isa_string.c_str());
437    }
438    if (use_native_bridge && dataDir == NULL) {
439      // dataDir should never be null if we need to use a native bridge.
440      // In general, dataDir will never be null for normal applications. It can only happen in
441      // special cases (for isolated processes which are not associated with any app). These are
442      // launched by the framework and should not be emulated anyway.
443      use_native_bridge = false;
444      ALOGW("Native bridge will not be used because dataDir == NULL.");
445    }
446
447    if (!MountEmulatedStorage(uid, mount_external, use_native_bridge)) {
448      ALOGW("Failed to mount emulated storage: %s", strerror(errno));
449      if (errno == ENOTCONN || errno == EROFS) {
450        // When device is actively encrypting, we get ENOTCONN here
451        // since FUSE was mounted before the framework restarted.
452        // When encrypted device is booting, we get EROFS since
453        // FUSE hasn't been created yet by init.
454        // In either case, continue without external storage.
455      } else {
456        ALOGE("Cannot continue without emulated storage");
457        RuntimeAbort(env);
458      }
459    }
460
461    SetGids(env, javaGids);
462
463    SetRLimits(env, javaRlimits);
464
465    if (use_native_bridge) {
466      ScopedUtfChars isa_string(env, instructionSet);
467      ScopedUtfChars data_dir(env, dataDir);
468      android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str());
469    }
470
471    int rc = setresgid(gid, gid, gid);
472    if (rc == -1) {
473      ALOGE("setresgid(%d) failed: %s", gid, strerror(errno));
474      RuntimeAbort(env);
475    }
476
477    rc = setresuid(uid, uid, uid);
478    if (rc == -1) {
479      ALOGE("setresuid(%d) failed: %s", uid, strerror(errno));
480      RuntimeAbort(env);
481    }
482
483    if (NeedsNoRandomizeWorkaround()) {
484        // Work around ARM kernel ASLR lossage (http://b/5817320).
485        int old_personality = personality(0xffffffff);
486        int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
487        if (new_personality == -1) {
488            ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
489        }
490    }
491
492    SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
493
494    SetSchedulerPolicy(env);
495
496    const char* se_info_c_str = NULL;
497    ScopedUtfChars* se_info = NULL;
498    if (java_se_info != NULL) {
499        se_info = new ScopedUtfChars(env, java_se_info);
500        se_info_c_str = se_info->c_str();
501        if (se_info_c_str == NULL) {
502          ALOGE("se_info_c_str == NULL");
503          RuntimeAbort(env);
504        }
505    }
506    const char* se_name_c_str = NULL;
507    ScopedUtfChars* se_name = NULL;
508    if (java_se_name != NULL) {
509        se_name = new ScopedUtfChars(env, java_se_name);
510        se_name_c_str = se_name->c_str();
511        if (se_name_c_str == NULL) {
512          ALOGE("se_name_c_str == NULL");
513          RuntimeAbort(env);
514        }
515    }
516    rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
517    if (rc == -1) {
518      ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
519            is_system_server, se_info_c_str, se_name_c_str);
520      RuntimeAbort(env);
521    }
522
523    // Make it easier to debug audit logs by setting the main thread's name to the
524    // nice name rather than "app_process".
525    if (se_info_c_str == NULL && is_system_server) {
526      se_name_c_str = "system_server";
527    }
528    if (se_info_c_str != NULL) {
529      SetThreadName(se_name_c_str);
530    }
531
532    delete se_info;
533    delete se_name;
534
535    UnsetSigChldHandler();
536
537    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
538                              is_system_server ? NULL : instructionSet);
539    if (env->ExceptionCheck()) {
540      ALOGE("Error calling post fork hooks.");
541      RuntimeAbort(env);
542    }
543  } else if (pid > 0) {
544    // the parent process
545  }
546  return pid;
547}
548}  // anonymous namespace
549
550namespace android {
551
552static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
553        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
554        jint debug_flags, jobjectArray rlimits,
555        jint mount_external, jstring se_info, jstring se_name,
556        jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
557    return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
558            rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose,
559            instructionSet, appDataDir);
560}
561
562static jint com_android_internal_os_Zygote_nativeForkSystemServer(
563        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
564        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
565        jlong effectiveCapabilities) {
566  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
567                                      debug_flags, rlimits,
568                                      permittedCapabilities, effectiveCapabilities,
569                                      MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL,
570                                      NULL, NULL);
571  if (pid > 0) {
572      // The zygote process checks whether the child process has died or not.
573      ALOGI("System server process %d has been created", pid);
574      gSystemServerPid = pid;
575      // There is a slight window that the system server process has crashed
576      // but it went unnoticed because we haven't published its pid yet. So
577      // we recheck here just to make sure that all is well.
578      int status;
579      if (waitpid(pid, &status, WNOHANG) == pid) {
580          ALOGE("System server process %d has died. Restarting Zygote!", pid);
581          RuntimeAbort(env);
582      }
583  }
584  return pid;
585}
586
587static JNINativeMethod gMethods[] = {
588    { "nativeForkAndSpecialize",
589      "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
590      (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
591    { "nativeForkSystemServer", "(II[II[[IJJ)I",
592      (void *) com_android_internal_os_Zygote_nativeForkSystemServer }
593};
594
595int register_com_android_internal_os_Zygote(JNIEnv* env) {
596  gZygoteClass = (jclass) env->NewGlobalRef(env->FindClass(kZygoteClassName));
597  if (gZygoteClass == NULL) {
598    RuntimeAbort(env);
599  }
600  gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks",
601                                                   "(ILjava/lang/String;)V");
602
603  return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote",
604      gMethods, NELEM(gMethods));
605}
606}  // namespace android
607
608