Skip to content

Commit bb01a1b

Browse files
committed
bpf: Fix mask direction swap upon off reg sign change
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: 7fedb63 ("bpf: Tighten speculative pointer arithmetic mask") Reported-by: Piotr Krysiuk <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Reviewed-by: Piotr Krysiuk <[email protected]> Acked-by: Alexei Starovoitov <[email protected]>
1 parent 3d0220f commit bb01a1b

File tree

1 file changed

+12
-10
lines changed

1 file changed

+12
-10
lines changed

kernel/bpf/verifier.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6409,18 +6409,10 @@ enum {
64096409
};
64106410

64116411
static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
6412-
const struct bpf_reg_state *off_reg,
6413-
u32 *alu_limit, u8 opcode)
6412+
u32 *alu_limit, bool mask_to_left)
64146413
{
6415-
bool off_is_neg = off_reg->smin_value < 0;
6416-
bool mask_to_left = (opcode == BPF_ADD && off_is_neg) ||
6417-
(opcode == BPF_SUB && !off_is_neg);
64186414
u32 max = 0, ptr_limit = 0;
64196415

6420-
if (!tnum_is_const(off_reg->var_off) &&
6421-
(off_reg->smin_value < 0) != (off_reg->smax_value < 0))
6422-
return REASON_BOUNDS;
6423-
64246416
switch (ptr_reg->type) {
64256417
case PTR_TO_STACK:
64266418
/* Offset 0 is out-of-bounds, but acceptable start for the
@@ -6488,6 +6480,7 @@ static bool sanitize_needed(u8 opcode)
64886480

64896481
struct bpf_sanitize_info {
64906482
struct bpf_insn_aux_data aux;
6483+
bool mask_to_left;
64916484
};
64926485

64936486
static int sanitize_ptr_alu(struct bpf_verifier_env *env,
@@ -6519,7 +6512,16 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
65196512
if (vstate->speculative)
65206513
goto do_sim;
65216514

6522-
err = retrieve_ptr_limit(ptr_reg, off_reg, &alu_limit, opcode);
6515+
if (!commit_window) {
6516+
if (!tnum_is_const(off_reg->var_off) &&
6517+
(off_reg->smin_value < 0) != (off_reg->smax_value < 0))
6518+
return REASON_BOUNDS;
6519+
6520+
info->mask_to_left = (opcode == BPF_ADD && off_is_neg) ||
6521+
(opcode == BPF_SUB && !off_is_neg);
6522+
}
6523+
6524+
err = retrieve_ptr_limit(ptr_reg, &alu_limit, info->mask_to_left);
65236525
if (err < 0)
65246526
return err;
65256527

0 commit comments

Comments
 (0)