Skip to content

Commit e4d4d45

Browse files
piotr-krysiukborkmann
authored andcommitted
bpf, x86: Validate computation of branch displacements for x86-64
The branch displacement logic in the BPF JIT compilers for x86 assumes that, for any generated branch instruction, the distance cannot increase between optimization passes. But this assumption can be violated due to how the distances are computed. Specifically, whenever a backward branch is processed in do_jit(), the distance is computed by subtracting the positions in the machine code from different optimization passes. This is because part of addrs[] is already updated for the current optimization pass, before the branch instruction is visited. And so the optimizer can expand blocks of machine code in some cases. This can confuse the optimizer logic, where it assumes that a fixed point has been reached for all machine code blocks once the total program size stops changing. And then the JIT compiler can output abnormal machine code containing incorrect branch displacements. To mitigate this issue, we assert that a fixed point is reached while populating the output image. This rejects any problematic programs. The issue affects both x86-32 and x86-64. We mitigate separately to ease backporting. Signed-off-by: Piotr Krysiuk <[email protected]> Reviewed-by: Daniel Borkmann <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 144748e commit e4d4d45

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

arch/x86/net/bpf_jit_comp.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,16 @@ st: if (is_imm8(insn->off))
16891689
}
16901690

16911691
if (image) {
1692-
if (unlikely(proglen + ilen > oldproglen)) {
1692+
/*
1693+
* When populating the image, assert that:
1694+
*
1695+
* i) We do not write beyond the allocated space, and
1696+
* ii) addrs[i] did not change from the prior run, in order
1697+
* to validate assumptions made for computing branch
1698+
* displacements.
1699+
*/
1700+
if (unlikely(proglen + ilen > oldproglen ||
1701+
proglen + ilen != addrs[i])) {
16931702
pr_err("bpf_jit: fatal error\n");
16941703
return -EFAULT;
16951704
}

0 commit comments

Comments
 (0)