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 static android.system.OsConstants.O_CLOEXEC;
20 
21 import static com.android.internal.os.ZygoteConnectionConstants.MAX_ZYGOTE_ARGC;
22 
23 import android.content.pm.ApplicationInfo;
24 import android.net.Credentials;
25 import android.net.LocalServerSocket;
26 import android.net.LocalSocket;
27 import android.net.NetworkUtils;
28 import android.os.FactoryTest;
29 import android.os.IVold;
30 import android.os.Process;
31 import android.os.SystemProperties;
32 import android.os.Trace;
33 import android.provider.DeviceConfig;
34 import android.system.ErrnoException;
35 import android.system.Os;
36 import android.util.Log;
37 
38 import dalvik.annotation.optimization.FastNative;
39 import dalvik.system.ZygoteHooks;
40 
41 import libcore.io.IoUtils;
42 
43 import java.io.BufferedReader;
44 import java.io.ByteArrayOutputStream;
45 import java.io.DataOutputStream;
46 import java.io.FileDescriptor;
47 import java.io.IOException;
48 import java.io.InputStreamReader;
49 
50 /** @hide */
51 public final class Zygote {
52     /*
53      * Bit values for "runtimeFlags" argument.  The definitions are duplicated
54      * in the native code.
55      */
56 
57     /** enable debugging over JDWP */
58     public static final int DEBUG_ENABLE_JDWP   = 1;
59     /** enable JNI checks */
60     public static final int DEBUG_ENABLE_CHECKJNI   = 1 << 1;
61     /** enable Java programming language "assert" statements */
62     public static final int DEBUG_ENABLE_ASSERT     = 1 << 2;
63     /** disable the AOT compiler and JIT */
64     public static final int DEBUG_ENABLE_SAFEMODE   = 1 << 3;
65     /** Enable logging of third-party JNI activity. */
66     public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
67     /** Force generation of native debugging information. */
68     public static final int DEBUG_GENERATE_DEBUG_INFO = 1 << 5;
69     /** Always use JIT-ed code. */
70     public static final int DEBUG_ALWAYS_JIT = 1 << 6;
71     /** Make the code native debuggable by turning off some optimizations. */
72     public static final int DEBUG_NATIVE_DEBUGGABLE = 1 << 7;
73     /** Make the code Java debuggable by turning off some optimizations. */
74     public static final int DEBUG_JAVA_DEBUGGABLE = 1 << 8;
75 
76     /** Turn off the verifier. */
77     public static final int DISABLE_VERIFIER = 1 << 9;
78     /** Only use oat files located in /system. Otherwise use dex/jar/apk . */
79     public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10;
80     /** Force generation of native debugging information for backtraces. */
81     public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 11;
82     /**
83      * Hidden API access restrictions. This is a mask for bits representing the API enforcement
84      * policy, defined by {@code @ApplicationInfo.HiddenApiEnforcementPolicy}.
85      */
86     public static final int API_ENFORCEMENT_POLICY_MASK = (1 << 12) | (1 << 13);
87     /**
88      * Bit shift for use with {@link #API_ENFORCEMENT_POLICY_MASK}.
89      *
90      * (flags & API_ENFORCEMENT_POLICY_MASK) >> API_ENFORCEMENT_POLICY_SHIFT gives
91      * @ApplicationInfo.ApiEnforcementPolicy values.
92      */
93     public static final int API_ENFORCEMENT_POLICY_SHIFT =
94             Integer.numberOfTrailingZeros(API_ENFORCEMENT_POLICY_MASK);
95     /**
96      * Enable system server ART profiling.
97      */
98     public static final int PROFILE_SYSTEM_SERVER = 1 << 14;
99 
100     /**
101      * Enable profiling from shell.
102      */
103     public static final int PROFILE_FROM_SHELL = 1 << 15;
104 
105     /*
106      * Enable using the ART app image startup cache
107      */
108     public static final int USE_APP_IMAGE_STARTUP_CACHE = 1 << 16;
109 
110     /**
111      * When set, application specified signal handlers are not chained (i.e, ignored)
112      * by the runtime.
113      *
114      * Used for debugging only. Usage: set debug.ignoreappsignalhandler to 1.
115      */
116     public static final int DEBUG_IGNORE_APP_SIGNAL_HANDLER = 1 << 17;
117 
118     /**
119      * Disable runtime access to {@link android.annotation.TestApi} annotated members.
120      *
121      * <p>This only takes effect if Hidden API access restrictions are enabled as well.
122      */
123     public static final int DISABLE_TEST_API_ENFORCEMENT_POLICY = 1 << 18;
124 
125     public static final int MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20);
126     /**
127      * Enable pointer tagging in this process.
128      * Tags are checked during memory deallocation, but not on access.
129      * TBI stands for Top-Byte-Ignore, an ARM CPU feature.
130      * {@link https://developer.arm.com/docs/den0024/latest/the-memory-management-unit/translation-table-configuration/virtual-address-tagging}
131      */
132     public static final int MEMORY_TAG_LEVEL_TBI = 1 << 19;
133 
134     /**
135      * Enable asynchronous memory tag checks in this process.
136      */
137     public static final int MEMORY_TAG_LEVEL_ASYNC = 2 << 19;
138 
139     /**
140      * Enable synchronous memory tag checks in this process.
141      */
142     public static final int MEMORY_TAG_LEVEL_SYNC = 3 << 19;
143 
144     /** No external storage should be mounted. */
145     public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
146     /** Default external storage should be mounted. */
147     public static final int MOUNT_EXTERNAL_DEFAULT = IVold.REMOUNT_MODE_DEFAULT;
148     /** Read-only external storage should be mounted. */
149     public static final int MOUNT_EXTERNAL_READ = IVold.REMOUNT_MODE_READ;
150     /** Read-write external storage should be mounted. */
151     public static final int MOUNT_EXTERNAL_WRITE = IVold.REMOUNT_MODE_WRITE;
152     /**
153      * Mount mode for apps that are already installed on the device before the isolated_storage
154      * feature is enabled.
155      */
156     public static final int MOUNT_EXTERNAL_LEGACY = IVold.REMOUNT_MODE_LEGACY;
157     /**
158      * Mount mode for package installers which should give them access to
159      * all obb dirs in addition to their package sandboxes
160      */
161     public static final int MOUNT_EXTERNAL_INSTALLER = IVold.REMOUNT_MODE_INSTALLER;
162     /** Read-write external storage should be mounted instead of package sandbox */
163     public static final int MOUNT_EXTERNAL_FULL = IVold.REMOUNT_MODE_FULL;
164 
165     /** Number of bytes sent to the Zygote over USAP pipes or the pool event FD */
166     public static final int USAP_MANAGEMENT_MESSAGE_BYTES = 8;
167 
168     /** Make the new process have top application priority. */
169     public static final String START_AS_TOP_APP_ARG = "--is-top-app";
170 
171     /**
172      * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
173      * in the abstract socket namespace. This socket name is what the new child zygote
174      * should listen for connections on.
175      */
176     public static final String CHILD_ZYGOTE_SOCKET_NAME_ARG = "--zygote-socket=";
177 
178     /**
179      * An extraArg passed when a zygote process is forking a child-zygote, specifying the
180      * requested ABI for the child Zygote.
181      */
182     public static final String CHILD_ZYGOTE_ABI_LIST_ARG = "--abi-list=";
183 
184     /**
185      * An extraArg passed when a zygote process is forking a child-zygote, specifying the
186      * start of the UID range the children of the Zygote may setuid()/setgid() to. This
187      * will be enforced with a seccomp filter.
188      */
189     public static final String CHILD_ZYGOTE_UID_RANGE_START = "--uid-range-start=";
190 
191     /**
192      * An extraArg passed when a zygote process is forking a child-zygote, specifying the
193      * end of the UID range the children of the Zygote may setuid()/setgid() to. This
194      * will be enforced with a seccomp filter.
195      */
196     public static final String CHILD_ZYGOTE_UID_RANGE_END = "--uid-range-end=";
197 
198     /** Prefix prepended to socket names created by init */
199     private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
200 
201     /**
202      * The duration to wait before re-checking Zygote related system properties.
203      *
204      * One minute in milliseconds.
205      */
206     public static final long PROPERTY_CHECK_INTERVAL = 60000;
207 
208     /**
209      * @hide for internal use only
210      */
211     public static final int SOCKET_BUFFER_SIZE = 256;
212 
213     /**
214      * @hide for internal use only
215      */
216     private static final int PRIORITY_MAX = -20;
217 
218     /** a prototype instance for a future List.toArray() */
219     protected static final int[][] INT_ARRAY_2D = new int[0][0];
220 
221     /**
222      * @hide for internal use only.
223      */
224     public static final String PRIMARY_SOCKET_NAME = "zygote";
225 
226     /**
227      * @hide for internal use only.
228      */
229     public static final String SECONDARY_SOCKET_NAME = "zygote_secondary";
230 
231     /**
232      * @hide for internal use only
233      */
234     public static final String USAP_POOL_PRIMARY_SOCKET_NAME = "usap_pool_primary";
235 
236     /**
237      * @hide for internal use only
238      */
239     public static final String USAP_POOL_SECONDARY_SOCKET_NAME = "usap_pool_secondary";
240 
Zygote()241     private Zygote() {}
242 
containsInetGid(int[] gids)243     private static boolean containsInetGid(int[] gids) {
244         for (int i = 0; i < gids.length; i++) {
245             if (gids[i] == android.os.Process.INET_GID) return true;
246         }
247         return false;
248     }
249 
250     /**
251      * Forks a new VM instance.  The current VM must have been started
252      * with the -Xzygote flag. <b>NOTE: new instance keeps all
253      * root capabilities. The new process is expected to call capset()</b>.
254      *
255      * @param uid the UNIX uid that the new process should setuid() to after
256      * fork()ing and and before spawning any threads.
257      * @param gid the UNIX gid that the new process should setgid() to after
258      * fork()ing and and before spawning any threads.
259      * @param gids null-ok; a list of UNIX gids that the new process should
260      * setgroups() to after fork and before spawning any threads.
261      * @param runtimeFlags bit flags that enable ART features.
262      * @param rlimits null-ok an array of rlimit tuples, with the second
263      * dimension having a length of 3 and representing
264      * (resource, rlim_cur, rlim_max). These are set via the posix
265      * setrlimit(2) call.
266      * @param seInfo null-ok a string specifying SELinux information for
267      * the new process.
268      * @param niceName null-ok a string specifying the process name.
269      * @param fdsToClose an array of ints, holding one or more POSIX
270      * file descriptor numbers that are to be closed by the child
271      * (and replaced by /dev/null) after forking.  An integer value
272      * of -1 in any entry in the array means "ignore this one".
273      * @param fdsToIgnore null-ok an array of ints, either null or holding
274      * one or more POSIX file descriptor numbers that are to be ignored
275      * in the file descriptor table check.
276      * @param startChildZygote if true, the new child process will itself be a
277      * new zygote process.
278      * @param instructionSet null-ok the instruction set to use.
279      * @param appDataDir null-ok the data directory of the app.
280      * @param isTopApp true if the process is for top (high priority) application.
281      *
282      * @return 0 if this is the child, pid of the child
283      * if this is the parent, or -1 on error.
284      */
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, boolean isTopApp)285     public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
286             int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
287             int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
288             boolean isTopApp) {
289         ZygoteHooks.preFork();
290 
291         int pid = nativeForkAndSpecialize(
292                 uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
293                 fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp);
294         if (pid == 0) {
295             // Note that this event ends at the end of handleChildProc,
296             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
297 
298             // If no GIDs were specified, don't make any permissions changes based on groups.
299             if (gids != null && gids.length > 0) {
300                 NetworkUtils.setAllowNetworkingForProcess(containsInetGid(gids));
301             }
302         }
303 
304         // Set the Java Language thread priority to the default value for new apps.
305         Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
306 
307         ZygoteHooks.postForkCommon();
308         return pid;
309     }
310 
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, boolean isTopApp)311     private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
312             int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
313             int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
314             String appDataDir, boolean isTopApp);
315 
316     /**
317      * Specialize an unspecialized app process.  The current VM must have been started
318      * with the -Xzygote flag.
319      *
320      * @param uid  The UNIX uid that the new process should setuid() to before spawning any threads
321      * @param gid  The UNIX gid that the new process should setgid() to before spawning any threads
322      * @param gids null-ok;  A list of UNIX gids that the new process should
323      * setgroups() to before spawning any threads
324      * @param runtimeFlags  Bit flags that enable ART features
325      * @param rlimits null-ok  An array of rlimit tuples, with the second
326      * dimension having a length of 3 and representing
327      * (resource, rlim_cur, rlim_max). These are set via the posix
328      * setrlimit(2) call.
329      * @param seInfo null-ok  A string specifying SELinux information for
330      * the new process.
331      * @param niceName null-ok  A string specifying the process name.
332      * @param startChildZygote  If true, the new child process will itself be a
333      * new zygote process.
334      * @param instructionSet null-ok  The instruction set to use.
335      * @param appDataDir null-ok  The data directory of the app.
336      * @param isTopApp  True if the process is for top (high priority) application.
337      */
specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp)338     public static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
339             int[][] rlimits, int mountExternal, String seInfo, String niceName,
340             boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp) {
341         nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
342                 niceName, startChildZygote, instructionSet, appDataDir, isTopApp);
343 
344         // Note that this event ends at the end of handleChildProc.
345         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
346 
347         // Set the Java Language thread priority to the default value for new apps.
348         Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
349 
350         /*
351          * This is called here (instead of after the fork but before the specialize) to maintain
352          * consistancy with the code paths for forkAndSpecialize.
353          *
354          * TODO (chriswailes): Look into moving this to immediately after the fork.
355          */
356         ZygoteHooks.postForkCommon();
357     }
358 
nativeSpecializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp)359     private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
360             int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
361             boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp);
362 
363     /**
364      * Called to do any initialization before starting an application.
365      */
nativePreApplicationInit()366     static native void nativePreApplicationInit();
367 
368     /**
369      * Special method to start the system server process. In addition to the
370      * common actions performed in forkAndSpecialize, the pid of the child
371      * process is recorded such that the death of the child process will cause
372      * zygote to exit.
373      *
374      * @param uid the UNIX uid that the new process should setuid() to after
375      * fork()ing and and before spawning any threads.
376      * @param gid the UNIX gid that the new process should setgid() to after
377      * fork()ing and and before spawning any threads.
378      * @param gids null-ok; a list of UNIX gids that the new process should
379      * setgroups() to after fork and before spawning any threads.
380      * @param runtimeFlags bit flags that enable ART features.
381      * @param rlimits null-ok an array of rlimit tuples, with the second
382      * dimension having a length of 3 and representing
383      * (resource, rlim_cur, rlim_max). These are set via the posix
384      * setrlimit(2) call.
385      * @param permittedCapabilities argument for setcap()
386      * @param effectiveCapabilities argument for setcap()
387      *
388      * @return 0 if this is the child, pid of the child
389      * if this is the parent, or -1 on error.
390      */
forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)391     public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
392             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
393         ZygoteHooks.preFork();
394 
395         int pid = nativeForkSystemServer(
396                 uid, gid, gids, runtimeFlags, rlimits,
397                 permittedCapabilities, effectiveCapabilities);
398 
399         // Set the Java Language thread priority to the default value for new apps.
400         Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
401 
402         ZygoteHooks.postForkCommon();
403         return pid;
404     }
405 
nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)406     private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
407             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
408 
409     /**
410      * Lets children of the zygote inherit open file descriptors to this path.
411      */
nativeAllowFileAcrossFork(String path)412     protected static native void nativeAllowFileAcrossFork(String path);
413 
414     /**
415      * Lets children of the zygote inherit open file descriptors that belong to the
416      * ApplicationInfo that is passed in.
417      *
418      * @param appInfo ApplicationInfo of the application
419      */
allowAppFilesAcrossFork(ApplicationInfo appInfo)420     protected static void allowAppFilesAcrossFork(ApplicationInfo appInfo) {
421         for (String path : appInfo.getAllApkPaths()) {
422             Zygote.nativeAllowFileAcrossFork(path);
423         }
424     }
425 
426     /**
427      * Installs a seccomp filter that limits setresuid()/setresgid() to the passed-in range
428      * @param uidGidMin The smallest allowed uid/gid
429      * @param uidGidMax The largest allowed uid/gid
430      */
nativeInstallSeccompUidGidFilter(int uidGidMin, int uidGidMax)431     native protected static void nativeInstallSeccompUidGidFilter(int uidGidMin, int uidGidMax);
432 
433     /**
434      * Initialize the native state of the Zygote.  This inclues
435      *   - Fetching socket FDs from the environment
436      *   - Initializing security properties
437      *   - Unmounting storage as appropriate
438      *   - Loading necessary performance profile information
439      *
440      * @param isPrimary  True if this is the zygote process, false if it is zygote_secondary
441      */
initNativeState(boolean isPrimary)442     static void initNativeState(boolean isPrimary) {
443         nativeInitNativeState(isPrimary);
444     }
445 
nativeInitNativeState(boolean isPrimary)446     protected static native void nativeInitNativeState(boolean isPrimary);
447 
448     /**
449      * Returns the raw string value of a system property.
450      *
451      * Note that Device Config is not available without an application so SystemProperties is used
452      * instead.
453      *
454      * TODO (chriswailes): Cache the system property location in native code and then write a JNI
455      *                     function to fetch it.
456      */
getConfigurationProperty(String propertyName, String defaultValue)457     public static String getConfigurationProperty(String propertyName, String defaultValue) {
458         return SystemProperties.get(
459                 String.join(".",
460                         "persist.device_config",
461                         DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
462                         propertyName),
463                 defaultValue);
464     }
465 
emptyUsapPool()466     protected static void emptyUsapPool() {
467         nativeEmptyUsapPool();
468     }
469 
nativeEmptyUsapPool()470     private static native void nativeEmptyUsapPool();
471 
472     /**
473      * Returns the value of a system property converted to a boolean using specific logic.
474      *
475      * Note that Device Config is not available without an application so SystemProperties is used
476      * instead.
477      *
478      * @see SystemProperties.getBoolean
479      *
480      * TODO (chriswailes): Cache the system property location in native code and then write a JNI
481      *                     function to fetch it.
482      * TODO (chriswailes): Move into ZygoteConfig.java once the necessary CL lands (go/ag/6580627)
483      */
getConfigurationPropertyBoolean( String propertyName, Boolean defaultValue)484     public static boolean getConfigurationPropertyBoolean(
485             String propertyName, Boolean defaultValue) {
486         return SystemProperties.getBoolean(
487                 String.join(".",
488                         "persist.device_config",
489                         DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
490                         propertyName),
491                 defaultValue);
492     }
493 
494     /**
495      * @return Number of unspecialized app processes currently in the pool
496      */
getUsapPoolCount()497     static int getUsapPoolCount() {
498         return nativeGetUsapPoolCount();
499     }
500 
nativeGetUsapPoolCount()501     private static native int nativeGetUsapPoolCount();
502 
503     /**
504      * @return The event FD used for communication between the signal handler and the ZygoteServer
505      *         poll loop
506      */
getUsapPoolEventFD()507     static FileDescriptor getUsapPoolEventFD() {
508         FileDescriptor fd = new FileDescriptor();
509         fd.setInt$(nativeGetUsapPoolEventFD());
510 
511         return fd;
512     }
513 
nativeGetUsapPoolEventFD()514     private static native int nativeGetUsapPoolEventFD();
515 
516     /**
517      * Fork a new unspecialized app process from the zygote
518      *
519      * @param usapPoolSocket  The server socket the USAP will call accept on
520      * @param sessionSocketRawFDs  Anonymous session sockets that are currently open
521      * @param isPriorityFork  Value controlling the process priority level until accept is called
522      * @return In the Zygote process this function will always return null; in unspecialized app
523      *         processes this function will return a Runnable object representing the new
524      *         application that is passed up from usapMain.
525      */
forkUsap(LocalServerSocket usapPoolSocket, int[] sessionSocketRawFDs, boolean isPriorityFork)526     static Runnable forkUsap(LocalServerSocket usapPoolSocket,
527                              int[] sessionSocketRawFDs,
528                              boolean isPriorityFork) {
529         FileDescriptor[] pipeFDs = null;
530 
531         try {
532             pipeFDs = Os.pipe2(O_CLOEXEC);
533         } catch (ErrnoException errnoEx) {
534             throw new IllegalStateException("Unable to create USAP pipe.", errnoEx);
535         }
536 
537         int pid =
538                 nativeForkUsap(pipeFDs[0].getInt$(), pipeFDs[1].getInt$(),
539                                sessionSocketRawFDs, isPriorityFork);
540 
541         if (pid == 0) {
542             IoUtils.closeQuietly(pipeFDs[0]);
543             return usapMain(usapPoolSocket, pipeFDs[1]);
544         } else {
545             // The read-end of the pipe will be closed by the native code.
546             // See removeUsapTableEntry();
547             IoUtils.closeQuietly(pipeFDs[1]);
548             return null;
549         }
550     }
551 
nativeForkUsap(int readPipeFD, int writePipeFD, int[] sessionSocketRawFDs, boolean isPriorityFork)552     private static native int nativeForkUsap(int readPipeFD,
553                                              int writePipeFD,
554                                              int[] sessionSocketRawFDs,
555                                              boolean isPriorityFork);
556 
557     /**
558      * This function is used by unspecialized app processes to wait for specialization requests from
559      * the system server.
560      *
561      * @param writePipe  The write end of the reporting pipe used to communicate with the poll loop
562      *                   of the ZygoteServer.
563      * @return A runnable oject representing the new application.
564      */
usapMain(LocalServerSocket usapPoolSocket, FileDescriptor writePipe)565     private static Runnable usapMain(LocalServerSocket usapPoolSocket,
566             FileDescriptor writePipe) {
567         final int pid = Process.myPid();
568         Process.setArgV0(Process.is64Bit() ? "usap64" : "usap32");
569 
570         LocalSocket sessionSocket = null;
571         DataOutputStream usapOutputStream = null;
572         Credentials peerCredentials = null;
573         ZygoteArguments args = null;
574 
575         // Change the priority to max before calling accept so we can respond to new specialization
576         // requests as quickly as possible.  This will be reverted to the default priority in the
577         // native specialization code.
578         boostUsapPriority();
579 
580         while (true) {
581             try {
582                 sessionSocket = usapPoolSocket.accept();
583 
584                 // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
585                 blockSigTerm();
586 
587                 BufferedReader usapReader =
588                         new BufferedReader(new InputStreamReader(sessionSocket.getInputStream()));
589                 usapOutputStream =
590                         new DataOutputStream(sessionSocket.getOutputStream());
591 
592                 peerCredentials = sessionSocket.getPeerCredentials();
593 
594                 String[] argStrings = readArgumentList(usapReader);
595 
596                 if (argStrings != null) {
597                     args = new ZygoteArguments(argStrings);
598 
599                     // TODO (chriswailes): Should this only be run for debug builds?
600                     validateUsapCommand(args);
601                     break;
602                 } else {
603                     Log.e("USAP", "Truncated command received.");
604                     IoUtils.closeQuietly(sessionSocket);
605 
606                     // Re-enable SIGTERM so the USAP can be flushed from the pool if necessary.
607                     unblockSigTerm();
608                 }
609             } catch (Exception ex) {
610                 Log.e("USAP", ex.getMessage());
611                 IoUtils.closeQuietly(sessionSocket);
612 
613                 // Re-enable SIGTERM so the USAP can be flushed from the pool if necessary.
614                 unblockSigTerm();
615             }
616         }
617 
618         try {
619             // SIGTERM is blocked on loop exit.  This prevents a USAP that is specializing from
620             // being killed during a pool flush.
621             setAppProcessName(args, "USAP");
622 
623             applyUidSecurityPolicy(args, peerCredentials);
624             applyDebuggerSystemProperty(args);
625 
626             int[][] rlimits = null;
627 
628             if (args.mRLimits != null) {
629                 rlimits = args.mRLimits.toArray(INT_ARRAY_2D);
630             }
631 
632             // This must happen before the SELinux policy for this process is
633             // changed when specializing.
634             try {
635                 // Used by ZygoteProcess.zygoteSendArgsAndGetResult to fill in a
636                 // Process.ProcessStartResult object.
637                 usapOutputStream.writeInt(pid);
638             } catch (IOException ioEx) {
639                 Log.e("USAP", "Failed to write response to session socket: "
640                         + ioEx.getMessage());
641                 throw new RuntimeException(ioEx);
642             } finally {
643                 IoUtils.closeQuietly(sessionSocket);
644 
645                 try {
646                     // This socket is closed using Os.close due to an issue with the implementation
647                     // of LocalSocketImp.close().  Because the raw FD is created by init and then
648                     // loaded from an environment variable (as opposed to being created by the
649                     // LocalSocketImpl itself) the current implementation will not actually close
650                     // the underlying FD.
651                     //
652                     // See b/130309968 for discussion of this issue.
653                     Os.close(usapPoolSocket.getFileDescriptor());
654                 } catch (ErrnoException ex) {
655                     Log.e("USAP", "Failed to close USAP pool socket");
656                     throw new RuntimeException(ex);
657                 }
658             }
659 
660             try {
661                 ByteArrayOutputStream buffer =
662                         new ByteArrayOutputStream(Zygote.USAP_MANAGEMENT_MESSAGE_BYTES);
663                 DataOutputStream outputStream = new DataOutputStream(buffer);
664 
665                 // This is written as a long so that the USAP reporting pipe and USAP pool event FD
666                 // handlers in ZygoteServer.runSelectLoop can be unified.  These two cases should
667                 // both send/receive 8 bytes.
668                 outputStream.writeLong(pid);
669                 outputStream.flush();
670 
671                 Os.write(writePipe, buffer.toByteArray(), 0, buffer.size());
672             } catch (Exception ex) {
673                 Log.e("USAP",
674                         String.format("Failed to write PID (%d) to pipe (%d): %s",
675                                 pid, writePipe.getInt$(), ex.getMessage()));
676                 throw new RuntimeException(ex);
677             } finally {
678                 IoUtils.closeQuietly(writePipe);
679             }
680 
681             specializeAppProcess(args.mUid, args.mGid, args.mGids,
682                     args.mRuntimeFlags, rlimits, args.mMountExternal,
683                     args.mSeInfo, args.mNiceName, args.mStartChildZygote,
684                     args.mInstructionSet, args.mAppDataDir, args.mIsTopApp);
685 
686             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
687 
688             return ZygoteInit.zygoteInit(args.mTargetSdkVersion,
689                     args.mDisabledCompatChanges,
690                     args.mRemainingArgs,
691                     null /* classLoader */);
692         } finally {
693             // Unblock SIGTERM to restore the process to default behavior.
694             unblockSigTerm();
695         }
696     }
697 
blockSigTerm()698     private static void blockSigTerm() {
699         nativeBlockSigTerm();
700     }
701 
nativeBlockSigTerm()702     private static native void nativeBlockSigTerm();
703 
unblockSigTerm()704     private static void unblockSigTerm() {
705         nativeUnblockSigTerm();
706     }
707 
nativeUnblockSigTerm()708     private static native void nativeUnblockSigTerm();
709 
boostUsapPriority()710     private static void boostUsapPriority() {
711         nativeBoostUsapPriority();
712     }
713 
nativeBoostUsapPriority()714     private static native void nativeBoostUsapPriority();
715 
setAppProcessName(ZygoteArguments args, String loggingTag)716     static void setAppProcessName(ZygoteArguments args, String loggingTag) {
717         if (args.mNiceName != null) {
718             Process.setArgV0(args.mNiceName);
719         } else if (args.mPackageName != null) {
720             Process.setArgV0(args.mPackageName);
721         } else {
722             Log.w(loggingTag, "Unable to set package name.");
723         }
724     }
725 
726     private static final String USAP_ERROR_PREFIX = "Invalid command to USAP: ";
727 
728     /**
729      * Checks a set of zygote arguments to see if they can be handled by a USAP.  Throws an
730      * exception if an invalid arugment is encountered.
731      * @param args  The arguments to test
732      */
validateUsapCommand(ZygoteArguments args)733     private static void validateUsapCommand(ZygoteArguments args) {
734         if (args.mAbiListQuery) {
735             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--query-abi-list");
736         } else if (args.mPidQuery) {
737             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--get-pid");
738         } else if (args.mPreloadDefault) {
739             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--preload-default");
740         } else if (args.mPreloadPackage != null) {
741             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--preload-package");
742         } else if (args.mPreloadApp != null) {
743             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--preload-app");
744         } else if (args.mStartChildZygote) {
745             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--start-child-zygote");
746         } else if (args.mApiBlacklistExemptions != null) {
747             throw new IllegalArgumentException(
748                     USAP_ERROR_PREFIX + "--set-api-blacklist-exemptions");
749         } else if (args.mHiddenApiAccessLogSampleRate != -1) {
750             throw new IllegalArgumentException(
751                     USAP_ERROR_PREFIX + "--hidden-api-log-sampling-rate=");
752         } else if (args.mHiddenApiAccessStatslogSampleRate != -1) {
753             throw new IllegalArgumentException(
754                     USAP_ERROR_PREFIX + "--hidden-api-statslog-sampling-rate=");
755         } else if (args.mInvokeWith != null) {
756             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--invoke-with");
757         } else if (args.mPermittedCapabilities != 0 || args.mEffectiveCapabilities != 0) {
758             throw new ZygoteSecurityException("Client may not specify capabilities: "
759                     + "permitted=0x" + Long.toHexString(args.mPermittedCapabilities)
760                     + ", effective=0x" + Long.toHexString(args.mEffectiveCapabilities));
761         }
762     }
763 
764     /**
765      * @return  Raw file descriptors for the read-end of USAP reporting pipes.
766      */
getUsapPipeFDs()767     protected static int[] getUsapPipeFDs() {
768         return nativeGetUsapPipeFDs();
769     }
770 
nativeGetUsapPipeFDs()771     private static native int[] nativeGetUsapPipeFDs();
772 
773     /**
774      * Remove the USAP table entry for the provided process ID.
775      *
776      * @param usapPID  Process ID of the entry to remove
777      * @return True if the entry was removed; false if it doesn't exist
778      */
removeUsapTableEntry(int usapPID)779     protected static boolean removeUsapTableEntry(int usapPID) {
780         return nativeRemoveUsapTableEntry(usapPID);
781     }
782 
nativeRemoveUsapTableEntry(int usapPID)783     private static native boolean nativeRemoveUsapTableEntry(int usapPID);
784 
785     /**
786      * uid 1000 (Process.SYSTEM_UID) may specify any uid &gt; 1000 in normal
787      * operation. It may also specify any gid and setgroups() list it chooses.
788      * In factory test mode, it may specify any UID.
789      *
790      * @param args non-null; zygote spawner arguments
791      * @param peer non-null; peer credentials
792      * @throws ZygoteSecurityException
793      */
applyUidSecurityPolicy(ZygoteArguments args, Credentials peer)794     protected static void applyUidSecurityPolicy(ZygoteArguments args, Credentials peer)
795             throws ZygoteSecurityException {
796 
797         if (peer.getUid() == Process.SYSTEM_UID) {
798             /* In normal operation, SYSTEM_UID can only specify a restricted
799              * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid.
800              */
801             boolean uidRestricted = FactoryTest.getMode() == FactoryTest.FACTORY_TEST_OFF;
802 
803             if (uidRestricted && args.mUidSpecified && (args.mUid < Process.SYSTEM_UID)) {
804                 throw new ZygoteSecurityException(
805                         "System UID may not launch process with UID < "
806                                 + Process.SYSTEM_UID);
807             }
808         }
809 
810         // If not otherwise specified, uid and gid are inherited from peer
811         if (!args.mUidSpecified) {
812             args.mUid = peer.getUid();
813             args.mUidSpecified = true;
814         }
815         if (!args.mGidSpecified) {
816             args.mGid = peer.getGid();
817             args.mGidSpecified = true;
818         }
819     }
820 
821     /**
822      * Applies debugger system properties to the zygote arguments.
823      *
824      * If "ro.debuggable" is "1", all apps are debuggable. Otherwise,
825      * the debugger state is specified via the "--enable-jdwp" flag
826      * in the spawn request.
827      *
828      * @param args non-null; zygote spawner args
829      */
applyDebuggerSystemProperty(ZygoteArguments args)830     protected static void applyDebuggerSystemProperty(ZygoteArguments args) {
831         if (RoSystemProperties.DEBUGGABLE) {
832             args.mRuntimeFlags |= Zygote.DEBUG_ENABLE_JDWP;
833         }
834     }
835 
836     /**
837      * Applies zygote security policy.
838      * Based on the credentials of the process issuing a zygote command:
839      * <ol>
840      * <li> uid 0 (root) may specify --invoke-with to launch Zygote with a
841      * wrapper command.
842      * <li> Any other uid may not specify any invoke-with argument.
843      * </ul>
844      *
845      * @param args non-null; zygote spawner arguments
846      * @param peer non-null; peer credentials
847      * @throws ZygoteSecurityException
848      */
applyInvokeWithSecurityPolicy(ZygoteArguments args, Credentials peer)849     protected static void applyInvokeWithSecurityPolicy(ZygoteArguments args, Credentials peer)
850             throws ZygoteSecurityException {
851         int peerUid = peer.getUid();
852 
853         if (args.mInvokeWith != null && peerUid != 0
854                 && (args.mRuntimeFlags & Zygote.DEBUG_ENABLE_JDWP) == 0) {
855             throw new ZygoteSecurityException("Peer is permitted to specify an "
856                     + "explicit invoke-with wrapper command only for debuggable "
857                     + "applications.");
858         }
859     }
860 
861     /**
862      * Applies invoke-with system properties to the zygote arguments.
863      *
864      * @param args non-null; zygote args
865      */
applyInvokeWithSystemProperty(ZygoteArguments args)866     protected static void applyInvokeWithSystemProperty(ZygoteArguments args) {
867         if (args.mInvokeWith == null && args.mNiceName != null) {
868             String property = "wrap." + args.mNiceName;
869             args.mInvokeWith = SystemProperties.get(property);
870             if (args.mInvokeWith != null && args.mInvokeWith.length() == 0) {
871                 args.mInvokeWith = null;
872             }
873         }
874     }
875 
876     /**
877      * Reads an argument list from the provided socket
878      * @return Argument list or null if EOF is reached
879      * @throws IOException passed straight through
880      */
readArgumentList(BufferedReader socketReader)881     static String[] readArgumentList(BufferedReader socketReader) throws IOException {
882         int argc;
883 
884         try {
885             String argc_string = socketReader.readLine();
886 
887             if (argc_string == null) {
888                 // EOF reached.
889                 return null;
890             }
891             argc = Integer.parseInt(argc_string);
892 
893         } catch (NumberFormatException ex) {
894             Log.e("Zygote", "Invalid Zygote wire format: non-int at argc");
895             throw new IOException("Invalid wire format");
896         }
897 
898         // See bug 1092107: large argc can be used for a DOS attack
899         if (argc > MAX_ZYGOTE_ARGC) {
900             throw new IOException("Max arg count exceeded");
901         }
902 
903         String[] args = new String[argc];
904         for (int arg_index = 0; arg_index < argc; arg_index++) {
905             args[arg_index] = socketReader.readLine();
906             if (args[arg_index] == null) {
907                 // We got an unexpected EOF.
908                 throw new IOException("Truncated request");
909             }
910         }
911 
912         return args;
913     }
914 
915     /**
916      * Creates a managed LocalServerSocket object using a file descriptor
917      * created by an init.rc script.  The init scripts that specify the
918      * sockets name can be found in system/core/rootdir.  The socket is bound
919      * to the file system in the /dev/sockets/ directory, and the file
920      * descriptor is shared via the ANDROID_SOCKET_<socketName> environment
921      * variable.
922      */
createManagedSocketFromInitSocket(String socketName)923     static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
924         int fileDesc;
925         final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
926 
927         try {
928             String env = System.getenv(fullSocketName);
929             fileDesc = Integer.parseInt(env);
930         } catch (RuntimeException ex) {
931             throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
932         }
933 
934         try {
935             FileDescriptor fd = new FileDescriptor();
936             fd.setInt$(fileDesc);
937             return new LocalServerSocket(fd);
938         } catch (IOException ex) {
939             throw new RuntimeException(
940                     "Error building socket from file descriptor: " + fileDesc, ex);
941         }
942     }
943 
callPostForkSystemServerHooks(int runtimeFlags)944     private static void callPostForkSystemServerHooks(int runtimeFlags) {
945         // SystemServer specific post fork hooks run before child post fork hooks.
946         ZygoteHooks.postForkSystemServer(runtimeFlags);
947     }
948 
callPostForkChildHooks(int runtimeFlags, boolean isSystemServer, boolean isZygote, String instructionSet)949     private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer,
950             boolean isZygote, String instructionSet) {
951         ZygoteHooks.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
952     }
953 
954     /**
955      * Executes "/system/bin/sh -c &lt;command&gt;" using the exec() system call.
956      * This method throws a runtime exception if exec() failed, otherwise, this
957      * method never returns.
958      *
959      * @param command The shell command to execute.
960      */
execShell(String command)961     public static void execShell(String command) {
962         String[] args = { "/system/bin/sh", "-c", command };
963         try {
964             Os.execv(args[0], args);
965         } catch (ErrnoException e) {
966             throw new RuntimeException(e);
967         }
968     }
969 
970     /**
971      * Appends quotes shell arguments to the specified string builder.
972      * The arguments are quoted using single-quotes, escaped if necessary,
973      * prefixed with a space, and appended to the command.
974      *
975      * @param command A string builder for the shell command being constructed.
976      * @param args An array of argument strings to be quoted and appended to the command.
977      * @see #execShell(String)
978      */
appendQuotedShellArgs(StringBuilder command, String[] args)979     public static void appendQuotedShellArgs(StringBuilder command, String[] args) {
980         for (String arg : args) {
981             command.append(" '").append(arg.replace("'", "'\\''")).append("'");
982         }
983     }
984 
985     /**
986      * Parse the given unsolicited zygote message as type SIGCHLD,
987      * extract the payload information into the given output buffer.
988      *
989      * @param in The unsolicited zygote message to be parsed
990      * @param length The number of bytes in the message
991      * @param out The output buffer where the payload information will be placed
992      * @return Number of elements being place into output buffer, or -1 if
993      *         either the message is malformed or not the type as expected here.
994      *
995      * @hide
996      */
997     @FastNative
nativeParseSigChld(byte[] in, int length, int[] out)998     public static native int nativeParseSigChld(byte[] in, int length, int[] out);
999 
1000     /**
1001      * Returns whether the hardware supports memory tagging (ARM MTE).
1002      */
nativeSupportsMemoryTagging()1003     public static native boolean nativeSupportsMemoryTagging();
1004 
1005     /**
1006      * Returns whether the kernel supports tagged pointers. Present in the
1007      * Android Common Kernel from 4.14 and up. By default, you should prefer
1008      * fully-feature Memory Tagging, rather than the static Tagged Pointers.
1009      */
nativeSupportsTaggedPointers()1010     public static native boolean nativeSupportsTaggedPointers();
1011 }
1012