From 11b21c8fd90a5124ddc2cd84d4e4ca7abc2dc12e Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Wed, 29 Apr 2026 12:55:27 +0700 Subject: [PATCH] network: capture manager (not Iwd_Network) in reply context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a Connect or Forget reply arrives after the Iwd_Network was freed (network disappeared from a scan, iwd vanished mid-call), the callback would dereference ctx->n->manager — use-after-free. The manager outlives every sub-object, so capture it directly along with a strdup'd SSID; the network back-ref isn't actually used for anything else. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/iwd/iwd_network.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/iwd/iwd_network.c b/src/iwd/iwd_network.c index 29da8cd..de83d92 100644 --- a/src/iwd/iwd_network.c +++ b/src/iwd/iwd_network.c @@ -79,9 +79,12 @@ iwd_network_free(Iwd_Network *n) free(n); } +/* Reply context captures the *manager* (which outlives all sub-objects) and + * a strdup'd SSID, never the Iwd_Network — the network may disappear from + * the next scan before iwd's reply lands, and a raw back-ref would UAF. */ typedef struct { - Iwd_Network *n; + Iwd_Manager *m; char *ssid; } _Net_Reply_Ctx; @@ -90,8 +93,8 @@ _on_connect_reply(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_ { _Net_Reply_Ctx *ctx = data; const char *en, *em; - if (eldbus_message_error_get(msg, &en, &em) && ctx->n->manager) - iwd_manager_report_error(ctx->n->manager, + if (eldbus_message_error_get(msg, &en, &em) && ctx->m) + iwd_manager_report_error(ctx->m, "Connect to '%s' failed: %s", ctx->ssid ? ctx->ssid : "?", em ? em : en); free(ctx->ssid); @@ -103,8 +106,8 @@ _on_forget_reply(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_U { _Net_Reply_Ctx *ctx = data; const char *en, *em; - if (eldbus_message_error_get(msg, &en, &em) && ctx->n->manager) - iwd_manager_report_error(ctx->n->manager, + if (eldbus_message_error_get(msg, &en, &em) && ctx->m) + iwd_manager_report_error(ctx->m, "Forget '%s' failed: %s", ctx->ssid ? ctx->ssid : "?", em ? em : en); free(ctx->ssid); @@ -129,7 +132,7 @@ _reply_ctx_new(Iwd_Network *n) { _Net_Reply_Ctx *ctx = calloc(1, sizeof(*ctx)); if (!ctx) return NULL; - ctx->n = n; + ctx->m = n->manager; ctx->ssid = n->ssid ? strdup(n->ssid) : NULL; return ctx; }