io_uring-6.11-20240830

-----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAmbSK4IQHGF4Ym9lQGtl
 cm5lbC5kawAKCRD301j7KXHgpliBEADDHUInWoLD5zBzZv5XNgu/U0VgpsLJnOWR
 DibfvGx5pMPOMvwtxvSlPBGGjWlimbIVmjV3I5SvP6mhyiOv4PaI7aSuA2k7Y0sy
 ex9vX0icXQXC5maKcvGOXXroP59SYcKQ1DCqZvXZOQ5D4/phB9y1ZRrwMHwzENYO
 ACd/yuef87Klzv4NZ7TSNjaJMa/fWY6nlTYVpaB79ke6AnvWntP9KOSIfu79nazN
 23hUbCcRRzt5YqwOJiogIFnt1gNyuipJewkH0vfLW4NQwp6FiOEOlmY8dZnu+flF
 mnObT5dm1UeIbsW9OanG/yqOaU645q8OgY59CN6FMX5SLfuLkZzlZIpzYY4vKxxu
 cO6woKSi/jzrgK4A6eapWxEfE/Wh9JLCLZy+PS8j+v3j9jt+DCMVO2/CLgD4wdMD
 wBgjOgAjAOWIdRoP/f+ocYCaml5YHP9A33AG3lgOYZ5EdXReGn20jevv7S0MD7Yu
 /QdJhE5RT8T2rxnyyZKzrJqI3rlkdwYQTh3PmepO1EvfnO1jmw9deNd+CdgpCD4Q
 lGjcNknpPN2SiWtIsKSOIQgNolTXM2RYD3sgYhyjofWvl1AKOQJXbRSnV5K9Hf4O
 /QhNO4sQW7G9EVjXoyMUiQ9nw7Y5Ty9Zo+zeH/Di22o4STje2mTKYoOGnQ1eITAY
 DrtMKuF22g==
 =Zabp
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2024-08-31 13:51:27 +12:00
commit ad246d9f04
2 changed files with 16 additions and 5 deletions

View File

@ -129,7 +129,7 @@ static int io_provided_buffers_select(struct io_kiocb *req, size_t *len,
iov[0].iov_base = buf; iov[0].iov_base = buf;
iov[0].iov_len = *len; iov[0].iov_len = *len;
return 0; return 1;
} }
static struct io_uring_buf *io_ring_head_to_buf(struct io_uring_buf_ring *br, static struct io_uring_buf *io_ring_head_to_buf(struct io_uring_buf_ring *br,

View File

@ -394,10 +394,11 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
struct io_uring_rsrc_update2 *up, struct io_uring_rsrc_update2 *up,
unsigned int nr_args) unsigned int nr_args)
{ {
struct iovec __user *uvec = u64_to_user_ptr(up->data);
u64 __user *tags = u64_to_user_ptr(up->tags); u64 __user *tags = u64_to_user_ptr(up->tags);
struct iovec fast_iov, *iov; struct iovec fast_iov, *iov;
struct page *last_hpage = NULL; struct page *last_hpage = NULL;
struct iovec __user *uvec;
u64 user_data = up->data;
__u32 done; __u32 done;
int i, err; int i, err;
@ -410,7 +411,8 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
struct io_mapped_ubuf *imu; struct io_mapped_ubuf *imu;
u64 tag = 0; u64 tag = 0;
iov = iovec_from_user(&uvec[done], 1, 1, &fast_iov, ctx->compat); uvec = u64_to_user_ptr(user_data);
iov = iovec_from_user(uvec, 1, 1, &fast_iov, ctx->compat);
if (IS_ERR(iov)) { if (IS_ERR(iov)) {
err = PTR_ERR(iov); err = PTR_ERR(iov);
break; break;
@ -443,6 +445,10 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
ctx->user_bufs[i] = imu; ctx->user_bufs[i] = imu;
*io_get_tag_slot(ctx->buf_data, i) = tag; *io_get_tag_slot(ctx->buf_data, i) = tag;
if (ctx->compat)
user_data += sizeof(struct compat_iovec);
else
user_data += sizeof(struct iovec);
} }
return done ? done : err; return done ? done : err;
} }
@ -949,7 +955,7 @@ int io_sqe_buffers_register(struct io_ring_ctx *ctx, void __user *arg,
struct page *last_hpage = NULL; struct page *last_hpage = NULL;
struct io_rsrc_data *data; struct io_rsrc_data *data;
struct iovec fast_iov, *iov = &fast_iov; struct iovec fast_iov, *iov = &fast_iov;
const struct iovec __user *uvec = (struct iovec * __user) arg; const struct iovec __user *uvec;
int i, ret; int i, ret;
BUILD_BUG_ON(IORING_MAX_REG_BUFFERS >= (1u << 16)); BUILD_BUG_ON(IORING_MAX_REG_BUFFERS >= (1u << 16));
@ -972,7 +978,8 @@ int io_sqe_buffers_register(struct io_ring_ctx *ctx, void __user *arg,
for (i = 0; i < nr_args; i++, ctx->nr_user_bufs++) { for (i = 0; i < nr_args; i++, ctx->nr_user_bufs++) {
if (arg) { if (arg) {
iov = iovec_from_user(&uvec[i], 1, 1, &fast_iov, ctx->compat); uvec = (struct iovec __user *) arg;
iov = iovec_from_user(uvec, 1, 1, &fast_iov, ctx->compat);
if (IS_ERR(iov)) { if (IS_ERR(iov)) {
ret = PTR_ERR(iov); ret = PTR_ERR(iov);
break; break;
@ -980,6 +987,10 @@ int io_sqe_buffers_register(struct io_ring_ctx *ctx, void __user *arg,
ret = io_buffer_validate(iov); ret = io_buffer_validate(iov);
if (ret) if (ret)
break; break;
if (ctx->compat)
arg += sizeof(struct compat_iovec);
else
arg += sizeof(struct iovec);
} }
if (!iov->iov_base && *io_get_tag_slot(data, i)) { if (!iov->iov_base && *io_get_tag_slot(data, i)) {