Commit f74c746e authored by Gabriel Krisman Bertazi's avatar Gabriel Krisman Bertazi Committed by Jens Axboe

io_uring/kbuf: Allow the full buffer id space for provided buffers

nbufs tracks the number of buffers and not the last bgid. In 16-bit, we
have 2^16 valid buffers, but the check mistakenly rejects the last
bid. Let's fix it to make the interface consistent with the
documentation.

Fixes: ddf0322d ("io_uring: add IORING_OP_PROVIDE_BUFFERS")
Signed-off-by: default avatarGabriel Krisman Bertazi <krisman@suse.de>
Link: https://lore.kernel.org/r/20231005000531.30800-3-krisman@suse.deSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent ab69838e
...@@ -19,12 +19,15 @@ ...@@ -19,12 +19,15 @@
#define BGID_ARRAY 64 #define BGID_ARRAY 64
/* BIDs are addressed by a 16-bit field in a CQE */
#define MAX_BIDS_PER_BGID (1 << 16)
struct io_provide_buf { struct io_provide_buf {
struct file *file; struct file *file;
__u64 addr; __u64 addr;
__u32 len; __u32 len;
__u32 bgid; __u32 bgid;
__u16 nbufs; __u32 nbufs;
__u16 bid; __u16 bid;
}; };
...@@ -289,7 +292,7 @@ int io_remove_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) ...@@ -289,7 +292,7 @@ int io_remove_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
return -EINVAL; return -EINVAL;
tmp = READ_ONCE(sqe->fd); tmp = READ_ONCE(sqe->fd);
if (!tmp || tmp > USHRT_MAX) if (!tmp || tmp > MAX_BIDS_PER_BGID)
return -EINVAL; return -EINVAL;
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
...@@ -332,7 +335,7 @@ int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe ...@@ -332,7 +335,7 @@ int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
return -EINVAL; return -EINVAL;
tmp = READ_ONCE(sqe->fd); tmp = READ_ONCE(sqe->fd);
if (!tmp || tmp > USHRT_MAX) if (!tmp || tmp > MAX_BIDS_PER_BGID)
return -E2BIG; return -E2BIG;
p->nbufs = tmp; p->nbufs = tmp;
p->addr = READ_ONCE(sqe->addr); p->addr = READ_ONCE(sqe->addr);
...@@ -352,7 +355,7 @@ int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe ...@@ -352,7 +355,7 @@ int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
tmp = READ_ONCE(sqe->off); tmp = READ_ONCE(sqe->off);
if (tmp > USHRT_MAX) if (tmp > USHRT_MAX)
return -E2BIG; return -E2BIG;
if (tmp + p->nbufs > USHRT_MAX) if (tmp + p->nbufs > MAX_BIDS_PER_BGID)
return -EINVAL; return -EINVAL;
p->bid = tmp; p->bid = tmp;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment