On Tue, 2026-06-09 at 22:55 +0800, Nuoqi Gui wrote:
> scalar += rdonly_untrusted_mem reaches adjust_ptr_min_max_vals() with the
> pointer as the source register. The untrusted PTR_TO_MEM case returns there
> without updating the scalar destination, leaving stale verifier state.
>
> Reject that addition before the early return. Pointer += scalar remains
> handled by the existing untrusted-memory rule.
>
> Fixes: f2362a57aeff ("bpf: allow void* cast using bpf_rdonly_cast()")
> Signed-off-by: Nuoqi Gui <[email protected]>
> ---
> kernel/bpf/verifier.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index c8d980fdd709..c6b350f9585a 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -14823,6 +14823,14 @@ static int adjust_reg_min_max_vals(struct
> bpf_verifier_env *env,
> * This is legal, but we have to reverse our
> * src/dest handling in computing the range
> */
> + if (opcode == BPF_ADD &&
> + base_type(src_reg->type) == PTR_TO_MEM &&
> + (src_reg->type & PTR_UNTRUSTED)) {
> + verbose(env, "R%d tried to add from %s
> to scalar\n",
> + insn->dst_reg,
> + reg_type_str(env,
> src_reg->type));
> + return -EACCES;
> + }
> err = mark_chain_precision(env, insn->dst_reg);
> if (err)
> return err;
Should the fix be like this:
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 7d27ba396d32..9c85dd680a46 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -13593,8 +13593,10 @@ static int adjust_ptr_min_max_vals(struct
bpf_verifier_env *env,
* Accesses to untrusted PTR_TO_MEM are done through probe
* instructions, hence no need to track offsets.
*/
- if (base_type(ptr_reg->type) == PTR_TO_MEM && (ptr_reg->type &
PTR_UNTRUSTED))
+ if (base_type(ptr_reg->type) == PTR_TO_MEM && (ptr_reg->type &
PTR_UNTRUSTED)) {
+ *dst_reg = *ptr_reg;
return 0;
+ }
switch (base_type(ptr_reg->type)) {
case PTR_TO_CTX:
Instead?