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 dfcbe011aff1e77dde49a541763fd5a01ef01eab..744fc9b778fe024b4728a96af6d296917addf0e3 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 be95570ab382e3862bb94a8c37f8a69c3942de96..28b602ac9cbe2ce8e65cf4d34dd5bc6fc662ff3d 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 8a2ff81d8350887a1eb6e9fa34d66f0f24d435e3..0a9293a572115d3e6c9ba1a4df10824462c323df 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\