Skip to content

Commit 0647b9c

Browse files
committed
Merge tag 'io_uring-5.18-2022-04-14' of git://git.kernel.dk/linux-block
Pull io_uring fixes from Jens Axboe: - Ensure we check and -EINVAL any use of reserved or struct padding. Although we generally always do that, it's missed in two spots for resource updates, one for the ring fd registration from this merge window, and one for the extended arg. Make sure we have all of them handled. (Dylan) - A few fixes for the deferred file assignment (me, Pavel) - Add a feature flag for the deferred file assignment so apps can tell we handle it correctly (me) - Fix a small perf regression with the current file position fix in this merge window (me) * tag 'io_uring-5.18-2022-04-14' of git://git.kernel.dk/linux-block: io_uring: abort file assignment prior to assigning creds io_uring: fix poll error reporting io_uring: fix poll file assign deadlock io_uring: use right issue_flags for splice/tee io_uring: verify pad field is 0 in io_get_ext_arg io_uring: verify resv is 0 in ringfd register/unregister io_uring: verify that resv2 is 0 in io_uring_rsrc_update2 io_uring: move io_uring_rsrc_update2 validation io_uring: fix assign file locking issue io_uring: stop using io_wq_work as an fd placeholder io_uring: move apoll->events cache io_uring: io_kiocb_update_pos() should not touch file for non -1 offset io_uring: flag the fact that linked file assignment is sane
2 parents bb34e0d + 7015214 commit 0647b9c

3 files changed

Lines changed: 59 additions & 41 deletions

File tree

fs/io-wq.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ struct io_wq_work_node *wq_stack_extract(struct io_wq_work_node *stack)
155155
struct io_wq_work {
156156
struct io_wq_work_node list;
157157
unsigned flags;
158-
int fd;
159158
};
160159

161160
static inline struct io_wq_work *wq_next_work(struct io_wq_work *work)

fs/io_uring.c

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,11 @@ struct io_kiocb {
907907

908908
u64 user_data;
909909
u32 result;
910-
u32 cflags;
910+
/* fd initially, then cflags for completion */
911+
union {
912+
u32 cflags;
913+
int fd;
914+
};
911915

912916
struct io_ring_ctx *ctx;
913917
struct task_struct *task;
@@ -916,8 +920,12 @@ struct io_kiocb {
916920
/* store used ubuf, so we can prevent reloading */
917921
struct io_mapped_ubuf *imu;
918922

919-
/* used by request caches, completion batching and iopoll */
920-
struct io_wq_work_node comp_list;
923+
union {
924+
/* used by request caches, completion batching and iopoll */
925+
struct io_wq_work_node comp_list;
926+
/* cache ->apoll->events */
927+
int apoll_events;
928+
};
921929
atomic_t refs;
922930
atomic_t poll_refs;
923931
struct io_task_work io_task_work;
@@ -3183,19 +3191,18 @@ static inline void io_rw_done(struct kiocb *kiocb, ssize_t ret)
31833191
static inline loff_t *io_kiocb_update_pos(struct io_kiocb *req)
31843192
{
31853193
struct kiocb *kiocb = &req->rw.kiocb;
3186-
bool is_stream = req->file->f_mode & FMODE_STREAM;
31873194

3188-
if (kiocb->ki_pos == -1) {
3189-
if (!is_stream) {
3190-
req->flags |= REQ_F_CUR_POS;
3191-
kiocb->ki_pos = req->file->f_pos;
3192-
return &kiocb->ki_pos;
3193-
} else {
3194-
kiocb->ki_pos = 0;
3195-
return NULL;
3196-
}
3195+
if (kiocb->ki_pos != -1)
3196+
return &kiocb->ki_pos;
3197+
3198+
if (!(req->file->f_mode & FMODE_STREAM)) {
3199+
req->flags |= REQ_F_CUR_POS;
3200+
kiocb->ki_pos = req->file->f_pos;
3201+
return &kiocb->ki_pos;
31973202
}
3198-
return is_stream ? NULL : &kiocb->ki_pos;
3203+
3204+
kiocb->ki_pos = 0;
3205+
return NULL;
31993206
}
32003207

32013208
static void kiocb_done(struct io_kiocb *req, ssize_t ret,
@@ -4351,7 +4358,7 @@ static int io_tee(struct io_kiocb *req, unsigned int issue_flags)
43514358
return -EAGAIN;
43524359

43534360
if (sp->flags & SPLICE_F_FD_IN_FIXED)
4354-
in = io_file_get_fixed(req, sp->splice_fd_in, IO_URING_F_UNLOCKED);
4361+
in = io_file_get_fixed(req, sp->splice_fd_in, issue_flags);
43554362
else
43564363
in = io_file_get_normal(req, sp->splice_fd_in);
43574364
if (!in) {
@@ -4393,7 +4400,7 @@ static int io_splice(struct io_kiocb *req, unsigned int issue_flags)
43934400
return -EAGAIN;
43944401

43954402
if (sp->flags & SPLICE_F_FD_IN_FIXED)
4396-
in = io_file_get_fixed(req, sp->splice_fd_in, IO_URING_F_UNLOCKED);
4403+
in = io_file_get_fixed(req, sp->splice_fd_in, issue_flags);
43974404
else
43984405
in = io_file_get_normal(req, sp->splice_fd_in);
43994406
if (!in) {
@@ -5834,7 +5841,6 @@ static void io_poll_remove_entries(struct io_kiocb *req)
58345841
static int io_poll_check_events(struct io_kiocb *req, bool locked)
58355842
{
58365843
struct io_ring_ctx *ctx = req->ctx;
5837-
struct io_poll_iocb *poll = io_poll_get_single(req);
58385844
int v;
58395845

58405846
/* req->task == current here, checking PF_EXITING is safe */
@@ -5851,17 +5857,17 @@ static int io_poll_check_events(struct io_kiocb *req, bool locked)
58515857
return -ECANCELED;
58525858

58535859
if (!req->result) {
5854-
struct poll_table_struct pt = { ._key = req->cflags };
5860+
struct poll_table_struct pt = { ._key = req->apoll_events };
5861+
unsigned flags = locked ? 0 : IO_URING_F_UNLOCKED;
58555862

5856-
if (unlikely(!io_assign_file(req, IO_URING_F_UNLOCKED)))
5857-
req->result = -EBADF;
5858-
else
5859-
req->result = vfs_poll(req->file, &pt) & req->cflags;
5863+
if (unlikely(!io_assign_file(req, flags)))
5864+
return -EBADF;
5865+
req->result = vfs_poll(req->file, &pt) & req->apoll_events;
58605866
}
58615867

58625868
/* multishot, just fill an CQE and proceed */
5863-
if (req->result && !(req->cflags & EPOLLONESHOT)) {
5864-
__poll_t mask = mangle_poll(req->result & poll->events);
5869+
if (req->result && !(req->apoll_events & EPOLLONESHOT)) {
5870+
__poll_t mask = mangle_poll(req->result & req->apoll_events);
58655871
bool filled;
58665872

58675873
spin_lock(&ctx->completion_lock);
@@ -5939,7 +5945,7 @@ static void __io_poll_execute(struct io_kiocb *req, int mask, int events)
59395945
* CPU. We want to avoid pulling in req->apoll->events for that
59405946
* case.
59415947
*/
5942-
req->cflags = events;
5948+
req->apoll_events = events;
59435949
if (req->opcode == IORING_OP_POLL_ADD)
59445950
req->io_task_work.func = io_poll_task_func;
59455951
else
@@ -6331,7 +6337,7 @@ static int io_poll_add_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
63316337
return -EINVAL;
63326338

63336339
io_req_set_refcount(req);
6334-
req->cflags = poll->events = io_poll_parse_events(sqe, flags);
6340+
req->apoll_events = poll->events = io_poll_parse_events(sqe, flags);
63356341
return 0;
63366342
}
63376343

@@ -6833,6 +6839,7 @@ static int io_files_update(struct io_kiocb *req, unsigned int issue_flags)
68336839
up.nr = 0;
68346840
up.tags = 0;
68356841
up.resv = 0;
6842+
up.resv2 = 0;
68366843

68376844
io_ring_submit_lock(ctx, needs_lock);
68386845
ret = __io_register_rsrc_update(ctx, IORING_RSRC_FILE,
@@ -7088,9 +7095,9 @@ static bool io_assign_file(struct io_kiocb *req, unsigned int issue_flags)
70887095
return true;
70897096

70907097
if (req->flags & REQ_F_FIXED_FILE)
7091-
req->file = io_file_get_fixed(req, req->work.fd, issue_flags);
7098+
req->file = io_file_get_fixed(req, req->fd, issue_flags);
70927099
else
7093-
req->file = io_file_get_normal(req, req->work.fd);
7100+
req->file = io_file_get_normal(req, req->fd);
70947101
if (req->file)
70957102
return true;
70967103

@@ -7104,13 +7111,14 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags)
71047111
const struct cred *creds = NULL;
71057112
int ret;
71067113

7114+
if (unlikely(!io_assign_file(req, issue_flags)))
7115+
return -EBADF;
7116+
71077117
if (unlikely((req->flags & REQ_F_CREDS) && req->creds != current_cred()))
71087118
creds = override_creds(req->creds);
71097119

71107120
if (!io_op_defs[req->opcode].audit_skip)
71117121
audit_uring_entry(req->opcode);
7112-
if (unlikely(!io_assign_file(req, issue_flags)))
7113-
return -EBADF;
71147122

71157123
switch (req->opcode) {
71167124
case IORING_OP_NOP:
@@ -7271,16 +7279,18 @@ static void io_wq_submit_work(struct io_wq_work *work)
72717279
if (timeout)
72727280
io_queue_linked_timeout(timeout);
72737281

7274-
if (!io_assign_file(req, issue_flags)) {
7275-
err = -EBADF;
7276-
work->flags |= IO_WQ_WORK_CANCEL;
7277-
}
72787282

72797283
/* either cancelled or io-wq is dying, so don't touch tctx->iowq */
72807284
if (work->flags & IO_WQ_WORK_CANCEL) {
7285+
fail:
72817286
io_req_task_queue_fail(req, err);
72827287
return;
72837288
}
7289+
if (!io_assign_file(req, issue_flags)) {
7290+
err = -EBADF;
7291+
work->flags |= IO_WQ_WORK_CANCEL;
7292+
goto fail;
7293+
}
72847294

72857295
if (req->flags & REQ_F_FORCE_ASYNC) {
72867296
bool opcode_poll = def->pollin || def->pollout;
@@ -7628,7 +7638,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
76287638
if (io_op_defs[opcode].needs_file) {
76297639
struct io_submit_state *state = &ctx->submit_state;
76307640

7631-
req->work.fd = READ_ONCE(sqe->fd);
7641+
req->fd = READ_ONCE(sqe->fd);
76327642

76337643
/*
76347644
* Plug now if we have more than 2 IO left after this, and the
@@ -10524,6 +10534,11 @@ static int io_ringfd_register(struct io_ring_ctx *ctx, void __user *__arg,
1052410534
break;
1052510535
}
1052610536

10537+
if (reg.resv) {
10538+
ret = -EINVAL;
10539+
break;
10540+
}
10541+
1052710542
if (reg.offset == -1U) {
1052810543
start = 0;
1052910544
end = IO_RINGFD_REG_MAX;
@@ -10570,7 +10585,7 @@ static int io_ringfd_unregister(struct io_ring_ctx *ctx, void __user *__arg,
1057010585
ret = -EFAULT;
1057110586
break;
1057210587
}
10573-
if (reg.offset >= IO_RINGFD_REG_MAX) {
10588+
if (reg.resv || reg.offset >= IO_RINGFD_REG_MAX) {
1057410589
ret = -EINVAL;
1057510590
break;
1057610591
}
@@ -10697,6 +10712,8 @@ static int io_get_ext_arg(unsigned flags, const void __user *argp, size_t *argsz
1069710712
return -EINVAL;
1069810713
if (copy_from_user(&arg, argp, sizeof(arg)))
1069910714
return -EFAULT;
10715+
if (arg.pad)
10716+
return -EINVAL;
1070010717
*sig = u64_to_user_ptr(arg.sigmask);
1070110718
*argsz = arg.sigmask_sz;
1070210719
*ts = u64_to_user_ptr(arg.ts);
@@ -11178,7 +11195,8 @@ static __cold int io_uring_create(unsigned entries, struct io_uring_params *p,
1117811195
IORING_FEAT_CUR_PERSONALITY | IORING_FEAT_FAST_POLL |
1117911196
IORING_FEAT_POLL_32BITS | IORING_FEAT_SQPOLL_NONFIXED |
1118011197
IORING_FEAT_EXT_ARG | IORING_FEAT_NATIVE_WORKERS |
11181-
IORING_FEAT_RSRC_TAGS | IORING_FEAT_CQE_SKIP;
11198+
IORING_FEAT_RSRC_TAGS | IORING_FEAT_CQE_SKIP |
11199+
IORING_FEAT_LINKED_FILE;
1118211200

1118311201
if (copy_to_user(params, p, sizeof(*p))) {
1118411202
ret = -EFAULT;
@@ -11389,8 +11407,6 @@ static int __io_register_rsrc_update(struct io_ring_ctx *ctx, unsigned type,
1138911407
__u32 tmp;
1139011408
int err;
1139111409

11392-
if (up->resv)
11393-
return -EINVAL;
1139411410
if (check_add_overflow(up->offset, nr_args, &tmp))
1139511411
return -EOVERFLOW;
1139611412
err = io_rsrc_node_switch_start(ctx);
@@ -11416,6 +11432,8 @@ static int io_register_files_update(struct io_ring_ctx *ctx, void __user *arg,
1141611432
memset(&up, 0, sizeof(up));
1141711433
if (copy_from_user(&up, arg, sizeof(struct io_uring_rsrc_update)))
1141811434
return -EFAULT;
11435+
if (up.resv || up.resv2)
11436+
return -EINVAL;
1141911437
return __io_register_rsrc_update(ctx, IORING_RSRC_FILE, &up, nr_args);
1142011438
}
1142111439

@@ -11428,7 +11446,7 @@ static int io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg,
1142811446
return -EINVAL;
1142911447
if (copy_from_user(&up, arg, sizeof(up)))
1143011448
return -EFAULT;
11431-
if (!up.nr || up.resv)
11449+
if (!up.nr || up.resv || up.resv2)
1143211450
return -EINVAL;
1143311451
return __io_register_rsrc_update(ctx, type, &up, up.nr);
1143411452
}

include/uapi/linux/io_uring.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ struct io_uring_params {
296296
#define IORING_FEAT_NATIVE_WORKERS (1U << 9)
297297
#define IORING_FEAT_RSRC_TAGS (1U << 10)
298298
#define IORING_FEAT_CQE_SKIP (1U << 11)
299+
#define IORING_FEAT_LINKED_FILE (1U << 12)
299300

300301
/*
301302
* io_uring_register(2) opcodes and arguments

0 commit comments

Comments
 (0)