From ed02b9cc1d377d03da2507c3a858f0874aef7494 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Sun, 1 Nov 2026 19:05:18 +0000 Subject: [PATCH] bpf: Don't turn kfunc arguments of an empty struct type into memory A kfunc can take a pointer to a struct that has only scalar members. Then the verifier also accepts memory of the prog: resolve_func_arg_type() changes ARG_PTR_TO_BTF_ID to memory of the size of the struct. An empty struct meets this condition too. But it is a handle for an object of another type. The io_uring kfuncs cast the empty struct iou_ctx to struct io_ring_ctx. Thus they use memory of the prog as a struct io_ring_ctx. Keep ARG_PTR_TO_BTF_ID for a pointer to an empty struct. Then the verifier accepts only a PTR_TO_BTF_ID of that struct, such as the ctx argument of loop_step(). Only one other kfunc takes an empty struct, struct bpf_ws_lock. It releases this argument, and the verifier does not change an argument that the kfunc releases. Add the rule to kfuncs.rst. Fixes: ec02fe217fa6 ("io_uring/bpf-ops: restrict ctx access to BPF") Signed-off-by: Alexei Starovoitov Link: https://patch.msgid.link/20261101190535.1454146-11-alexei.starovoitov@gmail.com --- Documentation/bpf/kfuncs.rst | 6 +++--- kernel/bpf/verifier.c | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/bpf/kfuncs.rst b/Documentation/bpf/kfuncs.rst index 329d1510b02a..901c37504217 100644 --- a/Documentation/bpf/kfuncs.rst +++ b/Documentation/bpf/kfuncs.rst @@ -410,9 +410,9 @@ explored states of the program. A pointer to a struct in the arguments of a KF_ACQUIRE kfunc accepts only an object of that type. The same applies to the argument that a KF_RELEASE kfunc releases. For other arguments a kfunc also accepts memory of the program, if the -struct has only scalar members. struct __sk_buff and struct xdp_md never accept -memory. A KF_ACQUIRE kfunc which wants such memory has to pair the pointer with -a __sz argument. +struct has only scalar members. A struct without members, struct __sk_buff and +struct xdp_md never accept memory. A KF_ACQUIRE kfunc which wants such memory +has to pair the pointer with a __sz argument. 2.5.2 KF_RET_NULL flag ---------------------- diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index ac56e7642432..1bf38f3e4819 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -13593,10 +13593,12 @@ static int resolve_func_arg_type(struct bpf_verifier_env *env, /* * A kfunc that takes a projection type (ie. xdp_md) casts it to the * underlying type. So memory of the program cannot stand in for it, - * even if the projection type holds only scalars. + * even if the projection type holds only scalars. A struct without + * members (ie. iou_ctx) is a handle for an object of another type. */ if (btf_is_projection_type(ref_tname) || - !btf_type_is_scalar_struct(env, btf, ref_t)) + !btf_type_is_scalar_struct(env, btf, ref_t) || + !btf_type_vlen(ref_t)) return 0; resolve_ret = btf_resolve_size(btf, ref_t, arg_size);