benchmark: protect against accidental fork bomb

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: https://github.com/nodejs/node/pull/66132
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
James M Snell committed 2026-09-26 21:18:45 +00:00
1 parent f378cfcfbf
commit d1960949bb
1 file changed
+30 -1
+30 -1
View File
@@ -198,6 +198,21 @@ class Benchmark {
}
_run() {
// A forked child is told to run the benchmark function directly, rather
// than build its own queue and fork again, through the
// NODE_RUN_BENCHMARK_FN environment variable. A child always inherits
// this.flags in its execArgv, so reaching _run() with those flags already
// applied means the variable did not survive to the child and every
// generation would keep forking. Fail loudly instead of forking forever.
if (process.send &&
this.flags.length > 0 &&
this.flags.every((flag) => process.execArgv.includes(flag))) {
throw new Error(
'Benchmark child process was started with the benchmark flags but ' +
'without NODE_RUN_BENCHMARK_FN, refusing to fork again. Something ' +
'removed the variable from the child environment.');
}
// If forked, report to the parent.
if (process.send) {
process.send({
@@ -213,6 +228,20 @@ class Benchmark {
this.originalOptions.setup(this.queue);
}
// Enforcing the permission model removes the environment variables
// --allow-env does not grant access to at startup, which would drop the
// NODE_RUN_BENCHMARK_FN set below. The child only ever sees the
// environment this process hands it, so granting access to all of it does
// not widen what the benchmark can reach. Audit mode removes nothing, so
// it is left alone to keep its diagnostics intact.
const childExecArgv = this.flags.concat(process.execArgv);
const enforcesPermission = (arg) =>
arg === '--permission' || arg.startsWith('--permission=');
if (childExecArgv.some(enforcesPermission) &&
!childExecArgv.some((arg) => arg.startsWith('--allow-env'))) {
childExecArgv.push('--allow-env=*');
}
const recursive = (queueIndex) => {
const config = this.queue[queueIndex];
@@ -233,7 +262,7 @@ class Benchmark {
const child = child_process.fork(require.main.filename, childArgs, {
env: childEnv,
execArgv: this.flags.concat(process.execArgv),
execArgv: childExecArgv,
});
child.on('message', sendResult);
child.on('close', (code) => {