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.
This commit is contained in:
Ariff Abdullah 2007-03-15 16:41:27 +00:00
parent 8d5162b9da
commit 4582b3a100
20 changed files with 25 additions and 34 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;