The bpf_probe_read_{user,kernel}{,_str}_dynptr() kfuncs provide
probe-read style nofault copies into dynptr-backed BPF memory. Their
legacy helper counterparts are exposed only to programs with CAP_PERFMON,
and the kernel-read helpers are additionally blocked by
LOCKDOWN_BPF_READ_KERNEL.

The dynptr kfuncs are registered in the common kfunc set, so the verifier
currently allows them with the generic kfunc privilege gate. Add a common
kfunc filter that mirrors the helper policy for these probe-read dynptr
kfuncs: require CAP_PERFMON for all four nofault probe-read variants and
apply the existing lockdown check to the kernel-read variants.

This preserves the existing dynptr copy implementation while aligning the
capability policy with the legacy probe-read helpers.

Fixes: a498ee7576de ("bpf: Implement dynptr copy kfuncs")
Signed-off-by: Nuoqi Gui <[email protected]>
---
 kernel/bpf/helpers.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 9ca195104667..fbef89196f85 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -4961,9 +4961,41 @@ BTF_ID_FLAGS(func, bpf_dynptr_file_discard)
 BTF_ID_FLAGS(func, bpf_timer_cancel_async)
 BTF_KFUNCS_END(common_btf_ids)
 
+#ifdef CONFIG_BPF_EVENTS
+BTF_KFUNCS_START(probe_read_dynptr_kfunc_ids)
+BTF_ID_FLAGS(func, bpf_probe_read_user_dynptr)
+BTF_ID_FLAGS(func, bpf_probe_read_kernel_dynptr)
+BTF_ID_FLAGS(func, bpf_probe_read_user_str_dynptr)
+BTF_ID_FLAGS(func, bpf_probe_read_kernel_str_dynptr)
+BTF_KFUNCS_END(probe_read_dynptr_kfunc_ids)
+
+BTF_KFUNCS_START(probe_read_kernel_dynptr_kfunc_ids)
+BTF_ID_FLAGS(func, bpf_probe_read_kernel_dynptr)
+BTF_ID_FLAGS(func, bpf_probe_read_kernel_str_dynptr)
+BTF_KFUNCS_END(probe_read_kernel_dynptr_kfunc_ids)
+#endif
+
+static int common_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id)
+{
+#ifdef CONFIG_BPF_EVENTS
+       if (!btf_id_set8_contains(&probe_read_dynptr_kfunc_ids, kfunc_id))
+               return 0;
+
+       if (!bpf_token_capable(prog->aux->token, CAP_PERFMON))
+               return -EACCES;
+
+       if (btf_id_set8_contains(&probe_read_kernel_dynptr_kfunc_ids, kfunc_id) 
&&
+           security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0)
+               return -EACCES;
+#endif
+
+       return 0;
+}
+
 static const struct btf_kfunc_id_set common_kfunc_set = {
        .owner = THIS_MODULE,
        .set   = &common_btf_ids,
+       .filter = common_kfunc_filter,
 };
 
 static int __init kfunc_init(void)

-- 
2.34.1


Reply via email to