-
Notifications
You must be signed in to change notification settings - Fork 5k
node:zlib: block worker shutdown on in-flight async compression (UAF) #35155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 1 commit
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
dd2e822
node:zlib: block worker shutdown on in-flight async compression
robobun 49cc64d
[autofix.ci] apply automated fixes
autofix-ci[bot] 392105e
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] 7ec87e9
[autofix.ci] apply automated fixes (attempt 3/3)
autofix-ci[bot] bb6a570
test: drop jitter sleep, trim comment, reject on early worker error/exit
robobun 67272f0
[autofix.ci] apply automated fixes
autofix-ci[bot] a157772
Release queued zlib completions at worker shutdown
robobun 12f4d39
test: add zstdCompress lane so NativeZstd tag is also exercised
robobun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| import { test, expect } from "bun:test"; | ||
| import { bunEnv, bunExe, isASAN } from "harness"; | ||
|
|
||
| // Regression test for a heap-use-after-free when a Worker is terminated | ||
| // while async node:zlib operations (gzip/brotliCompress/deflate) are running | ||
| // on the thread pool. The pool-thread completion callback dereferenced the | ||
| // worker's VirtualMachine/EventLoop after WebWorker::shutdown had already | ||
| // freed it: | ||
| // | ||
| // heap-use-after-free READ of size 8 thread T16 (Bun Pool 2) | ||
| // #0 event_loop src/jsc/VirtualMachine.rs | ||
| // #1 async_job_run<NativeBrotli> src/runtime/node/node_zlib_binding.rs | ||
| // freed by thread (Worker): WebWorker::shutdown src/jsc/web_worker.rs | ||
| // | ||
| // Keeping several codecs in flight at once makes the do_work() window wide | ||
| // enough that terminate() reliably lands inside it. | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| test( | ||
| "worker.terminate() during in-flight node:zlib async compression does not UAF", | ||
| async () => { | ||
| // ASAN poisons the freed VM immediately; a couple of rounds are enough. | ||
| // Release builds need the freed page to be reused/unmapped, which takes a | ||
| // few more. | ||
| const ROUNDS = isASAN ? 4 : 10; | ||
|
|
||
| const script = /* js */ ` | ||
| const { Worker } = require("node:worker_threads"); | ||
| const src = \` | ||
| const { parentPort } = require("node:worker_threads"); | ||
| const zlib = require("node:zlib"); | ||
| const { promisify } = require("node:util"); | ||
| const gz = promisify(zlib.gzip); | ||
| const br = promisify(zlib.brotliCompress); | ||
| const df = promisify(zlib.deflate); | ||
| const big = Buffer.alloc(16 << 20, 0x61); | ||
| const lanes = (n, f) => { | ||
| for (let i = 0; i < n; i++) | ||
| (async () => { for (;;) { try { await f(); } catch {} } })(); | ||
| }; | ||
| lanes(2, () => gz(big)); | ||
| lanes(1, () => br(big.subarray(0, 4 << 20))); | ||
| lanes(2, () => df(big.subarray(0, 10 << 20))); | ||
| parentPort.postMessage("up"); | ||
| \`; | ||
| (async () => { | ||
| for (let r = 0; r < ${ROUNDS}; r++) { | ||
| const w = new Worker(src, { eval: true }); | ||
| await new Promise(res => w.once("message", res)); | ||
| await Bun.sleep(60 + (r * 41) % 220); | ||
| await w.terminate(); | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| } | ||
| console.log("ok"); | ||
| })().catch(e => { | ||
| console.error(e); | ||
| process.exit(1); | ||
| }); | ||
| `; | ||
|
|
||
| await using proc = Bun.spawn({ | ||
| cmd: [bunExe(), "-e", script], | ||
| env: bunEnv, | ||
| stdout: "pipe", | ||
| stderr: "pipe", | ||
| }); | ||
| const [stdout, stderr, exitCode] = await Promise.all([ | ||
| proc.stdout.text(), | ||
| proc.stderr.text(), | ||
| proc.exited, | ||
| ]); | ||
|
|
||
| expect(stderr).not.toContain("heap-use-after-free"); | ||
| expect(stderr).not.toContain("AddressSanitizer"); | ||
| expect({ stdout: stdout.trim(), exitCode }).toEqual({ stdout: "ok", exitCode: 0 }); | ||
| }, | ||
| // Per-test override: each round starts a Worker under ASAN and compresses a | ||
| // 16 MiB buffer; the default 5s is too short for that even once. | ||
| 60_000, | ||
| ); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.