| From ab96952b49a5aed41022c9d96525cc6214b1a9a8 Mon Sep 17 00:00:00 2001 |
| From: Daniel Borkmann <daniel@iogearbox.net> |
| Date: Mon, 28 Jan 2019 21:23:23 +0100 |
| Subject: bpf: enable access to ax register also from verifier rewrite |
| |
| [ commit 9b73bfdd08e73231d6a90ae6db4b46b3fbf56c30 upstream ] |
| |
| Right now we are using BPF ax register in JIT for constant blinding as |
| well as in interpreter as temporary variable. Verifier will not be able |
| to use it simply because its use will get overridden from the former in |
| bpf_jit_blind_insn(). However, it can be made to work in that blinding |
| will be skipped if there is prior use in either source or destination |
| register on the instruction. Taking constraints of ax into account, the |
| verifier is then open to use it in rewrites under some constraints. Note, |
| ax register already has mappings in every eBPF JIT. |
| |
| Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> |
| Acked-by: Alexei Starovoitov <ast@kernel.org> |
| Signed-off-by: Alexei Starovoitov <ast@kernel.org> |
| Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| include/linux/filter.h | 7 +------ |
| kernel/bpf/core.c | 20 ++++++++++++++++++++ |
| 2 files changed, 21 insertions(+), 6 deletions(-) |
| |
| diff --git a/include/linux/filter.h b/include/linux/filter.h |
| index 68b97eda236d..b776626aeb84 100644 |
| --- a/include/linux/filter.h |
| +++ b/include/linux/filter.h |
| @@ -53,12 +53,7 @@ struct sock_reuseport; |
| #define BPF_REG_D BPF_REG_8 /* data, callee-saved */ |
| #define BPF_REG_H BPF_REG_9 /* hlen, callee-saved */ |
| |
| -/* Kernel hidden auxiliary/helper register for hardening step. |
| - * Only used by eBPF JITs. It's nothing more than a temporary |
| - * register that JITs use internally, only that here it's part |
| - * of eBPF instructions that have been rewritten for blinding |
| - * constants. See JIT pre-step in bpf_jit_blind_constants(). |
| - */ |
| +/* Kernel hidden auxiliary/helper register. */ |
| #define BPF_REG_AX MAX_BPF_REG |
| #define MAX_BPF_EXT_REG (MAX_BPF_REG + 1) |
| #define MAX_BPF_JIT_REG MAX_BPF_EXT_REG |
| diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c |
| index ada876048ca4..ac44653025ad 100644 |
| --- a/kernel/bpf/core.c |
| +++ b/kernel/bpf/core.c |
| @@ -727,6 +727,26 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from, |
| BUILD_BUG_ON(BPF_REG_AX + 1 != MAX_BPF_JIT_REG); |
| BUILD_BUG_ON(MAX_BPF_REG + 1 != MAX_BPF_JIT_REG); |
| |
| + /* Constraints on AX register: |
| + * |
| + * AX register is inaccessible from user space. It is mapped in |
| + * all JITs, and used here for constant blinding rewrites. It is |
| + * typically "stateless" meaning its contents are only valid within |
| + * the executed instruction, but not across several instructions. |
| + * There are a few exceptions however which are further detailed |
| + * below. |
| + * |
| + * Constant blinding is only used by JITs, not in the interpreter. |
| + * The interpreter uses AX in some occasions as a local temporary |
| + * register e.g. in DIV or MOD instructions. |
| + * |
| + * In restricted circumstances, the verifier can also use the AX |
| + * register for rewrites as long as they do not interfere with |
| + * the above cases! |
| + */ |
| + if (from->dst_reg == BPF_REG_AX || from->src_reg == BPF_REG_AX) |
| + goto out; |
| + |
| if (from->imm == 0 && |
| (from->code == (BPF_ALU | BPF_MOV | BPF_K) || |
| from->code == (BPF_ALU64 | BPF_MOV | BPF_K))) { |
| -- |
| 2.19.1 |
| |