diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2010-08-11 02:18:26 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2010-08-11 02:18:26 +0000 |
commit | 08950a9628800a6c04d1b045ef8a18d5fd0864ba (patch) | |
tree | 055d1abbe7b7565fff5d8a23ee91d93e6ab6c65f | |
parent | 5f0d4c915d87938445313e5481a3ccd7ccfbeedf (diff) |
Fix two problems in gdt, introduced in 4.7. Eliminate a use-after-free
of xs for xs->flags. Avoid calling scsi_done() twice when sync'ing
disks during shut down.
scsi_done() problem found by Federico Giannici. Feedback and fixes
from matthew@ and dlg@. Testing of various versions by Federico and
sthen@ via Pierre Berthier.
ok matthew@ deraadt@
-rw-r--r-- | sys/dev/ic/gdt_common.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/sys/dev/ic/gdt_common.c b/sys/dev/ic/gdt_common.c index 01ff8c10acb..e725786d5c8 100644 --- a/sys/dev/ic/gdt_common.c +++ b/sys/dev/ic/gdt_common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gdt_common.c,v 1.51 2010/06/28 18:31:02 krw Exp $ */ +/* $OpenBSD: gdt_common.c,v 1.52 2010/08/11 02:18:25 krw Exp $ */ /* * Copyright (c) 1999, 2000, 2003 Niklas Hallqvist. All rights reserved. @@ -587,6 +587,7 @@ gdt_scsi_cmd(struct scsi_xfer *xs) bus_dmamap_t xfer; int error; int s; + int polled; GDT_DPRINTF(GDT_D_CMD, ("gdt_scsi_cmd ")); @@ -615,6 +616,7 @@ gdt_scsi_cmd(struct scsi_xfer *xs) ccb = NULL; link = xs->sc_link; target = link->target; + polled = ISSET(xs->flags, SCSI_POLL); if (!gdt_polling && !(xs->flags & SCSI_POLL) && sc->sc_test_busy(sc)) { @@ -759,7 +761,6 @@ gdt_scsi_cmd(struct scsi_xfer *xs) splx(s); return; } - scsi_done(xs); } } @@ -767,7 +768,7 @@ gdt_scsi_cmd(struct scsi_xfer *xs) /* * Don't process the queue if we are polling. */ - if (xs->flags & SCSI_POLL) { + if (polled) { break; } } @@ -1155,8 +1156,11 @@ gdt_intr(void *arg) sync_val = gdt_sync_event(sc, ctx.service, ctx.istatus, xs); finish: - switch (sync_val) { + case 0: + if (xs && gdt_from_wait) + scsi_done(xs); + break; case 1: scsi_done(xs); break; |