Skip to content

src: fix use-after-free in CleanupHookThunkRun - #65196

Open
sreehariannam wants to merge 1 commit into
nodejs:mainfrom
sreehariannam:fix-cleanup-hook-thunk-uaf
Open

src: fix use-after-free in CleanupHookThunkRun#65196
sreehariannam wants to merge 1 commit into
nodejs:mainfrom
sreehariannam:fix-cleanup-hook-thunk-uaf

Conversation

@sreehariannam

@sreehariannam sreehariannam commented Aug 10, 2026

Copy link
Copy Markdown

Summary

CleanupHookThunkRun() read thunk->isolate / thunk->fun / thunk->arg
from the CleanupHookThunk after invoking thunk->fun(). For every
node::ObjectWrap still alive at teardown, thunk->fun is
ObjectWrap::CleanupHook, which deletes the wrap. Since #63642,
~ObjectWrap() calls RemoveEnvironmentCleanupHook() itself, which erases
the CleanupHookThunk from cleanup_hook_registry and frees the node it
lives in. The subsequent read to make the (now redundant) second
RemoveEnvironmentCleanupHook() call was therefore a use-after-free — this
is now the ordinary teardown path for every ObjectWrap-based addon, not an
edge case.

The fix caches isolate/fun/arg before invoking the hook, so nothing is
read from thunk once it may have already been freed.

Root cause and fix as diagnosed in the issue.

Fixes: #65195

Test plan

  • test/addons/worker-addon-exit (built with node-gyp, run under
    valgrind) is the existing repro described in the issue.

CleanupHookThunkRun() read thunk->isolate/fun/arg from the
CleanupHookThunk after invoking thunk->fun(). For every
node::ObjectWrap alive at teardown, thunk->fun is
ObjectWrap::CleanupHook, which deletes the wrap; ~ObjectWrap() calls
RemoveEnvironmentCleanupHook() itself, erasing the CleanupHookThunk
from the registry and freeing the node it lives in. The subsequent
read of thunk->isolate/fun/arg to make the (now redundant) second
RemoveEnvironmentCleanupHook() call was therefore a use-after-free.

Cache the fields before running the hook so nothing is read from
`thunk` once it may have been freed.

Fixes: nodejs#65195
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. labels Aug 10, 2026
@sreehariannam

Copy link
Copy Markdown
Author

cc @addaleax (you wrote both #63642 and #63985, whose interaction causes this) and @legendecas (reviewed #63642) — would appreciate a look when you have a chance.

@sreehariannam

Copy link
Copy Markdown
Author

cc @nsavoire — thanks for the thorough root-cause writeup and repro in the issue, it made this a straightforward fix to apply. If you get a chance to re-run your valgrind repro (test/addons/worker-addon-exit) against this branch, that would help confirm it before a maintainer looks at it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use-after-free in CleanupHookThunkRun for every node::ObjectWrap alive at teardown

2 participants