When detaching a network interface drain the workqueue freeing the inm's
because the destructor will access the if_ioctl() callback in the ifnet pointer which is about to be freed. This prevents use-after-free. PR: 233535 Differential Revision: https://reviews.freebsd.org/D18887 Reviewed by: bz (net) Tested by: ae MFC after: 1 week Sponsored by: Mellanox Technologies
This commit is contained in:
parent
7a02897647
commit
dea72f062a
@ -884,6 +884,13 @@ in6_purgemaddrs(struct ifnet *ifp)
|
||||
IN6_MULTI_LIST_UNLOCK();
|
||||
IN6_MULTI_UNLOCK();
|
||||
in6m_release_list_deferred(&purgeinms);
|
||||
|
||||
/*
|
||||
* Make sure all multicast deletions invoking if_ioctl() are
|
||||
* completed before returning. Else we risk accessing a freed
|
||||
* ifnet structure pointer.
|
||||
*/
|
||||
in6m_release_wait();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -584,6 +584,14 @@ in6m_release_list_deferred(struct in6_multi_head *inmh)
|
||||
GROUPTASK_ENQUEUE(&free_gtask);
|
||||
}
|
||||
|
||||
void
|
||||
in6m_release_wait(void)
|
||||
{
|
||||
|
||||
/* Wait for all jobs to complete. */
|
||||
gtaskqueue_drain_all(free_gtask.gt_taskqueue);
|
||||
}
|
||||
|
||||
void
|
||||
in6m_disconnect(struct in6_multi *inm)
|
||||
{
|
||||
|
@ -811,6 +811,7 @@ void in6m_print(const struct in6_multi *);
|
||||
int in6m_record_source(struct in6_multi *, const struct in6_addr *);
|
||||
void in6m_release_deferred(struct in6_multi *);
|
||||
void in6m_release_list_deferred(struct in6_multi_head *);
|
||||
void in6m_release_wait(void);
|
||||
void ip6_freemoptions(struct ip6_moptions *);
|
||||
int ip6_getmoptions(struct inpcb *, struct sockopt *);
|
||||
int ip6_setmoptions(struct inpcb *, struct sockopt *);
|
||||
|
Loading…
Reference in New Issue
Block a user