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
 			}