diff options
author | ariff <ariff@FreeBSD.org> | 2007-03-15 16:41:27 +0000 |
---|---|---|
committer | ariff <ariff@FreeBSD.org> | 2007-03-15 16:41:27 +0000 |
commit | 2de8168c3fd8f063e61cd20eda0fdd329a5bd131 (patch) | |
tree | d884183f5f2b6415baec7ed56444b465df96b56a | |
parent | 48dd70126224a7269bc4cb5c7c3cf730ace40c7b (diff) | |
download | FreeBSD-src-2de8168c3fd8f063e61cd20eda0fdd329a5bd131.zip FreeBSD-src-2de8168c3fd8f063e61cd20eda0fdd329a5bd131.tar.gz |
Fix severe out-of-bound mtx "type" pointer, causing WITNESS refcount
confusions and panic provided that the following conditions are met:
1) WITNESS is enabled (watch/trace).
2) Using modules, instead of statically linked (Not a strict
requirement, but easier to reproduce this way).
3) 2 or more modules share the same mtx type ("sound softc").
- They might share the same name (strcmp() == 0), but it always
point to different address.
4) Repetitive kldunload/load on any module that shares the same mtx
type (Not a strict requirement, but easier to reproduce this way).
Consider module A and module B:
- From enroll() - subr_witness.c:
* Load module A. Everything seems fine right now.
wA-w_refcount == 1 ; wA-w_name = "sound softc"
* Load module B.
* w->w_name == description will always fail.
("sound softc" from A and B point to different address).
* wA->w_refcount > 0 && strcmp(description, wA->w_name) == 0
* enroll() will return wA instead of returning (possibly unique)
wB.
wA->w_refcount++ , == 2.
* Unload module A, mtx_destroy(), wA->w_name become invalid,
but wA->w_refcount-- become 1 instead of 0. wA will not be
removed from witness list.
* Some other places call mtx_init(), iterating witness list,
found wA, failed on wA->w_name == description
* wA->w_refcount > 0 && strcmp(description, wA->w_name)
* Panic on strcmp() since wA->w_name no longer point to valid
address.
Note that this could happened in other places as well, not just sound
(eg. consider lots of drivers that share simmilar MTX_NETWORK_LOCK).
Solutions (for sound case):
1) Provide unique mtx type string for each mutex creation (chosen)
or
2) Put "sound softc" global variable somewhere and use it.
-rw-r--r-- | sys/dev/sound/isa/ad1816.c | 3 | ||||
-rw-r--r-- | sys/dev/sound/isa/mss.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/isa/sbc.c | 3 | ||||
-rw-r--r-- | sys/dev/sound/pci/als4000.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/atiixp.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/cmi.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/ds1.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/emu10k1.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/emu10kx-pcm.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/envy24.c | 4 | ||||
-rw-r--r-- | sys/dev/sound/pci/envy24ht.c | 5 | ||||
-rw-r--r-- | sys/dev/sound/pci/es137x.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/ich.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/maestro.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/maestro3.c | 7 | ||||
-rw-r--r-- | sys/dev/sound/pci/solo.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/t4dwave.c | 2 | ||||
-rw-r--r-- | sys/dev/sound/pci/via8233.c | 3 | ||||
-rw-r--r-- | sys/dev/sound/pci/via82c686.c | 3 | ||||
-rw-r--r-- | sys/dev/sound/sbus/cs4231.c | 7 |
20 files changed, 25 insertions, 34 deletions
diff --git a/sys/dev/sound/isa/ad1816.c b/sys/dev/sound/isa/ad1816.c index 283f66f..eb05e5e 100644 --- a/sys/dev/sound/isa/ad1816.c +++ b/sys/dev/sound/isa/ad1816.c @@ -601,7 +601,8 @@ ad1816_attach(device_t dev) ad1816 = (struct ad1816_info *)malloc(sizeof *ad1816, M_DEVBUF, M_NOWAIT | M_ZERO); if (!ad1816) return ENXIO; - ad1816->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + ad1816->lock = snd_mtxcreate(device_get_nameunit(dev), + "snd_ad1816 softc"); ad1816->io_rid = 2; ad1816->irq_rid = 0; ad1816->drq1_rid = 0; diff --git a/sys/dev/sound/isa/mss.c b/sys/dev/sound/isa/mss.c index 22af6e7..4820eed 100644 --- a/sys/dev/sound/isa/mss.c +++ b/sys/dev/sound/isa/mss.c @@ -1696,7 +1696,7 @@ mss_doattach(device_t dev, struct mss_info *mss) int pdma, rdma, flags = device_get_flags(dev); char status[SND_STATUSLEN], status2[SND_STATUSLEN]; - mss->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + mss->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_mss softc"); mss->bufsize = pcm_getbuffersize(dev, 4096, MSS_DEFAULT_BUFSZ, 65536); if (!mss_alloc_resources(mss, dev)) goto no; mss_init(mss, dev); diff --git a/sys/dev/sound/isa/sbc.c b/sys/dev/sound/isa/sbc.c index ef4b119..9cbe523 100644 --- a/sys/dev/sound/isa/sbc.c +++ b/sys/dev/sound/isa/sbc.c @@ -120,7 +120,8 @@ static void sb_setmixer(struct resource *io, u_int port, u_int value); static void sbc_lockinit(struct sbc_softc *scp) { - scp->lock = snd_mtxcreate(device_get_nameunit(scp->dev), "sound softc"); + scp->lock = snd_mtxcreate(device_get_nameunit(scp->dev), + "snd_sbc softc"); } static void diff --git a/sys/dev/sound/pci/als4000.c b/sys/dev/sound/pci/als4000.c index 892b21f..8f2d4ad 100644 --- a/sys/dev/sound/pci/als4000.c +++ b/sys/dev/sound/pci/als4000.c @@ -803,7 +803,7 @@ als_pci_attach(device_t dev) return ENXIO; } - sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_als4000 softc"); sc->dev = dev; data = pci_read_config(dev, PCIR_COMMAND, 2); diff --git a/sys/dev/sound/pci/atiixp.c b/sys/dev/sound/pci/atiixp.c index 3de48c1..d3e988a 100644 --- a/sys/dev/sound/pci/atiixp.c +++ b/sys/dev/sound/pci/atiixp.c @@ -1134,7 +1134,7 @@ atiixp_pci_attach(device_t dev) return (ENXIO); } - sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_atiixp softc"); sc->dev = dev; callout_init(&sc->poll_timer, CALLOUT_MPSAFE); diff --git a/sys/dev/sound/pci/cmi.c b/sys/dev/sound/pci/cmi.c index e5f7eb1..589f15a 100644 --- a/sys/dev/sound/pci/cmi.c +++ b/sys/dev/sound/pci/cmi.c @@ -929,7 +929,7 @@ cmi_attach(device_t dev) return ENXIO; } - sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_cmi softc"); data = pci_read_config(dev, PCIR_COMMAND, 2); data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN); pci_write_config(dev, PCIR_COMMAND, data, 2); diff --git a/sys/dev/sound/pci/ds1.c b/sys/dev/sound/pci/ds1.c index c9f0428..782a3a5 100644 --- a/sys/dev/sound/pci/ds1.c +++ b/sys/dev/sound/pci/ds1.c @@ -948,7 +948,7 @@ ds_pci_attach(device_t dev) return ENXIO; } - sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_ds1 softc"); sc->dev = dev; subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); sc->type = ds_finddev(pci_get_devid(dev), subdev); diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c index 68b89d8..d3cea09 100644 --- a/sys/dev/sound/pci/emu10k1.c +++ b/sys/dev/sound/pci/emu10k1.c @@ -1986,7 +1986,7 @@ emu_pci_attach(device_t dev) return ENXIO; } - sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_emu10k1 softc"); sc->dev = dev; sc->type = pci_get_devid(dev); sc->rev = pci_get_revid(dev); diff --git a/sys/dev/sound/pci/emu10kx-pcm.c b/sys/dev/sound/pci/emu10kx-pcm.c index 2ee69ff..1aab355 100644 --- a/sys/dev/sound/pci/emu10kx-pcm.c +++ b/sys/dev/sound/pci/emu10kx-pcm.c @@ -1016,7 +1016,7 @@ emu_pcm_attach(device_t dev) return (ENXIO); } - sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_emu10kx softc"); sc->dev = dev; r = BUS_READ_IVAR(device_get_parent(dev), dev, EMU_VAR_ISEMU10K1, &is_emu10k1); diff --git a/sys/dev/sound/pci/envy24.c b/sys/dev/sound/pci/envy24.c index 8de3c3b..b65b491 100644 --- a/sys/dev/sound/pci/envy24.c +++ b/sys/dev/sound/pci/envy24.c @@ -2371,7 +2371,6 @@ envy24_pci_attach(device_t dev) u_int32_t data; struct sc_info *sc; char status[SND_STATUSLEN]; - char name[ENVY24_NAMELEN]; int err = 0; int i; @@ -2385,8 +2384,7 @@ envy24_pci_attach(device_t dev) } bzero(sc, sizeof(*sc)); - snprintf(name, ENVY24_NAMELEN, "%s:envy24", device_get_nameunit(dev)); - sc->lock = snd_mtxcreate(name, name); + sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc"); sc->dev = dev; /* initialize PCI interface */ diff --git a/sys/dev/sound/pci/envy24ht.c b/sys/dev/sound/pci/envy24ht.c index c2ff685..e11a99b 100644 --- a/sys/dev/sound/pci/envy24ht.c +++ b/sys/dev/sound/pci/envy24ht.c @@ -2390,7 +2390,6 @@ envy24ht_pci_attach(device_t dev) u_int32_t data; struct sc_info *sc; char status[SND_STATUSLEN]; - char name[ENVY24HT_NAMELEN]; int err = 0; int i; @@ -2404,8 +2403,8 @@ envy24ht_pci_attach(device_t dev) } bzero(sc, sizeof(*sc)); - snprintf(name, ENVY24HT_NAMELEN, "%s:envy24ht", device_get_nameunit(dev)); - sc->lock = snd_mtxcreate(name, name); + sc->lock = snd_mtxcreate(device_get_nameunit(dev), + "snd_envy24ht softc"); sc->dev = dev; /* initialize PCI interface */ diff --git a/sys/dev/sound/pci/es137x.c b/sys/dev/sound/pci/es137x.c index 5d2ba37..261e9b7 100644 --- a/sys/dev/sound/pci/es137x.c +++ b/sys/dev/sound/pci/es137x.c @@ -1654,7 +1654,7 @@ es_pci_attach(device_t dev) device_printf(dev, "cannot allocate softc\n"); return (ENXIO); } - es->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + es->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_es137x softc"); es->dev = dev; es->escfg = 0; mapped = 0; diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c index 6d45930..9b07c1f 100644 --- a/sys/dev/sound/pci/ich.c +++ b/sys/dev/sound/pci/ich.c @@ -851,7 +851,7 @@ ich_pci_attach(device_t dev) return (ENXIO); } - sc->ich_lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + sc->ich_lock = snd_mtxcreate(device_get_nameunit(dev), "snd_ich softc"); sc->dev = dev; vendor = sc->vendor = pci_get_vendor(dev); diff --git a/sys/dev/sound/pci/maestro.c b/sys/dev/sound/pci/maestro.c index 124d98d..d81effe 100644 --- a/sys/dev/sound/pci/maestro.c +++ b/sys/dev/sound/pci/maestro.c @@ -1781,7 +1781,7 @@ agg_attach(device_t dev) ess->dev = dev; #ifdef USING_MUTEX - mtx_init(&ess->lock, device_get_desc(dev), "hardware status lock", + mtx_init(&ess->lock, device_get_desc(dev), "snd_maestro softc", MTX_DEF | MTX_RECURSE); if (!mtx_initialized(&ess->lock)) { device_printf(dev, "failed to create a mutex.\n"); diff --git a/sys/dev/sound/pci/maestro3.c b/sys/dev/sound/pci/maestro3.c index e8454f2..3ccfeb7 100644 --- a/sys/dev/sound/pci/maestro3.c +++ b/sys/dev/sound/pci/maestro3.c @@ -1267,12 +1267,7 @@ m3_pci_attach(device_t dev) sc->dev = dev; sc->type = pci_get_devid(dev); sc->sc_lock = snd_mtxcreate(device_get_nameunit(dev), - "sound softc"); - if (sc->sc_lock == NULL) { - device_printf(dev, "cannot create mutex\n"); - free(sc, M_DEVBUF); - return (ENXIO); - } + "snd_maestro3 softc"); for (card = m3_card_types ; card->pci_id ; card++) { if (sc->type == card->pci_id) { sc->which = card->which; diff --git a/sys/dev/sound/pci/solo.c b/sys/dev/sound/pci/solo.c index cb78403..c3de20c 100644 --- a/sys/dev/sound/pci/solo.c +++ b/sys/dev/sound/pci/solo.c @@ -897,7 +897,7 @@ ess_alloc_resources(struct ess_info *sc, device_t dev) RF_ACTIVE | RF_SHAREABLE); #if ESS18XX_MPSAFE == 1 - sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_solo softc"); return (sc->irq && sc->io && sc->sb && sc->vc && sc->mpu && sc->gp && sc->lock)? 0 : ENXIO; diff --git a/sys/dev/sound/pci/t4dwave.c b/sys/dev/sound/pci/t4dwave.c index 76f5867..ff8d4a3 100644 --- a/sys/dev/sound/pci/t4dwave.c +++ b/sys/dev/sound/pci/t4dwave.c @@ -821,7 +821,7 @@ tr_pci_attach(device_t dev) tr->type = pci_get_devid(dev); tr->rev = pci_get_revid(dev); - tr->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + tr->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_t4dwave softc"); data = pci_read_config(dev, PCIR_COMMAND, 2); data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); diff --git a/sys/dev/sound/pci/via8233.c b/sys/dev/sound/pci/via8233.c index 8667ea1..eca8d11 100644 --- a/sys/dev/sound/pci/via8233.c +++ b/sys/dev/sound/pci/via8233.c @@ -1123,7 +1123,8 @@ via_attach(device_t dev) device_printf(dev, "cannot allocate softc\n"); return (ENXIO); } - via->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + via->lock = snd_mtxcreate(device_get_nameunit(dev), + "snd_via8233 softc"); callout_init(&via->poll_timer, CALLOUT_MPSAFE); via->poll_ticks = 1; diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c index 2b73e1f..46800c7 100644 --- a/sys/dev/sound/pci/via82c686.c +++ b/sys/dev/sound/pci/via82c686.c @@ -481,7 +481,8 @@ via_attach(device_t dev) device_printf(dev, "cannot allocate softc\n"); return ENXIO; } - via->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); + via->lock = snd_mtxcreate(device_get_nameunit(dev), + "snd_via82c686 softc"); /* Get resources */ data = pci_read_config(dev, PCIR_COMMAND, 2); diff --git a/sys/dev/sound/sbus/cs4231.c b/sys/dev/sound/sbus/cs4231.c index d463392..ed070b7 100644 --- a/sys/dev/sound/sbus/cs4231.c +++ b/sys/dev/sound/sbus/cs4231.c @@ -375,12 +375,7 @@ cs4231_attach_common(struct cs4231_softc *sc) int i; sc->sc_lock = snd_mtxcreate(device_get_nameunit(sc->sc_dev), - "sound softc"); - if (sc->sc_lock == NULL) { - device_printf(sc->sc_dev, "cannot create mutex\n"); - free(sc, M_DEVBUF); - return (ENXIO); - } + "snd_cs4231 softc"); for (i = 0; i < sc->sc_nmres; i++) { sc->sc_rid[i] = i; |