mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 14:04:54 +02:00
bpf: Fix mask direction swap upon off reg sign change
commitbb01a1bba5upstream. Masking direction as indicated via mask_to_left is considered to be calculated once and then used to derive pointer limits. Thus, this needs to be placed into bpf_sanitize_info instead so we can pass it to sanitize_ptr_alu() call after the pointer move. Piotr noticed a corner case where the off reg causes masking direction change which then results in an incorrect final aux->alu_limit. Fixes:7fedb63a83("bpf: Tighten speculative pointer arithmetic mask") Reported-by: Piotr Krysiuk <piotras@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Piotr Krysiuk <piotras@gmail.com> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
4e2c7b2974
commit
c87ef240a8
|
|
@ -5666,18 +5666,10 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
|
static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
|
||||||
const struct bpf_reg_state *off_reg,
|
u32 *alu_limit, bool mask_to_left)
|
||||||
u32 *alu_limit, u8 opcode)
|
|
||||||
{
|
{
|
||||||
bool off_is_neg = off_reg->smin_value < 0;
|
|
||||||
bool mask_to_left = (opcode == BPF_ADD && off_is_neg) ||
|
|
||||||
(opcode == BPF_SUB && !off_is_neg);
|
|
||||||
u32 max = 0, ptr_limit = 0;
|
u32 max = 0, ptr_limit = 0;
|
||||||
|
|
||||||
if (!tnum_is_const(off_reg->var_off) &&
|
|
||||||
(off_reg->smin_value < 0) != (off_reg->smax_value < 0))
|
|
||||||
return REASON_BOUNDS;
|
|
||||||
|
|
||||||
switch (ptr_reg->type) {
|
switch (ptr_reg->type) {
|
||||||
case PTR_TO_STACK:
|
case PTR_TO_STACK:
|
||||||
/* Offset 0 is out-of-bounds, but acceptable start for the
|
/* Offset 0 is out-of-bounds, but acceptable start for the
|
||||||
|
|
@ -5745,6 +5737,7 @@ static bool sanitize_needed(u8 opcode)
|
||||||
|
|
||||||
struct bpf_sanitize_info {
|
struct bpf_sanitize_info {
|
||||||
struct bpf_insn_aux_data aux;
|
struct bpf_insn_aux_data aux;
|
||||||
|
bool mask_to_left;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sanitize_ptr_alu(struct bpf_verifier_env *env,
|
static int sanitize_ptr_alu(struct bpf_verifier_env *env,
|
||||||
|
|
@ -5776,7 +5769,16 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
|
||||||
if (vstate->speculative)
|
if (vstate->speculative)
|
||||||
goto do_sim;
|
goto do_sim;
|
||||||
|
|
||||||
err = retrieve_ptr_limit(ptr_reg, off_reg, &alu_limit, opcode);
|
if (!commit_window) {
|
||||||
|
if (!tnum_is_const(off_reg->var_off) &&
|
||||||
|
(off_reg->smin_value < 0) != (off_reg->smax_value < 0))
|
||||||
|
return REASON_BOUNDS;
|
||||||
|
|
||||||
|
info->mask_to_left = (opcode == BPF_ADD && off_is_neg) ||
|
||||||
|
(opcode == BPF_SUB && !off_is_neg);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = retrieve_ptr_limit(ptr_reg, &alu_limit, info->mask_to_left);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user