Skip to content

Commit fd2206e

Browse files
committed
io_uring: disallow close of ring itself
A previous commit enabled this functionality, which also enabled O_PATH to work correctly with io_uring. But we can't safely close the ring itself, as the file handle isn't reference counted inside io_uring_enter(). Instead of jumping through hoops to enable ring closure, add a "soft" ->needs_file option, ->needs_file_no_error. This enables O_PATH file descriptors to work, but still catches the case of trying to close the ring itself. Reported-by: Jann Horn <[email protected]> Fixes: 904fbcb ("io_uring: remove 'fd is io_uring' from close path") Signed-off-by: Jens Axboe <[email protected]>
1 parent 1ee08de commit fd2206e

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

fs/io_uring.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,8 @@ struct io_op_def {
698698
unsigned needs_mm : 1;
699699
/* needs req->file assigned */
700700
unsigned needs_file : 1;
701+
/* don't fail if file grab fails */
702+
unsigned needs_file_no_error : 1;
701703
/* hash wq insertion if file is a regular file */
702704
unsigned hash_reg_file : 1;
703705
/* unbound wq insertion if file is a non-regular file */
@@ -804,6 +806,8 @@ static const struct io_op_def io_op_defs[] = {
804806
.needs_fs = 1,
805807
},
806808
[IORING_OP_CLOSE] = {
809+
.needs_file = 1,
810+
.needs_file_no_error = 1,
807811
.file_table = 1,
808812
},
809813
[IORING_OP_FILES_UPDATE] = {
@@ -3421,6 +3425,10 @@ static int io_close_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
34213425
return -EBADF;
34223426

34233427
req->close.fd = READ_ONCE(sqe->fd);
3428+
if ((req->file && req->file->f_op == &io_uring_fops) ||
3429+
req->close.fd == req->ctx->ring_fd)
3430+
return -EBADF;
3431+
34243432
return 0;
34253433
}
34263434

@@ -5438,19 +5446,20 @@ static int io_file_get(struct io_submit_state *state, struct io_kiocb *req,
54385446
return -EBADF;
54395447
fd = array_index_nospec(fd, ctx->nr_user_files);
54405448
file = io_file_from_index(ctx, fd);
5441-
if (!file)
5442-
return -EBADF;
5443-
req->fixed_file_refs = ctx->file_data->cur_refs;
5444-
percpu_ref_get(req->fixed_file_refs);
5449+
if (file) {
5450+
req->fixed_file_refs = ctx->file_data->cur_refs;
5451+
percpu_ref_get(req->fixed_file_refs);
5452+
}
54455453
} else {
54465454
trace_io_uring_file_get(ctx, fd);
54475455
file = __io_file_get(state, fd);
5448-
if (unlikely(!file))
5449-
return -EBADF;
54505456
}
54515457

5452-
*out_file = file;
5453-
return 0;
5458+
if (file || io_op_defs[req->opcode].needs_file_no_error) {
5459+
*out_file = file;
5460+
return 0;
5461+
}
5462+
return -EBADF;
54545463
}
54555464

54565465
static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req,

0 commit comments

Comments
 (0)