kern/98015: [PATCH] bfe(4): double free in error handling path.
Ulrich Spoerlein
uspoerlein at gmail.com
Sat May 27 09:01:11 PDT 2006
>Number: 98015
>Category: kern
>Synopsis: [PATCH] bfe(4): double free in error handling path.
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sat May 27 16:00:44 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator: Ulrich Spoerlein
>Release: FreeBSD 6.1-STABLE i386
>Organization:
>Environment:
>Description:
When bfe_attach() fails, bfe_release_resources() is sometimes called twice.
>How-To-Repeat:
Change one if (foo()) to if (foo() || 1) and watch it panic.
>Fix:
Please note, that I really don't know what I'm doing here! I looked at various
other drivers in the tree, and they are all similiar yet slightly different. I'm
pretty sure, there are more faulty drivers due to copy'n'paste.
Since bfe_release_resource() is now only called from bfe_detach(), these two
could/should be merged. This would bring bfe(4) more in line with other NIC
drivers. There are also some style(9) "violations"
NB: Found by: Coverity CID 476
Then, there was a lock order reversal on kldunload. It seems it has vanished,
though I'm really not sure right now.
--- syscall (444, FreeBSD ELF32, kldunloadf), eip = 0x480b45cb, esp = 0xbfbfe89c, ebp = 0xbfbfed08 ---
lock order reversal: (sleepable after non-sleepable)
1st 0xc5020114 bfe0 (network driver) @ /usr/src/sys/modules/bfe/../../dev/bfe/if_bfe.c:446
2nd 0xc08b3b40 ACPI root bus (ACPI root bus) @ /usr/src/sys/modules/acpi/acpi/../../../dev/acpica/acpi.c:1075
KDB: stack backtrace:
kdb_backtrace(0,ffffffff,c072b2c0,c072bc20,c06f2d8c) at kdb_backtrace+0x29
witness_checkorder(c08b3b40,9,c08ac97b,433) at witness_checkorder+0x578
_sx_xlock(c08b3b40,c08ac97b,433,c4b4cc00,c4dc1640) at _sx_xlock+0x50
acpi_release_resource(c4b4cc00,c4c28500,1,0,c4dc1640) at acpi_release_resource+0x23
bus_generic_release_resource(c4b4c700,c4c28500,1,0,c4dc1640) at bus_generic_release_resource+0x64
resource_list_release(c4c4cd04,c4c04980,c4c28500,1,0) at resource_list_release+0x6e
bus_generic_rl_release_resource(c4c04980,c4c28500,1,0,c4dc1640) at bus_generic_rl_release_resource+0x5e
bus_generic_release_resource(c4c04600,c4c28500,1,0,c4dc1640) at bus_generic_release_resource+0x64
resource_list_release(c4c4cd04,c4c28580,c4c28500,1,0) at resource_list_release+0xfb
bus_generic_rl_release_resource(c4c28580,c4c28500,1,0,c4dc1640) at bus_generic_rl_release_resource+0x5e
bus_release_resource(c4c28500,1,0,c4dc1640,c501e000) at bus_release_resource+0x61
bfe_release_resources(c4dc9c00,c4c28500,c4c28500,c4ef4800,ed0cdc30) at bfe_release_resources+0x142
bfe_detach(c4c28500) at bfe_detach+0x58
device_detach(c4c28500) at device_detach+0x70
devclass_delete_driver(c4b0a240,c501d6f0,c4dc1900,c4f6d700,0) at devclass_delete_driver+0x8c
driver_module_handler(c4dc1900,1,c501d6dc,c4dc1900,ed0cdcb0) at driver_module_handler+0xa5
module_unload(c4dc1900,0,c071c500,c06b0e72,1fb) at module_unload+0x37
linker_file_unload(c4f6d700,0,0,c4db1900,ed0cdcdc) at linker_file_unload+0x72
kern_kldunload(c4db1900,1d,0,ed0cdd30,c0678e17) at kern_kldunload+0x7c
kldunloadf(c4db1900,ed0cdd04,2,0,292) at kldunloadf+0x1e
syscall(3b,3b,3b,1d,bfbfee37) at syscall+0x22f
Xint0x80_syscall() at Xint0x80_syscall+0x1f
--- syscall (444, FreeBSD ELF32, kldunloadf), eip = 0x480b45cb, esp = 0xbfbfe89c, ebp = 0xbfbfed08 ---
--- if_bfe.patch begins here ---
--- if_bfe.c.orig Tue May 23 19:49:54 2006
+++ if_bfe.c Wed May 24 17:16:32 2006
@@ -369,7 +369,6 @@
if (bfe_dma_alloc(dev)) {
printf("bfe%d: failed to allocate DMA resources\n",
sc->bfe_unit);
- bfe_release_resources(sc);
error = ENXIO;
goto fail;
}
@@ -424,13 +423,14 @@
bfe_intr, sc, &sc->bfe_intrhand);
if (error) {
- bfe_release_resources(sc);
printf("bfe%d: couldn't set up irq\n", unit);
+ ether_ifdetach(ifp);
goto fail;
}
fail:
if (error)
- bfe_release_resources(sc);
+ bfe_detach(dev);
+
return (error);
}
@@ -443,24 +443,17 @@
sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->bfe_mtx), ("bfe mutex not initialized"));
- BFE_LOCK(sc);
-
ifp = sc->bfe_ifp;
if (device_is_attached(dev)) {
+ BFE_LOCK(sc);
bfe_stop(sc);
+ bfe_chip_reset(sc);
+ BFE_UNLOCK(sc);
ether_ifdetach(ifp);
}
- bfe_chip_reset(sc);
-
- bus_generic_detach(dev);
- if(sc->bfe_miibus != NULL)
- device_delete_child(dev, sc->bfe_miibus);
-
bfe_release_resources(sc);
- BFE_UNLOCK(sc);
- mtx_destroy(&sc->bfe_mtx);
return (0);
}
@@ -922,6 +915,11 @@
dev = sc->bfe_dev;
+ if (sc->bfe_miibus != NULL)
+ device_delete_child(dev, sc->bfe_miibus);
+
+ bus_generic_detach(dev);
+
if (sc->bfe_vpd_prodname != NULL)
free(sc->bfe_vpd_prodname, M_DEVBUF);
@@ -971,6 +969,8 @@
if(sc->bfe_parent_tag != NULL)
bus_dma_tag_destroy(sc->bfe_parent_tag);
+
+ mtx_destroy(&sc->bfe_mtx);
return;
}
--- if_bfe.patch ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list