public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Liu Yong <pkfxxxing@gmail.com>,
	Jens Axboe <axboe@kernel.dk>
Subject: [PATCH 5.4 06/67] io_uring: prevent re-read of sqe->opcode
Date: Mon, 10 Aug 2020 17:20:53 +0200	[thread overview]
Message-ID: <20200810151809.747275663@linuxfoundation.org> (raw)
In-Reply-To: <20200810151809.438685785@linuxfoundation.org>

From: Jens Axboe <axboe@kernel.dk>

Liu reports that he can trigger a NULL pointer dereference with
IORING_OP_SENDMSG, by changing the sqe->opcode after we've validated
that the previous opcode didn't need a file and didn't assign one.

Ensure we validate and read the opcode only once.

Reported-by: Liu Yong <pkfxxxing@gmail.com>
Tested-by: Liu Yong <pkfxxxing@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/io_uring.c |   59 +++++++++++++++++++++++-----------------------------------
 1 file changed, 24 insertions(+), 35 deletions(-)

--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -279,6 +279,7 @@ struct sqe_submit {
 	bool				has_user;
 	bool				needs_lock;
 	bool				needs_fixed_file;
+	u8				opcode;
 };
 
 /*
@@ -505,7 +506,7 @@ static inline void io_queue_async_work(s
 	int rw = 0;
 
 	if (req->submit.sqe) {
-		switch (req->submit.sqe->opcode) {
+		switch (req->submit.opcode) {
 		case IORING_OP_WRITEV:
 		case IORING_OP_WRITE_FIXED:
 			rw = !(req->rw.ki_flags & IOCB_DIRECT);
@@ -1254,23 +1255,15 @@ static int io_import_fixed(struct io_rin
 }
 
 static ssize_t io_import_iovec(struct io_ring_ctx *ctx, int rw,
-			       const struct sqe_submit *s, struct iovec **iovec,
+			       struct io_kiocb *req, struct iovec **iovec,
 			       struct iov_iter *iter)
 {
-	const struct io_uring_sqe *sqe = s->sqe;
+	const struct io_uring_sqe *sqe = req->submit.sqe;
 	void __user *buf = u64_to_user_ptr(READ_ONCE(sqe->addr));
 	size_t sqe_len = READ_ONCE(sqe->len);
 	u8 opcode;
 
-	/*
-	 * We're reading ->opcode for the second time, but the first read
-	 * doesn't care whether it's _FIXED or not, so it doesn't matter
-	 * whether ->opcode changes concurrently. The first read does care
-	 * about whether it is a READ or a WRITE, so we don't trust this read
-	 * for that purpose and instead let the caller pass in the read/write
-	 * flag.
-	 */
-	opcode = READ_ONCE(sqe->opcode);
+	opcode = req->submit.opcode;
 	if (opcode == IORING_OP_READ_FIXED ||
 	    opcode == IORING_OP_WRITE_FIXED) {
 		ssize_t ret = io_import_fixed(ctx, rw, sqe, iter);
@@ -1278,7 +1271,7 @@ static ssize_t io_import_iovec(struct io
 		return ret;
 	}
 
-	if (!s->has_user)
+	if (!req->submit.has_user)
 		return -EFAULT;
 
 #ifdef CONFIG_COMPAT
@@ -1425,7 +1418,7 @@ static int io_read(struct io_kiocb *req,
 	if (unlikely(!(file->f_mode & FMODE_READ)))
 		return -EBADF;
 
-	ret = io_import_iovec(req->ctx, READ, s, &iovec, &iter);
+	ret = io_import_iovec(req->ctx, READ, req, &iovec, &iter);
 	if (ret < 0)
 		return ret;
 
@@ -1490,7 +1483,7 @@ static int io_write(struct io_kiocb *req
 	if (unlikely(!(file->f_mode & FMODE_WRITE)))
 		return -EBADF;
 
-	ret = io_import_iovec(req->ctx, WRITE, s, &iovec, &iter);
+	ret = io_import_iovec(req->ctx, WRITE, req, &iovec, &iter);
 	if (ret < 0)
 		return ret;
 
@@ -2109,15 +2102,14 @@ static int io_req_defer(struct io_ring_c
 static int __io_submit_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
 			   const struct sqe_submit *s, bool force_nonblock)
 {
-	int ret, opcode;
+	int ret;
 
 	req->user_data = READ_ONCE(s->sqe->user_data);
 
 	if (unlikely(s->index >= ctx->sq_entries))
 		return -EINVAL;
 
-	opcode = READ_ONCE(s->sqe->opcode);
-	switch (opcode) {
+	switch (req->submit.opcode) {
 	case IORING_OP_NOP:
 		ret = io_nop(req, req->user_data);
 		break;
@@ -2181,10 +2173,10 @@ static int __io_submit_sqe(struct io_rin
 	return 0;
 }
 
-static struct async_list *io_async_list_from_sqe(struct io_ring_ctx *ctx,
-						 const struct io_uring_sqe *sqe)
+static struct async_list *io_async_list_from_req(struct io_ring_ctx *ctx,
+						 struct io_kiocb *req)
 {
-	switch (sqe->opcode) {
+	switch (req->submit.opcode) {
 	case IORING_OP_READV:
 	case IORING_OP_READ_FIXED:
 		return &ctx->pending_async[READ];
@@ -2196,12 +2188,10 @@ static struct async_list *io_async_list_
 	}
 }
 
-static inline bool io_sqe_needs_user(const struct io_uring_sqe *sqe)
+static inline bool io_req_needs_user(struct io_kiocb *req)
 {
-	u8 opcode = READ_ONCE(sqe->opcode);
-
-	return !(opcode == IORING_OP_READ_FIXED ||
-		 opcode == IORING_OP_WRITE_FIXED);
+	return !(req->submit.opcode == IORING_OP_READ_FIXED ||
+		req->submit.opcode == IORING_OP_WRITE_FIXED);
 }
 
 static void io_sq_wq_submit_work(struct work_struct *work)
@@ -2217,7 +2207,7 @@ static void io_sq_wq_submit_work(struct
 	int ret;
 
 	old_cred = override_creds(ctx->creds);
-	async_list = io_async_list_from_sqe(ctx, req->submit.sqe);
+	async_list = io_async_list_from_req(ctx, req);
 
 	allow_kernel_signal(SIGINT);
 restart:
@@ -2239,7 +2229,7 @@ restart:
 		}
 
 		ret = 0;
-		if (io_sqe_needs_user(sqe) && !cur_mm) {
+		if (io_req_needs_user(req) && !cur_mm) {
 			if (!mmget_not_zero(ctx->sqo_mm)) {
 				ret = -EFAULT;
 			} else {
@@ -2387,11 +2377,9 @@ static bool io_add_to_prev_work(struct a
 	return ret;
 }
 
-static bool io_op_needs_file(const struct io_uring_sqe *sqe)
+static bool io_op_needs_file(struct io_kiocb *req)
 {
-	int op = READ_ONCE(sqe->opcode);
-
-	switch (op) {
+	switch (req->submit.opcode) {
 	case IORING_OP_NOP:
 	case IORING_OP_POLL_REMOVE:
 	case IORING_OP_TIMEOUT:
@@ -2419,7 +2407,7 @@ static int io_req_set_file(struct io_rin
 	 */
 	req->sequence = s->sequence;
 
-	if (!io_op_needs_file(s->sqe))
+	if (!io_op_needs_file(req))
 		return 0;
 
 	if (flags & IOSQE_FIXED_FILE) {
@@ -2460,7 +2448,7 @@ static int __io_queue_sqe(struct io_ring
 
 			s->sqe = sqe_copy;
 			memcpy(&req->submit, s, sizeof(*s));
-			list = io_async_list_from_sqe(ctx, s->sqe);
+			list = io_async_list_from_req(ctx, req);
 			if (!io_add_to_prev_work(list, req)) {
 				if (list)
 					atomic_inc(&list->cnt);
@@ -2582,7 +2570,7 @@ err:
 	req->user_data = s->sqe->user_data;
 
 #if defined(CONFIG_NET)
-	switch (READ_ONCE(s->sqe->opcode)) {
+	switch (req->submit.opcode) {
 	case IORING_OP_SENDMSG:
 	case IORING_OP_RECVMSG:
 		spin_lock(&current->fs->lock);
@@ -2697,6 +2685,7 @@ static bool io_get_sqring(struct io_ring
 	if (head < ctx->sq_entries) {
 		s->index = head;
 		s->sqe = &ctx->sq_sqes[head];
+		s->opcode = READ_ONCE(s->sqe->opcode);
 		s->sequence = ctx->cached_sq_head;
 		ctx->cached_sq_head++;
 		return true;



  parent reply	other threads:[~2020-08-10 15:26 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-10 15:20 [PATCH 5.4 00/67] 5.4.58-rc1 review Greg Kroah-Hartman
2020-08-10 15:20 ` [PATCH 5.4 01/67] USB: serial: qcserial: add EM7305 QDL product ID Greg Kroah-Hartman
2020-08-10 15:20 ` [PATCH 5.4 02/67] perf/core: Fix endless multiplex timer Greg Kroah-Hartman
2020-08-10 15:20 ` [PATCH 5.4 03/67] USB: iowarrior: fix up report size handling for some devices Greg Kroah-Hartman
2020-08-10 15:20 ` [PATCH 5.4 04/67] usb: xhci: define IDs for various ASMedia host controllers Greg Kroah-Hartman
2020-08-10 15:20 ` [PATCH 5.4 05/67] usb: xhci: Fix ASMedia ASM1142 DMA addressing Greg Kroah-Hartman
2020-08-10 15:20 ` Greg Kroah-Hartman [this message]
2020-08-10 15:20 ` [PATCH 5.4 07/67] io_uring: Fix use-after-free in io_sq_wq_submit_work() Greg Kroah-Hartman
2020-08-10 15:20 ` [PATCH 5.4 08/67] Revert "ALSA: hda: call runtime_allow() for all hda controllers" Greg Kroah-Hartman
2020-08-10 15:20 ` [PATCH 5.4 09/67] ALSA: hda/realtek: Add alc269/alc662 pin-tables for Loongson-3 laptops Greg Kroah-Hartman
2020-08-10 15:20 ` [PATCH 5.4 10/67] ALSA: hda/ca0132 - Add new quirk ID for Recon3D Greg Kroah-Hartman
2020-08-10 15:20 ` [PATCH 5.4 11/67] ALSA: hda/ca0132 - Fix ZxR Headphone gain control get value Greg Kroah-Hartman
2020-08-10 15:20 ` [PATCH 5.4 12/67] ALSA: hda/ca0132 - Fix AE-5 microphone selection commands Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 13/67] ALSA: seq: oss: Serialize ioctls Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 14/67] staging: android: ashmem: Fix lockdep warning for write operation Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 15/67] staging: rtl8712: handle firmware load failure Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 16/67] Staging: rtl8188eu: rtw_mlme: Fix uninitialized variable authmode Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 17/67] Bluetooth: Fix slab-out-of-bounds read in hci_extended_inquiry_result_evt() Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 18/67] Bluetooth: Prevent out-of-bounds read in hci_inquiry_result_evt() Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 19/67] Bluetooth: Prevent out-of-bounds read in hci_inquiry_result_with_rssi_evt() Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 20/67] omapfb: dss: Fix max fclk divider for omap36xx Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 21/67] binder: Prevent context manager from incrementing ref 0 Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 22/67] Smack: fix use-after-free in smk_write_relabel_self() Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 23/67] scripts: add dummy report mode to add_namespace.cocci Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 24/67] vgacon: Fix for missing check in scrollback handling Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 25/67] mtd: properly check all write ioctls for permissions Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 26/67] leds: wm831x-status: fix use-after-free on unbind Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 27/67] leds: lm36274: " Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 28/67] leds: da903x: " Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 29/67] leds: lm3533: " Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 30/67] leds: 88pm860x: " Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 31/67] net/9p: validate fds in p9_fd_open Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 32/67] drm/nouveau/fbcon: fix module unload when fbcon init has failed for some reason Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 33/67] drm/nouveau/fbcon: zero-initialise the mode_cmd2 structure Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 34/67] nvme-pci: prevent SK hynix PC400 from using Write Zeroes command Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 35/67] drm/drm_fb_helper: fix fbdev with sparc64 Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 36/67] i2c: slave: improve sanity check when registering Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 37/67] i2c: slave: add sanity check when unregistering Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 38/67] usb: hso: check for return value in hso_serial_common_create() Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 39/67] net: ethernet: mtk_eth_soc: Always call mtk_gmac0_rgmii_adjust() for mt7623 Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 40/67] ALSA: hda: fix NULL pointer dereference during suspend Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 41/67] firmware: Fix a reference count leak Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 42/67] cfg80211: check vendor command doit pointer before use Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 43/67] igb: reinit_locked() should be called with rtnl_lock Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 44/67] atm: fix atm_dev refcnt leaks in atmtcp_remove_persistent Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 45/67] tools lib traceevent: Fix memory leak in process_dynamic_array_len Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 46/67] Drivers: hv: vmbus: Ignore CHANNELMSG_TL_CONNECT_RESULT(23) Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 47/67] xattr: break delegations in {set,remove}xattr Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 48/67] Revert "powerpc/kasan: Fix shadow pages allocation failure" Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 49/67] PCI: tegra: Revert tegra124 raw_violation_fixup Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 50/67] ipv4: Silence suspicious RCU usage warning Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 51/67] ipv6: fix memory leaks on IPV6_ADDRFORM path Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 52/67] ipv6: Fix nexthop refcnt leak when creating ipv6 route info Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 53/67] net: ethernet: mtk_eth_soc: fix MTU warnings Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 54/67] rxrpc: Fix race between recvmsg and sendmsg on immediate call failure Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 55/67] vxlan: Ensure FDB dump is performed under RCU Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 56/67] net: lan78xx: replace bogus endpoint lookup Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 57/67] appletalk: Fix atalk_proc_init() return path Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 58/67] dpaa2-eth: Fix passing zero to PTR_ERR warning Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 59/67] hv_netvsc: do not use VF device if link is down Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 60/67] net: gre: recompute gre csum for sctp over gre tunnels Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 61/67] net: thunderx: use spin_lock_bh in nicvf_set_rx_mode_task() Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 62/67] openvswitch: Prevent kernel-infoleak in ovs_ct_put_key() Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 63/67] Revert "vxlan: fix tos value before xmit" Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 64/67] selftests/net: relax cpu affinity requirement in msg_zerocopy test Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 65/67] tcp: apply a floor of 1 for RTT samples from TCP timestamps Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 66/67] ima: move APPRAISE_BOOTPARAM dependency on ARCH_POLICY to runtime Greg Kroah-Hartman
2020-08-10 15:21 ` [PATCH 5.4 67/67] nfsd: Fix NFSv4 READ on RDMA when using readv Greg Kroah-Hartman
2020-08-10 23:10 ` [PATCH 5.4 00/67] 5.4.58-rc1 review Shuah Khan
2020-08-11  7:29 ` Naresh Kamboju
2020-08-11 14:23 ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200810151809.747275663@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=axboe@kernel.dk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pkfxxxing@gmail.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox