Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: add new negative selftests to cover missing check_func_arg_reg_off() and reg->type check

Add new negative selftests which are intended to cover the
out-of-bounds memory access that could be performed on a
CONST_PTR_TO_DYNPTR within functions taking a ARG_PTR_TO_DYNPTR |
MEM_RDONLY as an argument, and acceptance of invalid register types
i.e. PTR_TO_BTF_ID within functions taking a ARG_PTR_TO_DYNPTR |
MEM_RDONLY.

Reported-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Matt Bobrowski <mattbobrowski@google.com>
Link: https://lore.kernel.org/r/20240625062857.92760-2-mattbobrowski@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Matt Bobrowski and committed by
Alexei Starovoitov
aa293983 ec2b9a5e

+48 -2
+24
tools/testing/selftests/bpf/progs/dynptr_fail.c
··· 1686 1686 1687 1687 return !!data; 1688 1688 } 1689 + 1690 + __noinline long global_call_bpf_dynptr(const struct bpf_dynptr *dynptr) 1691 + { 1692 + long ret = 0; 1693 + /* Avoid leaving this global function empty to avoid having the compiler 1694 + * optimize away the call to this global function. 1695 + */ 1696 + __sink(ret); 1697 + return ret; 1698 + } 1699 + 1700 + SEC("?raw_tp") 1701 + __failure __msg("arg#1 expected pointer to stack or const struct bpf_dynptr") 1702 + int test_dynptr_reg_type(void *ctx) 1703 + { 1704 + struct task_struct *current = NULL; 1705 + /* R1 should be holding a PTR_TO_BTF_ID, so this shouldn't be a 1706 + * reg->type that can be passed to a function accepting a 1707 + * ARG_PTR_TO_DYNPTR | MEM_RDONLY. process_dynptr_func() should catch 1708 + * this. 1709 + */ 1710 + global_call_bpf_dynptr((const struct bpf_dynptr *)current); 1711 + return 0; 1712 + }
+1 -1
tools/testing/selftests/bpf/progs/test_kfunc_dynptr_param.c
··· 45 45 } 46 46 47 47 SEC("?lsm.s/bpf") 48 - __failure __msg("arg#0 expected pointer to stack or dynptr_ptr") 48 + __failure __msg("arg#1 expected pointer to stack or const struct bpf_dynptr") 49 49 int BPF_PROG(not_ptr_to_stack, int cmd, union bpf_attr *attr, unsigned int size) 50 50 { 51 51 unsigned long val = 0;
+1 -1
tools/testing/selftests/bpf/progs/test_kfunc_param_nullable.c
··· 29 29 } 30 30 31 31 SEC("tc") 32 - __failure __msg("expected pointer to stack or dynptr_ptr") 32 + __failure __msg("expected pointer to stack or const struct bpf_dynptr") 33 33 int kfunc_dynptr_nullable_test3(struct __sk_buff *skb) 34 34 { 35 35 struct bpf_dynptr data;
+22
tools/testing/selftests/bpf/progs/user_ringbuf_fail.c
··· 221 221 bpf_user_ringbuf_drain(&user_ringbuf, try_reinit_dynptr_ringbuf, NULL, 0); 222 222 return 0; 223 223 } 224 + 225 + __noinline long global_call_bpf_dynptr_data(struct bpf_dynptr *dynptr) 226 + { 227 + bpf_dynptr_data(dynptr, 0xA, 0xA); 228 + return 0; 229 + } 230 + 231 + static long callback_adjust_bpf_dynptr_reg_off(struct bpf_dynptr *dynptr, 232 + void *ctx) 233 + { 234 + global_call_bpf_dynptr_data(dynptr += 1024); 235 + return 0; 236 + } 237 + 238 + SEC("?raw_tp") 239 + __failure __msg("dereference of modified dynptr_ptr ptr R1 off=16384 disallowed") 240 + int user_ringbuf_callback_const_ptr_to_dynptr_reg_off(void *ctx) 241 + { 242 + bpf_user_ringbuf_drain(&user_ringbuf, 243 + callback_adjust_bpf_dynptr_reg_off, NULL, 0); 244 + return 0; 245 + }