On Tue Jun 9, 2026 at 1:01 PM EDT, Eduard Zingerman wrote:
> 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?

Seconded, AFAICT there is no reason to fail verification since we just
the pointer's value to the scalar. Whether the operation makes sense is
up to the programmer to decide.


Reply via email to