Couple "Denial of Service" Vulnerabilities in Solana rBPF

We discussed this vulnerability during Episode 146 on 17 May 2022

Couple of bugs originating in Solana’s JIT: one an optimization issue, the other a bad instruction choice, both found through fuzzing.

Denial of Service - Resource Exhaustion ($100,000 bounty) the first bug was a memory leak from the following code:

entrypoint:
  r0 = r0 + 255
  if r0 <= 8355838 goto -2
  r9 = r3 >> 3
  call -1

What happens here is that the first two lines just iterate and add 255 to r0 to run for exactly 65534 instructions. Each Solana program is limited to only 65535 instructions. After that it does a calculation for the 65535th instruction, and then a call -1 which gives an unresolved symbol error as -1 isn’t a defined function. This error will allocate a buffer to store what the unresolved symbol was.

The problem is that the instruction count is only checked at the end of each basic block, so it checked and updated after the if and added the call. So after the call happens, the instruction count is updated. It sees that it has gone over 65535 instructions and issues a new error for exceeding the maximum instruction count. This new error overwrites the previously error, overwritting the pointer to the allocated buffer and never freeing it.

Persistent read-only data corruption This one has a much simpler root cause, the cmp_immediate instruction would use the x86 opcode 0x81 for all compares including 8bit wide compares, but 0x80 should be used for 8bit immediate. This would happen while looking up an offset to a memory address, and if some non-zero values were in the upper bits, the comparison could end up approving a write to a read-only memory location thinking it is intended for a different location.