From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org, Tejun Heo <tj@kernel.org>
Subject: [PATCH 3.10 72/80] libata: fix sff host state machine locking while polling
Date: Tue, 1 Mar 2016 15:46:06 -0800 [thread overview]
Message-ID: <20160301234351.941381680@linuxfoundation.org> (raw)
In-Reply-To: <20160301234349.667990420@linuxfoundation.org>
3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <tj@kernel.org>
commit 8eee1d3ed5b6fc8e14389567c9a6f53f82bb7224 upstream.
The bulk of ATA host state machine is implemented by
ata_sff_hsm_move(). The function is called from either the interrupt
handler or, if polling, a work item. Unlike from the interrupt path,
the polling path calls the function without holding the host lock and
ata_sff_hsm_move() selectively grabs the lock.
This is completely broken. If an IRQ triggers while polling is in
progress, the two can easily race and end up accessing the hardware
and updating state machine state at the same time. This can put the
state machine in an illegal state and lead to a crash like the
following.
kernel BUG at drivers/ata/libata-sff.c:1302!
invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN
Modules linked in:
CPU: 1 PID: 10679 Comm: syz-executor Not tainted 4.5.0-rc1+ #300
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: ffff88002bd00000 ti: ffff88002e048000 task.ti: ffff88002e048000
RIP: 0010:[<ffffffff83a83409>] [<ffffffff83a83409>] ata_sff_hsm_move+0x619/0x1c60
...
Call Trace:
<IRQ>
[<ffffffff83a84c31>] __ata_sff_port_intr+0x1e1/0x3a0 drivers/ata/libata-sff.c:1584
[<ffffffff83a85611>] ata_bmdma_port_intr+0x71/0x400 drivers/ata/libata-sff.c:2877
[< inline >] __ata_sff_interrupt drivers/ata/libata-sff.c:1629
[<ffffffff83a85bf3>] ata_bmdma_interrupt+0x253/0x580 drivers/ata/libata-sff.c:2902
[<ffffffff81479f98>] handle_irq_event_percpu+0x108/0x7e0 kernel/irq/handle.c:157
[<ffffffff8147a717>] handle_irq_event+0xa7/0x140 kernel/irq/handle.c:205
[<ffffffff81484573>] handle_edge_irq+0x1e3/0x8d0 kernel/irq/chip.c:623
[< inline >] generic_handle_irq_desc include/linux/irqdesc.h:146
[<ffffffff811a92bc>] handle_irq+0x10c/0x2a0 arch/x86/kernel/irq_64.c:78
[<ffffffff811a7e4d>] do_IRQ+0x7d/0x1a0 arch/x86/kernel/irq.c:240
[<ffffffff86653d4c>] common_interrupt+0x8c/0x8c arch/x86/entry/entry_64.S:520
<EOI>
[< inline >] rcu_lock_acquire include/linux/rcupdate.h:490
[< inline >] rcu_read_lock include/linux/rcupdate.h:874
[<ffffffff8164b4a1>] filemap_map_pages+0x131/0xba0 mm/filemap.c:2145
[< inline >] do_fault_around mm/memory.c:2943
[< inline >] do_read_fault mm/memory.c:2962
[< inline >] do_fault mm/memory.c:3133
[< inline >] handle_pte_fault mm/memory.c:3308
[< inline >] __handle_mm_fault mm/memory.c:3418
[<ffffffff816efb16>] handle_mm_fault+0x2516/0x49a0 mm/memory.c:3447
[<ffffffff8127dc16>] __do_page_fault+0x376/0x960 arch/x86/mm/fault.c:1238
[<ffffffff8127e358>] trace_do_page_fault+0xe8/0x420 arch/x86/mm/fault.c:1331
[<ffffffff8126f514>] do_async_page_fault+0x14/0xd0 arch/x86/kernel/kvm.c:264
[<ffffffff86655578>] async_page_fault+0x28/0x30 arch/x86/entry/entry_64.S:986
Fix it by ensuring that the polling path is holding the host lock
before entering ata_sff_hsm_move() so that all hardware accesses and
state updates are performed under the host lock.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-and-tested-by: Dmitry Vyukov <dvyukov@google.com>
Link: http://lkml.kernel.org/g/CACT4Y+b_JsOxJu2EZyEf+mOXORc_zid5V1-pLZSroJVxyWdSpw@mail.gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/ata/libata-sff.c | 32 +++++++++++---------------------
1 file changed, 11 insertions(+), 21 deletions(-)
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -997,12 +997,9 @@ static inline int ata_hsm_ok_in_wq(struc
static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
{
struct ata_port *ap = qc->ap;
- unsigned long flags;
if (ap->ops->error_handler) {
if (in_wq) {
- spin_lock_irqsave(ap->lock, flags);
-
/* EH might have kicked in while host lock is
* released.
*/
@@ -1014,8 +1011,6 @@ static void ata_hsm_qc_complete(struct a
} else
ata_port_freeze(ap);
}
-
- spin_unlock_irqrestore(ap->lock, flags);
} else {
if (likely(!(qc->err_mask & AC_ERR_HSM)))
ata_qc_complete(qc);
@@ -1024,10 +1019,8 @@ static void ata_hsm_qc_complete(struct a
}
} else {
if (in_wq) {
- spin_lock_irqsave(ap->lock, flags);
ata_sff_irq_on(ap);
ata_qc_complete(qc);
- spin_unlock_irqrestore(ap->lock, flags);
} else
ata_qc_complete(qc);
}
@@ -1048,9 +1041,10 @@ int ata_sff_hsm_move(struct ata_port *ap
{
struct ata_link *link = qc->dev->link;
struct ata_eh_info *ehi = &link->eh_info;
- unsigned long flags = 0;
int poll_next;
+ lockdep_assert_held(ap->lock);
+
WARN_ON_ONCE((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
/* Make sure ata_sff_qc_issue() does not throw things
@@ -1112,14 +1106,6 @@ fsm_start:
}
}
- /* Send the CDB (atapi) or the first data block (ata pio out).
- * During the state transition, interrupt handler shouldn't
- * be invoked before the data transfer is complete and
- * hsm_task_state is changed. Hence, the following locking.
- */
- if (in_wq)
- spin_lock_irqsave(ap->lock, flags);
-
if (qc->tf.protocol == ATA_PROT_PIO) {
/* PIO data out protocol.
* send first data block.
@@ -1135,9 +1121,6 @@ fsm_start:
/* send CDB */
atapi_send_cdb(ap, qc);
- if (in_wq)
- spin_unlock_irqrestore(ap->lock, flags);
-
/* if polling, ata_sff_pio_task() handles the rest.
* otherwise, interrupt handler takes over from here.
*/
@@ -1361,12 +1344,14 @@ static void ata_sff_pio_task(struct work
u8 status;
int poll_next;
+ spin_lock_irq(ap->lock);
+
BUG_ON(ap->sff_pio_task_link == NULL);
/* qc can be NULL if timeout occurred */
qc = ata_qc_from_tag(ap, link->active_tag);
if (!qc) {
ap->sff_pio_task_link = NULL;
- return;
+ goto out_unlock;
}
fsm_start:
@@ -1381,11 +1366,14 @@ fsm_start:
*/
status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
if (status & ATA_BUSY) {
+ spin_unlock_irq(ap->lock);
ata_msleep(ap, 2);
+ spin_lock_irq(ap->lock);
+
status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
if (status & ATA_BUSY) {
ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
- return;
+ goto out_unlock;
}
}
@@ -1402,6 +1390,8 @@ fsm_start:
*/
if (poll_next)
goto fsm_start;
+out_unlock:
+ spin_unlock_irq(ap->lock);
}
/**
next prev parent reply other threads:[~2016-03-01 23:46 UTC|newest]
Thread overview: 80+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-01 23:44 [PATCH 3.10 00/80] 3.10.99-stable review Greg Kroah-Hartman
2016-03-01 23:44 ` [PATCH 3.10 01/80] tracepoints: Do not trace when cpu is offline Greg Kroah-Hartman
2016-03-01 23:44 ` [PATCH 3.10 02/80] drm/ast: Initialized data needed to map fbdev memory Greg Kroah-Hartman
2016-03-01 23:44 ` [PATCH 3.10 03/80] netfilter: nf_conntrack: fix RCU race in nf_conntrack_find_get Greg Kroah-Hartman
2016-03-01 23:44 ` [PATCH 3.10 04/80] bcache: unregister reboot notifier if bcache fails to unregister device Greg Kroah-Hartman
2016-03-01 23:44 ` [PATCH 3.10 05/80] tools: Add a "make all" rule Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 06/80] drm/radeon: fix hotplug race at startup Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 07/80] efi: Disable interrupts around EFI calls, not in the epilog/prolog calls Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 08/80] dm thin metadata: fix bug when taking a metadata snapshot Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 09/80] dm thin: fix race condition when destroying thin pool workqueue Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 10/80] can: ems_usb: Fix possible tx overflow Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 11/80] USB: cp210x: add IDs for GE B650V3 and B850V3 boards Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 12/80] USB: option: add support for SIM7100E Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 14/80] proc: Fix ptrace-based permission checks for accessing task maps Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 15/80] iw_cxgb3: Fix incorrectly returning error on success Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 16/80] MIPS: KVM: Fix ASID restoration logic Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 17/80] MIPS: KVM: Fix CACHE immediate offset sign extension Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 18/80] MIPS: KVM: Uninit VCPU in vcpu_create error path Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 19/80] splice: sendfile() at once fails for big files Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 21/80] unix: correctly track in-flight fds in sending process user_struct Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 23/80] dts: vt8500: Add SDHC node to DTS file for WM8650 Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 24/80] clocksource/drivers/vt8500: Increase the minimum delta Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 25/80] lockd: create NSM handles per net namespace Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 26/80] devres: fix a for loop bounds check Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 27/80] wm831x_power: Use IRQF_ONESHOT to request threaded IRQs Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 28/80] megaraid_sas: Do not use PAGE_SIZE for max_sectors Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 29/80] megaraid_sas : SMAP restriction--do not access user memory from IOCTL code Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 30/80] mmc: remove bondage between REQ_META and reliable write Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 31/80] mac: validate mac_partition is within sector Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 32/80] ARC: dw2 unwind: Remove falllback linear search thru FDE entries Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 33/80] vfs: Avoid softlockups with sendfile(2) Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 34/80] ring-buffer: Update read stamp with first real commit on page Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 35/80] virtio: fix memory leak of virtio ida cache layers Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 36/80] mac80211: mesh: fix call_rcu() usage Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 37/80] RDS: fix race condition when sending a message on unbound socket Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 38/80] can: sja1000: clear interrupts on start Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 39/80] sched/core: Remove false-positive warning from wake_up_process() Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 40/80] sata_sil: disable trim Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 41/80] dm btree: fix bufio buffer leaks in dm_btree_del() error path Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 42/80] vgaarb: fix signal handling in vga_get() Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 43/80] rfkill: copy the name into the rfkill struct Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 44/80] ses: Fix problems with simple enclosures Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 45/80] ses: fix additional element traversal bug Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 46/80] scripts: recordmcount: break hardlinks Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 47/80] Btrfs: add missing brelse when superblock checksum fails Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 48/80] Btrfs: igrab inode in writepage Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 49/80] Btrfs: send, dont BUG_ON() when an empty symlink is found Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 50/80] Btrfs: fix number of transaction units required to create symlink Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 51/80] s390: fix normalization bug in exception table sorting Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 52/80] s390/dasd: prevent incorrect length error under z/VM after PAV changes Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 53/80] s390/dasd: fix refcount for PAV reassignment Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 54/80] uml: flush stdout before forking Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 55/80] uml: fix hostfs mknod() Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 56/80] [media] media: dvb-core: Dont force CAN_INVERSION_AUTO in oneshot mode Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 57/80] [media] gspca: ov534/topro: prevent a division by 0 Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 58/80] [media] tda1004x: only update the frontend properties if locked Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 59/80] dm snapshot: fix hung bios when copy error occurs Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 60/80] posix-clock: Fix return code on the poll methods error path Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 61/80] mmc: mmci: fix an ages old detection error Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 62/80] sparc64: fix incorrect sign extension in sys_sparc64_personality Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 63/80] drm/vmwgfx: respect nomodeset Greg Kroah-Hartman
2016-03-01 23:45 ` [PATCH 3.10 64/80] drm/radeon: clean up fujitsu quirks Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 67/80] IB/qib: fix mcast detach when qp not attached Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 68/80] libceph: dont bail early from try_read() when skipping a message Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 69/80] cdc-acm:exclude Samsung phone 04e8:685d Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 70/80] rfkill: fix rfkill_fop_read wait_event usage Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 71/80] Revert "workqueue: make sure delayed work run in local cpu" Greg Kroah-Hartman
2016-03-01 23:46 ` Greg Kroah-Hartman [this message]
2016-03-01 23:46 ` [PATCH 3.10 73/80] PCI/AER: Flush workqueue on device remove to avoid use-after-free Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 74/80] nfs: fix nfs_size_to_loff_t Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 75/80] KVM: async_pf: do not warn on page allocation failures Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 76/80] tracing: Fix showing function event in available_events Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 77/80] sunrpc/cache: fix off-by-one in qword_get() Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 78/80] kernel/resource.c: fix muxed resource handling in __request_region() Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 79/80] do_last(): dont let a bogus return value from ->open() et.al. to confuse us Greg Kroah-Hartman
2016-03-01 23:46 ` [PATCH 3.10 80/80] xen/pcifront: Fix mysterious crashes when NUMA locality information was extracted Greg Kroah-Hartman
2016-03-02 1:37 ` [PATCH 3.10 00/80] 3.10.99-stable review Shuah Khan
2016-03-02 14:32 ` Guenter Roeck
2016-03-02 15:48 ` Willy Tarreau
2016-03-02 17:29 ` Greg Kroah-Hartman
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=20160301234351.941381680@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=tj@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;
as well as URLs for NNTP newsgroup(s).