From d2f05733699e37c557fccb79e6fced03aef82cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Wed, 29 Sep 2021 10:35:16 +0200 Subject: [PATCH] pipewire: module-zeroconf-discover: handle module destroy events module-zeroconf-discover loads module-pulse-tunnel for each entity exposed on the network. Previously, however, the destroy event of the loaded pulse-tunnel modules were not handled. This resulted in a use-after-free because both `pw_context_destroy()` and `module-zeroconf-discover.c:impl_free()` tried to destroy the pulse-tunnel modules. The reason for that is that since 1de16afc40b16f198a94e46ac6ad75949f2de81e the modules are prepended to the module list of the context, not appended, therefore modules are destroyed in LIFO order, thus the pulse-tunnel modules were destroyed before the zeroconf-discover module that loaded them. Fix that by handling the destroy event of the loaded pulse-tunnel modules. Fixes #1653 --- src/modules/module-zeroconf-discover.c | 30 ++++++++++++++++++++------ 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/modules/module-zeroconf-discover.c b/src/modules/module-zeroconf-discover.c index f828f477c..bd967cfd5 100644 --- a/src/modules/module-zeroconf-discover.c +++ b/src/modules/module-zeroconf-discover.c @@ -153,13 +153,7 @@ static struct tunnel *find_tunnel(struct impl *impl, const struct tunnel_info *i static void free_tunnel(struct tunnel *t) { - spa_list_remove(&t->link); - if (t->module) - pw_impl_module_destroy(t->module); - free((char*)t->info.name); - free((char*)t->info.type); - free((char*)t->info.domain); - free(t); + pw_impl_module_destroy(t->module); } static void impl_free(struct impl *impl) @@ -225,6 +219,25 @@ static void pw_properties_from_avahi_string(const char *key, const char *value, } } +static void submodule_destroy(void *data) +{ + struct tunnel *t = data; + + spa_list_remove(&t->link); + spa_hook_remove(&t->module_listener); + + free((char *) t->info.name); + free((char *) t->info.type); + free((char *) t->info.domain); + + free(t); +} + +static const struct pw_impl_module_events submodule_events = { + PW_VERSION_IMPL_MODULE_EVENTS, + .destroy = submodule_destroy, +}; + static void resolver_cb(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *a, uint16_t port, AvahiStringList *txt, @@ -342,6 +355,9 @@ static void resolver_cb(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiPr pw_impl_module_destroy(mod); goto done; } + + pw_impl_module_add_listener(mod, &t->module_listener, &submodule_events, t); + t->module = mod; done: