NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/58297: net/nd.c leaks mbufs pending neighbour discovery
>Number: 58297
>Category: kern
>Synopsis: net/nd.c leaks mbufs pending neighbour discovery
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue May 28 21:45:01 +0000 2024
>Originator: Taylor R Campbell
>Release: current, 10
>Organization:
The NDBSD Foundation
>Environment:
>Description:
When the network stack needs the link-layer address of the next hop for an outgoing packet, it asks nd_resolve (e.g., via ether_output -> arpresolve).
If nd_resolve doesn't know the link-layer address, it queues up the packet's mbuf in struct llentry::la_hold (a.k.a. ln_hold) for all packets to be transmitted via the same next hop once the link-layer address is resolved (via arp, ipv6nd, ...). (If the queue exceeds a maximum length -- currently, always 1 -- then older packets are freed.)
From time to time, the still-pending packets are supposed to be freed in lltable_drop_entry_queue, via lltable_drain (from arp_drain, called by arp_fasttimo; XXX no IPv6 callers?) or via llentry_free (from lltable_purge_entries, called by in_if_down, in6_if_down, nd6_purge).
But lltable_drop_entry_queue only frees the queued mbufs if la_numheld is positive. And nothing ever increments la_numheld. So whenever an llentry is freed, e.g. when an interface is brought down, it will leak any queued mbufs waiting for their next hop's link-layer address resolution.
Found by Edgar Fuss: https://mail-index.netbsd.org/tech-net/2024/04/23/msg008762.html
>How-To-Repeat:
1. ping a host on the local network that doesn't exist
2. bring the interface down before link-layer resolution has timed out and given up
>Fix:
From 2786a8a8ed3b3223888c8374c5d32162866aec91 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Wed, 24 Apr 2024 14:08:35 +0000
Subject: [PATCH] nd_resolve: Maintain la_numheld.
Otherwise lltable_drop_entry_quene never drops anything.
Addresses mbuf leak, PR kern/XXXXX.
---
sys/net/nd.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/sys/net/nd.c b/sys/net/nd.c
index c9c2ca6fddec..7be385b74693 100644
--- a/sys/net/nd.c
+++ b/sys/net/nd.c
@@ -374,14 +374,25 @@ nd_resolve(struct llentry *ln, const struct rtentry *rt, struct mbuf *m,
break;
}
}
+ KASSERTMSG(ln->la_numheld == i, "la_numheld=%d i=%d",
+ ln->la_numheld, i);
while (i >= nd->nd_maxqueuelen) {
m_hold = ln->ln_hold;
ln->ln_hold = ln->ln_hold->m_nextpkt;
m_freem(m_hold);
i--;
+ ln->la_numheld--;
}
- } else
+ } else {
+ KASSERTMSG(ln->la_numheld == 0, "la_numheld=%d",
+ ln->la_numheld);
ln->ln_hold = m;
+ }
+
+ KASSERTMSG(ln->la_numheld < nd->nd_maxqueuelen,
+ "la_numheld=%d nd_maxqueuelen=%d",
+ ln->la_numheld, nd->nd_maxqueuelen);
+ ln->la_numheld++;
if (ln->ln_asked >= nd->nd_mmaxtries)
error = (rt != NULL && rt->rt_flags & RTF_GATEWAY) ?
Home |
Main Index |
Thread Index |
Old Index