--- sys/bus/u4b/net/if_kue.c.orig +++ sys/bus/u4b/net/if_kue.c @@ -439,6 +439,24 @@ kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR, 0, &sc->sc_desc, sizeof(sc->sc_desc)); + /* + * Only now is sc_desc.kue_mcastfilt valid, so only now can the + * multicast filter buffer be sized. This allocation used to + * live in kue_attach(), where sc_desc was still all-zero: + * kmalloc(0) returns ZERO_LENGTH_PTR ((void *)-8, + * kern_slaballoc.c:193) which the NULL check cannot catch, and + * kue_setmulti() later wrote filter entries through it once the + * device-controlled descriptor had arrived -- deterministic + * kernel page fault on any SIOCADDMULTI while a device reports + * a non-zero filter count (DF-2340). A count of zero keeps + * sc_mcfilters NULL: kue_setmulti() then takes the allmulti + * path without touching the buffer and kfree(NULL) is a no-op. + */ + if (KUE_MCFILTCNT(sc) != 0) { + sc->sc_mcfilters = kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, + M_USBDEV, M_WAITOK | M_ZERO); + } + /* copy in ethernet address */ memcpy(ue->ue_eaddr, sc->sc_desc.kue_macaddr, sizeof(ue->ue_eaddr)); } @@ -485,13 +503,6 @@ goto detach; } - sc->sc_mcfilters = kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, - M_USBDEV, M_WAITOK); - if (sc->sc_mcfilters == NULL) { - device_printf(dev, "failed allocating USB memory\n"); - goto detach; - } - ue->ue_sc = sc; ue->ue_dev = dev; ue->ue_udev = uaa->device;