From: Pavel Begunkov Date: Tue, 2 Jun 2026 10:08:25 +0000 (+0100) Subject: io_uring/bpf-ops: restrict ctx access to BPF X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=ec02fe217fa66d79f8a65e8d28be9295c7f85093;p=thirdparty%2Fkernel%2Flinux.git io_uring/bpf-ops: restrict ctx access to BPF BPF programs should have no need in looking into struct io_ring_ctx, if anything, most of such cases would be anti patterns like looking up ring indices directly via the context. Replace it with a new empty structure, which is just an alias to struct io_ring_ctx. It'll create a new BTF type and fail verification if a BPF program tries to access it (beyond the first byte). It'll also give more flexibility for the future, and otherwise it can be made aligned with io_ring_ctx as before with struct groups if ever needed or extended in a different way. Fixes: d0e437b76bd3c ("io_uring/bpf-ops: implement loop_step with BPF struct_ops") Signed-off-by: Pavel Begunkov Link: https://patch.msgid.link/5f6ca3649e9e0bae8667db4357e28dd00cd07901.1780394491.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h index 23b8891d57045..aa4d5477f8591 100644 --- a/include/linux/io_uring_types.h +++ b/include/linux/io_uring_types.h @@ -290,6 +290,8 @@ enum { IO_RING_F_IOWQ_LIMITS_SET = BIT(12), }; +struct iou_ctx {}; + struct io_ring_ctx { /* const or read-mostly hot data */ struct { @@ -366,7 +368,7 @@ struct io_ring_ctx { struct io_alloc_cache rw_cache; struct io_alloc_cache cmd_cache; - int (*loop_step)(struct io_ring_ctx *ctx, + int (*loop_step)(struct iou_ctx *, struct iou_loop_params *); /* diff --git a/io_uring/bpf-ops.c b/io_uring/bpf-ops.c index 937e48bef40bc..5a50f0675fe58 100644 --- a/io_uring/bpf-ops.c +++ b/io_uring/bpf-ops.c @@ -14,15 +14,18 @@ static const struct btf_type *loop_params_type; __bpf_kfunc_start_defs(); -__bpf_kfunc int bpf_io_uring_submit_sqes(struct io_ring_ctx *ctx, u32 nr) +__bpf_kfunc int bpf_io_uring_submit_sqes(struct iou_ctx *loop_ctx, u32 nr) { + struct io_ring_ctx *ctx = io_loop_demangle_ctx(loop_ctx); + return io_submit_sqes(ctx, nr); } __bpf_kfunc -__u8 *bpf_io_uring_get_region(struct io_ring_ctx *ctx, __u32 region_id, +__u8 *bpf_io_uring_get_region(struct iou_ctx *loop_ctx, __u32 region_id, const size_t rdwr_buf_size) { + struct io_ring_ctx *ctx = io_loop_demangle_ctx(loop_ctx); struct io_mapped_region *r; lockdep_assert_held(&ctx->uring_lock); @@ -58,7 +61,7 @@ static const struct btf_kfunc_id_set bpf_io_uring_kfunc_set = { .set = &io_uring_kfunc_set, }; -static int io_bpf_ops__loop_step(struct io_ring_ctx *ctx, +static int io_bpf_ops__loop_step(struct iou_ctx *ctx, struct iou_loop_params *lp) { return IOU_LOOP_STOP; diff --git a/io_uring/bpf-ops.h b/io_uring/bpf-ops.h index b39b3fd3acdab..0b6d7894915e1 100644 --- a/io_uring/bpf-ops.h +++ b/io_uring/bpf-ops.h @@ -11,7 +11,7 @@ enum { }; struct io_uring_bpf_ops { - int (*loop_step)(struct io_ring_ctx *ctx, struct iou_loop_params *lp); + int (*loop_step)(struct iou_ctx *, struct iou_loop_params *lp); __u32 ring_fd; void *priv; diff --git a/io_uring/loop.c b/io_uring/loop.c index 31843cc3e4510..bbbb6ef14e6a8 100644 --- a/io_uring/loop.c +++ b/io_uring/loop.c @@ -49,7 +49,7 @@ static int __io_run_loop(struct io_ring_ctx *ctx) if (unlikely(!ctx->loop_step)) return -EFAULT; - step_res = ctx->loop_step(ctx, &lp); + step_res = ctx->loop_step(io_loop_mangle_ctx(ctx), &lp); if (step_res == IOU_LOOP_STOP) break; if (step_res != IOU_LOOP_CONTINUE) diff --git a/io_uring/loop.h b/io_uring/loop.h index d7718b9ce61ee..4dd4fb3aefefc 100644 --- a/io_uring/loop.h +++ b/io_uring/loop.h @@ -24,4 +24,14 @@ static inline bool io_has_loop_ops(struct io_ring_ctx *ctx) int io_run_loop(struct io_ring_ctx *ctx); +static inline struct iou_ctx *io_loop_mangle_ctx(struct io_ring_ctx *ctx) +{ + return (struct iou_ctx *)ctx; +} + +static inline struct io_ring_ctx *io_loop_demangle_ctx(struct iou_ctx *ctx) +{ + return (struct io_ring_ctx *)ctx; +} + #endif