]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
io_uring/bpf-ops: restrict ctx access to BPF
authorPavel Begunkov <asml.silence@gmail.com>
Tue, 2 Jun 2026 10:08:25 +0000 (11:08 +0100)
committerJens Axboe <axboe@kernel.dk>
Tue, 2 Jun 2026 17:20:21 +0000 (11:20 -0600)
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 <asml.silence@gmail.com>
Link: https://patch.msgid.link/5f6ca3649e9e0bae8667db4357e28dd00cd07901.1780394491.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/io_uring_types.h
io_uring/bpf-ops.c
io_uring/bpf-ops.h
io_uring/loop.c
io_uring/loop.h

index 23b8891d5704542b06ca2dd5784ef2bb51d816d4..aa4d5477f8591ddd236031f8d77053d8573d8d15 100644 (file)
@@ -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 *);
 
                /*
index 937e48bef40bcc05f9590badd6a1dcd3929dee22..5a50f0675fe58f74bb2521e3a4a4d413b2b644fc 100644 (file)
@@ -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;
index b39b3fd3acdab8d9c62ef548dc3033dc711d2d34..0b6d7894915e196e39957721c7629cf771e2d3af 100644 (file)
@@ -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;
index 31843cc3e4510b045f0adc1eed6307b118be6bf6..bbbb6ef14e6a8ea6c0cb624b4201c27fde3a24dd 100644 (file)
@@ -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)
index d7718b9ce61ee223674f7d091a6d0411e740a7a2..4dd4fb3aefefca0b6403fa7e736cbda2eaad9b0b 100644 (file)
@@ -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