blob: 1dd6c590353da8608145d8e058577b60b74edc5d [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#include <selinux/android.h>
Elliott Hughesc151f902012-06-21 20:33:21 -070040
Brian Carlstrom154cef62012-05-02 22:34:03 -070041#if defined(__linux__)
42#include <sys/personality.h>
Nick Kralevichb7882782012-09-27 12:29:02 -070043#include <sys/utsname.h>
Brian Carlstrom154cef62012-05-02 22:34:03 -070044#endif
45
Elliott Hughes01158d72011-09-19 19:47:10 -070046namespace art {
47
Brian Carlstromcaabb1b2011-10-11 18:09:13 -070048static pid_t gSystemServerPid = 0;
49
Elliott Hughes178cdcc2012-08-16 16:47:31 -070050// Must match values in dalvik.system.Zygote.
51enum MountExternalKind {
52 MOUNT_EXTERNAL_NONE = 0,
53 MOUNT_EXTERNAL_SINGLEUSER = 1,
54 MOUNT_EXTERNAL_MULTIUSER = 2,
55};
56
Elliott Hughes0512f022012-03-15 22:10:52 -070057static void Zygote_nativeExecShell(JNIEnv* env, jclass, jstring javaCommand) {
Elliott Hughes01158d72011-09-19 19:47:10 -070058 ScopedUtfChars command(env, javaCommand);
59 if (command.c_str() == NULL) {
60 return;
61 }
Elliott Hughesc1f143d2011-12-01 17:31:10 -080062 const char* argp[] = {_PATH_BSHELL, "-c", command.c_str(), NULL};
Elliott Hughes01158d72011-09-19 19:47:10 -070063 LOG(INFO) << "Exec: " << argp[0] << ' ' << argp[1] << ' ' << argp[2];
64
Elliott Hughesba8eee12012-01-24 20:25:24 -080065 execv(_PATH_BSHELL, const_cast<char**>(argp));
Elliott Hughes01158d72011-09-19 19:47:10 -070066 exit(127);
67}
68
Brian Carlstromcaabb1b2011-10-11 18:09:13 -070069// This signal handler is for zygote mode, since the zygote must reap its children
Elliott Hughes1bac54f2012-03-16 12:48:31 -070070static void SigChldHandler(int /*signal_number*/) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -070071 pid_t pid;
72 int status;
73
74 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
75 // Log process-death status that we care about. In general it is
76 // not safe to call LOG(...) from a signal handler because of
77 // possible reentrancy. However, we know a priori that the
78 // current implementation of LOG() is safe to call from a SIGCHLD
79 // handler in the zygote process. If the LOG() implementation
80 // changes its locking strategy or its use of syscalls within the
81 // lazy-init critical section, its use here may become unsafe.
82 if (WIFEXITED(status)) {
83 if (WEXITSTATUS(status)) {
84 LOG(INFO) << "Process " << pid << " exited cleanly (" << WEXITSTATUS(status) << ")";
85 } else if (false) {
86 LOG(INFO) << "Process " << pid << " exited cleanly (" << WEXITSTATUS(status) << ")";
87 }
88 } else if (WIFSIGNALED(status)) {
89 if (WTERMSIG(status) != SIGKILL) {
90 LOG(INFO) << "Process " << pid << " terminated by signal (" << WTERMSIG(status) << ")";
91 } else if (false) {
92 LOG(INFO) << "Process " << pid << " terminated by signal (" << WTERMSIG(status) << ")";
93 }
94#ifdef WCOREDUMP
95 if (WCOREDUMP(status)) {
96 LOG(INFO) << "Process " << pid << " dumped core";
97 }
98#endif /* ifdef WCOREDUMP */
99 }
100
101 // If the just-crashed process is the system_server, bring down zygote
102 // so that it is restarted by init and system server will be restarted
103 // from there.
104 if (pid == gSystemServerPid) {
Brian Carlstrom6a4be3a2011-10-20 16:34:03 -0700105 LOG(ERROR) << "Exit zygote because system server (" << pid << ") has terminated";
106 kill(getpid(), SIGKILL);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700107 }
108 }
109
110 if (pid < 0) {
111 PLOG(WARNING) << "Zygote SIGCHLD error in waitpid";
112 }
113}
114
Elliott Hughes0512f022012-03-15 22:10:52 -0700115// Configures the SIGCHLD handler for the zygote process. This is configured
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700116// very late, because earlier in the runtime we may fork() and exec()
117// other processes, and we want to waitpid() for those rather than
118// have them be harvested immediately.
119//
120// This ends up being called repeatedly before each fork(), but there's
121// no real harm in that.
Elliott Hughes0512f022012-03-15 22:10:52 -0700122static void SetSigChldHandler() {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700123 struct sigaction sa;
124 memset(&sa, 0, sizeof(sa));
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700125 sa.sa_handler = SigChldHandler;
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700126
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700127 int err = sigaction(SIGCHLD, &sa, NULL);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700128 if (err < 0) {
129 PLOG(WARNING) << "Error setting SIGCHLD handler";
130 }
131}
132
Elliott Hughes0512f022012-03-15 22:10:52 -0700133// Sets the SIGCHLD handler back to default behavior in zygote children.
134static void UnsetSigChldHandler() {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700135 struct sigaction sa;
136 memset(&sa, 0, sizeof(sa));
137 sa.sa_handler = SIG_DFL;
138
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700139 int err = sigaction(SIGCHLD, &sa, NULL);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700140 if (err < 0) {
141 PLOG(WARNING) << "Error unsetting SIGCHLD handler";
142 }
143}
144
145// Calls POSIX setgroups() using the int[] object as an argument.
146// A NULL argument is tolerated.
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700147static void SetGids(JNIEnv* env, jintArray javaGids) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700148 if (javaGids == NULL) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700149 return;
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700150 }
151
152 COMPILE_ASSERT(sizeof(gid_t) == sizeof(jint), sizeof_gid_and_jint_are_differerent);
153 ScopedIntArrayRO gids(env, javaGids);
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700154 CHECK(gids.get() != NULL);
155 int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
156 if (rc == -1) {
157 PLOG(FATAL) << "setgroups failed";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700158 }
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700159}
160
161// Sets the resource limits via setrlimit(2) for the values in the
162// two-dimensional array of integers that's passed in. The second dimension
163// contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
164// treated as an empty array.
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700165static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700166 if (javaRlimits == NULL) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700167 return;
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700168 }
169
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700170 rlimit rlim;
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700171 memset(&rlim, 0, sizeof(rlim));
172
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700173 for (int i = 0; i < env->GetArrayLength(javaRlimits); ++i) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700174 ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
175 ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
176 if (javaRlimit.size() != 3) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700177 LOG(FATAL) << "rlimits array must have a second dimension of size 3";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700178 }
179
180 rlim.rlim_cur = javaRlimit[1];
181 rlim.rlim_max = javaRlimit[2];
182
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700183 int rc = setrlimit(javaRlimit[0], &rlim);
184 if (rc == -1) {
185 PLOG(FATAL) << "setrlimit(" << javaRlimit[0] << ", "
186 << "{" << rlim.rlim_cur << ", " << rlim.rlim_max << "}) failed";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700187 }
188 }
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700189}
190
Elliott Hughes76e36942012-03-16 13:44:56 -0700191#if defined(HAVE_ANDROID_OS)
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700192
193// The debug malloc library needs to know whether it's the zygote or a child.
194extern "C" int gMallocLeakZygoteChild;
195
196static void EnableDebugger() {
197 // To let a non-privileged gdbserver attach to this
198 // process, we must set our dumpable flag.
199 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
200 PLOG(ERROR) << "prctl(PR_SET_DUMPABLE) failed for pid " << getpid();
201 }
202 // We don't want core dumps, though, so set the core dump size to 0.
203 rlimit rl;
204 rl.rlim_cur = 0;
205 rl.rlim_max = RLIM_INFINITY;
206 if (setrlimit(RLIMIT_CORE, &rl) == -1) {
207 PLOG(ERROR) << "setrlimit(RLIMIT_CORE) failed for pid " << getpid();
208 }
209}
210
211static void EnableKeepCapabilities() {
212 int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
213 if (rc == -1) {
214 PLOG(FATAL) << "prctl(PR_SET_KEEPCAPS) failed";
215 }
216}
217
Elliott Hughes76e36942012-03-16 13:44:56 -0700218static void SetCapabilities(int64_t permitted, int64_t effective) {
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700219 __user_cap_header_struct capheader;
220 __user_cap_data_struct capdata;
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700221
222 memset(&capheader, 0, sizeof(capheader));
223 memset(&capdata, 0, sizeof(capdata));
224
225 capheader.version = _LINUX_CAPABILITY_VERSION;
226 capheader.pid = 0;
227
228 capdata.effective = effective;
229 capdata.permitted = permitted;
230
231 if (capset(&capheader, &capdata) != 0) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800232 PLOG(FATAL) << "capset(" << permitted << ", " << effective << ") failed";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700233 }
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700234}
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700235
236static void SetSchedulerPolicy() {
237 errno = -set_sched_policy(0, SP_DEFAULT);
238 if (errno != 0) {
239 PLOG(FATAL) << "set_sched_policy(0, SP_DEFAULT) failed";
240 }
241}
242
Elliott Hughes76e36942012-03-16 13:44:56 -0700243#else
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700244
245static int gMallocLeakZygoteChild = 0;
246
247static void EnableDebugger() {}
248static void EnableKeepCapabilities() {}
Elliott Hughes76e36942012-03-16 13:44:56 -0700249static void SetCapabilities(int64_t, int64_t) {}
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700250static void SetSchedulerPolicy() {}
251
Elliott Hughes76e36942012-03-16 13:44:56 -0700252#endif
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700253
Elliott Hughes0512f022012-03-15 22:10:52 -0700254static void EnableDebugFeatures(uint32_t debug_flags) {
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700255 // Must match values in dalvik.system.Zygote.
256 enum {
257 DEBUG_ENABLE_DEBUGGER = 1,
258 DEBUG_ENABLE_CHECKJNI = 1 << 1,
259 DEBUG_ENABLE_ASSERT = 1 << 2,
260 DEBUG_ENABLE_SAFEMODE = 1 << 3,
261 DEBUG_ENABLE_JNI_LOGGING = 1 << 4,
262 };
263
264 if ((debug_flags & DEBUG_ENABLE_CHECKJNI) != 0) {
265 Runtime* runtime = Runtime::Current();
266 JavaVMExt* vm = runtime->GetJavaVM();
267 if (!vm->check_jni) {
268 LOG(DEBUG) << "Late-enabling -Xcheck:jni";
Elliott Hughes88c5c352012-03-15 18:49:48 -0700269 vm->SetCheckJniEnabled(true);
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700270 // There's only one thread running at this point, so only one JNIEnv to fix up.
Elliott Hughes88c5c352012-03-15 18:49:48 -0700271 Thread::Current()->GetJniEnv()->SetCheckJniEnabled(true);
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700272 } else {
273 LOG(DEBUG) << "Not late-enabling -Xcheck:jni (already on)";
274 }
275 debug_flags &= ~DEBUG_ENABLE_CHECKJNI;
276 }
277
278 if ((debug_flags & DEBUG_ENABLE_JNI_LOGGING) != 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800279 gLogVerbosity.third_party_jni = true;
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700280 debug_flags &= ~DEBUG_ENABLE_JNI_LOGGING;
281 }
282
283 Dbg::SetJdwpAllowed((debug_flags & DEBUG_ENABLE_DEBUGGER) != 0);
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700284 if ((debug_flags & DEBUG_ENABLE_DEBUGGER) != 0) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700285 EnableDebugger();
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700286 }
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700287 debug_flags &= ~DEBUG_ENABLE_DEBUGGER;
288
289 // These two are for backwards compatibility with Dalvik.
290 debug_flags &= ~DEBUG_ENABLE_ASSERT;
291 debug_flags &= ~DEBUG_ENABLE_SAFEMODE;
292
293 if (debug_flags != 0) {
294 LOG(ERROR) << StringPrintf("Unknown bits set in debug_flags: %#x", debug_flags);
295 }
296}
297
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700298// Create private mount space for this process and mount SD card
299// into it, based on the active user.
300static void MountExternalStorage(uid_t uid, jint mount_external) {
301 if (mount_external == MOUNT_EXTERNAL_NONE) {
302 return;
303 }
304
305#if 0
306 userid_t user_id = multiuser_getUserId(uid);
307
308 // Create private mount namespace for our process.
309 if (unshare(CLONE_NEWNS) == -1) {
310 PLOG(FATAL) << "unshare(CLONE_NEWNS) failed";
311 }
312
313 // Mark rootfs as being a slave in our process so that changes
314 // from parent namespace flow into our process.
315 if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1) {
316 PLOG(FATAL) << "mount(\"rootfs\", \"/\", NULL, (MS_SLAVE | MS_REC), NULL) failed";
317 }
318
319 // Create bind mount from specific path.
320 if (mount_external == MOUNT_EXTERNAL_SINGLEUSER) {
321 if (mount(EXTERNAL_STORAGE_SYSTEM, EXTERNAL_STORAGE_APP, "none", MS_BIND, NULL) == -1) {
322 PLOG(FATAL) << "mount(\"" << EXTERNAL_STORAGE_SYSTEM << "\", \"" << EXTERNAL_STORAGE_APP << "\", \"none\", MS_BIND, NULL) failed";
323 }
324 } else if (mount_external == MOUNT_EXTERNAL_MULTIUSER) {
325 // Assume path has already been created by installd.
326 std::string source_path(StringPrintf("%s/%d", EXTERNAL_STORAGE_SYSTEM, user_id));
327 if (mount(source_path.c_str(), EXTERNAL_STORAGE_APP, "none", MS_BIND, NULL) == -1) {
328 PLOG(FATAL) << "mount(\"" << source_path.c_str() << "\", \"" << EXTERNAL_STORAGE_APP << "\", \"none\", MS_BIND, NULL) failed";
329 }
330 } else {
331 LOG(FATAL) << "Mount mode unsupported: " << mount_external;
332 }
333#else
334 UNUSED(uid);
335 UNIMPLEMENTED(FATAL);
336#endif
337}
338
Nick Kralevichb7882782012-09-27 12:29:02 -0700339#if defined(__linux__)
340static bool NeedsNoRandomizeWorkaround() {
341 int major;
342 int minor;
343 struct utsname uts;
344 if (uname(&uts) == -1) {
345 return false;
346 }
347
348 if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
349 return false;
350 }
351
352 // Kernels before 3.4.* need the workaround.
353 return (major < 3) || ((major == 3) && (minor < 4));
354}
355#endif
356
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700357// Utility routine to fork zygote and specialize the child process.
Elliott Hughes0512f022012-03-15 22:10:52 -0700358static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
359 jint debug_flags, jobjectArray javaRlimits,
Elliott Hughesc151f902012-06-21 20:33:21 -0700360 jlong permittedCapabilities, jlong effectiveCapabilities,
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700361 jint mount_external,
Elliott Hughesc151f902012-06-21 20:33:21 -0700362 jstring java_se_info, jstring java_se_name, bool is_system_server) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700363 Runtime* runtime = Runtime::Current();
364 CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote";
Mathieu Chartiercc236d72012-07-20 10:29:05 -0700365 if (!runtime->PreZygoteFork()) {
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700366 LOG(FATAL) << "pre-fork heap failed";
367 }
368
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700369 SetSigChldHandler();
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700370
371 // Grab thread before fork potentially makes Thread::pthread_key_self_ unusable.
372 Thread* self = Thread::Current();
373
374 // dvmDumpLoaderStats("zygote"); // TODO: ?
375 pid_t pid = fork();
376
377 if (pid == 0) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700378 // The child process.
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700379 gMallocLeakZygoteChild = 1;
380
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700381 // Keep capabilities across UID change, unless we're staying root.
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700382 if (uid != 0) {
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700383 EnableKeepCapabilities();
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700384 }
385
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700386 MountExternalStorage(uid, mount_external);
387
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700388 SetGids(env, javaGids);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700389
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700390 SetRLimits(env, javaRlimits);
391
392 int rc = setgid(gid);
393 if (rc == -1) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800394 PLOG(FATAL) << "setgid(" << gid << ") failed";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700395 }
396
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700397 rc = setuid(uid);
398 if (rc == -1) {
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800399 PLOG(FATAL) << "setuid(" << uid << ") failed";
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700400 }
401
Brian Carlstrom154cef62012-05-02 22:34:03 -0700402#if defined(__linux__)
Nick Kralevichb7882782012-09-27 12:29:02 -0700403 if (NeedsNoRandomizeWorkaround()) {
404 // Work around ARM kernel ASLR lossage (http://b/5817320).
405 int old_personality = personality(0xffffffff);
406 int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
407 if (new_personality == -1) {
408 PLOG(WARNING) << "personality(" << new_personality << ") failed";
409 }
Elliott Hughes51e53862012-05-02 17:17:28 -0700410 }
Brian Carlstrom154cef62012-05-02 22:34:03 -0700411#endif
Elliott Hughes51e53862012-05-02 17:17:28 -0700412
Elliott Hughes3d30d9b2011-12-07 17:35:48 -0800413 SetCapabilities(permittedCapabilities, effectiveCapabilities);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700414
Elliott Hughes2abeb9b2012-05-11 23:42:02 -0700415 SetSchedulerPolicy();
Elliott Hughesb6636b82012-04-24 10:41:16 -0700416
Kenny Rootdc1cd102012-10-17 10:35:32 -0700417#if defined(HAVE_ANDROID_OS)
Elliott Hughesc151f902012-06-21 20:33:21 -0700418 {
Brian Carlstrom1a0b4752012-10-17 16:23:18 -0700419 const char* se_info_c_str = NULL;
420 UniquePtr<ScopedUtfChars> se_info;
421 if (java_se_info != NULL) {
422 se_info.reset(new ScopedUtfChars(env, java_se_info));
423 se_info_c_str = se_info->c_str();
424 CHECK(se_info_c_str != NULL);
425 }
426 const char* se_name_c_str = NULL;
427 UniquePtr<ScopedUtfChars> se_name;
428 if (java_se_name != NULL) {
429 se_name.reset(new ScopedUtfChars(env, java_se_name));
430 se_name_c_str = se_name->c_str();
431 CHECK(se_name_c_str != NULL);
432 }
433 rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
Elliott Hughesc151f902012-06-21 20:33:21 -0700434 if (rc == -1) {
435 PLOG(FATAL) << "selinux_android_setcontext(" << uid << ", "
436 << (is_system_server ? "true" : "false") << ", "
Brian Carlstrom1a0b4752012-10-17 16:23:18 -0700437 << "\"" << se_info_c_str << "\", \"" << se_name_c_str << "\") failed";
Elliott Hughesc151f902012-06-21 20:33:21 -0700438 }
439 }
440#else
441 UNUSED(is_system_server);
442 UNUSED(java_se_info);
443 UNUSED(java_se_name);
444#endif
445
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700446 // Our system thread ID, etc, has changed so reset Thread state.
447 self->InitAfterFork();
448
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700449 EnableDebugFeatures(debug_flags);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700450
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700451 UnsetSigChldHandler();
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700452 runtime->DidForkFromZygote();
453 } else if (pid > 0) {
454 // the parent process
455 }
456 return pid;
457}
458
Elliott Hughes0512f022012-03-15 22:10:52 -0700459static jint Zygote_nativeForkAndSpecialize(JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700460 jint debug_flags, jobjectArray rlimits, jint mount_external,
Elliott Hughesc151f902012-06-21 20:33:21 -0700461 jstring se_info, jstring se_name) {
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700462 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 -0700463}
464
Elliott Hughes0512f022012-03-15 22:10:52 -0700465static jint Zygote_nativeForkSystemServer(JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
466 jint debug_flags, jobjectArray rlimits,
467 jlong permittedCapabilities, jlong effectiveCapabilities) {
Elliott Hughes4ffd3132011-10-24 12:06:42 -0700468 pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
469 debug_flags, rlimits,
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700470 permittedCapabilities, effectiveCapabilities,
471 MOUNT_EXTERNAL_NONE, NULL, NULL, true);
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700472 if (pid > 0) {
473 // The zygote process checks whether the child process has died or not.
474 LOG(INFO) << "System server process " << pid << " has been created";
475 gSystemServerPid = pid;
476 // There is a slight window that the system server process has crashed
477 // but it went unnoticed because we haven't published its pid yet. So
478 // we recheck here just to make sure that all is well.
479 int status;
480 if (waitpid(pid, &status, WNOHANG) == pid) {
481 LOG(FATAL) << "System server process " << pid << " has died. Restarting Zygote!";
482 }
483 }
484 return pid;
485}
486
Elliott Hughes01158d72011-09-19 19:47:10 -0700487static JNINativeMethod gMethods[] = {
488 NATIVE_METHOD(Zygote, nativeExecShell, "(Ljava/lang/String;)V"),
489 //NATIVE_METHOD(Zygote, nativeFork, "()I"),
Elliott Hughes178cdcc2012-08-16 16:47:31 -0700490 NATIVE_METHOD(Zygote, nativeForkAndSpecialize, "(II[II[[IILjava/lang/String;Ljava/lang/String;)I"),
Brian Carlstromcaabb1b2011-10-11 18:09:13 -0700491 NATIVE_METHOD(Zygote, nativeForkSystemServer, "(II[II[[IJJ)I"),
Elliott Hughes01158d72011-09-19 19:47:10 -0700492};
493
Elliott Hughes01158d72011-09-19 19:47:10 -0700494void register_dalvik_system_Zygote(JNIEnv* env) {
Elliott Hughes7756d542012-05-24 21:56:51 -0700495 REGISTER_NATIVE_METHODS("dalvik/system/Zygote");
Elliott Hughes01158d72011-09-19 19:47:10 -0700496}
497
498} // namespace art