Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105786204
D19622.id55319.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D19622.id55319.diff
View Options
Index: sys/kern/kern_mbuf.c
===================================================================
--- sys/kern/kern_mbuf.c
+++ sys/kern/kern_mbuf.c
@@ -802,6 +802,13 @@
static void
mb_reclaim(uma_zone_t zone __unused, int pending __unused)
{
+
+ mb_reclaim_from_all_domains(NULL);
+}
+
+void
+mb_reclaim_from_all_domains(struct ifnet *ifp)
+{
struct domain *dp;
struct protosw *pr;
@@ -810,7 +817,7 @@
for (dp = domains; dp != NULL; dp = dp->dom_next)
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
if (pr->pr_drain != NULL)
- (*pr->pr_drain)();
+ (*pr->pr_drain)(ifp);
}
/*
Index: sys/net/if.c
===================================================================
--- sys/net/if.c
+++ sys/net/if.c
@@ -1206,6 +1206,13 @@
finish_vnet_shutdown:
#endif
/*
+ * Make sure all re-assembly mbufs get freed. This prevents
+ * references to our network interface structure after detach
+ * through mb->rcvif .
+ */
+ mb_reclaim_from_all_domains(ifp);
+
+ /*
* We cannot hold the lock over dom_ifdetach calls as they might
* sleep, for example trying to drain a callout, thus open up the
* theoretical race with re-attaching.
Index: sys/netinet/ip_input.c
===================================================================
--- sys/netinet/ip_input.c
+++ sys/netinet/ip_input.c
@@ -93,7 +93,7 @@
/* IP reassembly functions are defined in ip_reass.c. */
extern void ipreass_init(void);
-extern void ipreass_drain(void);
+extern void ipreass_drain(struct ifnet *);
extern void ipreass_slowtimo(void);
#ifdef VIMAGE
extern void ipreass_destroy(void);
@@ -852,17 +852,24 @@
}
void
-ip_drain(void)
+ip_drain(struct ifnet *ifp)
{
- VNET_ITERATOR_DECL(vnet_iter);
- VNET_LIST_RLOCK_NOSLEEP();
- VNET_FOREACH(vnet_iter) {
- CURVNET_SET(vnet_iter);
- ipreass_drain();
+ if (ifp != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ ipreass_drain(ifp);
CURVNET_RESTORE();
+ } else {
+ VNET_ITERATOR_DECL(vnet_iter);
+
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ ipreass_drain(NULL);
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK_NOSLEEP();
}
- VNET_LIST_RUNLOCK_NOSLEEP();
}
/*
Index: sys/netinet/ip_reass.c
===================================================================
--- sys/netinet/ip_reass.c
+++ sys/netinet/ip_reass.c
@@ -88,7 +88,7 @@
#define V_ipreass_maxbucketsize VNET(ipreass_maxbucketsize)
void ipreass_init(void);
-void ipreass_drain(void);
+void ipreass_drain(struct ifnet *);
void ipreass_slowtimo(void);
#ifdef VIMAGE
void ipreass_destroy(void);
@@ -592,7 +592,7 @@
* Drain off all datagram fragments.
*/
void
-ipreass_drain(void)
+ipreass_drain(struct ifnet *ifp)
{
for (int i = 0; i < IPREASS_NHASH; i++) {
@@ -614,7 +614,7 @@
ipreass_destroy(void)
{
- ipreass_drain();
+ ipreass_drain(NULL);
uma_zdestroy(V_ipq_zone);
for (int i = 0; i < IPREASS_NHASH; i++)
mtx_destroy(&V_ipq[i].lock);
@@ -712,7 +712,7 @@
V_noreass = 0;
} else if (max == 0) {
V_noreass = 1;
- ipreass_drain();
+ ipreass_drain(NULL);
} else if (max == -1) {
V_noreass = 0;
uma_zone_set_max(V_ipq_zone, 0);
Index: sys/netinet/ip_var.h
===================================================================
--- sys/netinet/ip_var.h
+++ sys/netinet/ip_var.h
@@ -209,7 +209,7 @@
int inp_setmoptions(struct inpcb *, struct sockopt *);
int ip_ctloutput(struct socket *, struct sockopt *sopt);
-void ip_drain(void);
+void ip_drain(struct ifnet *);
int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
u_long if_hwassist_flags);
void ip_forward(struct mbuf *m, int srcrt);
Index: sys/netinet/sctp_pcb.h
===================================================================
--- sys/netinet/sctp_pcb.h
+++ sys/netinet/sctp_pcb.h
@@ -619,7 +619,7 @@
int sctp_is_vtag_good(uint32_t, uint16_t lport, uint16_t rport, struct timeval *);
-/* void sctp_drain(void); */
+/* void sctp_drain(struct ifnet *); */
int sctp_destination_is_reachable(struct sctp_tcb *, struct sockaddr *);
Index: sys/netinet/sctp_pcb.c
===================================================================
--- sys/netinet/sctp_pcb.c
+++ sys/netinet/sctp_pcb.c
@@ -7051,45 +7051,56 @@
*/
}
+static void
+sctp_drain_sub(struct ifnet *ifp)
+{
+ struct sctp_inpcb *inp;
+ struct sctp_tcb *stcb;
+
+ SCTP_STAT_INCR(sctps_protocol_drain_calls);
+
+ if (ifp == NULL &&
+ SCTP_BASE_SYSCTL(sctp_do_drain) == 0)
+ return;
+
+ SCTP_INP_INFO_RLOCK();
+ LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
+ /* For each endpoint */
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ /* For each association */
+ SCTP_TCB_LOCK(stcb);
+ sctp_drain_mbufs(stcb);
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ }
+ SCTP_INP_INFO_RUNLOCK();
+}
+
void
-sctp_drain()
+sctp_drain(struct ifnet *ifp)
{
- /*
- * We must walk the PCB lists for ALL associations here. The system
- * is LOW on MBUF's and needs help. This is where reneging will
- * occur. We really hope this does NOT happen!
- */
- VNET_ITERATOR_DECL(vnet_iter);
- VNET_LIST_RLOCK_NOSLEEP();
- VNET_FOREACH(vnet_iter) {
- CURVNET_SET(vnet_iter);
- struct sctp_inpcb *inp;
- struct sctp_tcb *stcb;
- SCTP_STAT_INCR(sctps_protocol_drain_calls);
- if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) {
-#ifdef VIMAGE
- continue;
-#else
- return;
-#endif
+ if (ifp != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ sctp_drain_sub(ifp);
+ CURVNET_RESTORE();
+ } else {
+ /*
+ * We must walk the PCB lists for ALL associations here. The system
+ * is LOW on MBUF's and needs help. This is where reneging will
+ * occur. We really hope this does NOT happen!
+ */
+ VNET_ITERATOR_DECL(vnet_iter);
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ sctp_drain_sub(ifp);
+ CURVNET_RESTORE();
}
- SCTP_INP_INFO_RLOCK();
- LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
- /* For each endpoint */
- SCTP_INP_RLOCK(inp);
- LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
- /* For each association */
- SCTP_TCB_LOCK(stcb);
- sctp_drain_mbufs(stcb);
- SCTP_TCB_UNLOCK(stcb);
- }
- SCTP_INP_RUNLOCK(inp);
- }
- SCTP_INP_INFO_RUNLOCK();
- CURVNET_RESTORE();
+ VNET_LIST_RUNLOCK_NOSLEEP();
}
- VNET_LIST_RUNLOCK_NOSLEEP();
}
/*
Index: sys/netinet/sctp_var.h
===================================================================
--- sys/netinet/sctp_var.h
+++ sys/netinet/sctp_var.h
@@ -339,7 +339,7 @@
int sctp_input(struct mbuf **, int *, int);
#endif
void sctp_pathmtu_adjustment(struct sctp_tcb *, uint16_t);
-void sctp_drain(void);
+void sctp_drain(struct ifnet *);
void sctp_init(void);
void
sctp_notify(struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *,
Index: sys/netinet/tcp_subr.c
===================================================================
--- sys/netinet/tcp_subr.c
+++ sys/netinet/tcp_subr.c
@@ -1994,20 +1994,12 @@
return (tp);
}
-void
-tcp_drain(void)
+static void
+tcp_drain_sub(struct ifnet *ifp)
{
- VNET_ITERATOR_DECL(vnet_iter);
+ struct inpcb *inpb;
+ struct tcpcb *tcpb;
- if (!do_tcpdrain)
- return;
-
- VNET_LIST_RLOCK_NOSLEEP();
- VNET_FOREACH(vnet_iter) {
- CURVNET_SET(vnet_iter);
- struct inpcb *inpb;
- struct tcpcb *tcpb;
-
/*
* Walk the tcpbs, if existing, and flush the reassembly queue,
* if there is one...
@@ -2016,33 +2008,55 @@
* where we're really low on mbufs, this is potentially
* useful.
*/
- INP_INFO_WLOCK(&V_tcbinfo);
- CK_LIST_FOREACH(inpb, V_tcbinfo.ipi_listhead, inp_list) {
- INP_WLOCK(inpb);
- if (inpb->inp_flags & INP_TIMEWAIT) {
- INP_WUNLOCK(inpb);
- continue;
- }
- if ((tcpb = intotcpcb(inpb)) != NULL) {
- tcp_reass_flush(tcpb);
- tcp_clean_sackreport(tcpb);
+
+ INP_INFO_WLOCK(&V_tcbinfo);
+ CK_LIST_FOREACH(inpb, V_tcbinfo.ipi_listhead, inp_list) {
+ INP_WLOCK(inpb);
+ if (inpb->inp_flags & INP_TIMEWAIT) {
+ INP_WUNLOCK(inpb);
+ continue;
+ }
+ if ((tcpb = intotcpcb(inpb)) != NULL) {
+ tcp_reass_flush(tcpb);
+ tcp_clean_sackreport(tcpb);
#ifdef TCP_BLACKBOX
- tcp_log_drain(tcpb);
+ tcp_log_drain(tcpb);
#endif
#ifdef TCPPCAP
- if (tcp_pcap_aggressive_free) {
- /* Free the TCP PCAP queues. */
- tcp_pcap_drain(&(tcpb->t_inpkts));
- tcp_pcap_drain(&(tcpb->t_outpkts));
- }
+ if (tcp_pcap_aggressive_free) {
+ /* Free the TCP PCAP queues. */
+ tcp_pcap_drain(&(tcpb->t_inpkts));
+ tcp_pcap_drain(&(tcpb->t_outpkts));
+ }
#endif
- }
- INP_WUNLOCK(inpb);
}
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_WUNLOCK(inpb);
+ }
+ INP_INFO_WUNLOCK(&V_tcbinfo);
+}
+
+void
+tcp_drain(struct ifnet *ifp)
+{
+
+ if (ifp != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ tcp_drain_sub(ifp);
CURVNET_RESTORE();
+ } else {
+ VNET_ITERATOR_DECL(vnet_iter);
+
+ if (do_tcpdrain == 0)
+ return;
+
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ tcp_drain_sub(NULL);
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK_NOSLEEP();
}
- VNET_LIST_RUNLOCK_NOSLEEP();
}
/*
Index: sys/netinet/tcp_var.h
===================================================================
--- sys/netinet/tcp_var.h
+++ sys/netinet/tcp_var.h
@@ -836,7 +836,7 @@
int tcp_ctloutput(struct socket *, struct sockopt *);
struct tcpcb *
tcp_drop(struct tcpcb *, int);
-void tcp_drain(void);
+void tcp_drain(struct ifnet *);
void tcp_init(void);
void tcp_fini(void *);
char *tcp_log_addrs(struct in_conninfo *, struct tcphdr *, void *,
Index: sys/netinet6/frag6.c
===================================================================
--- sys/netinet6/frag6.c
+++ sys/netinet6/frag6.c
@@ -911,33 +911,47 @@
VNET_LIST_RUNLOCK_NOSLEEP();
}
+static void
+frag6_drain_sub(struct ifnet *ifp)
+{
+ struct ip6q *head;
+ int i;
+
+ for (i = 0; i < IP6REASS_NHASH; i++) {
+ if (IP6Q_TRYLOCK(i) == 0)
+ continue;
+ head = IP6Q_HEAD(i);
+ while (head->ip6q_next != head) {
+ IP6STAT_INC(ip6s_fragdropped);
+ /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
+ frag6_freef(head->ip6q_next, i);
+ }
+ IP6Q_UNLOCK(i);
+ }
+}
+
/*
* Drain off all datagram fragments.
*/
void
-frag6_drain(void)
+frag6_drain(struct ifnet *ifp)
{
- VNET_ITERATOR_DECL(vnet_iter);
- struct ip6q *head;
- int i;
- VNET_LIST_RLOCK_NOSLEEP();
- VNET_FOREACH(vnet_iter) {
- CURVNET_SET(vnet_iter);
- for (i = 0; i < IP6REASS_NHASH; i++) {
- if (IP6Q_TRYLOCK(i) == 0)
- continue;
- head = IP6Q_HEAD(i);
- while (head->ip6q_next != head) {
- IP6STAT_INC(ip6s_fragdropped);
- /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
- frag6_freef(head->ip6q_next, i);
- }
- IP6Q_UNLOCK(i);
+ if (ifp != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ frag6_drain_sub(ifp);
+ CURVNET_RESTORE();
+ } else {
+ VNET_ITERATOR_DECL(vnet_iter);
+
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ frag6_drain_sub(NULL);
+ CURVNET_RESTORE();
}
- CURVNET_RESTORE();
+ VNET_LIST_RUNLOCK_NOSLEEP();
}
- VNET_LIST_RUNLOCK_NOSLEEP();
}
int
Index: sys/netinet6/ip6_var.h
===================================================================
--- sys/netinet6/ip6_var.h
+++ sys/netinet6/ip6_var.h
@@ -418,7 +418,7 @@
void frag6_init(void);
int frag6_input(struct mbuf **, int *, int);
void frag6_slowtimo(void);
-void frag6_drain(void);
+void frag6_drain(struct ifnet *);
void rip6_init(void);
int rip6_input(struct mbuf **, int *, int);
Index: sys/sys/mbuf.h
===================================================================
--- sys/sys/mbuf.h
+++ sys/sys/mbuf.h
@@ -615,6 +615,7 @@
void mb_dupcl(struct mbuf *, struct mbuf *);
void mb_free_ext(struct mbuf *);
+void mb_reclaim_from_all_domains(struct ifnet *);
void m_adj(struct mbuf *, int);
int m_apply(struct mbuf *, int, int,
int (*)(void *, void *, u_int), void *);
Index: sys/sys/protosw.h
===================================================================
--- sys/sys/protosw.h
+++ sys/sys/protosw.h
@@ -42,6 +42,7 @@
struct sockaddr;
struct socket;
struct sockopt;
+struct ifnet;
/*#ifdef _KERNEL*/
/*
@@ -74,7 +75,7 @@
typedef void pr_init_t (void);
typedef void pr_fasttimo_t (void);
typedef void pr_slowtimo_t (void);
-typedef void pr_drain_t (void);
+typedef void pr_drain_t (struct ifnet *);
struct protosw {
short pr_type; /* socket type used for */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 21, 4:35 PM (16 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15543345
Default Alt Text
D19622.id55319.diff (12 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