ng_bridge(4) has an easily exploitable memory leak
Ruslan Ermilov
ru at FreeBSD.org
Thu Apr 8 03:09:50 PDT 2004
On Wed, Apr 07, 2004 at 12:28:38PM -0700, Julian Elischer wrote:
> On Wed, 7 Apr 2004, Ruslan Ermilov wrote:
>
> > On RELENG_4, ng_bridge(4) has an easily exploitable memory leak,
> > and may quickly run system out of mbufs. It's enough to just
> > have only one link connected to the bridge, e.g., the "upper"
> > hook of the ng_ether(4) with IP address assigned, and pinging
> > the broadcast IP address on the interface. The bug is more
> > real when constructing a bridge, or, like we experienced it,
> > by shutting down all except one bridge's link. The following
> > patch fixes it:
> >
[snipped]
> > An alternate solution is to MFC most of ng_bridge.c,v 1.8. Julian?
>
> what does an MFC diff look like?
> (bridge is one of archies's nodes)
>
But it was _you_ who masked this bugfix (which would equally apply
to RELENG_4 as well) under the "SMP preparation" emblem. ;)
Anyway, the patch for RELENG_4 is attached. I've only compile tested
it.
Cheers,
--
Ruslan Ermilov
ru at FreeBSD.org
FreeBSD committer
-------------- next part --------------
Index: ng_bridge.c
===================================================================
RCS file: /home/ncvs/src/sys/netgraph/ng_bridge.c,v
retrieving revision 1.1.2.6
diff -u -p -r1.1.2.6 ng_bridge.c
--- ng_bridge.c 9 Jan 2004 08:58:06 -0000 1.1.2.6
+++ ng_bridge.c 8 Apr 2004 09:53:43 -0000
@@ -518,7 +518,8 @@ ng_bridge_rcvdata(hook_p hook, struct mb
struct ng_bridge_link *link;
struct ether_header *eh;
int error = 0, linkNum;
- int i, manycast;
+ int manycast;
+ struct ng_bridge_link *firstLink;
/* Get link number */
linkNum = LINK_NUM(hook);
@@ -657,20 +658,43 @@ ng_bridge_rcvdata(hook_p hook, struct mb
}
/* Distribute unknown, multicast, broadcast pkts to all other links */
- for (linkNum = i = 0; i < priv->numLinks - 1; linkNum++) {
- struct ng_bridge_link *const destLink = priv->links[linkNum];
+ firstLink = NULL;
+ for (linkNum = 0; linkNum <= priv->numLinks; linkNum++) {
+ struct ng_bridge_link *destLink;
meta_p meta2 = NULL;
- struct mbuf *m2;
+ struct mbuf *m2 = NULL;
- /* Skip incoming link and disconnected links */
- if (destLink == NULL || destLink == link)
- continue;
-
- /* Copy mbuf and meta info */
- if (++i == priv->numLinks - 1) { /* last link */
- m2 = m;
- meta2 = meta;
- } else {
+ /*
+ * If we have checked all the links then now
+ * send the original on its reserved link
+ */
+ if (linkNum == priv->numLinks) {
+ /* If we never saw a good link, leave. */
+ if (firstLink == NULL) {
+ NG_FREE_DATA(m, meta);
+ return (0);
+ }
+ destLink = firstLink;
+ } else {
+ destLink = priv->links[linkNum];
+ /* Skip incoming link and disconnected links */
+ if (destLink == NULL || destLink == link) {
+ continue;
+ }
+ if (firstLink == NULL) {
+ /*
+ * This is the first usable link we have found.
+ * Reserve it for the originals.
+ * If we never find another we save a copy.
+ */
+ firstLink = destLink;
+ continue;
+ }
+
+ /*
+ * It's usable link but not the reserved (first) one.
+ * Copy mbuf and meta info for sending.
+ */
m2 = m_dup(m, M_NOWAIT); /* XXX m_copypacket() */
if (m2 == NULL) {
link->stats.memoryFailures++;
@@ -701,7 +725,16 @@ ng_bridge_rcvdata(hook_p hook, struct mb
}
/* Send packet */
- NG_SEND_DATA(error, destLink->hook, m2, meta2);
+ if (destLink == firstLink) {
+ /*
+ * If we've sent all the others, send the original
+ * on the first link we found.
+ */
+ NG_SEND_DATA(error, destLink->hook, m, meta);
+ break; /* always done last - not really needed. */
+ } else {
+ NG_SEND_DATA(error, destLink->hook, m2, meta2);
+ }
}
return (error);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-stable/attachments/20040408/a803a040/attachment.bin
More information about the freebsd-stable
mailing list