mac80211.sh: fix deadlock on configuring multiple PHYs simultaneously
authorFelix Fietkau <nbd@nbd.name>
Sun, 22 Oct 2023 16:00:08 +0000 (18:00 +0200)
committerFelix Fietkau <nbd@nbd.name>
Thu, 11 Jan 2024 09:40:43 +0000 (10:40 +0100)
When hitting a timing window where ubus configuration calls are hitting hostapd
and wpa_supplicant simultaneously, they can deadlock waiting for each other.
Fix this by using a lock around the ubus calls.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh

index 6ff627b03813bb2de0cd1f465014cc74031106a3..6572999fbc82526f590b0f1e3928f4a8f0a02ca6 100644 (file)
@@ -19,6 +19,10 @@ wdev_tool() {
        ucode /usr/share/hostap/wdev.uc "$@"
 }
 
+ubus_call() {
+       flock /var/run/hostapd.lock ubus call "$@"
+}
+
 drv_mac80211_init_device_config() {
        hostapd_common_add_device_config
 
@@ -903,7 +907,7 @@ wpa_supplicant_set_config() {
                ubus wait_for wpa_supplicant
        }
 
-       local supplicant_res="$(ubus call wpa_supplicant config_set "$data")"
+       local supplicant_res="$(ubus_call wpa_supplicant config_set "$data")"
        ret="$?"
        [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED
 
@@ -913,12 +917,12 @@ wpa_supplicant_set_config() {
 
 hostapd_set_config() {
        [ -n "$hostapd_ctrl" ] || {
-               ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null
+               ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null
                return 0;
        }
 
        ubus wait_for hostapd
-       local hostapd_res="$(ubus call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")"
+       local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")"
        ret="$?"
        [ "$ret" != 0 -o -z "$hostapd_res" ] && {
                wireless_setup_failed HOSTAPD_START_FAILED
@@ -933,7 +937,7 @@ wpa_supplicant_start() {
 
        [ -n "$wpa_supp_init" ] || return 0
 
-       ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null
+       ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null
 }
 
 mac80211_setup_supplicant() {
@@ -1041,8 +1045,8 @@ mac80211_reset_config() {
        local phy="$1"
 
        hostapd_conf_file="/var/run/hostapd-$phy.conf"
-       ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null
-       ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null
+       ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null
+       ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null
        wdev_tool "$phy" set_config '{}'
 }