[PATCH bpf-next v11 1/5] bpf: Move constants blinding out of arch-specific JITs

bot+bpf-ci at kernel.org bot+bpf-ci at kernel.org
Fri Apr 3 03:16:41 PDT 2026


> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index a431b7d50e1b..0d6bfccf0dd7 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c

[ ... ]

> +static int jit_subprogs(struct bpf_verifier_env *env)
> +{
> +	int err, i;
> +	bool blinded = false;
> +	struct bpf_insn *insn;
> +	struct bpf_prog *prog, *orig_prog;
> +	u32 *orig_subprog_starts;
> +
> +	if (env->subprog_cnt <= 1)
> +		return 0;
> +
> +	prog = orig_prog = env->prog;
> +	if (bpf_prog_need_blind(orig_prog)) {
> +		if (!IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON)) {
> +			orig_subprog_starts = dup_subprog_starts(env);
> +			if (!orig_subprog_starts) {
> +				err = -ENOMEM;
> +				goto out_cleanup;
> +			}
> +		}
> +		prog = bpf_jit_blind_constants(env, NULL);
> +		if (IS_ERR(prog)) {
> +			err = -ENOMEM;
> +			goto out_restore;

When bpf_jit_blind_constants() fails, prog holds an ERR_PTR value.
The goto out_restore falls through to out_cleanup which dereferences
prog:

    prog->jit_requested = 0;

That would be dereferencing ERR_PTR(-ENOMEM).

> +		}
> +		blinded = true;
> +	}
> +
> +	err = __jit_subprogs(env);
> +	if (blinded) {
> +		if (err) {
> +			bpf_jit_prog_release_other(orig_prog, prog);

Similarly, when blinding succeeds but __jit_subprogs() fails,
bpf_jit_prog_release_other() frees the clone through
bpf_prog_clone_free(). After this, prog points to freed memory,
and the goto out_restore falls through to out_cleanup where
prog->jit_requested is a use-after-free.

Both paths could use orig_prog (or env->prog, which was restored)
at out_cleanup instead of the stale prog local variable.

> +			/* roll back to the clean original prog */
> +			env->prog = orig_prog;
> +			goto out_restore;
> +		} else {
> +			bpf_jit_prog_release_other(prog, orig_prog);
> +			if (!IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON))
> +				kvfree(orig_subprog_starts);
> +		}
> +	} else if (err) {
> +		/* We will fall back to interpreter mode when err is not -EFAULT, before
> +		 * that, insn->off and insn->imm should be restored to their original values
> +		 * since they were modified by __jit_subprogs.
> +		 */
> +		if (err != EFAULT) {

The comment says "when err is not -EFAULT" but the code checks
err != EFAULT (positive 14).  Since __jit_subprogs() returns
negative error codes, this condition is always true.  Should this
be err != -EFAULT?

> +			for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
> +				if (!bpf_pseudo_call(insn))
> +					continue;
> +				insn->off = 0;
> +				insn->imm = env->insn_aux_data[i].call_imm;
> +			}
> +		}
> +		goto out_cleanup;
> +	}
> +
> +	return 0;
> +
> +out_restore:
> +	if (!IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON)) {
> +		restore_subprog_starts(env, orig_subprog_starts);
> +		kvfree(orig_subprog_starts);
> +	}
> +out_cleanup:
> +	/* cleanup main prog to be interpreted */
> +	prog->jit_requested = 0;
> +	prog->blinding_requested = 0;
>  	return err;
>  }

[ ... ]

> @@ -26456,7 +26529,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
>  err_unlock:
>  	if (!is_priv)
>  		mutex_unlock(&bpf_verifier_lock);
> -	clear_insn_aux_data(env, 0, env->prog->len);
> +	clear_insn_aux_data(env, 0, env->blinded_insn_aux_len ? : env->prog->len);

When blinding succeeds but JIT fails and jit_subprogs() rolls back
env->prog to the original (shorter) program, blinded_insn_aux_len
is larger than env->prog->len.

clear_insn_aux_data() iterates to blinded_insn_aux_len and calls
bpf_is_ldimm64(&insns[i]) on each entry.  The insns array comes
from env->prog->insnsi, which only has env->prog->len entries.
Can this read past the end of the program instructions array?

>  	vfree(env->insn_aux_data);

---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/23941975318


More information about the linux-arm-kernel mailing list