Commit 5b0bbee4 authored by Jens Axboe's avatar Jens Axboe

io_uring: statx must grab the file table for valid fd

Clay reports that OP_STATX fails for a test case with a valid fd
and empty path:

 -- Test 0: statx:fd 3: SUCCEED, file mode 100755
 -- Test 1: statx:path ./uring_statx: SUCCEED, file mode 100755
 -- Test 2: io_uring_statx:fd 3: FAIL, errno 9: Bad file descriptor
 -- Test 3: io_uring_statx:path ./uring_statx: SUCCEED, file mode 100755

This is due to statx not grabbing the process file table, hence we can't
lookup the fd in async context. If the fd is valid, ensure that we grab
the file table so we can grab the file from async context.

Cc: stable@vger.kernel.org # v5.6
Reported-by: default avatarClay Harris <bugs@claycon.org>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 44575a67
...@@ -524,6 +524,7 @@ enum { ...@@ -524,6 +524,7 @@ enum {
REQ_F_OVERFLOW_BIT, REQ_F_OVERFLOW_BIT,
REQ_F_POLLED_BIT, REQ_F_POLLED_BIT,
REQ_F_BUFFER_SELECTED_BIT, REQ_F_BUFFER_SELECTED_BIT,
REQ_F_NO_FILE_TABLE_BIT,
/* not a real bit, just to check we're not overflowing the space */ /* not a real bit, just to check we're not overflowing the space */
__REQ_F_LAST_BIT, __REQ_F_LAST_BIT,
...@@ -577,6 +578,8 @@ enum { ...@@ -577,6 +578,8 @@ enum {
REQ_F_POLLED = BIT(REQ_F_POLLED_BIT), REQ_F_POLLED = BIT(REQ_F_POLLED_BIT),
/* buffer already selected */ /* buffer already selected */
REQ_F_BUFFER_SELECTED = BIT(REQ_F_BUFFER_SELECTED_BIT), REQ_F_BUFFER_SELECTED = BIT(REQ_F_BUFFER_SELECTED_BIT),
/* doesn't need file table for this request */
REQ_F_NO_FILE_TABLE = BIT(REQ_F_NO_FILE_TABLE_BIT),
}; };
struct async_poll { struct async_poll {
...@@ -799,6 +802,7 @@ static const struct io_op_def io_op_defs[] = { ...@@ -799,6 +802,7 @@ static const struct io_op_def io_op_defs[] = {
.needs_file = 1, .needs_file = 1,
.fd_non_neg = 1, .fd_non_neg = 1,
.needs_fs = 1, .needs_fs = 1,
.file_table = 1,
}, },
[IORING_OP_READ] = { [IORING_OP_READ] = {
.needs_mm = 1, .needs_mm = 1,
...@@ -3355,8 +3359,12 @@ static int io_statx(struct io_kiocb *req, bool force_nonblock) ...@@ -3355,8 +3359,12 @@ static int io_statx(struct io_kiocb *req, bool force_nonblock)
struct kstat stat; struct kstat stat;
int ret; int ret;
if (force_nonblock) if (force_nonblock) {
/* only need file table for an actual valid fd */
if (ctx->dfd == -1 || ctx->dfd == AT_FDCWD)
req->flags |= REQ_F_NO_FILE_TABLE;
return -EAGAIN; return -EAGAIN;
}
if (vfs_stat_set_lookup_flags(&lookup_flags, ctx->how.flags)) if (vfs_stat_set_lookup_flags(&lookup_flags, ctx->how.flags))
return -EINVAL; return -EINVAL;
...@@ -5429,7 +5437,7 @@ static int io_grab_files(struct io_kiocb *req) ...@@ -5429,7 +5437,7 @@ static int io_grab_files(struct io_kiocb *req)
int ret = -EBADF; int ret = -EBADF;
struct io_ring_ctx *ctx = req->ctx; struct io_ring_ctx *ctx = req->ctx;
if (req->work.files) if (req->work.files || (req->flags & REQ_F_NO_FILE_TABLE))
return 0; return 0;
if (!ctx->ring_file) if (!ctx->ring_file)
return -EBADF; return -EBADF;
......
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