Commit aa293983 authored by Matt Bobrowski's avatar Matt Bobrowski Committed by Alexei Starovoitov

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: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: default avatarEduard Zingerman <eddyz87@gmail.com>
Signed-off-by: default avatarMatt Bobrowski <mattbobrowski@google.com>
Link: https://lore.kernel.org/r/20240625062857.92760-2-mattbobrowski@google.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent ec2b9a5e
......@@ -1686,3 +1686,27 @@ int test_dynptr_skb_small_buff(struct __sk_buff *skb)
return !!data;
}
__noinline long global_call_bpf_dynptr(const struct bpf_dynptr *dynptr)
{
long ret = 0;
/* Avoid leaving this global function empty to avoid having the compiler
* optimize away the call to this global function.
*/
__sink(ret);
return ret;
}
SEC("?raw_tp")
__failure __msg("arg#1 expected pointer to stack or const struct bpf_dynptr")
int test_dynptr_reg_type(void *ctx)
{
struct task_struct *current = NULL;
/* R1 should be holding a PTR_TO_BTF_ID, so this shouldn't be a
* reg->type that can be passed to a function accepting a
* ARG_PTR_TO_DYNPTR | MEM_RDONLY. process_dynptr_func() should catch
* this.
*/
global_call_bpf_dynptr((const struct bpf_dynptr *)current);
return 0;
}
......@@ -45,7 +45,7 @@ int BPF_PROG(not_valid_dynptr, int cmd, union bpf_attr *attr, unsigned int size)
}
SEC("?lsm.s/bpf")
__failure __msg("arg#0 expected pointer to stack or dynptr_ptr")
__failure __msg("arg#1 expected pointer to stack or const struct bpf_dynptr")
int BPF_PROG(not_ptr_to_stack, int cmd, union bpf_attr *attr, unsigned int size)
{
unsigned long val = 0;
......
......@@ -29,7 +29,7 @@ int kfunc_dynptr_nullable_test2(struct __sk_buff *skb)
}
SEC("tc")
__failure __msg("expected pointer to stack or dynptr_ptr")
__failure __msg("expected pointer to stack or const struct bpf_dynptr")
int kfunc_dynptr_nullable_test3(struct __sk_buff *skb)
{
struct bpf_dynptr data;
......
......@@ -221,3 +221,25 @@ int user_ringbuf_callback_reinit_dynptr_ringbuf(void *ctx)
bpf_user_ringbuf_drain(&user_ringbuf, try_reinit_dynptr_ringbuf, NULL, 0);
return 0;
}
__noinline long global_call_bpf_dynptr_data(struct bpf_dynptr *dynptr)
{
bpf_dynptr_data(dynptr, 0xA, 0xA);
return 0;
}
static long callback_adjust_bpf_dynptr_reg_off(struct bpf_dynptr *dynptr,
void *ctx)
{
global_call_bpf_dynptr_data(dynptr += 1024);
return 0;
}
SEC("?raw_tp")
__failure __msg("dereference of modified dynptr_ptr ptr R1 off=16384 disallowed")
int user_ringbuf_callback_const_ptr_to_dynptr_reg_off(void *ctx)
{
bpf_user_ringbuf_drain(&user_ringbuf,
callback_adjust_bpf_dynptr_reg_off, NULL, 0);
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment