1d0e437b7SPavel Begunkov /* SPDX-License-Identifier: GPL-2.0 */ 2d0e437b7SPavel Begunkov #include <linux/mutex.h> 3d0e437b7SPavel Begunkov #include <linux/bpf.h> 4d0e437b7SPavel Begunkov #include <linux/bpf_verifier.h> 5d0e437b7SPavel Begunkov 6d0e437b7SPavel Begunkov #include "io_uring.h" 7d0e437b7SPavel Begunkov #include "register.h" 898f37634SPavel Begunkov #include "loop.h" 989081924SPavel Begunkov #include "memmap.h" 10d0e437b7SPavel Begunkov #include "bpf-ops.h" 11d0e437b7SPavel Begunkov 1298f37634SPavel Begunkov static DEFINE_MUTEX(io_bpf_ctrl_mutex); 13d0e437b7SPavel Begunkov static const struct btf_type *loop_params_type; 14d0e437b7SPavel Begunkov 1589081924SPavel Begunkov __bpf_kfunc_start_defs(); 1689081924SPavel Begunkov 1789081924SPavel Begunkov __bpf_kfunc int bpf_io_uring_submit_sqes(struct io_ring_ctx *ctx, u32 nr) 1889081924SPavel Begunkov { 1989081924SPavel Begunkov return io_submit_sqes(ctx, nr); 2089081924SPavel Begunkov } 2189081924SPavel Begunkov 2289081924SPavel Begunkov __bpf_kfunc 2389081924SPavel Begunkov __u8 *bpf_io_uring_get_region(struct io_ring_ctx *ctx, __u32 region_id, 2489081924SPavel Begunkov const size_t rdwr_buf_size) 2589081924SPavel Begunkov { 2689081924SPavel Begunkov struct io_mapped_region *r; 2789081924SPavel Begunkov 2889081924SPavel Begunkov lockdep_assert_held(&ctx->uring_lock); 2989081924SPavel Begunkov 3089081924SPavel Begunkov switch (region_id) { 3189081924SPavel Begunkov case IOU_REGION_MEM: 3289081924SPavel Begunkov r = &ctx->param_region; 3389081924SPavel Begunkov break; 3489081924SPavel Begunkov case IOU_REGION_CQ: 3589081924SPavel Begunkov r = &ctx->ring_region; 3689081924SPavel Begunkov break; 3789081924SPavel Begunkov case IOU_REGION_SQ: 3889081924SPavel Begunkov r = &ctx->sq_region; 3989081924SPavel Begunkov break; 4089081924SPavel Begunkov default: 4189081924SPavel Begunkov return NULL; 4289081924SPavel Begunkov } 4389081924SPavel Begunkov 4489081924SPavel Begunkov if (unlikely(rdwr_buf_size > io_region_size(r))) 4589081924SPavel Begunkov return NULL; 4689081924SPavel Begunkov return io_region_get_ptr(r); 4789081924SPavel Begunkov } 4889081924SPavel Begunkov 4989081924SPavel Begunkov __bpf_kfunc_end_defs(); 5089081924SPavel Begunkov 5189081924SPavel Begunkov BTF_KFUNCS_START(io_uring_kfunc_set) 5289081924SPavel Begunkov BTF_ID_FLAGS(func, bpf_io_uring_submit_sqes, KF_SLEEPABLE); 5389081924SPavel Begunkov BTF_ID_FLAGS(func, bpf_io_uring_get_region, KF_RET_NULL); 5489081924SPavel Begunkov BTF_KFUNCS_END(io_uring_kfunc_set) 5589081924SPavel Begunkov 5689081924SPavel Begunkov static const struct btf_kfunc_id_set bpf_io_uring_kfunc_set = { 5789081924SPavel Begunkov .owner = THIS_MODULE, 5889081924SPavel Begunkov .set = &io_uring_kfunc_set, 5989081924SPavel Begunkov }; 6089081924SPavel Begunkov 61d0e437b7SPavel Begunkov static int io_bpf_ops__loop_step(struct io_ring_ctx *ctx, 62d0e437b7SPavel Begunkov struct iou_loop_params *lp) 63d0e437b7SPavel Begunkov { 64d0e437b7SPavel Begunkov return IOU_LOOP_STOP; 65d0e437b7SPavel Begunkov } 66d0e437b7SPavel Begunkov 67d0e437b7SPavel Begunkov static struct io_uring_bpf_ops io_bpf_ops_stubs = { 68d0e437b7SPavel Begunkov .loop_step = io_bpf_ops__loop_step, 69d0e437b7SPavel Begunkov }; 70d0e437b7SPavel Begunkov 71d0e437b7SPavel Begunkov static bool bpf_io_is_valid_access(int off, int size, 72d0e437b7SPavel Begunkov enum bpf_access_type type, 73d0e437b7SPavel Begunkov const struct bpf_prog *prog, 74d0e437b7SPavel Begunkov struct bpf_insn_access_aux *info) 75d0e437b7SPavel Begunkov { 76d0e437b7SPavel Begunkov if (type != BPF_READ) 77d0e437b7SPavel Begunkov return false; 78d0e437b7SPavel Begunkov if (off < 0 || off >= sizeof(__u64) * MAX_BPF_FUNC_ARGS) 79d0e437b7SPavel Begunkov return false; 80d0e437b7SPavel Begunkov if (off % size != 0) 81d0e437b7SPavel Begunkov return false; 82d0e437b7SPavel Begunkov 83d0e437b7SPavel Begunkov return btf_ctx_access(off, size, type, prog, info); 84d0e437b7SPavel Begunkov } 85d0e437b7SPavel Begunkov 86d0e437b7SPavel Begunkov static int bpf_io_btf_struct_access(struct bpf_verifier_log *log, 87d0e437b7SPavel Begunkov const struct bpf_reg_state *reg, int off, 88d0e437b7SPavel Begunkov int size) 89d0e437b7SPavel Begunkov { 90d0e437b7SPavel Begunkov const struct btf_type *t = btf_type_by_id(reg->btf, reg->btf_id); 91d0e437b7SPavel Begunkov 92d0e437b7SPavel Begunkov if (t == loop_params_type) { 93d0e437b7SPavel Begunkov if (off + size <= offsetofend(struct iou_loop_params, cq_wait_idx)) 94d0e437b7SPavel Begunkov return SCALAR_VALUE; 95d0e437b7SPavel Begunkov } 96d0e437b7SPavel Begunkov 97d0e437b7SPavel Begunkov return -EACCES; 98d0e437b7SPavel Begunkov } 99d0e437b7SPavel Begunkov 100d0e437b7SPavel Begunkov static const struct bpf_verifier_ops bpf_io_verifier_ops = { 101d0e437b7SPavel Begunkov .get_func_proto = bpf_base_func_proto, 102d0e437b7SPavel Begunkov .is_valid_access = bpf_io_is_valid_access, 103d0e437b7SPavel Begunkov .btf_struct_access = bpf_io_btf_struct_access, 104d0e437b7SPavel Begunkov }; 105d0e437b7SPavel Begunkov 106d0e437b7SPavel Begunkov static const struct btf_type * 107d0e437b7SPavel Begunkov io_lookup_struct_type(struct btf *btf, const char *name) 108d0e437b7SPavel Begunkov { 109d0e437b7SPavel Begunkov s32 type_id; 110d0e437b7SPavel Begunkov 111d0e437b7SPavel Begunkov type_id = btf_find_by_name_kind(btf, name, BTF_KIND_STRUCT); 112d0e437b7SPavel Begunkov if (type_id < 0) 113d0e437b7SPavel Begunkov return NULL; 114d0e437b7SPavel Begunkov return btf_type_by_id(btf, type_id); 115d0e437b7SPavel Begunkov } 116d0e437b7SPavel Begunkov 117d0e437b7SPavel Begunkov static int bpf_io_init(struct btf *btf) 118d0e437b7SPavel Begunkov { 11989081924SPavel Begunkov int ret; 12089081924SPavel Begunkov 121d0e437b7SPavel Begunkov loop_params_type = io_lookup_struct_type(btf, "iou_loop_params"); 122d0e437b7SPavel Begunkov if (!loop_params_type) { 123d0e437b7SPavel Begunkov pr_err("io_uring: Failed to locate iou_loop_params\n"); 124d0e437b7SPavel Begunkov return -EINVAL; 125d0e437b7SPavel Begunkov } 126d0e437b7SPavel Begunkov 12789081924SPavel Begunkov ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, 12889081924SPavel Begunkov &bpf_io_uring_kfunc_set); 12989081924SPavel Begunkov if (ret) { 13089081924SPavel Begunkov pr_err("io_uring: Failed to register kfuncs (%d)\n", ret); 13189081924SPavel Begunkov return ret; 13289081924SPavel Begunkov } 133d0e437b7SPavel Begunkov return 0; 134d0e437b7SPavel Begunkov } 135d0e437b7SPavel Begunkov 136d0e437b7SPavel Begunkov static int bpf_io_check_member(const struct btf_type *t, 137d0e437b7SPavel Begunkov const struct btf_member *member, 138d0e437b7SPavel Begunkov const struct bpf_prog *prog) 139d0e437b7SPavel Begunkov { 140d0e437b7SPavel Begunkov return 0; 141d0e437b7SPavel Begunkov } 142d0e437b7SPavel Begunkov 143d0e437b7SPavel Begunkov static int bpf_io_init_member(const struct btf_type *t, 144d0e437b7SPavel Begunkov const struct btf_member *member, 145d0e437b7SPavel Begunkov void *kdata, const void *udata) 146d0e437b7SPavel Begunkov { 14798f37634SPavel Begunkov u32 moff = __btf_member_bit_offset(t, member) / 8; 14898f37634SPavel Begunkov const struct io_uring_bpf_ops *uops = udata; 14998f37634SPavel Begunkov struct io_uring_bpf_ops *ops = kdata; 15098f37634SPavel Begunkov 15198f37634SPavel Begunkov switch (moff) { 15298f37634SPavel Begunkov case offsetof(struct io_uring_bpf_ops, ring_fd): 15398f37634SPavel Begunkov ops->ring_fd = uops->ring_fd; 15498f37634SPavel Begunkov return 1; 15598f37634SPavel Begunkov } 15698f37634SPavel Begunkov return 0; 15798f37634SPavel Begunkov } 15898f37634SPavel Begunkov 15998f37634SPavel Begunkov static int io_install_bpf(struct io_ring_ctx *ctx, struct io_uring_bpf_ops *ops) 16098f37634SPavel Begunkov { 16198f37634SPavel Begunkov if (ctx->flags & (IORING_SETUP_SQPOLL | IORING_SETUP_IOPOLL)) 16298f37634SPavel Begunkov return -EOPNOTSUPP; 16398f37634SPavel Begunkov if (!(ctx->flags & IORING_SETUP_DEFER_TASKRUN)) 16498f37634SPavel Begunkov return -EOPNOTSUPP; 16598f37634SPavel Begunkov 16698f37634SPavel Begunkov if (ctx->bpf_ops) 16798f37634SPavel Begunkov return -EBUSY; 16898f37634SPavel Begunkov if (WARN_ON_ONCE(!ops->loop_step)) 16998f37634SPavel Begunkov return -EINVAL; 17098f37634SPavel Begunkov 17198f37634SPavel Begunkov ops->priv = ctx; 17298f37634SPavel Begunkov ctx->bpf_ops = ops; 17398f37634SPavel Begunkov ctx->loop_step = ops->loop_step; 174d0e437b7SPavel Begunkov return 0; 175d0e437b7SPavel Begunkov } 176d0e437b7SPavel Begunkov 177d0e437b7SPavel Begunkov static int bpf_io_reg(void *kdata, struct bpf_link *link) 178d0e437b7SPavel Begunkov { 17998f37634SPavel Begunkov struct io_uring_bpf_ops *ops = kdata; 18098f37634SPavel Begunkov struct io_ring_ctx *ctx; 18198f37634SPavel Begunkov struct file *file; 18298f37634SPavel Begunkov int ret = -EBUSY; 18398f37634SPavel Begunkov 184*c5e9f6a9SJens Axboe file = io_uring_ctx_get_file(ops->ring_fd, false); 18598f37634SPavel Begunkov if (IS_ERR(file)) 18698f37634SPavel Begunkov return PTR_ERR(file); 18798f37634SPavel Begunkov ctx = file->private_data; 18898f37634SPavel Begunkov 18998f37634SPavel Begunkov scoped_guard(mutex, &io_bpf_ctrl_mutex) { 19098f37634SPavel Begunkov guard(mutex)(&ctx->uring_lock); 19198f37634SPavel Begunkov ret = io_install_bpf(ctx, ops); 19298f37634SPavel Begunkov } 19398f37634SPavel Begunkov 19498f37634SPavel Begunkov fput(file); 19598f37634SPavel Begunkov return ret; 19698f37634SPavel Begunkov } 19798f37634SPavel Begunkov 19898f37634SPavel Begunkov static void io_eject_bpf(struct io_ring_ctx *ctx) 19998f37634SPavel Begunkov { 20098f37634SPavel Begunkov struct io_uring_bpf_ops *ops = ctx->bpf_ops; 20198f37634SPavel Begunkov 20298f37634SPavel Begunkov if (WARN_ON_ONCE(!ops)) 20398f37634SPavel Begunkov return; 20498f37634SPavel Begunkov if (WARN_ON_ONCE(ops->priv != ctx)) 20598f37634SPavel Begunkov return; 20698f37634SPavel Begunkov 20798f37634SPavel Begunkov ops->priv = NULL; 20898f37634SPavel Begunkov ctx->bpf_ops = NULL; 20998f37634SPavel Begunkov ctx->loop_step = NULL; 210d0e437b7SPavel Begunkov } 211d0e437b7SPavel Begunkov 212d0e437b7SPavel Begunkov static void bpf_io_unreg(void *kdata, struct bpf_link *link) 213d0e437b7SPavel Begunkov { 21498f37634SPavel Begunkov struct io_uring_bpf_ops *ops = kdata; 21598f37634SPavel Begunkov struct io_ring_ctx *ctx; 21698f37634SPavel Begunkov 21798f37634SPavel Begunkov guard(mutex)(&io_bpf_ctrl_mutex); 21898f37634SPavel Begunkov ctx = ops->priv; 21998f37634SPavel Begunkov if (ctx) { 22098f37634SPavel Begunkov guard(mutex)(&ctx->uring_lock); 22198f37634SPavel Begunkov if (WARN_ON_ONCE(ctx->bpf_ops != ops)) 22298f37634SPavel Begunkov return; 22398f37634SPavel Begunkov 22498f37634SPavel Begunkov io_eject_bpf(ctx); 22598f37634SPavel Begunkov } 22698f37634SPavel Begunkov } 22798f37634SPavel Begunkov 22898f37634SPavel Begunkov void io_unregister_bpf_ops(struct io_ring_ctx *ctx) 22998f37634SPavel Begunkov { 23098f37634SPavel Begunkov /* 23198f37634SPavel Begunkov * ->bpf_ops is write protected by io_bpf_ctrl_mutex and uring_lock, 23298f37634SPavel Begunkov * and read protected by either. Try to avoid taking the global lock 23398f37634SPavel Begunkov * for rings that never had any bpf installed. 23498f37634SPavel Begunkov */ 23598f37634SPavel Begunkov scoped_guard(mutex, &ctx->uring_lock) { 23698f37634SPavel Begunkov if (!ctx->bpf_ops) 23798f37634SPavel Begunkov return; 23898f37634SPavel Begunkov } 23998f37634SPavel Begunkov 24098f37634SPavel Begunkov guard(mutex)(&io_bpf_ctrl_mutex); 24198f37634SPavel Begunkov guard(mutex)(&ctx->uring_lock); 24298f37634SPavel Begunkov if (ctx->bpf_ops) 24398f37634SPavel Begunkov io_eject_bpf(ctx); 244d0e437b7SPavel Begunkov } 245d0e437b7SPavel Begunkov 246d0e437b7SPavel Begunkov static struct bpf_struct_ops bpf_ring_ops = { 247d0e437b7SPavel Begunkov .verifier_ops = &bpf_io_verifier_ops, 248d0e437b7SPavel Begunkov .reg = bpf_io_reg, 249d0e437b7SPavel Begunkov .unreg = bpf_io_unreg, 250d0e437b7SPavel Begunkov .check_member = bpf_io_check_member, 251d0e437b7SPavel Begunkov .init_member = bpf_io_init_member, 252d0e437b7SPavel Begunkov .init = bpf_io_init, 253d0e437b7SPavel Begunkov .cfi_stubs = &io_bpf_ops_stubs, 254d0e437b7SPavel Begunkov .name = "io_uring_bpf_ops", 255d0e437b7SPavel Begunkov .owner = THIS_MODULE, 256d0e437b7SPavel Begunkov }; 257d0e437b7SPavel Begunkov 258d0e437b7SPavel Begunkov static int __init io_uring_bpf_init(void) 259d0e437b7SPavel Begunkov { 260d0e437b7SPavel Begunkov int ret; 261d0e437b7SPavel Begunkov 262d0e437b7SPavel Begunkov ret = register_bpf_struct_ops(&bpf_ring_ops, io_uring_bpf_ops); 263d0e437b7SPavel Begunkov if (ret) { 264d0e437b7SPavel Begunkov pr_err("io_uring: Failed to register struct_ops (%d)\n", ret); 265d0e437b7SPavel Begunkov return ret; 266d0e437b7SPavel Begunkov } 267d0e437b7SPavel Begunkov 268d0e437b7SPavel Begunkov return 0; 269d0e437b7SPavel Begunkov } 270d0e437b7SPavel Begunkov __initcall(io_uring_bpf_init); 271