From 559737354c252ac39c80e51e5b8124a19e4a4cd4 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Wed, 21 Oct 2026 18:24:04 +0200 Subject: [PATCH 1/2] Revert "test: mark worker init failure flaky on SmartOS" This reverts commit 6ecfd6587d3dadc6a4f21bbfa5b7a014bb9b5d1d. --- test/parallel/parallel.status | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index 6ad0e2b29f9d..15fc53543b03 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -38,8 +38,6 @@ test-crypto-keygen: SKIP test-debugger-heap-profiler: PASS, FLAKY [$system==solaris] # Also applies to SmartOS -# https://github.com/nodejs/node/pull/66282#issuecomment-5833089308 -test-worker-init-failure: PASS, FLAKY # https://github.com/nodejs/node/issues/43457 test-domain-no-error-handler-abort-on-uncaught-0: PASS, FLAKY test-domain-no-error-handler-abort-on-uncaught-1: PASS,FLAKY From 678108813e3219ada5c4da3d32ac83a6734711cf Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Wed, 21 Oct 2026 18:24:04 +0200 Subject: [PATCH 2/2] Revert "src: seed V8 from the OS CSPRNG instead of OpenSSL's DRBG" This reverts commit 43d3fe95581cb599611dc8e1aae9a79a900998b8. --- src/node.cc | 36 ++++--------------- .../test-legacy-provider-option.js | 3 -- .../openssl3-conf/random_unavailable.cnf | 7 ---- test/parallel/test-crypto-no-algorithm.js | 18 ---------- test/parallel/test-crypto-secure-heap.js | 35 ------------------ 5 files changed, 6 insertions(+), 93 deletions(-) delete mode 100644 test/fixtures/openssl3-conf/random_unavailable.cnf diff --git a/src/node.cc b/src/node.cc index e2efaad8a20c..f7a19747bed6 100644 --- a/src/node.cc +++ b/src/node.cc @@ -50,9 +50,6 @@ #if HAVE_OPENSSL #include "ncrypto.h" -#if OPENSSL_VERSION_MAJOR >= 3 -#include -#endif #include "node_crypto.h" #if OPENSSL_VERSION_MAJOR >= 3 && !defined(CONF_MFLAGS_IGNORE_MISSING_FILE) // OpenSSL hides this deprecated macro under OPENSSL_NO_DEPRECATED, but the @@ -1393,36 +1390,15 @@ InitializeOncePerProcessInternal( } crypto::InstallFipsIndicatorCallback(); - // Activating the default provider here keeps --openssl-legacy-provider - // working. Its explicit load disables OpenSSL's fallback, and the eager - // CSPRNG check used to activate the provider as a side effect. Only - // check the seeding when that provider is missing or FIPS is on, so a - // configuration without a DRBG still aborts at startup instead of - // hanging at the first crypto call. Otherwise the DRBG is instantiated - // on first use. -#if OPENSSL_VERSION_MAJOR >= 3 - const bool check_csprng = ncrypto::isFipsEnabled() || - !OSSL_PROVIDER_available(nullptr, "default"); -#else - const bool check_csprng = true; -#endif - if (check_csprng) { - CHECK(ncrypto::CSPRNG(nullptr, 0)); - } + // Ensure CSPRNG is properly seeded. + CHECK(ncrypto::CSPRNG(nullptr, 0)); - // V8 uses the entropy for hash seeds, ASLR and Math.random(), none of - // it cryptographic. Going through OpenSSL would instantiate the DRBG - // and build the default provider's algorithm tables on every startup. - // V8 falls back to very weak entropy when the source fails, so abort - // instead. V8::SetEntropySource([](unsigned char* buffer, size_t length) { -#ifdef _AIX - // uv_random() reads /dev/random on AIX, which blocks. OpenSSL seeds - // from /dev/urandom there. + // V8 falls back to very weak entropy when this function fails + // and /dev/urandom isn't available. That wouldn't be so bad if + // the entropy was only used for Math.random() but it's also used for + // hash table and address space layout randomization. Better to abort. CHECK(ncrypto::CSPRNG(buffer, length)); -#else - CHECK_EQ(uv_random(nullptr, nullptr, buffer, length, 0, nullptr), 0); -#endif return true; }); #endif // !defined(OPENSSL_IS_BORINGSSL) diff --git a/test/addons/openssl-providers/test-legacy-provider-option.js b/test/addons/openssl-providers/test-legacy-provider-option.js index 1f01ce55a8f2..5ad60dac9b86 100644 --- a/test/addons/openssl-providers/test-legacy-provider-option.js +++ b/test/addons/openssl-providers/test-legacy-provider-option.js @@ -22,6 +22,3 @@ if (getFips()) { common.skip('this test cannot be run in FIPS mode'); } providers.testProviderPresent('legacy'); -// The explicit legacy load disables OpenSSL's provider fallback, so the -// default provider has to be active before it runs. -providers.testProviderPresent('default'); diff --git a/test/fixtures/openssl3-conf/random_unavailable.cnf b/test/fixtures/openssl3-conf/random_unavailable.cnf deleted file mode 100644 index a2dc8d2c9ffa..000000000000 --- a/test/fixtures/openssl3-conf/random_unavailable.cnf +++ /dev/null @@ -1,7 +0,0 @@ -nodejs_conf = nodejs_init - -[nodejs_init] -random = random_sect - -[random_sect] -random = NO-SUCH-DRBG diff --git a/test/parallel/test-crypto-no-algorithm.js b/test/parallel/test-crypto-no-algorithm.js index 0354aad8b0be..06aab7614ff5 100644 --- a/test/parallel/test-crypto-no-algorithm.js +++ b/test/parallel/test-crypto-no-algorithm.js @@ -57,21 +57,3 @@ if (isMainThread) { assert(common.nodeProcessAborted(cp.status, cp.signal), `process did not abort, code:${cp.status} signal:${cp.signal}`); } - -// AIX keeps OpenSSL as V8's entropy source, so a DRBG that cannot be -// fetched still aborts at startup there. -if (!common.isAIX) { - // A configuration whose random section names a DRBG that cannot be - // fetched starts normally; the first crypto call fails, without a hang. - const fixtures = require('../common/fixtures'); - const { spawnSync } = require('node:child_process'); - const randomConf = fixtures.path('openssl3-conf', 'random_unavailable.cnf'); - const cp = spawnSync(process.execPath, - [ `--openssl-config=${randomConf}`, '-e', - 'require("node:crypto").randomBytes(8)' ], - { encoding: 'utf8' }); - assert(!common.nodeProcessAborted(cp.status, cp.signal), - `process aborted, code:${cp.status} signal:${cp.signal}`); - assert.strictEqual(cp.status, 1); - assert.match(cp.stderr, /unable to fetch drbg/); -} diff --git a/test/parallel/test-crypto-secure-heap.js b/test/parallel/test-crypto-secure-heap.js index 3c79d1bb8a6d..22f90b6be99f 100644 --- a/test/parallel/test-crypto-secure-heap.js +++ b/test/parallel/test-crypto-secure-heap.js @@ -70,28 +70,6 @@ if (process.argv[2] === 'child') { return; } -if (process.argv[2] === 'workers') { - // Eight Workers held alive at once. A 1 KiB secure heap has room for a - // few DRBGs only, so an isolate setup that drew its entropy through - // OpenSSL would fail for the later Workers and abort the process. - const { Worker } = require('worker_threads'); - const i32 = new Int32Array(new SharedArrayBuffer(4)); - let online = 0; - for (let i = 0; i < 8; i++) { - const worker = new Worker( - 'const { workerData } = require("worker_threads");' + - 'Atomics.wait(workerData.i32, 0, 0);', - { eval: true, workerData: { i32 } }); - worker.on('online', () => { - if (++online === 8) { - Atomics.store(i32, 0, 1); - Atomics.notify(i32, 0); - } - }); - } - return; -} - const child = fork( process.argv[1], ['child'], @@ -101,19 +79,6 @@ child.on('exit', common.mustCall((code) => { assert.strictEqual(code, 0); })); -// AIX keeps OpenSSL as V8's entropy source, so a Worker's isolate setup -// still draws on the secure heap there. -if (!common.isAIX) { - const child = fork( - process.argv[1], - ['workers'], - { execArgv: ['--secure-heap=1024', '--secure-heap-min=4'] }); - child.on('exit', common.mustCall((code, signal) => { - assert.strictEqual(signal, null); - assert.strictEqual(code, 0); - })); -} - { const child = fork(fixtures.path('a.js'), { execArgv: ['--secure-heap=3', '--secure-heap-min=3'],