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