Buffer registration is expensive in terms of cpu/mem overhead and there seems no good reason to allow overlapping ranges. Signed-off-by: Bijan Mottahedeh <bijan.mottahedeh@xxxxxxxxxx> --- fs/io_uring.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 9158130..4248726 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -7211,6 +7211,12 @@ static int io_copy_iov(struct io_ring_ctx *ctx, struct iovec *dst, return 0; } +static inline int iov_overlap(struct iovec *v1, struct iovec *v2) +{ + return (v1->iov_base <= (v2->iov_base + v2->iov_len - 1) && + v2->iov_base <= (v1->iov_base + v1->iov_len - 1)); +} + static int io_sqe_buffer_register(struct io_ring_ctx *ctx, void __user *arg, unsigned nr_args) { @@ -7233,7 +7239,7 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, void __user *arg, struct io_mapped_ubuf *imu = &ctx->user_bufs[i]; unsigned long off, start, end, ubuf; int pret, nr_pages; - struct iovec iov; + struct iovec iov, prv_iov; size_t size; ret = io_copy_iov(ctx, &iov, arg, i); @@ -7258,6 +7264,12 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, void __user *arg, start = ubuf >> PAGE_SHIFT; nr_pages = end - start; + /* disallow overlapping buffers */ + if (i > 0 && iov_overlap(&prv_iov, &iov)) + goto err; + + prv_iov = iov; + if (ctx->account_mem) { ret = io_account_mem(ctx->user, nr_pages); if (ret) -- 1.8.3.1