1. The trusted vma->vm_mm pointer can be null and must be checked before dereferencing. 2. The trusted mm->owner pointer can be null and must be checked before dereferencing. 3. Sleepable programs are prohibited because the call site operates under RCU protection. Signed-off-by: Yafang Shao <laoar.shao@xxxxxxxxx> --- .../selftests/bpf/prog_tests/thp_adjust.c | 7 +++++ .../bpf/progs/test_thp_adjust_sleepable.c | 22 ++++++++++++++ .../bpf/progs/test_thp_adjust_trusted_owner.c | 30 +++++++++++++++++++ .../bpf/progs/test_thp_adjust_trusted_vma.c | 27 +++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/test_thp_adjust_sleepable.c create mode 100644 tools/testing/selftests/bpf/progs/test_thp_adjust_trusted_owner.c create mode 100644 tools/testing/selftests/bpf/progs/test_thp_adjust_trusted_vma.c diff --git a/tools/testing/selftests/bpf/prog_tests/thp_adjust.c b/tools/testing/selftests/bpf/prog_tests/thp_adjust.c index 30172f2ee5d5..bbe1a82345ef 100644 --- a/tools/testing/selftests/bpf/prog_tests/thp_adjust.c +++ b/tools/testing/selftests/bpf/prog_tests/thp_adjust.c @@ -5,6 +5,9 @@ #include <test_progs.h> #include "cgroup_helpers.h" #include "test_thp_adjust.skel.h" +#include "test_thp_adjust_sleepable.skel.h" +#include "test_thp_adjust_trusted_vma.skel.h" +#include "test_thp_adjust_trusted_owner.skel.h" #define LEN (16 * 1024 * 1024) /* 16MB */ #define THP_ENABLED_FILE "/sys/kernel/mm/transparent_hugepage/enabled" @@ -274,4 +277,8 @@ void test_thp_adjust(void) subtest_thp_policy_update(); thp_adjust_destroy(); + + RUN_TESTS(test_thp_adjust_trusted_vma); + RUN_TESTS(test_thp_adjust_trusted_owner); + RUN_TESTS(test_thp_adjust_sleepable); } diff --git a/tools/testing/selftests/bpf/progs/test_thp_adjust_sleepable.c b/tools/testing/selftests/bpf/progs/test_thp_adjust_sleepable.c new file mode 100644 index 000000000000..9b92359f9789 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_thp_adjust_sleepable.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> + +#include "bpf_misc.h" + +char _license[] SEC("license") = "GPL"; + +SEC("struct_ops.s/thp_get_order") +__failure __msg("attach to unsupported member thp_get_order of struct bpf_thp_ops") +int BPF_PROG(thp_sleepable, struct vm_area_struct *vma, enum bpf_thp_vma_type vma_type, + enum tva_type tva_type, unsigned long orders) +{ + return -1; +} + +SEC(".struct_ops.link") +struct bpf_thp_ops vma_ops = { + .thp_get_order = (void *)thp_sleepable, +}; diff --git a/tools/testing/selftests/bpf/progs/test_thp_adjust_trusted_owner.c b/tools/testing/selftests/bpf/progs/test_thp_adjust_trusted_owner.c new file mode 100644 index 000000000000..b3f98c2a9b43 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_thp_adjust_trusted_owner.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> + +#include "bpf_misc.h" + +char _license[] SEC("license") = "GPL"; + +SEC("struct_ops/thp_get_order") +__failure __msg("R3 pointer arithmetic on rcu_ptr_or_null_ prohibited, null-check it first") +int BPF_PROG(thp_trusted_owner, struct vm_area_struct *vma, enum bpf_thp_vma_type vma_type, + enum tva_type tva_type, unsigned long orders) +{ + struct mm_struct *mm = vma->vm_mm; + struct task_struct *p; + + if (!mm) + return 0; + + p = mm->owner; + bpf_printk("The task name is %s\n", p->comm); + return -1; +} + +SEC(".struct_ops.link") +struct bpf_thp_ops vma_ops = { + .thp_get_order = (void *)thp_trusted_owner, +}; diff --git a/tools/testing/selftests/bpf/progs/test_thp_adjust_trusted_vma.c b/tools/testing/selftests/bpf/progs/test_thp_adjust_trusted_vma.c new file mode 100644 index 000000000000..5ce100348714 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_thp_adjust_trusted_vma.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> + +#include "bpf_misc.h" + +char _license[] SEC("license") = "GPL"; + +SEC("struct_ops/thp_get_order") +__failure __msg("R1 invalid mem access 'trusted_ptr_or_null_'") +int BPF_PROG(thp_trusted_vma, struct vm_area_struct *vma, enum bpf_thp_vma_type vma_type, + enum tva_type tva_type, unsigned long orders) +{ + struct mm_struct *mm = vma->vm_mm; + struct task_struct *p = mm->owner; + + if (!p) + return 0; + return -1; +} + +SEC(".struct_ops.link") +struct bpf_thp_ops vma_ops = { + .thp_get_order = (void *)thp_trusted_vma, +}; -- 2.47.3