Unverified Commit 95685dd6 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!13458 io_uring: fix CVE-2024-53052

Merge Pull Request from: @ci-robot 
 
PR sync from: Baokun Li <libaokun1@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/C6XFDRDESLFKQ6AJWACFBBYIE3KVOOUZ/ 
Amir Goldstein (3):
  io_uring: rename kiocb_end_write() local helper
  fs: create kiocb_{start,end}_write() helpers
  io_uring: use kiocb_{start,end}_write() helpers

Jens Axboe (1):
  io_uring/rw: fix missing NOWAIT check for O_DIRECT start write


-- 
2.46.1
 
https://gitee.com/src-openeuler/kernel/issues/IB5KQC 
 
Link:https://gitee.com/openeuler/kernel/pulls/13458

 

Reviewed-by: default avatarLi Nan <linan122@huawei.com>
Signed-off-by: default avatarLi Nan <linan122@huawei.com>
parents 7a4bd8ff 1aecd259
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -1815,6 +1815,41 @@ static inline bool sb_start_intwrite_trylock(struct super_block *sb)
	return __sb_start_write_trylock(sb, SB_FREEZE_FS);
}

/**
 * kiocb_start_write - get write access to a superblock for async file io
 * @iocb: the io context we want to submit the write with
 *
 * This is a variant of sb_start_write() for async io submission.
 * Should be matched with a call to kiocb_end_write().
 */
static inline void kiocb_start_write(struct kiocb *iocb)
{
	struct inode *inode = file_inode(iocb->ki_filp);

	sb_start_write(inode->i_sb);
	/*
	 * Fool lockdep by telling it the lock got released so that it
	 * doesn't complain about the held lock when we return to userspace.
	 */
	__sb_writers_release(inode->i_sb, SB_FREEZE_WRITE);
}

/**
 * kiocb_end_write - drop write access to a superblock after async file io
 * @iocb: the io context we sumbitted the write with
 *
 * Should be matched with a call to kiocb_start_write().
 */
static inline void kiocb_end_write(struct kiocb *iocb)
{
	struct inode *inode = file_inode(iocb->ki_filp);

	/*
	 * Tell lockdep we inherited freeze protection from submission thread.
	 */
	__sb_writers_acquired(inode->i_sb, SB_FREEZE_WRITE);
	sb_end_write(inode->i_sb);
}

extern bool inode_owner_or_capable(const struct inode *inode);

+27 −23
Original line number Diff line number Diff line
@@ -2677,17 +2677,12 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, long min)
	return ret;
}

static void kiocb_end_write(struct io_kiocb *req)
static void io_req_end_write(struct io_kiocb *req)
{
	/*
	 * Tell lockdep we inherited freeze protection from submission
	 * thread.
	 */
	if (req->flags & REQ_F_ISREG) {
		struct super_block *sb = file_inode(req->file)->i_sb;
		struct io_rw *rw = &req->rw;

		__sb_writers_acquired(sb, SB_FREEZE_WRITE);
		sb_end_write(sb);
		kiocb_end_write(&rw->kiocb);
	}
}

@@ -2747,7 +2742,7 @@ static void io_req_io_end(struct io_kiocb *req)
	struct io_rw *rw = &req->rw;

	if (rw->kiocb.ki_flags & IOCB_WRITE) {
		kiocb_end_write(req);
		io_req_end_write(req);
		fsnotify_modify(req->file);
	} else {
		fsnotify_access(req->file);
@@ -2827,7 +2822,7 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res, long res2)
	struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb);

	if (kiocb->ki_flags & IOCB_WRITE)
		kiocb_end_write(req);
		io_req_end_write(req);
	if (unlikely(res != req->result)) {
		if (res == -EAGAIN && io_rw_should_reissue(req)) {
			req->flags |= REQ_F_REISSUE;
@@ -3734,6 +3729,25 @@ static int io_write_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
	return io_prep_rw(req, sqe, WRITE);
}

static bool io_kiocb_start_write(struct io_kiocb *req, struct kiocb *kiocb)
{
	struct inode *inode;
	bool ret;

	if (!(req->flags & REQ_F_ISREG))
		return true;
	if (!(kiocb->ki_flags & IOCB_NOWAIT)) {
		kiocb_start_write(kiocb);
		return true;
	}

	inode = file_inode(kiocb->ki_filp);
	ret = sb_start_write_trylock(inode->i_sb);
	if (ret)
		__sb_writers_release(inode->i_sb, SB_FREEZE_WRITE);
	return ret;
}

static int io_write(struct io_kiocb *req, unsigned int issue_flags)
{
	struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
@@ -3780,18 +3794,8 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags)
	if (unlikely(ret))
		goto out_free;

	/*
	 * Open-code file_start_write here to grab freeze protection,
	 * which will be released by another thread in
	 * io_complete_rw().  Fool lockdep by telling it the lock got
	 * released so that it doesn't complain about the held lock when
	 * we return to userspace.
	 */
	if (req->flags & REQ_F_ISREG) {
		sb_start_write(file_inode(req->file)->i_sb);
		__sb_writers_release(file_inode(req->file)->i_sb,
					SB_FREEZE_WRITE);
	}
	if (unlikely(!io_kiocb_start_write(req, kiocb)))
		goto copy_iov;
	kiocb->ki_flags |= IOCB_WRITE;

	if (req->file->f_op->write_iter)
@@ -3827,7 +3831,7 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags)
		ret = io_setup_async_rw(req, iovec, inline_vecs, iter, false);
		if (!ret) {
			if (kiocb->ki_flags & IOCB_WRITE)
				kiocb_end_write(req);
				io_req_end_write(req);
			return -EAGAIN;
		}
		return ret;