diff options
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.patch | 59 |
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)) { |