summaryrefslogtreecommitdiff
path: root/sys/net/if_trunk.c
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-06-15 15:55:09 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-06-15 15:55:09 +0000
commit739db261821a9f301dd2ae94064f20ababbafe6c (patch)
treeecb2cbd9568368130e2dd23e2eaf33b098046cac /sys/net/if_trunk.c
parent6ece26b0c5e55037adfc02db8e3815bf0fbdf2e9 (diff)
Fix a double free in the destroy path triggered when a second process,
in my case dhclient(8), races with ifconfig(8) to free the descriptors of the joined multicast groups. While here reduce the difference with carp(4). ok dms@
Diffstat (limited to 'sys/net/if_trunk.c')
-rw-r--r--sys/net/if_trunk.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/sys/net/if_trunk.c b/sys/net/if_trunk.c
index 32d23f258c5..5de66dd6e3e 100644
--- a/sys/net/if_trunk.c
+++ b/sys/net/if_trunk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_trunk.c,v 1.101 2015/06/09 14:50:14 mpi Exp $ */
+/* $OpenBSD: if_trunk.c,v 1.102 2015/06/15 15:55:08 mpi Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
@@ -857,18 +857,20 @@ trunk_ether_delmulti(struct trunk_softc *tr, struct ifreq *ifr)
if ((error = ether_delmulti(ifr, &tr->tr_ac)) != ENETRESET)
return (error);
- if ((error = trunk_ioctl_allports(tr, SIOCDELMULTI,
- (caddr_t)ifr)) != 0) {
+ /* We no longer use this multicast address. Tell parent so. */
+ error = trunk_ioctl_allports(tr, SIOCDELMULTI, (caddr_t)ifr);
+ if (error == 0) {
+ SLIST_REMOVE(&tr->tr_mc_head, mc, trunk_mc, mc_entries);
+ free(mc, M_DEVBUF, sizeof(*mc));
+ } else {
/* XXX At least one port failed to remove the address */
if (tr->tr_ifflags & IFF_DEBUG) {
printf("%s: failed to remove multicast address "
- "on all ports\n", tr->tr_ifname);
+ "on all ports (%d)\n", tr->tr_ifname, error);
}
+ (void)ether_addmulti(ifr, &tr->tr_ac);
}
- SLIST_REMOVE(&tr->tr_mc_head, mc, trunk_mc, mc_entries);
- free(mc, M_DEVBUF, 0);
-
return (0);
}
@@ -886,7 +888,7 @@ trunk_ether_purgemulti(struct trunk_softc *tr)
trunk_ioctl_allports(tr, SIOCDELMULTI, (caddr_t)ifr);
SLIST_REMOVE(&tr->tr_mc_head, mc, trunk_mc, mc_entries);
- free(mc, M_DEVBUF, 0);
+ free(mc, M_DEVBUF, sizeof(*mc));
}
}