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 20 import android.os.Trace; 21 import dalvik.system.ZygoteHooks; 22 import android.system.ErrnoException; 23 import android.system.Os; 24 25 /** @hide */ 26 public final class Zygote { 27 /* 28 * Bit values for "debugFlags" argument. The definitions are duplicated 29 * in the native code. 30 */ 31 32 /** enable debugging over JDWP */ 33 public static final int DEBUG_ENABLE_DEBUGGER = 1; 34 /** enable JNI checks */ 35 public static final int DEBUG_ENABLE_CHECKJNI = 1 << 1; 36 /** enable Java programming language "assert" statements */ 37 public static final int DEBUG_ENABLE_ASSERT = 1 << 2; 38 /** disable the AOT compiler and JIT */ 39 public static final int DEBUG_ENABLE_SAFEMODE = 1 << 3; 40 /** Enable logging of third-party JNI activity. */ 41 public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4; 42 /** enable the JIT compiler */ 43 public static final int DEBUG_ENABLE_JIT = 1 << 5; 44 /** Force generation of native debugging information. */ 45 public static final int DEBUG_GENERATE_DEBUG_INFO = 1 << 6; 46 47 /** No external storage should be mounted. */ 48 public static final int MOUNT_EXTERNAL_NONE = 0; 49 /** Default external storage should be mounted. */ 50 public static final int MOUNT_EXTERNAL_DEFAULT = 1; 51 /** Read-only external storage should be mounted. */ 52 public static final int MOUNT_EXTERNAL_READ = 2; 53 /** Read-write external storage should be mounted. */ 54 public static final int MOUNT_EXTERNAL_WRITE = 3; 55 56 private static final ZygoteHooks VM_HOOKS = new ZygoteHooks(); 57 Zygote()58 private Zygote() {} 59 60 /** 61 * Forks a new VM instance. The current VM must have been started 62 * with the -Xzygote flag. <b>NOTE: new instance keeps all 63 * root capabilities. The new process is expected to call capset()</b>. 64 * 65 * @param uid the UNIX uid that the new process should setuid() to after 66 * fork()ing and and before spawning any threads. 67 * @param gid the UNIX gid that the new process should setgid() to after 68 * fork()ing and and before spawning any threads. 69 * @param gids null-ok; a list of UNIX gids that the new process should 70 * setgroups() to after fork and before spawning any threads. 71 * @param debugFlags bit flags that enable debugging features. 72 * @param rlimits null-ok an array of rlimit tuples, with the second 73 * dimension having a length of 3 and representing 74 * (resource, rlim_cur, rlim_max). These are set via the posix 75 * setrlimit(2) call. 76 * @param seInfo null-ok a string specifying SELinux information for 77 * the new process. 78 * @param niceName null-ok a string specifying the process name. 79 * @param fdsToClose an array of ints, holding one or more POSIX 80 * file descriptor numbers that are to be closed by the child 81 * (and replaced by /dev/null) after forking. An integer value 82 * of -1 in any entry in the array means "ignore this one". 83 * @param instructionSet null-ok the instruction set to use. 84 * @param appDataDir null-ok the data directory of the app. 85 * 86 * @return 0 if this is the child, pid of the child 87 * if this is the parent, or -1 on error. 88 */ forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, String instructionSet, String appDataDir)89 public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, 90 int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, 91 String instructionSet, String appDataDir) { 92 VM_HOOKS.preFork(); 93 int pid = nativeForkAndSpecialize( 94 uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, 95 instructionSet, appDataDir); 96 // Enable tracing as soon as possible for the child process. 97 if (pid == 0) { 98 Trace.setTracingEnabled(true); 99 100 // Note that this event ends at the end of handleChildProc, 101 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); 102 } 103 VM_HOOKS.postForkCommon(); 104 return pid; 105 } 106 nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, String instructionSet, String appDataDir)107 native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags, 108 int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, 109 String instructionSet, String appDataDir); 110 111 /** 112 * Special method to start the system server process. In addition to the 113 * common actions performed in forkAndSpecialize, the pid of the child 114 * process is recorded such that the death of the child process will cause 115 * zygote to exit. 116 * 117 * @param uid the UNIX uid that the new process should setuid() to after 118 * fork()ing and and before spawning any threads. 119 * @param gid the UNIX gid that the new process should setgid() to after 120 * fork()ing and and before spawning any threads. 121 * @param gids null-ok; a list of UNIX gids that the new process should 122 * setgroups() to after fork and before spawning any threads. 123 * @param debugFlags bit flags that enable debugging features. 124 * @param rlimits null-ok an array of rlimit tuples, with the second 125 * dimension having a length of 3 and representing 126 * (resource, rlim_cur, rlim_max). These are set via the posix 127 * setrlimit(2) call. 128 * @param permittedCapabilities argument for setcap() 129 * @param effectiveCapabilities argument for setcap() 130 * 131 * @return 0 if this is the child, pid of the child 132 * if this is the parent, or -1 on error. 133 */ forkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)134 public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags, 135 int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { 136 VM_HOOKS.preFork(); 137 int pid = nativeForkSystemServer( 138 uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities); 139 // Enable tracing as soon as we enter the system_server. 140 if (pid == 0) { 141 Trace.setTracingEnabled(true); 142 } 143 VM_HOOKS.postForkCommon(); 144 return pid; 145 } 146 nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)147 native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags, 148 int[][] rlimits, long permittedCapabilities, long effectiveCapabilities); 149 callPostForkChildHooks(int debugFlags, String instructionSet)150 private static void callPostForkChildHooks(int debugFlags, String instructionSet) { 151 VM_HOOKS.postForkChild(debugFlags, instructionSet); 152 } 153 154 155 /** 156 * Executes "/system/bin/sh -c <command>" using the exec() system call. 157 * This method throws a runtime exception if exec() failed, otherwise, this 158 * method never returns. 159 * 160 * @param command The shell command to execute. 161 */ execShell(String command)162 public static void execShell(String command) { 163 String[] args = { "/system/bin/sh", "-c", command }; 164 try { 165 Os.execv(args[0], args); 166 } catch (ErrnoException e) { 167 throw new RuntimeException(e); 168 } 169 } 170 171 /** 172 * Appends quotes shell arguments to the specified string builder. 173 * The arguments are quoted using single-quotes, escaped if necessary, 174 * prefixed with a space, and appended to the command. 175 * 176 * @param command A string builder for the shell command being constructed. 177 * @param args An array of argument strings to be quoted and appended to the command. 178 * @see #execShell(String) 179 */ appendQuotedShellArgs(StringBuilder command, String[] args)180 public static void appendQuotedShellArgs(StringBuilder command, String[] args) { 181 for (String arg : args) { 182 command.append(" '").append(arg.replace("'", "'\\''")).append("'"); 183 } 184 } 185 } 186