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