From 0e8fec37da9cf57066d72798633fe1fd31481ece Mon Sep 17 00:00:00 2001 Subject: Enable TLS to communciation between JBooster Server and Client JVM --- .../linux/jbooster/net/clientStream_linux.cpp | 54 ++++ .../net/serverListeningThread_linux.cpp | 64 ++++- src/hotspot/share/cds/filemap.cpp | 2 +- src/hotspot/share/include/jvm.h | 5 +- .../jbooster/client/clientDataManager.cpp | 79 +++--- .../jbooster/client/clientDataManager.hpp | 16 +- .../jbooster/client/clientMessageHandler.cpp | 6 +- .../share/jbooster/jBoosterManager.cpp | 1 + .../share/jbooster/jBoosterSymbols.hpp | 1 + .../share/jbooster/jClientArguments.cpp | 36 +-- .../share/jbooster/jClientArguments.hpp | 32 ++- src/hotspot/share/jbooster/jClientVMFlags.cpp | 19 +- src/hotspot/share/jbooster/jClientVMFlags.hpp | 11 +- .../share/jbooster/jbooster_globals.hpp | 3 + .../share/jbooster/net/clientStream.cpp | 48 +++- .../share/jbooster/net/clientStream.hpp | 6 + .../jbooster/net/communicationStream.cpp | 37 ++- .../jbooster/net/communicationStream.hpp | 12 +- src/hotspot/share/jbooster/net/errorCode.hpp | 1 + .../jbooster/net/serverListeningThread.cpp | 55 ++++- .../jbooster/net/serverListeningThread.hpp | 13 +- .../share/jbooster/net/serverStream.cpp | 31 +-- .../share/jbooster/net/serverStream.hpp | 6 +- src/hotspot/share/jbooster/net/sslUtils.cpp | 231 ++++++++++++++++++ src/hotspot/share/jbooster/net/sslUtils.hpp | 148 +++++++++++ .../jbooster/server/serverDataManager.cpp | 42 ++-- .../jbooster/server/serverDataManager.hpp | 30 ++- .../jbooster/server/serverDataManagerLog.cpp | 17 +- .../jbooster/server/serverMessageHandler.cpp | 30 ++- src/hotspot/share/prims/jvm.cpp | 16 +- src/hotspot/share/runtime/java.cpp | 2 +- .../share/classes/jdk/jbooster/JBooster.java | 11 +- .../share/classes/jdk/jbooster/Options.java | 22 ++ .../share/native/libjbooster/JBooster.c | 8 +- test/jdk/tools/jbooster/JBoosterCmdTest.java | 2 +- test/jdk/tools/jbooster/JBoosterNetTest.java | 2 +- test/jdk/tools/jbooster/JBoosterSSLTest.java | 152 ++++++++++++ .../jbooster/JBoosterSharedCacheTest.java | 150 ++++++++++++ test/jdk/tools/jbooster/JBoosterTestBase.java | 6 +- test/jdk/tools/jbooster/server-cert.pem | 22 ++ test/jdk/tools/jbooster/server-key.pem | 27 ++ test/jdk/tools/jbooster/unrelated-cert.pem | 22 ++ 42 files changed, 1243 insertions(+), 235 deletions(-) create mode 100644 src/hotspot/share/jbooster/net/sslUtils.cpp create mode 100644 src/hotspot/share/jbooster/net/sslUtils.hpp create mode 100644 test/jdk/tools/jbooster/JBoosterSSLTest.java create mode 100644 test/jdk/tools/jbooster/JBoosterSharedCacheTest.java create mode 100644 test/jdk/tools/jbooster/server-cert.pem create mode 100644 test/jdk/tools/jbooster/server-key.pem create mode 100644 test/jdk/tools/jbooster/unrelated-cert.pem diff --git a/src/hotspot/os/linux/jbooster/net/clientStream_linux.cpp b/src/hotspot/os/linux/jbooster/net/clientStream_linux.cpp index 6425ef0f2..d0b43506d 100644 --- a/src/hotspot/os/linux/jbooster/net/clientStream_linux.cpp +++ b/src/hotspot/os/linux/jbooster/net/clientStream_linux.cpp @@ -28,7 +28,9 @@ #include "jbooster/net/clientStream.hpp" #include "jbooster/net/errorCode.hpp" +#include "jbooster/net/sslUtils.hpp" #include "logging/log.hpp" +#include "runtime/java.hpp" #include "runtime/os.hpp" #define LOG_INNER(socket_fd, address, port, err_code, format, args...) \ @@ -142,3 +144,55 @@ int ClientStream::try_to_connect_once(int* res_fd, const char* address, const ch *res_fd = -1; return res_err; } + +int ClientStream::try_to_ssl_connect(SSL** res_ssl, int conn_fd) { + errno = 0; + + SSL* ssl = nullptr; + do { + SSL* ssl = SSLUtils::ssl_new(_client_ssl_ctx); + if (ssl == nullptr) { + log_error(jbooster, rpc)("Failed to get SSL."); + break; + } + + int ret = 0; + if (ret = SSLUtils::ssl_set_fd(ssl, conn_fd) != 1) { + SSLUtils::handle_ssl_error(ssl, ret, "Failed to set SSL file descriptor"); + break; + } + + if (ret = SSLUtils::ssl_connect(ssl) != 1) { + SSLUtils::handle_ssl_error(ssl, ret, "Failed to build SSL connection"); + break; + } + + if (!verify_cert(ssl)) { + break; + } + + // success + assert(errno == 0, "why errno=%s", JBErr::err_name(errno)); + *res_ssl = ssl; + return 0; + } while (false); + + // fail + int res_err = JBErr::BAD_SSL; + SSLUtils::shutdown_and_free_ssl(ssl); + return res_err; +} + +bool ClientStream::verify_cert(SSL* ssl) { + X509* cert = SSLUtils::ssl_get_peer_certificate(ssl); + if ((cert == nullptr)) { + log_error(jbooster, rpc)("Server cert unspecified."); + return false; + } + int res = SSLUtils::ssl_get_verify_result(ssl); + if (res != X509_V_OK) { + log_error(jbooster, rpc)("Failed to verify server cert."); + return false; + } + return true; +} diff --git a/src/hotspot/os/linux/jbooster/net/serverListeningThread_linux.cpp b/src/hotspot/os/linux/jbooster/net/serverListeningThread_linux.cpp index bc3eae5b0..073052e72 100644 --- a/src/hotspot/os/linux/jbooster/net/serverListeningThread_linux.cpp +++ b/src/hotspot/os/linux/jbooster/net/serverListeningThread_linux.cpp @@ -28,8 +28,10 @@ #include "jbooster/net/errorCode.hpp" #include "jbooster/net/serverListeningThread.hpp" +#include "jbooster/net/sslUtils.hpp" #include "logging/log.hpp" #include "runtime/interfaceSupport.inline.hpp" +#include "runtime/java.hpp" static int init_server_socket_opts(int socket_fd) { // enable reuse of address @@ -105,6 +107,56 @@ static int bind_address(const char* address, uint16_t port) { return socket_fd; } +static SSL* try_to_ssl_connect(int conn_fd, SSL_CTX* ssl_ctx) { + SSL* ssl = SSLUtils::ssl_new(ssl_ctx); + if (ssl == nullptr) { + log_error(jbooster, rpc)("Failed to get SSL."); + os::close(conn_fd); + return nullptr; + } + + int ret = 0; + const char* error_description = nullptr; + if (ret = SSLUtils::ssl_set_fd(ssl, conn_fd) != 1) { + error_description = "Failed to set SSL file descriptor"; + } else if (ret = SSLUtils::ssl_accept(ssl) != 1) { + error_description = "Failed to accept SSL connection"; + } + + if (error_description != nullptr) { + SSLUtils::handle_ssl_error(ssl, ret, error_description); + SSLUtils::shutdown_and_free_ssl(ssl); + os::close(conn_fd); + return nullptr; + } + + log_info(jbooster, rpc)("Succeeded to build SSL connection."); + return ssl; +} + +bool ServerListeningThread::prepare_and_handle_new_connection(int server_fd, sockaddr_in* acc_addr, socklen_t* acc_addrlen, TRAPS) { + int conn_fd = accept(server_fd, (sockaddr*)acc_addr, acc_addrlen); + if (conn_fd < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + log_error(jbooster, rpc)("Failed to accept: %s.", strerror(errno)); + } + return false; + } + if (init_accepted_socket_opts(conn_fd, _timeout_ms) < 0) { + return false; + } + + SSL* ssl = nullptr; + if (_server_ssl_ctx != nullptr) { + ssl = try_to_ssl_connect(conn_fd, _server_ssl_ctx); + if (ssl == nullptr) { + return false; + } + } + handle_new_connection(conn_fd, ssl, THREAD); + return true; +} + /** * Keep listening for client requests. */ @@ -138,19 +190,15 @@ int ServerListeningThread::run_listener(TRAPS) { } while (!get_exit_flag()) { - int conn_fd = accept(server_fd, (sockaddr*)&acc_addr, &acc_addrlen); - if (conn_fd < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - log_error(jbooster, rpc)("Failed to accept: %s.", strerror(errno)); - } + if (!prepare_and_handle_new_connection(server_fd, &acc_addr, &acc_addrlen, THREAD)) { break; } - if (init_accepted_socket_opts(conn_fd, _timeout_ms) < 0) break; - - handle_new_connection(conn_fd, THREAD); } } + if (_server_ssl_ctx != nullptr) { + SSLUtils::ssl_ctx_free(_server_ssl_ctx); + } close(server_fd); log_debug(jbooster, rpc)("The JBooster server listener thread stopped."); return 0; diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 1fe0adbe5..76e078d12 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1216,7 +1216,7 @@ void FileMapInfo::open_for_write(const char* path) { int fd; #if INCLUDE_JBOOSTER - if (UseJBooster && ClientDataManager::get().is_cds_allowed()) { + if (UseJBooster && ClientDataManager::get().boost_level().is_cds_allowed()) { // The _full_path points to the tmp file in the JBooster environment. // The tmp file should have been created before (see dump_cds() in // clientMessageHandler.cpp). So do not remove it or try to create it. diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 488ad25ce..7c917a240 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -1105,13 +1105,14 @@ JVM_GetEnclosingMethodInfo(JNIEnv* env, jclass ofClass); * Init the JBooster server in Hotspot. */ JNIEXPORT void JNICALL -JVM_JBoosterInitVM(JNIEnv *env, jint server_port, jint connection_timeout, jint cleanup_timeout, jstring cache_path); +JVM_JBoosterInitVM(JNIEnv *env, jint server_port, jint connection_timeout, jint cleanup_timeout, + jstring cache_path, jstring ssl_key, jstring ssl_cert); /** * Handle a TCP connection. */ JNIEXPORT void JNICALL -JVM_JBoosterHandleConnection(JNIEnv *env, jint connection_fd); +JVM_JBoosterHandleConnection(JNIEnv *env, jint connection_fd, jlong connection_ssl); /** * Print data in ServerDataManager. diff --git a/src/hotspot/share/jbooster/client/clientDataManager.cpp b/src/hotspot/share/jbooster/client/clientDataManager.cpp index 0504dc656..3fbe143a8 100644 --- a/src/hotspot/share/jbooster/client/clientDataManager.cpp +++ b/src/hotspot/share/jbooster/client/clientDataManager.cpp @@ -27,6 +27,7 @@ #include "jbooster/client/clientDataManager.hpp" #include "jbooster/client/clientStartupSignal.hpp" #include "jbooster/net/clientStream.hpp" +#include "jbooster/net/sslUtils.hpp" #include "logging/log.hpp" #include "runtime/arguments.hpp" #include "runtime/globals_extension.hpp" @@ -43,15 +44,9 @@ ClientDataManager::ClientDataManager() { _program_str_id = nullptr; _cache_dir_path = nullptr; - _allow_aot = false; - _allow_cds = false; - _allow_clr = false; - _allow_pgo = false; - _using_aot = false; _using_cds = false; _using_clr = false; - _using_pgo = false; _cache_clr_path = nullptr; _cache_cds_path = nullptr; @@ -81,25 +76,32 @@ void ClientDataManager::init_client_vm_options() { if (!FLAG_IS_DEFAULT(UseBoostPackages)) { if (strcmp(UseBoostPackages, "all") == 0) { - _allow_clr = _allow_cds = _allow_aot = _allow_pgo = true; + _boost_level.set_allow_clr(true); + _boost_level.set_allow_cds(true); + _boost_level.set_allow_aot(true); + _boost_level.set_enable_aot_pgo(true); } else { - _allow_clr = is_option_on("UseBoostPackages", UseBoostPackages, "clr"); - _allow_cds = is_option_on("UseBoostPackages", UseBoostPackages, "cds"); - _allow_aot = is_option_on("UseBoostPackages", UseBoostPackages, "aot"); - _allow_pgo = is_option_on("UseBoostPackages", UseBoostPackages, "pgo"); - if (_allow_pgo) _allow_aot = true; + _boost_level.set_allow_clr(is_option_on("UseBoostPackages", UseBoostPackages, "clr")); + _boost_level.set_allow_cds(is_option_on("UseBoostPackages", UseBoostPackages, "cds")); + _boost_level.set_allow_aot(is_option_on("UseBoostPackages", UseBoostPackages, "aot")); + _boost_level.set_enable_aot_pgo(is_option_on("UseBoostPackages", UseBoostPackages, "pgo")); + if (_boost_level.is_aot_pgo_enabled()) _boost_level.set_allow_aot(true); } } else { switch (BoostStopAtLevel) { - case 4: _allow_pgo = true; - case 3: _allow_aot = true; - case 2: _allow_cds = true; - case 1: _allow_clr = true; + case 4: _boost_level.set_enable_aot_pgo(true); + case 3: _boost_level.set_allow_aot(true); + case 2: _boost_level.set_allow_cds(true); + case 1: _boost_level.set_allow_clr(true); case 0: break; default: break; } } + if (FLAG_IS_DEFAULT(UseAggressiveCDS) || UseAggressiveCDS) { + _boost_level.set_enable_cds_agg(true); + } + if (JBoosterStartupSignal != nullptr) { ClientStartupSignal::init_phase1(); } @@ -113,17 +115,23 @@ void ClientDataManager::init_const() { _program_args->is_jar(), _program_args->hash()); _cache_clr_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, "clr.log"); - _cache_cds_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, "cds.jsa"); - const char* aot_path_suffix = _allow_pgo ? "aot-pgo.so" : "aot.so"; + const char* cds_path_suffix = _boost_level.is_cds_agg_enabled() ? "cds-agg.jsa" : "cds-dy.jsa"; + _cache_cds_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, cds_path_suffix); + const char* aot_path_suffix = _boost_level.is_aot_pgo_enabled() ? "aot-pgo.so" : "aot-static.so"; _cache_aot_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, aot_path_suffix); } void ClientDataManager::init_client_duty() { + if (JBoosterServerSSLRootCerts) { + if (!SSLUtils::init_ssl_lib()) { + vm_exit_during_initialization("Failed to load all functions from OpenSSL Dynamic Library."); + } + ClientStream::client_init_ssl_ctx(JBoosterServerSSLRootCerts); + } // Connect to jbooster before initializing CDS, before loading java_lang_classes // and before starting the compiler threads. ClientStream client_stream(JBoosterAddress, JBoosterPort, JBoosterTimeout, nullptr); int rpc_err = client_stream.connect_and_init_session(&_using_clr, &_using_cds, &_using_aot); - if (_using_aot && _allow_pgo) _using_pgo = true; set_server_available(rpc_err == 0); } @@ -132,11 +140,10 @@ void ClientDataManager::init_client_duty_under_local_mode() { _using_clr = FileUtils::is_file(_cache_clr_path); _using_cds = FileUtils::is_file(_cache_cds_path); _using_aot = FileUtils::is_file(_cache_aot_path); - if (_using_aot && _allow_pgo) _using_pgo = true; } jint ClientDataManager::init_clr_options() { - if (!is_clr_allowed()) return JNI_OK; + if (!_boost_level.is_clr_allowed()) return JNI_OK; if (FLAG_SET_CMDLINE(UseClassLoaderResourceCache, true) != JVMFlag::SUCCESS) { return JNI_EINVAL; @@ -156,10 +163,14 @@ jint ClientDataManager::init_clr_options() { } jint ClientDataManager::init_cds_options() { - if (!is_cds_allowed()) return JNI_OK; + if (!_boost_level.is_cds_allowed()) return JNI_OK; + + if (FLAG_IS_CMDLINE(SharedArchiveFile) || FLAG_IS_CMDLINE(ArchiveClassesAtExit) || FLAG_IS_CMDLINE(SharedArchiveConfigFile)) { + vm_exit_during_initialization("Do not set CDS path manually whe using JBooster."); + } - if (FLAG_IS_CMDLINE(SharedArchiveFile) || FLAG_IS_CMDLINE(ArchiveClassesAtExit)) { - vm_exit_during_initialization("Do not set CDS manually whe using JBooster."); + if (FLAG_IS_CMDLINE(DynamicDumpSharedSpaces) || FLAG_IS_CMDLINE(DumpSharedSpaces) || FLAG_IS_CMDLINE(UseSharedSpaces)) { + vm_exit_during_initialization("Do not set dump/load CDS manually whe using JBooster."); } if (is_cds_being_used()) { @@ -197,7 +208,7 @@ jint ClientDataManager::init_cds_options() { } jint ClientDataManager::init_aot_options() { - if (!is_aot_allowed()) return JNI_OK; + if (!_boost_level.is_aot_allowed()) return JNI_OK; if (FLAG_SET_CMDLINE(UseAOT, true) != JVMFlag::SUCCESS) { return JNI_EINVAL; } @@ -210,7 +221,7 @@ jint ClientDataManager::init_aot_options() { } jint ClientDataManager::init_pgo_options() { - if (!is_pgo_allowed()) return JNI_OK; + if (!_boost_level.is_aot_pgo_enabled()) return JNI_OK; if (FLAG_SET_CMDLINE(TypeProfileWidth, 8) != JVMFlag::SUCCESS) { return JNI_EINVAL; } @@ -220,13 +231,11 @@ jint ClientDataManager::init_pgo_options() { void ClientDataManager::print_init_state() { log_info(jbooster)("Using boost packages:\n" " - CLR: allowed_to_use=%s,\tis_being_used=%s\n" - " - CDS: allowed_to_use=%s,\tis_being_used=%s\n" - " - AOT: allowed_to_use=%s,\tis_being_used=%s\n" - " - PGO: allowed_to_use=%s,\tis_being_used=%s", - BOOL_TO_STR(is_clr_allowed()), BOOL_TO_STR(is_clr_being_used()), - BOOL_TO_STR(is_cds_allowed()), BOOL_TO_STR(is_cds_being_used()), - BOOL_TO_STR(is_aot_allowed()), BOOL_TO_STR(is_aot_being_used()), - BOOL_TO_STR(is_pgo_allowed()), BOOL_TO_STR(is_pgo_being_used())); + " - CDS: allowed_to_use=%s,\tis_being_used=%s,\tis_aggressive_cds_enabled=%s\n" + " - AOT: allowed_to_use=%s,\tis_being_used=%s,\tis_pgo_aot_enabled=%s\n", + BOOL_TO_STR(_boost_level.is_clr_allowed()), BOOL_TO_STR(is_clr_being_used()), + BOOL_TO_STR(_boost_level.is_cds_allowed()), BOOL_TO_STR(is_cds_being_used()), BOOL_TO_STR(_boost_level.is_cds_agg_enabled()), + BOOL_TO_STR(_boost_level.is_aot_allowed()), BOOL_TO_STR(is_aot_being_used()), BOOL_TO_STR(_boost_level.is_aot_pgo_enabled())); } static void check_jbooster_port() { @@ -328,7 +337,7 @@ void ClientDataManager::init_phase2(TRAPS) { } ClientDaemonThread::start_thread(CHECK); - if (_singleton->is_clr_allowed()) { + if (_singleton->_boost_level.is_clr_allowed()) { Klass* klass = SystemDictionary::resolve_or_fail(vmSymbols::java_net_ClassLoaderResourceCache(), true, CHECK); InstanceKlass::cast(klass)->initialize(CHECK); } @@ -339,7 +348,7 @@ jint ClientDataManager::escape() { return JNI_EINVAL; } - if(!JBoosterLocalMode){ + if (!JBoosterLocalMode) { log_error(jbooster)("Rolled back to the original path (UseJBooster=false), since the server is unavailable."); } return JNI_OK; diff --git a/src/hotspot/share/jbooster/client/clientDataManager.hpp b/src/hotspot/share/jbooster/client/clientDataManager.hpp index 07be0dc2a..da4a8cacb 100644 --- a/src/hotspot/share/jbooster/client/clientDataManager.hpp +++ b/src/hotspot/share/jbooster/client/clientDataManager.hpp @@ -39,15 +39,11 @@ class ClientDataManager: public CHeapObj { const char* _program_str_id; const char* _cache_dir_path; - bool _allow_clr; - bool _allow_cds; - bool _allow_aot; - bool _allow_pgo; + JClientBoostLevel _boost_level; bool _using_clr; bool _using_cds; bool _using_aot; - bool _using_pgo; const char* _cache_clr_path; const char* _cache_cds_path; @@ -102,21 +98,17 @@ public: // $HOME/.jbooster/client const char* cache_dir_path() { return _cache_dir_path; } - bool is_clr_allowed() { return _allow_clr; } - bool is_cds_allowed() { return _allow_cds; } - bool is_aot_allowed() { return _allow_aot; } - bool is_pgo_allowed() { return _allow_pgo; } + JClientBoostLevel& boost_level() { return _boost_level; } bool is_clr_being_used() { return _using_clr; } bool is_cds_being_used() { return _using_cds; } bool is_aot_being_used() { return _using_aot; } - bool is_pgo_being_used() { return _using_pgo; } // /client/cache--clr.log const char* cache_clr_path() { return _cache_clr_path; } - // /client/cache--cds.jsa + // /client/cache--cds-[dy|agg].jsa const char* cache_cds_path() { return _cache_cds_path; } - // /client/cache--aot[-pgo].so + // /client/cache--aot-[static|pgo].so const char* cache_aot_path() { return _cache_aot_path; } uint32_t session_id() { return _session_id; } diff --git a/src/hotspot/share/jbooster/client/clientMessageHandler.cpp b/src/hotspot/share/jbooster/client/clientMessageHandler.cpp index 0ebe350a0..9119b897a 100644 --- a/src/hotspot/share/jbooster/client/clientMessageHandler.cpp +++ b/src/hotspot/share/jbooster/client/clientMessageHandler.cpp @@ -87,7 +87,7 @@ void ClientMessageHandler::trigger_cache_generation_tasks(TriggerTaskPhase phase ClientMessageHandler msg_handler(client_stream); bool cache_file_task = false; - if (ClientDataManager::get().is_clr_allowed() || ClientDataManager::get().is_cds_allowed()) { + if (ClientDataManager::get().boost_level().is_clr_allowed() || ClientDataManager::get().boost_level().is_cds_allowed()) { cache_file_task = (phase == ON_SHUTDOWN); } if (cache_file_task) { @@ -95,7 +95,7 @@ void ClientMessageHandler::trigger_cache_generation_tasks(TriggerTaskPhase phase } bool lazy_aot_task = false; - if (ClientDataManager::get().is_aot_allowed()) { + if (ClientDataManager::get().boost_level().is_aot_allowed()) { lazy_aot_task = ((phase == ON_STARTUP) || ((phase == ON_SHUTDOWN) && !ClientDataManager::get().is_startup_end())); } if (lazy_aot_task) { @@ -170,7 +170,7 @@ static void dump_cds() { } int ClientMessageHandler::handle_CacheAggressiveCDS() { - if (DynamicDumpSharedSpaces && ClientDataManager::get().is_cds_allowed()) { + if (DynamicDumpSharedSpaces && ClientDataManager::get().boost_level().is_cds_allowed()) { dump_cds(); } FileWrapper file(ClientDataManager::get().cache_cds_path(), diff --git a/src/hotspot/share/jbooster/jBoosterManager.cpp b/src/hotspot/share/jbooster/jBoosterManager.cpp index 64af5e894..2a8995f4a 100644 --- a/src/hotspot/share/jbooster/jBoosterManager.cpp +++ b/src/hotspot/share/jbooster/jBoosterManager.cpp @@ -178,4 +178,5 @@ void JBoosterManager::check_arguments() { check_argument(FLAG_MEMBER_ENUM(JBoosterClientStrictMatch)); check_argument(FLAG_MEMBER_ENUM(PrintAllClassInfo)); check_argument(FLAG_MEMBER_ENUM(CheckClassFileTimeStamp)); + check_argument(FLAG_MEMBER_ENUM(JBoosterServerSSLRootCerts)); } \ No newline at end of file diff --git a/src/hotspot/share/jbooster/jBoosterSymbols.hpp b/src/hotspot/share/jbooster/jBoosterSymbols.hpp index e45bf85aa..4d7f64318 100644 --- a/src/hotspot/share/jbooster/jBoosterSymbols.hpp +++ b/src/hotspot/share/jbooster/jBoosterSymbols.hpp @@ -26,6 +26,7 @@ #define JBOOSTER_TEMPLATES(template) \ template(receiveConnection_name, "receiveConnection") \ + template(receiveConnection_signature, "(IJ)Z") \ template(codesource_signature, "Ljava/security/CodeSource;") \ template(getProtectionDomainByURLString_name, "getProtectionDomainByURLString") \ template(getProtectionDomainByURLString_signature, "(Ljava/lang/String;)Ljava/security/ProtectionDomain;") \ diff --git a/src/hotspot/share/jbooster/jClientArguments.cpp b/src/hotspot/share/jbooster/jClientArguments.cpp index 1ae91674f..37093d031 100644 --- a/src/hotspot/share/jbooster/jClientArguments.cpp +++ b/src/hotspot/share/jbooster/jClientArguments.cpp @@ -209,10 +209,6 @@ void JClientArguments::init_for_client() { } else { _java_commands = StringUtils::copy_to_heap("", mtJBooster); } - _jbooster_allow_clr = ClientDataManager::get().is_clr_allowed(); - _jbooster_allow_cds = ClientDataManager::get().is_cds_allowed(); - _jbooster_allow_aot = ClientDataManager::get().is_aot_allowed(); - _jbooster_allow_pgo = ClientDataManager::get().is_pgo_allowed(); _related_flags = new JClientVMFlags(true); _hash = calc_hash(); @@ -232,11 +228,7 @@ uint32_t JClientArguments::calc_hash() { result = calc_new_hash(result, _classpath_timestamp_hash); result = calc_new_hash(result, _agent_name_hash); result = calc_new_hash(result, StringUtils::hash_code(_java_commands)); - result = calc_new_hash(result, primitive_hash(_jbooster_allow_clr)); - result = calc_new_hash(result, primitive_hash(_jbooster_allow_cds)); - result = calc_new_hash(result, primitive_hash(_jbooster_allow_aot)); - result = calc_new_hash(result, primitive_hash(_jbooster_allow_pgo)); - result = calc_new_hash(result, _related_flags->hash(_jbooster_allow_clr, _jbooster_allow_cds, _jbooster_allow_aot)); + result = calc_new_hash(result, _related_flags->hash()); return result; } @@ -255,14 +247,7 @@ bool JClientArguments::equals(const JClientArguments* that) const { if (this->_classpath_timestamp_hash != that->_classpath_timestamp_hash) return false; if (this->_agent_name_hash != that->_agent_name_hash) return false; if (StringUtils::compare(this->_java_commands, that->_java_commands) != 0) return false; - if (this->_jbooster_allow_clr != that->_jbooster_allow_clr) return false; - if (this->_jbooster_allow_cds != that->_jbooster_allow_cds) return false; - if (this->_jbooster_allow_aot != that->_jbooster_allow_aot) return false; - if (this->_jbooster_allow_pgo != that->_jbooster_allow_pgo) return false; - if (!this->_related_flags->equals(that->_related_flags, - _jbooster_allow_clr, - _jbooster_allow_cds, - _jbooster_allow_aot)) return false; + if (!this->_related_flags->equals(that->_related_flags)) return false; return true; } @@ -279,14 +264,8 @@ void JClientArguments::print_args(outputStream* st) const { st->print_cr(" classpath_timestamp_hash: %x", _classpath_timestamp_hash); st->print_cr(" agent_name_hash: %x", _agent_name_hash); st->print_cr(" java_commands: \"%s\"", _java_commands); - st->print_cr(" allow_clr: %s", BOOL_TO_STR(_jbooster_allow_clr)); - st->print_cr(" allow_cds: %s", BOOL_TO_STR(_jbooster_allow_cds)); - st->print_cr(" allow_aot: %s", BOOL_TO_STR(_jbooster_allow_aot)); - st->print_cr(" allow_pgo: %s", BOOL_TO_STR(_jbooster_allow_pgo)); st->print_cr(" vm_flags:"); - st->print_cr(" hash: %u", _related_flags->hash(_jbooster_allow_clr, - _jbooster_allow_cds, - _jbooster_allow_aot)); + st->print_cr(" hash: %u", _related_flags->hash()); _related_flags->print_flags(st); } @@ -308,10 +287,6 @@ int JClientArguments::serialize(MessageBuffer& buf) const { JB_RETURN(buf.serialize_no_meta(_classpath_timestamp_hash)); JB_RETURN(buf.serialize_no_meta(_agent_name_hash)); JB_RETURN(buf.serialize_with_meta(&_java_commands)); - JB_RETURN(buf.serialize_no_meta(_jbooster_allow_clr)); - JB_RETURN(buf.serialize_no_meta(_jbooster_allow_cds)); - JB_RETURN(buf.serialize_no_meta(_jbooster_allow_aot)); - JB_RETURN(buf.serialize_no_meta(_jbooster_allow_pgo)); JB_RETURN(buf.serialize_with_meta(_related_flags)); JB_RETURN(buf.serialize_no_meta(_hash)); @@ -351,11 +326,6 @@ int JClientArguments::deserialize(MessageBuffer& buf) { JB_RETURN(buf.deserialize_with_meta(&sw_java_commands)); _java_commands = sw_java_commands.export_string(); - JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_clr)); - JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_cds)); - JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_aot)); - JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_pgo)); - _related_flags = new JClientVMFlags(false); JB_RETURN(buf.deserialize_with_meta(_related_flags)); diff --git a/src/hotspot/share/jbooster/jClientArguments.hpp b/src/hotspot/share/jbooster/jClientArguments.hpp index 7a0db1738..be057a07d 100644 --- a/src/hotspot/share/jbooster/jClientArguments.hpp +++ b/src/hotspot/share/jbooster/jClientArguments.hpp @@ -27,6 +27,30 @@ #include "jbooster/jClientVMFlags.hpp" #include "jbooster/net/serialization.hpp" +class JClientBoostLevel { + bool _allow_clr; + bool _allow_cds; + bool _allow_aot; + bool _enable_aot_pgo; + bool _enable_cds_agg; + +public: + JClientBoostLevel(): _allow_clr(false), _allow_cds(false), _allow_aot(false), _enable_aot_pgo(false), _enable_cds_agg(false) {} + JClientBoostLevel(const JClientBoostLevel& level) = default; + + bool is_clr_allowed() const { return _allow_clr; } + bool is_cds_allowed() const { return _allow_cds; } + bool is_aot_allowed() const { return _allow_aot; } + bool is_aot_pgo_enabled() const {return _enable_aot_pgo; } + bool is_cds_agg_enabled() const {return _enable_cds_agg; } + + void set_allow_clr(bool allow_clr) { _allow_clr = allow_clr; } + void set_allow_cds(bool allow_cds) { _allow_cds = allow_cds; } + void set_allow_aot(bool allow_aot) { _allow_aot = allow_aot; } + void set_enable_aot_pgo(bool enable_aot_pgo) { _enable_aot_pgo = enable_aot_pgo; } + void set_enable_cds_agg(bool enable_cds_agg) { _enable_cds_agg = enable_cds_agg; } +}; + /** * Arguments that identify a program. */ @@ -64,10 +88,6 @@ private: uint32_t _classpath_timestamp_hash; uint32_t _agent_name_hash; const char* _java_commands; - bool _jbooster_allow_clr; - bool _jbooster_allow_cds; - bool _jbooster_allow_aot; - bool _jbooster_allow_pgo; JClientVMFlags* _related_flags; // ========================= end ========================= @@ -93,10 +113,6 @@ public: uint32_t classpath_timestamp_hash() const { return _classpath_timestamp_hash; } uint32_t agent_name_hash() const { return _agent_name_hash; } const char* java_commands() const { return _java_commands; } - bool jbooster_allow_clr() const { return _jbooster_allow_clr; } - bool jbooster_allow_cds() const { return _jbooster_allow_cds; } - bool jbooster_allow_aot() const { return _jbooster_allow_aot; } - bool jbooster_allow_pgo() const { return _jbooster_allow_pgo; } JClientVMFlags* related_flags() const { return _related_flags; } bool equals(const JClientArguments* that) const; diff --git a/src/hotspot/share/jbooster/jClientVMFlags.cpp b/src/hotspot/share/jbooster/jClientVMFlags.cpp index 6e46aeb48..570c1b64c 100644 --- a/src/hotspot/share/jbooster/jClientVMFlags.cpp +++ b/src/hotspot/share/jbooster/jClientVMFlags.cpp @@ -125,28 +125,17 @@ JClientVMFlags::~JClientVMFlags() { #undef FREE_FLAG } -bool JClientVMFlags::equals(JClientVMFlags* that, bool allow_clr, bool allow_cds, bool allow_aot) { +bool JClientVMFlags::equals(JClientVMFlags* that) { #define CMP_FLAG(type, flag) if (!FlagTypeHandler::equals(this->v_##flag, that->v_##flag)) return false; - if (allow_cds) { - JCLIENT_CDS_VM_FLAGS(CMP_FLAG) - } - if (allow_aot) { - JCLIENT_AOT_VM_FLAGS(CMP_FLAG) - } + JCLIENT_VM_FLAGS(CMP_FLAG) #undef CMP_FLAG - return true; } -uint32_t JClientVMFlags::hash(bool allow_clr, bool allow_cds, bool allow_aot) { +uint32_t JClientVMFlags::hash() { uint32_t result = 1; #define CALC_FLAG_HASH(type, flag) result = 31 * result + FlagTypeHandler::hash(v_##flag); - if (allow_cds) { - JCLIENT_CDS_VM_FLAGS(CALC_FLAG_HASH) - } - if (allow_aot) { - JCLIENT_AOT_VM_FLAGS(CALC_FLAG_HASH) - } + JCLIENT_VM_FLAGS(CALC_FLAG_HASH) #undef CALC_FLAG_HASH return result; } diff --git a/src/hotspot/share/jbooster/jClientVMFlags.hpp b/src/hotspot/share/jbooster/jClientVMFlags.hpp index 71da58934..9d203d041 100644 --- a/src/hotspot/share/jbooster/jClientVMFlags.hpp +++ b/src/hotspot/share/jbooster/jClientVMFlags.hpp @@ -29,14 +29,7 @@ #include "runtime/globals_extension.hpp" #define JCLIENT_CDS_VM_FLAGS(f) \ - f(bool, DynamicDumpSharedSpaces ) \ - f(bool, DumpSharedSpaces ) \ - f(bool, UseSharedSpaces ) \ - f(ccstr, SharedArchiveFile ) \ - f(ccstr, SharedArchiveConfigFile ) \ - f(ccstr, ArchiveClassesAtExit ) \ f(size_t, MaxMetaspaceSize ) \ - f(bool, UseAggressiveCDS ) \ f(size_t, SharedBaseAddress ) \ f(bool, UseCompressedOops ) \ f(bool, UseCompressedClassPointers ) \ @@ -87,8 +80,8 @@ public: int serialize(MessageBuffer& buf) const; int deserialize(MessageBuffer& buf); - bool equals(JClientVMFlags* that, bool allow_clr, bool allow_cds, bool allow_aot); - uint32_t hash(bool allow_clr, bool allow_cds, bool allow_aot); + bool equals(JClientVMFlags* that); + uint32_t hash(); void print_flags(outputStream* st); }; diff --git a/src/hotspot/share/jbooster/jbooster_globals.hpp b/src/hotspot/share/jbooster/jbooster_globals.hpp index 3eb74abf8..74968af75 100644 --- a/src/hotspot/share/jbooster/jbooster_globals.hpp +++ b/src/hotspot/share/jbooster/jbooster_globals.hpp @@ -116,6 +116,9 @@ \ product(bool, ClassLoaderResourceCacheVerboseMode, false, DIAGNOSTIC, \ "Dump/load more data for verification and debugging.") \ + \ + product(ccstr, JBoosterServerSSLRootCerts, NULL, EXPERIMENTAL, \ + "The file path to save server SSL root certificate.") \ // end of JBOOSTER_FLAGS diff --git a/src/hotspot/share/jbooster/net/clientStream.cpp b/src/hotspot/share/jbooster/net/clientStream.cpp index d72b796d5..5b66e083f 100644 --- a/src/hotspot/share/jbooster/net/clientStream.cpp +++ b/src/hotspot/share/jbooster/net/clientStream.cpp @@ -25,10 +25,13 @@ #include "jbooster/net/clientStream.hpp" #include "jbooster/net/rpcCompatibility.hpp" #include "jbooster/net/serializationWrappers.hpp" +#include "jbooster/net/sslUtils.hpp" #include "jbooster/utilities/fileUtils.hpp" #include "runtime/java.hpp" #include "runtime/thread.hpp" +SSL_CTX* ClientStream::_client_ssl_ctx = nullptr; + ClientStream::ClientStream(const char* address, const char* port, uint32_t timeout_ms): CommunicationStream(Thread::current_or_null()), _server_address(address), @@ -49,6 +52,29 @@ ClientStream::~ClientStream() { } } +void ClientStream::client_init_ssl_ctx(const char* root_certs) { + guarantee(_client_ssl_ctx == nullptr, "sanity"); + + SSLUtils::openssl_init_ssl(); + _client_ssl_ctx = SSLUtils::ssl_ctx_new(SSLUtils::sslv23_client_method()); + if (_client_ssl_ctx == nullptr) { + vm_exit_during_initialization("Failed to create SSL context."); + } + + SSLUtils::ssl_ctx_set_options(_client_ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2); + + const int security_level = 2; + SSLUtils::ssl_ctx_set_security_level(_client_ssl_ctx, security_level); + + SSLUtils::ssl_ctx_set_verify(_client_ssl_ctx, SSL_VERIFY_PEER, NULL); + if (SSLUtils::ssl_ctx_load_verify_locations(_client_ssl_ctx, root_certs, NULL) != 1) { + if (log_is_enabled(Error, jbooster, rpc)) { + SSLUtils::err_print_errors_fp(stderr); + } + vm_exit_during_initialization("Failed to load root cert."); + } +} + int ClientStream::connect_to_server() { close_stream(); const int retries = 3; @@ -58,10 +84,16 @@ int ClientStream::connect_to_server() { int conn_fd; JB_THROW(try_to_connect_once(&conn_fd, _server_address, _server_port, _timeout_ms)); assert(conn_fd >= 0 && errno == 0, "sanity"); - init_stream(conn_fd); + + SSL* ssl = nullptr; + if (_client_ssl_ctx != nullptr) { + JB_THROW(try_to_ssl_connect(&ssl, conn_fd)); + assert(ssl != nullptr && errno == 0, "sanity"); + } + init_stream(conn_fd, ssl); return 0; } JB_TRY_BREAKABLE_END - JB_CATCH(ECONNREFUSED, EBADF) { + JB_CATCH(ECONNREFUSED, EBADF, JBErr::BAD_SSL) { last_err = JB_ERR; } JB_CATCH_REST() { last_err = JB_ERR; @@ -69,7 +101,7 @@ int ClientStream::connect_to_server() { } JB_CATCH_END; } - if (last_err == ECONNREFUSED || last_err == EBADF) { + if (last_err == ECONNREFUSED || last_err == EBADF || last_err == JBErr::BAD_SSL) { constexpr const char* fmt = "Failed to connect to the JBooster server! Retried %d times."; if (JBoosterCrashIfNoServer) { fatal(fmt, retries); @@ -119,7 +151,9 @@ int ClientStream::sync_session_meta__client(bool* has_remote_clr, bool* has_remo RpcCompatibility comp; uint64_t client_random_id = cdm.random_id(); JClientArguments* program_args = cdm.program_args(); - JB_RETURN(send_request(MessageType::ClientSessionMeta, &comp, &client_random_id, program_args)); + JClientBoostLevel boost_level = cdm.boost_level(); + + JB_RETURN(send_request(MessageType::ClientSessionMeta, &comp, &client_random_id, program_args, &boost_level)); uint64_t server_random_id; uint32_t session_id, program_id; @@ -176,21 +210,21 @@ int ClientStream::connect_and_init_session(bool* use_clr, bool* use_cds, bool* u JB_THROW(sync_session_meta__client(&has_remote_clr, &has_remote_cds, &has_remote_aot)); JB_THROW(request_cache_file(use_clr, - cdm.is_clr_allowed(), + cdm.boost_level().is_clr_allowed(), FileUtils::is_file(cdm.cache_clr_path()), has_remote_clr, cdm.cache_clr_path(), MessageType::GetClassLoaderResourceCache)); JB_THROW(request_cache_file(use_cds, - cdm.is_cds_allowed(), + cdm.boost_level().is_cds_allowed(), FileUtils::is_file(cdm.cache_cds_path()), has_remote_cds, cdm.cache_cds_path(), MessageType::GetAggressiveCDSCache)); JB_THROW(request_cache_file(use_aot, - cdm.is_aot_allowed(), + cdm.boost_level().is_aot_allowed(), FileUtils::is_file(cdm.cache_aot_path()), has_remote_aot, cdm.cache_aot_path(), diff --git a/src/hotspot/share/jbooster/net/clientStream.hpp b/src/hotspot/share/jbooster/net/clientStream.hpp index 1f185644f..3c4d0fc8c 100644 --- a/src/hotspot/share/jbooster/net/clientStream.hpp +++ b/src/hotspot/share/jbooster/net/clientStream.hpp @@ -28,6 +28,8 @@ class ClientStream: public CommunicationStream { private: + static SSL_CTX* _client_ssl_ctx; + const char* const _server_address; const char* const _server_port; const uint32_t _timeout_ms; @@ -36,6 +38,8 @@ private: private: static int try_to_connect_once(int* res_fd, const char* address, const char* port, uint32_t timeout_ms); + static int try_to_ssl_connect(SSL** res_ssl, int conn_fd); + static bool verify_cert(SSL* ssl); int request_cache_file(bool* use_it, bool allowed_to_use, @@ -55,6 +59,8 @@ public: ClientStream(const char* address, const char* port, uint32_t timeout_ms, Thread* thread); ~ClientStream(); + static void client_init_ssl_ctx(const char* root_certs); + void set_inform_before_close(bool should) { _inform_before_close = should; } int connect_and_init_session(bool* use_clr, bool* use_cds, bool* use_aot); diff --git a/src/hotspot/share/jbooster/net/communicationStream.cpp b/src/hotspot/share/jbooster/net/communicationStream.cpp index f0898170c..cdb4b8fa7 100644 --- a/src/hotspot/share/jbooster/net/communicationStream.cpp +++ b/src/hotspot/share/jbooster/net/communicationStream.cpp @@ -22,6 +22,7 @@ */ #include "jbooster/net/communicationStream.inline.hpp" +#include "jbooster/net/sslUtils.hpp" #include "runtime/os.inline.hpp" #ifdef ASSERT #include "runtime/thread.inline.hpp" @@ -54,19 +55,27 @@ void CommunicationStream::handle_net_err(int comm_size, bool is_recv) { return; } +int CommunicationStream::read_from_fd_or_ssl(char* buf, size_t size) { + if (_ssl == nullptr) { + return os::recv(_conn_fd, buf, size, 0); + } else { + return SSLUtils::ssl_read(_ssl, buf, size); + } +} + uint32_t CommunicationStream::read_once_from_stream(char* buf, uint32_t size) { - int read_size = os::recv(_conn_fd, buf, (size_t) size, 0); - if (read_size <= 0) { - handle_net_err(read_size, true); - return 0; - } - return (uint32_t) read_size; + int read_size = read_from_fd_or_ssl(buf, size); + if (read_size <= 0) { + handle_net_err(read_size, true); + return 0; + } + return (uint32_t) read_size; } uint32_t CommunicationStream::read_all_from_stream(char* buf, uint32_t size) { uint32_t total_read_size = 0; while (total_read_size < size) { - int read_size = os::recv(_conn_fd, buf + total_read_size, (size_t) (size - total_read_size), 0); + int read_size = read_from_fd_or_ssl(buf + total_read_size, (size_t) (size - total_read_size)); if (read_size <= 0) { handle_net_err(read_size, true); break; @@ -76,8 +85,16 @@ uint32_t CommunicationStream::read_all_from_stream(char* buf, uint32_t size) { return total_read_size; } +int CommunicationStream::write_to_fd_or_ssl(char* buf, size_t size) { + if (_ssl == nullptr) { + return os::send(_conn_fd, buf, size, 0); + } else { + return SSLUtils::ssl_write(_ssl, buf, size); + } +} + uint32_t CommunicationStream::write_once_to_stream(char* buf, uint32_t size) { - int written_size = os::send(_conn_fd, buf, size, 0); + int written_size = write_to_fd_or_ssl(buf, size); if (written_size <= 0) { handle_net_err(written_size, false); return 0; @@ -88,7 +105,7 @@ uint32_t CommunicationStream::write_once_to_stream(char* buf, uint32_t size) { uint32_t CommunicationStream::write_all_to_stream(char* buf, uint32_t size) { uint32_t total_written_size = 0; while (total_written_size < size) { - int written_size = os::send(_conn_fd, buf + total_written_size, (size_t) (size - total_written_size), 0); + int written_size = write_to_fd_or_ssl(buf + total_written_size, (size_t) (size - total_written_size)); if (written_size <= 0) { handle_net_err(written_size, false); break; @@ -99,6 +116,8 @@ uint32_t CommunicationStream::write_all_to_stream(char* buf, uint32_t size) { } void CommunicationStream::close_stream() { + SSLUtils::shutdown_and_free_ssl(_ssl); + if (_conn_fd >= 0) { log_trace(jbooster, rpc)("Connection closed. stream_id=%u.", stream_id()); os::close(_conn_fd); diff --git a/src/hotspot/share/jbooster/net/communicationStream.hpp b/src/hotspot/share/jbooster/net/communicationStream.hpp index 7b2cfd9db..926221986 100644 --- a/src/hotspot/share/jbooster/net/communicationStream.hpp +++ b/src/hotspot/share/jbooster/net/communicationStream.hpp @@ -30,6 +30,8 @@ #include "utilities/globalDefinitions.hpp" class Thread; +typedef struct ssl_st SSL; +typedef struct ssl_ctx_st SSL_CTX; /** * Base class of ServerStream and ClientStream. @@ -39,6 +41,7 @@ class Thread; class CommunicationStream: public CHeapObj { private: int _conn_fd; // generated by the OS + SSL* _ssl; uint32_t _stream_id; // generated by the server int _errno; @@ -56,6 +59,8 @@ private: int get_errno() { return _errno; } int get_and_clear_errno() { int eno = _errno; _errno = 0; return eno; } int return_errno_or_flag(int flag) { return get_errno() ? get_and_clear_errno() : flag; } + int read_from_fd_or_ssl(char* buf, size_t size); + int write_to_fd_or_ssl(char* buf, size_t size); uint32_t read_once_from_stream(char* buf, uint32_t size); uint32_t read_all_from_stream(char* buf, uint32_t size); @@ -71,6 +76,7 @@ private: protected: CommunicationStream(Thread* thread): _conn_fd(-1), + _ssl(nullptr), _stream_id(0), _errno(0), _msg_recv(SerializationMode::DESERIALIZE, this), @@ -80,7 +86,11 @@ protected: virtual ~CommunicationStream() { close_stream(); } - void init_stream(int conn_fd) { _conn_fd = conn_fd; } + void init_stream(int conn_fd, SSL* ssl) { + _conn_fd = conn_fd; + _ssl = ssl; + } + void close_stream(); int recv_message(); diff --git a/src/hotspot/share/jbooster/net/errorCode.hpp b/src/hotspot/share/jbooster/net/errorCode.hpp index 8dddd31f0..625ef6951 100644 --- a/src/hotspot/share/jbooster/net/errorCode.hpp +++ b/src/hotspot/share/jbooster/net/errorCode.hpp @@ -29,6 +29,7 @@ #define JB_ERROR_CODES(f) \ f(CONN_CLOSED, "Connection has been closed" ) \ f(CONN_CLOSED_BY_PEER, "Connection is closed by the other end" ) \ + f(BAD_SSL, "Unexpected SSL error during initialization" ) \ f(BAD_MSG_SIZE, "Unexpected size of the received message" ) \ f(BAD_MSG_TYPE, "Unexpected message type of the received message" ) \ f(BAD_MSG_DATA, "Unexpected payload data of the received message" ) \ diff --git a/src/hotspot/share/jbooster/net/serverListeningThread.cpp b/src/hotspot/share/jbooster/net/serverListeningThread.cpp index 0f7b5dc8d..f01ab7bf1 100644 --- a/src/hotspot/share/jbooster/net/serverListeningThread.cpp +++ b/src/hotspot/share/jbooster/net/serverListeningThread.cpp @@ -26,6 +26,7 @@ #include "classfile/vmSymbols.hpp" #include "jbooster/net/serverListeningThread.hpp" #include "jbooster/net/serverStream.hpp" +#include "jbooster/net/sslUtils.hpp" #include "jbooster/server/serverDataManager.hpp" #include "jbooster/server/serverMessageHandler.hpp" #include "logging/log.hpp" @@ -38,6 +39,7 @@ #include "runtime/thread.inline.hpp" ServerListeningThread* ServerListeningThread::_singleton = nullptr; +SSL_CTX* ServerListeningThread::_server_ssl_ctx = nullptr; /** * This function is called in the main thread. @@ -45,7 +47,21 @@ ServerListeningThread* ServerListeningThread::_singleton = nullptr; ServerListeningThread* ServerListeningThread::start_thread(const char* address, uint16_t port, uint32_t timeout_ms, + const char* ssl_key, + const char* ssl_cert, TRAPS) { + if ((ssl_key == nullptr && ssl_cert != nullptr) || (ssl_key != nullptr && ssl_cert == nullptr)) { + log_error(jbooster, rpc)("You must include --ssl-cert and --ssl-key together."); + vm_exit(1); + } + if (ssl_key != nullptr && ssl_cert != nullptr) { + if (!SSLUtils::init_ssl_lib()) { + log_error(jbooster, rpc)("Failed to load all functions from OpenSSL Dynamic Library."); + vm_exit(1); + } + server_init_ssl_ctx(ssl_key, ssl_cert); + } + JavaThread* new_thread = new JavaThread(&server_listener_thread_entry); guarantee(new_thread != nullptr && new_thread->osthread() != nullptr, "sanity"); guarantee(_singleton == nullptr, "sanity"); @@ -74,6 +90,35 @@ ServerListeningThread* ServerListeningThread::start_thread(const char* address, return _singleton; } +void ServerListeningThread::server_init_ssl_ctx(const char* ssl_key, const char* ssl_cert) { + SSLUtils::openssl_init_ssl(); + + _server_ssl_ctx = SSLUtils::ssl_ctx_new(SSLUtils::sslv23_server_method()); + if (_server_ssl_ctx == nullptr) { + log_error(jbooster, rpc)("Failed to create SSL context"); + vm_exit(1); + } + + SSLUtils::ssl_ctx_set_options(_server_ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2); + + const int security_level = 2; + SSLUtils::ssl_ctx_set_security_level(_server_ssl_ctx, security_level); + + const char* error_description = nullptr; + if (SSLUtils::ssl_ctx_use_certificate_file(_server_ssl_ctx, ssl_cert, SSL_FILETYPE_PEM) != 1) { + error_description = "Failed to add certificate file to SSL context."; + SSLUtils::handle_ssl_ctx_error(error_description); + } + if (SSLUtils::ssl_ctx_use_privatekey_file(_server_ssl_ctx, ssl_key, SSL_FILETYPE_PEM) != 1) { + error_description = "Failed to add private key file to SSL context."; + SSLUtils::handle_ssl_ctx_error(error_description); + } + if (SSLUtils::ssl_ctx_check_private_key(_server_ssl_ctx) != 1) { + error_description = "Private key doesn't match certificate."; + SSLUtils::handle_ssl_ctx_error(error_description); + } +} + void ServerListeningThread::server_listener_thread_entry(JavaThread* thread, TRAPS) { JB_TRY { JB_THROW(_singleton->run_listener(thread)); @@ -109,7 +154,7 @@ uint32_t ServerListeningThread::new_stream_id() { /** * Add the new connection to the connection thread pool. */ -void ServerListeningThread::handle_new_connection(int conn_fd, TRAPS) { +void ServerListeningThread::handle_new_connection(int conn_fd, SSL* ssl, TRAPS) { ThreadInVMfromNative tiv(THREAD); ResourceMark rm(THREAD); HandleMark hm(THREAD); @@ -117,12 +162,14 @@ void ServerListeningThread::handle_new_connection(int conn_fd, TRAPS) { JavaValue result(T_BOOLEAN); JavaCallArguments args; args.push_int(conn_fd); + args.push_long((jlong)(uintptr_t) ssl); JavaCalls::call_static(&result, ServerDataManager::get().main_klass(), vmSymbols::receiveConnection_name(), - vmSymbols::int_bool_signature(), + vmSymbols::receiveConnection_signature(), &args, CATCH); if (!result.get_jboolean()) { log_warning(jbooster, rpc)("Failed to handle the new connection as the thread pool is full."); + SSLUtils::shutdown_and_free_ssl(ssl); os::close(conn_fd); } } @@ -133,11 +180,11 @@ void ServerListeningThread::handle_new_connection(int conn_fd, TRAPS) { * This function is called in another java thread (not in ServerListeningThread thread). * So do not use `this` here. */ -void ServerListeningThread::handle_connection(int conn_fd) { +void ServerListeningThread::handle_connection(int conn_fd, long ssl) { JavaThread* THREAD = JavaThread::current(); ThreadToNativeFromVM ttn(THREAD); - ServerStream* server_stream = new ServerStream(conn_fd, THREAD); + ServerStream* server_stream = new ServerStream(conn_fd, (SSL*)(uintptr_t) ssl, THREAD); ThreadServerStreamMark tssm(server_stream, true, THREAD); server_stream->handle_meta_request(new_stream_id()); if (server_stream->is_stream_closed()) return; diff --git a/src/hotspot/share/jbooster/net/serverListeningThread.hpp b/src/hotspot/share/jbooster/net/serverListeningThread.hpp index 49f5efb3f..abf6e4f79 100644 --- a/src/hotspot/share/jbooster/net/serverListeningThread.hpp +++ b/src/hotspot/share/jbooster/net/serverListeningThread.hpp @@ -25,10 +25,15 @@ #define SHARE_JBOOSTER_NET_SERVERLISTENINGTHREAD_HPP #include "runtime/thread.hpp" +#include // for addrinfo + +typedef struct ssl_st SSL; +typedef struct ssl_ctx_st SSL_CTX; class ServerListeningThread : public CHeapObj { private: static ServerListeningThread* _singleton; + static SSL_CTX* _server_ssl_ctx; JavaThread* const _the_java_thread; const char* const _address; @@ -40,13 +45,15 @@ private: volatile bool _exit_flag; private: + static void server_init_ssl_ctx(const char* ssl_key, const char* ssl_cert); static void server_listener_thread_entry(JavaThread* thread, TRAPS); ServerListeningThread(JavaThread* the_java_thread, const char* address, uint16_t port, uint32_t timeout_ms); uint32_t new_stream_id(); - void handle_new_connection(int conn_fd, TRAPS); + bool prepare_and_handle_new_connection(int server_fd, sockaddr_in* acc_addr, socklen_t* acc_addrlen, TRAPS); + void handle_new_connection(int conn_fd, SSL* ssl, TRAPS); int run_listener(TRAPS); @@ -54,6 +61,8 @@ public: static ServerListeningThread* start_thread(const char* address, uint16_t port, uint32_t timeout_ms, + const char* ssl_key, + const char* ssl_cert, TRAPS); ~ServerListeningThread(); @@ -61,7 +70,7 @@ public: bool get_exit_flag() { return _exit_flag; } void set_exit_flag() { _exit_flag = true; } - void handle_connection(int conn_fd); + void handle_connection(int conn_fd, long ssl); }; #endif // SHARE_JBOOSTER_NET_SERVERLISTENINGTHREAD_HPP diff --git a/src/hotspot/share/jbooster/net/serverStream.cpp b/src/hotspot/share/jbooster/net/serverStream.cpp index a3e7fa5c6..838364fca 100644 --- a/src/hotspot/share/jbooster/net/serverStream.cpp +++ b/src/hotspot/share/jbooster/net/serverStream.cpp @@ -30,16 +30,16 @@ #include "runtime/thread.hpp" #include "runtime/timerTrace.hpp" -ServerStream::ServerStream(int conn_fd): +ServerStream::ServerStream(int conn_fd, SSL* ssl): CommunicationStream(Thread::current_or_null()), _session_data(nullptr) { - init_stream(conn_fd); + init_stream(conn_fd, ssl); } -ServerStream::ServerStream(int conn_fd, Thread* thread): +ServerStream::ServerStream(int conn_fd, SSL* ssl, Thread* thread): CommunicationStream(thread), _session_data(nullptr) { - init_stream(conn_fd); + init_stream(conn_fd, ssl); } ServerStream::~ServerStream() { @@ -52,8 +52,8 @@ uint32_t ServerStream::session_id() { void ServerStream::set_session_data(JClientSessionData* sd) { JClientSessionData* old_sd = _session_data; - if (sd == old_sd) return; - // Do not call sd->ref_cnt().inc() here as it has been inc when obtained. + // Do not let `sd` increase 1 here as it has been increased when obtained. + // But let `old_sd` decrease 1 even if `sd == old_sd` for the same reason. if (old_sd != nullptr) { old_sd->ref_cnt().dec_and_update_time(); } @@ -105,7 +105,8 @@ int ServerStream::sync_session_meta__server() { RpcCompatibility comp; uint64_t client_random_id; JClientArguments program_args(false); // on-stack allocation to prevent memory leakage - JB_RETURN(parse_request(&comp, &client_random_id, &program_args)); + JClientBoostLevel boost_level; + JB_RETURN(parse_request(&comp, &client_random_id, &program_args, &boost_level)); const char* unsupport_reason = nullptr; if (!program_args.check_compatibility_with_server(&unsupport_reason)) { @@ -115,7 +116,7 @@ int ServerStream::sync_session_meta__server() { JB_RETURN(JBErr::ABORT_CUR_PHRASE); } - JClientSessionData* sd = sdm.create_session(client_random_id, &program_args, Thread::current()); + JClientSessionData* sd = sdm.create_session(client_random_id, &program_args, boost_level, Thread::current()); JClientProgramData* pd = sd->program_data(); set_session_data(sd); @@ -123,8 +124,8 @@ int ServerStream::sync_session_meta__server() { uint32_t session_id = sd->session_id(); uint32_t program_id = pd->program_id(); bool has_remote_clr = pd->clr_cache_state().is_cached(); - bool has_remote_cds = pd->cds_cache_state().is_cached(); - bool has_remote_aot = pd->aot_cache_state().is_cached(); + bool has_remote_cds = boost_level.is_cds_agg_enabled() ? pd->agg_cds_cache_state().is_cached() : pd->dy_cds_cache_state().is_cached(); + bool has_remote_aot = boost_level.is_aot_pgo_enabled() ? pd->aot_pgo_cache_state().is_cached() : pd->aot_static_cache_state().is_cached(); JB_RETURN(send_response(stream_id_addr(), &server_random_id, &session_id, &program_id, &has_remote_clr, &has_remote_cds, &has_remote_aot)); log_info(jbooster, rpc)("New client: session_id=%u, program_id=%u, " @@ -138,10 +139,10 @@ int ServerStream::sync_session_meta__server() { BOOL_TO_STR(has_remote_aot), stream_id()); - return handle_sync_requests(pd); + return handle_sync_requests(pd, boost_level.is_cds_agg_enabled(), boost_level.is_aot_pgo_enabled()); } -int ServerStream::handle_sync_requests(JClientProgramData* pd) { +int ServerStream::handle_sync_requests(JClientProgramData* pd, bool enable_cds_agg, bool enable_aot_pgo) { bool not_end = true; do { MessageType type; @@ -155,13 +156,15 @@ int ServerStream::handle_sync_requests(JClientProgramData* pd) { } case MessageType::GetAggressiveCDSCache: { TraceTime tt("Send cds", TRACETIME_LOG(Info, jbooster)); - FileWrapper file(pd->cds_cache_state().file_path(), SerializationMode::SERIALIZE); + const char* cds_file_path = enable_cds_agg ? pd->agg_cds_cache_state().file_path() : pd->dy_cds_cache_state().file_path(); + FileWrapper file(cds_file_path, SerializationMode::SERIALIZE); JB_RETURN(file.send_file(this)); break; } case MessageType::GetLazyAOTCache: { TraceTime tt("Send aot", TRACETIME_LOG(Info, jbooster)); - FileWrapper file(pd->aot_cache_state().file_path(), SerializationMode::SERIALIZE); + const char* aot_file_path = enable_aot_pgo ? pd->aot_pgo_cache_state().file_path() : pd->aot_static_cache_state().file_path(); + FileWrapper file(aot_file_path, SerializationMode::SERIALIZE); JB_RETURN(file.send_file(this)); break; } diff --git a/src/hotspot/share/jbooster/net/serverStream.hpp b/src/hotspot/share/jbooster/net/serverStream.hpp index 56d05dabb..7239813cd 100644 --- a/src/hotspot/share/jbooster/net/serverStream.hpp +++ b/src/hotspot/share/jbooster/net/serverStream.hpp @@ -40,11 +40,11 @@ private: int sync_stream_meta__server(); int resync_session_and_stream_meta__server(); - int handle_sync_requests(JClientProgramData* pd); + int handle_sync_requests(JClientProgramData* pd, bool enable_cds_agg, bool enable_aot_pgo); public: - ServerStream(int conn_fd); - ServerStream(int conn_fd, Thread* thread); + ServerStream(int conn_fd, SSL* ssl); + ServerStream(int conn_fd, SSL* ssl, Thread* thread); ~ServerStream(); void handle_meta_request(uint32_t stream_id); diff --git a/src/hotspot/share/jbooster/net/sslUtils.cpp b/src/hotspot/share/jbooster/net/sslUtils.cpp new file mode 100644 index 000000000..96a159871 --- /dev/null +++ b/src/hotspot/share/jbooster/net/sslUtils.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "logging/log.hpp" +#include "jbooster/net/sslUtils.hpp" +#include "runtime/java.hpp" +#include +#include + +void* SSLUtils::_lib_handle = nullptr; +enum SSLUtils::SSLVersion SSLUtils::_version = V0; +const char* SSLUtils::OPENSSL_VERSION_1_0 = "OpenSSL 1.0."; +const char* SSLUtils::OPENSSL_VERSION_1_1 = "OpenSSL 1.1."; +const char* SSLUtils::OPENSSL_VERSION_3_X = "OpenSSL 3."; + +SSLUtils::openssl_version_func_t SSLUtils::_openssl_version = nullptr; +SSLUtils::openssl_init_ssl_func_t SSLUtils::_openssl_init_ssl = nullptr; +SSLUtils::ssl_ctx_new_func_t SSLUtils::_ssl_ctx_new = nullptr; +SSLUtils::sslv23_client_method_func_t SSLUtils::_sslv23_client_method = nullptr; +SSLUtils::sslv23_server_method_func_t SSLUtils::_sslv23_server_method = nullptr; +SSLUtils::ssl_ctx_ctrl_func_t SSLUtils::_ssl_ctx_ctrl = nullptr; +SSLUtils::ssl_ctx_set_options_func_t SSLUtils::_ssl_ctx_set_options = nullptr; +SSLUtils::ssl_ctx_set_cipher_list_func_t SSLUtils::_ssl_ctx_set_cipher_list = nullptr; +SSLUtils::ssl_ctx_set_ciphersuites_func_t SSLUtils::_ssl_ctx_set_ciphersuites = nullptr; +SSLUtils::ssl_ctx_set_verify_func_t SSLUtils::_ssl_ctx_set_verify = nullptr; +SSLUtils::ssl_ctx_load_verify_locations_func_t SSLUtils::_ssl_ctx_load_verify_locations = nullptr; +SSLUtils::ssl_ctx_use_certificate_file_func_t SSLUtils::_ssl_ctx_use_certificate_file = nullptr; +SSLUtils::ssl_ctx_use_privatekey_file_func_t SSLUtils::_ssl_ctx_use_privatekey_file = nullptr; +SSLUtils::ssl_ctx_check_private_key_func_t SSLUtils::_ssl_ctx_check_private_key = nullptr; +SSLUtils::ssl_ctx_set_security_level_func_t SSLUtils::_ssl_ctx_set_security_level = nullptr; +SSLUtils::ssl_new_func_t SSLUtils::_ssl_new = nullptr; +SSLUtils::ssl_set_fd_func_t SSLUtils::_ssl_set_fd = nullptr; +SSLUtils::ssl_get_error_func_t SSLUtils::_ssl_get_error = nullptr; +SSLUtils::ssl_accept_func_t SSLUtils::_ssl_accept = nullptr; +SSLUtils::ssl_connect_func_t SSLUtils::_ssl_connect = nullptr; +SSLUtils::ssl_read_func_t SSLUtils::_ssl_read = nullptr; +SSLUtils::ssl_write_func_t SSLUtils::_ssl_write = nullptr; +SSLUtils::ssl_shutdown_func_t SSLUtils::_ssl_shutdown = nullptr; +SSLUtils::ssl_free_func_t SSLUtils::_ssl_free = nullptr; +SSLUtils::ssl_ctx_free_func_t SSLUtils::_ssl_ctx_free = nullptr; +SSLUtils::ssl_get_peer_certificate_func_t SSLUtils::_ssl_get_peer_certificate = nullptr; +SSLUtils::ssl_get_verify_result_func_t SSLUtils::_ssl_get_verify_result = nullptr; +SSLUtils::err_peak_error_func_t SSLUtils::_err_peak_error = nullptr; +SSLUtils::err_error_string_n_func_t SSLUtils::_err_error_string_n = nullptr; +SSLUtils::err_get_error_func_t SSLUtils::_err_get_error = nullptr; +SSLUtils::err_print_errors_fp_func_t SSLUtils::_err_print_errors_fp = nullptr; + +static void* open_ssl_lib() { + const char* const lib_names[] = { + "libssl.so.3", + "libssl.so.1.1", + "libssl.so.1.0.0", + "libssl.so.10", + "libssl.so" + }; + const int lib_names_len = sizeof(lib_names) / sizeof(lib_names[0]); + + void* res = nullptr; + for (int i = 0; i < lib_names_len; ++i) { + res = ::dlopen(lib_names[i], RTLD_NOW); + if (res != nullptr) { + break; + } + } + return res; +} + +void SSLUtils::find_ssl_version() { + const char* openssl_version_res = nullptr; + _openssl_version = (openssl_version_func_t)::dlsym(_lib_handle, "OpenSSL_version"); + if (_openssl_version) { + openssl_version_res = openssl_version(); + if (0 == strncmp(openssl_version_res, OPENSSL_VERSION_1_1, strlen(OPENSSL_VERSION_1_1))) { + _version = V1_1; + } else if (0 == strncmp(openssl_version_res, OPENSSL_VERSION_3_X, strlen(OPENSSL_VERSION_3_X))) { + _version = V3; + } + } else { + _openssl_version = (openssl_version_func_t) ::dlsym(_lib_handle, "SSLeay_version"); + if (_openssl_version) { + openssl_version_res = openssl_version(); + if (0 == strncmp(openssl_version_res, OPENSSL_VERSION_1_0, strlen(OPENSSL_VERSION_1_0))) { + _version = V1_0; + } + } + } +} + +void SSLUtils::find_address_in_dynamic_lib() { + if (_version == V3) { + _ssl_get_peer_certificate = (ssl_get_peer_certificate_func_t) ::dlsym(_lib_handle, "SSL_get1_peer_certificate"); + } else { + _ssl_get_peer_certificate = (ssl_get_peer_certificate_func_t) ::dlsym(_lib_handle, "SSL_get_peer_certificate"); + } + + _openssl_init_ssl = (openssl_init_ssl_func_t) ::dlsym(_lib_handle, "OPENSSL_init_ssl"); + _sslv23_client_method = (sslv23_client_method_func_t) ::dlsym(_lib_handle, "TLS_client_method"); + _sslv23_server_method = (sslv23_server_method_func_t) ::dlsym(_lib_handle, "TLS_server_method"); + _ssl_ctx_new = (ssl_ctx_new_func_t) ::dlsym(_lib_handle, "SSL_CTX_new"); + _ssl_ctx_ctrl = (ssl_ctx_ctrl_func_t) ::dlsym(_lib_handle, "SSL_CTX_ctrl"); + _ssl_ctx_set_options = (ssl_ctx_set_options_func_t) ::dlsym(_lib_handle, "SSL_CTX_set_options"); + _ssl_ctx_set_cipher_list = (ssl_ctx_set_cipher_list_func_t) ::dlsym(_lib_handle, "SSL_CTX_set_cipher_list"); + _ssl_ctx_set_ciphersuites = (ssl_ctx_set_ciphersuites_func_t) ::dlsym(_lib_handle, "SSL_CTX_set_ciphersuites"); + _ssl_ctx_set_verify = (ssl_ctx_set_verify_func_t) ::dlsym(_lib_handle, "SSL_CTX_set_verify"); + _ssl_ctx_load_verify_locations = (ssl_ctx_load_verify_locations_func_t) ::dlsym(_lib_handle, "SSL_CTX_load_verify_locations"); + _ssl_ctx_use_certificate_file = (ssl_ctx_use_certificate_file_func_t) ::dlsym(_lib_handle, "SSL_CTX_use_certificate_file"); + _ssl_ctx_use_privatekey_file = (ssl_ctx_use_privatekey_file_func_t) ::dlsym(_lib_handle, "SSL_CTX_use_PrivateKey_file"); + _ssl_ctx_check_private_key = (ssl_ctx_check_private_key_func_t) ::dlsym(_lib_handle, "SSL_CTX_check_private_key"); + _ssl_ctx_set_security_level = (ssl_ctx_set_security_level_func_t) ::dlsym(_lib_handle, "SSL_CTX_set_security_level"); + _ssl_new = (ssl_new_func_t) ::dlsym(_lib_handle, "SSL_new"); + _ssl_set_fd = (ssl_set_fd_func_t) ::dlsym(_lib_handle, "SSL_set_fd"); + _ssl_get_error = (ssl_get_error_func_t) ::dlsym(_lib_handle, "SSL_get_error"); + _ssl_accept = (ssl_accept_func_t) ::dlsym(_lib_handle, "SSL_accept"); + _ssl_connect = (ssl_connect_func_t) ::dlsym(_lib_handle, "SSL_connect"); + _ssl_read = (ssl_read_func_t) ::dlsym(_lib_handle, "SSL_read"); + _ssl_write = (ssl_write_func_t) ::dlsym(_lib_handle, "SSL_write"); + _ssl_shutdown = (ssl_shutdown_func_t) ::dlsym(_lib_handle, "SSL_shutdown"); + _ssl_free = (ssl_free_func_t) ::dlsym(_lib_handle, "SSL_free"); + _ssl_ctx_free = (ssl_ctx_free_func_t) ::dlsym(_lib_handle, "SSL_CTX_free"); + _ssl_get_verify_result = (ssl_get_verify_result_func_t) ::dlsym(_lib_handle, "SSL_get_verify_result"); + _err_peak_error = (err_peak_error_func_t) ::dlsym(_lib_handle, "ERR_peek_error"); + _err_error_string_n = (err_error_string_n_func_t) ::dlsym(_lib_handle, "ERR_error_string_n"); + _err_get_error = (err_get_error_func_t) ::dlsym(_lib_handle, "ERR_get_error"); + _err_print_errors_fp = (err_print_errors_fp_func_t) ::dlsym(_lib_handle, "ERR_print_errors_fp"); +} + +bool SSLUtils::check_if_find_all_functions() { + if ( + (_openssl_version == nullptr) || + (_openssl_init_ssl == nullptr) || + (_ssl_ctx_new == nullptr) || + (_sslv23_client_method == nullptr) || + (_sslv23_server_method == nullptr) || + (_ssl_ctx_ctrl == nullptr) || + (_ssl_ctx_set_options == nullptr) || + (_ssl_ctx_set_cipher_list == nullptr) || + (_ssl_ctx_set_ciphersuites == nullptr) || + (_ssl_ctx_set_verify == nullptr) || + (_ssl_ctx_load_verify_locations == nullptr) || + (_ssl_ctx_use_certificate_file == nullptr) || + (_ssl_ctx_use_privatekey_file == nullptr) || + (_ssl_ctx_check_private_key == nullptr) || + (_ssl_ctx_set_security_level == nullptr) || + (_ssl_new == nullptr) || + (_ssl_set_fd == nullptr) || + (_ssl_get_error == nullptr) || + (_ssl_accept == nullptr) || + (_ssl_connect == nullptr) || + (_ssl_read == nullptr) || + (_ssl_write == nullptr) || + (_ssl_shutdown == nullptr) || + (_ssl_free == nullptr) || + (_ssl_ctx_free == nullptr) || + (_ssl_get_peer_certificate == nullptr) || + (_ssl_get_verify_result == nullptr) || + (_err_peak_error == nullptr) || + (_err_error_string_n == nullptr) || + (_err_get_error == nullptr) || + (_err_print_errors_fp == nullptr) + ) { return false; } + return true; +} + +bool SSLUtils::init_ssl_lib() { + _lib_handle = open_ssl_lib(); + if (_lib_handle == nullptr) { + return false; + } + + find_ssl_version(); + if (_version == V0) { + return false; + } else if (_version == V1_0) { + log_error(jbooster, rpc)("JBooster only supports OpenSSL 1.1.0+."); + return false; + } + + find_address_in_dynamic_lib(); + return check_if_find_all_functions(); +} + +void SSLUtils::shutdown_and_free_ssl(SSL*& ssl) { + if (ssl != nullptr) { + SSLUtils::ssl_shutdown(ssl); + SSLUtils::ssl_free(ssl); + ssl = nullptr; + } +} + +void SSLUtils::handle_ssl_ctx_error(const char* error_description) { + log_error(jbooster, rpc)("%s", error_description); + if (log_is_enabled(Error, jbooster, rpc)) { + SSLUtils::err_print_errors_fp(stderr); + } + vm_exit(1); +} + +void SSLUtils::handle_ssl_error(SSL* ssl, int ret, const char* error_description) { + const char* errno_copy = strerror(errno); + int error = SSLUtils::ssl_get_error(ssl, ret); + unsigned long earliest_error = SSLUtils::err_peak_error(); + + char error_string[256] = {0}; + SSLUtils::err_error_string_n(earliest_error, error_string, sizeof(error_string)); + + log_error(jbooster, rpc)("%s! Error Code: %d, Earliest Error: %lu, Error String: %s, Errno: %s", + error_description, error, earliest_error, error_string, errno_copy); + if (log_is_enabled(Error, jbooster, rpc)) { + SSLUtils::err_print_errors_fp(stderr); + } +} \ No newline at end of file diff --git a/src/hotspot/share/jbooster/net/sslUtils.hpp b/src/hotspot/share/jbooster/net/sslUtils.hpp new file mode 100644 index 000000000..0b8253b40 --- /dev/null +++ b/src/hotspot/share/jbooster/net/sslUtils.hpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_JBOOSTER_UTILITIES_SSLUtils_HPP +#define SHARE_JBOOSTER_UTILITIES_SSLUtils_HPP + +#include "memory/allocation.hpp" +#include + +class SSLUtils : AllStatic { + typedef const char* (*openssl_version_func_t)(int num); + typedef int (*openssl_init_ssl_func_t)(uint64_t opts, const void* settings); + typedef SSL_CTX* (*ssl_ctx_new_func_t)(const SSL_METHOD* meth); + typedef SSL_METHOD* (*sslv23_client_method_func_t)(void); + typedef SSL_METHOD* (*sslv23_server_method_func_t)(void); + typedef long (*ssl_ctx_ctrl_func_t)(SSL_CTX* ctx, int cmd, long larg, void* parg); + typedef uint64_t (*ssl_ctx_set_options_func_t)(SSL_CTX* ctx, uint64_t options); + typedef int (*ssl_ctx_set_cipher_list_func_t)(SSL_CTX* ctx, const char* str); + typedef int (*ssl_ctx_set_ciphersuites_func_t)(SSL_CTX* ctx, const char* str); + typedef void (*ssl_ctx_set_verify_func_t)(SSL_CTX* ctx, int mode, SSL_verify_cb callback); + typedef int (*ssl_ctx_load_verify_locations_func_t)(SSL_CTX* ctx, const char* CAfile, const char* CApath); + typedef int (*ssl_ctx_use_certificate_file_func_t)(SSL_CTX* ctx, const char* file, int type); + typedef int (*ssl_ctx_use_privatekey_file_func_t)(SSL_CTX* ctx, const char* file, int type); + typedef int (*ssl_ctx_check_private_key_func_t)(const SSL_CTX* ctx); + typedef void (*ssl_ctx_set_security_level_func_t)(SSL_CTX *ctx, int level); + typedef SSL* (*ssl_new_func_t)(SSL_CTX* ctx); + typedef int (*ssl_set_fd_func_t)(SSL* s, int fd); + typedef int (*ssl_get_error_func_t)(const SSL* s, int ret_code); + typedef int (*ssl_accept_func_t)(const SSL* ssl); + typedef int (*ssl_connect_func_t)(const SSL* ssl); + typedef int (*ssl_read_func_t)(SSL* ssl, void* buf, int num); + typedef int (*ssl_write_func_t)(SSL* ssl, const void* buf, int num); + typedef int (*ssl_shutdown_func_t)(SSL* ssl); + typedef void (*ssl_free_func_t)(SSL* ssl); + typedef void (*ssl_ctx_free_func_t)(SSL_CTX* ctx); + typedef X509* (*ssl_get_peer_certificate_func_t)(const SSL* ssl); + typedef long (*ssl_get_verify_result_func_t)(const SSL* ssl); + typedef unsigned long (*err_peak_error_func_t)(void); + typedef void (*err_error_string_n_func_t)(unsigned long e, char *buf, size_t len); + typedef unsigned long (*err_get_error_func_t)(void); + typedef void (*err_print_errors_fp_func_t)(FILE *fp); + + static enum SSLVersion { + V0, V1_0, V1_1, V3 + } _version; + + static void* _lib_handle; + static const char* OPENSSL_VERSION_1_0; + static const char* OPENSSL_VERSION_1_1; + static const char* OPENSSL_VERSION_3_X; + + static openssl_version_func_t _openssl_version; + static openssl_init_ssl_func_t _openssl_init_ssl; + static ssl_ctx_new_func_t _ssl_ctx_new; + static sslv23_client_method_func_t _sslv23_client_method; + static sslv23_server_method_func_t _sslv23_server_method; + static ssl_ctx_ctrl_func_t _ssl_ctx_ctrl; + static ssl_ctx_set_options_func_t _ssl_ctx_set_options; + static ssl_ctx_set_cipher_list_func_t _ssl_ctx_set_cipher_list; + static ssl_ctx_set_ciphersuites_func_t _ssl_ctx_set_ciphersuites; + static ssl_ctx_set_verify_func_t _ssl_ctx_set_verify; + static ssl_ctx_load_verify_locations_func_t _ssl_ctx_load_verify_locations; + static ssl_ctx_use_certificate_file_func_t _ssl_ctx_use_certificate_file; + static ssl_ctx_use_privatekey_file_func_t _ssl_ctx_use_privatekey_file; + static ssl_ctx_check_private_key_func_t _ssl_ctx_check_private_key; + static ssl_ctx_set_security_level_func_t _ssl_ctx_set_security_level; + static ssl_new_func_t _ssl_new; + static ssl_set_fd_func_t _ssl_set_fd; + static ssl_get_error_func_t _ssl_get_error; + static ssl_accept_func_t _ssl_accept; + static ssl_connect_func_t _ssl_connect; + static ssl_read_func_t _ssl_read; + static ssl_write_func_t _ssl_write; + static ssl_shutdown_func_t _ssl_shutdown; + static ssl_free_func_t _ssl_free; + static ssl_ctx_free_func_t _ssl_ctx_free; + static ssl_get_peer_certificate_func_t _ssl_get_peer_certificate; + static ssl_get_verify_result_func_t _ssl_get_verify_result; + static err_peak_error_func_t _err_peak_error; + static err_error_string_n_func_t _err_error_string_n; + static err_get_error_func_t _err_get_error; + static err_print_errors_fp_func_t _err_print_errors_fp; + +public: + static bool init_ssl_lib(); + static void find_ssl_version(); + static void find_address_in_dynamic_lib(); + static bool check_if_find_all_functions(); + + static const char* openssl_version() { return (*_openssl_version)(0); } + + static int openssl_init_ssl() { return (*_openssl_init_ssl)(0, NULL); } + static SSL_CTX* ssl_ctx_new(const SSL_METHOD* meth) { return (*_ssl_ctx_new)(meth); } + static SSL_METHOD* sslv23_client_method() { return (*_sslv23_client_method)(); } + static SSL_METHOD* sslv23_server_method() { return (*_sslv23_server_method)(); } + static long ssl_ctx_ctrl(SSL_CTX* ctx, int cmd, long larg, void* parg) { return (*_ssl_ctx_ctrl)(ctx, cmd, larg, parg); } + static uint64_t ssl_ctx_set_options(SSL_CTX* ctx, uint64_t options) { return (*_ssl_ctx_set_options)(ctx, options); }; + static int ssl_ctx_set_cipher_list(SSL_CTX* ctx, const char* str) { return (*_ssl_ctx_set_cipher_list)(ctx, str); }; + static int ssl_ctx_set_ciphersuites(SSL_CTX* ctx, const char* str) { return (*_ssl_ctx_set_ciphersuites)(ctx, str); }; + static void ssl_ctx_set_verify(SSL_CTX* ctx, int mode, SSL_verify_cb callback) { return (*_ssl_ctx_set_verify)(ctx, mode, callback); } + static int ssl_ctx_load_verify_locations(SSL_CTX* ctx, const char* CAfile, const char* CApath) { return (*_ssl_ctx_load_verify_locations)(ctx, CAfile, CApath); } + static int ssl_ctx_use_certificate_file(SSL_CTX* ctx, const char* file, int type) { return (*_ssl_ctx_use_certificate_file)(ctx, file, type); } + static int ssl_ctx_use_privatekey_file(SSL_CTX* ctx, const char* file, int type) { return (*_ssl_ctx_use_privatekey_file)(ctx, file, type); } + static void ssl_ctx_set_security_level(SSL_CTX *ctx, int level) { return (*_ssl_ctx_set_security_level)(ctx, level); } + static int ssl_ctx_check_private_key(const SSL_CTX* ctx) { return (*_ssl_ctx_check_private_key)(ctx); } + static SSL* ssl_new(SSL_CTX* ctx) { return (*_ssl_new)(ctx); } + static int ssl_set_fd(SSL* s, int fd) { return (*_ssl_set_fd)(s, fd); } + static int ssl_get_error(const SSL* s, int ret_code) { return (*_ssl_get_error)(s, ret_code); } + static int ssl_accept(const SSL* ssl) { return (*_ssl_accept)(ssl); } + static int ssl_connect(const SSL* ssl) { return (*_ssl_connect)(ssl); } + static int ssl_read(SSL* ssl, void* buf, int num) { return (*_ssl_read)(ssl, buf, num); } + static int ssl_write(SSL* ssl, const void* buf, int num) { return (*_ssl_write)(ssl, buf, num); } + static int ssl_shutdown(SSL* ssl) { return (*_ssl_shutdown)(ssl); } + static void ssl_free(SSL* ssl) { return (*_ssl_free)(ssl); } + static void ssl_ctx_free(SSL_CTX* ctx) { return (*_ssl_ctx_free)(ctx); } + static X509* ssl_get_peer_certificate(const SSL* ssl) { return (*_ssl_get_peer_certificate)(ssl); } + static long ssl_get_verify_result(const SSL* ssl) { return (*_ssl_get_verify_result)(ssl); } + static unsigned long err_peak_error() { return (*_err_peak_error)(); } + static void err_error_string_n(unsigned long e, char *buf, size_t len) { return (*_err_error_string_n)(e, buf, len); } + static unsigned long err_get_error() { return (*_err_get_error)(); } + static void err_print_errors_fp(FILE *fp) { return (*_err_print_errors_fp)(fp); }; + + static void shutdown_and_free_ssl(SSL*& ssl); + static void handle_ssl_ctx_error(const char* error_description); + static void handle_ssl_error(SSL* ssl, int ret, const char* error_description); +}; + +#endif // SHARE_JBOOSTER_UTILITIES_SSLUtils_HPP diff --git a/src/hotspot/share/jbooster/server/serverDataManager.cpp b/src/hotspot/share/jbooster/server/serverDataManager.cpp index 8753102a4..b2f36c4e5 100644 --- a/src/hotspot/share/jbooster/server/serverDataManager.cpp +++ b/src/hotspot/share/jbooster/server/serverDataManager.cpp @@ -170,15 +170,13 @@ jlong RefCntWithTime::no_ref_time(jlong current_time) const { // -------------------------------- JClientCacheState --------------------------------- -JClientCacheState::JClientCacheState(): _is_allowed(false), - _state(NOT_GENERATED), +JClientCacheState::JClientCacheState(): _state(NOT_GENERATED), _file_path(nullptr), _file_timestamp(0) { // The real assignment is in JClientProgramData::JClientProgramData(). } -void JClientCacheState::init(bool allow, const char* file_path) { - _is_allowed = allow; +void JClientCacheState::init(const char* file_path) { _file_path = file_path; bool file_exists = FileUtils::is_file(file_path); _state = file_exists ? GENERATED : NOT_GENERATED; @@ -259,6 +257,11 @@ bool JClientCacheState::is_cached() { return false; } +const char* JClientCacheState::cache_state_str() { + return is_cached() ? "generated" : (is_being_generated() ? "generating" : "none"); +} + + void JClientCacheState::remove_file() { if (is_cached()) { remove_file_and_set_not_generated_sync(); @@ -277,18 +280,16 @@ JClientProgramData::JClientProgramData(uint32_t program_id, JClientArguments* pr _program_args->program_entry(), _program_args->is_jar(), _program_args->hash()); - bool allow_clr = _program_args->jbooster_allow_clr(); - bool allow_cds = _program_args->jbooster_allow_cds(); - bool allow_aot = _program_args->jbooster_allow_aot(); - bool allow_pgo = _program_args->jbooster_allow_pgo(); const char* clr_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "clr.log"); - const char* cds_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "cds.jsa"); - const char* aot_path_suffix = allow_pgo ? "aot-pgo.so" : "aot.so"; - const char* aot_path = JBoosterManager::calc_cache_path(sd, _program_str_id, aot_path_suffix); - clr_cache_state().init(allow_clr, clr_path); - cds_cache_state().init(allow_cds, cds_path); - aot_cache_state().init(allow_aot, aot_path); - _using_pgo = allow_pgo; + const char* dy_cds_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "cds-dy.jsa"); + const char* agg_cds_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "cds-agg.jsa"); + const char* aot_static_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "aot-static.so"); + const char* aot_pgo_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "aot-pgo.so"); + clr_cache_state().init(clr_path); + dy_cds_cache_state().init(dy_cds_path); + agg_cds_cache_state().init(agg_cds_path); + aot_static_cache_state().init(aot_static_path); + aot_pgo_cache_state().init(aot_pgo_path); } JClientProgramData::~JClientProgramData() { @@ -357,10 +358,12 @@ public: JClientSessionData::JClientSessionData(uint32_t session_id, uint64_t client_random_id, - JClientProgramData* program_data): + JClientProgramData* program_data, + JClientBoostLevel boost_level): _session_id(session_id), _random_id(client_random_id), _program_data(program_data), + _boost_level(boost_level), _cl_s2c(), _cl_c2s(), _k_c2s(), @@ -540,7 +543,7 @@ void ServerDataManager::init_cache_path(const char* optional_cache_path) { FileUtils::mkdirs(JBoosterCachePath); } -void ServerDataManager::init_phase3(int server_port, int connection_timeout, int cleanup_timeout, const char* cache_path, TRAPS) { +void ServerDataManager::init_phase3(int server_port, int connection_timeout, int cleanup_timeout, const char* cache_path, const char* ssl_key, const char* ssl_cert, TRAPS) { JBoosterManager::server_only(); init_cache_path(cache_path); @@ -548,7 +551,7 @@ void ServerDataManager::init_phase3(int server_port, int connection_timeout, int ServerControlThread::set_unused_shared_data_cleanup_timeout(cleanup_timeout); _singleton->_control_thread = ServerControlThread::start_thread(CHECK); - _singleton->_listening_thread = ServerListeningThread::start_thread(JBoosterAddress, (uint16_t) server_port, connection_timeout, CHECK); + _singleton->_listening_thread = ServerListeningThread::start_thread(JBoosterAddress, (uint16_t) server_port, connection_timeout, ssl_key, ssl_cert, CHECK); } /** @@ -610,10 +613,11 @@ JClientSessionData* ServerDataManager::get_session(uint32_t session_id, Thread* */ JClientSessionData* ServerDataManager::create_session(uint64_t client_random_id, JClientArguments* program_args, + JClientBoostLevel boost_level, Thread* thread) { uint32_t session_id = Atomic::add(&_next_session_allocation_id, 1u); JClientProgramData* pd = get_or_create_program(program_args, thread); - JClientSessionData* sd = new JClientSessionData(session_id, client_random_id, pd); + JClientSessionData* sd = new JClientSessionData(session_id, client_random_id, pd, boost_level); JClientSessionData** res = _sessions.put_if_absent(session_id, sd, thread); guarantee(res != nullptr && *res == sd, "sanity"); diff --git a/src/hotspot/share/jbooster/server/serverDataManager.hpp b/src/hotspot/share/jbooster/server/serverDataManager.hpp index 9181acd10..2cb7d2de0 100644 --- a/src/hotspot/share/jbooster/server/serverDataManager.hpp +++ b/src/hotspot/share/jbooster/server/serverDataManager.hpp @@ -133,7 +133,6 @@ class JClientCacheState final: public StackObj { static const int BEING_GENERATED = 1; static const int GENERATED = 2; - bool _is_allowed; volatile int _state; const char* _file_path; uint64_t _file_timestamp; @@ -149,9 +148,7 @@ public: JClientCacheState(); ~JClientCacheState(); - void init(bool allow, const char* file_path); - - bool is_allowed() { return _is_allowed; } + void init(const char* file_path); // /server/cache-- const char* file_path() { return _file_path; } @@ -167,6 +164,7 @@ public: // Unlike the APIs above, the APIs above only change the atomic variables, // while the following APIs checks whether the cache file exists. bool is_cached(); + const char* cache_state_str(); void remove_file(); }; @@ -188,10 +186,10 @@ private: RefCntWithTime _ref_cnt; JClientCacheState _clr_cache_state; - JClientCacheState _cds_cache_state; - JClientCacheState _aot_cache_state; - - bool _using_pgo; // use pgo if or not, as boost level 4 + JClientCacheState _dy_cds_cache_state; + JClientCacheState _agg_cds_cache_state; + JClientCacheState _aot_static_cache_state; + JClientCacheState _aot_pgo_cache_state; NONCOPYABLE(JClientProgramData); @@ -211,9 +209,10 @@ public: RefCntWithTime& ref_cnt() { return _ref_cnt; } JClientCacheState& clr_cache_state() { return _clr_cache_state; } - JClientCacheState& cds_cache_state() { return _cds_cache_state; } - JClientCacheState& aot_cache_state() { return _aot_cache_state; } - bool using_pgo() { return _using_pgo; } + JClientCacheState& dy_cds_cache_state() { return _dy_cds_cache_state; } + JClientCacheState& agg_cds_cache_state() { return _agg_cds_cache_state; } + JClientCacheState& aot_static_cache_state() { return _aot_static_cache_state; } + JClientCacheState& aot_pgo_cache_state() { return _aot_pgo_cache_state; } }; /** @@ -248,6 +247,8 @@ private: JClientProgramData* const _program_data; + JClientBoostLevel _boost_level; + // server-side CLD pointer -> client-side CLD pointer AddressMap _cl_s2c; // client-side CLD pointer -> server-side CLD pointer @@ -269,7 +270,7 @@ private: static bool remove_address(AddressMap& table, address key, Thread* thread); public: - JClientSessionData(uint32_t session_id, uint64_t client_random_id, JClientProgramData* program_data); + JClientSessionData(uint32_t session_id, uint64_t client_random_id, JClientProgramData* program_data, JClientBoostLevel boost_level); ~JClientSessionData(); uint32_t session_id() const { return _session_id; } @@ -278,6 +279,8 @@ public: JClientProgramData* program_data() const { return _program_data; } + const JClientBoostLevel& boost_level() const { return _boost_level; } + address client_cld_address(ClassLoaderData* server_data, Thread* thread); ClassLoaderData* server_cld_address(address client_data, Thread* thread); ClassLoaderData* add_class_loader_if_absent(address client_cld_addr, @@ -399,7 +402,7 @@ public: static jint init_phase1(); static void init_phase2(TRAPS) { /* do nothing */ } - static void init_phase3(int server_port, int connection_timeout, int cleanup_timeout, const char* cache_path, TRAPS); + static void init_phase3(int server_port, int connection_timeout, int cleanup_timeout, const char* cache_path, const char* ssl_key, const char* ssl_cert, TRAPS); // $HOME/.jbooster/server const char* cache_dir_path() { return _cache_dir_path; } @@ -416,6 +419,7 @@ public: JClientSessionData* get_session(uint32_t session_id, Thread* thread); JClientSessionData* create_session(uint64_t client_random_id, JClientArguments* program_args, + JClientBoostLevel boost_level, Thread* thread); bool try_remove_session(uint32_t session_id, Thread* thread); diff --git a/src/hotspot/share/jbooster/server/serverDataManagerLog.cpp b/src/hotspot/share/jbooster/server/serverDataManagerLog.cpp index 47e9c6b01..c0a7b8647 100644 --- a/src/hotspot/share/jbooster/server/serverDataManagerLog.cpp +++ b/src/hotspot/share/jbooster/server/serverDataManagerLog.cpp @@ -93,19 +93,20 @@ public: bool operator () (ServerDataManager::JClientProgramDataMap::KVNode* kv_node) { JClientProgramData* pd = kv_node->value(); JClientCacheState& clr = pd->clr_cache_state(); - JClientCacheState& cds = pd->cds_cache_state(); - JClientCacheState& aot = pd->aot_cache_state(); - const char* clr_stat = (clr.is_cached() ? "generated" : (clr.is_being_generated() ? "generating" : "none")); - const char* cds_stat = (cds.is_cached() ? "generated" : (cds.is_being_generated() ? "generating" : "none")); - const char* aot_stat = (aot.is_cached() ? "generated" : (aot.is_being_generated() ? "generating" : "none")); + JClientCacheState& agg_cds = pd->agg_cds_cache_state(); + JClientCacheState& dy_cds = pd->dy_cds_cache_state(); + JClientCacheState& aot_static = pd->aot_static_cache_state(); + JClientCacheState& aot_pgo = pd->aot_pgo_cache_state(); OUT_1("-"); OUT_2("program_id: %u", pd->program_id()); OUT_2("program_name: %s", pd->program_args()->program_name()); OUT_2("program_hash: %x", pd->program_args()->hash()); OUT_2("ref_cnt: %d", pd->ref_cnt().get()); - OUT_2("clr_cache: %s", clr_stat); - OUT_2("cds_cache: %s", cds_stat); - OUT_2("aot_cache: %s", aot_stat); + OUT_2("clr_cache: %s", clr.cache_state_str()); + OUT_2("dy_cds_cache: %s", dy_cds.cache_state_str()); + OUT_2("agg_cds_cache: %s", agg_cds.cache_state_str()); + OUT_2("aot_static_cache: %s", aot_static.cache_state_str()); + OUT_2("aot_pgo_cache: %s", aot_pgo.cache_state_str()); OUT_2("class_loader_size: " SIZE_FORMAT, pd->class_loaders()->size()); if (pd->class_loaders()->size() > 0) { OUT_2("class_loaders:"); diff --git a/src/hotspot/share/jbooster/server/serverMessageHandler.cpp b/src/hotspot/share/jbooster/server/serverMessageHandler.cpp index 962e93cc7..49c25efb1 100644 --- a/src/hotspot/share/jbooster/server/serverMessageHandler.cpp +++ b/src/hotspot/share/jbooster/server/serverMessageHandler.cpp @@ -275,7 +275,7 @@ int ServerMessageHandler::request_methods_not_compile(GrowableArray* me } int ServerMessageHandler::request_client_cache(MessageType msg_type, JClientCacheState& cache) { - if (cache.is_allowed() && !cache.is_cached() && cache.set_being_generated()) { + if (!cache.is_cached() && cache.set_being_generated()) { JB_TRY { JB_THROW(ss().send_request(msg_type)); FileWrapper file(cache.file_path(), SerializationMode::DESERIALIZE); @@ -294,10 +294,14 @@ int ServerMessageHandler::request_client_cache(MessageType msg_type, JClientCach int ServerMessageHandler::handle_cache_file_sync_task(TRAPS) { DebugUtils::assert_thread_nonjava_or_in_native(); - JClientProgramData* pd = ss().session_data()->program_data(); + JClientSessionData* sd = ss().session_data(); + JClientProgramData* pd = sd->program_data(); + bool enabling_cds_agg = sd->boost_level().is_cds_agg_enabled(); JB_RETURN(request_client_cache(MessageType::CacheClassLoaderResource, pd->clr_cache_state())); - JB_RETURN(request_client_cache(MessageType::CacheAggressiveCDS, pd->cds_cache_state())); + + JClientCacheState& cds_cache_state = enabling_cds_agg ? pd->agg_cds_cache_state() : pd->dy_cds_cache_state(); + JB_RETURN(request_client_cache(MessageType::CacheAggressiveCDS, cds_cache_state)); JB_RETURN(ss().send_request(MessageType::EndOfCurrentPhase)); return 0; @@ -306,8 +310,10 @@ int ServerMessageHandler::handle_cache_file_sync_task(TRAPS) { int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) { DebugUtils::assert_thread_in_native(); - JClientProgramData* pd = ss().session_data()->program_data(); - JClientCacheState& aot_cache_state = pd->aot_cache_state(); + JClientSessionData* sd = ss().session_data(); + JClientProgramData* pd = sd->program_data(); + bool enabling_aot_pgo = sd->boost_level().is_aot_pgo_enabled(); + JClientCacheState& aot_cache_state = enabling_aot_pgo ? pd->aot_pgo_cache_state() : pd->aot_static_cache_state(); ResourceMark rm(THREAD); GrowableArray klasses_to_compile; GrowableArray methods_to_compile; @@ -321,7 +327,7 @@ int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) { JB_THROW(request_missing_class_loaders(THREAD)); JB_THROW(request_missing_klasses(THREAD)); JB_THROW(request_methods_to_compile(&klasses_to_compile, &methods_to_compile, THREAD)); - if (pd->using_pgo()) { + if (enabling_aot_pgo) { JB_THROW(request_methods_not_compile(&methods_not_compile, THREAD)); JB_THROW(request_method_data(THREAD)); } @@ -338,7 +344,7 @@ int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) { JB_RETURN(try_to_compile_lazy_aot(&klasses_to_compile, &methods_to_compile, &methods_not_compile, - pd->using_pgo(), + enabling_aot_pgo, THREAD)); } else { // not compile in current thread if (aot_cache_state.is_being_generated()) { @@ -358,10 +364,10 @@ int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) { int ServerMessageHandler::try_to_compile_lazy_aot(GrowableArray* klasses_to_compile, GrowableArray* methods_to_compile, GrowableArray* methods_not_compile, - bool use_pgo, + bool enabling_aot_pgo, TRAPS) { JClientProgramData* pd = ss().session_data()->program_data(); - JClientCacheState& aot_cache_state = pd->aot_cache_state(); + JClientCacheState& aot_cache_state = enabling_aot_pgo ? pd->aot_pgo_cache_state() : pd->aot_static_cache_state(); if (klasses_to_compile->is_empty()) { // the expected path without plugin aot_cache_state.set_not_generated(); @@ -376,17 +382,17 @@ int ServerMessageHandler::try_to_compile_lazy_aot(GrowableArray* ThreadInVMfromNative tiv(THREAD); if (methods_to_compile->is_empty()) { - successful = LazyAOT::compile_classes_by_graal(session_id, file_path, klasses_to_compile, use_pgo, THREAD); + successful = LazyAOT::compile_classes_by_graal(session_id, file_path, klasses_to_compile, enabling_aot_pgo, THREAD); } else { successful = LazyAOT::compile_methods_by_graal(session_id, file_path, klasses_to_compile, - methods_to_compile, methods_not_compile, use_pgo, THREAD); + methods_to_compile, methods_not_compile, enabling_aot_pgo, THREAD); } if (successful) { guarantee(!HAS_PENDING_EXCEPTION, "sanity"); chmod(file_path, S_IREAD); aot_cache_state.set_generated(); - log_info(jbooster, compilation)("Successfully comiled %d classes. session_id=%u.", + log_info(jbooster, compilation)("Successfully compiled %d classes. session_id=%u.", klasses_to_compile->length(), ss().session_id()); } else if (HAS_PENDING_EXCEPTION) { diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index c9d3768cd..b5a3bf95d 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -3860,20 +3860,28 @@ JVM_END // JBooster //////////////////////////////////////////////////////////////////////// -JVM_ENTRY(void, JVM_JBoosterInitVM(JNIEnv *env, jint server_port, jint connection_timeout, jint cleanup_timeout, jstring cache_path)) +JVM_ENTRY(void, JVM_JBoosterInitVM(JNIEnv *env, jint server_port, jint connection_timeout, jint cleanup_timeout, jstring cache_path, jstring ssl_key, jstring ssl_cert)) #if INCLUDE_JBOOSTER ResourceMark rm(THREAD); const char* cache_path_c = NULL; if (cache_path != NULL) { cache_path_c = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(cache_path)); } - ServerDataManager::init_phase3(server_port, connection_timeout, cleanup_timeout, cache_path_c, THREAD); + const char* ssl_key_c = NULL; + if (ssl_key != NULL) { + ssl_key_c = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(ssl_key)); + } + const char* ssl_cert_c = NULL; + if (ssl_cert != NULL) { + ssl_cert_c = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(ssl_cert)); + } + ServerDataManager::init_phase3(server_port, connection_timeout, cleanup_timeout, cache_path_c, ssl_key_c, ssl_cert_c, THREAD); #endif // INCLUDE_JBOOSTER JVM_END -JVM_ENTRY(void, JVM_JBoosterHandleConnection(JNIEnv *env, jint connection_fd)) +JVM_ENTRY(void, JVM_JBoosterHandleConnection(JNIEnv *env, jint connection_fd, jlong connection_ssl)) #if INCLUDE_JBOOSTER - ServerDataManager::get().listening_thread()->handle_connection(connection_fd); + ServerDataManager::get().listening_thread()->handle_connection(connection_fd, connection_ssl); #endif // INCLUDE_JBOOSTER JVM_END diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index 43da20b3f..a77f30b8c 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -526,7 +526,7 @@ void before_exit(JavaThread* thread, bool halt) { os::terminate_signal_thread(); #if INCLUDE_CDS - if (DynamicDumpSharedSpaces JBOOSTER_ONLY(&& !(UseJBooster && ClientDataManager::get().is_cds_allowed()))) { + if (DynamicDumpSharedSpaces JBOOSTER_ONLY(&& !(UseJBooster && ClientDataManager::get().boost_level().is_cds_allowed()))) { ExceptionMark em(thread); DynamicArchive::dump(); if (thread->has_pending_exception()) { diff --git a/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java b/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java index 642fbafa6..db5d916ac 100644 --- a/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java +++ b/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java @@ -99,7 +99,8 @@ public final class JBooster { connectionPool = new ConnectionPool(); Main.initForJBooster(); initInVM(options.getServerPort(), options.getConnectionTimeout(), - options.getCleanupTimeout(), options.getCachePath()); + options.getCleanupTimeout(), options.getCachePath(), + options.getSSLKey(), options.getSSLCert()); } private static void loop() { @@ -167,8 +168,8 @@ public final class JBooster { /** * This method is invoked only in C++. */ - private static boolean receiveConnection(int connectionFd) { - return connectionPool.execute(() -> handleConnection(connectionFd)); + private static boolean receiveConnection(int connectionFd, long connectionSSL) { + return connectionPool.execute(() -> handleConnection(connectionFd, connectionSSL)); } /** @@ -198,9 +199,9 @@ public final class JBooster { return false; } - private static native void initInVM(int serverPort, int connectionTimeout, int cleanupTimeout, String cachePath); + private static native void initInVM(int serverPort, int connectionTimeout, int cleanupTimeout, String cachePath, String sslKey, String sslCert); - private static native void handleConnection(int connectionFd); + private static native void handleConnection(int connectionFd, long connectionSSL); static native void printStoredClientData(boolean printAll); diff --git a/src/jdk.jbooster/share/classes/jdk/jbooster/Options.java b/src/jdk.jbooster/share/classes/jdk/jbooster/Options.java index 869e5ca97..f81d69287 100644 --- a/src/jdk.jbooster/share/classes/jdk/jbooster/Options.java +++ b/src/jdk.jbooster/share/classes/jdk/jbooster/Options.java @@ -93,6 +93,18 @@ public final class Options { protected void process(Options options, String arg) { options.interactive = false; } + }, new Option(of("--ssl-key"), "file-path", + "The file path to save server SSL key.") { + @Override + protected void process(Options options, String arg) { + options.sslKey = arg; + } + }, new Option(of("--ssl-cert"), "file-path", + "The file path to save server SSL certificate.") { + @Override + protected void process(Options options, String arg) { + options.sslCert = arg; + } }}; private int serverPort = UNSET_PORT; @@ -100,6 +112,8 @@ public final class Options { private int cleanupTimeout = CLEANUP_TIMEOUT; private String cachePath = null; // set on C++ side private boolean interactive = true; + private String sslKey = null; + private String sslCert = null; public int getServerPort() { return serverPort; @@ -121,6 +135,14 @@ public final class Options { return interactive; } + public String getSSLKey() { + return sslKey; + } + + public String getSSLCert() { + return sslCert; + } + /** * Parse the args of main(). * diff --git a/src/jdk.jbooster/share/native/libjbooster/JBooster.c b/src/jdk.jbooster/share/native/libjbooster/JBooster.c index 0c25710ae..1c489b57b 100644 --- a/src/jdk.jbooster/share/native/libjbooster/JBooster.c +++ b/src/jdk.jbooster/share/native/libjbooster/JBooster.c @@ -27,15 +27,15 @@ #include "jdk_jbooster_JBooster.h" JNIEXPORT void JNICALL -Java_jdk_jbooster_JBooster_initInVM(JNIEnv * env, jclass unused, jint server_port, jint connection_timeout, jint cleanup_timeout, jstring cache_path) +Java_jdk_jbooster_JBooster_initInVM(JNIEnv * env, jclass unused, jint server_port, jint connection_timeout, jint cleanup_timeout, jstring cache_path, jstring ssl_key, jstring ssl_cert) { - JVM_JBoosterInitVM(env, server_port, connection_timeout, cleanup_timeout, cache_path); + JVM_JBoosterInitVM(env, server_port, connection_timeout, cleanup_timeout, cache_path, ssl_key, ssl_cert); } JNIEXPORT void JNICALL -Java_jdk_jbooster_JBooster_handleConnection(JNIEnv * env, jclass unused, jint connection_fd) +Java_jdk_jbooster_JBooster_handleConnection(JNIEnv * env, jclass unused, jint connection_fd, jlong connection_ssl) { - JVM_JBoosterHandleConnection(env, connection_fd); + JVM_JBoosterHandleConnection(env, connection_fd, connection_ssl); } JNIEXPORT void JNICALL diff --git a/test/jdk/tools/jbooster/JBoosterCmdTest.java b/test/jdk/tools/jbooster/JBoosterCmdTest.java index 98439e699..4a2c0801a 100644 --- a/test/jdk/tools/jbooster/JBoosterCmdTest.java +++ b/test/jdk/tools/jbooster/JBoosterCmdTest.java @@ -35,7 +35,7 @@ import static jdk.test.lib.Asserts.*; * /test/lib * @modules jdk.jbooster * @build SimpleClient - * @run main/othervm/timeout=300 JBoosterCmdTest + * @run main/othervm/timeout=5000 JBoosterCmdTest */ public class JBoosterCmdTest extends JBoosterTestBase { diff --git a/test/jdk/tools/jbooster/JBoosterNetTest.java b/test/jdk/tools/jbooster/JBoosterNetTest.java index a71368127..0df0e265f 100644 --- a/test/jdk/tools/jbooster/JBoosterNetTest.java +++ b/test/jdk/tools/jbooster/JBoosterNetTest.java @@ -36,7 +36,7 @@ import static jdk.test.lib.Asserts.*; * /test/lib * @modules jdk.jbooster * @build SimpleClient - * @run main/othervm/timeout=300 JBoosterNetTest + * @run main/othervm/timeout=5000 JBoosterNetTest */ public class JBoosterNetTest extends JBoosterTestBase { diff --git a/test/jdk/tools/jbooster/JBoosterSSLTest.java b/test/jdk/tools/jbooster/JBoosterSSLTest.java new file mode 100644 index 000000000..192acc6dd --- /dev/null +++ b/test/jdk/tools/jbooster/JBoosterSSLTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + import java.io.File; + import java.util.List; + import java.util.ArrayList; + import java.util.concurrent.TimeUnit; + import java.util.regex.Pattern; + +import static jdk.test.lib.Asserts.*; + +/* +* jbooster testing. +* @test +* @summary Test jbooster server +* @library ../lib +* /test/lib +* @modules jdk.jbooster +* @build SimpleClient +* @run main/othervm/timeout=5000 JBoosterSSLTest +*/ +public class JBoosterSSLTest extends JBoosterTestBase { + private static void testSSLCorrectArgs(TestContext ctx) throws Exception { + ArrayList serverArgs = new ArrayList<>(SERVER_STANDARD_ARGS); + + final String sep = File.separator; + String testSrc = System.getProperty("test.src", "") + sep; + + serverArgs.add(serverArgs.size() - 1, String.format("--ssl-cert=%sserver-cert.pem", testSrc)); + serverArgs.add(serverArgs.size() - 1, String.format("--ssl-key=%sserver-key.pem", testSrc)); + Process server = jbooster(ctx, List.of(), serverArgs); + server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + + ArrayList clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS); + clientArgs.add(4, String.format("-XX:JBoosterServerSSLRootCerts=%sserver-cert.pem", testSrc)); + Process client = java(ctx, clientArgs); + client.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS); + + assertEquals(client.exitValue(), 0, "good"); + exitNormallyByCommandQ(server); + } + + private static void testSSLNoArgs(TestContext ctx) throws Exception { + ArrayList serverArgs = new ArrayList<>(SERVER_STANDARD_ARGS); + Process server = jbooster(ctx, List.of(), SERVER_STANDARD_ARGS); + server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + + ArrayList clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS); + Process client = java(ctx, CLIENT_STANDARD_ARGS); + client.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS); + + assertEquals(client.exitValue(), 0, "good"); + exitNormallyByCommandQ(server); + } + + private static void testSSLDifferentCert(TestContext ctx) throws Exception { + ArrayList serverArgs = new ArrayList<>(SERVER_STANDARD_ARGS); + + final String sep = File.separator; + String testSrc = System.getProperty("test.src", "") + sep; + + serverArgs.add(serverArgs.size() - 1, String.format("--ssl-cert=%sserver-cert.pem", testSrc)); + serverArgs.add(serverArgs.size() - 1, String.format("--ssl-key=%sserver-key.pem", testSrc)); + Process server = jbooster(ctx, List.of(), serverArgs); + server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + + ArrayList clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS); + clientArgs.add(4, String.format("-XX:JBoosterServerSSLRootCerts=%sunrelated-cert.pem", testSrc)); + Process client = java(ctx, clientArgs); + client.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS); + + assertNotEquals(client.exitValue(), 0, "Both certs must be the same."); + exitNormallyByCommandQ(server); + } + + private static void testSSLClientNoArg(TestContext ctx) throws Exception { + ArrayList serverArgs = new ArrayList<>(SERVER_STANDARD_ARGS); + + final String sep = File.separator; + String testSrc = System.getProperty("test.src", "") + sep; + + serverArgs.add(serverArgs.size() - 1, String.format("--ssl-cert=%sserver-cert.pem", testSrc)); + serverArgs.add(serverArgs.size() - 1, String.format("--ssl-key=%sserver-key.pem", testSrc)); + Process server = jbooster(ctx, List.of(), serverArgs); + server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + + Process client = java(ctx, CLIENT_STANDARD_ARGS); + client.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS); + + assertNotEquals(client.exitValue(), 0, "Client choose not to use SSL."); + exitNormallyByCommandQ(server); + } + + private static void testSSLServerNoArg(TestContext ctx) throws Exception { + Process server = jbooster(ctx, List.of(), SERVER_STANDARD_ARGS); + + final String sep = File.separator; + String testSrc = System.getProperty("test.src", "") + sep; + + server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + + ArrayList clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS); + clientArgs.add(4, String.format("-XX:JBoosterServerSSLRootCerts=%sserver-cert.pem", testSrc)); + Process client = java(ctx, clientArgs); + client.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS); + + assertNotEquals(client.exitValue(), 0, "Server choose not to use SSL."); + exitNormallyByCommandQ(server); + } + + private static void testSSLServerOneArg(TestContext ctx) throws Exception { + ArrayList serverArgs1 = new ArrayList<>(SERVER_STANDARD_ARGS); + + final String sep = File.separator; + String testSrc = System.getProperty("test.src", "") + sep; + + serverArgs1.add(serverArgs1.size() - 1, String.format("--ssl-cert=%sserver-cert.pem", testSrc)); + Process server1 = jbooster(ctx, List.of(), serverArgs1); + server1.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + assertEquals(server1.exitValue(), 1, "Missing Arg --ssl-key."); + + ArrayList serverArgs2 = new ArrayList<>(SERVER_STANDARD_ARGS); + serverArgs2.add(serverArgs2.size() - 1, String.format("--ssl-key=%sserver-key.pem", testSrc)); + Process server2 = jbooster(ctx, List.of(), serverArgs2); + server2.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + assertEquals(server2.exitValue(), 1, "Missing Arg --ssl-cert."); + } + + public static void main(String[] args) throws Exception { + testCases(JBoosterSSLTest.class); + } +} \ No newline at end of file diff --git a/test/jdk/tools/jbooster/JBoosterSharedCacheTest.java b/test/jdk/tools/jbooster/JBoosterSharedCacheTest.java new file mode 100644 index 000000000..bab3e2fa8 --- /dev/null +++ b/test/jdk/tools/jbooster/JBoosterSharedCacheTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + import java.io.File; + import java.util.List; + import java.util.ArrayList; + import java.util.concurrent.TimeUnit; + import java.util.regex.Pattern; + + import static jdk.test.lib.Asserts.*; + + /* + * jbooster testing. + * @test + * @summary Test jbooster server + * @library ../lib + * /test/lib + * @modules jdk.jbooster + * @build SimpleClient + * @run main/othervm/timeout=5000 JBoosterSharedCacheTest + */ + public class JBoosterSharedCacheTest extends JBoosterTestBase { + + public static boolean checkFileNumAndCacheType(String cacheType, int num) throws Exception { + File dir = new File(SERVER_CACHE_PATH); + File[] fileList = dir.listFiles(); + if (fileList.length != num) { + return false; + } + + if (fileList != null){ + for (File subFile : fileList) { + if (subFile.isFile() && subFile.getName().endsWith(cacheType)){ + return true; + } + } + } + return false; + } + + public static boolean checkCacheFilesSameProgram() throws Exception { + File dir = new File(SERVER_CACHE_PATH); + File[] fileList = dir.listFiles(); + String hash = null; + for (File subFile : fileList) { + String file_hash = subFile.getName().split("-")[2]; + if (hash == null) { + hash = file_hash; + } else { + if (!hash.equals(file_hash)) { + return false; + } + } + } + return true; + } + + private static void testCacheAtLevel1(TestContext ctx) throws Exception { + Process server = jbooster(ctx, List.of("-Xlog:jbooster*=trace"), SERVER_STANDARD_ARGS); + server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + + ArrayList clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS_WITHOUT_LEVEL); + clientArgs.add(4, "-XX:BoostStopAtLevel=1"); + Process p = java(ctx, clientArgs); + p.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS); + + assertEquals(checkFileNumAndCacheType("clr.log", 1), true, "clr not generated."); + exitNormallyByCommandQ(server); + } + + private static void testCacheAtLevel2(TestContext ctx) throws Exception { + Process server = jbooster(ctx, List.of("-Xlog:jbooster*=trace"), SERVER_STANDARD_ARGS); + server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + + ArrayList clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS_WITHOUT_LEVEL); + clientArgs.add(4, "-XX:BoostStopAtLevel=2"); + Process p = java(ctx, clientArgs); + p.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS); + + assertEquals(checkFileNumAndCacheType("cds-agg.jsa", 2), true, "cds-agg not generated."); + exitNormallyByCommandQ(server); + } + + private static void testCacheAtLevel3(TestContext ctx) throws Exception { + Process server = jbooster(ctx, List.of("-Xlog:jbooster*=trace"), SERVER_STANDARD_ARGS); + server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + + ArrayList clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS_WITHOUT_LEVEL); + clientArgs.add(4, "-XX:BoostStopAtLevel=3"); + Process p = java(ctx, clientArgs); + p.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS); + + Thread.currentThread().sleep(5000); + assertEquals(checkFileNumAndCacheType("aot-static.so", 3), true, "aot-static not generated."); + exitNormallyByCommandQ(server); + } + + private static void testCacheAtLevel4(TestContext ctx) throws Exception { + Process server = jbooster(ctx, List.of("-Xlog:jbooster*=trace"), SERVER_STANDARD_ARGS); + server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + + ArrayList clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS_WITHOUT_LEVEL); + clientArgs.add(4, "-XX:BoostStopAtLevel=4"); + Process p = java(ctx, clientArgs); + p.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS); + + Thread.currentThread().sleep(5000); + assertEquals(checkFileNumAndCacheType("aot-pgo.so", 4), true, "aot-pgo not generated."); + exitNormallyByCommandQ(server); + } + + private static void testCacheWithDyCDS(TestContext ctx) throws Exception { + Process server = jbooster(ctx, List.of("-Xlog:jbooster*=trace"), SERVER_STANDARD_ARGS); + server.waitFor(WAIT_START_TIME, TimeUnit.SECONDS); + + ArrayList clientArgs = new ArrayList<>(CLIENT_STANDARD_ARGS_WITHOUT_LEVEL); + clientArgs.add(4, "-XX:BoostStopAtLevel=4"); + clientArgs.add(5, "-XX:-UseAggressiveCDS"); + Process p = java(ctx, clientArgs); + p.waitFor(WAIT_EXIT_TIME, TimeUnit.SECONDS); + + assertEquals(checkFileNumAndCacheType("cds-dy.jsa", 5), true, "cds-dy not generated."); + assertEquals(checkCacheFilesSameProgram(), true, "hash not same."); + exitNormallyByCommandQ(server); + } + + public static void main(String[] args) throws Exception { + testCases(JBoosterSharedCacheTest.class); + } + } diff --git a/test/jdk/tools/jbooster/JBoosterTestBase.java b/test/jdk/tools/jbooster/JBoosterTestBase.java index 8f925d7f3..08792a77b 100644 --- a/test/jdk/tools/jbooster/JBoosterTestBase.java +++ b/test/jdk/tools/jbooster/JBoosterTestBase.java @@ -67,6 +67,9 @@ public class JBoosterTestBase { "SimpleClient" ); + public static final List CLIENT_STANDARD_ARGS_WITHOUT_LEVEL = CLIENT_STANDARD_ARGS.stream() + .filter(s -> !"-XX:BoostStopAtLevel=4".equals(s)).toList(); + public static final List CLIENT_OFFLINE_ARGS = List.of( "-XX:+UnlockExperimentalVMOptions", "-XX:+UseJBooster", @@ -84,7 +87,7 @@ public class JBoosterTestBase { public static Process jbooster(TestContext ctx, List vmArgs, List jboosterArgs) throws Exception { JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jbooster"); - launcher.addVMArgs(Utils.getTestJavaOpts()); + // launcher.addVMArgs(Utils.getTestJavaOpts()); if (vmArgs != null) { for (String vmArg : vmArgs) { launcher.addVMArg(vmArg); @@ -151,6 +154,7 @@ public class JBoosterTestBase { } finally { for (Process p : ctx.getProcesses()) { if (p.isAlive()) { + p.waitFor(WAIT_SHORT_TIME, TimeUnit.SECONDS); p.destroyForcibly(); } } diff --git a/test/jdk/tools/jbooster/server-cert.pem b/test/jdk/tools/jbooster/server-cert.pem new file mode 100644 index 000000000..923cf333a --- /dev/null +++ b/test/jdk/tools/jbooster/server-cert.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDjTCCAnWgAwIBAgIUUo4hM/1j2s4ZT0VPHU/1rOzu5DIwDQYJKoZIhvcNAQEL +BQAwVjELMAkGA1UEBhMCY24xETAPBgNVBAgMCHNoYW5naGFpMREwDwYDVQQHDAhz +aGFuZ2hhaTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTI0 +MDYyNjEwMDcxNVoXDTI1MDYyNjEwMDcxNVowVjELMAkGA1UEBhMCY24xETAPBgNV +BAgMCHNoYW5naGFpMREwDwYDVQQHDAhzaGFuZ2hhaTEhMB8GA1UECgwYSW50ZXJu +ZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAoZ3+SQavSX6hZXLJtDlXe1TrNROWxySmnL3FBuEEH7SlwOoVxRW1P+ZivPp4 +vjnWDXaafb5yVc0w7A+6Clt/OFrgvhw92quxHnGGvy3IxNMdgL2lNZ6gjeUXs2IA +59FdboSgDbJvJAcemq7v2UhbAAmq47+pQ+ZtVnF2LCN424PObGlnxJDDVb+vWTF9 +DlUvvkv3XW8anP5iPnZ0Ou91Lu4WTSvD2TZCDUVWrP52jj9H08WlTA8SUOxluixu +f4SJ0WO767VABBkYAZ+/4fERZL4PSf6l1XLjJBFEb0rn1dECEe559OHPHjBZly0i +t39Fc8kCfTxKVjdpBwhC98gCyQIDAQABo1MwUTAdBgNVHQ4EFgQU4fQgXJlXPnbA +TlDDncohnRoP7mMwHwYDVR0jBBgwFoAU4fQgXJlXPnbATlDDncohnRoP7mMwDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEALbIy4RBXvkej98ZoxshC +VbrVQdjTY9DkZIOIOHn2jwwyiezSI+Aff+mg0XgWEB+pC7i1CnqOk0EW2pUsTmvd +fY2fUCrGr7mH58mq5ADwOURByPtpstFtjWNcUuiqoKGwP+hP64mf+gY8r7Gc9k9V +zCS0e1r4i87kW2pvqdY9aJ5xNOb6PfWc31c5f8306MfnFiy/U5m2lGCs0KVkwjtm +3Xm5hI3OYYdZ5c4mHGtVmFnzLz+moxywWu6vXYTcuDe6v2JRJ2ZB6znwNOWO56RR +WhEssi4Szig1206d5idUgAB8OwttUtEMtT+labAvUKeeI0eiYlpsgyMbrW0VE4qQ +bg== +-----END CERTIFICATE----- diff --git a/test/jdk/tools/jbooster/server-key.pem b/test/jdk/tools/jbooster/server-key.pem new file mode 100644 index 000000000..77bf13bb3 --- /dev/null +++ b/test/jdk/tools/jbooster/server-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAoZ3+SQavSX6hZXLJtDlXe1TrNROWxySmnL3FBuEEH7SlwOoV +xRW1P+ZivPp4vjnWDXaafb5yVc0w7A+6Clt/OFrgvhw92quxHnGGvy3IxNMdgL2l +NZ6gjeUXs2IA59FdboSgDbJvJAcemq7v2UhbAAmq47+pQ+ZtVnF2LCN424PObGln +xJDDVb+vWTF9DlUvvkv3XW8anP5iPnZ0Ou91Lu4WTSvD2TZCDUVWrP52jj9H08Wl +TA8SUOxluixuf4SJ0WO767VABBkYAZ+/4fERZL4PSf6l1XLjJBFEb0rn1dECEe55 +9OHPHjBZly0it39Fc8kCfTxKVjdpBwhC98gCyQIDAQABAoIBAEOMJB5jY9mkylH7 +QuBHYw/R8yhQ0qDS6avzCKkSXMXfm7NgYs7nfsSBRt1TFinzREqGOpW5hlHkG8Fd +5VS03xwvp2TtqtB9F97wde/rc9EHp3oKSUV60gHcMSaxHE3HTHSHi9mNrTPyodDm +sqouupHueHUNwvH1GdeaPli+TqH373vknnrPJENsz2dWrLlkeY3EIAud1NnFcuWV +FLhvYybAtb9xrq11TcXZwir9/2/mxppwDT1NyQ50YVgmV8obtXhvAbV4gXad1ivx +cTUq/Dc7qHKjttfC/wcTNS7HQmzekl2096pWNAZhOgjxdooxOf81nxk+gHF1IjtP +LVKyZG0CgYEA13rdC+6EV8RO4+djgJ5NObOZOx9Pvq3Q5R7b8ZlccBTfK7D2lM2d +jDcQK9up/WUH8t1a7BDMz8/NnSsYHL4SACe5NtM9XtUSMvzHXXjiCCa8NUs9Ii1C +93eMHAKekkOALnw8cS3VkjJ99gxbF1H3qWqZ9aDTHbIhi9WbJcdbtPcCgYEAwAIx +Whf/llcQX0ooWAw9lJP6K2rYS8wW6V6/Cp830v7v5FZlvsJvZfHNRoM7a+/pueh+ +jx+yZC+D2rtwZebWLkspsQI0KuB4SK3HvzPUqBPncT2pyg6Vv6vwQLvjC21tMvzM +hIup52Xp9QNmUQKE2cNVl0AegG3wFwEOYCyQ1j8CgYAEVV44rTVQJoyHnNGtdoGL +FYeRXtHVvd0jnnlB5JmtT14lnMt4tqHifgD/QM2sYOnGApmfgb78tuslrAYyHchy +5FmfNqRXUeWpzNedk57IFy9VywuRsmNUYr0YmxzhSCY9yRXWGNvgss9BsYHreCSI +7bHm9LMKN9jg3Qzft6CqhQKBgQCagek2x3L7hqn9FA6s84SmSAGa6IqPS/bv6jcv +E/p3BoECLGgJfiroTRDTegzaCZ/54tXc1DPYHMgsvoJu7bdSX1d4Qf66thD04yqG +eO3aJtIqNOWpW90y9OgLH2ZPrsmdqwHkcwLQ2xjN+eNesvk2xtHcOVOSI2V9DXOE +/re6PwKBgQC0x6sw/egYWibdM815zRZ1onvQNm1XiyTc4XBAwD3wMGcFsRzjmEJs +/eRNGCP3uTaixF+JueLI3bap5fouk9m2wLezrkSkUZQT6qQMQe6APBPRWqHNdWRr +WodIiUX8toXwajlJAOZwvzUaqDrW3pIfiv9yQIHfyAaHzpnX4m9/uQ== +-----END RSA PRIVATE KEY----- diff --git a/test/jdk/tools/jbooster/unrelated-cert.pem b/test/jdk/tools/jbooster/unrelated-cert.pem new file mode 100644 index 000000000..a865fe54c --- /dev/null +++ b/test/jdk/tools/jbooster/unrelated-cert.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDjTCCAnWgAwIBAgIUUZE/fNRyso3SrZMwXumPUplx03IwDQYJKoZIhvcNAQEL +BQAwVjELMAkGA1UEBhMCY24xETAPBgNVBAgMCHNoYW5naGFpMREwDwYDVQQHDAhz +aGFuZ2hhaTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTI0 +MDYyNjEwMDc0MloXDTI1MDYyNjEwMDc0MlowVjELMAkGA1UEBhMCY24xETAPBgNV +BAgMCHNoYW5naGFpMREwDwYDVQQHDAhzaGFuZ2hhaTEhMB8GA1UECgwYSW50ZXJu +ZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAsAT1DkzNXE1kPiO3RZK4HnUROwa0dAaylFb5B5CxsuTSkR+j5Jl9syyoRnRf +tu+GZ0MsA4OG5BbSxEZjiHtgEJO7FgvvxSCade0cD/OqQqMY9bnX+nhbW++JCRNc +WcHlZODSxuQjYNdQOi/+Y4vKJhvlbHFujRpKqb6zbfehIjRTXNCCZInno2gcAV/f +JWVT6umhTXHqH82UnsaLGYELOLrpuXAVGxu9ThCa8GInM9/rMrlk8ejSU6bx/bh9 +FajFfGIcdOa8uDFQGLiPaRg6IAncSRLruurJIWJ8CrXQSMnUUCjlHy07vNrJnnXr +ONZdJLMDY12x0Ss2LIGuHE+rDQIDAQABo1MwUTAdBgNVHQ4EFgQUV7nqiMC46+Wp +z+Sa+6522O+jGQ0wHwYDVR0jBBgwFoAUV7nqiMC46+Wpz+Sa+6522O+jGQ0wDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAb6nhPg0WBQyDKXsX0tAS +Al11vKHrzLd3/KqAzrb78YZKmQIHb6jjwYz/S5CBuHsxq37MIGSmZlr0VMgnOTTq +WO2KpEZBQAIAEV2JOMkSzkjhQA3Ftwon8phuEghiODW2dFLtFv+NdS4crJ4A9jFa +XnFhQlWqA0WUr98ZZWjpCXxE+SFjY+FGvR19GCDF1iOQPSmV2fr57gxGD9R7M38L +jgR/2TzNxR8+vVeC0V4R0wOZJsacxdJBn3XgvsJIhm3npnlWgtL1ND7cH9VVB/H7 +P2THAgyviUEbHL4LuZbIIONJPQqMwnNUAprDgcVWQG/Fgvt8mPUO/ksCs1uOGFEX +9Q== +-----END CERTIFICATE----- -- 2.22.0