mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 15:22:21 -04:00
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:
committed by
Eduard Zingerman
parent
cdf19b1b3c
commit
21596761ff
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user