summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorPiotr Krysiuk <piotras@gmail.com>2021-03-16 08:26:25 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-03-20 10:51:13 +0100
commit6bc7314a685952608e32e8776a39173130540d7f (patch)
tree215ae845825914801e04c4586c6f7a0d50fe6dc4 /kernel
parentc4f3aa4343deccf5b8e1bfcc7c36224aaf3a8b26 (diff)
downloadlinux-6bc7314a685952608e32e8776a39173130540d7f.tar.gz
linux-6bc7314a685952608e32e8776a39173130540d7f.tar.bz2
linux-6bc7314a685952608e32e8776a39173130540d7f.zip
bpf: Simplify alu_limit masking for pointer arithmetic
commit b5871dca250cd391885218b99cc015aca1a51aea upstream. Instead of having the mov32 with aux->alu_limit - 1 immediate, move this operation to retrieve_ptr_limit() instead to simplify the logic and to allow for subsequent sanity boundary checks inside retrieve_ptr_limit(). This avoids in future that at the time of the verifier masking rewrite we'd run into an underflow which would not sign extend due to the nature of mov32 instruction. Signed-off-by: Piotr Krysiuk <piotras@gmail.com> Co-developed-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/verifier.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index c5b596f41ada..78abf6cc6a1a 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5398,16 +5398,16 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
*/
off = ptr_reg->off + ptr_reg->var_off.value;
if (mask_to_left)
- *ptr_limit = MAX_BPF_STACK + off + 1;
+ *ptr_limit = MAX_BPF_STACK + off;
else
- *ptr_limit = -off;
+ *ptr_limit = -off - 1;
return 0;
case PTR_TO_MAP_VALUE:
if (mask_to_left) {
- *ptr_limit = ptr_reg->umax_value + ptr_reg->off + 1;
+ *ptr_limit = ptr_reg->umax_value + ptr_reg->off;
} else {
off = ptr_reg->smin_value + ptr_reg->off;
- *ptr_limit = ptr_reg->map_ptr->value_size - off;
+ *ptr_limit = ptr_reg->map_ptr->value_size - off - 1;
}
return 0;
default:
@@ -11083,7 +11083,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
off_reg = issrc ? insn->src_reg : insn->dst_reg;
if (isneg)
*patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1);
- *patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit - 1);
+ *patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit);
*patch++ = BPF_ALU64_REG(BPF_SUB, BPF_REG_AX, off_reg);
*patch++ = BPF_ALU64_REG(BPF_OR, BPF_REG_AX, off_reg);
*patch++ = BPF_ALU64_IMM(BPF_NEG, BPF_REG_AX, 0);