Consider the following program: r1 = map_value; /* low 32 bits are zero at runtime */ r6 = 0xdead000000000000; if w1 != 0 goto l1; l0: r1 += r6; r2 = *(u64 *)(r1 + 0); exit; l1: r6 = 0; goto l0; At the moment is_branch_taken() reports the jump as always taken, because it does not distinguish between BPF_JMP and BPF_JMP32 comparisons when processing 'if w1 != 0 ...'.
Showing the changes to kernel (1 of 1 file). Show all
Unified · Split
| @@ -16337,6 +16337,13 @@ static int is_branch_taken(struct bpf_verifier_env *env, struct bpf_reg_state *r · 16336 unmodified lines | |||
| 16337 | if (__is_pointer_value(false, reg1) || __is_pointer_value(false, reg2)) { | 16337 | if (__is_pointer_value(false, reg1) || __is_pointer_value(false, reg2)) { |
| 16338 | u64 val; | 16338 | u64 val; |
| 16339 | 16339 | ||
| 16340 | /* | ||
| 16341 | * The low 32 bits of a valid pointer may well be zero, hence | ||
| 16342 | * nothing below applies to a 32-bit comparison. | ||
| 16343 | */ | ||
| 16344 | if (is_jmp32) | ||
| 16345 | return -1; | ||
| 16346 | |||
| 16340 | /* arrange that reg2 is a scalar, and reg1 is a pointer */ | 16347 | /* arrange that reg2 is a scalar, and reg1 is a pointer */ |
| 16341 | if (!is_reg_const(reg2, is_jmp32)) { | 16348 | if (!is_reg_const(reg2, is_jmp32)) { |
| 16342 | opcode = flip_opcode(opcode); | 16349 | opcode = flip_opcode(opcode); |