blob: 40d78688cb4c06a6e3552bcf16b6294ae2e12dcf [file] [log] [blame]
Narayan Kamath973b4662014-03-31 13:41:26 +01001/*
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
17package com.android.internal.os;
18
Chris Wailescb0b37f2019-01-11 17:04:41 -080019import static android.system.OsConstants.O_CLOEXEC;
20
Chris Wailes2be26262019-01-11 16:14:43 -080021import static com.android.internal.os.ZygoteConnectionConstants.MAX_ZYGOTE_ARGC;
22
Martijn Coenen4b988162019-01-28 13:58:45 +010023import android.content.pm.ApplicationInfo;
Chris Wailes2be26262019-01-11 16:14:43 -080024import android.net.Credentials;
Chris Wailescb0b37f2019-01-11 17:04:41 -080025import android.net.LocalServerSocket;
26import android.net.LocalSocket;
Chris Wailes2be26262019-01-11 16:14:43 -080027import android.os.FactoryTest;
Jeff Sharkeyace874b2017-09-07 15:27:33 -060028import android.os.IVold;
Chris Wailes2be26262019-01-11 16:14:43 -080029import android.os.Process;
30import android.os.SystemProperties;
Narayan Kamathfbb32f62015-06-12 15:34:35 +010031import android.os.Trace;
Elliott Hughes860c5912014-04-28 19:19:13 -070032import android.system.ErrnoException;
33import android.system.Os;
Chris Wailes2be26262019-01-11 16:14:43 -080034import android.util.Log;
Narayan Kamath973b4662014-03-31 13:41:26 +010035
Jeff Sharkeyace874b2017-09-07 15:27:33 -060036import dalvik.system.ZygoteHooks;
Tobias Sargeantb9679dc2016-01-19 16:34:54 +000037
Chris Wailescb0b37f2019-01-11 17:04:41 -080038import libcore.io.IoUtils;
39
Chris Wailes2be26262019-01-11 16:14:43 -080040import java.io.BufferedReader;
Chris Wailescb0b37f2019-01-11 17:04:41 -080041import java.io.ByteArrayOutputStream;
42import java.io.DataOutputStream;
43import java.io.FileDescriptor;
Chris Wailes2be26262019-01-11 16:14:43 -080044import java.io.IOException;
Chris Wailescb0b37f2019-01-11 17:04:41 -080045import java.io.InputStreamReader;
Chris Wailes2be26262019-01-11 16:14:43 -080046
Narayan Kamath973b4662014-03-31 13:41:26 +010047/** @hide */
48public final class Zygote {
49 /*
Nicolas Geoffray81edac42017-09-07 14:13:29 +010050 * Bit values for "runtimeFlags" argument. The definitions are duplicated
Narayan Kamath973b4662014-03-31 13:41:26 +010051 * in the native code.
52 */
53
54 /** enable debugging over JDWP */
Nicolas Geoffray347b1df2016-12-20 14:05:05 +000055 public static final int DEBUG_ENABLE_JDWP = 1;
Narayan Kamath973b4662014-03-31 13:41:26 +010056 /** enable JNI checks */
57 public static final int DEBUG_ENABLE_CHECKJNI = 1 << 1;
58 /** enable Java programming language "assert" statements */
59 public static final int DEBUG_ENABLE_ASSERT = 1 << 2;
Mathieu Chartier7a490282015-03-17 09:51:36 -070060 /** disable the AOT compiler and JIT */
Narayan Kamath973b4662014-03-31 13:41:26 +010061 public static final int DEBUG_ENABLE_SAFEMODE = 1 << 3;
62 /** Enable logging of third-party JNI activity. */
63 public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
David Srbecky065075e2015-05-28 17:16:09 +010064 /** Force generation of native debugging information. */
Nicolas Geoffray9abbf452015-11-05 11:29:42 +000065 public static final int DEBUG_GENERATE_DEBUG_INFO = 1 << 5;
Tamas Berghammerdf6cb282016-01-29 12:07:00 +000066 /** Always use JIT-ed code. */
67 public static final int DEBUG_ALWAYS_JIT = 1 << 6;
Nicolas Geoffray347b1df2016-12-20 14:05:05 +000068 /** Make the code native debuggable by turning off some optimizations. */
Tamas Berghammerdf6cb282016-01-29 12:07:00 +000069 public static final int DEBUG_NATIVE_DEBUGGABLE = 1 << 7;
Nicolas Geoffray347b1df2016-12-20 14:05:05 +000070 /** Make the code Java debuggable by turning off some optimizations. */
71 public static final int DEBUG_JAVA_DEBUGGABLE = 1 << 8;
Mathieu Chartier7a490282015-03-17 09:51:36 -070072
Nicolas Geoffray1f88ad62017-09-13 14:21:00 +010073 /** Turn off the verifier. */
74 public static final int DISABLE_VERIFIER = 1 << 9;
75 /** Only use oat files located in /system. Otherwise use dex/jar/apk . */
76 public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10;
David Srbecky156ed922018-01-30 14:37:37 +000077 /** Force generation of native debugging information for backtraces. */
Mathew Inwood16073b82018-03-23 10:05:01 +000078 public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 11;
79 /**
80 * Hidden API access restrictions. This is a mask for bits representing the API enforcement
81 * policy, defined by {@code @ApplicationInfo.HiddenApiEnforcementPolicy}.
82 */
83 public static final int API_ENFORCEMENT_POLICY_MASK = (1 << 12) | (1 << 13);
84 /**
85 * Bit shift for use with {@link #API_ENFORCEMENT_POLICY_MASK}.
86 *
87 * (flags & API_ENFORCEMENT_POLICY_MASK) >> API_ENFORCEMENT_POLICY_SHIFT gives
88 * @ApplicationInfo.ApiEnforcementPolicy values.
89 */
90 public static final int API_ENFORCEMENT_POLICY_SHIFT =
91 Integer.numberOfTrailingZeros(API_ENFORCEMENT_POLICY_MASK);
Calin Juravle8eb891b2018-05-03 19:51:18 -070092 /**
93 * Enable system server ART profiling.
94 */
95 public static final int PROFILE_SYSTEM_SERVER = 1 << 14;
Nicolas Geoffray1f88ad62017-09-13 14:21:00 +010096
Yabin Cui4d8546d2019-01-29 16:29:20 -080097 /**
98 * Enable profiling from shell.
99 */
100 public static final int PROFILE_FROM_SHELL = 1 << 15;
101
Mathieu Chartierced7e082019-02-04 13:28:36 -0800102 /*
103 * Enable using the ART app image startup cache
104 */
105 public static final int USE_APP_IMAGE_STARTUP_CACHE = 1 << 16;
106
Narayan Kamath973b4662014-03-31 13:41:26 +0100107 /** No external storage should be mounted. */
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600108 public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700109 /** Default external storage should be mounted. */
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600110 public static final int MOUNT_EXTERNAL_DEFAULT = IVold.REMOUNT_MODE_DEFAULT;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700111 /** Read-only external storage should be mounted. */
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600112 public static final int MOUNT_EXTERNAL_READ = IVold.REMOUNT_MODE_READ;
Jeff Sharkey9527b222015-06-24 15:24:48 -0700113 /** Read-write external storage should be mounted. */
Jeff Sharkeyace874b2017-09-07 15:27:33 -0600114 public static final int MOUNT_EXTERNAL_WRITE = IVold.REMOUNT_MODE_WRITE;
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800115 /**
Sudheer Shanka0b6da532019-01-09 12:06:51 -0800116 * Mount mode for apps that are already installed on the device before the isolated_storage
117 * feature is enabled.
118 */
119 public static final int MOUNT_EXTERNAL_LEGACY = IVold.REMOUNT_MODE_LEGACY;
120 /**
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800121 * Mount mode for package installers which should give them access to
122 * all obb dirs in addition to their package sandboxes
123 */
124 public static final int MOUNT_EXTERNAL_INSTALLER = IVold.REMOUNT_MODE_INSTALLER;
Sudheer Shanka98cb3f02018-08-17 16:10:29 -0700125 /** Read-write external storage should be mounted instead of package sandbox */
126 public static final int MOUNT_EXTERNAL_FULL = IVold.REMOUNT_MODE_FULL;
Narayan Kamath973b4662014-03-31 13:41:26 +0100127
Chris Wailescb0b37f2019-01-11 17:04:41 -0800128 /** Number of bytes sent to the Zygote over blastula pipes or the pool event FD */
129 public static final int BLASTULA_MANAGEMENT_MESSAGE_BYTES = 8;
130
Chris Wailesba4c2eb2019-01-11 17:13:00 -0800131 /**
132 * If the blastula pool should be created and used to start applications.
133 *
134 * Setting this value to false will disable the creation, maintenance, and use of the blastula
135 * pool. When the blastula pool is disabled the application lifecycle will be identical to
136 * previous versions of Android.
137 */
Chris Wailescb0b37f2019-01-11 17:04:41 -0800138 public static final boolean BLASTULA_POOL_ENABLED = false;
139
140 /**
141 * File descriptor used for communication between the signal handler and the ZygoteServer poll
142 * loop.
143 * */
144 protected static FileDescriptor sBlastulaPoolEventFD;
145
Robert Sesekd0a190df2018-02-12 18:46:01 -0500146 /**
147 * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
148 * in the abstract socket namespace. This socket name is what the new child zygote
149 * should listen for connections on.
150 */
151 public static final String CHILD_ZYGOTE_SOCKET_NAME_ARG = "--zygote-socket=";
152
Martijn Coenen7e6fa672018-11-05 11:45:26 +0100153 /**
154 * An extraArg passed when a zygote process is forking a child-zygote, specifying the
155 * requested ABI for the child Zygote.
156 */
157 public static final String CHILD_ZYGOTE_ABI_LIST_ARG = "--abi-list=";
158
Martijn Coenen86f08a52019-01-03 16:23:01 +0100159 /**
160 * An extraArg passed when a zygote process is forking a child-zygote, specifying the
161 * start of the UID range the children of the Zygote may setuid()/setgid() to. This
162 * will be enforced with a seccomp filter.
163 */
164 public static final String CHILD_ZYGOTE_UID_RANGE_START = "--uid-range-start=";
165
166 /**
167 * An extraArg passed when a zygote process is forking a child-zygote, specifying the
168 * end of the UID range the children of the Zygote may setuid()/setgid() to. This
169 * will be enforced with a seccomp filter.
170 */
171 public static final String CHILD_ZYGOTE_UID_RANGE_END = "--uid-range-end=";
172
Chris Wailescb0b37f2019-01-11 17:04:41 -0800173 /** Prefix prepended to socket names created by init */
174 private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
175
176 /**
177 * The maximum value that the sBlastulaPoolMax variable may take. This value
178 * is a mirror of BLASTULA_POOL_MAX_LIMIT found in com_android_internal_os_Zygote.cpp.
179 */
180 static final int BLASTULA_POOL_MAX_LIMIT = 10;
181
182 /**
183 * The minimum value that the sBlastulaPoolMin variable may take.
184 */
185 static final int BLASTULA_POOL_MIN_LIMIT = 1;
186
187 /**
188 * The runtime-adjustable maximum Blastula pool size.
189 */
190 static int sBlastulaPoolMax = BLASTULA_POOL_MAX_LIMIT;
191
192 /**
193 * The runtime-adjustable minimum Blastula pool size.
194 */
195 static int sBlastulaPoolMin = BLASTULA_POOL_MIN_LIMIT;
196
197 /**
198 * The runtime-adjustable value used to determine when to re-fill the
199 * blastula pool. The pool will be re-filled when
200 * (sBlastulaPoolMax - gBlastulaPoolCount) >= sBlastulaPoolRefillThreshold.
201 */
202 // TODO (chriswailes): This must be updated at the same time as sBlastulaPoolMax.
203 static int sBlastulaPoolRefillThreshold = (sBlastulaPoolMax / 2);
204
Chris Wailesba4c2eb2019-01-11 17:13:00 -0800205 /**
206 * @hide for internal use only
207 */
208 public static final int SOCKET_BUFFER_SIZE = 256;
209
Chris Wailescb0b37f2019-01-11 17:04:41 -0800210 private static LocalServerSocket sBlastulaPoolSocket = null;
211
Chris Wailes2be26262019-01-11 16:14:43 -0800212 /** a prototype instance for a future List.toArray() */
213 protected static final int[][] INT_ARRAY_2D = new int[0][0];
214
Narayan Kamath973b4662014-03-31 13:41:26 +0100215 private Zygote() {}
216
Victor Hsiehc8176ef2018-01-08 12:43:00 -0800217 /** Called for some security initialization before any fork. */
Chris Wailesaa1c9622019-01-10 16:55:32 -0800218 static native void nativeSecurityInit();
Victor Hsiehc8176ef2018-01-08 12:43:00 -0800219
Narayan Kamath973b4662014-03-31 13:41:26 +0100220 /**
221 * Forks a new VM instance. The current VM must have been started
222 * with the -Xzygote flag. <b>NOTE: new instance keeps all
223 * root capabilities. The new process is expected to call capset()</b>.
224 *
225 * @param uid the UNIX uid that the new process should setuid() to after
226 * fork()ing and and before spawning any threads.
227 * @param gid the UNIX gid that the new process should setgid() to after
228 * fork()ing and and before spawning any threads.
229 * @param gids null-ok; a list of UNIX gids that the new process should
230 * setgroups() to after fork and before spawning any threads.
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100231 * @param runtimeFlags bit flags that enable ART features.
Narayan Kamath973b4662014-03-31 13:41:26 +0100232 * @param rlimits null-ok an array of rlimit tuples, with the second
233 * dimension having a length of 3 and representing
234 * (resource, rlim_cur, rlim_max). These are set via the posix
235 * setrlimit(2) call.
236 * @param seInfo null-ok a string specifying SELinux information for
237 * the new process.
238 * @param niceName null-ok a string specifying the process name.
239 * @param fdsToClose an array of ints, holding one or more POSIX
240 * file descriptor numbers that are to be closed by the child
241 * (and replaced by /dev/null) after forking. An integer value
242 * of -1 in any entry in the array means "ignore this one".
Andreas Gampe8dfa1782017-01-05 12:45:58 -0800243 * @param fdsToIgnore null-ok an array of ints, either null or holding
244 * one or more POSIX file descriptor numbers that are to be ignored
245 * in the file descriptor table check.
Robert Sesekd0a190df2018-02-12 18:46:01 -0500246 * @param startChildZygote if true, the new child process will itself be a
247 * new zygote process.
Andreas Gampeaec67dc2014-09-02 21:23:06 -0700248 * @param instructionSet null-ok the instruction set to use.
jgu212eacd062014-09-10 06:55:07 -0400249 * @param appDataDir null-ok the data directory of the app.
Narayan Kamath973b4662014-03-31 13:41:26 +0100250 *
251 * @return 0 if this is the child, pid of the child
252 * if this is the parent, or -1 on error.
253 */
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100254 public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700255 int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
256 int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
Sudheer Shanka03fd40b2019-02-06 12:39:14 -0800257 String packageName, String[] packagesForUID, String[] visibleVolIDs, String sandboxId) {
Neil Fuller555d8b72019-01-28 18:29:20 +0000258 ZygoteHooks.preFork();
Hiroshi Yamauchi1e3db872017-03-02 13:39:07 -0800259 // Resets nice priority for zygote process.
260 resetNicePriority();
Narayan Kamath973b4662014-03-31 13:41:26 +0100261 int pid = nativeForkAndSpecialize(
Chris Wailesaa1c9622019-01-10 16:55:32 -0800262 uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
263 fdsToIgnore, startChildZygote, instructionSet, appDataDir, packageName,
Sudheer Shanka03fd40b2019-02-06 12:39:14 -0800264 packagesForUID, visibleVolIDs, sandboxId);
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100265 // Enable tracing as soon as possible for the child process.
266 if (pid == 0) {
Andreas Gampe8f4eab22017-09-13 18:16:13 -0700267 Trace.setTracingEnabled(true, runtimeFlags);
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100268
269 // Note that this event ends at the end of handleChildProc,
270 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
271 }
Neil Fuller555d8b72019-01-28 18:29:20 +0000272 ZygoteHooks.postForkCommon();
Narayan Kamath973b4662014-03-31 13:41:26 +0100273 return pid;
274 }
275
Chris Wailesaa1c9622019-01-10 16:55:32 -0800276 private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
277 int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
278 int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
Sudheer Shanka03fd40b2019-02-06 12:39:14 -0800279 String appDataDir, String packageName, String[] packagesForUID, String[] visibleVolIDs,
280 String sandboxId);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800281
Chris Wailescb0b37f2019-01-11 17:04:41 -0800282 /**
283 * Specialize a Blastula instance. The current VM must have been started
284 * with the -Xzygote flag.
285 *
286 * @param uid The UNIX uid that the new process should setuid() to before spawning any threads
287 * @param gid The UNIX gid that the new process should setgid() to before spawning any threads
288 * @param gids null-ok; A list of UNIX gids that the new process should
289 * setgroups() to before spawning any threads
290 * @param runtimeFlags Bit flags that enable ART features
291 * @param rlimits null-ok An array of rlimit tuples, with the second
292 * dimension having a length of 3 and representing
293 * (resource, rlim_cur, rlim_max). These are set via the posix
294 * setrlimit(2) call.
295 * @param seInfo null-ok A string specifying SELinux information for
296 * the new process.
297 * @param niceName null-ok A string specifying the process name.
298 * @param startChildZygote If true, the new child process will itself be a
299 * new zygote process.
300 * @param instructionSet null-ok The instruction set to use.
301 * @param appDataDir null-ok The data directory of the app.
302 */
303 public static void specializeBlastula(int uid, int gid, int[] gids, int runtimeFlags,
304 int[][] rlimits, int mountExternal, String seInfo, String niceName,
Chris Wailesba4c2eb2019-01-11 17:13:00 -0800305 boolean startChildZygote, String instructionSet, String appDataDir, String packageName,
Sudheer Shanka03fd40b2019-02-06 12:39:14 -0800306 String[] packagesForUID, String[] visibleVolIDs, String sandboxId) {
Chris Wailescb0b37f2019-01-11 17:04:41 -0800307
308 nativeSpecializeBlastula(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
309 niceName, startChildZygote, instructionSet, appDataDir,
Sudheer Shanka03fd40b2019-02-06 12:39:14 -0800310 packageName, packagesForUID, visibleVolIDs, sandboxId);
Chris Wailescb0b37f2019-01-11 17:04:41 -0800311
312 // Enable tracing as soon as possible for the child process.
313 Trace.setTracingEnabled(true, runtimeFlags);
314
315 // Note that this event ends at the end of handleChildProc.
316 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
317
318 /*
319 * This is called here (instead of after the fork but before the specialize) to maintain
320 * consistancy with the code paths for forkAndSpecialize.
321 *
322 * TODO (chriswailes): Look into moving this to immediately after the fork.
323 */
Neil Fuller555d8b72019-01-28 18:29:20 +0000324 ZygoteHooks.postForkCommon();
Chris Wailescb0b37f2019-01-11 17:04:41 -0800325 }
326
Chris Wailesaa1c9622019-01-10 16:55:32 -0800327 private static native void nativeSpecializeBlastula(int uid, int gid, int[] gids,
328 int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
329 boolean startChildZygote, String instructionSet, String appDataDir, String packageName,
Sudheer Shanka03fd40b2019-02-06 12:39:14 -0800330 String[] packagesForUID, String[] visibleVolIDs, String sandboxId);
Narayan Kamath973b4662014-03-31 13:41:26 +0100331
332 /**
Christopher Ferris2980de42017-06-20 16:13:40 -0700333 * Called to do any initialization before starting an application.
334 */
Chris Wailesaa1c9622019-01-10 16:55:32 -0800335 static native void nativePreApplicationInit();
Christopher Ferris2980de42017-06-20 16:13:40 -0700336
337 /**
Narayan Kamath973b4662014-03-31 13:41:26 +0100338 * Special method to start the system server process. In addition to the
339 * common actions performed in forkAndSpecialize, the pid of the child
340 * process is recorded such that the death of the child process will cause
341 * zygote to exit.
342 *
343 * @param uid the UNIX uid that the new process should setuid() to after
344 * fork()ing and and before spawning any threads.
345 * @param gid the UNIX gid that the new process should setgid() to after
346 * fork()ing and and before spawning any threads.
347 * @param gids null-ok; a list of UNIX gids that the new process should
348 * setgroups() to after fork and before spawning any threads.
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100349 * @param runtimeFlags bit flags that enable ART features.
Narayan Kamath973b4662014-03-31 13:41:26 +0100350 * @param rlimits null-ok an array of rlimit tuples, with the second
351 * dimension having a length of 3 and representing
352 * (resource, rlim_cur, rlim_max). These are set via the posix
353 * setrlimit(2) call.
354 * @param permittedCapabilities argument for setcap()
355 * @param effectiveCapabilities argument for setcap()
356 *
357 * @return 0 if this is the child, pid of the child
358 * if this is the parent, or -1 on error.
359 */
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100360 public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
Narayan Kamath973b4662014-03-31 13:41:26 +0100361 int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
Neil Fuller555d8b72019-01-28 18:29:20 +0000362 ZygoteHooks.preFork();
Hiroshi Yamauchi1e3db872017-03-02 13:39:07 -0800363 // Resets nice priority for zygote process.
364 resetNicePriority();
Narayan Kamath973b4662014-03-31 13:41:26 +0100365 int pid = nativeForkSystemServer(
Chris Wailesaa1c9622019-01-10 16:55:32 -0800366 uid, gid, gids, runtimeFlags, rlimits,
367 permittedCapabilities, effectiveCapabilities);
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100368 // Enable tracing as soon as we enter the system_server.
369 if (pid == 0) {
Andreas Gampe8f4eab22017-09-13 18:16:13 -0700370 Trace.setTracingEnabled(true, runtimeFlags);
Narayan Kamathfbb32f62015-06-12 15:34:35 +0100371 }
Neil Fuller555d8b72019-01-28 18:29:20 +0000372 ZygoteHooks.postForkCommon();
Narayan Kamath973b4662014-03-31 13:41:26 +0100373 return pid;
374 }
375
Chris Wailesaa1c9622019-01-10 16:55:32 -0800376 private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
Narayan Kamath973b4662014-03-31 13:41:26 +0100377 int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
378
doheon1.lee885b7422016-01-20 13:07:27 +0900379 /**
Robert Sesek54e387d2016-12-02 17:27:50 -0500380 * Lets children of the zygote inherit open file descriptors to this path.
381 */
Chris Wailesaa1c9622019-01-10 16:55:32 -0800382 protected static native void nativeAllowFileAcrossFork(String path);
Robert Sesek54e387d2016-12-02 17:27:50 -0500383
384 /**
Martijn Coenen4b988162019-01-28 13:58:45 +0100385 * Lets children of the zygote inherit open file descriptors that belong to the
386 * ApplicationInfo that is passed in.
387 *
388 * @param appInfo ApplicationInfo of the application
389 */
390 protected static void allowAppFilesAcrossFork(ApplicationInfo appInfo) {
391 Zygote.nativeAllowFileAcrossFork(appInfo.sourceDir);
392 if (appInfo.splitSourceDirs != null) {
393 for (String path : appInfo.splitSourceDirs) {
394 Zygote.nativeAllowFileAcrossFork(path);
395 }
396 }
397 // As well as its shared libs
398 if (appInfo.sharedLibraryFiles != null) {
399 for (String path : appInfo.sharedLibraryFiles) {
400 Zygote.nativeAllowFileAcrossFork(path);
401 }
402 }
403 }
404
405 /**
Martijn Coenen86f08a52019-01-03 16:23:01 +0100406 * Installs a seccomp filter that limits setresuid()/setresgid() to the passed-in range
407 * @param uidGidMin The smallest allowed uid/gid
408 * @param uidGidMax The largest allowed uid/gid
409 */
410 native protected static void nativeInstallSeccompUidGidFilter(int uidGidMin, int uidGidMax);
411
412 /**
doheon1.lee885b7422016-01-20 13:07:27 +0900413 * Zygote unmount storage space on initializing.
414 * This method is called once.
415 */
Chris Wailesaa1c9622019-01-10 16:55:32 -0800416 protected static native void nativeUnmountStorageOnInit();
417
Chris Wailescb0b37f2019-01-11 17:04:41 -0800418 /**
419 * Get socket file descriptors (opened by init) from the environment and
420 * store them for access from native code later.
421 *
422 * @param isPrimary True if this is the zygote process, false if it is zygote_secondary
423 */
424 public static void getSocketFDs(boolean isPrimary) {
425 nativeGetSocketFDs(isPrimary);
426 }
427
Chris Wailesaa1c9622019-01-10 16:55:32 -0800428 protected static native void nativeGetSocketFDs(boolean isPrimary);
429
Chris Wailescb0b37f2019-01-11 17:04:41 -0800430 /**
431 * Initialize the blastula pool and fill it with the desired number of
432 * processes.
433 */
434 protected static Runnable initBlastulaPool() {
435 if (BLASTULA_POOL_ENABLED) {
436 sBlastulaPoolEventFD = getBlastulaPoolEventFD();
437
438 return fillBlastulaPool(null);
439 } else {
440 return null;
441 }
442 }
443
444 /**
445 * Checks to see if the current policy says that pool should be refilled, and spawns new
446 * blastulas if necessary.
447 *
448 * NOTE: This function doesn't need to be guarded with BLASTULA_POOL_ENABLED because it is
449 * only called from contexts that are only valid if the pool is enabled.
450 *
451 * @param sessionSocketRawFDs Anonymous session sockets that are currently open
452 * @return In the Zygote process this function will always return null; in blastula processes
453 * this function will return a Runnable object representing the new application that is
454 * passed up from blastulaMain.
455 */
456 protected static Runnable fillBlastulaPool(int[] sessionSocketRawFDs) {
457 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillBlastulaPool");
458
459 int blastulaPoolCount = getBlastulaPoolCount();
460
461 int numBlastulasToSpawn = sBlastulaPoolMax - blastulaPoolCount;
462
463 if (blastulaPoolCount < sBlastulaPoolMin
464 || numBlastulasToSpawn >= sBlastulaPoolRefillThreshold) {
465
466 // Disable some VM functionality and reset some system values
467 // before forking.
Neil Fuller555d8b72019-01-28 18:29:20 +0000468 ZygoteHooks.preFork();
Chris Wailescb0b37f2019-01-11 17:04:41 -0800469 resetNicePriority();
470
471 while (blastulaPoolCount++ < sBlastulaPoolMax) {
472 Runnable caller = forkBlastula(sessionSocketRawFDs);
473
474 if (caller != null) {
475 return caller;
476 }
477 }
478
479 // Re-enable runtime services for the Zygote. Blastula services
480 // are re-enabled in specializeBlastula.
Neil Fuller555d8b72019-01-28 18:29:20 +0000481 ZygoteHooks.postForkCommon();
Chris Wailescb0b37f2019-01-11 17:04:41 -0800482
483 Log.i("zygote", "Filled the blastula pool. New blastulas: " + numBlastulasToSpawn);
484 }
485
486 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
487
488 return null;
489 }
490
491 /**
492 * @return Number of blastulas currently in the pool
493 */
494 private static int getBlastulaPoolCount() {
495 return nativeGetBlastulaPoolCount();
496 }
497
Chris Wailesaa1c9622019-01-10 16:55:32 -0800498 private static native int nativeGetBlastulaPoolCount();
499
Chris Wailescb0b37f2019-01-11 17:04:41 -0800500 /**
501 * @return The event FD used for communication between the signal handler and the ZygoteServer
502 * poll loop
503 */
504 private static FileDescriptor getBlastulaPoolEventFD() {
505 FileDescriptor fd = new FileDescriptor();
506 fd.setInt$(nativeGetBlastulaPoolEventFD());
507
508 return fd;
509 }
510
Chris Wailesaa1c9622019-01-10 16:55:32 -0800511 private static native int nativeGetBlastulaPoolEventFD();
512
Chris Wailescb0b37f2019-01-11 17:04:41 -0800513 /**
514 * Fork a new blastula process from the zygote
515 *
516 * @param sessionSocketRawFDs Anonymous session sockets that are currently open
517 * @return In the Zygote process this function will always return null; in blastula processes
518 * this function will return a Runnable object representing the new application that is
519 * passed up from blastulaMain.
520 */
521 private static Runnable forkBlastula(int[] sessionSocketRawFDs) {
522 FileDescriptor[] pipeFDs = null;
523
524 try {
525 pipeFDs = Os.pipe2(O_CLOEXEC);
526 } catch (ErrnoException errnoEx) {
527 throw new IllegalStateException("Unable to create blastula pipe.", errnoEx);
528 }
529
530 int pid =
531 nativeForkBlastula(pipeFDs[0].getInt$(), pipeFDs[1].getInt$(), sessionSocketRawFDs);
532
533 if (pid == 0) {
534 IoUtils.closeQuietly(pipeFDs[0]);
535 return blastulaMain(pipeFDs[1]);
536 } else {
537 // The read-end of the pipe will be closed by the native code.
538 // See removeBlastulaTableEntry();
539 IoUtils.closeQuietly(pipeFDs[1]);
540 return null;
541 }
542 }
543
Chris Wailesaa1c9622019-01-10 16:55:32 -0800544 private static native int nativeForkBlastula(int readPipeFD,
545 int writePipeFD,
546 int[] sessionSocketRawFDs);
547
Chris Wailescb0b37f2019-01-11 17:04:41 -0800548 /**
549 * This function is used by blastulas to wait for specialization requests from the system
550 * server.
551 *
552 * @param writePipe The write end of the reporting pipe used to communicate with the poll loop
553 * of the ZygoteServer.
554 * @return A runnable oject representing the new application.
555 */
556 static Runnable blastulaMain(FileDescriptor writePipe) {
557 final int pid = Process.myPid();
558
559 LocalSocket sessionSocket = null;
560 DataOutputStream blastulaOutputStream = null;
561 Credentials peerCredentials = null;
562 String[] argStrings = null;
563
564 while (true) {
565 try {
566 sessionSocket = sBlastulaPoolSocket.accept();
567
568 BufferedReader blastulaReader =
569 new BufferedReader(new InputStreamReader(sessionSocket.getInputStream()));
570 blastulaOutputStream =
571 new DataOutputStream(sessionSocket.getOutputStream());
572
573 peerCredentials = sessionSocket.getPeerCredentials();
574
575 argStrings = readArgumentList(blastulaReader);
576
577 if (argStrings != null) {
578 break;
579 } else {
580 Log.e("Blastula", "Truncated command received.");
581 IoUtils.closeQuietly(sessionSocket);
582 }
583 } catch (IOException ioEx) {
584 Log.e("Blastula", "Failed to read command: " + ioEx.getMessage());
585 IoUtils.closeQuietly(sessionSocket);
586 }
587 }
588
589 ZygoteArguments args = new ZygoteArguments(argStrings);
590
591 // TODO (chriswailes): Should this only be run for debug builds?
592 validateBlastulaCommand(args);
593
594 applyUidSecurityPolicy(args, peerCredentials);
595 applyDebuggerSystemProperty(args);
596
597 int[][] rlimits = null;
598
599 if (args.mRLimits != null) {
600 rlimits = args.mRLimits.toArray(INT_ARRAY_2D);
601 }
602
603 // This must happen before the SELinux policy for this process is
604 // changed when specializing.
605 try {
606 // Used by ZygoteProcess.zygoteSendArgsAndGetResult to fill in a
607 // Process.ProcessStartResult object.
608 blastulaOutputStream.writeInt(pid);
609 } catch (IOException ioEx) {
610 Log.e("Blastula", "Failed to write response to session socket: " + ioEx.getMessage());
611 System.exit(-1);
612 } finally {
613 IoUtils.closeQuietly(sessionSocket);
614 IoUtils.closeQuietly(sBlastulaPoolSocket);
615 }
616
617 try {
618 ByteArrayOutputStream buffer =
619 new ByteArrayOutputStream(Zygote.BLASTULA_MANAGEMENT_MESSAGE_BYTES);
620 DataOutputStream outputStream = new DataOutputStream(buffer);
621
622 // This is written as a long so that the blastula reporting pipe and blastula pool
623 // event FD handlers in ZygoteServer.runSelectLoop can be unified. These two cases
624 // should both send/receive 8 bytes.
625 outputStream.writeLong(pid);
626 outputStream.flush();
627
628 Os.write(writePipe, buffer.toByteArray(), 0, buffer.size());
629 } catch (Exception ex) {
630 Log.e("Blastula",
631 String.format("Failed to write PID (%d) to pipe (%d): %s",
632 pid, writePipe.getInt$(), ex.getMessage()));
633 System.exit(-1);
634 } finally {
635 IoUtils.closeQuietly(writePipe);
636 }
637
638 specializeBlastula(args.mUid, args.mGid, args.mGids,
639 args.mRuntimeFlags, rlimits, args.mMountExternal,
640 args.mSeInfo, args.mNiceName, args.mStartChildZygote,
641 args.mInstructionSet, args.mAppDataDir, args.mPackageName,
Sudheer Shanka03fd40b2019-02-06 12:39:14 -0800642 args.mPackagesForUid, args.mVisibleVolIds, args.mSandboxId);
Chris Wailescb0b37f2019-01-11 17:04:41 -0800643
644 if (args.mNiceName != null) {
645 Process.setArgV0(args.mNiceName);
646 }
647
648 // End of the postFork event.
649 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
650
651 return ZygoteInit.zygoteInit(args.mTargetSdkVersion,
652 args.mRemainingArgs,
653 null /* classLoader */);
654 }
655
656 private static final String BLASTULA_ERROR_PREFIX = "Invalid command to blastula: ";
657
658 /**
659 * Checks a set of zygote arguments to see if they can be handled by a blastula. Throws an
660 * exception if an invalid arugment is encountered.
661 * @param args The arguments to test
662 */
663 static void validateBlastulaCommand(ZygoteArguments args) {
664 if (args.mAbiListQuery) {
665 throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--query-abi-list");
666 } else if (args.mPidQuery) {
667 throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--get-pid");
668 } else if (args.mPreloadDefault) {
669 throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--preload-default");
670 } else if (args.mPreloadPackage != null) {
671 throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--preload-package");
672 } else if (args.mPreloadApp != null) {
673 throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--preload-app");
674 } else if (args.mStartChildZygote) {
675 throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--start-child-zygote");
676 } else if (args.mApiBlacklistExemptions != null) {
677 throw new IllegalArgumentException(
678 BLASTULA_ERROR_PREFIX + "--set-api-blacklist-exemptions");
679 } else if (args.mHiddenApiAccessLogSampleRate != -1) {
680 throw new IllegalArgumentException(
681 BLASTULA_ERROR_PREFIX + "--hidden-api-log-sampling-rate=");
682 } else if (args.mInvokeWith != null) {
683 throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--invoke-with");
684 } else if (args.mPermittedCapabilities != 0 || args.mEffectiveCapabilities != 0) {
685 throw new ZygoteSecurityException("Client may not specify capabilities: "
686 + "permitted=0x" + Long.toHexString(args.mPermittedCapabilities)
687 + ", effective=0x" + Long.toHexString(args.mEffectiveCapabilities));
688 }
689 }
690
691 /**
692 * @return Raw file descriptors for the read-end of blastula reporting pipes.
693 */
694 protected static int[] getBlastulaPipeFDs() {
695 return nativeGetBlastulaPipeFDs();
696 }
697
Chris Wailesaa1c9622019-01-10 16:55:32 -0800698 private static native int[] nativeGetBlastulaPipeFDs();
699
Chris Wailescb0b37f2019-01-11 17:04:41 -0800700 /**
701 * Remove the blastula table entry for the provided process ID.
702 *
703 * @param blastulaPID Process ID of the entry to remove
704 * @return True if the entry was removed; false if it doesn't exist
705 */
706 protected static boolean removeBlastulaTableEntry(int blastulaPID) {
707 return nativeRemoveBlastulaTableEntry(blastulaPID);
708 }
709
Chris Wailesaa1c9622019-01-10 16:55:32 -0800710 private static native boolean nativeRemoveBlastulaTableEntry(int blastulaPID);
711
Chris Wailes2be26262019-01-11 16:14:43 -0800712 /**
713 * uid 1000 (Process.SYSTEM_UID) may specify any uid &gt; 1000 in normal
714 * operation. It may also specify any gid and setgroups() list it chooses.
715 * In factory test mode, it may specify any UID.
716 *
717 * @param args non-null; zygote spawner arguments
718 * @param peer non-null; peer credentials
719 * @throws ZygoteSecurityException
720 */
721 protected static void applyUidSecurityPolicy(ZygoteArguments args, Credentials peer)
722 throws ZygoteSecurityException {
723
724 if (peer.getUid() == Process.SYSTEM_UID) {
725 /* In normal operation, SYSTEM_UID can only specify a restricted
726 * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid.
727 */
728 boolean uidRestricted = FactoryTest.getMode() == FactoryTest.FACTORY_TEST_OFF;
729
730 if (uidRestricted && args.mUidSpecified && (args.mUid < Process.SYSTEM_UID)) {
731 throw new ZygoteSecurityException(
732 "System UID may not launch process with UID < "
733 + Process.SYSTEM_UID);
734 }
735 }
736
737 // If not otherwise specified, uid and gid are inherited from peer
738 if (!args.mUidSpecified) {
739 args.mUid = peer.getUid();
740 args.mUidSpecified = true;
741 }
742 if (!args.mGidSpecified) {
743 args.mGid = peer.getGid();
744 args.mGidSpecified = true;
745 }
746 }
747
748 /**
749 * Applies debugger system properties to the zygote arguments.
750 *
751 * If "ro.debuggable" is "1", all apps are debuggable. Otherwise,
752 * the debugger state is specified via the "--enable-jdwp" flag
753 * in the spawn request.
754 *
755 * @param args non-null; zygote spawner args
756 */
757 protected static void applyDebuggerSystemProperty(ZygoteArguments args) {
758 if (RoSystemProperties.DEBUGGABLE) {
759 args.mRuntimeFlags |= Zygote.DEBUG_ENABLE_JDWP;
760 }
761 }
762
763 /**
764 * Applies zygote security policy.
765 * Based on the credentials of the process issuing a zygote command:
766 * <ol>
767 * <li> uid 0 (root) may specify --invoke-with to launch Zygote with a
768 * wrapper command.
769 * <li> Any other uid may not specify any invoke-with argument.
770 * </ul>
771 *
772 * @param args non-null; zygote spawner arguments
773 * @param peer non-null; peer credentials
774 * @throws ZygoteSecurityException
775 */
776 protected static void applyInvokeWithSecurityPolicy(ZygoteArguments args, Credentials peer)
777 throws ZygoteSecurityException {
778 int peerUid = peer.getUid();
779
780 if (args.mInvokeWith != null && peerUid != 0
781 && (args.mRuntimeFlags & Zygote.DEBUG_ENABLE_JDWP) == 0) {
782 throw new ZygoteSecurityException("Peer is permitted to specify an"
783 + "explicit invoke-with wrapper command only for debuggable"
784 + "applications.");
785 }
786 }
787
788 /**
789 * Applies invoke-with system properties to the zygote arguments.
790 *
791 * @param args non-null; zygote args
792 */
793 protected static void applyInvokeWithSystemProperty(ZygoteArguments args) {
794 if (args.mInvokeWith == null && args.mNiceName != null) {
795 String property = "wrap." + args.mNiceName;
796 args.mInvokeWith = SystemProperties.get(property);
797 if (args.mInvokeWith != null && args.mInvokeWith.length() == 0) {
798 args.mInvokeWith = null;
799 }
800 }
801 }
802
803 /**
804 * Reads an argument list from the provided socket
805 * @return Argument list or null if EOF is reached
806 * @throws IOException passed straight through
807 */
808 static String[] readArgumentList(BufferedReader socketReader) throws IOException {
809
810 /**
811 * See android.os.Process.zygoteSendArgsAndGetPid()
812 * Presently the wire format to the zygote process is:
813 * a) a count of arguments (argc, in essence)
814 * b) a number of newline-separated argument strings equal to count
815 *
816 * After the zygote process reads these it will write the pid of
817 * the child or -1 on failure.
818 */
819
820 int argc;
821
822 try {
823 String argc_string = socketReader.readLine();
824
825 if (argc_string == null) {
826 // EOF reached.
827 return null;
828 }
829 argc = Integer.parseInt(argc_string);
830
831 } catch (NumberFormatException ex) {
832 Log.e("Zygote", "Invalid Zygote wire format: non-int at argc");
833 throw new IOException("Invalid wire format");
834 }
835
836 // See bug 1092107: large argc can be used for a DOS attack
837 if (argc > MAX_ZYGOTE_ARGC) {
838 throw new IOException("Max arg count exceeded");
839 }
840
841 String[] args = new String[argc];
842 for (int arg_index = 0; arg_index < argc; arg_index++) {
843 args[arg_index] = socketReader.readLine();
844 if (args[arg_index] == null) {
845 // We got an unexpected EOF.
846 throw new IOException("Truncated request");
847 }
848 }
849
850 return args;
851 }
852
Chris Wailescb0b37f2019-01-11 17:04:41 -0800853 /**
854 * Creates a managed object representing the Blastula pool socket that has
855 * already been initialized and bound by init.
856 *
857 * TODO (chriswailes): Move the name selection logic into this function.
858 *
859 * @throws RuntimeException when open fails
860 */
861 static void createBlastulaSocket(String socketName) {
862 if (BLASTULA_POOL_ENABLED && sBlastulaPoolSocket == null) {
863 sBlastulaPoolSocket = createManagedSocketFromInitSocket(socketName);
864 }
865 }
866
867 /**
868 * Creates a managed LocalServerSocket object using a file descriptor
869 * created by an init.rc script. The init scripts that specify the
870 * sockets name can be found in system/core/rootdir. The socket is bound
871 * to the file system in the /dev/sockets/ directory, and the file
872 * descriptor is shared via the ANDROID_SOCKET_<socketName> environment
873 * variable.
874 */
875 static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
876 int fileDesc;
877 final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
878
879 try {
880 String env = System.getenv(fullSocketName);
881 fileDesc = Integer.parseInt(env);
882 } catch (RuntimeException ex) {
883 throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
884 }
885
886 try {
887 FileDescriptor fd = new FileDescriptor();
888 fd.setInt$(fileDesc);
889 return new LocalServerSocket(fd);
890 } catch (IOException ex) {
891 throw new RuntimeException(
892 "Error building socket from file descriptor: " + fileDesc, ex);
893 }
894 }
doheon1.lee885b7422016-01-20 13:07:27 +0900895
Orion Hodson46724e72018-10-19 13:05:33 +0100896 private static void callPostForkSystemServerHooks() {
897 // SystemServer specific post fork hooks run before child post fork hooks.
Neil Fuller555d8b72019-01-28 18:29:20 +0000898 ZygoteHooks.postForkSystemServer();
Orion Hodson46724e72018-10-19 13:05:33 +0100899 }
900
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100901 private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer,
Robert Sesekd0a190df2018-02-12 18:46:01 -0500902 boolean isZygote, String instructionSet) {
Neil Fuller555d8b72019-01-28 18:29:20 +0000903 ZygoteHooks.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
Narayan Kamath973b4662014-03-31 13:41:26 +0100904 }
905
Narayan Kamathb49996d2017-02-06 20:24:08 +0000906 /**
Hiroshi Yamauchi1e3db872017-03-02 13:39:07 -0800907 * Resets the calling thread priority to the default value (Thread.NORM_PRIORITY
908 * or nice value 0). This updates both the priority value in java.lang.Thread and
909 * the nice value (setpriority).
Narayan Kamathb49996d2017-02-06 20:24:08 +0000910 */
Hiroshi Yamauchi1e3db872017-03-02 13:39:07 -0800911 static void resetNicePriority() {
912 Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
913 }
Narayan Kamath973b4662014-03-31 13:41:26 +0100914
915 /**
916 * Executes "/system/bin/sh -c &lt;command&gt;" using the exec() system call.
917 * This method throws a runtime exception if exec() failed, otherwise, this
918 * method never returns.
919 *
920 * @param command The shell command to execute.
921 */
922 public static void execShell(String command) {
923 String[] args = { "/system/bin/sh", "-c", command };
924 try {
Elliott Hughes860c5912014-04-28 19:19:13 -0700925 Os.execv(args[0], args);
Narayan Kamath973b4662014-03-31 13:41:26 +0100926 } catch (ErrnoException e) {
927 throw new RuntimeException(e);
928 }
929 }
930
931 /**
932 * Appends quotes shell arguments to the specified string builder.
933 * The arguments are quoted using single-quotes, escaped if necessary,
934 * prefixed with a space, and appended to the command.
935 *
936 * @param command A string builder for the shell command being constructed.
937 * @param args An array of argument strings to be quoted and appended to the command.
938 * @see #execShell(String)
939 */
940 public static void appendQuotedShellArgs(StringBuilder command, String[] args) {
941 for (String arg : args) {
942 command.append(" '").append(arg.replace("'", "'\\''")).append("'");
943 }
944 }
Narayan Kamath973b4662014-03-31 13:41:26 +0100945}