summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2007-07-04 12:15:53 +0000
committerclaudio <claudio@openbsd.org>2007-07-04 12:15:53 +0000
commit5b0dc0eb9f226ab65c61c52d0dafbab527e4e27a (patch)
tree147e000b9b331cafdc218bc6938e263955c0a48b
parentadd "cua" to the NAME section; (diff)
downloadwireguard-openbsd-5b0dc0eb9f226ab65c61c52d0dafbab527e4e27a.tar.xz
wireguard-openbsd-5b0dc0eb9f226ab65c61c52d0dafbab527e4e27a.zip
Fix a use after free crash in in_delmulti(). If a interface is detached
before it is removed from the multicast group in_delmulti() will try to access the no longer available ifp. We invalidate the ifa_ifp back pointer in the ifa in if_detach() now and use the ifa_ifp in in_delmulti() instead of the internal inm_ifp. By doing it this way we know if the interface was removed. This fixes a kernel panic triggered by ospfd and gif(4) tunnels. looks good henning@ reyk@
-rw-r--r--sys/net/if.c4
-rw-r--r--sys/netinet/in.c22
2 files changed, 16 insertions, 10 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index ffd9cb5e874..c1730c44073 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.163 2007/06/17 21:01:32 henning Exp $ */
+/* $OpenBSD: if.c,v 1.164 2007/07/04 12:15:53 claudio Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -580,6 +580,7 @@ do { \
if (ifa == ifnet_addrs[ifp->if_index])
continue;
+ ifa->ifa_ifp = NULL;
IFAFREE(ifa);
}
@@ -589,6 +590,7 @@ do { \
if_free_sadl(ifp);
+ ifnet_addrs[ifp->if_index]->ifa_ifp = NULL;
IFAFREE(ifnet_addrs[ifp->if_index]);
ifnet_addrs[ifp->if_index] = NULL;
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 453e7205167..59fb21f6b07 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.c,v 1.47 2007/05/27 20:04:25 dlg Exp $ */
+/* $OpenBSD: in.c,v 1.48 2007/07/04 12:15:53 claudio Exp $ */
/* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
/*
@@ -1012,6 +1012,7 @@ in_delmulti(inm)
struct in_multi *inm;
{
struct ifreq ifr;
+ struct ifnet *ifp;
int s = splsoftnet();
if (--inm->inm_refcount == 0) {
@@ -1024,15 +1025,18 @@ in_delmulti(inm)
* Unlink from list.
*/
LIST_REMOVE(inm, inm_list);
+ ifp = inm->inm_ia->ia_ifp;
IFAFREE(&inm->inm_ia->ia_ifa);
- /*
- * Notify the network driver to update its multicast reception
- * filter.
- */
- satosin(&ifr.ifr_addr)->sin_family = AF_INET;
- satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
- (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
- (caddr_t)&ifr);
+
+ if (ifp) {
+ /*
+ * Notify the network driver to update its multicast
+ * reception filter.
+ */
+ satosin(&ifr.ifr_addr)->sin_family = AF_INET;
+ satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
+ (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
+ }
free(inm, M_IPMADDR);
}
splx(s);