BPF programs can be loaded with the BPF_F_TEST_RND_HI32 flag to instruct the verifier to randomize the high 32 bits of a register being used as a subregister. This is done in the opt_subreg_zext_lo32_rnd_hi32 pass that scans the BPF program instruction by instruction, regardless of whether the flag is set or not, and testing the flag on every iteration. However, the flag is not modified at verification time, and the function is a no-op if it is unset. Gate the randomization pass behind a single flag check instead of testing the flag in the main loop of the pass. Signed-off-by: Emil Tsalapatis <emil@xxxxxxxxxxxxxxx> --- kernel/bpf/verifier.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index e2fcea860755..dc0981205d6a 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -21062,9 +21062,7 @@ static int opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env, int i, patch_len, delta = 0, len = env->prog->len; struct bpf_insn *insns = env->prog->insnsi; struct bpf_prog *new_prog; - bool rnd_hi32; - rnd_hi32 = attr->prog_flags & BPF_F_TEST_RND_HI32; zext_patch[1] = BPF_ZEXT_REG(0); rnd_hi32_patch[1] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_AX, 0); rnd_hi32_patch[2] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_AX, 32); @@ -21080,9 +21078,6 @@ static int opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env, u8 code, class; u32 imm_rnd; - if (!rnd_hi32) - continue; - code = insn.code; class = BPF_CLASS(code); if (load_reg == -1) @@ -24700,7 +24695,9 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 * insns could be handled correctly. */ if (ret == 0 && !bpf_prog_is_offloaded(env->prog->aux)) { - ret = opt_subreg_zext_lo32_rnd_hi32(env, attr); + if (attr->prog_flags & BPF_F_TEST_RND_HI32) + ret = opt_subreg_zext_lo32_rnd_hi32(env, attr); + env->prog->aux->verifier_zext = bpf_jit_needs_zext() ? !ret : false; } -- 2.49.0