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