From e23ab9a19a65a3a72681264e53160f5b4222507c Mon Sep 17 00:00:00 2001 From: kuenking111 Date: Mon, 24 Oct 2022 17:14:38 +0800 Subject: [PATCH] I5XEUK: 8065895: Synchronous signals during error reporting may terminate or hang VM process --- ...ing-may-terminate-or-hang-vm-process.patch | 485 ++++++++++++++++++ openjdk-1.8.0.spec | 8 +- 2 files changed, 491 insertions(+), 2 deletions(-) create mode 100644 8065895-Synchronous-signals-during-error-reporting-may-terminate-or-hang-vm-process.patch diff --git a/8065895-Synchronous-signals-during-error-reporting-may-terminate-or-hang-vm-process.patch b/8065895-Synchronous-signals-during-error-reporting-may-terminate-or-hang-vm-process.patch new file mode 100644 index 0000000..2e5bc25 --- /dev/null +++ b/8065895-Synchronous-signals-during-error-reporting-may-terminate-or-hang-vm-process.patch @@ -0,0 +1,485 @@ +From 69371858fda3c1793faf8bbf116ec4fe554605ac Mon Sep 17 00:00:00 2001 +From: hedongbo +Date: Fri, 21 Oct 2022 15:16:04 +0800 +Subject: 8065895: Synchronous signals during error reporting may + terminate or hang VM process + +Bug url: https://bugs.openjdk.java.net/browse/JDK-8065895 +--- + hotspot/src/os/aix/vm/vmError_aix.cpp | 11 +++-- + hotspot/src/os/bsd/vm/vmError_bsd.cpp | 47 +++++++++++------- + hotspot/src/os/linux/vm/vmError_linux.cpp | 48 ++++++++++++------- + hotspot/src/os/solaris/vm/vmError_solaris.cpp | 48 ++++++++++++------- + hotspot/src/share/vm/runtime/globals.hpp | 4 ++ + hotspot/src/share/vm/utilities/debug.cpp | 48 ++++++++++++++++--- + hotspot/src/share/vm/utilities/debug.hpp | 18 +++++++ + hotspot/src/share/vm/utilities/vmError.cpp | 29 +++++++++++ + 8 files changed, 196 insertions(+), 57 deletions(-) + +diff --git a/hotspot/src/os/aix/vm/vmError_aix.cpp b/hotspot/src/os/aix/vm/vmError_aix.cpp +index d99436ebc..34709134a 100644 +--- a/hotspot/src/os/aix/vm/vmError_aix.cpp ++++ b/hotspot/src/os/aix/vm/vmError_aix.cpp +@@ -80,7 +80,6 @@ static void save_signal(int idx, int sig) { + } + + int VMError::get_resetted_sigflags(int sig) { +- // Handle all program errors. + for (int i = 0; i < NUM_SIGNALS; i++) { + if (SIGNALS[i] == sig) { + return resettedSigflags[i]; +@@ -90,7 +89,6 @@ int VMError::get_resetted_sigflags(int sig) { + } + + address VMError::get_resetted_sighandler(int sig) { +- // Handle all program errors. + for (int i = 0; i < NUM_SIGNALS; i++) { + if (SIGNALS[i] == sig) { + return resettedSighandler[i]; +@@ -100,12 +98,19 @@ address VMError::get_resetted_sighandler(int sig) { + } + + static void crash_handler(int sig, siginfo_t* info, void* ucVoid) { ++ + // Unmask current signal. + sigset_t newset; + sigemptyset(&newset); + sigaddset(&newset, sig); ++ // and all other synchronous signals too. ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ sigaddset(&newset, SIGNALS[i]); ++ } ++ sigthreadmask(SIG_UNBLOCK, &newset, NULL); + +- Unimplemented(); ++ VMError err(NULL, sig, NULL, info, ucVoid); ++ err.report_and_die(); + } + + void VMError::reset_signal_handlers() { +diff --git a/hotspot/src/os/bsd/vm/vmError_bsd.cpp b/hotspot/src/os/bsd/vm/vmError_bsd.cpp +index 8ec6ca04c..f09e1163f 100644 +--- a/hotspot/src/os/bsd/vm/vmError_bsd.cpp ++++ b/hotspot/src/os/bsd/vm/vmError_bsd.cpp +@@ -63,9 +63,15 @@ void VMError::show_message_box(char *buf, int buflen) { + } while (yes); + } + ++// handle all synchronous program error signals which may happen during error ++// reporting. They must be unblocked, caught, handled. ++ ++static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed ++static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int); ++ + // Space for our "saved" signal flags and handlers +-static int resettedSigflags[2]; +-static address resettedSighandler[2]; ++static int resettedSigflags[NUM_SIGNALS]; ++static address resettedSighandler[NUM_SIGNALS]; + + static void save_signal(int idx, int sig) + { +@@ -78,19 +84,19 @@ static void save_signal(int idx, int sig) + } + + int VMError::get_resetted_sigflags(int sig) { +- if(SIGSEGV == sig) { +- return resettedSigflags[0]; +- } else if(SIGBUS == sig) { +- return resettedSigflags[1]; ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ if (SIGNALS[i] == sig) { ++ return resettedSigflags[i]; ++ } + } + return -1; + } + + address VMError::get_resetted_sighandler(int sig) { +- if(SIGSEGV == sig) { +- return resettedSighandler[0]; +- } else if(SIGBUS == sig) { +- return resettedSighandler[1]; ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ if (SIGNALS[i] == sig) { ++ return resettedSighandler[i]; ++ } + } + return NULL; + } +@@ -100,16 +106,25 @@ static void crash_handler(int sig, siginfo_t* info, void* ucVoid) { + sigset_t newset; + sigemptyset(&newset); + sigaddset(&newset, sig); +- sigprocmask(SIG_UNBLOCK, &newset, NULL); ++ // also unmask other synchronous signals ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ sigaddset(&newset, SIGNALS[i]); ++ } ++ pthread_sigmask(SIG_UNBLOCK, &newset, NULL); + + VMError err(NULL, sig, NULL, info, ucVoid); + err.report_and_die(); + } + + void VMError::reset_signal_handlers() { +- // Save sigflags for resetted signals +- save_signal(0, SIGSEGV); +- save_signal(1, SIGBUS); +- os::signal(SIGSEGV, CAST_FROM_FN_PTR(void *, crash_handler)); +- os::signal(SIGBUS, CAST_FROM_FN_PTR(void *, crash_handler)); ++ // install signal handlers for all synchronous program error signals ++ sigset_t newset; ++ sigemptyset(&newset); ++ ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ save_signal(i, SIGNALS[i]); ++ os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler)); ++ sigaddset(&newset, SIGNALS[i]); ++ } ++ pthread_sigmask(SIG_UNBLOCK, &newset, NULL); + } +diff --git a/hotspot/src/os/linux/vm/vmError_linux.cpp b/hotspot/src/os/linux/vm/vmError_linux.cpp +index 378c9a6ab..fca239c7e 100644 +--- a/hotspot/src/os/linux/vm/vmError_linux.cpp ++++ b/hotspot/src/os/linux/vm/vmError_linux.cpp +@@ -63,9 +63,15 @@ void VMError::show_message_box(char *buf, int buflen) { + } while (yes); + } + ++// handle all synchronous program error signals which may happen during error ++// reporting. They must be unblocked, caught, handled. ++ ++static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed ++static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int); ++ + // Space for our "saved" signal flags and handlers +-static int resettedSigflags[2]; +-static address resettedSighandler[2]; ++static int resettedSigflags[NUM_SIGNALS]; ++static address resettedSighandler[NUM_SIGNALS]; + + static void save_signal(int idx, int sig) + { +@@ -78,19 +84,19 @@ static void save_signal(int idx, int sig) + } + + int VMError::get_resetted_sigflags(int sig) { +- if(SIGSEGV == sig) { +- return resettedSigflags[0]; +- } else if(SIGBUS == sig) { +- return resettedSigflags[1]; ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ if (SIGNALS[i] == sig) { ++ return resettedSigflags[i]; ++ } + } + return -1; + } + + address VMError::get_resetted_sighandler(int sig) { +- if(SIGSEGV == sig) { +- return resettedSighandler[0]; +- } else if(SIGBUS == sig) { +- return resettedSighandler[1]; ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ if (SIGNALS[i] == sig) { ++ return resettedSighandler[i]; ++ } + } + return NULL; + } +@@ -100,16 +106,26 @@ static void crash_handler(int sig, siginfo_t* info, void* ucVoid) { + sigset_t newset; + sigemptyset(&newset); + sigaddset(&newset, sig); +- sigprocmask(SIG_UNBLOCK, &newset, NULL); ++ // also unmask other synchronous signals ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ sigaddset(&newset, SIGNALS[i]); ++ } ++ pthread_sigmask(SIG_UNBLOCK, &newset, NULL); + + VMError err(NULL, sig, NULL, info, ucVoid); + err.report_and_die(); + } + + void VMError::reset_signal_handlers() { +- // Save sigflags for resetted signals +- save_signal(0, SIGSEGV); +- save_signal(1, SIGBUS); +- os::signal(SIGSEGV, CAST_FROM_FN_PTR(void *, crash_handler)); +- os::signal(SIGBUS, CAST_FROM_FN_PTR(void *, crash_handler)); ++ // install signal handlers for all synchronous program error signals ++ sigset_t newset; ++ sigemptyset(&newset); ++ ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ save_signal(i, SIGNALS[i]); ++ os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler)); ++ sigaddset(&newset, SIGNALS[i]); ++ } ++ pthread_sigmask(SIG_UNBLOCK, &newset, NULL); ++ + } +diff --git a/hotspot/src/os/solaris/vm/vmError_solaris.cpp b/hotspot/src/os/solaris/vm/vmError_solaris.cpp +index 6f3f5b06f..e24e5f6bf 100644 +--- a/hotspot/src/os/solaris/vm/vmError_solaris.cpp ++++ b/hotspot/src/os/solaris/vm/vmError_solaris.cpp +@@ -30,6 +30,7 @@ + + #include + #include ++#include + #include + + void VMError::show_message_box(char *buf, int buflen) { +@@ -59,9 +60,15 @@ void VMError::show_message_box(char *buf, int buflen) { + } while (yes); + } + ++// handle all synchronous program error signals which may happen during error ++// reporting. They must be unblocked, caught, handled. ++ ++static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed ++static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int); ++ + // Space for our "saved" signal flags and handlers +-static int resettedSigflags[2]; +-static address resettedSighandler[2]; ++static int resettedSigflags[NUM_SIGNALS]; ++static address resettedSighandler[NUM_SIGNALS]; + + static void save_signal(int idx, int sig) + { +@@ -74,19 +81,19 @@ static void save_signal(int idx, int sig) + } + + int VMError::get_resetted_sigflags(int sig) { +- if(SIGSEGV == sig) { +- return resettedSigflags[0]; +- } else if(SIGBUS == sig) { +- return resettedSigflags[1]; ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ if (SIGNALS[i] == sig) { ++ return resettedSigflags[i]; ++ } + } + return -1; + } + + address VMError::get_resetted_sighandler(int sig) { +- if(SIGSEGV == sig) { +- return resettedSighandler[0]; +- } else if(SIGBUS == sig) { +- return resettedSighandler[1]; ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ if (SIGNALS[i] == sig) { ++ return resettedSighandler[i]; ++ } + } + return NULL; + } +@@ -96,16 +103,25 @@ static void crash_handler(int sig, siginfo_t* info, void* ucVoid) { + sigset_t newset; + sigemptyset(&newset); + sigaddset(&newset, sig); +- sigprocmask(SIG_UNBLOCK, &newset, NULL); ++ // also unmask other synchronous signals ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ sigaddset(&newset, SIGNALS[i]); ++ } ++ thr_sigsetmask(SIG_UNBLOCK, &newset, NULL); + + VMError err(NULL, sig, NULL, info, ucVoid); + err.report_and_die(); + } + + void VMError::reset_signal_handlers() { +- // Save sigflags for resetted signals +- save_signal(0, SIGSEGV); +- save_signal(1, SIGBUS); +- os::signal(SIGSEGV, CAST_FROM_FN_PTR(void *, crash_handler)); +- os::signal(SIGBUS, CAST_FROM_FN_PTR(void *, crash_handler)); ++ // install signal handlers for all synchronous program error signals ++ sigset_t newset; ++ sigemptyset(&newset); ++ ++ for (int i = 0; i < NUM_SIGNALS; i++) { ++ save_signal(i, SIGNALS[i]); ++ os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler)); ++ sigaddset(&newset, SIGNALS[i]); ++ } ++ thr_sigsetmask(SIG_UNBLOCK, &newset, NULL); + } +diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp +index eb13ee0d7..0dab18e1a 100644 +--- a/hotspot/src/share/vm/runtime/globals.hpp ++++ b/hotspot/src/share/vm/runtime/globals.hpp +@@ -916,6 +916,10 @@ class CommandLineFlags { + "determines which error to provoke. See test_error_handler() " \ + "in debug.cpp.") \ + \ ++ notproduct(uintx, TestCrashInErrorHandler, 0, \ ++ "If > 0, provokes an error inside VM error handler (a secondary " \ ++ "crash). see test_error_handler() in debug.cpp.") \ ++ \ + develop(bool, Verbose, false, \ + "Print additional debugging information from other modes") \ + \ +diff --git a/hotspot/src/share/vm/utilities/debug.cpp b/hotspot/src/share/vm/utilities/debug.cpp +index 58a32a2b8..8cea16d32 100644 +--- a/hotspot/src/share/vm/utilities/debug.cpp ++++ b/hotspot/src/share/vm/utilities/debug.cpp +@@ -337,13 +337,47 @@ bool is_error_reported() { + #ifndef PRODUCT + #include + ++typedef void (*voidfun_t)(); ++// Crash with an authentic sigfpe ++static void crash_with_sigfpe() { ++ // generate a native synchronous SIGFPE where possible; ++ // if that did not cause a signal (e.g. on ppc), just ++ // raise the signal. ++ volatile int x = 0; ++ volatile int y = 1/x; ++#ifndef _WIN32 ++ raise(SIGFPE); ++#endif ++} // end: crash_with_sigfpe ++ ++// crash with sigsegv at non-null address. ++static void crash_with_segfault() { ++ ++ char* const crash_addr = (char*) get_segfault_address(); ++ *crash_addr = 'X'; ++ ++} // end: crash_with_segfault ++ ++// returns an address which is guaranteed to generate a SIGSEGV on read, ++// for test purposes, which is not NULL and contains bits in every word ++void* get_segfault_address() { ++ return (void*) ++#ifdef _LP64 ++ 0xABC0000000000ABCULL; ++#else ++ 0x00000ABC; ++#endif ++} ++ + void test_error_handler() { +- uintx test_num = ErrorHandlerTest; +- if (test_num == 0) return; ++ controlled_crash(ErrorHandlerTest); ++} ++ ++void controlled_crash(int how) { ++ if (how == 0) return; + + // If asserts are disabled, use the corresponding guarantee instead. +- size_t n = test_num; +- NOT_DEBUG(if (n <= 2) n += 2); ++ NOT_DEBUG(if (how <= 2) how += 2); + + const char* const str = "hello"; + const size_t num = (size_t)os::vm_page_size(); +@@ -354,7 +388,7 @@ void test_error_handler() { + const void (*funcPtr)(void) = (const void(*)()) 0xF; // bad function pointer + + // Keep this in sync with test/runtime/6888954/vmerrors.sh. +- switch (n) { ++ switch (how) { + case 1: assert(str == NULL, "expected null"); + case 2: assert(num == 1023 && *str == 'X', + err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); +@@ -379,8 +413,10 @@ void test_error_handler() { + // There's no guarantee the bad function pointer will crash us + // so "break" out to the ShouldNotReachHere(). + case 13: (*funcPtr)(); break; ++ case 14: crash_with_segfault(); break; ++ case 15: crash_with_sigfpe(); break; + +- default: tty->print_cr("ERROR: %d: unexpected test_num value.", n); ++ default: tty->print_cr("ERROR: %d: unexpected test_num value.", how); + } + ShouldNotReachHere(); + } +diff --git a/hotspot/src/share/vm/utilities/debug.hpp b/hotspot/src/share/vm/utilities/debug.hpp +index 3c3f8afe2..7a5e1523b 100644 +--- a/hotspot/src/share/vm/utilities/debug.hpp ++++ b/hotspot/src/share/vm/utilities/debug.hpp +@@ -266,6 +266,24 @@ void set_error_reported(); + /* Test assert(), fatal(), guarantee(), etc. */ + NOT_PRODUCT(void test_error_handler();) + ++// crash in a controlled way: ++// how can be one of: ++// 1,2 - asserts ++// 3,4 - guarantee ++// 5-7 - fatal ++// 8 - vm_exit_out_of_memory ++// 9 - ShouldNotCallThis ++// 10 - ShouldNotReachHere ++// 11 - Unimplemented ++// 12,13 - (not guaranteed) crashes ++// 14 - SIGSEGV ++// 15 - SIGFPE ++NOT_PRODUCT(void controlled_crash(int how);) ++ ++// returns an address which is guaranteed to generate a SIGSEGV on read, ++// for test purposes, which is not NULL and contains bits in every word ++NOT_PRODUCT(void* get_segfault_address();) ++ + void pd_ps(frame f); + void pd_obfuscate_location(char *buf, size_t buflen); + +diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp +index aa0b63a80..9b40a3468 100644 +--- a/hotspot/src/share/vm/utilities/vmError.cpp ++++ b/hotspot/src/share/vm/utilities/vmError.cpp +@@ -397,6 +397,26 @@ void VMError::report(outputStream* st) { + "Runtime Environment to continue."); + } + ++#ifndef PRODUCT ++ // Error handler self tests ++ ++ // test secondary error handling. Test it twice, to test that resetting ++ // error handler after a secondary crash works. ++ STEP(13, "(test secondary crash 1)") ++ if (_verbose && TestCrashInErrorHandler != 0) { ++ st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...", ++ TestCrashInErrorHandler); ++ controlled_crash(TestCrashInErrorHandler); ++ } ++ ++ STEP(14, "(test secondary crash 2)") ++ if (_verbose && TestCrashInErrorHandler != 0) { ++ st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...", ++ TestCrashInErrorHandler); ++ controlled_crash(TestCrashInErrorHandler); ++ } ++#endif // PRODUCT ++ + STEP(15, "(printing type of error)") + + switch(static_cast(_id)) { +@@ -829,6 +849,15 @@ void VMError::report(outputStream* st) { + st->cr(); + } + ++#ifndef PRODUCT ++ // print a defined marker to show that error handling finished correctly. ++ STEP(290, "(printing end marker)" ) ++ ++ if (_verbose) { ++ st->print_cr("END."); ++ } ++#endif ++ + END + + # undef BEGIN +-- +2.22.0 + diff --git a/openjdk-1.8.0.spec b/openjdk-1.8.0.spec index 134d270..8bf06da 100644 --- a/openjdk-1.8.0.spec +++ b/openjdk-1.8.0.spec @@ -916,7 +916,7 @@ Provides: java-%{javaver}-%{origin}-accessibility%{?1} = %{epoch}:%{version}-%{r Name: java-%{javaver}-%{origin} Version: %{javaver}.%{updatever}.%{buildver} -Release: 2 +Release: 3 # java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons # and this change was brought into RHEL-4. java-1.5.0-ibm packages # also included the epoch in their virtual provides. This created a @@ -1151,7 +1151,7 @@ Patch264: 8287109-Distrust-failed-with-CertificateExpired.patch # 8u352 Patch265: cve-2022-37434-Fix-a-bug-when-getting-a-gzip-header-extra-field-with-inflate.patch - +Patch266: 8065895-Synchronous-signals-during-error-reporting-may-terminate-or-hang-vm-process.patch ############################################# # @@ -1643,6 +1643,7 @@ pushd %{top_level_dir_name} %patch263 -p1 %patch264 -p1 %patch265 -p1 +%patch266 -p1 popd # System library fixes @@ -2267,6 +2268,9 @@ cjc.mainProgram(arg) %endif %changelog +* Mon Oct 24 2022 kuenking111 - 1:1.8.0.352-b08.3 +- add 8065895-Synchronous-signals-during-error-reporting-may-terminate-or-hang-vm-process.patch + * Mon Oct 24 2022 kuenking111 - 1:1.8.0.352-b08.2 - add cve-2022-37434-Fix-a-bug-when-getting-a-gzip-header-extra-field-with-inflate.patch -- Gitee