src: make InitializeOncePerProcess more flexible

PR-URL: https://github.com/nodejs/node/pull/38888
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Shelley Vohr
2021-06-01 14:47:03 +02:00
parent d07c12f444
commit d8d1d9631b
2 changed files with 82 additions and 49 deletions

View File

@@ -233,7 +233,7 @@ int Environment::InitializeInspector(
return 0;
}
#endif // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
#endif // HAVE_INSPECTOR
#define ATOMIC_WAIT_EVENTS(V) \
V(kStartWait, "started") \
@@ -957,12 +957,26 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
}
InitializationResult InitializeOncePerProcess(int argc, char** argv) {
return InitializeOncePerProcess(argc, argv, kDefaultInitialization);
}
InitializationResult InitializeOncePerProcess(
int argc,
char** argv,
InitializationSettingsFlags flags) {
uint64_t init_flags = flags;
if (init_flags & kDefaultInitialization) {
init_flags = init_flags | kInitializeV8 | kInitOpenSSL | kRunPlatformInit;
}
// Initialized the enabled list for Debug() calls with system
// environment variables.
per_process::enabled_debug_list.Parse(nullptr);
atexit(ResetStdio);
PlatformInit();
if (init_flags & kRunPlatformInit)
PlatformInit();
CHECK_GT(argc, 0);
@@ -1015,65 +1029,71 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) {
return result;
}
if (init_flags & kInitOpenSSL) {
#if HAVE_OPENSSL
{
std::string extra_ca_certs;
if (credentials::SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs))
crypto::UseExtraCaCerts(extra_ca_certs);
}
// In the case of FIPS builds we should make sure
// the random source is properly initialized first.
{
std::string extra_ca_certs;
if (credentials::SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs))
crypto::UseExtraCaCerts(extra_ca_certs);
}
// In the case of FIPS builds we should make sure
// the random source is properly initialized first.
#if OPENSSL_VERSION_MAJOR >= 3
// Call OPENSSL_init_crypto to initialize OPENSSL_INIT_LOAD_CONFIG to
// avoid the default behavior where errors raised during the parsing of the
// OpenSSL configuration file are not propagated and cannot be detected.
//
// If FIPS is configured the OpenSSL configuration file will have an .include
// pointing to the fipsmodule.cnf file generated by the openssl fipsinstall
// command. If the path to this file is incorrect no error will be reported.
//
// For Node.js this will mean that EntropySource will be called by V8 as part
// of its initialization process, and EntropySource will in turn call
// CheckEntropy. CheckEntropy will call RAND_status which will now always
// return 0, leading to an endless loop and the node process will appear to
// hang/freeze.
std::string env_openssl_conf;
credentials::SafeGetenv("OPENSSL_CONF", &env_openssl_conf);
// Call OPENSSL_init_crypto to initialize OPENSSL_INIT_LOAD_CONFIG to
// avoid the default behavior where errors raised during the parsing of the
// OpenSSL configuration file are not propagated and cannot be detected.
//
// If FIPS is configured the OpenSSL configuration file will have an
// .include pointing to the fipsmodule.cnf file generated by the openssl
// fipsinstall command. If the path to this file is incorrect no error
// will be reported.
//
// For Node.js this will mean that EntropySource will be called by V8 as
// part of its initialization process, and EntropySource will in turn call
// CheckEntropy. CheckEntropy will call RAND_status which will now always
// return 0, leading to an endless loop and the node process will appear to
// hang/freeze.
std::string env_openssl_conf;
credentials::SafeGetenv("OPENSSL_CONF", &env_openssl_conf);
bool has_cli_conf = !per_process::cli_options->openssl_config.empty();
if (has_cli_conf || !env_openssl_conf.empty()) {
OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
OPENSSL_INIT_set_config_file_flags(settings, CONF_MFLAGS_DEFAULT_SECTION);
if (has_cli_conf) {
const char* conf = per_process::cli_options->openssl_config.c_str();
OPENSSL_INIT_set_config_filename(settings, conf);
}
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, settings);
OPENSSL_INIT_free(settings);
bool has_cli_conf = !per_process::cli_options->openssl_config.empty();
if (has_cli_conf || !env_openssl_conf.empty()) {
OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
OPENSSL_INIT_set_config_file_flags(settings, CONF_MFLAGS_DEFAULT_SECTION);
if (has_cli_conf) {
const char* conf = per_process::cli_options->openssl_config.c_str();
OPENSSL_INIT_set_config_filename(settings, conf);
}
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, settings);
OPENSSL_INIT_free(settings);
if (ERR_peek_error() != 0) {
result.exit_code = ERR_GET_REASON(ERR_peek_error());
result.early_return = true;
fprintf(stderr, "OpenSSL configuration error:\n");
ERR_print_errors_fp(stderr);
return result;
if (ERR_peek_error() != 0) {
result.exit_code = ERR_GET_REASON(ERR_peek_error());
result.early_return = true;
fprintf(stderr, "OpenSSL configuration error:\n");
ERR_print_errors_fp(stderr);
return result;
}
}
}
#else
if (FIPS_mode()) {
OPENSSL_init();
}
if (FIPS_mode()) {
OPENSSL_init();
}
#endif
// V8 on Windows doesn't have a good source of entropy. Seed it from
// OpenSSL's pool.
V8::SetEntropySource(crypto::EntropySource);
// V8 on Windows doesn't have a good source of entropy. Seed it from
// OpenSSL's pool.
V8::SetEntropySource(crypto::EntropySource);
#endif // HAVE_OPENSSL
}
per_process::v8_platform.Initialize(
static_cast<int>(per_process::cli_options->v8_thread_pool_size));
V8::Initialize();
if (init_flags & kInitializeV8) {
V8::Initialize();
}
performance::performance_v8_start = PERFORMANCE_NOW();
per_process::v8_initialized = true;
return result;
}

View File

@@ -316,7 +316,20 @@ struct InitializationResult {
std::vector<std::string> exec_args;
bool early_return = false;
};
enum InitializationSettingsFlags : uint64_t {
kDefaultInitialization = 1 << 0,
kInitializeV8 = 1 << 1,
kRunPlatformInit = 1 << 2,
kInitOpenSSL = 1 << 3
};
// TODO(codebytere): eventually document and expose to embedders.
InitializationResult InitializeOncePerProcess(int argc, char** argv);
InitializationResult InitializeOncePerProcess(
int argc,
char** argv,
InitializationSettingsFlags flags);
void TearDownOncePerProcess();
void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s);
void SetIsolateMiscHandlers(v8::Isolate* isolate, const IsolateSettings& s);