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: ec02fe217f ("io_uring/bpf-ops: restrict ctx access to BPF")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-11-alexei.starovoitov@gmail.com
This commit is contained in:
Alexei Starovoitov 2026-11-01 19:05:18 +00:00
parent 07684726d3
commit ed02b9cc1d
No known key found for this signature in database
2 changed files with 7 additions and 5 deletions

View File

@ -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
----------------------

View File

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