diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2017-08-04 14:00:34 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2017-08-04 14:00:34 +0000 |
commit | 3a9c60fdcb6d6401d3b8afc88f849569d49048b7 (patch) | |
tree | 0f004b2a399994d2c384e3dc56ad4deb59eaa501 /sbin | |
parent | c20203584f6cf613f6d00aac0a95e06c8c902574 (diff) |
When free(3)'ing an address_proposal we need to stop the libevent
timer.
Resulting use-after-free found the hard way by me.
Introduce free_address_proposal() to make sure we always do this.
While here also stop the interface timer when deleting an interface.
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/slaacd/engine.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/sbin/slaacd/engine.c b/sbin/slaacd/engine.c index 998f2fc631b..b9cb943e63f 100644 --- a/sbin/slaacd/engine.c +++ b/sbin/slaacd/engine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: engine.c,v 1.8 2017/07/17 11:27:05 florian Exp $ */ +/* $OpenBSD: engine.c,v 1.9 2017/08/04 14:00:33 florian Exp $ */ /* * Copyright (c) 2017 Florian Obser <florian@openbsd.org> @@ -230,6 +230,7 @@ void gen_addr(struct slaacd_iface *, struct radv_prefix *, struct address_proposal *, int); void gen_address_proposal(struct slaacd_iface *, struct radv *, struct radv_prefix *, int); +void free_address_proposal(struct address_proposal *); void configure_address(struct address_proposal *); void in6_prefixlen2mask(struct in6_addr *, int len); void gen_dfr_proposal(struct slaacd_iface *, struct @@ -510,8 +511,7 @@ engine_dispatch_frontend(int fd, short event, void *bula) if (addr_proposal) { /* XXX should we inform netcfgd? */ LIST_REMOVE(addr_proposal, entries); - evtimer_del(&addr_proposal->timer); - free(addr_proposal); + free_address_proposal(addr_proposal); } break; @@ -874,13 +874,14 @@ remove_slaacd_iface(uint32_t if_index) addr_proposal = LIST_FIRST(&iface->addr_proposals); LIST_REMOVE(addr_proposal, entries); - free(addr_proposal); + free_address_proposal(addr_proposal); } while(!LIST_EMPTY(&iface->dfr_proposals)) { dfr_proposal = LIST_FIRST(&iface->dfr_proposals); free_dfr_proposal(dfr_proposal); } + evtimer_del(&iface->timer); free(iface); break; } @@ -1771,6 +1772,16 @@ gen_address_proposal(struct slaacd_iface *iface, struct radv *ra, struct } void +free_address_proposal(struct address_proposal *addr_proposal) +{ + if (addr_proposal == NULL) + return; + + evtimer_del(&addr_proposal->timer); + free(addr_proposal); +} + +void gen_dfr_proposal(struct slaacd_iface *iface, struct radv *ra) { struct dfr_proposal *dfr_proposal; @@ -1958,8 +1969,7 @@ address_proposal_timeout(int fd, short events, void *arg) log_debug("%s: giving up, no response to proposal", __func__); LIST_REMOVE(addr_proposal, entries); - evtimer_del(&addr_proposal->timer); - free(addr_proposal); + free_address_proposal(addr_proposal); } break; case PROPOSAL_CONFIGURED: @@ -1987,7 +1997,7 @@ address_proposal_timeout(int fd, short events, void *arg) addr_proposal->vltime) == 0) { evtimer_del(&addr_proposal->timer); LIST_REMOVE(addr_proposal, entries); - free(addr_proposal); + free_address_proposal(addr_proposal); log_debug("%s: removing address proposal", __func__); break; } |