summaryrefslogtreecommitdiffstats
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-24 11:04:55 +0100
commit59ce8e5ecf2dc409736f564d80dd25f7101739b3 (patch)
tree85b757fe9351bcfec74bfa44dd551c8ffd4fecd7
parent92df5a174c6e7a3078e81b919c4d859d4f9f3f2e (diff)
downloadlinux-stable-59ce8e5ecf2dc409736f564d80dd25f7101739b3.tar.gz
linux-stable-59ce8e5ecf2dc409736f564d80dd25f7101739b3.tar.bz2
linux-stable-59ce8e5ecf2dc409736f564d80dd25f7101739b3.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>
-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 393f1209a776..a83f2feee426 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2035,16 +2035,16 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
case PTR_TO_STACK:
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:
@@ -4802,7 +4802,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);