Hi,

could you please test following patch:
 http://sources.zabbadoz.net/freebsd/patchset/mii-20050326-plug-leaks.diff

Any feedback welcome.

Thanks in advance.

-- 
Greetings
Bjoern A. Zeeb                          bzeeb at Zabbadoz dot NeT


Index: sys/dev/mii/mii.c
===================================================================
RCS file: /local/mirror/FreeBSD/r/ncvs/src/sys/dev/mii/mii.c,v
retrieving revision 1.25
diff -u -p -r1.25 mii.c
--- sys/dev/mii/mii.c   16 Feb 2005 05:56:39 -0000      1.25
+++ sys/dev/mii/mii.c   26 Mar 2005 19:02:41 -0000
@@ -115,7 +115,7 @@ miibus_probe(device_t dev)
        struct mii_attach_args  ma, *args;
        struct mii_data         *mii;
        device_t                child = NULL, parent;
-       int                     bmsr, capmask = 0xFFFFFFFF;
+       int                     bmsr, capmask = 0xFFFFFFFF, count = 0;

        mii = device_get_softc(dev);
        parent = device_get_parent(dev);
@@ -149,12 +149,24 @@ miibus_probe(device_t dev)

                args = malloc(sizeof(struct mii_attach_args),
                    M_DEVBUF, M_NOWAIT);
+               if (args == NULL) {
+                       device_printf(dev, "%s: memory allocation failure, "
+                           "phyno %d", __func__, ma.mii_phyno);
+                       continue;
+               }
                bcopy((char *)&ma, (char *)args, sizeof(ma));
                child = device_add_child(dev, NULL, -1);
+               if (child == NULL) {
+                       free(args, M_DEVBUF);
+                       device_printf(dev, "%s: device_add_child failed",
+                           __func__);
+                       continue;
+               }
                device_set_ivars(child, args);
+               count++;
        }

-       if (child == NULL)
+       if (count == 0)
                return(ENXIO);

        device_set_desc(dev, "MII bus");
@@ -176,20 +188,40 @@ miibus_attach(device_t dev)
         */
        mii->mii_ifp = device_get_softc(device_get_parent(dev));
        v = device_get_ivars(dev);
+       if (v == NULL)
+               return (ENXIO); /* XXX */
        ifmedia_upd = v[0];
        ifmedia_sts = v[1];
        ifmedia_init(&mii->mii_media, IFM_IMASK, ifmedia_upd, ifmedia_sts);
-       bus_generic_attach(dev);

-       return(0);
+       return(bus_generic_attach(dev));
 }

 int
 miibus_detach(device_t dev)
 {
        struct mii_data         *mii;
+       device_t                *children, *childp;
+       int                     error, j, childcount = 0;
+       void                    *v;
+
+       if (device_get_state(dev) != DS_ATTACHED)
+               return (EBUSY);

-       bus_generic_detach(dev);
+       device_get_children(dev, &children, &childcount);
+       for (j = 0, childp = children; j < childcount; j++, childp++) {
+               /*
+                * Free ivars but not before device_detach.
+                * miibus_child_* fuinctions still use them unchecked.
+                */
+               v = device_get_ivars(*childp);
+               if ((error = device_detach(*childp)) != 0)
+                       return (error);
+               if (v != NULL) {
+                       device_set_ivars(*childp, NULL);
+                       free(v, M_DEVBUF);
+               }
+       }
        mii = device_get_softc(dev);
        ifmedia_removeall(&mii->mii_media);
        mii->mii_ifp = NULL;
@@ -300,12 +332,16 @@ mii_phy_probe(device_t dev, device_t *ch
        int                     bmsr, i;

        v = malloc(sizeof(vm_offset_t) * 2, M_DEVBUF, M_NOWAIT);
-       if (v == 0) {
+       if (v == NULL) {
                return (ENOMEM);
        }
        v[0] = ifmedia_upd;
        v[1] = ifmedia_sts;
        *child = device_add_child(dev, "miibus", -1);
+       if (*child == NULL) {
+               free(v, M_DEVBUF);
+               return (ENXIO);
+       }
        device_set_ivars(*child, v);

        for (i = 0; i < MII_NPHY; i++) {
@@ -319,14 +355,23 @@ mii_phy_probe(device_t dev, device_t *ch
        }

        if (i == MII_NPHY) {
+               device_set_ivars(*child, NULL);
+               free(v, M_DEVBUF);
                device_delete_child(dev, *child);
                *child = NULL;
                return(ENXIO);
        }

-       bus_generic_attach(dev);
+       i = bus_generic_attach(dev);

-       return(0);
+       /* Free ivars as they are no longer needed. */
+       v = device_get_ivars(*child);
+       if (v != NULL) {
+               device_set_ivars(*child, NULL);
+               free(v, M_DEVBUF);
+       }
+
+       return(i);
 }

 /*
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to