[PATCH bpf v3 1/2] bpf: Reject bare pointer for __arg_trusted arg
From: Yiyang Chen
Date: Tue Oct 06 2026 - 12:08:56 EST
A global subprogram parameter tagged __arg_trusted is specified to accept
only lifetime-protected PTR_TO_BTF_ID registers, but the call-site check in
btf_check_func_arg_match() also accepts a bare PTR_TO_BTF_ID.
check_reg_type() resolves the accepted set from the base argument type
alone and compares only MEM_RDONLY and PTR_MAYBE_NULL, so the PTR_TRUSTED
bit of arg_type is never consulted. btf_ptr_types includes bare
PTR_TO_BTF_ID, and nothing else on the subprogram call path rejects it.
The callee is then validated with PTR_TRUSTED set on the register while
the caller passed a pointer without lifetime protection.
bpf_may_fault_on_deref() is false for PTR_TRUSTED, so the dereference
becomes a raw load instead of a BPF_PROBE_MEM probe and the callee can
pass the pointer on as trusted.
Reject a bare PTR_TO_BTF_ID when the argument is marked PTR_TRUSTED. Keep
accepting referenced, trusted, and RCU-protected registers.
PTR_MAYBE_NULL is allowed when __arg_nullable declares it.
The check runs after check_reg_type() and check_func_arg_reg_off()
succeed so that type and offset diagnostics keep their current wording.
The kfunc path is unchanged.
Fixes: e2b3c4ff5d183da6d1863c2321413406a2752e7a ("bpf: add __arg_trusted global func arg tag")
Signed-off-by: Yiyang Chen <chenyy23@xxxxxxxxxxxxxxxxxxxxx>
---
kernel/bpf/verifier.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 5f874979b8d75..7ea181f3e8c15 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -9806,6 +9806,30 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
err = err ?: check_func_arg_reg_off(env, reg, argno, arg->arg_type);
if (err)
return err;
+
+ /*
+ * A __arg_trusted argument requires a referenced, trusted, or
+ * RCU-protected pointer. btf_ptr_types also matches a bare
+ * PTR_TO_BTF_ID, but that has no lifetime protection even
+ * though the callee is verified with PTR_TRUSTED.
+ * PTR_MAYBE_NULL is allowed when __arg_nullable declares it.
+ *
+ * Checked after the type/offset match so that type and offset
+ * diagnostics keep their current wording.
+ */
+ if (arg->arg_type & PTR_TRUSTED) {
+ u32 flags = type_flag(reg->type);
+
+ if (!reg_is_referenced(env, reg) &&
+ (!(flags & (BPF_REG_TRUSTED_MODIFIERS | MEM_RCU)) ||
+ (flags & ~(BPF_REG_TRUSTED_MODIFIERS | MEM_RCU |
+ (arg->arg_type & PTR_MAYBE_NULL))))) {
+ bpf_log(log,
+ "%s must be referenced, trusted, or RCU protected\n",
+ reg_arg_name(env, argno));
+ return -EINVAL;
+ }
+ }
} else {
verifier_bug(env, "unrecognized %s type %d",
reg_arg_name(env, argno), arg->arg_type);
--
2.43.0