network: capture manager (not Iwd_Network) in reply context

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) <noreply@anthropic.com>
This commit is contained in:
nemunaire 2026-04-29 12:55:27 +07:00
commit 11b21c8fd9

View file

@ -79,9 +79,12 @@ iwd_network_free(Iwd_Network *n)
free(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 typedef struct
{ {
Iwd_Network *n; Iwd_Manager *m;
char *ssid; char *ssid;
} _Net_Reply_Ctx; } _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; _Net_Reply_Ctx *ctx = data;
const char *en, *em; const char *en, *em;
if (eldbus_message_error_get(msg, &en, &em) && ctx->n->manager) if (eldbus_message_error_get(msg, &en, &em) && ctx->m)
iwd_manager_report_error(ctx->n->manager, iwd_manager_report_error(ctx->m,
"Connect to '%s' failed: %s", "Connect to '%s' failed: %s",
ctx->ssid ? ctx->ssid : "?", em ? em : en); ctx->ssid ? ctx->ssid : "?", em ? em : en);
free(ctx->ssid); 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; _Net_Reply_Ctx *ctx = data;
const char *en, *em; const char *en, *em;
if (eldbus_message_error_get(msg, &en, &em) && ctx->n->manager) if (eldbus_message_error_get(msg, &en, &em) && ctx->m)
iwd_manager_report_error(ctx->n->manager, iwd_manager_report_error(ctx->m,
"Forget '%s' failed: %s", "Forget '%s' failed: %s",
ctx->ssid ? ctx->ssid : "?", em ? em : en); ctx->ssid ? ctx->ssid : "?", em ? em : en);
free(ctx->ssid); free(ctx->ssid);
@ -129,7 +132,7 @@ _reply_ctx_new(Iwd_Network *n)
{ {
_Net_Reply_Ctx *ctx = calloc(1, sizeof(*ctx)); _Net_Reply_Ctx *ctx = calloc(1, sizeof(*ctx));
if (!ctx) return NULL; if (!ctx) return NULL;
ctx->n = n; ctx->m = n->manager;
ctx->ssid = n->ssid ? strdup(n->ssid) : NULL; ctx->ssid = n->ssid ? strdup(n->ssid) : NULL;
return ctx; return ctx;
} }