From: Willy Tarreau <w@1wt.eu>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Bjorn Helgaas <bhelgaas@google.com>,
Ben Hutchings <ben@decadent.org.uk>, Willy Tarreau <w@1wt.eu>
Subject: [PATCH 2.6.32 17/55] PCI/AER: Flush workqueue on device remove to avoid use-after-free
Date: Fri, 04 Mar 2016 16:30:17 +0100 [thread overview]
Message-ID: <20160304153001.451906127@1wt.eu> (raw)
In-Reply-To: <148ee355b419e9976ca727513a1405c8@local>
2.6.32-longterm review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
commit 4ae2182b1e3407de369f8c5d799543b7db74221b upstream.
A Root Port's AER structure (rpc) contains a queue of events. aer_irq()
enqueues AER status information and schedules aer_isr() to dequeue and
process it. When we remove a device, aer_remove() waits for the queue to
be empty, then frees the rpc struct.
But aer_isr() references the rpc struct after dequeueing and possibly
emptying the queue, which can cause a use-after-free error as in the
following scenario with two threads, aer_isr() on the left and a
concurrent aer_remove() on the right:
Thread A Thread B
-------- --------
aer_irq():
rpc->prod_idx++
aer_remove():
wait_event(rpc->prod_idx == rpc->cons_idx)
# now blocked until queue becomes empty
aer_isr(): # ...
rpc->cons_idx++ # unblocked because queue is now empty
... kfree(rpc)
mutex_unlock(&rpc->rpc_mutex)
To prevent this problem, use flush_work() to wait until the last scheduled
instance of aer_isr() has completed before freeing the rpc struct in
aer_remove().
I reproduced this use-after-free by flashing a device FPGA and
re-enumerating the bus to find the new device. With SLUB debug, this
crashes with 0x6b bytes (POISON_FREE, the use-after-free magic number) in
GPR25:
pcieport 0000:00:00.0: AER: Multiple Corrected error received: id=0000
Unable to handle kernel paging request for data at address 0x27ef9e3e
Workqueue: events aer_isr
GPR24: dd6aa000 6b6b6b6b 605f8378 605f8360 d99b12c0 604fc674 606b1704 d99b12c0
NIP [602f5328] pci_walk_bus+0xd4/0x104
[bhelgaas: changelog, stable tag]
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
[wt: in 2.6.32, kfree() is called from aer_delete_rootport()]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
drivers/pci/pcie/aer/aerdrv.c | 3 +--
drivers/pci/pcie/aer/aerdrv.h | 1 -
drivers/pci/pcie/aer/aerdrv_core.c | 2 --
3 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 40c3cc5..8d8bef3 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -153,7 +153,6 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
INIT_WORK(&rpc->dpc_handler, aer_isr);
rpc->prod_idx = rpc->cons_idx = 0;
mutex_init(&rpc->rpc_mutex);
- init_waitqueue_head(&rpc->wait_release);
/* Use PCIE bus function to store rpc into PCIE device */
set_service_data(dev, rpc);
@@ -176,7 +175,7 @@ static void aer_remove(struct pcie_device *dev)
if (rpc->isr)
free_irq(dev->irq, dev);
- wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
+ flush_work(&rpc->dpc_handler);
aer_delete_rootport(rpc);
set_service_data(dev, NULL);
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index bd833ea..ef6163f 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -86,7 +86,6 @@ struct aer_rpc {
* recovery on the same
* root port hierarchy
*/
- wait_queue_head_t wait_release;
};
struct aer_broadcast_data {
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 72fa87c0..093045a 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -844,8 +844,6 @@ void aer_isr(struct work_struct *work)
e_src = get_e_source(rpc);
}
mutex_unlock(&rpc->rpc_mutex);
-
- wake_up(&rpc->wait_release);
}
/**
--
1.7.12.2.21.g234cd45.dirty
next prev parent reply other threads:[~2016-03-04 16:12 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <148ee355b419e9976ca727513a1405c8@local>
2016-03-04 15:30 ` [PATCH 2.6.32 00/55] 2.6.32.71-longterm review Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 01/55] usb: serial: visor: fix crash on detecting device without write_urbs Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 02/55] usbvision fix overflow of interfaces array Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 03/55] USB: visor: fix null-deref at probe Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 04/55] sctp: Prevent soft lockup when sctp_accept() is called during a timeout event Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 05/55] sctp: translate network order to host order when users get a hmacid Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 06/55] tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 07/55] x86/mm: Add barriers and document switch_mm()-vs-flush synchronization Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 08/55] x86/mm: Improve switch_mm() barrier comments Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 10/55] sparc64: fix incorrect sign extension in sys_sparc64_personality Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 11/55] locks: fix unlock when fcntl_setlk races with a close Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 12/55] l2tp: fix another panic in pppol2tp Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 13/55] vfs: make AIO use the proper rw_verify_area() area helpers Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 14/55] readv/writev: do the same MAX_RW_COUNT truncation that read/write does Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 15/55] pipe: Fix buffer offset after partially failed read Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 16/55] af_unix: fix struct pid memory leak Willy Tarreau
2016-03-04 15:30 ` Willy Tarreau [this message]
2016-03-04 15:30 ` [PATCH 2.6.32 18/55] libata: disable forced PORTS_IMPL for >= AHCI 1.3 Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 19/55] rfkill: fix rfkill_fop_read wait_event usage Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 20/55] SCSI: fix crashes in sd and sr runtime PM Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 21/55] tda1004x: only update the frontend properties if locked Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 22/55] saa7134-alsa: Only frees registered sound cards Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 23/55] scsi_dh_rdac: always retry MODE SELECT on command lock violation Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 24/55] ocfs2/dlm: clear refmap bit of recovery lock while doing local recovery cleanup Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 25/55] udf: Promote some debugging messages to udf_error Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 26/55] udf: limit the maximum number of indirect extents in a row Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 27/55] udf: Prevent buffer overrun with multi-byte characters Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 28/55] udf: Check output buffer length when converting name to CS0 Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 29/55] ocfs2/dlm: ignore cleaning the migration mle that is inuse Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 30/55] ALSA: dummy: Disable switching timer backend via sysfs Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 31/55] ALSA: timer: Harden slave timer list handling Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 32/55] ALSA: hrtimer: Fix stall by hrtimer_cancel() Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 33/55] ALSA: pcm: Fix snd_pcm_hw_params struct copy in compat mode Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 34/55] ALSA: seq: Fix snd_seq_call_port_info_ioctl " Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 35/55] ALSA: control: Avoid kernel warnings from tlv ioctl with numid 0 Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 36/55] ALSA: seq: Fix incorrect sanity check at snd_seq_oss_synth_cleanup() Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 37/55] ALSA: seq: Degrade the error message for too many opens Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 38/55] ALSA: seq: Fix race at closing in virmidi driver Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 39/55] ALSA: rawmidi: Remove kernel WARNING for NULL user-space buffer check Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 40/55] ALSA: pcm: Fix potential deadlock in OSS emulation Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 41/55] ALSA: seq: Fix yet another races among ALSA timer accesses Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 42/55] ALSA: timer: Fix link corruption due to double start or stop Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 43/55] ALSA: rawmidi: Make snd_rawmidi_transmit() race-free Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 44/55] ALSA: rawmidi: Fix race at copying & updating the position Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 45/55] ALSA: seq: Fix lockdep warnings due to double mutex locks Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 46/55] ALSA: timer: Fix double unlink of active_list Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 47/55] ALSA: timer: Fix leftover link at closing Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 48/55] ALSA: timer: Fix race among timer ioctls Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 49/55] ALSA: timer: Fix wrong instance passed to slave callbacks Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 50/55] ALSA: timer: Fix race at concurrent reads Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 51/55] ALSA: usb-audio: avoid freeing umidi object twice Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 52/55] ALSA: seq: Fix missing NULL check at remove_events ioctl Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 53/55] ALSA: seq: Fix race at timer setup and close Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 54/55] RDMA/cxgb3: Dont free skbs on NET_XMIT_* indications from LLD Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 55/55] iw_cxgb3: Fix incorrectly returning error on success Willy Tarreau
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=20160304153001.451906127@1wt.eu \
--to=w@1wt.eu \
--cc=ben@decadent.org.uk \
--cc=bhelgaas@google.com \
--cc=bigeasy@linutronix.de \
--cc=linux-kernel@vger.kernel.org \
--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
all inboxes | Powered by JetHome®