]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bpf: Allow instructions with arena source and non-arena dest registers
authorEmil Tsalapatis <emil@etsalapatis.com>
Sun, 12 Apr 2026 17:45:38 +0000 (13:45 -0400)
committerAlexei Starovoitov <ast@kernel.org>
Sun, 12 Apr 2026 19:47:39 +0000 (12:47 -0700)
The compiler sometimes stores the result of a PTR_TO_ARENA and SCALAR
operation into the scalar register rather than the pointer register.
Relax the verifier to allow operations between a source arena register
and a destination non-arena register, marking the destination's value
as a PTR_TO_ARENA.

Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
Acked-by: Song Liu <song@kernel.org>
Fixes: 6082b6c328b5 ("bpf: Recognize addr_space_cast instruction in the verifier.")
Link: https://lore.kernel.org/r/20260412174546.18684-2-emil@etsalapatis.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c

index 4fa9d2bc07f6fb1ac0c08dda7359847cc16f49dd..9e4980128151baeac4ef35e42923a3c36bc5501e 100644 (file)
@@ -15051,11 +15051,20 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
        int err;
 
        dst_reg = &regs[insn->dst_reg];
-       src_reg = NULL;
+       if (BPF_SRC(insn->code) == BPF_X)
+               src_reg = &regs[insn->src_reg];
+       else
+               src_reg = NULL;
 
-       if (dst_reg->type == PTR_TO_ARENA) {
+       /* Case where at least one operand is an arena. */
+       if (dst_reg->type == PTR_TO_ARENA || (src_reg && src_reg->type == PTR_TO_ARENA)) {
                struct bpf_insn_aux_data *aux = cur_aux(env);
 
+               if (dst_reg->type != PTR_TO_ARENA)
+                       *dst_reg = *src_reg;
+
+               dst_reg->subreg_def = env->insn_idx + 1;
+
                if (BPF_CLASS(insn->code) == BPF_ALU64)
                        /*
                         * 32-bit operations zero upper bits automatically.
@@ -15071,7 +15080,6 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                ptr_reg = dst_reg;
 
        if (BPF_SRC(insn->code) == BPF_X) {
-               src_reg = &regs[insn->src_reg];
                if (src_reg->type != SCALAR_VALUE) {
                        if (dst_reg->type != SCALAR_VALUE) {
                                /* Combining two pointers by any ALU op yields