mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-10-26 10:57:38 +08:00
bpf: Check helper and kfunc arguments in one path
Generated kfunc prototypes now carry the argument kinds and metadata needed by the helper argument checker, but kfunc calls still duplicate the per-argument loop and switch. Add check_func_args() to determine the argument count, validate outgoing kfunc stack arguments, and drive check_func_arg() for both call kinds. Move the remaining kfunc-only argument handlers, including the dynptr clone runtime refinement, into check_func_arg(), derive each kfunc BTF referent there once, and skip check_reg_arg() for stack-passed arguments that check_outgoing_stack_args() already validated. Keep special-kfunc ID checks behind small helpers so their table can remain in place. Keep the intentional differences selected by call metadata: helpers retain their privileged ARG_ANYTHING pointer-leak behavior, while kfunc scalars use strict ARG_SCALAR register admission. The shared ARG_PTR_TO_BTF_ID case retains helper-only compatible-ID and bpf_kptr_xchg() handling, performs kfunc trusted/RCU provenance checks, and selects the expected BTF based on call kind. Helper and kfunc memory arguments likewise retain their access modes and share fixed-memory and memory/size diagnostics. Treat an accepted nullable NULL as a completed argument check, matching the former kfunc continue path. The skipped helper-specific processing is either a no-op for NULL or deferred to the paired size argument. Signed-off-by: Amery Hung <ameryhung@gmail.com> Link: https://lore.kernel.org/r/20260911220415.1396439-24-ameryhung@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
1 parent
4f18de58a4
commit
ab7fff217f
5 files changed
+445
-495
No files matched your search
+441
-491
File diff suppressed because it is too large.
Load diff
@@ -11,7 +11,7 @@ struct {
|
||||
const char *prog_name;
|
||||
const char *err_msg;
|
||||
} cb_refs_tests[] = {
|
||||
{ "underflow_prog", "release function bpf_kfunc_call_test_release expects referenced PTR_TO_BTF_ID passed to R1" },
|
||||
{ "underflow_prog", "R1 type=scalar expected=ptr_, trusted_ptr_, rcu_ptr_" },
|
||||
{ "leak_prog", "Unreleased reference id=4 alloc_insn=3" }, /* alloc_insn=3{2,3} */
|
||||
{ "nested_cb", "Unreleased reference id=4 alloc_insn=2" }, /* alloc_insn=2{4,5} */
|
||||
{ "non_cb_transfer_ref", "Unreleased reference id=4 alloc_insn=1" }, /* alloc_insn=1{1,2} */
|
||||
|
||||
@@ -191,7 +191,7 @@ int BPF_PROG(cgrp_kfunc_release_untrusted, struct cgroup *cgrp, const char *path
|
||||
}
|
||||
|
||||
SEC("tp_btf/cgroup_mkdir")
|
||||
__failure __msg("release function bpf_cgroup_release expects referenced PTR_TO_BTF_ID passed to R1")
|
||||
__failure __msg("R1 type=fp expected=ptr_, trusted_ptr_, rcu_ptr_")
|
||||
int BPF_PROG(cgrp_kfunc_release_fp, struct cgroup *cgrp, const char *path)
|
||||
{
|
||||
struct cgroup *acquired = (struct cgroup *)&path;
|
||||
|
||||
@@ -179,7 +179,7 @@ int BPF_PROG(task_kfunc_release_untrusted, struct task_struct *task, u64 clone_f
|
||||
}
|
||||
|
||||
SEC("tp_btf/task_newtask")
|
||||
__failure __msg("release function bpf_task_release expects referenced PTR_TO_BTF_ID passed to R1")
|
||||
__failure __msg("R1 type=fp expected=ptr_, trusted_ptr_, rcu_ptr_")
|
||||
int BPF_PROG(task_kfunc_release_fp, struct task_struct *task, u64 clone_flags)
|
||||
{
|
||||
struct task_struct *acquired = (struct task_struct *)&clone_flags;
|
||||
|
||||
@@ -42,7 +42,7 @@ int wakeup_source_access_lock_fields(void *ctx)
|
||||
}
|
||||
|
||||
SEC("syscall")
|
||||
__failure __msg("release function bpf_wakeup_sources_read_unlock expects referenced PTR_TO_BTF_ID passed to R1")
|
||||
__failure __msg("R1 type=scalar expected=ptr_, trusted_ptr_, rcu_ptr_")
|
||||
int wakeup_source_unlock_no_lock(void *ctx)
|
||||
{
|
||||
struct bpf_ws_lock *lock = (void *)0x1;
|
||||
|
||||
Reference in new issue
Block a user