Skip to content

Conversation

@nickva
Copy link
Contributor

@nickva nickva commented Nov 20, 2025

In #462 during exit we call js_std_free_handlers() then JS_FreeRuntime().

js_std_free_handlers() frees the JSThreadState memory. However, later in JS_FreeRuntime() we run GC, which runs js_worker_finalizer and that accesses the port list from the already freed JSThreadState, so it results in a use-after-free error.

To fix it try to run GC in js_std_free_handlers() just before before cleaning and freeing JSThreadState.

Fix #462

In bellard#462 during exit we call `js_std_free_handlers()` then `JS_FreeRuntime()`.

`js_std_free_handlers()` frees the `JSThreadState` memory. However, later in
`JS_FreeRuntime()` we run GC, which runs `js_worker_finalizer` and that
accesses the port list from the already freed `JSThreadState`, so it results in
a use-after-free error.

To fix it try to run GC in `js_std_free_handlers()` just before before cleaning and
freeing `JSThreadState`.

Fix bellard#462
@nickva
Copy link
Contributor Author

nickva commented Nov 20, 2025

Not sure if this entirely right, maybe it's better if the port list has a mutex and a reference count like message pipes...

It does not trigger the UAF from #463 any longer at least:

% make CONFIG_ASAN=n qjs && ./qjs --std ./uaf.js
make: `qjs' is up to date.
qjs(74987,0x7ff85a0d5400) malloc: nano zone abandoned due to inability to reserve vm space.
ReferenceError: 'gc' is not defined
    at set (./uaf.js:9:7)
    at <anonymous> (./uaf.js:14:4)
    at <anonymous> (./uaf.js:15:3)
ReferenceError: could not load module filename 'non-exist.js'
@bellard
Copy link
Owner

bellard commented Nov 22, 2025

Already fixed.

@bellard bellard closed this Nov 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants