Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F159266740
D19622.id57839.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D19622.id57839.diff
View Options
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>
@@ -181,6 +184,7 @@
struct ip *ip;
struct mbuf *p, *q, *nq, *t;
struct ipq *fp;
+ struct ifnet *srcifp;
struct ipqhead *head;
int i, hlen, next, tmpmax;
u_int8_t ecn, ecn0;
@@ -241,6 +245,11 @@
}
/*
+ * Store receive network interface pointer for later.
+ */
+ srcifp = m->m_pkthdr.rcvif;
+
+ /*
* Attempt reassembly; if it succeeds, proceed.
* ip_reass() will return a different mbuf.
*/
@@ -490,8 +499,11 @@
m->m_len += (ip->ip_hl << 2);
m->m_data -= (ip->ip_hl << 2);
/* some debugging cruft by sklower, below, will go away soon */
- if (m->m_flags & M_PKTHDR) /* XXX this should be done elsewhere */
+ if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
m_fixhdr(m);
+ /* set valid receive interface pointer */
+ m->m_pkthdr.rcvif = srcifp;
+ }
IPSTAT_INC(ips_reassembled);
IPQ_UNLOCK(hash);
@@ -607,7 +619,43 @@
}
}
+/*
+ * 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 (!vnet_is_running(ifp->if_vnet)) {
+ /* the IPv4 reassembly hash is 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) {
+ /* clear no longer valid rcvif pointer */
+ if (m->m_pkthdr.rcvif == ifp)
+ m->m_pkthdr.rcvif = NULL;
+ }
+ }
+ 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
@@ -223,6 +223,7 @@
sizeof(ip6f->ip6f_ident)) / sizeof(uint32_t)];
uint32_t hash, *hashkeyp;
struct ifnet *dstifp;
+ struct ifnet *srcifp;
u_int8_t ecn, ecn0;
#ifdef RSS
struct m_tag *mtag;
@@ -243,6 +244,11 @@
return (IPPROTO_DONE);
#endif
+ /*
+ * Store receive network interface pointer for later.
+ */
+ srcifp = m->m_pkthdr.rcvif;
+
dstifp = NULL;
/* find the destination interface of the packet. */
ia = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
@@ -432,6 +438,9 @@
frag6_deq(af6, hash);
free(af6, M_FTABLE);
+ /* set valid receive interface pointer */
+ merr->m_pkthdr.rcvif = srcifp;
+
/* adjust pointer. */
ip6err = mtod(merr, struct ip6_hdr *);
@@ -683,6 +692,8 @@
for (t = m; t; t = t->m_next)
plen += t->m_len;
m->m_pkthdr.len = plen;
+ /* set valid receive interface pointer */
+ m->m_pkthdr.rcvif = srcifp;
}
#ifdef RSS
@@ -749,7 +760,7 @@
* Return ICMP time exceeded error for the 1st fragment.
* Just free other fragments.
*/
- if (af6->ip6af_off == 0) {
+ if (af6->ip6af_off == 0 && m->m_pkthdr.rcvif != NULL) {
struct ip6_hdr *ip6;
/* adjust pointer */
@@ -941,6 +952,49 @@
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 (!vnet_is_running(ifp->if_vnet)) {
+ /* the IPv6 reassembly hash is 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);
+
+ /* clear no longer valid rcvif pointer */
+ if (m->m_pkthdr.rcvif == ifp)
+ m->m_pkthdr.rcvif = NULL;
+ }
+ }
+ 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, Jun 13, 2:54 AM (10 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33919252
Default Alt Text
D19622.id57839.diff (4 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