From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Sahitya Tummala <stummala@codeaurora.org>,
Pradeep P V K <ppvk@codeaurora.org>, Jens Axboe <axboe@kernel.dk>,
Sasha Levin <sashal@kernel.org>,
linux-block@vger.kernel.org
Subject: [PATCH AUTOSEL 4.14 15/22] block: Fix use-after-free issue accessing struct io_cq
Date: Thu, 9 Apr 2020 23:50:37 -0400 [thread overview]
Message-ID: <20200410035044.9698-15-sashal@kernel.org> (raw)
In-Reply-To: <20200410035044.9698-1-sashal@kernel.org>
From: Sahitya Tummala <stummala@codeaurora.org>
[ Upstream commit 30a2da7b7e225ef6c87a660419ea04d3cef3f6a7 ]
There is a potential race between ioc_release_fn() and
ioc_clear_queue() as shown below, due to which below kernel
crash is observed. It also can result into use-after-free
issue.
context#1: context#2:
ioc_release_fn() __ioc_clear_queue() gets the same icq
->spin_lock(&ioc->lock); ->spin_lock(&ioc->lock);
->ioc_destroy_icq(icq);
->list_del_init(&icq->q_node);
->call_rcu(&icq->__rcu_head,
icq_free_icq_rcu);
->spin_unlock(&ioc->lock);
->ioc_destroy_icq(icq);
->hlist_del_init(&icq->ioc_node);
This results into below crash as this memory
is now used by icq->__rcu_head in context#1.
There is a chance that icq could be free'd
as well.
22150.386550: <6> Unable to handle kernel write to read-only memory
at virtual address ffffffaa8d31ca50
...
Call trace:
22150.607350: <2> ioc_destroy_icq+0x44/0x110
22150.611202: <2> ioc_clear_queue+0xac/0x148
22150.615056: <2> blk_cleanup_queue+0x11c/0x1a0
22150.619174: <2> __scsi_remove_device+0xdc/0x128
22150.623465: <2> scsi_forget_host+0x2c/0x78
22150.627315: <2> scsi_remove_host+0x7c/0x2a0
22150.631257: <2> usb_stor_disconnect+0x74/0xc8
22150.635371: <2> usb_unbind_interface+0xc8/0x278
22150.639665: <2> device_release_driver_internal+0x198/0x250
22150.644897: <2> device_release_driver+0x24/0x30
22150.649176: <2> bus_remove_device+0xec/0x140
22150.653204: <2> device_del+0x270/0x460
22150.656712: <2> usb_disable_device+0x120/0x390
22150.660918: <2> usb_disconnect+0xf4/0x2e0
22150.664684: <2> hub_event+0xd70/0x17e8
22150.668197: <2> process_one_work+0x210/0x480
22150.672222: <2> worker_thread+0x32c/0x4c8
Fix this by adding a new ICQ_DESTROYED flag in ioc_destroy_icq() to
indicate this icq is once marked as destroyed. Also, ensure
__ioc_clear_queue() is accessing icq within rcu_read_lock/unlock so
that icq doesn't get free'd up while it is still using it.
Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
Co-developed-by: Pradeep P V K <ppvk@codeaurora.org>
Signed-off-by: Pradeep P V K <ppvk@codeaurora.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
block/blk-ioc.c | 7 +++++++
include/linux/iocontext.h | 1 +
2 files changed, 8 insertions(+)
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index f23311e4b201f..e56a480b6f929 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -87,6 +87,7 @@ static void ioc_destroy_icq(struct io_cq *icq)
* making it impossible to determine icq_cache. Record it in @icq.
*/
icq->__rcu_icq_cache = et->icq_cache;
+ icq->flags |= ICQ_DESTROYED;
call_rcu(&icq->__rcu_head, icq_free_icq_rcu);
}
@@ -230,15 +231,21 @@ static void __ioc_clear_queue(struct list_head *icq_list)
{
unsigned long flags;
+ rcu_read_lock();
while (!list_empty(icq_list)) {
struct io_cq *icq = list_entry(icq_list->next,
struct io_cq, q_node);
struct io_context *ioc = icq->ioc;
spin_lock_irqsave(&ioc->lock, flags);
+ if (icq->flags & ICQ_DESTROYED) {
+ spin_unlock_irqrestore(&ioc->lock, flags);
+ continue;
+ }
ioc_destroy_icq(icq);
spin_unlock_irqrestore(&ioc->lock, flags);
}
+ rcu_read_unlock();
}
/**
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index dba15ca8e60bc..1dcd9198beb7f 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -8,6 +8,7 @@
enum {
ICQ_EXITED = 1 << 2,
+ ICQ_DESTROYED = 1 << 3,
};
/*
--
2.20.1
next prev parent reply other threads:[~2020-04-10 3:52 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-10 3:50 [PATCH AUTOSEL 4.14 01/22] null_blk: Fix the null_add_dev() error path Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 02/22] null_blk: Handle null_add_dev() failures properly Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 03/22] null_blk: fix spurious IO errors after failed past-wp access Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 04/22] x86: Don't let pgprot_modify() change the page encryption bit Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 05/22] block: keep bdi->io_pages in sync with max_sectors_kb for stacked devices Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 06/22] irqchip/versatile-fpga: Handle chained IRQs properly Sasha Levin
2020-04-10 3:50 ` Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 07/22] sched: Avoid scale real weight down to zero Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 08/22] selftests/x86/ptrace_syscall_32: Fix no-vDSO segfault Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 09/22] PCI/switchtec: Fix init_completion race condition with poll_wait() Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 10/22] libata: Remove extra scsi_host_put() in ata_scsi_add_hosts() Sasha Levin
2020-04-10 3:50 ` [Cluster-devel] [PATCH AUTOSEL 4.14 11/22] gfs2: Don't demote a glock until its revokes are written Sasha Levin
2020-04-10 3:50 ` Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 12/22] x86/boot: Use unsigned comparison for addresses Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 13/22] efi/x86: Ignore the memory attributes table on i386 Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 14/22] genirq/irqdomain: Check pointer in irq_domain_alloc_irqs_hierarchy() Sasha Levin
2020-04-10 3:50 ` Sasha Levin [this message]
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 16/22] usb: dwc3: core: add support for disabling SS instances in park mode Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 17/22] irqchip/gic-v4: Provide irq_retrigger to avoid circular locking dependency Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 18/22] locking/lockdep: Avoid recursion in lockdep_count_{for,back}ward_deps() Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 19/22] block, bfq: fix use-after-free in bfq_idle_slice_timer_body Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 20/22] btrfs: hold a ref on the root in btrfs_recover_relocation Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 21/22] btrfs: remove a BUG_ON() from merge_reloc_roots() Sasha Levin
2020-04-10 3:50 ` [PATCH AUTOSEL 4.14 22/22] btrfs: track reloc roots based on their commit root bytenr Sasha Levin
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=20200410035044.9698-15-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=axboe@kernel.dk \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ppvk@codeaurora.org \
--cc=stable@vger.kernel.org \
--cc=stummala@codeaurora.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.