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 --- .../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 72b2ec31025a..2e9864732c11 100644 --- a/tools/testing/selftests/bpf/prog_tests/thp_adjust.c +++ b/tools/testing/selftests/bpf/prog_tests/thp_adjust.c @@ -4,6 +4,9 @@ #include #include #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" @@ -278,4 +281,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..4db78f2f0b2d --- /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 +#include + +#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 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..88bb09cb7cc2 --- /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 +#include + +#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 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..df7b0c160153 --- /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 +#include + +#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 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