diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c index 64ac49ad67e6..ec9e3907c75d 100644 --- a/tools/testing/selftests/bpf/prog_tests/verifier.c +++ b/tools/testing/selftests/bpf/prog_tests/verifier.c @@ -53,6 +53,7 @@ #include "verifier_iterating_callbacks.skel.h" #include "verifier_jeq_infer_not_null.skel.h" #include "verifier_jit_convergence.skel.h" +#include "verifier_kfunc_perfmon.skel.h" #include "verifier_ld_ind.skel.h" #include "verifier_ldsx.skel.h" #include "verifier_leak_ptr.skel.h" @@ -216,6 +217,7 @@ void test_verifier_int_ptr(void) { RUN(verifier_int_ptr); } void test_verifier_iterating_callbacks(void) { RUN(verifier_iterating_callbacks); } void test_verifier_jeq_infer_not_null(void) { RUN(verifier_jeq_infer_not_null); } void test_verifier_jit_convergence(void) { RUN(verifier_jit_convergence); } +void test_verifier_kfunc_perfmon(void) { RUN(verifier_kfunc_perfmon); } void test_verifier_load_acquire(void) { RUN(verifier_load_acquire); } void test_verifier_ld_ind(void) { RUN(verifier_ld_ind); } void test_verifier_ldsx(void) { RUN(verifier_ldsx); } diff --git a/tools/testing/selftests/bpf/progs/verifier_kfunc_perfmon.c b/tools/testing/selftests/bpf/progs/verifier_kfunc_perfmon.c new file mode 100644 index 000000000000..76c39ef30e96 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/verifier_kfunc_perfmon.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include "bpf_misc.h" + +void *user_ptr; +char dynptr_buf[8]; +u64 kaddr; + +extern struct kmem_cache *bpf_get_kmem_cache(u64 addr) __ksym; + +SEC("socket") +__success +__caps_unpriv(CAP_BPF) +__failure_unpriv +__msg_unpriv("bpf_rdonly_cast is allowed only to CAP_PERFMON and CAP_SYS_ADMIN") +int rdonly_cast_noperfmon(void *ctx) +{ + char *p = bpf_rdonly_cast(0, 0); + + return p[0x7fff]; +} + +SEC("socket") +__success +__caps_unpriv(CAP_BPF) +__failure_unpriv +__msg_unpriv("bpf_probe_read_kernel_dynptr is allowed only to CAP_PERFMON and CAP_SYS_ADMIN") +int probe_read_kernel_dynptr_noperfmon(void *ctx) +{ + struct bpf_dynptr dptr; + + bpf_dynptr_from_mem(dynptr_buf, sizeof(dynptr_buf), 0, &dptr); + bpf_probe_read_kernel_dynptr(&dptr, 0, sizeof(dynptr_buf), user_ptr); + return 0; +} + +SEC("socket") +__success +__caps_unpriv(CAP_BPF) +__failure_unpriv +__msg_unpriv("bpf_stream_vprintk is allowed only to CAP_PERFMON and CAP_SYS_ADMIN") +int stream_vprintk_noperfmon(void *ctx) +{ + bpf_stream_printk(BPF_STDOUT, "%pB", (void *)kaddr); + return 0; +} + +SEC("socket") +__success +__caps_unpriv(CAP_BPF) +__failure_unpriv +__msg_unpriv("bpf_get_kmem_cache is allowed only to CAP_PERFMON and CAP_SYS_ADMIN") +int get_kmem_cache_noperfmon(void *ctx) +{ + return !!bpf_get_kmem_cache(kaddr); +} + +__weak int subprog_untrusted_read(void *p __arg_untrusted) +{ + return *(char *)p; +} + +SEC("socket") +__success +__caps_unpriv(CAP_BPF) +__failure_unpriv +__msg_unpriv("rdonly_untrusted_mem access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN") +int arg_untrusted_read_noperfmon(void *ctx) +{ + return subprog_untrusted_read(0); +} + +char _license[] SEC("license") = "GPL";