Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105785683
D19622.id56513.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D19622.id56513.diff
View Options
Index: sys/net/vnet.c
===================================================================
--- sys/net/vnet.c
+++ sys/net/vnet.c
@@ -577,6 +577,7 @@
curvnet->vnet_state = vs->subsystem;
vs->func(vs->arg);
}
+ curvnet->vnet_state = SI_SUB_LAST;
VNET_SYSINIT_RUNLOCK();
}
@@ -596,6 +597,7 @@
curvnet->vnet_state = vs->subsystem;
vs->func(vs->arg);
}
+ curvnet->vnet_state = 0;
VNET_SYSINIT_RUNLOCK();
}
Index: sys/netinet/ip_reass.c
===================================================================
--- sys/netinet/ip_reass.c
+++ sys/netinet/ip_reass.c
@@ -47,7 +47,10 @@
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_var.h>
#include <net/rss_config.h>
#include <net/netisr.h>
#include <net/vnet.h>
@@ -607,7 +610,44 @@
}
}
+/*
+ * Drain off all datagram fragments belonging to
+ * the given network interface.
+ */
+static void
+ipreass_cleanup(void *arg __unused, struct ifnet *ifp)
+{
+ struct ipq *fp, *temp;
+ struct mbuf *m;
+ int i;
+
+ KASSERT(ifp != NULL, ("%s: ifp is NULL", __func__));
+
#ifdef VIMAGE
+ if (ifp->if_vnet->vnet_state <= SI_SUB_PROTO_DOMAIN) {
+ /* the IP reassembly hash has or will soon be destroyed */
+ return;
+ }
+#endif
+ CURVNET_SET_QUIET(ifp->if_vnet);
+ for (i = 0; i < IPREASS_NHASH; i++) {
+ IPQ_LOCK(i);
+ /* Scan fragment list. */
+ TAILQ_FOREACH_SAFE(fp, &V_ipq[i].head, ipq_list, temp) {
+ for (m = fp->ipq_frags; m != NULL; m = m->m_nextpkt) {
+ if (m->m_pkthdr.rcvif == ifp) {
+ ipq_drop(&V_ipq[i], fp);
+ break;
+ }
+ }
+ }
+ IPQ_UNLOCK(i);
+ }
+ CURVNET_RESTORE();
+}
+EVENTHANDLER_DEFINE(ifnet_departure_event, ipreass_cleanup, NULL, 0);
+
+#ifdef VIMAGE
/*
* Destroy IP reassembly structures.
*/
Index: sys/netinet6/frag6.c
===================================================================
--- sys/netinet6/frag6.c
+++ sys/netinet6/frag6.c
@@ -82,7 +82,7 @@
static void frag6_insque_head(struct ip6q *, struct ip6q *,
uint32_t bucket);
static void frag6_remque(struct ip6q *, uint32_t bucket);
-static void frag6_freef(struct ip6q *, uint32_t bucket);
+static void frag6_freef(struct ip6q *, uint32_t bucket, bool send_icmp);
struct ip6qbucket {
struct ip6q ip6q;
@@ -595,7 +595,7 @@
if (af6->ip6af_off != next) {
if (q6->ip6q_nfrag > V_ip6_maxfragsperpacket) {
IP6STAT_ADD(ip6s_fragdropped, q6->ip6q_nfrag);
- frag6_freef(q6, hash);
+ frag6_freef(q6, hash, true);
}
IP6Q_UNLOCK(hash);
return IPPROTO_DONE;
@@ -605,7 +605,7 @@
if (af6->ip6af_up->ip6af_mff) {
if (q6->ip6q_nfrag > V_ip6_maxfragsperpacket) {
IP6STAT_ADD(ip6s_fragdropped, q6->ip6q_nfrag);
- frag6_freef(q6, hash);
+ frag6_freef(q6, hash, true);
}
IP6Q_UNLOCK(hash);
return IPPROTO_DONE;
@@ -732,7 +732,7 @@
* associated datagrams.
*/
static void
-frag6_freef(struct ip6q *q6, uint32_t bucket)
+frag6_freef(struct ip6q *q6, uint32_t bucket, bool send_icmp)
{
struct ip6asfrag *af6, *down6;
@@ -749,7 +749,7 @@
* Return ICMP time exceeded error for the 1st fragment.
* Just free other fragments.
*/
- if (af6->ip6af_off == 0) {
+ if (af6->ip6af_off == 0 && send_icmp != false) {
struct ip6_hdr *ip6;
/* adjust pointer */
@@ -865,7 +865,7 @@
IP6STAT_ADD(ip6s_fragtimeout,
q6->ip6q_prev->ip6q_nfrag);
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
- frag6_freef(q6->ip6q_prev, i);
+ frag6_freef(q6->ip6q_prev, i, true);
}
}
/*
@@ -884,7 +884,7 @@
IP6STAT_ADD(ip6s_fragoverflow,
q6->ip6q_prev->ip6q_nfrag);
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
- frag6_freef(head->ip6q_prev, i);
+ frag6_freef(head->ip6q_prev, i, true);
}
IP6Q_UNLOCK(i);
}
@@ -902,7 +902,7 @@
IP6STAT_ADD(ip6s_fragoverflow,
q6->ip6q_prev->ip6q_nfrag);
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
- frag6_freef(head->ip6q_prev, i);
+ frag6_freef(head->ip6q_prev, i, true);
}
IP6Q_UNLOCK(i);
i = (i + 1) % IP6REASS_NHASH;
@@ -932,7 +932,7 @@
while (head->ip6q_next != head) {
IP6STAT_INC(ip6s_fragdropped);
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
- frag6_freef(head->ip6q_next, i);
+ frag6_freef(head->ip6q_next, i, true);
}
IP6Q_UNLOCK(i);
}
@@ -941,6 +941,51 @@
VNET_LIST_RUNLOCK_NOSLEEP();
}
+/*
+ * Drain off all datagram fragments belonging to
+ * the given network interface.
+ */
+static void
+frag6_cleanup(void *arg __unused, struct ifnet *ifp)
+{
+ struct ip6q *q6, *q6n, *head;
+ struct ip6asfrag *af6;
+ struct mbuf *m;
+ int i;
+
+ KASSERT(ifp != NULL, ("%s: ifp is NULL", __func__));
+
+#ifdef VIMAGE
+ if (ifp->if_vnet->vnet_state <= SI_SUB_PROTO_DOMAIN) {
+ /* the IPv6 reassembly hash has or will soon be destroyed */
+ return;
+ }
+#endif
+ CURVNET_SET_QUIET(ifp->if_vnet);
+ for (i = 0; i < IP6REASS_NHASH; i++) {
+ IP6Q_LOCK(i);
+ head = IP6Q_HEAD(i);
+ /* Scan fragment list. */
+ for (q6 = head->ip6q_next; q6 != head; q6 = q6n) {
+ q6n = q6->ip6q_next;
+
+ for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
+ af6 = af6->ip6af_down) {
+ m = IP6_REASS_MBUF(af6);
+
+ if (m->m_pkthdr.rcvif == ifp) {
+ IP6STAT_INC(ip6s_fragdropped);
+ frag6_freef(q6, i, false);
+ break;
+ }
+ }
+ }
+ IP6Q_UNLOCK(i);
+ }
+ CURVNET_RESTORE();
+}
+EVENTHANDLER_DEFINE(ifnet_departure_event, frag6_cleanup, NULL, 0);
+
int
ip6_deletefraghdr(struct mbuf *m, int offset, int wait)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 21, 4:24 PM (16 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15543214
Default Alt Text
D19622.id56513.diff (5 KB)
Attached To
Mode
D19622: Fix panic in network stack due memory use after free in relation to fragmented packets
Attached
Detach File
Event Timeline
Log In to Comment