diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-06-15 15:55:09 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-06-15 15:55:09 +0000 |
commit | 739db261821a9f301dd2ae94064f20ababbafe6c (patch) | |
tree | ecb2cbd9568368130e2dd23e2eaf33b098046cac /sys/net/if_trunk.c | |
parent | 6ece26b0c5e55037adfc02db8e3815bf0fbdf2e9 (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.c | 18 |
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)); } } |