Skip to content

Commit

Permalink
bpf: add new negative selftests to cover missing check_func_arg_reg_o…
Browse files Browse the repository at this point in the history
…ff() 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>
  • Loading branch information
Matt Bobrowski authored and Alexei Starovoitov committed Jun 26, 2024
1 parent ec2b9a5 commit aa29398
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 2 deletions.
24 changes: 24 additions & 0 deletions tools/testing/selftests/bpf/progs/dynptr_fail.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
22 changes: 22 additions & 0 deletions tools/testing/selftests/bpf/progs/user_ringbuf_fail.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

0 comments on commit aa29398

Please sign in to comment.