308 #define WTERMSIG(status) ((status)&0x7F) 309 #endif 310 311 static const char * 312 getBytes(JNIEnv *env, jbyteArray arr) 313 { 314 return arr == NULL ? NULL : 315 (const char*) (*env)->GetByteArrayElements(env, arr, NULL); 316 } 317 318 static void 319 releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr) 320 { 321 if (parr != NULL) 322 (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT); 323 } 324 325 #define IOE_FORMAT "error=%d, %s" 326 327 static void 328 throwIOException(JNIEnv *env, int errnum, const char *defaultDetail) 329 { 330 const char *detail = defaultDetail; 331 char *errmsg; 332 size_t fmtsize; 333 char tmpbuf[1024]; 334 jstring s; 335 336 if (errnum != 0) { 337 int ret = getErrorString(errnum, tmpbuf, sizeof(tmpbuf)); 338 if (ret != EINVAL) 339 detail = tmpbuf; 340 } 341 /* ASCII Decimal representation uses 2.4 times as many bits as binary. */ 342 fmtsize = sizeof(IOE_FORMAT) + strlen(detail) + 3 * sizeof(errnum); 343 errmsg = NEW(char, fmtsize); 344 if (errmsg == NULL) 345 return; 346 347 snprintf(errmsg, fmtsize, IOE_FORMAT, errnum, detail); 348 s = JNU_NewStringPlatform(env, errmsg); 349 if (s != NULL) { 350 jobject x = JNU_NewObjectByName(env, "java/io/IOException", 351 "(Ljava/lang/String;)V", s); 352 if (x != NULL) 353 (*env)->Throw(env, x); 354 } 355 free(errmsg); 356 } 357 358 #ifdef DEBUG_PROCESS 359 /* Debugging process code is difficult; where to write debug output? */ 360 static void 361 debugPrint(char *format, ...) 362 { 363 FILE *tty = fopen("/dev/tty", "w"); 364 va_list ap; 365 va_start(ap, format); 366 vfprintf(tty, format, ap); 367 va_end(ap); 455 456 static pid_t 457 forkChild(ChildStuff *c) { 458 pid_t resultPid; 459 460 /* 461 * From Solaris fork(2): In Solaris 10, a call to fork() is 462 * identical to a call to fork1(); only the calling thread is 463 * replicated in the child process. This is the POSIX-specified 464 * behavior for fork(). 465 */ 466 resultPid = fork(); 467 468 if (resultPid == 0) { 469 childProcess(c); 470 } 471 assert(resultPid != 0); /* childProcess never returns */ 472 return resultPid; 473 } 474 475 /* Returns 1 if spawnhelper executable bits are set as expected. */ 476 static int check_helper(const char* helperpath) { 477 struct stat s; 478 int rc = stat(helperpath, &s); 479 if (rc == 0) { 480 /* Require all bits set since this is how jspawnhelper 481 * is set up in a canonical installation */ 482 if (s.st_mode & S_IXUSR && 483 s.st_mode & S_IXGRP && 484 s.st_mode & S_IXOTH) { 485 return 1; 486 } else { 487 return 0; 488 } 489 } else { 490 return 0; 491 } 492 } 493 494 static pid_t 495 spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) { 496 pid_t resultPid; 497 jboolean isCopy; 498 int i, offset, rval, bufsize, magic; 499 char *buf, buf1[16]; 500 char *hlpargs[2]; 501 SpawnInfo sp; 502 503 /* Some posix_spawn() implementations do not report exec() errors back to the caller; 504 * POSIX leaves that up to the implementor, it only requires the child process to fail with 505 * error code 127. 506 * Since we cannot use that information (the payload binary may also use exit code 127 for 507 * its own purposes), lets do at least a basic guess if exec(jspawnhelper) will succeed. 508 * There are many reasons why it could fail, most of which one cannot be tested without 509 * exec'ing, but we can at least check permissions. Since jspawnhelper is part of the JDK 510 * it should have the execute permissions set correctly. */ 511 if (check_helper(helperpath) == 0) { 512 throwIOException(env, 0, "jspawnhelper is not accessible."); 513 return -1; 514 } 515 516 /* need to tell helper which fd is for receiving the childstuff 517 * and which fd to send response back on 518 */ 519 snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1]); 520 /* put the fd string as argument to the helper cmd */ 521 hlpargs[0] = buf1; 522 hlpargs[1] = 0; 523 524 /* Following items are sent down the pipe to the helper 525 * after it is spawned. 526 * All strings are null terminated. All arrays of strings 527 * have an empty string for termination. 528 * - the ChildStuff struct 529 * - the SpawnInfo struct 530 * - the argv strings array 531 * - the envv strings array 532 * - the home directory string 655 if (envBlock != NULL) { 656 /* Convert envBlock into a char ** envv */ 657 if ((penvBlock = getBytes(env, envBlock)) == NULL) goto Catch; 658 if ((c->envv = NEW(const char *, envc + 1)) == NULL) goto Catch; 659 initVectorFromBlock(c->envv, penvBlock, envc); 660 } 661 662 if (dir != NULL) { 663 if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch; 664 } 665 666 assert(std_fds != NULL); 667 fds = (*env)->GetIntArrayElements(env, std_fds, NULL); 668 if (fds == NULL) goto Catch; 669 670 if ((fds[0] == -1 && pipe(in) < 0) || 671 (fds[1] == -1 && pipe(out) < 0) || 672 (fds[2] == -1 && pipe(err) < 0) || 673 (pipe(childenv) < 0) || 674 (pipe(fail) < 0)) { 675 throwIOException(env, errno, "Bad file descriptor"); 676 goto Catch; 677 } 678 c->fds[0] = fds[0]; 679 c->fds[1] = fds[1]; 680 c->fds[2] = fds[2]; 681 682 copyPipe(in, c->in); 683 copyPipe(out, c->out); 684 copyPipe(err, c->err); 685 copyPipe(fail, c->fail); 686 copyPipe(childenv, c->childenv); 687 688 c->redirectErrorStream = redirectErrorStream; 689 c->mode = mode; 690 691 resultPid = startChild(env, process, c, phelperpath); 692 assert(resultPid != 0); 693 694 if (resultPid < 0) { 695 /* Throw an IOException with a generic text unless an exception was already raised. */ 696 if (!(*env)->ExceptionCheck(env)) { 697 switch (c->mode) { 698 case MODE_VFORK: 699 throwIOException(env, errno, "vfork failed"); 700 break; 701 case MODE_FORK: 702 throwIOException(env, errno, "fork failed"); 703 break; 704 case MODE_POSIX_SPAWN: 705 throwIOException(env, errno, "posix_spawn failed"); 706 break; 707 } 708 } 709 goto Catch; 710 } 711 close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec (childproc.c) */ 712 713 switch (readFully(fail[0], &errnum, sizeof(errnum))) { 714 case 0: break; /* Exec succeeded */ 715 case sizeof(errnum): 716 waitpid(resultPid, NULL, 0); 717 throwIOException(env, errnum, "Exec failed"); 718 goto Catch; 719 default: 720 throwIOException(env, errno, "Read failed"); 721 goto Catch; 722 } 723 724 fds[0] = (in [1] != -1) ? in [1] : -1; 725 fds[1] = (out[0] != -1) ? out[0] : -1; 726 fds[2] = (err[0] != -1) ? err[0] : -1; 727 728 Finally: 729 /* Always clean up the child's side of the pipes */ 730 closeSafely(in [0]); 731 closeSafely(out[1]); 732 closeSafely(err[1]); 733 734 /* Always clean up fail and childEnv descriptors */ 735 closeSafely(fail[0]); 736 closeSafely(fail[1]); 737 closeSafely(childenv[0]); 738 closeSafely(childenv[1]); 739 740 releaseBytes(env, helperpath, phelperpath); | 308 #define WTERMSIG(status) ((status)&0x7F) 309 #endif 310 311 static const char * 312 getBytes(JNIEnv *env, jbyteArray arr) 313 { 314 return arr == NULL ? NULL : 315 (const char*) (*env)->GetByteArrayElements(env, arr, NULL); 316 } 317 318 static void 319 releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr) 320 { 321 if (parr != NULL) 322 (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT); 323 } 324 325 #define IOE_FORMAT "error=%d, %s" 326 327 static void 328 throwIOException(JNIEnv *env, int errnum, const char *defaultDetail, const char* addinfo) 329 { 330 const char *detail = defaultDetail; 331 char *errmsg; 332 size_t fmtsize; 333 char tmpbuf[1024]; 334 jstring s; 335 336 if (errnum != 0) { 337 int ret = getErrorString(errnum, tmpbuf, sizeof(tmpbuf)); 338 if (ret != EINVAL) 339 detail = tmpbuf; 340 } 341 /* ASCII Decimal representation uses 2.4 times as many bits as binary. */ 342 fmtsize = sizeof(IOE_FORMAT) + strlen(detail) + 3 * sizeof(errnum) + 343 (addinfo == NULL ? 0 : 1 + strlen(addinfo) + 2); // " (<info>)" 344 errmsg = NEW(char, fmtsize); 345 if (errmsg == NULL) 346 return; 347 348 snprintf(errmsg, fmtsize, IOE_FORMAT, errnum, detail); 349 if (addinfo != NULL) { 350 strcat(errmsg, " ("); 351 strcat(errmsg, addinfo); 352 strcat(errmsg, ")"); 353 } 354 355 s = JNU_NewStringPlatform(env, errmsg); 356 if (s != NULL) { 357 jobject x = JNU_NewObjectByName(env, "java/io/IOException", 358 "(Ljava/lang/String;)V", s); 359 if (x != NULL) 360 (*env)->Throw(env, x); 361 } 362 free(errmsg); 363 } 364 365 #ifdef DEBUG_PROCESS 366 /* Debugging process code is difficult; where to write debug output? */ 367 static void 368 debugPrint(char *format, ...) 369 { 370 FILE *tty = fopen("/dev/tty", "w"); 371 va_list ap; 372 va_start(ap, format); 373 vfprintf(tty, format, ap); 374 va_end(ap); 462 463 static pid_t 464 forkChild(ChildStuff *c) { 465 pid_t resultPid; 466 467 /* 468 * From Solaris fork(2): In Solaris 10, a call to fork() is 469 * identical to a call to fork1(); only the calling thread is 470 * replicated in the child process. This is the POSIX-specified 471 * behavior for fork(). 472 */ 473 resultPid = fork(); 474 475 if (resultPid == 0) { 476 childProcess(c); 477 } 478 assert(resultPid != 0); /* childProcess never returns */ 479 return resultPid; 480 } 481 482 /* Returns 0 if at least one executable bit is set on the spawn helper binary, 483 * -1 otherwise. */ 484 static int isHelperExecutable(const char* helperpath) { 485 /* Note that this check will never be sufficient; exec() may still fail 486 * for many reasons and it is impossible to predict them all. The point of 487 * this test is to catch the most common failure reason and give the caller 488 * a clear diagnostic message. 489 * But never shall this test give us false positives (make us avoid exec()ing 490 * where it would have actually worked.) So since exec() success cannot be 491 * completely predicted, we err on the side of false negatives - when in doubt, 492 * try it. 493 */ 494 static int cached_rc = -2; 495 if (cached_rc == 0 || cached_rc == -1) { 496 /* The helper binary is part of the JDK and should have been set up 497 * correctly. This is very unlikely to happen intermittently. Therefore 498 * it should be okay to cache the result. */ 499 return cached_rc; 500 } 501 502 struct stat s; 503 int rc = stat(helperpath, &s); 504 if (rc == 0) { 505 /* Require at least one exec bit set since this is how the spawn helper 506 * is set up in a canonical installation. */ 507 if (s.st_mode & S_IXUSR || 508 s.st_mode & S_IXGRP || 509 s.st_mode & S_IXOTH) { 510 cached_rc = 0; 511 return 0; 512 } 513 } 514 cached_rc = -1; 515 return -1; 516 } 517 518 static pid_t 519 spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) { 520 pid_t resultPid = -1; 521 jboolean isCopy; 522 int i, offset, rval, bufsize, magic; 523 char *buf, buf1[16]; 524 char *hlpargs[2]; 525 SpawnInfo sp; 526 527 /* Some posix_spawn() implementations do not report exec() errors back to the caller; 528 * POSIX leaves that up to the implementor, it only requires the child process to fail with 529 * error code 127. 530 * The problem with that is that posix_spawn() will seemingly succeed, child process will 531 * have been started but will immediately die with exit code 127. This is impossible to 532 * tell apart from cases where we successfully exec()'d the target program and it died 533 * with 127. In the former case we want to throw an IOException, the latter case is fine 534 * and should be handled by the java program. 535 * There is no perfect solution, but here we try - before starting the child - to catch 536 * obvious cases which will make the first exec() fail. */ 537 if (isHelperExecutable(helperpath) != 0) { 538 errno = EACCES; 539 c->error_detail = "No execute permission for spawn helper."; 540 return -1; 541 } 542 543 /* need to tell helper which fd is for receiving the childstuff 544 * and which fd to send response back on 545 */ 546 snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1]); 547 /* put the fd string as argument to the helper cmd */ 548 hlpargs[0] = buf1; 549 hlpargs[1] = 0; 550 551 /* Following items are sent down the pipe to the helper 552 * after it is spawned. 553 * All strings are null terminated. All arrays of strings 554 * have an empty string for termination. 555 * - the ChildStuff struct 556 * - the SpawnInfo struct 557 * - the argv strings array 558 * - the envv strings array 559 * - the home directory string 682 if (envBlock != NULL) { 683 /* Convert envBlock into a char ** envv */ 684 if ((penvBlock = getBytes(env, envBlock)) == NULL) goto Catch; 685 if ((c->envv = NEW(const char *, envc + 1)) == NULL) goto Catch; 686 initVectorFromBlock(c->envv, penvBlock, envc); 687 } 688 689 if (dir != NULL) { 690 if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch; 691 } 692 693 assert(std_fds != NULL); 694 fds = (*env)->GetIntArrayElements(env, std_fds, NULL); 695 if (fds == NULL) goto Catch; 696 697 if ((fds[0] == -1 && pipe(in) < 0) || 698 (fds[1] == -1 && pipe(out) < 0) || 699 (fds[2] == -1 && pipe(err) < 0) || 700 (pipe(childenv) < 0) || 701 (pipe(fail) < 0)) { 702 throwIOException(env, errno, "Bad file descriptor", NULL); 703 goto Catch; 704 } 705 c->fds[0] = fds[0]; 706 c->fds[1] = fds[1]; 707 c->fds[2] = fds[2]; 708 709 copyPipe(in, c->in); 710 copyPipe(out, c->out); 711 copyPipe(err, c->err); 712 copyPipe(fail, c->fail); 713 copyPipe(childenv, c->childenv); 714 715 c->redirectErrorStream = redirectErrorStream; 716 c->mode = mode; 717 c->error_detail = NULL; 718 719 resultPid = startChild(env, process, c, phelperpath); 720 assert(resultPid != 0); 721 722 if (resultPid < 0) { 723 switch (c->mode) { 724 case MODE_VFORK: 725 throwIOException(env, errno, "vfork failed", c->error_detail); 726 break; 727 case MODE_FORK: 728 throwIOException(env, errno, "fork failed", c->error_detail); 729 break; 730 case MODE_POSIX_SPAWN: 731 throwIOException(env, errno, "posix_spawn failed", c->error_detail); 732 break; 733 } 734 goto Catch; 735 } 736 close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec (childproc.c) */ 737 738 switch (readFully(fail[0], &errnum, sizeof(errnum))) { 739 case 0: break; /* Exec succeeded */ 740 case sizeof(errnum): 741 waitpid(resultPid, NULL, 0); 742 throwIOException(env, errnum, "Exec failed", NULL); 743 goto Catch; 744 default: 745 throwIOException(env, errno, "Read failed", NULL); 746 goto Catch; 747 } 748 749 fds[0] = (in [1] != -1) ? in [1] : -1; 750 fds[1] = (out[0] != -1) ? out[0] : -1; 751 fds[2] = (err[0] != -1) ? err[0] : -1; 752 753 Finally: 754 /* Always clean up the child's side of the pipes */ 755 closeSafely(in [0]); 756 closeSafely(out[1]); 757 closeSafely(err[1]); 758 759 /* Always clean up fail and childEnv descriptors */ 760 closeSafely(fail[0]); 761 closeSafely(fail[1]); 762 closeSafely(childenv[0]); 763 closeSafely(childenv[1]); 764 765 releaseBytes(env, helperpath, phelperpath); |