--- /dev/null
+From e4d4d456436bfb2fe412ee2cd489f7658449b098 Mon Sep 17 00:00:00 2001
+From: Piotr Krysiuk <piotras@gmail.com>
+Date: Mon, 5 Apr 2021 22:52:15 +0100
+Subject: bpf, x86: Validate computation of branch displacements for x86-64
+
+From: Piotr Krysiuk <piotras@gmail.com>
+
+commit e4d4d456436bfb2fe412ee2cd489f7658449b098 upstream.
+
+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 <piotras@gmail.com>
+Reviewed-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/net/bpf_jit_comp.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -1082,7 +1082,16 @@ common_load:
+ }
+
+ if (image) {
+- if (unlikely(proglen + ilen > oldproglen)) {
++ /*
++ * When populating the image, assert that:
++ *
++ * i) We do not write beyond the allocated space, and
++ * ii) addrs[i] did not change from the prior run, in order
++ * to validate assumptions made for computing branch
++ * displacements.
++ */
++ if (unlikely(proglen + ilen > oldproglen ||
++ proglen + ilen != addrs[i])) {
+ pr_err("bpf_jit_compile fatal error\n");
+ return -EFAULT;
+ }
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
- fs/cifs/smb2misc.c | 4 ++--
+ fs/cifs/smb2misc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
-diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
-index bddb2d7b3982..075b285bbd3e 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
-@@ -651,8 +651,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
+@@ -651,8 +651,8 @@ smb2_is_valid_oplock_break(char *buffer,
}
}
spin_unlock(&cifs_tcp_ses_lock);
}
void
---
-2.30.2
-