summaryrefslogtreecommitdiffstats
path: root/debian/patches/bugfix/all/bpf-fix-kernel-address-leakage-in-atomic-cmpxchg-s-r0-aux-reg.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/bugfix/all/bpf-fix-kernel-address-leakage-in-atomic-cmpxchg-s-r0-aux-reg.patch')
-rw-r--r--debian/patches/bugfix/all/bpf-fix-kernel-address-leakage-in-atomic-cmpxchg-s-r0-aux-reg.patch59
1 files changed, 59 insertions, 0 deletions
diff --git a/debian/patches/bugfix/all/bpf-fix-kernel-address-leakage-in-atomic-cmpxchg-s-r0-aux-reg.patch b/debian/patches/bugfix/all/bpf-fix-kernel-address-leakage-in-atomic-cmpxchg-s-r0-aux-reg.patch
new file mode 100644
index 000000000..aad743511
--- /dev/null
+++ b/debian/patches/bugfix/all/bpf-fix-kernel-address-leakage-in-atomic-cmpxchg-s-r0-aux-reg.patch
@@ -0,0 +1,59 @@
+From a82fe085f344ef20b452cd5f481010ff96b5c4cd Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Tue, 7 Dec 2021 11:02:02 +0000
+Subject: bpf: Fix kernel address leakage in atomic cmpxchg's r0 aux reg
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit a82fe085f344ef20b452cd5f481010ff96b5c4cd upstream.
+
+The implementation of BPF_CMPXCHG on a high level has the following parameters:
+
+ .-[old-val] .-[new-val]
+ BPF_R0 = cmpxchg{32,64}(DST_REG + insn->off, BPF_R0, SRC_REG)
+ `-[mem-loc] `-[old-val]
+
+Given a BPF insn can only have two registers (dst, src), the R0 is fixed and
+used as an auxilliary register for input (old value) as well as output (returning
+old value from memory location). While the verifier performs a number of safety
+checks, it misses to reject unprivileged programs where R0 contains a pointer as
+old value.
+
+Through brute-forcing it takes about ~16sec on my machine to leak a kernel pointer
+with BPF_CMPXCHG. The PoC is basically probing for kernel addresses by storing the
+guessed address into the map slot as a scalar, and using the map value pointer as
+R0 while SRC_REG has a canary value to detect a matching address.
+
+Fix it by checking R0 for pointers, and reject if that's the case for unprivileged
+programs.
+
+Fixes: 5ffa25502b5a ("bpf: Add instructions for atomic_[cmp]xchg")
+Reported-by: Ryota Shiga (Flatt Security)
+Acked-by: Brendan Jackman <jackmanb@google.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -4386,9 +4386,16 @@ static int check_atomic(struct bpf_verif
+
+ if (insn->imm == BPF_CMPXCHG) {
+ /* Check comparison of R0 with memory location */
+- err = check_reg_arg(env, BPF_REG_0, SRC_OP);
++ const u32 aux_reg = BPF_REG_0;
++
++ err = check_reg_arg(env, aux_reg, SRC_OP);
+ if (err)
+ return err;
++
++ if (is_pointer_value(env, aux_reg)) {
++ verbose(env, "R%d leaks addr into mem\n", aux_reg);
++ return -EACCES;
++ }
+ }
+
+ if (is_pointer_value(env, insn->src_reg)) {