wifi: nl80211: force WLAN_AKM_SUITE_SAE in big endian in NL80211_CMD_EXTERNAL_AUTH
authorAlexis Lothoré <alexis.lothore@bootlin.com>
Thu, 15 Feb 2024 14:13:52 +0000 (15:13 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 21 Feb 2024 14:19:05 +0000 (15:19 +0100)
User-space supplicant (observed at least on wpa_supplicant) historically
parses the NL80211_ATTR_AKM_SUITES from the NL80211_CMD_EXTERNAL_AUTH
message as big endian _only_ when its value is WLAN_AKM_SUITE_SAE, while
processing anything else in host endian. This behavior makes any driver
relying on SAE external auth to switch AKM suite to big endian if it is
WLAN_AKM_SUITE_SAE. A fix bringing compatibility with both endianness
has been brought into wpa_supplicant, however we must keep compatibility
with older versions, while trying to reduce the occurences of this manual
conversion in wireless drivers.

Add the be32 conversion specifically on WLAN_AKM_SUITE_SAE in nl80211 layer
to keep compatibility with older wpa_supplicant versions.

Suggested-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Alexis Lothoré <alexis.lothore@bootlin.com>
Link: https://msgid.link/20240215-nl80211_fix_akm_suites_endianness-v1-1-57e902632f9d@bootlin.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/wireless/nl80211.c

index dd9a092..ab6d98c 100644 (file)
@@ -20132,9 +20132,26 @@ int cfg80211_external_auth_request(struct net_device *dev,
        if (!hdr)
                goto nla_put_failure;
 
+       /* Some historical mistakes in drivers <-> userspace interface (notably
+        * between drivers and wpa_supplicant) led to a big-endian conversion
+        * being needed on NL80211_ATTR_AKM_SUITES _only_ when its value is
+        * WLAN_AKM_SUITE_SAE. This is now fixed on userspace side, but for the
+        * benefit of older wpa_supplicant versions, send this particular value
+        * in big-endian. Note that newer wpa_supplicant will also detect this
+        * particular value in big endian still, so it all continues to work.
+        */
+       if (params->key_mgmt_suite == WLAN_AKM_SUITE_SAE) {
+               if (nla_put_be32(msg, NL80211_ATTR_AKM_SUITES,
+                                cpu_to_be32(WLAN_AKM_SUITE_SAE)))
+                       goto nla_put_failure;
+       } else {
+               if (nla_put_u32(msg, NL80211_ATTR_AKM_SUITES,
+                               params->key_mgmt_suite))
+                       goto nla_put_failure;
+       }
+
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
-           nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
            nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
                        params->action) ||
            nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||