hostapd: fix ucode memory leak with strings

This fixes a common reference counting bug typically along the lines of:
```
uc_value_push(ucv_get(ucv_string_new(...)));
```
This would leave our new string with a reference count of 2, one from
the construction of the string, the other from `ucv_get`. This would
prevent the strings from being correctly cleaned up when it goes out
of scope.

Signed-off-by: Matthew Cather <mattbob4@gmail.com>
This commit is contained in:
Matthew Cather 2025-03-03 13:22:11 -06:00 committed by Felix Fietkau
parent 90dee1ab30
commit f79968ee0f
3 changed files with 19 additions and 22 deletions

View File

@ -56,7 +56,7 @@ hostapd_ucode_update_bss_list(struct hostapd_iface *iface, uc_value_t *if_bss, u
struct hostapd_data *hapd = iface->bss[i]; struct hostapd_data *hapd = iface->bss[i];
uc_value_t *val = hostapd_ucode_bss_get_uval(hapd); uc_value_t *val = hostapd_ucode_bss_get_uval(hapd);
ucv_array_set(list, i, ucv_get(ucv_string_new(hapd->conf->iface))); ucv_array_set(list, i, ucv_string_new(hapd->conf->iface));
ucv_object_add(bss, hapd->conf->iface, ucv_get(val)); ucv_object_add(bss, hapd->conf->iface, ucv_get(val));
} }
ucv_object_add(if_bss, iface->phy, ucv_get(list)); ucv_object_add(if_bss, iface->phy, ucv_get(list));
@ -721,11 +721,10 @@ int hostapd_ucode_sta_auth(struct hostapd_data *hapd, struct sta_info *sta)
if (wpa_ucode_call_prepare("sta_auth")) if (wpa_ucode_call_prepare("sta_auth"))
return 0; return 0;
uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface))); uc_value_push(ucv_string_new(hapd->conf->iface));
snprintf(addr, sizeof(addr), MACSTR, MAC2STR(sta->addr)); snprintf(addr, sizeof(addr), MACSTR, MAC2STR(sta->addr));
val = ucv_string_new(addr); uc_value_push(ucv_string_new(addr));
uc_value_push(ucv_get(val));
val = wpa_ucode_call(2); val = wpa_ucode_call(2);
@ -787,16 +786,15 @@ void hostapd_ucode_sta_connected(struct hostapd_data *hapd, struct sta_info *sta
if (wpa_ucode_call_prepare("sta_connected")) if (wpa_ucode_call_prepare("sta_connected"))
return; return;
uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface))); uc_value_push(ucv_string_new(hapd->conf->iface));
snprintf(addr, sizeof(addr), MACSTR, MAC2STR(sta->addr)); snprintf(addr, sizeof(addr), MACSTR, MAC2STR(sta->addr));
val = ucv_string_new(addr); uc_value_push(ucv_string_new(addr));
uc_value_push(ucv_get(val));
val = ucv_object_new(vm); val = ucv_object_new(vm);
if (sta->psk_idx) if (sta->psk_idx)
ucv_object_add(val, "psk_idx", ucv_int64_new(sta->psk_idx - 1)); ucv_object_add(val, "psk_idx", ucv_int64_new(sta->psk_idx - 1));
uc_value_push(ucv_get(val)); uc_value_push(val);
val = wpa_ucode_call(3); val = wpa_ucode_call(3);
if (ucv_type(val) != UC_OBJECT) if (ucv_type(val) != UC_OBJECT)
@ -929,8 +927,8 @@ void hostapd_ucode_bss_cb(struct hostapd_data *hapd, const char *type)
return; return;
val = hostapd_ucode_bss_get_uval(hapd); val = hostapd_ucode_bss_get_uval(hapd);
uc_value_push(ucv_get(ucv_string_new(hapd->iface->phy))); uc_value_push(ucv_string_new(hapd->iface->phy));
uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface))); uc_value_push(ucv_string_new(hapd->conf->iface));
uc_value_push(ucv_get(val)); uc_value_push(ucv_get(val));
ucv_put(wpa_ucode_call(3)); ucv_put(wpa_ucode_call(3));
ucv_gc(vm); ucv_gc(vm);
@ -963,9 +961,9 @@ void hostapd_ucode_apup_newpeer(struct hostapd_data *hapd, const char *ifname)
return; return;
val = hostapd_ucode_bss_get_uval(hapd); val = hostapd_ucode_bss_get_uval(hapd);
uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface))); // BSS ifname uc_value_push(ucv_string_new(hapd->conf->iface)); // BSS ifname
uc_value_push(ucv_get(val)); uc_value_push(ucv_get(val));
uc_value_push(ucv_get(ucv_string_new(ifname))); // APuP peer ifname uc_value_push(ucv_string_new(ifname)); // APuP peer ifname
ucv_put(wpa_ucode_call(2)); ucv_put(wpa_ucode_call(2));
ucv_gc(vm); ucv_gc(vm);
} }

View File

@ -172,7 +172,7 @@ uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs)
ucv_object_add(ret, "op_class", ucv_int64_new(op_class)); ucv_object_add(ret, "op_class", ucv_int64_new(op_class));
ucv_object_add(ret, "channel", ucv_int64_new(channel)); ucv_object_add(ret, "channel", ucv_int64_new(channel));
ucv_object_add(ret, "hw_mode", ucv_int64_new(hw_mode)); ucv_object_add(ret, "hw_mode", ucv_int64_new(hw_mode));
ucv_object_add(ret, "hw_mode_str", ucv_get(ucv_string_new(modestr))); ucv_object_add(ret, "hw_mode_str", ucv_string_new(modestr));
ucv_object_add(ret, "sec_channel", ucv_int64_new(sec_channel)); ucv_object_add(ret, "sec_channel", ucv_int64_new(sec_channel));
ucv_object_add(ret, "frequency", ucv_int64_new(freq_val)); ucv_object_add(ret, "frequency", ucv_int64_new(freq_val));

View File

@ -49,7 +49,7 @@ void wpas_ucode_add_bss(struct wpa_supplicant *wpa_s)
if (wpa_ucode_call_prepare("iface_add")) if (wpa_ucode_call_prepare("iface_add"))
return; return;
uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname))); uc_value_push(ucv_string_new(wpa_s->ifname));
uc_value_push(ucv_get(wpas_ucode_iface_get_uval(wpa_s))); uc_value_push(ucv_get(wpas_ucode_iface_get_uval(wpa_s)));
ucv_put(wpa_ucode_call(2)); ucv_put(wpa_ucode_call(2));
ucv_gc(vm); ucv_gc(vm);
@ -67,7 +67,7 @@ void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s)
if (wpa_ucode_call_prepare("iface_remove")) if (wpa_ucode_call_prepare("iface_remove"))
return; return;
uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname))); uc_value_push(ucv_string_new(wpa_s->ifname));
uc_value_push(ucv_get(val)); uc_value_push(ucv_get(val));
ucv_put(wpa_ucode_call(2)); ucv_put(wpa_ucode_call(2));
ucv_gc(vm); ucv_gc(vm);
@ -86,9 +86,9 @@ void wpas_ucode_update_state(struct wpa_supplicant *wpa_s)
return; return;
state = wpa_supplicant_state_txt(wpa_s->wpa_state); state = wpa_supplicant_state_txt(wpa_s->wpa_state);
uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname))); uc_value_push(ucv_string_new(wpa_s->ifname));
uc_value_push(ucv_get(val)); uc_value_push(ucv_get(val));
uc_value_push(ucv_get(ucv_string_new(state))); uc_value_push(ucv_string_new(state));
ucv_put(wpa_ucode_call(3)); ucv_put(wpa_ucode_call(3));
ucv_gc(vm); ucv_gc(vm);
} }
@ -108,9 +108,9 @@ void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_d
if (wpa_ucode_call_prepare("event")) if (wpa_ucode_call_prepare("event"))
return; return;
uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname))); uc_value_push(ucv_string_new(wpa_s->ifname));
uc_value_push(ucv_get(val)); uc_value_push(ucv_get(val));
uc_value_push(ucv_get(ucv_string_new(event_to_string(event)))); uc_value_push(ucv_string_new(event_to_string(event)));
val = ucv_object_new(vm); val = ucv_object_new(vm);
uc_value_push(ucv_get(val)); uc_value_push(ucv_get(val));
@ -212,15 +212,14 @@ uc_wpas_iface_status(uc_vm_t *vm, size_t nargs)
{ {
struct wpa_supplicant *wpa_s = uc_fn_thisval("wpas.iface"); struct wpa_supplicant *wpa_s = uc_fn_thisval("wpas.iface");
struct wpa_bss *bss; struct wpa_bss *bss;
uc_value_t *ret, *val; uc_value_t *ret;
if (!wpa_s) if (!wpa_s)
return NULL; return NULL;
ret = ucv_object_new(vm); ret = ucv_object_new(vm);
val = ucv_string_new(wpa_supplicant_state_txt(wpa_s->wpa_state)); ucv_object_add(ret, "state", ucv_string_new(wpa_supplicant_state_txt(wpa_s->wpa_state)));
ucv_object_add(ret, "state", ucv_get(val));
bss = wpa_s->current_bss; bss = wpa_s->current_bss;
if (bss) { if (bss) {