popup: resolve connect/forget targets by netpath at click time
The row click handlers held a raw Iwd_Network * captured at paint time. If iwd vanished (name-owner change clears the network hash via _on_name_vanished) between paint and click, the struct was freed and the callback dereferenced it. Mirror the pattern already used for the forget-confirmation dialog: stash a strdup'd object path on the button, free it via EVAS_CALLBACK_DEL when the row is destroyed, and re-resolve through the live hash at click time. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d467231321
commit
20945c6329
1 changed files with 32 additions and 5 deletions
|
|
@ -117,12 +117,23 @@ _active_device(void)
|
||||||
|
|
||||||
/* ----- list rendering -------------------------------------------------- */
|
/* ----- list rendering -------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Click data is a strdup'd object path, freed via the row's EVAS_CALLBACK_DEL.
|
||||||
|
* Holding the Iwd_Network * directly would UAF if iwd vanished (its hash is
|
||||||
|
* cleared in _on_name_vanished) between row paint and click. */
|
||||||
|
static void
|
||||||
|
_row_path_free(void *data, Evas *e EINA_UNUSED,
|
||||||
|
Evas_Object *o EINA_UNUSED, void *ev EINA_UNUSED)
|
||||||
|
{ free(data); }
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_on_net_clicked(void *data, Evas_Object *obj EINA_UNUSED, void *ev EINA_UNUSED)
|
_on_net_clicked(void *data, Evas_Object *obj EINA_UNUSED, void *ev EINA_UNUSED)
|
||||||
{
|
{
|
||||||
Iwd_Network *n = data;
|
const char *netpath = data;
|
||||||
|
if (!netpath || !e_iwd || !e_iwd->manager) return;
|
||||||
|
const Eina_Hash *h = iwd_manager_networks(e_iwd->manager);
|
||||||
|
Iwd_Network *n = h ? eina_hash_find(h, netpath) : NULL;
|
||||||
if (!n) return;
|
if (!n) return;
|
||||||
if (e_iwd && e_iwd->manager) iwd_manager_clear_error(e_iwd->manager);
|
iwd_manager_clear_error(e_iwd->manager);
|
||||||
iwd_network_connect(n);
|
iwd_network_connect(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,7 +167,10 @@ static void _forget_confirm_no(void *data EINA_UNUSED, Evas_Object *obj, void *e
|
||||||
static void
|
static void
|
||||||
_on_net_forget(void *data, Evas_Object *obj EINA_UNUSED, void *ev EINA_UNUSED)
|
_on_net_forget(void *data, Evas_Object *obj EINA_UNUSED, void *ev EINA_UNUSED)
|
||||||
{
|
{
|
||||||
Iwd_Network *n = data;
|
const char *netpath = data;
|
||||||
|
if (!netpath || !e_iwd || !e_iwd->manager) return;
|
||||||
|
const Eina_Hash *h = iwd_manager_networks(e_iwd->manager);
|
||||||
|
Iwd_Network *n = h ? eina_hash_find(h, netpath) : NULL;
|
||||||
if (!n) return;
|
if (!n) return;
|
||||||
|
|
||||||
/* Forget destroys the saved passphrase irreversibly — confirm first.
|
/* Forget destroys the saved passphrase irreversibly — confirm first.
|
||||||
|
|
@ -264,7 +278,16 @@ _rebuild_list(Popup *p)
|
||||||
elm_object_access_info_set(btn, access);
|
elm_object_access_info_set(btn, access);
|
||||||
evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0);
|
evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0);
|
||||||
evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, 0);
|
evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, 0);
|
||||||
evas_object_smart_callback_add(btn, "clicked", _on_net_clicked, n);
|
/* Pass a copy of the object path, not the Iwd_Network *: the network
|
||||||
|
* may disappear (iwd_dbus name-vanished, scan refresh) before the
|
||||||
|
* user clicks, freeing the struct. The path is re-resolved through
|
||||||
|
* the live hash at click time. The buffer is freed via the button's
|
||||||
|
* EVAS_CALLBACK_DEL when the row is rebuilt or popup torn down. */
|
||||||
|
char *click_path = n->path ? strdup(n->path) : NULL;
|
||||||
|
if (click_path)
|
||||||
|
evas_object_event_callback_add(btn, EVAS_CALLBACK_DEL,
|
||||||
|
_row_path_free, click_path);
|
||||||
|
evas_object_smart_callback_add(btn, "clicked", _on_net_clicked, click_path);
|
||||||
elm_box_pack_end(row, btn);
|
elm_box_pack_end(row, btn);
|
||||||
evas_object_show(btn);
|
evas_object_show(btn);
|
||||||
|
|
||||||
|
|
@ -276,7 +299,11 @@ _rebuild_list(Popup *p)
|
||||||
char facc[128];
|
char facc[128];
|
||||||
snprintf(facc, sizeof(facc), "Forget %s", raw_ssid);
|
snprintf(facc, sizeof(facc), "Forget %s", raw_ssid);
|
||||||
elm_object_access_info_set(fb, facc);
|
elm_object_access_info_set(fb, facc);
|
||||||
evas_object_smart_callback_add(fb, "clicked", _on_net_forget, n);
|
char *forget_path = n->path ? strdup(n->path) : NULL;
|
||||||
|
if (forget_path)
|
||||||
|
evas_object_event_callback_add(fb, EVAS_CALLBACK_DEL,
|
||||||
|
_row_path_free, forget_path);
|
||||||
|
evas_object_smart_callback_add(fb, "clicked", _on_net_forget, forget_path);
|
||||||
elm_box_pack_end(row, fb);
|
elm_box_pack_end(row, fb);
|
||||||
evas_object_show(fb);
|
evas_object_show(fb);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue