Skip to content

Commit ad246d9

Browse files
committed
Merge tag 'io_uring-6.11-20240830' of git://git.kernel.dk/linux
Pull io_uring fixes from Jens Axboe: - A fix for a regression that happened in 6.11 merge window, where the copying of iovecs for compat mode applications got broken for certain cases. - Fix for a bug introduced in 6.10, where if using recv/send bundles with classic provided buffers, the recv/send would fail to set the right iovec count. This caused 0 byte send/recv results. Found via code coverage testing and writing a test case to exercise it. * tag 'io_uring-6.11-20240830' of git://git.kernel.dk/linux: io_uring/kbuf: return correct iovec count from classic buffer peek io_uring/rsrc: ensure compat iovecs are copied correctly
2 parents fb24560 + f274495 commit ad246d9

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

io_uring/kbuf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ static int io_provided_buffers_select(struct io_kiocb *req, size_t *len,
129129

130130
iov[0].iov_base = buf;
131131
iov[0].iov_len = *len;
132-
return 0;
132+
return 1;
133133
}
134134

135135
static struct io_uring_buf *io_ring_head_to_buf(struct io_uring_buf_ring *br,

io_uring/rsrc.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,11 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
394394
struct io_uring_rsrc_update2 *up,
395395
unsigned int nr_args)
396396
{
397-
struct iovec __user *uvec = u64_to_user_ptr(up->data);
398397
u64 __user *tags = u64_to_user_ptr(up->tags);
399398
struct iovec fast_iov, *iov;
400399
struct page *last_hpage = NULL;
400+
struct iovec __user *uvec;
401+
u64 user_data = up->data;
401402
__u32 done;
402403
int i, err;
403404

@@ -410,7 +411,8 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
410411
struct io_mapped_ubuf *imu;
411412
u64 tag = 0;
412413

413-
iov = iovec_from_user(&uvec[done], 1, 1, &fast_iov, ctx->compat);
414+
uvec = u64_to_user_ptr(user_data);
415+
iov = iovec_from_user(uvec, 1, 1, &fast_iov, ctx->compat);
414416
if (IS_ERR(iov)) {
415417
err = PTR_ERR(iov);
416418
break;
@@ -443,6 +445,10 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
443445

444446
ctx->user_bufs[i] = imu;
445447
*io_get_tag_slot(ctx->buf_data, i) = tag;
448+
if (ctx->compat)
449+
user_data += sizeof(struct compat_iovec);
450+
else
451+
user_data += sizeof(struct iovec);
446452
}
447453
return done ? done : err;
448454
}
@@ -949,7 +955,7 @@ int io_sqe_buffers_register(struct io_ring_ctx *ctx, void __user *arg,
949955
struct page *last_hpage = NULL;
950956
struct io_rsrc_data *data;
951957
struct iovec fast_iov, *iov = &fast_iov;
952-
const struct iovec __user *uvec = (struct iovec * __user) arg;
958+
const struct iovec __user *uvec;
953959
int i, ret;
954960

955961
BUILD_BUG_ON(IORING_MAX_REG_BUFFERS >= (1u << 16));
@@ -972,14 +978,19 @@ int io_sqe_buffers_register(struct io_ring_ctx *ctx, void __user *arg,
972978

973979
for (i = 0; i < nr_args; i++, ctx->nr_user_bufs++) {
974980
if (arg) {
975-
iov = iovec_from_user(&uvec[i], 1, 1, &fast_iov, ctx->compat);
981+
uvec = (struct iovec __user *) arg;
982+
iov = iovec_from_user(uvec, 1, 1, &fast_iov, ctx->compat);
976983
if (IS_ERR(iov)) {
977984
ret = PTR_ERR(iov);
978985
break;
979986
}
980987
ret = io_buffer_validate(iov);
981988
if (ret)
982989
break;
990+
if (ctx->compat)
991+
arg += sizeof(struct compat_iovec);
992+
else
993+
arg += sizeof(struct iovec);
983994
}
984995

985996
if (!iov->iov_base && *io_get_tag_slot(data, i)) {

0 commit comments

Comments
 (0)