|
Gary Lin |
3cfc76 |
From: Piotr Krysiuk <piotras@gmail.com>
|
|
Gary Lin |
3cfc76 |
Date: Tue, 6 Apr 2021 21:59:39 +0100
|
|
Gary Lin |
3cfc76 |
Subject: bpf, x86: Validate computation of branch displacements for x86-32
|
|
Gary Lin |
3cfc76 |
Patch-mainline: v5.12-rc7
|
|
Gary Lin |
3cfc76 |
Git-commit: 26f55a59dc65ff77cd1c4b37991e26497fc68049
|
|
Gary Lin |
3cfc76 |
References: bsc#1184391 CVE-2021-29154
|
|
Gary Lin |
3cfc76 |
|
|
Gary Lin |
3cfc76 |
The branch displacement logic in the BPF JIT compilers for x86 assumes
|
|
Gary Lin |
3cfc76 |
that, for any generated branch instruction, the distance cannot
|
|
Gary Lin |
3cfc76 |
increase between optimization passes.
|
|
Gary Lin |
3cfc76 |
|
|
Gary Lin |
3cfc76 |
But this assumption can be violated due to how the distances are
|
|
Gary Lin |
3cfc76 |
computed. Specifically, whenever a backward branch is processed in
|
|
Gary Lin |
3cfc76 |
do_jit(), the distance is computed by subtracting the positions in the
|
|
Gary Lin |
3cfc76 |
machine code from different optimization passes. This is because part
|
|
Gary Lin |
3cfc76 |
of addrs[] is already updated for the current optimization pass, before
|
|
Gary Lin |
3cfc76 |
the branch instruction is visited.
|
|
Gary Lin |
3cfc76 |
|
|
Gary Lin |
3cfc76 |
And so the optimizer can expand blocks of machine code in some cases.
|
|
Gary Lin |
3cfc76 |
|
|
Gary Lin |
3cfc76 |
This can confuse the optimizer logic, where it assumes that a fixed
|
|
Gary Lin |
3cfc76 |
point has been reached for all machine code blocks once the total
|
|
Gary Lin |
3cfc76 |
program size stops changing. And then the JIT compiler can output
|
|
Gary Lin |
3cfc76 |
abnormal machine code containing incorrect branch displacements.
|
|
Gary Lin |
3cfc76 |
|
|
Gary Lin |
3cfc76 |
To mitigate this issue, we assert that a fixed point is reached while
|
|
Gary Lin |
3cfc76 |
populating the output image. This rejects any problematic programs.
|
|
Gary Lin |
3cfc76 |
The issue affects both x86-32 and x86-64. We mitigate separately to
|
|
Gary Lin |
3cfc76 |
ease backporting.
|
|
Gary Lin |
3cfc76 |
|
|
Gary Lin |
3cfc76 |
Signed-off-by: Piotr Krysiuk <piotras@gmail.com>
|
|
Gary Lin |
3cfc76 |
Reviewed-by: Daniel Borkmann <daniel@iogearbox.net>
|
|
Gary Lin |
3cfc76 |
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
|
|
Gary Lin |
3cfc76 |
Acked-by: Gary Lin <glin@suse.com>
|
|
Gary Lin |
3cfc76 |
---
|
|
Gary Lin |
3cfc76 |
arch/x86/net/bpf_jit_comp32.c | 11 ++++++++++-
|
|
Gary Lin |
3cfc76 |
1 file changed, 10 insertions(+), 1 deletion(-)
|
|
Gary Lin |
3cfc76 |
|
|
Gary Lin |
3cfc76 |
--- a/arch/x86/net/bpf_jit_comp32.c
|
|
Gary Lin |
3cfc76 |
+++ b/arch/x86/net/bpf_jit_comp32.c
|
|
Gary Lin |
3cfc76 |
@@ -2260,7 +2260,16 @@ notyet:
|
|
Gary Lin |
3cfc76 |
}
|
|
Gary Lin |
3cfc76 |
|
|
Gary Lin |
3cfc76 |
if (image) {
|
|
Gary Lin |
3cfc76 |
- if (unlikely(proglen + ilen > oldproglen)) {
|
|
Gary Lin |
3cfc76 |
+ /*
|
|
Gary Lin |
3cfc76 |
+ * When populating the image, assert that:
|
|
Gary Lin |
3cfc76 |
+ *
|
|
Gary Lin |
3cfc76 |
+ * i) We do not write beyond the allocated space, and
|
|
Gary Lin |
3cfc76 |
+ * ii) addrs[i] did not change from the prior run, in order
|
|
Gary Lin |
3cfc76 |
+ * to validate assumptions made for computing branch
|
|
Gary Lin |
3cfc76 |
+ * displacements.
|
|
Gary Lin |
3cfc76 |
+ */
|
|
Gary Lin |
3cfc76 |
+ if (unlikely(proglen + ilen > oldproglen ||
|
|
Gary Lin |
3cfc76 |
+ proglen + ilen != addrs[i])) {
|
|
Gary Lin |
3cfc76 |
pr_err("bpf_jit: fatal error\n");
|
|
Gary Lin |
3cfc76 |
return -EFAULT;
|
|
Gary Lin |
3cfc76 |
}
|