Commit 7c5f7b16 authored by Juntong Deng's avatar Juntong Deng Committed by Alexei Starovoitov

selftests/bpf: Add tests for iter next method returning valid pointer

This patch adds test cases for iter next method returning valid
pointer, which can also used as usage examples.

Currently iter next method should return valid pointer.

iter_next_trusted is the correct usage and test if iter next method
return valid pointer. bpf_iter_task_vma_next has KF_RET_NULL flag,
so the returned pointer may be NULL. We need to check if the pointer
is NULL before using it.

iter_next_trusted_or_null is the incorrect usage. There is no checking
before using the pointer, so it will be rejected by the verifier.

iter_next_rcu and iter_next_rcu_or_null are similar test cases for
KF_RCU_PROTECTED iterators.

iter_next_rcu_not_trusted is used to test that the pointer returned by
iter next method of KF_RCU_PROTECTED iterator cannot be passed in
KF_TRUSTED_ARGS kfuncs.

iter_next_ptr_mem_not_trusted is used to test that base type
PTR_TO_MEM should not be combined with type flag PTR_TRUSTED.
Signed-off-by: default avatarJuntong Deng <juntong.deng@outlook.com>
Link: https://lore.kernel.org/r/AM6PR03MB5848709758F6922F02AF9F1F99962@AM6PR03MB5848.eurprd03.prod.outlook.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 4cc8c50c
......@@ -198,6 +198,22 @@ __bpf_kfunc void bpf_kfunc_nested_release_test(struct sk_buff *ptr)
{
}
__bpf_kfunc void bpf_kfunc_trusted_vma_test(struct vm_area_struct *ptr)
{
}
__bpf_kfunc void bpf_kfunc_trusted_task_test(struct task_struct *ptr)
{
}
__bpf_kfunc void bpf_kfunc_trusted_num_test(int *ptr)
{
}
__bpf_kfunc void bpf_kfunc_rcu_task_test(struct task_struct *ptr)
{
}
__bpf_kfunc struct bpf_testmod_ctx *
bpf_testmod_ctx_create(int *err)
{
......@@ -559,6 +575,10 @@ BTF_ID_FLAGS(func, bpf_kfunc_dynptr_test)
BTF_ID_FLAGS(func, bpf_kfunc_nested_acquire_nonzero_offset_test, KF_ACQUIRE)
BTF_ID_FLAGS(func, bpf_kfunc_nested_acquire_zero_offset_test, KF_ACQUIRE)
BTF_ID_FLAGS(func, bpf_kfunc_nested_release_test, KF_RELEASE)
BTF_ID_FLAGS(func, bpf_kfunc_trusted_vma_test, KF_TRUSTED_ARGS)
BTF_ID_FLAGS(func, bpf_kfunc_trusted_task_test, KF_TRUSTED_ARGS)
BTF_ID_FLAGS(func, bpf_kfunc_trusted_num_test, KF_TRUSTED_ARGS)
BTF_ID_FLAGS(func, bpf_kfunc_rcu_task_test, KF_RCU)
BTF_ID_FLAGS(func, bpf_testmod_ctx_create, KF_ACQUIRE | KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_testmod_ctx_release, KF_RELEASE)
BTF_KFUNCS_END(bpf_testmod_common_kfunc_ids)
......
......@@ -154,4 +154,9 @@ int bpf_kfunc_st_ops_test_epilogue(struct st_ops_args *args) __ksym;
int bpf_kfunc_st_ops_test_pro_epilogue(struct st_ops_args *args) __ksym;
int bpf_kfunc_st_ops_inc10(struct st_ops_args *args) __ksym;
void bpf_kfunc_trusted_vma_test(struct vm_area_struct *ptr) __ksym;
void bpf_kfunc_trusted_task_test(struct task_struct *ptr) __ksym;
void bpf_kfunc_trusted_num_test(int *ptr) __ksym;
void bpf_kfunc_rcu_task_test(struct task_struct *ptr) __ksym;
#endif /* _BPF_TESTMOD_KFUNC_H */
......@@ -14,6 +14,7 @@
#include "iters_state_safety.skel.h"
#include "iters_looping.skel.h"
#include "iters_num.skel.h"
#include "iters_testmod.skel.h"
#include "iters_testmod_seq.skel.h"
#include "iters_task_vma.skel.h"
#include "iters_task.skel.h"
......@@ -297,8 +298,10 @@ void test_iters(void)
RUN_TESTS(iters);
RUN_TESTS(iters_css_task);
if (env.has_testmod)
if (env.has_testmod) {
RUN_TESTS(iters_testmod);
RUN_TESTS(iters_testmod_seq);
}
if (test__start_subtest("num"))
subtest_num_iters();
......
// SPDX-License-Identifier: GPL-2.0
#include "vmlinux.h"
#include "bpf_experimental.h"
#include <bpf/bpf_helpers.h>
#include "bpf_misc.h"
#include "../bpf_testmod/bpf_testmod_kfunc.h"
char _license[] SEC("license") = "GPL";
SEC("raw_tp/sys_enter")
__success
int iter_next_trusted(const void *ctx)
{
struct task_struct *cur_task = bpf_get_current_task_btf();
struct bpf_iter_task_vma vma_it;
struct vm_area_struct *vma_ptr;
bpf_iter_task_vma_new(&vma_it, cur_task, 0);
vma_ptr = bpf_iter_task_vma_next(&vma_it);
if (vma_ptr == NULL)
goto out;
bpf_kfunc_trusted_vma_test(vma_ptr);
out:
bpf_iter_task_vma_destroy(&vma_it);
return 0;
}
SEC("raw_tp/sys_enter")
__failure __msg("Possibly NULL pointer passed to trusted arg0")
int iter_next_trusted_or_null(const void *ctx)
{
struct task_struct *cur_task = bpf_get_current_task_btf();
struct bpf_iter_task_vma vma_it;
struct vm_area_struct *vma_ptr;
bpf_iter_task_vma_new(&vma_it, cur_task, 0);
vma_ptr = bpf_iter_task_vma_next(&vma_it);
bpf_kfunc_trusted_vma_test(vma_ptr);
bpf_iter_task_vma_destroy(&vma_it);
return 0;
}
SEC("raw_tp/sys_enter")
__success
int iter_next_rcu(const void *ctx)
{
struct task_struct *cur_task = bpf_get_current_task_btf();
struct bpf_iter_task task_it;
struct task_struct *task_ptr;
bpf_iter_task_new(&task_it, cur_task, 0);
task_ptr = bpf_iter_task_next(&task_it);
if (task_ptr == NULL)
goto out;
bpf_kfunc_rcu_task_test(task_ptr);
out:
bpf_iter_task_destroy(&task_it);
return 0;
}
SEC("raw_tp/sys_enter")
__failure __msg("Possibly NULL pointer passed to trusted arg0")
int iter_next_rcu_or_null(const void *ctx)
{
struct task_struct *cur_task = bpf_get_current_task_btf();
struct bpf_iter_task task_it;
struct task_struct *task_ptr;
bpf_iter_task_new(&task_it, cur_task, 0);
task_ptr = bpf_iter_task_next(&task_it);
bpf_kfunc_rcu_task_test(task_ptr);
bpf_iter_task_destroy(&task_it);
return 0;
}
SEC("raw_tp/sys_enter")
__failure __msg("R1 must be referenced or trusted")
int iter_next_rcu_not_trusted(const void *ctx)
{
struct task_struct *cur_task = bpf_get_current_task_btf();
struct bpf_iter_task task_it;
struct task_struct *task_ptr;
bpf_iter_task_new(&task_it, cur_task, 0);
task_ptr = bpf_iter_task_next(&task_it);
if (task_ptr == NULL)
goto out;
bpf_kfunc_trusted_task_test(task_ptr);
out:
bpf_iter_task_destroy(&task_it);
return 0;
}
SEC("raw_tp/sys_enter")
__failure __msg("R1 cannot write into rdonly_mem")
/* Message should not be 'R1 cannot write into rdonly_trusted_mem' */
int iter_next_ptr_mem_not_trusted(const void *ctx)
{
struct bpf_iter_num num_it;
int *num_ptr;
bpf_iter_num_new(&num_it, 0, 10);
num_ptr = bpf_iter_num_next(&num_it);
if (num_ptr == NULL)
goto out;
bpf_kfunc_trusted_num_test(num_ptr);
out:
bpf_iter_num_destroy(&num_it);
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