Commit 1d3962ae authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'io_uring-5.7-2020-05-08' of git://git.kernel.dk/linux-block

Pull io_uring fixes from Jens Axboe:

 - Fix finish_wait() balancing in file cancelation (Xiaoguang)

 - Ensure early cleanup of resources in ring map failure (Xiaoguang)

 - Ensure IORING_OP_SLICE does the right file mode checks (Pavel)

 - Remove file opening from openat/openat2/statx, it's not needed and
   messes with O_PATH

* tag 'io_uring-5.7-2020-05-08' of git://git.kernel.dk/linux-block:
  io_uring: don't use 'fd' for openat/openat2/statx
  splice: move f_mode checks to do_{splice,tee}()
  io_uring: handle -EFAULT properly in io_uring_setup()
  io_uring: fix mismatched finish_wait() calls in io_uring_cancel_files()
parents d5eeab8d 63ff8223
Loading
Loading
Loading
Loading
+22 −43
Original line number Diff line number Diff line
@@ -680,8 +680,6 @@ struct io_op_def {
	unsigned		needs_mm : 1;
	/* needs req->file assigned */
	unsigned		needs_file : 1;
	/* needs req->file assigned IFF fd is >= 0 */
	unsigned		fd_non_neg : 1;
	/* hash wq insertion if file is a regular file */
	unsigned		hash_reg_file : 1;
	/* unbound wq insertion if file is a non-regular file */
@@ -784,8 +782,6 @@ static const struct io_op_def io_op_defs[] = {
		.needs_file		= 1,
	},
	[IORING_OP_OPENAT] = {
		.needs_file		= 1,
		.fd_non_neg		= 1,
		.file_table		= 1,
		.needs_fs		= 1,
	},
@@ -799,8 +795,6 @@ static const struct io_op_def io_op_defs[] = {
	},
	[IORING_OP_STATX] = {
		.needs_mm		= 1,
		.needs_file		= 1,
		.fd_non_neg		= 1,
		.needs_fs		= 1,
		.file_table		= 1,
	},
@@ -837,8 +831,6 @@ static const struct io_op_def io_op_defs[] = {
		.buffer_select		= 1,
	},
	[IORING_OP_OPENAT2] = {
		.needs_file		= 1,
		.fd_non_neg		= 1,
		.file_table		= 1,
		.needs_fs		= 1,
	},
@@ -5368,15 +5360,6 @@ static void io_wq_submit_work(struct io_wq_work **workptr)
	io_steal_work(req, workptr);
}

static int io_req_needs_file(struct io_kiocb *req, int fd)
{
	if (!io_op_defs[req->opcode].needs_file)
		return 0;
	if ((fd == -1 || fd == AT_FDCWD) && io_op_defs[req->opcode].fd_non_neg)
		return 0;
	return 1;
}

static inline struct file *io_file_from_index(struct io_ring_ctx *ctx,
					      int index)
{
@@ -5414,14 +5397,11 @@ static int io_file_get(struct io_submit_state *state, struct io_kiocb *req,
}

static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req,
			   int fd, unsigned int flags)
			   int fd)
{
	bool fixed;

	if (!io_req_needs_file(req, fd))
		return 0;

	fixed = (flags & IOSQE_FIXED_FILE);
	fixed = (req->flags & REQ_F_FIXED_FILE) != 0;
	if (unlikely(!fixed && req->needs_fixed_file))
		return -EBADF;

@@ -5798,7 +5778,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
		       struct io_submit_state *state, bool async)
{
	unsigned int sqe_flags;
	int id, fd;
	int id;

	/*
	 * All io need record the previous position, if LINK vs DARIN,
@@ -5850,8 +5830,10 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
					IOSQE_ASYNC | IOSQE_FIXED_FILE |
					IOSQE_BUFFER_SELECT | IOSQE_IO_LINK);

	fd = READ_ONCE(sqe->fd);
	return io_req_set_file(state, req, fd, sqe_flags);
	if (!io_op_defs[req->opcode].needs_file)
		return 0;

	return io_req_set_file(state, req, READ_ONCE(sqe->fd));
}

static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
@@ -7360,11 +7342,9 @@ static int io_uring_release(struct inode *inode, struct file *file)
static void io_uring_cancel_files(struct io_ring_ctx *ctx,
				  struct files_struct *files)
{
	struct io_kiocb *req;
	DEFINE_WAIT(wait);

	while (!list_empty_careful(&ctx->inflight_list)) {
		struct io_kiocb *cancel_req = NULL;
		struct io_kiocb *cancel_req = NULL, *req;
		DEFINE_WAIT(wait);

		spin_lock_irq(&ctx->inflight_lock);
		list_for_each_entry(req, &ctx->inflight_list, inflight_entry) {
@@ -7404,6 +7384,7 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
			 */
			if (refcount_sub_and_test(2, &cancel_req->refs)) {
				io_put_req(cancel_req);
				finish_wait(&ctx->inflight_wait, &wait);
				continue;
			}
		}
@@ -7411,9 +7392,9 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
		io_wq_cancel_work(ctx->io_wq, &cancel_req->work);
		io_put_req(cancel_req);
		schedule();
	}
		finish_wait(&ctx->inflight_wait, &wait);
	}
}

static int io_uring_flush(struct file *file, void *data)
{
@@ -7761,7 +7742,8 @@ err:
	return ret;
}

static int io_uring_create(unsigned entries, struct io_uring_params *p)
static int io_uring_create(unsigned entries, struct io_uring_params *p,
			   struct io_uring_params __user *params)
{
	struct user_struct *user = NULL;
	struct io_ring_ctx *ctx;
@@ -7853,6 +7835,14 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
	p->cq_off.overflow = offsetof(struct io_rings, cq_overflow);
	p->cq_off.cqes = offsetof(struct io_rings, cqes);

	p->features = IORING_FEAT_SINGLE_MMAP | IORING_FEAT_NODROP |
			IORING_FEAT_SUBMIT_STABLE | IORING_FEAT_RW_CUR_POS |
			IORING_FEAT_CUR_PERSONALITY | IORING_FEAT_FAST_POLL;

	if (copy_to_user(params, p, sizeof(*p))) {
		ret = -EFAULT;
		goto err;
	}
	/*
	 * Install ring fd as the very last thing, so we don't risk someone
	 * having closed it before we finish setup
@@ -7861,9 +7851,6 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
	if (ret < 0)
		goto err;

	p->features = IORING_FEAT_SINGLE_MMAP | IORING_FEAT_NODROP |
			IORING_FEAT_SUBMIT_STABLE | IORING_FEAT_RW_CUR_POS |
			IORING_FEAT_CUR_PERSONALITY | IORING_FEAT_FAST_POLL;
	trace_io_uring_create(ret, ctx, p->sq_entries, p->cq_entries, p->flags);
	return ret;
err:
@@ -7879,7 +7866,6 @@ err:
static long io_uring_setup(u32 entries, struct io_uring_params __user *params)
{
	struct io_uring_params p;
	long ret;
	int i;

	if (copy_from_user(&p, params, sizeof(p)))
@@ -7894,14 +7880,7 @@ static long io_uring_setup(u32 entries, struct io_uring_params __user *params)
			IORING_SETUP_CLAMP | IORING_SETUP_ATTACH_WQ))
		return -EINVAL;

	ret = io_uring_create(entries, &p);
	if (ret < 0)
		return ret;

	if (copy_to_user(params, &p, sizeof(p)))
		return -EFAULT;

	return ret;
	return  io_uring_create(entries, &p, params);
}

SYSCALL_DEFINE2(io_uring_setup, u32, entries,
+18 −27
Original line number Diff line number Diff line
@@ -1118,6 +1118,10 @@ long do_splice(struct file *in, loff_t __user *off_in,
	loff_t offset;
	long ret;

	if (unlikely(!(in->f_mode & FMODE_READ) ||
		     !(out->f_mode & FMODE_WRITE)))
		return -EBADF;

	ipipe = get_pipe_info(in);
	opipe = get_pipe_info(out);

@@ -1125,12 +1129,6 @@ long do_splice(struct file *in, loff_t __user *off_in,
		if (off_in || off_out)
			return -ESPIPE;

		if (!(in->f_mode & FMODE_READ))
			return -EBADF;

		if (!(out->f_mode & FMODE_WRITE))
			return -EBADF;

		/* Splicing to self would be fun, but... */
		if (ipipe == opipe)
			return -EINVAL;
@@ -1153,9 +1151,6 @@ long do_splice(struct file *in, loff_t __user *off_in,
			offset = out->f_pos;
		}

		if (unlikely(!(out->f_mode & FMODE_WRITE)))
			return -EBADF;

		if (unlikely(out->f_flags & O_APPEND))
			return -EINVAL;

@@ -1440,16 +1435,12 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in,
	error = -EBADF;
	in = fdget(fd_in);
	if (in.file) {
		if (in.file->f_mode & FMODE_READ) {
		out = fdget(fd_out);
		if (out.file) {
				if (out.file->f_mode & FMODE_WRITE)
					error = do_splice(in.file, off_in,
							  out.file, off_out,
			error = do_splice(in.file, off_in, out.file, off_out,
					  len, flags);
			fdput(out);
		}
		}
		fdput(in);
	}
	return error;
@@ -1770,6 +1761,10 @@ static long do_tee(struct file *in, struct file *out, size_t len,
	struct pipe_inode_info *opipe = get_pipe_info(out);
	int ret = -EINVAL;

	if (unlikely(!(in->f_mode & FMODE_READ) ||
		     !(out->f_mode & FMODE_WRITE)))
		return -EBADF;

	/*
	 * Duplicate the contents of ipipe to opipe without actually
	 * copying the data.
@@ -1795,7 +1790,7 @@ static long do_tee(struct file *in, struct file *out, size_t len,

SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
{
	struct fd in;
	struct fd in, out;
	int error;

	if (unlikely(flags & ~SPLICE_F_ALL))
@@ -1807,15 +1802,11 @@ SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
	error = -EBADF;
	in = fdget(fdin);
	if (in.file) {
		if (in.file->f_mode & FMODE_READ) {
			struct fd out = fdget(fdout);
		out = fdget(fdout);
		if (out.file) {
				if (out.file->f_mode & FMODE_WRITE)
					error = do_tee(in.file, out.file,
							len, flags);
			error = do_tee(in.file, out.file, len, flags);
			fdput(out);
		}
		}
 		fdput(in);
 	}