summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in.c
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2010-10-16 19:53:22 +0000
committerbz <bz@FreeBSD.org>2010-10-16 19:53:22 +0000
commitafcba250aaa205745643b19446da3a6dfd095ef1 (patch)
tree0afa2fe149a99043aec110c7115822acb7ffe0c4 /sys/netinet/in.c
parentdb6298744f50e2e1d33a908bc0369ca9ace6924a (diff)
downloadFreeBSD-src-afcba250aaa205745643b19446da3a6dfd095ef1.zip
FreeBSD-src-afcba250aaa205745643b19446da3a6dfd095ef1.tar.gz
MfP4 CH182763 (original version):
Make it harder to exploit certain in_control() related races between the intiial lookup at the beginning and the time we will remove the entry from the lists by re-checking that entry is still in the list before trying to remove it. (*) It is believed that with the current code and locking strategy we cannot completely fix all race. Reported by: Nima Misaghian (nima_misa hotmail.com) on net@ 20100817 Tested by: Nima Misaghian (nima_misa hotmail.com) (original version) PR: kern/146250 Submitted by: Mikolaj Golub (to.my.trociny gmail.com) (different version) MFC after: 1 week
Diffstat (limited to 'sys/netinet/in.c')
-rw-r--r--sys/netinet/in.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index aded2c6..b2ae8d9 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -599,6 +599,21 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
}
IF_ADDR_LOCK(ifp);
+ /* Re-check that ia is still part of the list. */
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (ifa == &ia->ia_ifa)
+ break;
+ }
+ if (ifa == NULL) {
+ /*
+ * If we lost the race with another thread, there is no need to
+ * try it again for the next loop as there is no other exit
+ * path between here and out.
+ */
+ IF_ADDR_UNLOCK(ifp);
+ error = EADDRNOTAVAIL;
+ goto out;
+ }
TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
IF_ADDR_UNLOCK(ifp);
ifa_free(&ia->ia_ifa); /* if_addrhead */
OpenPOWER on IntegriCloud