1 /* 2 * Copyright (C) 2014 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 package com.android.internal.os; 18 19 import android.os.IVold; 20 import android.os.Trace; 21 import android.system.ErrnoException; 22 import android.system.Os; 23 24 import dalvik.system.ZygoteHooks; 25 26 /** @hide */ 27 public final class Zygote { 28 /* 29 * Bit values for "runtimeFlags" argument. The definitions are duplicated 30 * in the native code. 31 */ 32 33 /** enable debugging over JDWP */ 34 public static final int DEBUG_ENABLE_JDWP = 1; 35 /** enable JNI checks */ 36 public static final int DEBUG_ENABLE_CHECKJNI = 1 << 1; 37 /** enable Java programming language "assert" statements */ 38 public static final int DEBUG_ENABLE_ASSERT = 1 << 2; 39 /** disable the AOT compiler and JIT */ 40 public static final int DEBUG_ENABLE_SAFEMODE = 1 << 3; 41 /** Enable logging of third-party JNI activity. */ 42 public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4; 43 /** Force generation of native debugging information. */ 44 public static final int DEBUG_GENERATE_DEBUG_INFO = 1 << 5; 45 /** Always use JIT-ed code. */ 46 public static final int DEBUG_ALWAYS_JIT = 1 << 6; 47 /** Make the code native debuggable by turning off some optimizations. */ 48 public static final int DEBUG_NATIVE_DEBUGGABLE = 1 << 7; 49 /** Make the code Java debuggable by turning off some optimizations. */ 50 public static final int DEBUG_JAVA_DEBUGGABLE = 1 << 8; 51 52 /** Turn off the verifier. */ 53 public static final int DISABLE_VERIFIER = 1 << 9; 54 /** Only use oat files located in /system. Otherwise use dex/jar/apk . */ 55 public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10; 56 /** Force generation of native debugging information for backtraces. */ 57 public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 11; 58 /** 59 * Hidden API access restrictions. This is a mask for bits representing the API enforcement 60 * policy, defined by {@code @ApplicationInfo.HiddenApiEnforcementPolicy}. 61 */ 62 public static final int API_ENFORCEMENT_POLICY_MASK = (1 << 12) | (1 << 13); 63 /** 64 * Bit shift for use with {@link #API_ENFORCEMENT_POLICY_MASK}. 65 * 66 * (flags & API_ENFORCEMENT_POLICY_MASK) >> API_ENFORCEMENT_POLICY_SHIFT gives 67 * @ApplicationInfo.ApiEnforcementPolicy values. 68 */ 69 public static final int API_ENFORCEMENT_POLICY_SHIFT = 70 Integer.numberOfTrailingZeros(API_ENFORCEMENT_POLICY_MASK); 71 /** 72 * Enable system server ART profiling. 73 */ 74 public static final int PROFILE_SYSTEM_SERVER = 1 << 14; 75 76 /** No external storage should be mounted. */ 77 public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE; 78 /** Default external storage should be mounted. */ 79 public static final int MOUNT_EXTERNAL_DEFAULT = IVold.REMOUNT_MODE_DEFAULT; 80 /** Read-only external storage should be mounted. */ 81 public static final int MOUNT_EXTERNAL_READ = IVold.REMOUNT_MODE_READ; 82 /** Read-write external storage should be mounted. */ 83 public static final int MOUNT_EXTERNAL_WRITE = IVold.REMOUNT_MODE_WRITE; 84 85 private static final ZygoteHooks VM_HOOKS = new ZygoteHooks(); 86 87 /** 88 * An extraArg passed when a zygote process is forking a child-zygote, specifying a name 89 * in the abstract socket namespace. This socket name is what the new child zygote 90 * should listen for connections on. 91 */ 92 public static final String CHILD_ZYGOTE_SOCKET_NAME_ARG = "--zygote-socket="; 93 Zygote()94 private Zygote() {} 95 96 /** Called for some security initialization before any fork. */ nativeSecurityInit()97 native static void nativeSecurityInit(); 98 99 /** 100 * Forks a new VM instance. The current VM must have been started 101 * with the -Xzygote flag. <b>NOTE: new instance keeps all 102 * root capabilities. The new process is expected to call capset()</b>. 103 * 104 * @param uid the UNIX uid that the new process should setuid() to after 105 * fork()ing and and before spawning any threads. 106 * @param gid the UNIX gid that the new process should setgid() to after 107 * fork()ing and and before spawning any threads. 108 * @param gids null-ok; a list of UNIX gids that the new process should 109 * setgroups() to after fork and before spawning any threads. 110 * @param runtimeFlags bit flags that enable ART features. 111 * @param rlimits null-ok an array of rlimit tuples, with the second 112 * dimension having a length of 3 and representing 113 * (resource, rlim_cur, rlim_max). These are set via the posix 114 * setrlimit(2) call. 115 * @param seInfo null-ok a string specifying SELinux information for 116 * the new process. 117 * @param niceName null-ok a string specifying the process name. 118 * @param fdsToClose an array of ints, holding one or more POSIX 119 * file descriptor numbers that are to be closed by the child 120 * (and replaced by /dev/null) after forking. An integer value 121 * of -1 in any entry in the array means "ignore this one". 122 * @param fdsToIgnore null-ok an array of ints, either null or holding 123 * one or more POSIX file descriptor numbers that are to be ignored 124 * in the file descriptor table check. 125 * @param startChildZygote if true, the new child process will itself be a 126 * new zygote process. 127 * @param instructionSet null-ok the instruction set to use. 128 * @param appDataDir null-ok the data directory of the app. 129 * 130 * @return 0 if this is the child, pid of the child 131 * if this is the parent, or -1 on error. 132 */ forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir)133 public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, 134 int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, 135 int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) { 136 VM_HOOKS.preFork(); 137 // Resets nice priority for zygote process. 138 resetNicePriority(); 139 int pid = nativeForkAndSpecialize( 140 uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, 141 fdsToIgnore, startChildZygote, instructionSet, appDataDir); 142 // Enable tracing as soon as possible for the child process. 143 if (pid == 0) { 144 Trace.setTracingEnabled(true, runtimeFlags); 145 146 // Note that this event ends at the end of handleChildProc, 147 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); 148 } 149 VM_HOOKS.postForkCommon(); 150 return pid; 151 } 152 nativeForkAndSpecialize(int uid, int gid, int[] gids,int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir)153 native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int runtimeFlags, 154 int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, 155 int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir); 156 157 /** 158 * Called to do any initialization before starting an application. 159 */ nativePreApplicationInit()160 native static void nativePreApplicationInit(); 161 162 /** 163 * Special method to start the system server process. In addition to the 164 * common actions performed in forkAndSpecialize, the pid of the child 165 * process is recorded such that the death of the child process will cause 166 * zygote to exit. 167 * 168 * @param uid the UNIX uid that the new process should setuid() to after 169 * fork()ing and and before spawning any threads. 170 * @param gid the UNIX gid that the new process should setgid() to after 171 * fork()ing and and before spawning any threads. 172 * @param gids null-ok; a list of UNIX gids that the new process should 173 * setgroups() to after fork and before spawning any threads. 174 * @param runtimeFlags bit flags that enable ART features. 175 * @param rlimits null-ok an array of rlimit tuples, with the second 176 * dimension having a length of 3 and representing 177 * (resource, rlim_cur, rlim_max). These are set via the posix 178 * setrlimit(2) call. 179 * @param permittedCapabilities argument for setcap() 180 * @param effectiveCapabilities argument for setcap() 181 * 182 * @return 0 if this is the child, pid of the child 183 * if this is the parent, or -1 on error. 184 */ forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)185 public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, 186 int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { 187 VM_HOOKS.preFork(); 188 // Resets nice priority for zygote process. 189 resetNicePriority(); 190 int pid = nativeForkSystemServer( 191 uid, gid, gids, runtimeFlags, rlimits, permittedCapabilities, effectiveCapabilities); 192 // Enable tracing as soon as we enter the system_server. 193 if (pid == 0) { 194 Trace.setTracingEnabled(true, runtimeFlags); 195 } 196 VM_HOOKS.postForkCommon(); 197 return pid; 198 } 199 nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)200 native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, 201 int[][] rlimits, long permittedCapabilities, long effectiveCapabilities); 202 203 /** 204 * Lets children of the zygote inherit open file descriptors to this path. 205 */ nativeAllowFileAcrossFork(String path)206 native protected static void nativeAllowFileAcrossFork(String path); 207 208 /** 209 * Zygote unmount storage space on initializing. 210 * This method is called once. 211 */ nativeUnmountStorageOnInit()212 native protected static void nativeUnmountStorageOnInit(); 213 callPostForkChildHooks(int runtimeFlags, boolean isSystemServer, boolean isZygote, String instructionSet)214 private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer, 215 boolean isZygote, String instructionSet) { 216 VM_HOOKS.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet); 217 } 218 219 /** 220 * Resets the calling thread priority to the default value (Thread.NORM_PRIORITY 221 * or nice value 0). This updates both the priority value in java.lang.Thread and 222 * the nice value (setpriority). 223 */ resetNicePriority()224 static void resetNicePriority() { 225 Thread.currentThread().setPriority(Thread.NORM_PRIORITY); 226 } 227 228 /** 229 * Executes "/system/bin/sh -c <command>" using the exec() system call. 230 * This method throws a runtime exception if exec() failed, otherwise, this 231 * method never returns. 232 * 233 * @param command The shell command to execute. 234 */ execShell(String command)235 public static void execShell(String command) { 236 String[] args = { "/system/bin/sh", "-c", command }; 237 try { 238 Os.execv(args[0], args); 239 } catch (ErrnoException e) { 240 throw new RuntimeException(e); 241 } 242 } 243 244 /** 245 * Appends quotes shell arguments to the specified string builder. 246 * The arguments are quoted using single-quotes, escaped if necessary, 247 * prefixed with a space, and appended to the command. 248 * 249 * @param command A string builder for the shell command being constructed. 250 * @param args An array of argument strings to be quoted and appended to the command. 251 * @see #execShell(String) 252 */ appendQuotedShellArgs(StringBuilder command, String[] args)253 public static void appendQuotedShellArgs(StringBuilder command, String[] args) { 254 for (String arg : args) { 255 command.append(" '").append(arg.replace("'", "'\\''")).append("'"); 256 } 257 } 258 } 259