qmonnet / rbpf

Rust virtual machine and JIT compiler for eBPF programs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Inconsistences in arithmetic shift implementation (mask offset)

pcy190 opened this issue · comments

This issue follows #99 and #100. The previous PR demonstrates the implementation incompliance on the logic shift implementation. However, the arithmetic shift operation still meets this problem, and needs the additional mask offset as well.

The current implementation of ARSH64 is not compliant, and undefined behavior happens if we overflow the number of bits we have when trying to shift.

The following PoC program could trigger this inconsistency:

mov64 r8, 0x054545ff
arsh64 r8, r8
exit

Note that in the kernel interpreter implementation, it masks the SRC/IMM as well.
https://github.com/torvalds/linux/blob/610a9b8f49fbcf1100716370d3b5f6f884a2835a/kernel/bpf/core.c#L1794-L1805

Hence we need to mask the shift offset with 63 in the following code. Since we don't perform verifier check on the immediate value, we need to mask the IMM as well.

rbpf/src/interpreter.rs

Lines 289 to 290 in 7bebff5

ebpf::ARSH64_IMM => reg[_dst] = (reg[_dst] as i64 >> insn.imm) as u64,
ebpf::ARSH64_REG => reg[_dst] = (reg[_dst] as i64 >> reg[_src]) as u64,

Will PR a patch recently :)

Thanks a lot for the follow-up! And apologies for the delay. This looks correct, and also consistent with the draft BPF ISA specification.

Note that in the kernel interpreter implementation, it masks the SRC/IMM as well.

Not accurate - It does apply the mask for a SRC register, but it rejects the program in the verifier if the operation uses an IMM value that it judges incorrect. I think this is what you meant, given that you mentioned we don't do the check in the verifier.

Thanks a lot for the patch!