changes around fixed rsrc
Subsystems (3)
cover changes around fixed rsrc
1-2 put some limits on the fixed file tables sizes, files and buffers.
3/3 adds compatibility checks for ->splice_fd_in, for all requests buy rw and some others, see the patch message.
All based on 5.15 and merked stable, looks to me as the best way.
Pavel Begunkov (3):
io_uring: limit fixed table size by RLIMIT_NOFILE
io_uring: place fixed tables under memcg limits
io_uring: add ->splice_fd_in checks
fs/io_uring.c | 61 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 25 deletions(-)
Signature · 1 line
2.32.0
PATCH 1/3 io_uring: limit fixed table size by RLIMIT_NOFILE
Limit the number of files in io_uring fixed tables by RLIMIT_NOFILE, that's the first and the simpliest restriction that we should impose.
--- fs/io_uring.c | 2 ++ 1 file changed, 2 insertions(+)
fs/io_uring.c +2 -0
@@ -7730,6 +7730,8 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,return -EINVAL ;if (nr_args >IORING_MAX_FIXED_FILES )return -EMFILE ; +if (nr_args >rlimit (RLIMIT_NOFILE )) +return -EMFILE ; ret =io_rsrc_node_switch_start (ctx);if (ret)return ret;
Signature · 1 line
2.32.0
PATCH 2/3 io_uring: place fixed tables under memcg limits
In reply to Pavel BegunkovFixed tables may be large enough, place all of them together with allocated tags under memcg limits.
--- fs/io_uring.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
fs/io_uring.c +4 -3
@@ -7135,14 +7135,14 @@ static void **io_alloc_page_table(size_t size)size_t init_size = size;void **table; - table =kcalloc (nr_tables,sizeof (*table),GFP_KERNEL ); + table =kcalloc (nr_tables,sizeof (*table),GFP_KERNEL_ACCOUNT );if (!table)return NULL ;for (i =0 ; i < nr_tables; i++) {unsigned int this_size =min_t (size_t, size,PAGE_SIZE ); - table[i] =kzalloc (this_size,GFP_KERNEL ); + table[i] =kzalloc (this_size,GFP_KERNEL_ACCOUNT );if (!table[i]) {io_free_page_table (table, init_size);return NULL ;
@@ -7333,7 +7333,8 @@ static int io_rsrc_data_alloc(struct io_ring_ctx *ctx, rsrc_put_fn *do_put,static bool io_alloc_file_tables (struct io_file_table *table,unsigned nr_files) { - table->files =kvcalloc (nr_files,sizeof (table->files[0 ]),GFP_KERNEL ); + table->files =kvcalloc (nr_files,sizeof (table->files[0 ]), +GFP_KERNEL_ACCOUNT );return !!table->files; }
Signature · 1 line
2.32.0
PATCH 3/3 io_uring: add ->splice_fd_in checks
In reply to Pavel Begunkov->splice_fd_in is used only by splice/tee, but no other request checks it for validity. Add the check for most of request types excluding reads/writes/sends/recvs, we don't want overhead for them and can leave them be as is until the field is actually used.
--- fs/io_uring.c | 52 +++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 22 deletions(-)
fs/io_uring.c +30 -22
@@ -3502,7 +3502,7 @@ static int io_renameat_prep(struct io_kiocb *req,if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (sqe->ioprio || sqe->buf_index) +if (sqe->ioprio || sqe->buf_index || sqe->splice_fd_in)return -EINVAL ;if (unlikely (req->flags &REQ_F_FIXED_FILE ))return -EBADF ;
@@ -3553,7 +3553,8 @@ static int io_unlinkat_prep(struct io_kiocb *req,if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (sqe->ioprio || sqe->off || sqe->len || sqe->buf_index) +if (sqe->ioprio || sqe->off || sqe->len || sqe->buf_index || + sqe->splice_fd_in)return -EINVAL ;if (unlikely (req->flags &REQ_F_FIXED_FILE ))return -EBADF ;
@@ -3599,8 +3600,8 @@ static int io_shutdown_prep(struct io_kiocb *req,#if defined(CONFIG_NET )if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (sqe->ioprio || sqe->off || sqe->addr || sqe->rw_flags || - sqe->buf_index) +if (unlikely (sqe->ioprio || sqe->off || sqe->addr || sqe->rw_flags || + sqe->buf_index || sqe->splice_fd_in))return -EINVAL ; req->shutdown.how =READ_ONCE (sqe->len);
@@ -3748,7 +3749,8 @@ static int io_fsync_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)if (unlikely (ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (unlikely (sqe->addr || sqe->ioprio || sqe->buf_index)) +if (unlikely (sqe->addr || sqe->ioprio || sqe->buf_index || + sqe->splice_fd_in))return -EINVAL ; req->sync.flags =READ_ONCE (sqe->fsync_flags);
@@ -3781,7 +3783,8 @@ static int io_fsync(struct io_kiocb *req, unsigned int issue_flags)static int io_fallocate_prep (struct io_kiocb *req,const struct io_uring_sqe *sqe) { -if (sqe->ioprio || sqe->buf_index || sqe->rw_flags) +if (sqe->ioprio || sqe->buf_index || sqe->rw_flags || + sqe->splice_fd_in)return -EINVAL ;if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ;
@@ -3814,7 +3817,7 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqeif (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (unlikely (sqe->ioprio || sqe->buf_index)) +if (unlikely (sqe->ioprio || sqe->buf_index || sqe->splice_fd_in))return -EINVAL ;if (unlikely (req->flags &REQ_F_FIXED_FILE ))return -EBADF ;
@@ -3933,7 +3936,8 @@ static int io_remove_buffers_prep(struct io_kiocb *req,struct io_provide_buf *p = &req->pbuf;u64 tmp; -if (sqe->ioprio || sqe->rw_flags || sqe->addr || sqe->len || sqe->off) +if (sqe->ioprio || sqe->rw_flags || sqe->addr || sqe->len || sqe->off || + sqe->splice_fd_in)return -EINVAL ; tmp =READ_ONCE (sqe->fd);
@@ -4004,7 +4008,7 @@ static int io_provide_buffers_prep(struct io_kiocb *req,struct io_provide_buf *p = &req->pbuf;u64 tmp; -if (sqe->ioprio || sqe->rw_flags) +if (sqe->ioprio || sqe->rw_flags || sqe->splice_fd_in)return -EINVAL ; tmp =READ_ONCE (sqe->fd);
@@ -4091,7 +4095,7 @@ static int io_epoll_ctl_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) {#if defined(CONFIG_EPOLL ) -if (sqe->ioprio || sqe->buf_index) +if (sqe->ioprio || sqe->buf_index || sqe->splice_fd_in)return -EINVAL ;if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ;
@@ -4137,7 +4141,7 @@ static int io_epoll_ctl(struct io_kiocb *req, unsigned int issue_flags)static int io_madvise_prep (struct io_kiocb *req,const struct io_uring_sqe *sqe) {#if defined(CONFIG_ADVISE_SYSCALLS ) && defined(CONFIG_MMU ) -if (sqe->ioprio || sqe->buf_index || sqe->off) +if (sqe->ioprio || sqe->buf_index || sqe->off || sqe->splice_fd_in)return -EINVAL ;if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ;
@@ -4172,7 +4176,7 @@ static int io_madvise(struct io_kiocb *req, unsigned int issue_flags)static int io_fadvise_prep (struct io_kiocb *req,const struct io_uring_sqe *sqe) { -if (sqe->ioprio || sqe->buf_index || sqe->addr) +if (sqe->ioprio || sqe->buf_index || sqe->addr || sqe->splice_fd_in)return -EINVAL ;if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ;
@@ -4210,7 +4214,7 @@ static int io_statx_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) {if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (sqe->ioprio || sqe->buf_index) +if (sqe->ioprio || sqe->buf_index || sqe->splice_fd_in)return -EINVAL ;if (req->flags &REQ_F_FIXED_FILE )return -EBADF ;
@@ -4246,7 +4250,7 @@ static int io_close_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ;if (sqe->ioprio || sqe->off || sqe->addr || sqe->len || - sqe->rw_flags || sqe->buf_index) + sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)return -EINVAL ;if (req->flags &REQ_F_FIXED_FILE )return -EBADF ;
@@ -4307,7 +4311,8 @@ static int io_sfr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)if (unlikely (ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (unlikely (sqe->addr || sqe->ioprio || sqe->buf_index)) +if (unlikely (sqe->addr || sqe->ioprio || sqe->buf_index || + sqe->splice_fd_in))return -EINVAL ; req->sync.off =READ_ONCE (sqe->off);
@@ -4734,7 +4739,7 @@ static int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (sqe->ioprio || sqe->len || sqe->buf_index) +if (sqe->ioprio || sqe->len || sqe->buf_index || sqe->splice_fd_in)return -EINVAL ; accept->addr =u64_to_user_ptr (READ_ONCE (sqe->addr));
@@ -4782,7 +4787,8 @@ static int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (sqe->ioprio || sqe->len || sqe->buf_index || sqe->rw_flags) +if (sqe->ioprio || sqe->len || sqe->buf_index || sqe->rw_flags || + sqe->splice_fd_in)return -EINVAL ; conn->addr =u64_to_user_ptr (READ_ONCE (sqe->addr));
@@ -5377,7 +5383,7 @@ static int io_poll_update_prep(struct io_kiocb *req,if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (sqe->ioprio || sqe->buf_index) +if (sqe->ioprio || sqe->buf_index || sqe->splice_fd_in)return -EINVAL ; flags =READ_ONCE (sqe->len); if (flags & ~(IORING_POLL_UPDATE_EVENTS | IORING_POLL_UPDATE_USER_DATA |
@@ -5616,7 +5622,7 @@ static int io_timeout_remove_prep(struct io_kiocb *req,return -EINVAL ;if (unlikely (req->flags & (REQ_F_FIXED_FILE |REQ_F_BUFFER_SELECT )))return -EINVAL ; -if (sqe->ioprio || sqe->buf_index || sqe->len) +if (sqe->ioprio || sqe->buf_index || sqe->len || sqe->splice_fd_in)return -EINVAL ; tr->addr =READ_ONCE (sqe->addr);
@@ -5677,7 +5683,8 @@ static int io_timeout_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe,if (unlikely (req->ctx->flags &IORING_SETUP_IOPOLL ))return -EINVAL ; -if (sqe->ioprio || sqe->buf_index || sqe->len !=1 ) +if (sqe->ioprio || sqe->buf_index || sqe->len !=1 || + sqe->splice_fd_in)return -EINVAL ;if (off && is_timeout_link)return -EINVAL ;
@@ -5833,7 +5840,8 @@ static int io_async_cancel_prep(struct io_kiocb *req,return -EINVAL ;if (unlikely (req->flags & (REQ_F_FIXED_FILE |REQ_F_BUFFER_SELECT )))return -EINVAL ; -if (sqe->ioprio || sqe->off || sqe->len || sqe->cancel_flags) +if (sqe->ioprio || sqe->off || sqe->len || sqe->cancel_flags || + sqe->splice_fd_in)return -EINVAL ; req->cancel.addr =READ_ONCE (sqe->addr);
@@ -5874,7 +5882,7 @@ static int io_rsrc_update_prep(struct io_kiocb *req, {if (unlikely (req->flags & (REQ_F_FIXED_FILE |REQ_F_BUFFER_SELECT )))return -EINVAL ; -if (sqe->ioprio || sqe->rw_flags) +if (sqe->ioprio || sqe->rw_flags || sqe->splice_fd_in)return -EINVAL ; req->rsrc_update.offset =READ_ONCE (sqe->off);
Signature · 1 line
2.32.0
Jens Axboe
maintainerQuoted 8 lines · Pavel Begunkov
1-2 put some limits on the fixed file tables sizes, files and buffers.
3/3 adds compatibility checks for ->splice_fd_in, for all requests buy rw and some others, see the patch message.
All based on 5.15 and merked stable, looks to me as the best way.
Quoted 7 lines
Pavel Begunkov (3):
io_uring: limit fixed table size byRLIMIT_NOFILE
io_uring: place fixed tables under memcg limits
io_uring: add ->splice_fd_in checksfs/io_uring.c | 61 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 25 deletions(-)
Applied - especially 3/3 will be a bit of a stable pain. Nothing difficult, just needs attention for each version...
Signature · 1 line
Jens Axboe
Quoted 14 lines · Jens Axboe
Quoted 13 lines · Pavel Begunkov
1-2 put some limits on the fixed file tables sizes, files and buffers.
3/3 adds compatibility checks for ->splice_fd_in, for all requests buy rw and some others, see the patch message.
All based on 5.15 and merked stable, looks to me as the best way.
Pavel Begunkov (3):
io_uring: limit fixed table size byRLIMIT_NOFILE
io_uring: place fixed tables under memcg limits
io_uring: add ->splice_fd_in checks
Quoted 5 lines
Quoted 2 lines
fs/io_uring.c | 61 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 25 deletions(-)Applied - especially 3/3 will be a bit of a stable pain. Nothing difficult, just needs attention for each version...
Yep. Thanks, Jens
Signature · 1 line
Pavel Begunkov