bpf: Assign ID to scalars on spill
authorMaxim Mikityanskiy <maxim@isovalent.com>
Mon, 8 Jan 2024 20:52:02 +0000 (22:52 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 23 Jan 2024 22:40:23 +0000 (14:40 -0800)
Currently, when a scalar bounded register is spilled to the stack, its
ID is preserved, but only if was already assigned, i.e. if this register
was MOVed before.

Assign an ID on spill if none is set, so that equal scalars could be
tracked if a register is spilled to the stack and filled into another
register.

One test is adjusted to reflect the change in register IDs.

Signed-off-by: Maxim Mikityanskiy <maxim@isovalent.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20240108205209.838365-9-maxtram95@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c
tools/testing/selftests/bpf/progs/verifier_direct_packet_access.c
tools/testing/selftests/bpf/verifier/precise.c

index dfcbe01..744fc9b 100644 (file)
@@ -4505,9 +4505,15 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
 
        mark_stack_slot_scratched(env, spi);
        if (reg && !(off % BPF_REG_SIZE) && register_is_bounded(reg) && env->bpf_capable) {
+               bool reg_value_fits;
+
+               reg_value_fits = get_reg_width(reg) <= BITS_PER_BYTE * size;
+               /* Make sure that reg had an ID to build a relation on spill. */
+               if (reg_value_fits)
+                       assign_scalar_id_before_mov(env, reg);
                save_register_state(env, state, spi, reg, size);
                /* Break the relation on a narrowing spill. */
-               if (get_reg_width(reg) > BITS_PER_BYTE * size)
+               if (!reg_value_fits)
                        state->stack[spi].spilled_ptr.id = 0;
        } else if (!reg && !(off % BPF_REG_SIZE) && is_bpf_st_mem(insn) &&
                   insn->imm != 0 && env->bpf_capable) {
index be95570..28b602a 100644 (file)
@@ -568,7 +568,7 @@ l0_%=:      r0 = 0;                                         \
 
 SEC("tc")
 __description("direct packet access: test23 (x += pkt_ptr, 4)")
-__failure __msg("invalid access to packet, off=0 size=8, R5(id=2,off=0,r=0)")
+__failure __msg("invalid access to packet, off=0 size=8, R5(id=3,off=0,r=0)")
 __flag(BPF_F_ANY_ALIGNMENT)
 __naked void test23_x_pkt_ptr_4(void)
 {
index 8a2ff81..0a9293a 100644 (file)
        .prog_type = BPF_PROG_TYPE_XDP,
        .flags = BPF_F_TEST_STATE_FREQ,
        .errstr = "mark_precise: frame0: last_idx 7 first_idx 7\
-       mark_precise: frame0: parent state regs=r4 stack=:\
+       mark_precise: frame0: parent state regs=r4 stack=-8:\
        mark_precise: frame0: last_idx 6 first_idx 4\
-       mark_precise: frame0: regs=r4 stack= before 6: (b7) r0 = -1\
-       mark_precise: frame0: regs=r4 stack= before 5: (79) r4 = *(u64 *)(r10 -8)\
+       mark_precise: frame0: regs=r4 stack=-8 before 6: (b7) r0 = -1\
+       mark_precise: frame0: regs=r4 stack=-8 before 5: (79) r4 = *(u64 *)(r10 -8)\
        mark_precise: frame0: regs= stack=-8 before 4: (7b) *(u64 *)(r3 -8) = r0\
        mark_precise: frame0: parent state regs=r0 stack=:\
        mark_precise: frame0: last_idx 3 first_idx 3\