selftests/bpf: Cover commuted pointer state propagation

Add verifier coverage for the three cases affected by preserving the full
pointer state across scalar += pointer: stack frame number inheritance,
readonly-untrusted memory access, and dynptr data-slice invalidation.

Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
Tested-by: Daniel Wade <danjwade95@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260729-c3-035-public-bpf-v4-v4-4-8ee297e2346b@mails.tsinghua.edu.cn
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
This commit is contained in:
Yiyang Chen
2026-07-29 15:18:30 +00:00
committed by Eduard Zingerman
parent cdf19b1b3c
commit 21596761ff
3 changed files with 88 additions and 0 deletions

View File

@@ -1635,6 +1635,36 @@ static int callback(__u32 index, void *data)
return 0;
}
/* A commuted add should preserve the parent id of a dynptr data slice. */
SEC("?raw_tp")
__failure __msg("invalid mem access 'scalar'")
int dynptr_slice_commuted_invalidate(void *ctx)
{
struct bpf_dynptr ptr;
__u32 *slice, *derived;
bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(__u32), 0, &ptr);
slice = bpf_dynptr_data(&ptr, 0, sizeof(__u32));
if (!slice)
goto done;
asm volatile ("%[dst] = 0;"
"%[dst] += %[src];"
"%[src] = 0;"
: [dst]"=&r"(derived), [src]"+r"(slice)
:
: "memory");
bpf_ringbuf_discard_dynptr(&ptr, 0);
val = *derived;
return 0;
done:
bpf_ringbuf_discard_dynptr(&ptr, 0);
return 0;
}
/* If the dynptr is written into in a callback function, its data
* slices should be invalidated as well.
*/

View File

@@ -226,4 +226,21 @@ int null_check(void *ctx)
return 0;
}
SEC("socket")
__success
__retval(1)
int ldx_is_ok_commuted_addr(void *ctx)
{
int v, *p, *derived;
v = 1;
p = bpf_rdonly_cast(&v, 0);
asm volatile ("%[dst] = 0;"
"%[dst] += %[src];"
: [dst]"=&r"(derived)
: [src]"r"(p)
: "memory");
return *derived;
}
char _license[] SEC("license") = "GPL";

View File

@@ -97,4 +97,45 @@ __naked void misaligned_read_from_stack(void)
" ::: __clobber_all);
}
SEC("socket")
__description("stack pointer arithmetic preserves frame number")
__failure __msg("R7 invalid mem access 'scalar'")
__naked void stack_ptr_arith_preserves_frameno(void)
{
asm volatile ("\
r3 = 0; \
*(u64 *)(r10 - 8) = r3; \
r1 = %[map_hash_8b] ll; \
r2 = r10; \
r2 += -8; \
call %[bpf_map_lookup_elem]; \
if r0 != 0 goto +2; \
r0 = 0; \
exit; \
r1 = r0; \
r2 = 0; \
r3 = 0; \
call stack_ptr_arith_preserves_frameno_subprog;\
r0 = 0; \
exit; \
":
: __imm(bpf_map_lookup_elem),
__imm_addr(map_hash_8b)
: __clobber_all);
}
static __used __naked void stack_ptr_arith_preserves_frameno_subprog(void)
{
asm volatile ("\
*(u64 *)(r10 - 8) = r1; \
r6 = -8; \
r6 += r10; \
*(u64 *)(r6 + 0) = r2; \
r7 = *(u64 *)(r10 - 8); \
*(u64 *)(r7 + 0) = r3; \
r0 = 0; \
exit; \
"::: __clobber_all);
}
char _license[] SEC("license") = "GPL";