com_android_internal_os_Zygote.cpp revision 79ec4c15ab941419d21700a9734f5238b975c31a
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    if (!is_system_server && dataDir == NULL) {
420        ALOGE("Application private dir cannot be null");
421        RuntimeAbort(env);
422    }
423    // The child process.
424    gMallocLeakZygoteChild = 1;
425
426    // Clean up any descriptors which must be closed immediately
427    DetachDescriptors(env, fdsToClose);
428
429    // Keep capabilities across UID change, unless we're staying root.
430    if (uid != 0) {
431      EnableKeepCapabilities(env);
432    }
433
434    DropCapabilitiesBoundingSet(env);
435
436    bool use_native_bridge = !is_system_server && (instructionSet != NULL)
437        && android::NativeBridgeAvailable();
438    if (use_native_bridge) {
439      ScopedUtfChars isa_string(env, instructionSet);
440      use_native_bridge = android::NeedsNativeBridge(isa_string.c_str());
441    }
442
443    if (!MountEmulatedStorage(uid, mount_external, use_native_bridge)) {
444      ALOGW("Failed to mount emulated storage: %s", strerror(errno));
445      if (errno == ENOTCONN || errno == EROFS) {
446        // When device is actively encrypting, we get ENOTCONN here
447        // since FUSE was mounted before the framework restarted.
448        // When encrypted device is booting, we get EROFS since
449        // FUSE hasn't been created yet by init.
450        // In either case, continue without external storage.
451      } else {
452        ALOGE("Cannot continue without emulated storage");
453        RuntimeAbort(env);
454      }
455    }
456
457    SetGids(env, javaGids);
458
459    SetRLimits(env, javaRlimits);
460
461    if (use_native_bridge) {
462      ScopedUtfChars isa_string(env, instructionSet);
463      ScopedUtfChars data_dir(env, dataDir);
464      android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str());
465    }
466
467    int rc = setresgid(gid, gid, gid);
468    if (rc == -1) {
469      ALOGE("setresgid(%d) failed: %s", gid, strerror(errno));
470      RuntimeAbort(env);
471    }
472
473    rc = setresuid(uid, uid, uid);
474    if (rc == -1) {
475      ALOGE("setresuid(%d) failed: %s", uid, strerror(errno));
476      RuntimeAbort(env);
477    }
478
479    if (NeedsNoRandomizeWorkaround()) {
480        // Work around ARM kernel ASLR lossage (http://b/5817320).
481        int old_personality = personality(0xffffffff);
482        int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
483        if (new_personality == -1) {
484            ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
485        }
486    }
487
488    SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
489
490    SetSchedulerPolicy(env);
491
492    const char* se_info_c_str = NULL;
493    ScopedUtfChars* se_info = NULL;
494    if (java_se_info != NULL) {
495        se_info = new ScopedUtfChars(env, java_se_info);
496        se_info_c_str = se_info->c_str();
497        if (se_info_c_str == NULL) {
498          ALOGE("se_info_c_str == NULL");
499          RuntimeAbort(env);
500        }
501    }
502    const char* se_name_c_str = NULL;
503    ScopedUtfChars* se_name = NULL;
504    if (java_se_name != NULL) {
505        se_name = new ScopedUtfChars(env, java_se_name);
506        se_name_c_str = se_name->c_str();
507        if (se_name_c_str == NULL) {
508          ALOGE("se_name_c_str == NULL");
509          RuntimeAbort(env);
510        }
511    }
512    rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
513    if (rc == -1) {
514      ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
515            is_system_server, se_info_c_str, se_name_c_str);
516      RuntimeAbort(env);
517    }
518
519    // Make it easier to debug audit logs by setting the main thread's name to the
520    // nice name rather than "app_process".
521    if (se_info_c_str == NULL && is_system_server) {
522      se_name_c_str = "system_server";
523    }
524    if (se_info_c_str != NULL) {
525      SetThreadName(se_name_c_str);
526    }
527
528    delete se_info;
529    delete se_name;
530
531    UnsetSigChldHandler();
532
533    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
534                              is_system_server ? NULL : instructionSet);
535    if (env->ExceptionCheck()) {
536      ALOGE("Error calling post fork hooks.");
537      RuntimeAbort(env);
538    }
539  } else if (pid > 0) {
540    // the parent process
541  }
542  return pid;
543}
544}  // anonymous namespace
545
546namespace android {
547
548static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
549        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
550        jint debug_flags, jobjectArray rlimits,
551        jint mount_external, jstring se_info, jstring se_name,
552        jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
553    return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
554            rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose,
555            instructionSet, appDataDir);
556}
557
558static jint com_android_internal_os_Zygote_nativeForkSystemServer(
559        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
560        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
561        jlong effectiveCapabilities) {
562  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
563                                      debug_flags, rlimits,
564                                      permittedCapabilities, effectiveCapabilities,
565                                      MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL,
566                                      NULL, NULL);
567  if (pid > 0) {
568      // The zygote process checks whether the child process has died or not.
569      ALOGI("System server process %d has been created", pid);
570      gSystemServerPid = pid;
571      // There is a slight window that the system server process has crashed
572      // but it went unnoticed because we haven't published its pid yet. So
573      // we recheck here just to make sure that all is well.
574      int status;
575      if (waitpid(pid, &status, WNOHANG) == pid) {
576          ALOGE("System server process %d has died. Restarting Zygote!", pid);
577          RuntimeAbort(env);
578      }
579  }
580  return pid;
581}
582
583static JNINativeMethod gMethods[] = {
584    { "nativeForkAndSpecialize",
585      "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
586      (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
587    { "nativeForkSystemServer", "(II[II[[IJJ)I",
588      (void *) com_android_internal_os_Zygote_nativeForkSystemServer }
589};
590
591int register_com_android_internal_os_Zygote(JNIEnv* env) {
592  gZygoteClass = (jclass) env->NewGlobalRef(env->FindClass(kZygoteClassName));
593  if (gZygoteClass == NULL) {
594    RuntimeAbort(env);
595  }
596  gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks",
597                                                   "(ILjava/lang/String;)V");
598
599  return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote",
600      gMethods, NELEM(gMethods));
601}
602}  // namespace android
603
604