On Sat, Jun 13, 2026 at 5:38 AM Nuoqi Gui <[email protected]> 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.
>
> Handle the untrusted PTR_TO_MEM case before the early return. Addition and
> pointer-minus-scalar subtraction preserve the pointer type and keep the
> existing "do not track offsets" rule for untrusted memory.
> Scalar-minus-pointer and unsupported pointer ALU operations are still
> rejected instead of being accepted by the early return.
>
> Fixes: f2362a57aeff ("bpf: allow void* cast using bpf_rdonly_cast()")
> Signed-off-by: Nuoqi Gui <[email protected]>
> ---
>  kernel/bpf/verifier.c | 28 ++++++++++++++++++++++++++--
>  1 file changed, 26 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index c8d980fdd709..26c67c53166b 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -13729,8 +13729,32 @@ 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))
> -               return 0;
> +       if (base_type(ptr_reg->type) == PTR_TO_MEM &&
> +           (ptr_reg->type & PTR_UNTRUSTED)) {

do not introduce line wrap.

> +               switch (opcode) {
> +               case BPF_ADD:
> +                       *dst_reg = *ptr_reg;
> +                       return 0;
> +               case BPF_SUB:
> +                       if (dst_reg == off_reg) {
> +                               verbose(env, "R%d tried to subtract pointer 
> from scalar\n",
> +                                       dst);
> +                               return -EACCES;
> +                       }
> +                       *dst_reg = *ptr_reg;
> +                       return 0;
> +               case BPF_AND:
> +               case BPF_OR:
> +               case BPF_XOR:
> +                       verbose(env, "R%d bitwise operator %s on pointer 
> prohibited\n",
> +                               dst, bpf_alu_string[opcode >> 4]);
> +                       return -EACCES;
> +               default:
> +                       verbose(env, "R%d pointer arithmetic with %s operator 
> prohibited\n",
> +                               dst, bpf_alu_string[opcode >> 4]);
> +                       return -EACCES;

No need to arbitrary rejection.
All ALUs should be allowed.
Something like
if (ptr_reg != dst_reg)
  *dst_reg = *ptr_reg;

pw-bot: cr

Reply via email to