selftests/bpf: Add tests for the KF_PERFMON gates

Add test cases where each one loads with CAP_BPF alone and checks that
the program is correctly rejected.

  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_kfunc_perfmon
  [...]
  #627/1   verifier_kfunc_perfmon/rdonly_cast_noperfmon:OK
  #627/2   verifier_kfunc_perfmon/rdonly_cast_noperfmon @unpriv:OK
  #627/3   verifier_kfunc_perfmon/probe_read_kernel_dynptr_noperfmon:OK
  #627/4   verifier_kfunc_perfmon/probe_read_kernel_dynptr_noperfmon @unpriv:OK
  #627/5   verifier_kfunc_perfmon/stream_vprintk_noperfmon:OK
  #627/6   verifier_kfunc_perfmon/stream_vprintk_noperfmon @unpriv:OK
  #627/7   verifier_kfunc_perfmon/get_kmem_cache_noperfmon:OK
  #627/8   verifier_kfunc_perfmon/get_kmem_cache_noperfmon @unpriv:OK
  #627/9   verifier_kfunc_perfmon/arg_untrusted_read_noperfmon:OK
  #627/10  verifier_kfunc_perfmon/arg_untrusted_read_noperfmon @unpriv:OK
  #627     verifier_kfunc_perfmon:OK
  Summary: 1/10 PASSED, 0 SKIPPED, 0/0 FAILED

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20260910213510.49358-4-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Daniel Borkmann 2026-09-10 23:35:10 +02:00 committed by Alexei Starovoitov
parent f9191460cd
commit a903f145a8
2 changed files with 77 additions and 0 deletions

View File

@ -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); }

View File

@ -0,0 +1,75 @@
// SPDX-License-Identifier: GPL-2.0
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#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";