This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository enlightenment.
View the commit online.
commit 3f68e2d824ba50f7c343eaed25bdd716c8157379
Author: [email protected] <[email protected]>
AuthorDate: Sun May 17 16:09:32 2026 -0600
fix(networkmanager): fix use-after-free in _device_free on wireless proxy teardown
The _device_free() function had a use-after-free bug triggered on every
Wi-Fi device shutdown: both dev->proxy (NM_IFACE_PROPS) and
dev->wireless_proxy (NM_IFACE_WIFI) are child proxies of a shared
Eldbus_Object. The old code called eldbus_object_unref() in the
wireless-proxy block, prematurely dropping the object's refcount to zero.
eldbus then ran _eldbus_object_clear, which freed all child proxies via
the object's _on_object_free callback — including dev->proxy. When
execution reached the dev->proxy block below, it dereferenced freed
memory, crashing with "Eina Magic Check Failed ... Input handle has
already been freed".
Fix: remove the erroneous eldbus_proxy_object_get/eldbus_object_unref
from the wireless block. The shared object's single reference (taken
once in _device_new) must be released exactly once, in the dev->proxy
block where it is retrieved and both proxies have finished their
cleanup. This way eldbus's _on_object_free cascade correctly frees the
wireless_proxy as a side-effect of dev->proxy teardown.
Verified under valgrind: crash signature and invalid reads gone; no
regressions on non-Wi-Fi path; full E shutdown clean on both paths.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
src/modules/networkmanager/e_networkmanager.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/modules/networkmanager/e_networkmanager.c b/src/modules/networkmanager/e_networkmanager.c
index 3fee61041..c36736c49 100644
--- a/src/modules/networkmanager/e_networkmanager.c
+++ b/src/modules/networkmanager/e_networkmanager.c
@@ -742,7 +742,6 @@ _device_free(struct NM_Device *dev)
if (dev->wireless_proxy)
{
- Eldbus_Object *wobj = eldbus_proxy_object_get(dev->wireless_proxy);
if (dev->ap_added_handler)
{
eldbus_signal_handler_del(dev->ap_added_handler);
@@ -753,8 +752,13 @@ _device_free(struct NM_Device *dev)
eldbus_signal_handler_del(dev->ap_removed_handler);
dev->ap_removed_handler = NULL;
}
+ /* wireless_proxy shares the same Eldbus_Object as dev->proxy.
+ * eldbus_proxy_get() does NOT increment the object's refcount, so
+ * proxy_unref here must NOT be paired with an object_unref — doing so
+ * would drop the object to refcount 0, triggering _eldbus_object_clear
+ * which frees dev->proxy via its _on_object_free callback, causing a
+ * use-after-free when the dev->proxy block below runs. */
eldbus_proxy_unref(dev->wireless_proxy);
- if (wobj) eldbus_object_unref(wobj);
}
if (dev->proxy)
@@ -764,6 +768,9 @@ _device_free(struct NM_Device *dev)
eldbus_signal_handler_del(dev->prop_changed_handler);
dev->prop_changed_handler = NULL;
}
+ /* The sole object ref belongs to this proxy (taken by eldbus_object_get
+ * in _device_new and never stored separately). Unref proxy first, then
+ * unref the object exactly once. */
obj = eldbus_proxy_object_get(dev->proxy);
eldbus_proxy_unref(dev->proxy);
eldbus_object_unref(obj);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.