test/review: plug mii leakage

From: Bjoern A. Zeeb <bzeeb-lists_at_lists.zabbadoz.net>
Date: Sun, 27 Mar 2005 19:54:25 +0000 (UTC)
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
_at__at_ -115,7 +115,7 _at__at_ 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);
_at__at_ -149,12 +149,24 _at__at_ 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");
_at__at_ -176,20 +188,40 _at__at_ 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;
_at__at_ -300,12 +332,16 _at__at_ 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++) {
_at__at_ -319,14 +355,23 _at__at_ 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);
 }

 /*
Received on Sun Mar 27 2005 - 17:55:09 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:30 UTC