summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorsmh <smh@FreeBSD.org>2014-12-21 16:43:56 +0000
committersmh <smh@FreeBSD.org>2014-12-21 16:43:56 +0000
commit5f92f0907a2e4697198dd62d1d9ecc01f3c548a0 (patch)
tree1d51567670b493587db37695b4ae26347d92543c /sys/dev
parent3b6e56e0bc47caf7b4d5edad6c18cd5e0773d5fa (diff)
downloadFreeBSD-src-5f92f0907a2e4697198dd62d1d9ecc01f3c548a0.zip
FreeBSD-src-5f92f0907a2e4697198dd62d1d9ecc01f3c548a0.tar.gz
MFC r272223:
Prevent possible use after free in ahci direct mode Sponsored by: Multiplay
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ahci/ahci.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index ce54c77..9a925ea 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -1580,6 +1580,7 @@ ahci_ch_intr_direct(void *arg)
struct ahci_channel *ch = device_get_softc(dev);
struct ccb_hdr *ccb_h;
uint32_t istatus;
+ STAILQ_HEAD(, ccb_hdr) tmp_doneq = STAILQ_HEAD_INITIALIZER(tmp_doneq);
/* Read interrupt statuses. */
istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
@@ -1590,9 +1591,14 @@ ahci_ch_intr_direct(void *arg)
ch->batch = 1;
ahci_ch_intr_main(ch, istatus);
ch->batch = 0;
+ /*
+ * Prevent the possibility of issues caused by processing the queue
+ * while unlocked below by moving the contents to a local queue.
+ */
+ STAILQ_CONCAT(&tmp_doneq, &ch->doneq);
mtx_unlock(&ch->mtx);
- while ((ccb_h = STAILQ_FIRST(&ch->doneq)) != NULL) {
- STAILQ_REMOVE_HEAD(&ch->doneq, sim_links.stqe);
+ while ((ccb_h = STAILQ_FIRST(&tmp_doneq)) != NULL) {
+ STAILQ_REMOVE_HEAD(&tmp_doneq, sim_links.stqe);
xpt_done_direct((union ccb *)ccb_h);
}
}
OpenPOWER on IntegriCloud