dalvik_system_Zygote.cpp revision 5c80d7d72a54a30abc3bbf2fafb62a06062eccea
1/* 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 17/* 18 * dalvik.system.Zygote 19 */ 20#include "Dalvik.h" 21#include "native/InternalNativePriv.h" 22 23#include <signal.h> 24#include <linux/personality.h> 25#include <sys/types.h> 26#include <sys/wait.h> 27#include <grp.h> 28#include <errno.h> 29#include <paths.h> 30 31#if defined(HAVE_PRCTL) 32# include <sys/prctl.h> 33#endif 34 35#define ZYGOTE_LOG_TAG "Zygote" 36 37/* must match values in dalvik.system.Zygote */ 38enum { 39 DEBUG_ENABLE_DEBUGGER = 1, 40 DEBUG_ENABLE_CHECKJNI = 1 << 1, 41 DEBUG_ENABLE_ASSERT = 1 << 2, 42 DEBUG_ENABLE_SAFEMODE = 1 << 3, 43 DEBUG_ENABLE_JNI_LOGGING = 1 << 4, 44}; 45 46/* 47 * This signal handler is for zygote mode, since the zygote 48 * must reap its children 49 */ 50static void sigchldHandler(int s) 51{ 52 pid_t pid; 53 int status; 54 55 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 56 /* Log process-death status that we care about. In general it is not 57 safe to call ALOG(...) from a signal handler because of possible 58 reentrancy. However, we know a priori that the current implementation 59 of ALOG() is safe to call from a SIGCHLD handler in the zygote process. 60 If the ALOG() implementation changes its locking strategy or its use 61 of syscalls within the lazy-init critical section, its use here may 62 become unsafe. */ 63 if (WIFEXITED(status)) { 64 if (WEXITSTATUS(status)) { 65 ALOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)", 66 (int) pid, WEXITSTATUS(status)); 67 } else { 68 IF_ALOGV(/*should use ZYGOTE_LOG_TAG*/) { 69 ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, 70 "Process %d exited cleanly (%d)", 71 (int) pid, WEXITSTATUS(status)); 72 } 73 } 74 } else if (WIFSIGNALED(status)) { 75 if (WTERMSIG(status) != SIGKILL) { 76 ALOG(LOG_DEBUG, ZYGOTE_LOG_TAG, 77 "Process %d terminated by signal (%d)", 78 (int) pid, WTERMSIG(status)); 79 } else { 80 IF_ALOGV(/*should use ZYGOTE_LOG_TAG*/) { 81 ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, 82 "Process %d terminated by signal (%d)", 83 (int) pid, WTERMSIG(status)); 84 } 85 } 86#ifdef WCOREDUMP 87 if (WCOREDUMP(status)) { 88 ALOG(LOG_INFO, ZYGOTE_LOG_TAG, "Process %d dumped core", 89 (int) pid); 90 } 91#endif /* ifdef WCOREDUMP */ 92 } 93 94 /* 95 * If the just-crashed process is the system_server, bring down zygote 96 * so that it is restarted by init and system server will be restarted 97 * from there. 98 */ 99 if (pid == gDvm.systemServerPid) { 100 ALOG(LOG_INFO, ZYGOTE_LOG_TAG, 101 "Exit zygote because system server (%d) has terminated", 102 (int) pid); 103 kill(getpid(), SIGKILL); 104 } 105 } 106 107 if (pid < 0) { 108 ALOG(LOG_WARN, ZYGOTE_LOG_TAG, 109 "Zygote SIGCHLD error in waitpid: %s",strerror(errno)); 110 } 111} 112 113/* 114 * configure sigchld handler for the zygote process 115 * This is configured very late, because earlier in the dalvik lifecycle 116 * we can fork() and exec() for the verifier/optimizer, and we 117 * want to waitpid() for those rather than have them be harvested immediately. 118 * 119 * This ends up being called repeatedly before each fork(), but there's 120 * no real harm in that. 121 */ 122static void setSignalHandler() 123{ 124 int err; 125 struct sigaction sa; 126 127 memset(&sa, 0, sizeof(sa)); 128 129 sa.sa_handler = sigchldHandler; 130 131 err = sigaction (SIGCHLD, &sa, NULL); 132 133 if (err < 0) { 134 ALOGW("Error setting SIGCHLD handler: %s", strerror(errno)); 135 } 136} 137 138/* 139 * Set the SIGCHLD handler back to default behavior in zygote children 140 */ 141static void unsetSignalHandler() 142{ 143 int err; 144 struct sigaction sa; 145 146 memset(&sa, 0, sizeof(sa)); 147 148 sa.sa_handler = SIG_DFL; 149 150 err = sigaction (SIGCHLD, &sa, NULL); 151 152 if (err < 0) { 153 ALOGW("Error unsetting SIGCHLD handler: %s", strerror(errno)); 154 } 155} 156 157/* 158 * Calls POSIX setgroups() using the int[] object as an argument. 159 * A NULL argument is tolerated. 160 */ 161 162static int setgroupsIntarray(ArrayObject* gidArray) 163{ 164 gid_t *gids; 165 u4 i; 166 s4 *contents; 167 168 if (gidArray == NULL) { 169 return 0; 170 } 171 172 /* just in case gid_t and u4 are different... */ 173 gids = (gid_t *)alloca(sizeof(gid_t) * gidArray->length); 174 contents = (s4 *)(void *)gidArray->contents; 175 176 for (i = 0 ; i < gidArray->length ; i++) { 177 gids[i] = (gid_t) contents[i]; 178 } 179 180 return setgroups((size_t) gidArray->length, gids); 181} 182 183/* 184 * Sets the resource limits via setrlimit(2) for the values in the 185 * two-dimensional array of integers that's passed in. The second dimension 186 * contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is 187 * treated as an empty array. 188 * 189 * -1 is returned on error. 190 */ 191static int setrlimitsFromArray(ArrayObject* rlimits) 192{ 193 u4 i; 194 struct rlimit rlim; 195 196 if (rlimits == NULL) { 197 return 0; 198 } 199 200 memset (&rlim, 0, sizeof(rlim)); 201 202 ArrayObject** tuples = (ArrayObject **)(void *)rlimits->contents; 203 204 for (i = 0; i < rlimits->length; i++) { 205 ArrayObject * rlimit_tuple = tuples[i]; 206 s4* contents = (s4 *)(void *)rlimit_tuple->contents; 207 int err; 208 209 if (rlimit_tuple->length != 3) { 210 ALOGE("rlimits array must have a second dimension of size 3"); 211 return -1; 212 } 213 214 rlim.rlim_cur = contents[1]; 215 rlim.rlim_max = contents[2]; 216 217 err = setrlimit(contents[0], &rlim); 218 219 if (err < 0) { 220 return -1; 221 } 222 } 223 224 return 0; 225} 226 227/* native public static int fork(); */ 228static void Dalvik_dalvik_system_Zygote_fork(const u4* args, JValue* pResult) 229{ 230 pid_t pid; 231 232 if (!gDvm.zygote) { 233 dvmThrowIllegalStateException( 234 "VM instance not started with -Xzygote"); 235 236 RETURN_VOID(); 237 } 238 239 if (!dvmGcPreZygoteFork()) { 240 ALOGE("pre-fork heap failed"); 241 dvmAbort(); 242 } 243 244 setSignalHandler(); 245 246 dvmDumpLoaderStats("zygote"); 247 pid = fork(); 248 249#ifdef HAVE_ANDROID_OS 250 if (pid == 0) { 251 /* child process */ 252 extern int gMallocLeakZygoteChild; 253 gMallocLeakZygoteChild = 1; 254 } 255#endif 256 257 RETURN_INT(pid); 258} 259 260/* 261 * Enable/disable debug features requested by the caller. 262 * 263 * debugger 264 * If set, enable debugging; if not set, disable debugging. This is 265 * easy to handle, because the JDWP thread isn't started until we call 266 * dvmInitAfterZygote(). 267 * checkjni 268 * If set, make sure "check JNI" is enabled. 269 * assert 270 * If set, make sure assertions are enabled. This gets fairly weird, 271 * because it affects the result of a method called by class initializers, 272 * and hence can't affect pre-loaded/initialized classes. 273 * safemode 274 * If set, operates the VM in the safe mode. The definition of "safe mode" is 275 * implementation dependent and currently only the JIT compiler is disabled. 276 * This is easy to handle because the compiler thread and associated resources 277 * are not requested until we call dvmInitAfterZygote(). 278 */ 279static void enableDebugFeatures(u4 debugFlags) 280{ 281 ALOGV("debugFlags is 0x%02x", debugFlags); 282 283 gDvm.jdwpAllowed = ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0); 284 285 if ((debugFlags & DEBUG_ENABLE_CHECKJNI) != 0) { 286 /* turn it on if it's not already enabled */ 287 dvmLateEnableCheckedJni(); 288 } 289 290 if ((debugFlags & DEBUG_ENABLE_JNI_LOGGING) != 0) { 291 gDvmJni.logThirdPartyJni = true; 292 } 293 294 if ((debugFlags & DEBUG_ENABLE_ASSERT) != 0) { 295 /* turn it on if it's not already enabled */ 296 dvmLateEnableAssertions(); 297 } 298 299 if ((debugFlags & DEBUG_ENABLE_SAFEMODE) != 0) { 300#if defined(WITH_JIT) 301 /* turn off the jit if it is explicitly requested by the app */ 302 if (gDvm.executionMode == kExecutionModeJit) 303 gDvm.executionMode = kExecutionModeInterpFast; 304#endif 305 } 306 307#ifdef HAVE_ANDROID_OS 308 if ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0) { 309 /* To let a non-privileged gdbserver attach to this 310 * process, we must set its dumpable bit flag. However 311 * we are not interested in generating a coredump in 312 * case of a crash, so also set the coredump size to 0 313 * to disable that 314 */ 315 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) { 316 ALOGE("could not set dumpable bit flag for pid %d: %s", 317 getpid(), strerror(errno)); 318 } else { 319 struct rlimit rl; 320 rl.rlim_cur = 0; 321 rl.rlim_max = RLIM_INFINITY; 322 if (setrlimit(RLIMIT_CORE, &rl) < 0) { 323 ALOGE("could not disable core file generation for pid %d: %s", 324 getpid(), strerror(errno)); 325 } 326 } 327 } 328#endif 329} 330 331/* 332 * Set Linux capability flags. 333 * 334 * Returns 0 on success, errno on failure. 335 */ 336static int setCapabilities(int64_t permitted, int64_t effective) 337{ 338#ifdef HAVE_ANDROID_OS 339 struct __user_cap_header_struct capheader; 340 struct __user_cap_data_struct capdata; 341 342 memset(&capheader, 0, sizeof(capheader)); 343 memset(&capdata, 0, sizeof(capdata)); 344 345 capheader.version = _LINUX_CAPABILITY_VERSION; 346 capheader.pid = 0; 347 348 capdata.effective = effective; 349 capdata.permitted = permitted; 350 351 ALOGV("CAPSET perm=%llx eff=%llx", permitted, effective); 352 if (capset(&capheader, &capdata) != 0) 353 return errno; 354#endif /*HAVE_ANDROID_OS*/ 355 356 return 0; 357} 358 359/* 360 * Utility routine to fork zygote and specialize the child process. 361 */ 362static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) 363{ 364 pid_t pid; 365 366 uid_t uid = (uid_t) args[0]; 367 gid_t gid = (gid_t) args[1]; 368 ArrayObject* gids = (ArrayObject *)args[2]; 369 u4 debugFlags = args[3]; 370 ArrayObject *rlimits = (ArrayObject *)args[4]; 371 int64_t permittedCapabilities, effectiveCapabilities; 372 373 if (isSystemServer) { 374 /* 375 * Don't use GET_ARG_LONG here for now. gcc is generating code 376 * that uses register d8 as a temporary, and that's coming out 377 * scrambled in the child process. b/3138621 378 */ 379 //permittedCapabilities = GET_ARG_LONG(args, 5); 380 //effectiveCapabilities = GET_ARG_LONG(args, 7); 381 permittedCapabilities = args[5] | (int64_t) args[6] << 32; 382 effectiveCapabilities = args[7] | (int64_t) args[8] << 32; 383 } else { 384 permittedCapabilities = effectiveCapabilities = 0; 385 } 386 387 if (!gDvm.zygote) { 388 dvmThrowIllegalStateException( 389 "VM instance not started with -Xzygote"); 390 391 return -1; 392 } 393 394 if (!dvmGcPreZygoteFork()) { 395 ALOGE("pre-fork heap failed"); 396 dvmAbort(); 397 } 398 399 setSignalHandler(); 400 401 dvmDumpLoaderStats("zygote"); 402 pid = fork(); 403 404 if (pid == 0) { 405 int err; 406 /* The child process */ 407 408#ifdef HAVE_ANDROID_OS 409 extern int gMallocLeakZygoteChild; 410 gMallocLeakZygoteChild = 1; 411 412 /* keep caps across UID change, unless we're staying root */ 413 if (uid != 0) { 414 err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 415 416 if (err < 0) { 417 ALOGE("cannot PR_SET_KEEPCAPS: %s", strerror(errno)); 418 dvmAbort(); 419 } 420 } 421 422#endif /* HAVE_ANDROID_OS */ 423 424 err = setgroupsIntarray(gids); 425 426 if (err < 0) { 427 ALOGE("cannot setgroups(): %s", strerror(errno)); 428 dvmAbort(); 429 } 430 431 err = setrlimitsFromArray(rlimits); 432 433 if (err < 0) { 434 ALOGE("cannot setrlimit(): %s", strerror(errno)); 435 dvmAbort(); 436 } 437 438 err = setgid(gid); 439 if (err < 0) { 440 ALOGE("cannot setgid(%d): %s", gid, strerror(errno)); 441 dvmAbort(); 442 } 443 444 err = setuid(uid); 445 if (err < 0) { 446 ALOGE("cannot setuid(%d): %s", uid, strerror(errno)); 447 dvmAbort(); 448 } 449 450 int current = personality(0xffffFFFF); 451 int success = personality((ADDR_NO_RANDOMIZE | current)); 452 if (success == -1) { 453 ALOGW("Personality switch failed. current=%d error=%d\n", current, errno); 454 } 455 456 err = setCapabilities(permittedCapabilities, effectiveCapabilities); 457 if (err != 0) { 458 ALOGE("cannot set capabilities (%llx,%llx): %s", 459 permittedCapabilities, effectiveCapabilities, strerror(err)); 460 dvmAbort(); 461 } 462 463 /* 464 * Our system thread ID has changed. Get the new one. 465 */ 466 Thread* thread = dvmThreadSelf(); 467 thread->systemTid = dvmGetSysThreadId(); 468 469 /* configure additional debug options */ 470 enableDebugFeatures(debugFlags); 471 472 unsetSignalHandler(); 473 gDvm.zygote = false; 474 if (!dvmInitAfterZygote()) { 475 ALOGE("error in post-zygote initialization"); 476 dvmAbort(); 477 } 478 } else if (pid > 0) { 479 /* the parent process */ 480 } 481 482 return pid; 483} 484 485/* native public static int forkAndSpecialize(int uid, int gid, 486 * int[] gids, int debugFlags); 487 */ 488static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args, 489 JValue* pResult) 490{ 491 pid_t pid; 492 493 pid = forkAndSpecializeCommon(args, false); 494 495 RETURN_INT(pid); 496} 497 498/* native public static int forkSystemServer(int uid, int gid, 499 * int[] gids, int debugFlags, long permittedCapabilities, 500 * long effectiveCapabilities); 501 */ 502static void Dalvik_dalvik_system_Zygote_forkSystemServer( 503 const u4* args, JValue* pResult) 504{ 505 pid_t pid; 506 pid = forkAndSpecializeCommon(args, true); 507 508 /* The zygote process checks whether the child process has died or not. */ 509 if (pid > 0) { 510 int status; 511 512 ALOGI("System server process %d has been created", pid); 513 gDvm.systemServerPid = pid; 514 /* There is a slight window that the system server process has crashed 515 * but it went unnoticed because we haven't published its pid yet. So 516 * we recheck here just to make sure that all is well. 517 */ 518 if (waitpid(pid, &status, WNOHANG) == pid) { 519 ALOGE("System server process %d has died. Restarting Zygote!", pid); 520 kill(getpid(), SIGKILL); 521 } 522 } 523 RETURN_INT(pid); 524} 525 526/* native private static void nativeExecShell(String command); 527 */ 528static void Dalvik_dalvik_system_Zygote_execShell( 529 const u4* args, JValue* pResult) 530{ 531 StringObject* command = (StringObject*)args[0]; 532 533 const char *argp[] = {_PATH_BSHELL, "-c", NULL, NULL}; 534 argp[2] = dvmCreateCstrFromString(command); 535 536 ALOGI("Exec: %s %s %s", argp[0], argp[1], argp[2]); 537 538 execv(_PATH_BSHELL, (char**)argp); 539 exit(127); 540} 541 542const DalvikNativeMethod dvm_dalvik_system_Zygote[] = { 543 { "nativeFork", "()I", 544 Dalvik_dalvik_system_Zygote_fork }, 545 { "nativeForkAndSpecialize", "(II[II[[I)I", 546 Dalvik_dalvik_system_Zygote_forkAndSpecialize }, 547 { "nativeForkSystemServer", "(II[II[[IJJ)I", 548 Dalvik_dalvik_system_Zygote_forkSystemServer }, 549 { "nativeExecShell", "(Ljava/lang/String;)V", 550 Dalvik_dalvik_system_Zygote_execShell }, 551 { NULL, NULL, NULL }, 552}; 553