cva6
cva6 copied to clipboard
[Bug Report] implict address truncation
Our co-simulation framework found that cva6 will truncate the address to use, specifically ignoring the highest 8 bits for pc and the highest 32 bits for load/store.
Let's take the rv64mi-p-access test in riscv-test as an example. In this test case, we set the MSB of a legal address 0x00000000800001dc to 1, and then we will try to access 0x80000000800001dc.
[spike] core 0: 0x00000000800001b4 (0x000283e7) jalr t2, t0, 0
[cva6] 705ns 690 M 00000000800001b4 1 000283e7 jalr t2, t0, 0
[spike] core 0: exception trap_instruction_access_fault, epc 0x80000000800001dc
[spike] core 0: tval 0x80000000800001dc
[spike] core 0: 0x0000000080000004 (0x34302f73) csrr t5, mtval
[error] PC SIM 0000000080000004, DUT 80000000800001dc
[error] INSN SIM 34302f73, DUT 0ff0000f
[CJ] Commit Failed
[cva6] 732ns 717 M 80000000800001dc 0 0ff0000f fence // CVA6 continues to execute
It is obviously an illegal address, and spike throws the exception correctly, but cva6 ignores the highest 8 bits and continues to execute it as normal, because the value in 0x800001dc is 0x0ff0000f:
>>> 800001dc: 0ff0000f fence <<<
800001e0: 00018063 beqz gp,800001e0 <fail+0x4>
800001e4: 00119193 slli gp,gp,0x1
Honestly, we didn't expect that cva6 didn't pass riscv-tests. Truncating pc will make it much less difficult for an attacker to launch an attack using memory corruption vulnerabilities, like the bug mentioned by google's team.
The consequence of using an unaligned addition like this is that we've also corrupted the value of X1, which stores the userspace address from which to copy in the data. Instead of the upper bytes being all 0, the top byte is now nonzero. Quite fortunately, however, this isn't a problem because the kernel was compiled with support for the Top Byte Ignore (TBI) architectural feature enabled for userspace, which means that the top byte of the pointer will be ignored for the purpose of address translation by the CPU.
The truncated mechanism implicitly implements a mechanism similar to TBI, which means that an attacker only needs to modify 56 bytes to be able to tamper with the control flow of the program, and the specification also suggests:
Ordinarily, if an instruction attempts to access memory at an inaccessible address, an exception is raised for the instruction. Vacant locations in the address space are never accessible.
@LuminaDCIX helps reproduce the problem
That is a good point. Technically 0x80000000800001dc
is a legal address and the memory subsystem truncates this to the physical address length set for the system:
https://github.com/openhwgroup/cva6/blob/909d85a56cc5ace65765a63d7ed56b7ac2026f99/core/include/riscv_pkg.sv#L41
I agree that it isn't very beautiful in the way it is handled. But generally speaking that is only a problem in M-Mode where you anyway need to trust your software. In any higher privilege mode you would either set PMPs or VM to restrict access based on the entire virtual address.
The fundamental "flaw" is the missing PMA that indicates whether a memory region has anything present behind itself or not.
Hi @zarubaf, what is the resolution of this issue? It looks like it will be WontFix
. Please confirm.