blob: fbd0d104a437f3aeec5f2365c24c8a7b8cd52b80 [file] [log] [blame]
Elliott Hughes01158d72011-09-19 19:47:10 -07001/*
2 * Copyright (C) 2008 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
Brian Carlstromcaabb1b2011-10-11 18:09:13 -070017#include <grp.h>
Elliott Hughes01158d72011-09-19 19:47:10 -070018#include <paths.h>
Elliott Hughesada2da92012-01-17 17:58:58 -080019#include <signal.h>
Elliott Hughes01158d72011-09-19 19:47:10 -070020#include <stdlib.h>
Elliott Hughes178cdcc2012-08-16 16:47:31 -070021#include <sys/mount.h>
Brian Carlstromcaabb1b2011-10-11 18:09:13 -070022#include <sys/types.h>
23#include <sys/wait.h>
Elliott Hughes01158d72011-09-19 19:47:10 -070024#include <unistd.h>
25
Elliott Hughesb6636b82012-04-24 10:41:16 -070026#include "cutils/sched_policy.h"
Elliott Hughes4ffd3132011-10-24 12:06:42 -070027#include "debugger.h"
28#include "jni_internal.h"
Elliott Hughes4ffd3132011-10-24 12:06:42 -070029#include "JNIHelp.h"
30#include "ScopedLocalRef.h"
31#include "ScopedPrimitiveArray.h"
32#include "ScopedUtfChars.h"
Brian Carlstromcaabb1b2011-10-11 18:09:13 -070033#include "thread.h"
34
Elliott Hughesb4807ec2012-01-17 18:33:04 -080035#if defined(HAVE_PRCTL)
36#include <sys/prctl.h>
37#endif
38
Elliott Hughesc151f902012-06-21 20:33:21 -070039#if defined(HAVE_SELINUX)
40#include <selinux/android.h>
41#endif
42
Brian Carlstrom154cef62012-05-02 22:34:03 -070043#if defined(__linux__)
44#include <sys/personality.h>
45#endif
46
Elliott Hughes01158d72011-09-19 19:47:10 -070047namespace art {
48
Brian Carlstromcaabb1b2011-10-11 18:09:13 -070049static pid_t gSystemServerPid = 0;
50
Elliott Hughes178cdcc2012-08-16 16:47:31 -070051// Must match values in dalvik.system.Zygote.
52enum MountExternalKind {
53 MOUNT_EXTERNAL_NONE = 0,
54 MOUNT_EXTERNAL_SINGLEUSER = 1,
55 MOUNT_EXTERNAL_MULTIUSER = 2,
56};
57
Elliott Hughes0512f022012-03-15 22:10:52 -070058static void Zygote_nativeExecShell(JNIEnv* env, jclass, jstring javaCommand) {
Elliott Hughes01158d72011-09-19 19:47:10 -070059 ScopedUtfChars command(env, javaCommand);
60 if (command.c_str() == NULL) {
61 return;
62 }
Elliott Hughesc1f143d2011-12-01 17:31:10 -080063 const char* argp[] = {_PATH_BSHELL, "-c", command.c_str(), NULL};
Elliott Hughes01158d72011-09-19 19:47:10 -070064 LOG(INFO) << "Exec: " << argp[0] << ' ' << argp[1] << ' ' << argp[2];
65
Elliott Hughesba8eee12012-01-24 20:25:24 -080066 execv(_PATH_BSHELL, const_cast<char**>(argp));
Elliott Hughes01158d72011-09-19 19:47:10 -070067 exit(127);
68}
69
Brian Carlstromcaabb1b2011-10-11 18:09:13 -070070// This signal handler is for zygote mode, since the zygote must reap its children
Elliott Hughes1bac54f2012-03-16 12:48:31 -070071static void SigChldHandler(int /*signal_number*/) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -070072 pid_t pid;
73 int status;
74
75 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
76 // Log process-death status that we care about. In general it is
77 // not safe to call LOG(...) from a signal handler because of
78 // possible reentrancy. However, we know a priori that the
79 // current implementation of LOG() is safe to call from a SIGCHLD
80 // handler in the zygote process. If the LOG() implementation
81 // changes its locking strategy or its use of syscalls within the
82 // lazy-init critical section, its use here may become unsafe.
83 if (WIFEXITED(status)) {
84 if (WEXITSTATUS(status)) {
85 LOG(INFO) << "Process " << pid << " exited cleanly (" << WEXITSTATUS(status) << ")";
86 } else if (false) {
87 LOG(INFO) << "Process " << pid << " exited cleanly (" << WEXITSTATUS(status) << ")";
88 }
89 } else if (WIFSIGNALED(status)) {
90 if (WTERMSIG(status) != SIGKILL) {
91 LOG(INFO) << "Process " << pid << " terminated by signal (" << WTERMSIG(status) << ")";
92 } else if (false) {
93 LOG(INFO) << "Process " << pid << " terminated by signal (" << WTERMSIG(status) << ")";
94 }
95#ifdef WCOREDUMP
96 if (WCOREDUMP(status)) {
97 LOG(INFO) << "Process " << pid << " dumped core";
98 }
99#endif /* ifdef WCOREDUMP */
100 }
101
102 // If the just-crashed process is the system_server, bring down zygote
103 // so that it is restarted by init and system server will be restarted
104 // from there.
105 if (pid == gSystemServerPid) {
Brian Carlstrom6a4be3a2011-10-20 16:34:03 -0700106 LOG(ERROR) << "Exit zygote because system server (" << pid << ") has terminated";
107 kill(getpid(), SIGKILL);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700108 }
109 }
110
111 if (pid < 0) {
112 PLOG(WARNING) << "Zygote SIGCHLD error in waitpid";
113 }
114}
115
Elliott Hughes0512f022012-03-15 22:10:52 -0700116// Configures the SIGCHLD handler for the zygote process. This is configured
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700117// very late, because earlier in the runtime we may fork() and exec()
118// other processes, and we want to waitpid() for those rather than
119// have them be harvested immediately.
120//
121// This ends up being called repeatedly before each fork(), but there's
122// no real harm in that.
Elliott Hughes0512f022012-03-15 22:10:52 -0700123static void SetSigChldHandler() {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700124 struct sigaction sa;
125 memset(&sa, 0, sizeof(sa));
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700126 sa.sa_handler = SigChldHandler;
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700127
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700128 int err = sigaction(SIGCHLD, &sa, NULL);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700129 if (err < 0) {
130 PLOG(WARNING) << "Error setting SIGCHLD handler";
131 }
132}
133
Elliott Hughes0512f022012-03-15 22:10:52 -0700134// Sets the SIGCHLD handler back to default behavior in zygote children.
135static void UnsetSigChldHandler() {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700136 struct sigaction sa;
137 memset(&sa, 0, sizeof(sa));
138 sa.sa_handler = SIG_DFL;
139
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700140 int err = sigaction(SIGCHLD, &sa, NULL);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700141 if (err < 0) {
142 PLOG(WARNING) << "Error unsetting SIGCHLD handler";
143 }
144}
145
146// Calls POSIX setgroups() using the int[] object as an argument.
147// A NULL argument is tolerated.
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700148static void SetGids(JNIEnv* env, jintArray javaGids) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700149 if (javaGids == NULL) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700150 return;
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700151 }
152
153 COMPILE_ASSERT(sizeof(gid_t) == sizeof(jint), sizeof_gid_and_jint_are_differerent);
154 ScopedIntArrayRO gids(env, javaGids);
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700155 CHECK(gids.get() != NULL);
156 int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
157 if (rc == -1) {
158 PLOG(FATAL) << "setgroups failed";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700159 }
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700160}
161
162// Sets the resource limits via setrlimit(2) for the values in the
163// two-dimensional array of integers that's passed in. The second dimension
164// contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
165// treated as an empty array.
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700166static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700167 if (javaRlimits == NULL) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700168 return;
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700169 }
170
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700171 rlimit rlim;
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700172 memset(&rlim, 0, sizeof(rlim));
173
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700174 for (int i = 0; i < env->GetArrayLength(javaRlimits); ++i) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700175 ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
176 ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
177 if (javaRlimit.size() != 3) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700178 LOG(FATAL) << "rlimits array must have a second dimension of size 3";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700179 }
180
181 rlim.rlim_cur = javaRlimit[1];
182 rlim.rlim_max = javaRlimit[2];
183
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700184 int rc = setrlimit(javaRlimit[0], &rlim);
185 if (rc == -1) {
186 PLOG(FATAL) << "setrlimit(" << javaRlimit[0] << ", "
187 << "{" << rlim.rlim_cur << ", " << rlim.rlim_max << "}) failed";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700188 }
189 }
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700190}
191
Elliott Hughes76e36942012-03-16 13:44:56 -0700192#if defined(HAVE_ANDROID_OS)
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700193
194// The debug malloc library needs to know whether it's the zygote or a child.
195extern "C" int gMallocLeakZygoteChild;
196
197static void EnableDebugger() {
198 // To let a non-privileged gdbserver attach to this
199 // process, we must set our dumpable flag.
200 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
201 PLOG(ERROR) << "prctl(PR_SET_DUMPABLE) failed for pid " << getpid();
202 }
203 // We don't want core dumps, though, so set the core dump size to 0.
204 rlimit rl;
205 rl.rlim_cur = 0;
206 rl.rlim_max = RLIM_INFINITY;
207 if (setrlimit(RLIMIT_CORE, &rl) == -1) {
208 PLOG(ERROR) << "setrlimit(RLIMIT_CORE) failed for pid " << getpid();
209 }
210}
211
212static void EnableKeepCapabilities() {
213 int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
214 if (rc == -1) {
215 PLOG(FATAL) << "prctl(PR_SET_KEEPCAPS) failed";
216 }
217}
218
Elliott Hughes76e36942012-03-16 13:44:56 -0700219static void SetCapabilities(int64_t permitted, int64_t effective) {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700220 __user_cap_header_struct capheader;
221 __user_cap_data_struct capdata;
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700222
223 memset(&capheader, 0, sizeof(capheader));
224 memset(&capdata, 0, sizeof(capdata));
225
226 capheader.version = _LINUX_CAPABILITY_VERSION;
227 capheader.pid = 0;
228
229 capdata.effective = effective;
230 capdata.permitted = permitted;
231
232 if (capset(&capheader, &capdata) != 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800233 PLOG(FATAL) << "capset(" << permitted << ", " << effective << ") failed";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700234 }
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700235}
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700236
237static void SetSchedulerPolicy() {
238 errno = -set_sched_policy(0, SP_DEFAULT);
239 if (errno != 0) {
240 PLOG(FATAL) << "set_sched_policy(0, SP_DEFAULT) failed";
241 }
242}
243
Elliott Hughes76e36942012-03-16 13:44:56 -0700244#else
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700245
246static int gMallocLeakZygoteChild = 0;
247
248static void EnableDebugger() {}
249static void EnableKeepCapabilities() {}
Elliott Hughes76e36942012-03-16 13:44:56 -0700250static void SetCapabilities(int64_t, int64_t) {}
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700251static void SetSchedulerPolicy() {}
252
Elliott Hughes76e36942012-03-16 13:44:56 -0700253#endif
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700254
Elliott Hughes0512f022012-03-15 22:10:52 -0700255static void EnableDebugFeatures(uint32_t debug_flags) {
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700256 // Must match values in dalvik.system.Zygote.
257 enum {
258 DEBUG_ENABLE_DEBUGGER = 1,
259 DEBUG_ENABLE_CHECKJNI = 1 << 1,
260 DEBUG_ENABLE_ASSERT = 1 << 2,
261 DEBUG_ENABLE_SAFEMODE = 1 << 3,
262 DEBUG_ENABLE_JNI_LOGGING = 1 << 4,
263 };
264
265 if ((debug_flags & DEBUG_ENABLE_CHECKJNI) != 0) {
266 Runtime* runtime = Runtime::Current();
267 JavaVMExt* vm = runtime->GetJavaVM();
268 if (!vm->check_jni) {
269 LOG(DEBUG) << "Late-enabling -Xcheck:jni";
Elliott Hughes88c5c352012-03-15 18:49:48 -0700270 vm->SetCheckJniEnabled(true);
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700271 // There's only one thread running at this point, so only one JNIEnv to fix up.
Elliott Hughes88c5c352012-03-15 18:49:48 -0700272 Thread::Current()->GetJniEnv()->SetCheckJniEnabled(true);
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700273 } else {
274 LOG(DEBUG) << "Not late-enabling -Xcheck:jni (already on)";
275 }
276 debug_flags &= ~DEBUG_ENABLE_CHECKJNI;
277 }
278
279 if ((debug_flags & DEBUG_ENABLE_JNI_LOGGING) != 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800280 gLogVerbosity.third_party_jni = true;
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700281 debug_flags &= ~DEBUG_ENABLE_JNI_LOGGING;
282 }
283
284 Dbg::SetJdwpAllowed((debug_flags & DEBUG_ENABLE_DEBUGGER) != 0);
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700285 if ((debug_flags & DEBUG_ENABLE_DEBUGGER) != 0) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700286 EnableDebugger();
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700287 }
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700288 debug_flags &= ~DEBUG_ENABLE_DEBUGGER;
289
290 // These two are for backwards compatibility with Dalvik.
291 debug_flags &= ~DEBUG_ENABLE_ASSERT;
292 debug_flags &= ~DEBUG_ENABLE_SAFEMODE;
293
294 if (debug_flags != 0) {
295 LOG(ERROR) << StringPrintf("Unknown bits set in debug_flags: %#x", debug_flags);
296 }
297}
298
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700299// Create private mount space for this process and mount SD card
300// into it, based on the active user.
301static void MountExternalStorage(uid_t uid, jint mount_external) {
302 if (mount_external == MOUNT_EXTERNAL_NONE) {
303 return;
304 }
305
306#if 0
307 userid_t user_id = multiuser_getUserId(uid);
308
309 // Create private mount namespace for our process.
310 if (unshare(CLONE_NEWNS) == -1) {
311 PLOG(FATAL) << "unshare(CLONE_NEWNS) failed";
312 }
313
314 // Mark rootfs as being a slave in our process so that changes
315 // from parent namespace flow into our process.
316 if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1) {
317 PLOG(FATAL) << "mount(\"rootfs\", \"/\", NULL, (MS_SLAVE | MS_REC), NULL) failed";
318 }
319
320 // Create bind mount from specific path.
321 if (mount_external == MOUNT_EXTERNAL_SINGLEUSER) {
322 if (mount(EXTERNAL_STORAGE_SYSTEM, EXTERNAL_STORAGE_APP, "none", MS_BIND, NULL) == -1) {
323 PLOG(FATAL) << "mount(\"" << EXTERNAL_STORAGE_SYSTEM << "\", \"" << EXTERNAL_STORAGE_APP << "\", \"none\", MS_BIND, NULL) failed";
324 }
325 } else if (mount_external == MOUNT_EXTERNAL_MULTIUSER) {
326 // Assume path has already been created by installd.
327 std::string source_path(StringPrintf("%s/%d", EXTERNAL_STORAGE_SYSTEM, user_id));
328 if (mount(source_path.c_str(), EXTERNAL_STORAGE_APP, "none", MS_BIND, NULL) == -1) {
329 PLOG(FATAL) << "mount(\"" << source_path.c_str() << "\", \"" << EXTERNAL_STORAGE_APP << "\", \"none\", MS_BIND, NULL) failed";
330 }
331 } else {
332 LOG(FATAL) << "Mount mode unsupported: " << mount_external;
333 }
334#else
335 UNUSED(uid);
336 UNIMPLEMENTED(FATAL);
337#endif
338}
339
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700340// Utility routine to fork zygote and specialize the child process.
Elliott Hughes0512f022012-03-15 22:10:52 -0700341static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
342 jint debug_flags, jobjectArray javaRlimits,
Elliott Hughesc151f902012-06-21 20:33:21 -0700343 jlong permittedCapabilities, jlong effectiveCapabilities,
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700344 jint mount_external,
Elliott Hughesc151f902012-06-21 20:33:21 -0700345 jstring java_se_info, jstring java_se_name, bool is_system_server) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700346 Runtime* runtime = Runtime::Current();
347 CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote";
Mathieu Chartiercc236d72012-07-20 10:29:05 -0700348 if (!runtime->PreZygoteFork()) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700349 LOG(FATAL) << "pre-fork heap failed";
350 }
351
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700352 SetSigChldHandler();
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700353
354 // Grab thread before fork potentially makes Thread::pthread_key_self_ unusable.
355 Thread* self = Thread::Current();
356
357 // dvmDumpLoaderStats("zygote"); // TODO: ?
358 pid_t pid = fork();
359
360 if (pid == 0) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700361 // The child process.
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700362 gMallocLeakZygoteChild = 1;
363
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700364 // Keep capabilities across UID change, unless we're staying root.
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700365 if (uid != 0) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700366 EnableKeepCapabilities();
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700367 }
368
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700369 MountExternalStorage(uid, mount_external);
370
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700371 SetGids(env, javaGids);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700372
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700373 SetRLimits(env, javaRlimits);
374
375 int rc = setgid(gid);
376 if (rc == -1) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800377 PLOG(FATAL) << "setgid(" << gid << ") failed";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700378 }
379
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700380 rc = setuid(uid);
381 if (rc == -1) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800382 PLOG(FATAL) << "setuid(" << uid << ") failed";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700383 }
384
Brian Carlstrom154cef62012-05-02 22:34:03 -0700385#if defined(__linux__)
Elliott Hughes51e53862012-05-02 17:17:28 -0700386 // Work around ARM kernel ASLR lossage (http://b/5817320).
387 int old_personality = personality(0xffffffff);
388 int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
389 if (new_personality == -1) {
390 PLOG(WARNING) << "personality(" << new_personality << ") failed";
391 }
Brian Carlstrom154cef62012-05-02 22:34:03 -0700392#endif
Elliott Hughes51e53862012-05-02 17:17:28 -0700393
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800394 SetCapabilities(permittedCapabilities, effectiveCapabilities);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700395
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700396 SetSchedulerPolicy();
Elliott Hughesb6636b82012-04-24 10:41:16 -0700397
Elliott Hughesc151f902012-06-21 20:33:21 -0700398#if defined(HAVE_SELINUX) && defined(HAVE_ANDROID_OS)
399 {
400 ScopedUtfChars se_info(env, java_se_info);
401 CHECK(se_info != NULL);
402 ScopedUtfChars se_name(env, java_se_name);
403 CHECK(se_name != NULL);
404 rc = selinux_android_setcontext(uid, is_system_server, se_info, se_name);
405 if (rc == -1) {
406 PLOG(FATAL) << "selinux_android_setcontext(" << uid << ", "
407 << (is_system_server ? "true" : "false") << ", "
408 << "\"" << se_info << "\", \"" << se_name << "\") failed";
409 }
410 }
411#else
412 UNUSED(is_system_server);
413 UNUSED(java_se_info);
414 UNUSED(java_se_name);
415#endif
416
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700417 // Our system thread ID, etc, has changed so reset Thread state.
418 self->InitAfterFork();
419
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700420 EnableDebugFeatures(debug_flags);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700421
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700422 UnsetSigChldHandler();
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700423 runtime->DidForkFromZygote();
424 } else if (pid > 0) {
425 // the parent process
426 }
427 return pid;
428}
429
Elliott Hughes0512f022012-03-15 22:10:52 -0700430static jint Zygote_nativeForkAndSpecialize(JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700431 jint debug_flags, jobjectArray rlimits, jint mount_external,
Elliott Hughesc151f902012-06-21 20:33:21 -0700432 jstring se_info, jstring se_name) {
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700433 return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, 0, 0, mount_external, se_info, se_name, false);
Brian Carlstroma9f19782011-10-13 00:14:47 -0700434}
435
Elliott Hughes0512f022012-03-15 22:10:52 -0700436static jint Zygote_nativeForkSystemServer(JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
437 jint debug_flags, jobjectArray rlimits,
438 jlong permittedCapabilities, jlong effectiveCapabilities) {
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700439 pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
440 debug_flags, rlimits,
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700441 permittedCapabilities, effectiveCapabilities,
442 MOUNT_EXTERNAL_NONE, NULL, NULL, true);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700443 if (pid > 0) {
444 // The zygote process checks whether the child process has died or not.
445 LOG(INFO) << "System server process " << pid << " has been created";
446 gSystemServerPid = pid;
447 // There is a slight window that the system server process has crashed
448 // but it went unnoticed because we haven't published its pid yet. So
449 // we recheck here just to make sure that all is well.
450 int status;
451 if (waitpid(pid, &status, WNOHANG) == pid) {
452 LOG(FATAL) << "System server process " << pid << " has died. Restarting Zygote!";
453 }
454 }
455 return pid;
456}
457
Elliott Hughes01158d72011-09-19 19:47:10 -0700458static JNINativeMethod gMethods[] = {
459 NATIVE_METHOD(Zygote, nativeExecShell, "(Ljava/lang/String;)V"),
460 //NATIVE_METHOD(Zygote, nativeFork, "()I"),
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700461 NATIVE_METHOD(Zygote, nativeForkAndSpecialize, "(II[II[[IILjava/lang/String;Ljava/lang/String;)I"),
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700462 NATIVE_METHOD(Zygote, nativeForkSystemServer, "(II[II[[IJJ)I"),
Elliott Hughes01158d72011-09-19 19:47:10 -0700463};
464
Elliott Hughes01158d72011-09-19 19:47:10 -0700465void register_dalvik_system_Zygote(JNIEnv* env) {
Elliott Hughes7756d542012-05-24 21:56:51 -0700466 REGISTER_NATIVE_METHODS("dalvik/system/Zygote");
Elliott Hughes01158d72011-09-19 19:47:10 -0700467}
468
469} // namespace art