• 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 android.annotation.NonNull;
22 import android.annotation.Nullable;
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.FactoryTest;
28 import android.os.IVold;
29 import android.os.Process;
30 import android.os.SystemProperties;
31 import android.os.Trace;
32 import android.provider.DeviceConfig;
33 import android.system.ErrnoException;
34 import android.system.Os;
35 import android.util.Log;
36 
37 import com.android.internal.net.NetworkUtilsInternal;
38 
39 import dalvik.annotation.optimization.CriticalNative;
40 import dalvik.annotation.optimization.FastNative;
41 import dalvik.system.ZygoteHooks;
42 
43 import libcore.io.IoUtils;
44 
45 import java.io.ByteArrayOutputStream;
46 import java.io.DataOutputStream;
47 import java.io.FileDescriptor;
48 import java.io.IOException;
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      * {@link ApplicationInfo.HiddenApiEnforcementPolicy} 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     public static final int MEMORY_TAG_LEVEL_NONE = 0;
128     /**
129      * Enable pointer tagging in this process.
130      * Tags are checked during memory deallocation, but not on access.
131      * TBI stands for Top-Byte-Ignore, an ARM CPU feature.
132      * {@link https://developer.arm.com/docs/den0024/latest/the-memory-management-unit/translation-table-configuration/virtual-address-tagging}
133      */
134     public static final int MEMORY_TAG_LEVEL_TBI = 1 << 19;
135 
136     /**
137      * Enable asynchronous memory tag checks in this process.
138      */
139     public static final int MEMORY_TAG_LEVEL_ASYNC = 2 << 19;
140 
141     /**
142      * Enable synchronous memory tag checks in this process.
143      */
144     public static final int MEMORY_TAG_LEVEL_SYNC = 3 << 19;
145 
146     /**
147      * A two-bit field for GWP-ASan level of this process. See the possible values below.
148      */
149     public static final int GWP_ASAN_LEVEL_MASK = (1 << 21) | (1 << 22);
150 
151     /**
152      * Disable GWP-ASan in this process.
153      * GWP-ASan is a low-overhead memory bug detector using guard pages on a small
154      * subset of heap allocations.
155      */
156     public static final int GWP_ASAN_LEVEL_NEVER = 0 << 21;
157 
158     /**
159      * Enable GWP-ASan in this process with a small sampling rate.
160      * With approx. 1% chance GWP-ASan will be activated and apply its protection
161      * to a small subset of heap allocations.
162      * Otherwise (~99% chance) this process is unaffected.
163      */
164     public static final int GWP_ASAN_LEVEL_LOTTERY = 1 << 21;
165 
166     /**
167      * Always enable GWP-ASan in this process.
168      * GWP-ASan is activated unconditionally (but still, only a small subset of
169      * allocations is protected).
170      */
171     public static final int GWP_ASAN_LEVEL_ALWAYS = 1 << 22;
172 
173     /**
174      * Enable automatic zero-initialization of native heap memory allocations.
175      */
176     public static final int NATIVE_HEAP_ZERO_INIT = 1 << 23;
177 
178     /**
179      * Enable profiling from system services. This loads profiling related plugins in ART.
180      */
181     public static final int PROFILEABLE = 1 << 24;
182 
183     /** No external storage should be mounted. */
184     public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
185     /** Default external storage should be mounted. */
186     public static final int MOUNT_EXTERNAL_DEFAULT = IVold.REMOUNT_MODE_DEFAULT;
187     /**
188      * Mount mode for package installers which should give them access to
189      * all obb dirs in addition to their package sandboxes
190      */
191     public static final int MOUNT_EXTERNAL_INSTALLER = IVold.REMOUNT_MODE_INSTALLER;
192     /** The lower file system should be bind mounted directly on external storage */
193     public static final int MOUNT_EXTERNAL_PASS_THROUGH = IVold.REMOUNT_MODE_PASS_THROUGH;
194 
195     /** Use the regular scoped storage filesystem, but Android/ should be writable.
196      * Used to support the applications hosting DownloadManager and the MTP server.
197      */
198     public static final int MOUNT_EXTERNAL_ANDROID_WRITABLE = IVold.REMOUNT_MODE_ANDROID_WRITABLE;
199 
200     /** Number of bytes sent to the Zygote over USAP pipes or the pool event FD */
201     static final int USAP_MANAGEMENT_MESSAGE_BYTES = 8;
202 
203     /** Make the new process have top application priority. */
204     public static final String START_AS_TOP_APP_ARG = "--is-top-app";
205 
206     /** List of packages with the same uid, and its app data info: volume uuid and inode. */
207     public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map";
208 
209     /** List of allowlisted packages and its app data info: volume uuid and inode. */
210     public static final String ALLOWLISTED_DATA_INFO_MAP = "--allowlisted-data-info-map";
211 
212     /** Bind mount app storage dirs to lower fs not via fuse */
213     public static final String BIND_MOUNT_APP_STORAGE_DIRS = "--bind-mount-storage-dirs";
214 
215     /** Bind mount app storage dirs to lower fs not via fuse */
216     public static final String BIND_MOUNT_APP_DATA_DIRS = "--bind-mount-data-dirs";
217 
218     /**
219      * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
220      * in the abstract socket namespace. This socket name is what the new child zygote
221      * should listen for connections on.
222      */
223     public static final String CHILD_ZYGOTE_SOCKET_NAME_ARG = "--zygote-socket=";
224 
225     /**
226      * An extraArg passed when a zygote process is forking a child-zygote, specifying the
227      * requested ABI for the child Zygote.
228      */
229     public static final String CHILD_ZYGOTE_ABI_LIST_ARG = "--abi-list=";
230 
231     /**
232      * An extraArg passed when a zygote process is forking a child-zygote, specifying the
233      * start of the UID range the children of the Zygote may setuid()/setgid() to. This
234      * will be enforced with a seccomp filter.
235      */
236     public static final String CHILD_ZYGOTE_UID_RANGE_START = "--uid-range-start=";
237 
238     /**
239      * An extraArg passed when a zygote process is forking a child-zygote, specifying the
240      * end of the UID range the children of the Zygote may setuid()/setgid() to. This
241      * will be enforced with a seccomp filter.
242      */
243     public static final String CHILD_ZYGOTE_UID_RANGE_END = "--uid-range-end=";
244 
245     private static final String TAG = "Zygote";
246 
247     /** Prefix prepended to socket names created by init */
248     private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
249 
250     /**
251      * The duration to wait before re-checking Zygote related system properties.
252      *
253      * One minute in milliseconds.
254      */
255     public static final long PROPERTY_CHECK_INTERVAL = 60000;
256 
257     /**
258      * @hide for internal use only
259      */
260     public static final int SOCKET_BUFFER_SIZE = 256;
261 
262     /**
263      * @hide for internal use only
264      */
265     private static final int PRIORITY_MAX = -20;
266 
267     /** a prototype instance for a future List.toArray() */
268     static final int[][] INT_ARRAY_2D = new int[0][0];
269 
270     /**
271      * @hide for internal use only.
272      */
273     public static final String PRIMARY_SOCKET_NAME = "zygote";
274 
275     /**
276      * @hide for internal use only.
277      */
278     public static final String SECONDARY_SOCKET_NAME = "zygote_secondary";
279 
280     /**
281      * @hide for internal use only
282      */
283     public static final String USAP_POOL_PRIMARY_SOCKET_NAME = "usap_pool_primary";
284 
285     /**
286      * @hide for internal use only
287      */
288     public static final String USAP_POOL_SECONDARY_SOCKET_NAME = "usap_pool_secondary";
289 
Zygote()290     private Zygote() {}
291 
containsInetGid(int[] gids)292     private static boolean containsInetGid(int[] gids) {
293         for (int i = 0; i < gids.length; i++) {
294             if (gids[i] == android.os.Process.INET_GID) return true;
295         }
296         return false;
297     }
298 
299     /**
300      * Forks a new VM instance.  The current VM must have been started
301      * with the -Xzygote flag. <b>NOTE: new instance keeps all
302      * root capabilities. The new process is expected to call capset()</b>.
303      *
304      * @param uid the UNIX uid that the new process should setuid() to after
305      * fork()ing and and before spawning any threads.
306      * @param gid the UNIX gid that the new process should setgid() to after
307      * fork()ing and and before spawning any threads.
308      * @param gids null-ok; a list of UNIX gids that the new process should
309      * setgroups() to after fork and before spawning any threads.
310      * @param runtimeFlags bit flags that enable ART features.
311      * @param rlimits null-ok an array of rlimit tuples, with the second
312      * dimension having a length of 3 and representing
313      * (resource, rlim_cur, rlim_max). These are set via the posix
314      * setrlimit(2) call.
315      * @param seInfo null-ok a string specifying SELinux information for
316      * the new process.
317      * @param niceName null-ok a string specifying the process name.
318      * @param fdsToClose an array of ints, holding one or more POSIX
319      * file descriptor numbers that are to be closed by the child
320      * (and replaced by /dev/null) after forking.  An integer value
321      * of -1 in any entry in the array means "ignore this one".
322      * @param fdsToIgnore null-ok an array of ints, either null or holding
323      * one or more POSIX file descriptor numbers that are to be ignored
324      * in the file descriptor table check.
325      * @param startChildZygote if true, the new child process will itself be a
326      * new zygote process.
327      * @param instructionSet null-ok the instruction set to use.
328      * @param appDataDir null-ok the data directory of the app.
329      * @param isTopApp true if the process is for top (high priority) application.
330      * @param pkgDataInfoList A list that stores related packages and its app data
331      * info: volume uuid and inode.
332      * @param allowlistedDataInfoList Like pkgDataInfoList, but it's for allowlisted apps.
333      * @param bindMountAppDataDirs  True if the zygote needs to mount data dirs.
334      * @param bindMountAppStorageDirs  True if the zygote needs to mount storage dirs.
335      *
336      * @return 0 if this is the child, pid of the child
337      * if this is the parent, or -1 on error.
338      */
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, String[] pkgDataInfoList, String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs)339     static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
340             int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
341             int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
342             boolean isTopApp, String[] pkgDataInfoList, String[] allowlistedDataInfoList,
343             boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
344         ZygoteHooks.preFork();
345 
346         int pid = nativeForkAndSpecialize(
347                 uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
348                 fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
349                 pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs,
350                 bindMountAppStorageDirs);
351         if (pid == 0) {
352             // Note that this event ends at the end of handleChildProc,
353             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
354 
355             // If no GIDs were specified, don't make any permissions changes based on groups.
356             if (gids != null && gids.length > 0) {
357                 NetworkUtilsInternal.setAllowNetworkingForProcess(containsInetGid(gids));
358             }
359         }
360 
361         // Set the Java Language thread priority to the default value for new apps.
362         Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
363 
364         ZygoteHooks.postForkCommon();
365         return pid;
366     }
367 
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, String[] pkgDataInfoList, String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs)368     private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
369             int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
370             int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
371             String appDataDir, boolean isTopApp, String[] pkgDataInfoList,
372             String[] allowlistedDataInfoList, boolean bindMountAppDataDirs,
373             boolean bindMountAppStorageDirs);
374 
375     /**
376      * Specialize an unspecialized app process.  The current VM must have been started
377      * with the -Xzygote flag.
378      *
379      * @param uid  The UNIX uid that the new process should setuid() to before spawning any threads
380      * @param gid  The UNIX gid that the new process should setgid() to before spawning any threads
381      * @param gids null-ok;  A list of UNIX gids that the new process should
382      * setgroups() to before spawning any threads
383      * @param runtimeFlags  Bit flags that enable ART features
384      * @param rlimits null-ok  An array of rlimit tuples, with the second
385      * dimension having a length of 3 and representing
386      * (resource, rlim_cur, rlim_max). These are set via the posix
387      * setrlimit(2) call.
388      * @param seInfo null-ok  A string specifying SELinux information for
389      * the new process.
390      * @param niceName null-ok  A string specifying the process name.
391      * @param startChildZygote  If true, the new child process will itself be a
392      * new zygote process.
393      * @param instructionSet null-ok  The instruction set to use.
394      * @param appDataDir null-ok  The data directory of the app.
395      * @param isTopApp  True if the process is for top (high priority) application.
396      * @param pkgDataInfoList A list that stores related packages and its app data
397      * volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name,
398      * app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid,
399      * app_b_ce_inode, ...];
400      * @param allowlistedDataInfoList Like pkgDataInfoList, but it's for allowlisted apps.
401      * @param bindMountAppDataDirs  True if the zygote needs to mount data dirs.
402      * @param bindMountAppStorageDirs  True if the zygote needs to mount storage dirs.
403      */
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, String[] pkgDataInfoList, String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs)404     private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
405             int[][] rlimits, int mountExternal, String seInfo, String niceName,
406             boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
407             String[] pkgDataInfoList, String[] allowlistedDataInfoList,
408             boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
409         nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
410                 niceName, startChildZygote, instructionSet, appDataDir, isTopApp,
411                 pkgDataInfoList, allowlistedDataInfoList,
412                 bindMountAppDataDirs, bindMountAppStorageDirs);
413 
414         // Note that this event ends at the end of handleChildProc.
415         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
416 
417         if (gids != null && gids.length > 0) {
418             NetworkUtilsInternal.setAllowNetworkingForProcess(containsInetGid(gids));
419         }
420 
421         // Set the Java Language thread priority to the default value for new apps.
422         Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
423 
424         /*
425          * This is called here (instead of after the fork but before the specialize) to maintain
426          * consistancy with the code paths for forkAndSpecialize.
427          *
428          * TODO (chriswailes): Look into moving this to immediately after the fork.
429          */
430         ZygoteHooks.postForkCommon();
431     }
432 
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, String[] pkgDataInfoList, String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs)433     private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
434             int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
435             boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
436             String[] pkgDataInfoList, String[] allowlistedDataInfoList,
437             boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs);
438 
439     /**
440      * Called to do any initialization before starting an application.
441      */
nativePreApplicationInit()442     static native void nativePreApplicationInit();
443 
444     /**
445      * Special method to start the system server process. In addition to the
446      * common actions performed in forkAndSpecialize, the pid of the child
447      * process is recorded such that the death of the child process will cause
448      * zygote to exit.
449      *
450      * @param uid the UNIX uid that the new process should setuid() to after
451      * fork()ing and and before spawning any threads.
452      * @param gid the UNIX gid that the new process should setgid() to after
453      * fork()ing and and before spawning any threads.
454      * @param gids null-ok; a list of UNIX gids that the new process should
455      * setgroups() to after fork and before spawning any threads.
456      * @param runtimeFlags bit flags that enable ART features.
457      * @param rlimits null-ok an array of rlimit tuples, with the second
458      * dimension having a length of 3 and representing
459      * (resource, rlim_cur, rlim_max). These are set via the posix
460      * setrlimit(2) call.
461      * @param permittedCapabilities argument for setcap()
462      * @param effectiveCapabilities argument for setcap()
463      *
464      * @return 0 if this is the child, pid of the child
465      * if this is the parent, or -1 on error.
466      */
forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)467     static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
468             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
469         ZygoteHooks.preFork();
470 
471         int pid = nativeForkSystemServer(
472                 uid, gid, gids, runtimeFlags, rlimits,
473                 permittedCapabilities, effectiveCapabilities);
474 
475         // Set the Java Language thread priority to the default value for new apps.
476         Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
477 
478         ZygoteHooks.postForkCommon();
479         return pid;
480     }
481 
nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)482     private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
483             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
484 
485     /**
486      * Lets children of the zygote inherit open file descriptors to this path.
487      */
nativeAllowFileAcrossFork(String path)488     protected static native void nativeAllowFileAcrossFork(String path);
489 
490     /**
491      * Lets children of the zygote inherit open file descriptors that belong to the
492      * ApplicationInfo that is passed in.
493      *
494      * @param appInfo ApplicationInfo of the application
495      */
allowAppFilesAcrossFork(ApplicationInfo appInfo)496     static void allowAppFilesAcrossFork(ApplicationInfo appInfo) {
497         for (String path : appInfo.getAllApkPaths()) {
498             Zygote.nativeAllowFileAcrossFork(path);
499         }
500     }
501 
502     /**
503      * Scans file descriptors in /proc/self/fd/, stores their metadata from readlink(2)/stat(2) when
504      * available. Saves this information in a global on native side, to be used by subsequent call
505      * to allowFilesOpenedByPreload(). Fatally fails if the FDs are of unsupported type and are not
506      * explicitly allowed. Ignores repeated invocations.
507      *
508      * Inspecting the FDs is more permissive than in forkAndSpecialize() because preload is invoked
509      * earlier and hence needs to allow a few open sockets. The checks in forkAndSpecialize()
510      * enforce that these sockets are closed when forking.
511      */
markOpenedFilesBeforePreload()512     static void markOpenedFilesBeforePreload() {
513         nativeMarkOpenedFilesBeforePreload();
514     }
515 
nativeMarkOpenedFilesBeforePreload()516     private static native void nativeMarkOpenedFilesBeforePreload();
517 
518     /**
519      * By scanning /proc/self/fd/ determines file descriptor numbers in this process opened since
520      * the first call to markOpenedFilesBeforePreload(). These FDs are treated as 'owned' by the
521      * custom preload of the App Zygote - the app is responsible for not sharing data with its other
522      * processes using these FDs, including by lseek(2). File descriptor types and file names are
523      * not checked. Changes in FDs recorded by markOpenedFilesBeforePreload() are not expected and
524      * kill the current process.
525      */
allowFilesOpenedByPreload()526     static void allowFilesOpenedByPreload() {
527         nativeAllowFilesOpenedByPreload();
528     }
529 
nativeAllowFilesOpenedByPreload()530     private static native void nativeAllowFilesOpenedByPreload();
531 
532     /**
533      * Installs a seccomp filter that limits setresuid()/setresgid() to the passed-in range
534      * @param uidGidMin The smallest allowed uid/gid
535      * @param uidGidMax The largest allowed uid/gid
536      */
nativeInstallSeccompUidGidFilter(int uidGidMin, int uidGidMax)537     native protected static void nativeInstallSeccompUidGidFilter(int uidGidMin, int uidGidMax);
538 
539     /**
540      * Initialize the native state of the Zygote.  This inclues
541      *   - Fetching socket FDs from the environment
542      *   - Initializing security properties
543      *   - Unmounting storage as appropriate
544      *   - Loading necessary performance profile information
545      *
546      * @param isPrimary  True if this is the zygote process, false if it is zygote_secondary
547      */
initNativeState(boolean isPrimary)548     static void initNativeState(boolean isPrimary) {
549         nativeInitNativeState(isPrimary);
550     }
551 
nativeInitNativeState(boolean isPrimary)552     protected static native void nativeInitNativeState(boolean isPrimary);
553 
554     /**
555      * Returns the raw string value of a system property.
556      *
557      * Note that Device Config is not available without an application so SystemProperties is used
558      * instead.
559      *
560      * TODO (chriswailes): Cache the system property location in native code and then write a JNI
561      *                     function to fetch it.
562      */
getConfigurationProperty(String propertyName, String defaultValue)563     public static String getConfigurationProperty(String propertyName, String defaultValue) {
564         return SystemProperties.get(
565                 String.join(".",
566                         "persist.device_config",
567                         DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
568                         propertyName),
569                 defaultValue);
570     }
571 
emptyUsapPool()572     static void emptyUsapPool() {
573         nativeEmptyUsapPool();
574     }
575 
nativeEmptyUsapPool()576     private static native void nativeEmptyUsapPool();
577 
578     /**
579      * Returns the value of a system property converted to a boolean using specific logic.
580      *
581      * Note that Device Config is not available without an application so SystemProperties is used
582      * instead.
583      *
584      * @see SystemProperties#getBoolean
585      *
586      * TODO (chriswailes): Cache the system property location in native code and then write a JNI
587      *                     function to fetch it.
588      * TODO (chriswailes): Move into ZygoteConfig.java once the necessary CL lands (go/ag/6580627)
589      */
getConfigurationPropertyBoolean( String propertyName, Boolean defaultValue)590     public static boolean getConfigurationPropertyBoolean(
591             String propertyName, Boolean defaultValue) {
592         return SystemProperties.getBoolean(
593                 String.join(".",
594                         "persist.device_config",
595                         DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
596                         propertyName),
597                 defaultValue);
598     }
599 
600     /**
601      * @return Number of unspecialized app processes currently in the pool
602      */
getUsapPoolCount()603     static int getUsapPoolCount() {
604         return nativeGetUsapPoolCount();
605     }
606 
nativeGetUsapPoolCount()607     private static native int nativeGetUsapPoolCount();
608 
609     /**
610      * @return The event FD used for communication between the signal handler and the ZygoteServer
611      *         poll loop
612      */
getUsapPoolEventFD()613     static FileDescriptor getUsapPoolEventFD() {
614         FileDescriptor fd = new FileDescriptor();
615         fd.setInt$(nativeGetUsapPoolEventFD());
616 
617         return fd;
618     }
619 
nativeGetUsapPoolEventFD()620     private static native int nativeGetUsapPoolEventFD();
621 
622     /**
623      * Fork a new unspecialized app process from the zygote. Adds the Usap to the native
624      * Usap table.
625      *
626      * @param usapPoolSocket  The server socket the USAP will call accept on
627      * @param sessionSocketRawFDs  Anonymous session sockets that are currently open.
628      *         These are closed in the child.
629      * @param isPriorityFork Raise the initial process priority level because this is on the
630      *         critical path for application startup.
631      * @return In the child process, this returns a Runnable that waits for specialization
632      *         info to start an app process. In the sygote/parent process this returns null.
633      */
forkUsap(LocalServerSocket usapPoolSocket, int[] sessionSocketRawFDs, boolean isPriorityFork)634     static @Nullable Runnable forkUsap(LocalServerSocket usapPoolSocket,
635                                        int[] sessionSocketRawFDs,
636                                        boolean isPriorityFork) {
637         FileDescriptor readFD;
638         FileDescriptor writeFD;
639 
640         try {
641             FileDescriptor[] pipeFDs = Os.pipe2(O_CLOEXEC);
642             readFD = pipeFDs[0];
643             writeFD = pipeFDs[1];
644         } catch (ErrnoException errnoEx) {
645             throw new IllegalStateException("Unable to create USAP pipe.", errnoEx);
646         }
647 
648         int pid = nativeForkApp(readFD.getInt$(), writeFD.getInt$(),
649                                 sessionSocketRawFDs, /*argsKnown=*/ false, isPriorityFork);
650         if (pid == 0) {
651             IoUtils.closeQuietly(readFD);
652             return childMain(null, usapPoolSocket, writeFD);
653         } else if (pid == -1) {
654             // Fork failed.
655             return null;
656         } else {
657             // readFD will be closed by the native code. See removeUsapTableEntry();
658             IoUtils.closeQuietly(writeFD);
659             nativeAddUsapTableEntry(pid, readFD.getInt$());
660             return null;
661         }
662     }
663 
nativeForkApp(int readPipeFD, int writePipeFD, int[] sessionSocketRawFDs, boolean argsKnown, boolean isPriorityFork)664     private static native int nativeForkApp(int readPipeFD,
665                                             int writePipeFD,
666                                             int[] sessionSocketRawFDs,
667                                             boolean argsKnown,
668                                             boolean isPriorityFork);
669 
670     /**
671      * Add an entry for a new Usap to the table maintained in native code.
672      */
673     @CriticalNative
nativeAddUsapTableEntry(int pid, int readPipeFD)674     private static native void nativeAddUsapTableEntry(int pid, int readPipeFD);
675 
676     /**
677      * Fork a new app process from the zygote. argBuffer contains a fork command that
678      * request neither a child zygote, nor a wrapped process. Continue to accept connections
679      * on the specified socket, use those to refill argBuffer, and continue to process
680      * sufficiently simple fork requests. We presume that the only open file descriptors
681      * requiring special treatment are the session socket embedded in argBuffer, and
682      * zygoteSocket.
683      * @param argBuffer containing initial command and the connected socket from which to
684      *         read more
685      * @param zygoteSocket socket from which to obtain new connections when current argBuffer
686      *         one is disconnected
687      * @param expectedUId Uid of peer for initial requests. Subsequent requests from a different
688      *               peer will cause us to return rather than perform the requested fork.
689      * @param minUid Minimum Uid enforced for all but first fork request. The caller checks
690      *               the Uid policy for the initial request.
691      * @param firstNiceName name of first created process. Used for error reporting only.
692      * @return A Runnable in each child process, null in the parent.
693      * If this returns in then argBuffer still contains a command needing to be executed.
694      */
forkSimpleApps(@onNull ZygoteCommandBuffer argBuffer, @NonNull FileDescriptor zygoteSocket, int expectedUid, int minUid, @Nullable String firstNiceName)695     static @Nullable Runnable forkSimpleApps(@NonNull ZygoteCommandBuffer argBuffer,
696                                              @NonNull FileDescriptor zygoteSocket,
697                                              int expectedUid,
698                                              int minUid,
699                                              @Nullable String firstNiceName) {
700         boolean in_child =
701                 argBuffer.forkRepeatedly(zygoteSocket, expectedUid, minUid, firstNiceName);
702         if (in_child) {
703             return childMain(argBuffer, /*usapPoolSocket=*/null, /*writePipe=*/null);
704         } else {
705             return null;
706         }
707     }
708 
709     /**
710      * Specialize the current process into one described by argBuffer or the command read from
711      * usapPoolSocket. Exactly one of those must be null. If we are given an argBuffer, we close
712      * it. Used both for a specializing a USAP process, and for process creation without USAPs.
713      * In both cases, we specialize the process after first returning to Java code.
714      *
715      * @param writePipe  The write end of the reporting pipe used to communicate with the poll loop
716      *                   of the ZygoteServer.
717      * @return A runnable oject representing the new application.
718      */
childMain(@ullable ZygoteCommandBuffer argBuffer, @Nullable LocalServerSocket usapPoolSocket, FileDescriptor writePipe)719     private static Runnable childMain(@Nullable ZygoteCommandBuffer argBuffer,
720                                       @Nullable LocalServerSocket usapPoolSocket,
721                                       FileDescriptor writePipe) {
722         final int pid = Process.myPid();
723 
724         DataOutputStream usapOutputStream = null;
725         ZygoteArguments args = null;
726 
727         // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
728         blockSigTerm();
729 
730         LocalSocket sessionSocket = null;
731         if (argBuffer == null) {
732             // Read arguments from usapPoolSocket instead.
733 
734             Process.setArgV0(Process.is64Bit() ? "usap64" : "usap32");
735 
736             // Change the priority to max before calling accept so we can respond to new
737             // specialization requests as quickly as possible.  This will be reverted to the
738             // default priority in the native specialization code.
739             boostUsapPriority();
740 
741             while (true) {
742                 ZygoteCommandBuffer tmpArgBuffer = null;
743                 try {
744                     sessionSocket = usapPoolSocket.accept();
745 
746                     usapOutputStream =
747                             new DataOutputStream(sessionSocket.getOutputStream());
748                     Credentials peerCredentials = sessionSocket.getPeerCredentials();
749                     tmpArgBuffer = new ZygoteCommandBuffer(sessionSocket);
750                     args = ZygoteArguments.getInstance(argBuffer);
751                     applyUidSecurityPolicy(args, peerCredentials);
752                     // TODO (chriswailes): Should this only be run for debug builds?
753                     validateUsapCommand(args);
754                     break;
755                 } catch (Exception ex) {
756                     Log.e("USAP", ex.getMessage());
757                 }
758                 // Re-enable SIGTERM so the USAP can be flushed from the pool if necessary.
759                 unblockSigTerm();
760                 IoUtils.closeQuietly(sessionSocket);
761                 IoUtils.closeQuietly(tmpArgBuffer);
762                 blockSigTerm();
763             }
764         } else {
765             try {
766                 args = ZygoteArguments.getInstance(argBuffer);
767             } catch (Exception ex) {
768                 Log.e("AppStartup", ex.getMessage());
769                 throw new AssertionError("Failed to parse application start command", ex);
770             }
771             // peerCredentials were checked in parent.
772         }
773         if (args == null) {
774             throw new AssertionError("Empty command line");
775         }
776         try {
777             // SIGTERM is blocked here.  This prevents a USAP that is specializing from being
778             // killed during a pool flush.
779 
780             applyDebuggerSystemProperty(args);
781 
782             int[][] rlimits = null;
783 
784             if (args.mRLimits != null) {
785                 rlimits = args.mRLimits.toArray(INT_ARRAY_2D);
786             }
787 
788             if (argBuffer == null) {
789                 // This must happen before the SELinux policy for this process is
790                 // changed when specializing.
791                 try {
792                     // Used by ZygoteProcess.zygoteSendArgsAndGetResult to fill in a
793                     // Process.ProcessStartResult object.
794                     usapOutputStream.writeInt(pid);
795                 } catch (IOException ioEx) {
796                     Log.e("USAP", "Failed to write response to session socket: "
797                             + ioEx.getMessage());
798                     throw new RuntimeException(ioEx);
799                 } finally {
800                     try {
801                         // Since the raw FD is created by init and then loaded from an environment
802                         // variable (as opposed to being created by the LocalSocketImpl itself),
803                         // the LocalSocket/LocalSocketImpl does not own the Os-level socket. See
804                         // the spec for LocalSocket.createConnectedLocalSocket(FileDescriptor fd).
805                         // Thus closing the LocalSocket does not suffice. See b/130309968 for more
806                         // discussion.
807                         FileDescriptor fd = usapPoolSocket.getFileDescriptor();
808                         usapPoolSocket.close();
809                         Os.close(fd);
810                     } catch (ErrnoException | IOException ex) {
811                         Log.e("USAP", "Failed to close USAP pool socket");
812                         throw new RuntimeException(ex);
813                     }
814                 }
815             }
816 
817             if (writePipe != null) {
818                 try {
819                     ByteArrayOutputStream buffer =
820                             new ByteArrayOutputStream(Zygote.USAP_MANAGEMENT_MESSAGE_BYTES);
821                     DataOutputStream outputStream = new DataOutputStream(buffer);
822 
823                     // This is written as a long so that the USAP reporting pipe and USAP pool
824                     // event FD handlers in ZygoteServer.runSelectLoop can be unified.  These two
825                     // cases should both send/receive 8 bytes.
826                     // TODO: Needs tweaking to handle the non-Usap invoke-with case, which expects
827                     // a different format.
828                     outputStream.writeLong(pid);
829                     outputStream.flush();
830                     Os.write(writePipe, buffer.toByteArray(), 0, buffer.size());
831                 } catch (Exception ex) {
832                     Log.e("USAP",
833                             String.format("Failed to write PID (%d) to pipe (%d): %s",
834                                     pid, writePipe.getInt$(), ex.getMessage()));
835                     throw new RuntimeException(ex);
836                 } finally {
837                     IoUtils.closeQuietly(writePipe);
838                 }
839             }
840 
841             specializeAppProcess(args.mUid, args.mGid, args.mGids,
842                                  args.mRuntimeFlags, rlimits, args.mMountExternal,
843                                  args.mSeInfo, args.mNiceName, args.mStartChildZygote,
844                                  args.mInstructionSet, args.mAppDataDir, args.mIsTopApp,
845                                  args.mPkgDataInfoList, args.mAllowlistedDataInfoList,
846                                  args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs);
847 
848             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
849 
850             return ZygoteInit.zygoteInit(args.mTargetSdkVersion,
851                                          args.mDisabledCompatChanges,
852                                          args.mRemainingArgs,
853                                          null /* classLoader */);
854         } finally {
855             // Unblock SIGTERM to restore the process to default behavior.
856             unblockSigTerm();
857         }
858     }
859 
blockSigTerm()860     private static void blockSigTerm() {
861         nativeBlockSigTerm();
862     }
863 
nativeBlockSigTerm()864     private static native void nativeBlockSigTerm();
865 
unblockSigTerm()866     private static void unblockSigTerm() {
867         nativeUnblockSigTerm();
868     }
869 
nativeUnblockSigTerm()870     private static native void nativeUnblockSigTerm();
871 
boostUsapPriority()872     private static void boostUsapPriority() {
873         nativeBoostUsapPriority();
874     }
875 
nativeBoostUsapPriority()876     private static native void nativeBoostUsapPriority();
877 
setAppProcessName(ZygoteArguments args, String loggingTag)878     static void setAppProcessName(ZygoteArguments args, String loggingTag) {
879         if (args.mNiceName != null) {
880             Process.setArgV0(args.mNiceName);
881         } else if (args.mPackageName != null) {
882             Process.setArgV0(args.mPackageName);
883         } else {
884             Log.w(loggingTag, "Unable to set package name.");
885         }
886     }
887 
888     private static final String USAP_ERROR_PREFIX = "Invalid command to USAP: ";
889 
890     /**
891      * Checks a set of zygote arguments to see if they can be handled by a USAP.  Throws an
892      * exception if an invalid arugment is encountered.
893      * @param args  The arguments to test
894      */
validateUsapCommand(ZygoteArguments args)895     private static void validateUsapCommand(ZygoteArguments args) {
896         if (args.mAbiListQuery) {
897             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--query-abi-list");
898         } else if (args.mPidQuery) {
899             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--get-pid");
900         } else if (args.mPreloadDefault) {
901             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--preload-default");
902         } else if (args.mPreloadPackage != null) {
903             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--preload-package");
904         } else if (args.mPreloadApp != null) {
905             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--preload-app");
906         } else if (args.mStartChildZygote) {
907             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--start-child-zygote");
908         } else if (args.mApiDenylistExemptions != null) {
909             throw new IllegalArgumentException(
910                     USAP_ERROR_PREFIX + "--set-api-denylist-exemptions");
911         } else if (args.mHiddenApiAccessLogSampleRate != -1) {
912             throw new IllegalArgumentException(
913                     USAP_ERROR_PREFIX + "--hidden-api-log-sampling-rate=");
914         } else if (args.mHiddenApiAccessStatslogSampleRate != -1) {
915             throw new IllegalArgumentException(
916                     USAP_ERROR_PREFIX + "--hidden-api-statslog-sampling-rate=");
917         } else if (args.mInvokeWith != null) {
918             throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--invoke-with");
919         } else if (args.mPermittedCapabilities != 0 || args.mEffectiveCapabilities != 0) {
920             throw new ZygoteSecurityException("Client may not specify capabilities: "
921                 + "permitted=0x" + Long.toHexString(args.mPermittedCapabilities)
922                 + ", effective=0x" + Long.toHexString(args.mEffectiveCapabilities));
923         }
924     }
925 
926     /**
927      * @return  Raw file descriptors for the read-end of USAP reporting pipes.
928      */
getUsapPipeFDs()929     static int[] getUsapPipeFDs() {
930         return nativeGetUsapPipeFDs();
931     }
932 
nativeGetUsapPipeFDs()933     private static native int[] nativeGetUsapPipeFDs();
934 
935     /**
936      * Remove the USAP table entry for the provided process ID.
937      *
938      * @param usapPID  Process ID of the entry to remove
939      * @return True if the entry was removed; false if it doesn't exist
940      */
removeUsapTableEntry(int usapPID)941     static boolean removeUsapTableEntry(int usapPID) {
942         return nativeRemoveUsapTableEntry(usapPID);
943     }
944 
945     @CriticalNative
nativeRemoveUsapTableEntry(int usapPID)946     private static native boolean nativeRemoveUsapTableEntry(int usapPID);
947 
948     /**
949      * Return the minimum child uid that the given peer is allowed to create.
950      * uid 1000 (Process.SYSTEM_UID) may specify any uid &ge; 1000 in normal
951      * operation. It may also specify any gid and setgroups() list it chooses.
952      * In factory test mode, it may specify any UID.
953      */
minChildUid(Credentials peer)954     static int minChildUid(Credentials peer) {
955         if (peer.getUid() == Process.SYSTEM_UID
956                 && FactoryTest.getMode() == FactoryTest.FACTORY_TEST_OFF) {
957             /* In normal operation, SYSTEM_UID can only specify a restricted
958              * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid.
959              */
960             return Process.SYSTEM_UID;
961         } else {
962             return 0;
963         }
964     }
965 
966     /*
967      * Adjust uid and gid arguments, ensuring that the security policy is satisfied.
968      * @param args non-null; zygote spawner arguments
969      * @param peer non-null; peer credentials
970      * @throws ZygoteSecurityException Indicates a security issue when applying the UID based
971      *  security policies
972      */
applyUidSecurityPolicy(ZygoteArguments args, Credentials peer)973     static void applyUidSecurityPolicy(ZygoteArguments args, Credentials peer)
974             throws ZygoteSecurityException {
975 
976         if (args.mUidSpecified && (args.mUid < minChildUid(peer))) {
977             throw new ZygoteSecurityException(
978                     "System UID may not launch process with UID < "
979                     + Process.SYSTEM_UID);
980         }
981 
982         // If not otherwise specified, uid and gid are inherited from peer
983         if (!args.mUidSpecified) {
984             args.mUid = peer.getUid();
985             args.mUidSpecified = true;
986         }
987         if (!args.mGidSpecified) {
988             args.mGid = peer.getGid();
989             args.mGidSpecified = true;
990         }
991     }
992 
993     /**
994      * Applies debugger system properties to the zygote arguments.
995      *
996      * If "ro.debuggable" is "1", all apps are debuggable. Otherwise,
997      * the debugger state is specified via the "--enable-jdwp" flag
998      * in the spawn request.
999      *
1000      * @param args non-null; zygote spawner args
1001      */
applyDebuggerSystemProperty(ZygoteArguments args)1002     static void applyDebuggerSystemProperty(ZygoteArguments args) {
1003         if (RoSystemProperties.DEBUGGABLE) {
1004             args.mRuntimeFlags |= Zygote.DEBUG_ENABLE_JDWP;
1005         }
1006     }
1007 
1008     /**
1009      * Applies zygote security policy.
1010      * Based on the credentials of the process issuing a zygote command:
1011      * <ol>
1012      * <li> uid 0 (root) may specify --invoke-with to launch Zygote with a
1013      * wrapper command.
1014      * <li> Any other uid may not specify any invoke-with argument.
1015      * </ul>
1016      *
1017      * @param args non-null; zygote spawner arguments
1018      * @param peer non-null; peer credentials
1019      * @throws ZygoteSecurityException Thrown when `--invoke-with` is specified for a non-debuggable
1020      *  application.
1021      */
applyInvokeWithSecurityPolicy(ZygoteArguments args, Credentials peer)1022     static void applyInvokeWithSecurityPolicy(ZygoteArguments args, Credentials peer)
1023             throws ZygoteSecurityException {
1024         int peerUid = peer.getUid();
1025 
1026         if (args.mInvokeWith != null && peerUid != 0
1027                 && (args.mRuntimeFlags & Zygote.DEBUG_ENABLE_JDWP) == 0) {
1028             throw new ZygoteSecurityException("Peer is permitted to specify an "
1029                 + "explicit invoke-with wrapper command only for debuggable "
1030                 + "applications.");
1031         }
1032     }
1033 
1034     /**
1035      * Gets the wrap property if set.
1036      *
1037      * @param appName the application name to check
1038      * @return value of wrap property or null if property not set or
1039      * null if app_name is null or null if app_name is empty
1040      */
getWrapProperty(String appName)1041     public static String getWrapProperty(String appName) {
1042         if (appName == null || appName.isEmpty()) {
1043             return null;
1044         }
1045 
1046         String propertyValue = SystemProperties.get("wrap." + appName);
1047         if (propertyValue != null && !propertyValue.isEmpty()) {
1048             return propertyValue;
1049         }
1050         return null;
1051     }
1052 
1053     /**
1054      * Applies invoke-with system properties to the zygote arguments.
1055      *
1056      * @param args non-null; zygote args
1057      */
applyInvokeWithSystemProperty(ZygoteArguments args)1058     static void applyInvokeWithSystemProperty(ZygoteArguments args) {
1059         if (args.mInvokeWith == null) {
1060             args.mInvokeWith = getWrapProperty(args.mNiceName);
1061         }
1062     }
1063 
1064     /**
1065      * Creates a managed LocalServerSocket object using a file descriptor
1066      * created by an init.rc script.  The init scripts that specify the
1067      * sockets name can be found in system/core/rootdir.  The socket is bound
1068      * to the file system in the /dev/sockets/ directory, and the file
1069      * descriptor is shared via the ANDROID_SOCKET_<socketName> environment
1070      * variable.
1071      */
createManagedSocketFromInitSocket(String socketName)1072     static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
1073         int fileDesc;
1074         final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
1075 
1076         try {
1077             String env = System.getenv(fullSocketName);
1078             fileDesc = Integer.parseInt(env);
1079         } catch (RuntimeException ex) {
1080             throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
1081         }
1082 
1083         try {
1084             FileDescriptor fd = new FileDescriptor();
1085             fd.setInt$(fileDesc);
1086             return new LocalServerSocket(fd);
1087         } catch (IOException ex) {
1088             throw new RuntimeException(
1089                 "Error building socket from file descriptor: " + fileDesc, ex);
1090         }
1091     }
1092 
1093     // This function is called from native code in com_android_internal_os_Zygote.cpp
1094     @SuppressWarnings("unused")
callPostForkSystemServerHooks(int runtimeFlags)1095     private static void callPostForkSystemServerHooks(int runtimeFlags) {
1096         // SystemServer specific post fork hooks run before child post fork hooks.
1097         ZygoteHooks.postForkSystemServer(runtimeFlags);
1098     }
1099 
1100     // This function is called from native code in com_android_internal_os_Zygote.cpp
1101     @SuppressWarnings("unused")
callPostForkChildHooks(int runtimeFlags, boolean isSystemServer, boolean isZygote, String instructionSet)1102     private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer,
1103             boolean isZygote, String instructionSet) {
1104         ZygoteHooks.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
1105     }
1106 
1107     /**
1108      * Executes "/system/bin/sh -c &lt;command&gt;" using the exec() system call.
1109      * This method throws a runtime exception if exec() failed, otherwise, this
1110      * method never returns.
1111      *
1112      * @param command The shell command to execute.
1113      */
execShell(String command)1114     static void execShell(String command) {
1115         String[] args = { "/system/bin/sh", "-c", command };
1116         try {
1117             Os.execv(args[0], args);
1118         } catch (ErrnoException e) {
1119             throw new RuntimeException(e);
1120         }
1121     }
1122 
1123     /**
1124      * Appends quotes shell arguments to the specified string builder.
1125      * The arguments are quoted using single-quotes, escaped if necessary,
1126      * prefixed with a space, and appended to the command.
1127      *
1128      * @param command A string builder for the shell command being constructed.
1129      * @param args An array of argument strings to be quoted and appended to the command.
1130      * @see #execShell(String)
1131      */
appendQuotedShellArgs(StringBuilder command, String[] args)1132     static void appendQuotedShellArgs(StringBuilder command, String[] args) {
1133         for (String arg : args) {
1134             command.append(" '").append(arg.replace("'", "'\\''")).append("'");
1135         }
1136     }
1137 
1138     /**
1139      * Parse the given unsolicited zygote message as type SIGCHLD,
1140      * extract the payload information into the given output buffer.
1141      *
1142      * @param in The unsolicited zygote message to be parsed
1143      * @param length The number of bytes in the message
1144      * @param out The output buffer where the payload information will be placed
1145      * @return Number of elements being place into output buffer, or -1 if
1146      *         either the message is malformed or not the type as expected here.
1147      *
1148      * @hide
1149      */
1150     @FastNative
nativeParseSigChld(byte[] in, int length, int[] out)1151     public static native int nativeParseSigChld(byte[] in, int length, int[] out);
1152 
1153     /**
1154      * Returns whether the hardware supports memory tagging (ARM MTE).
1155      */
nativeSupportsMemoryTagging()1156     public static native boolean nativeSupportsMemoryTagging();
1157 
1158     /**
1159      * Returns whether the kernel supports tagged pointers. Present in the
1160      * Android Common Kernel from 4.14 and up. By default, you should prefer
1161      * fully-feature Memory Tagging, rather than the static Tagged Pointers.
1162      */
nativeSupportsTaggedPointers()1163     public static native boolean nativeSupportsTaggedPointers();
1164 
1165     /**
1166      * Returns the current native tagging level, as one of the
1167      * MEMORY_TAG_LEVEL_* constants. Returns zero if no tagging is present, or
1168      * we failed to determine the level.
1169      */
nativeCurrentTaggingLevel()1170     public static native int nativeCurrentTaggingLevel();
1171 }
1172