mips-openwrt-linux-uclibc-gcc 4.5.2 (Linaro GCC 4.5-2011.02-0), the default compiler for MIPS since r25708, miscompiles send_assoc_resp in hostapd's src/ap/ieee802_11.c. Specifically, the association ID (AID) field in the association response frame is set improperly. This gives a connected STA the wrong idea of what its AID is, causing it to consult the wrong bit in the traffic information map (TIM) when determining whether the AP has any data buffered for it. A STA with an aggressive power saving policy might not switch out of power saving mode until it has reason to transmit; this will cause delayed or dropped frame delivery to the STA.
IEEE 802.11-2007 7.3.1.8 says that the association ID (AID) is transmitted in a 16-bit field, of which the high-order 2 bits must be set to 1, and the low-order 14 bits are significant and represent the actual AID value. The code generation bug causes the low-order 8 bits of the field to always be set to 1. For example, AID 1 would normally be transmitted in an association response frame as 0x01 0xc0 (in little-endian byte order); this bug causes it to be transmitted as 0xff 0xc0. The STA would consult bit 255 instead of bit 1 in the TIM. Splitting the AID value out into its own temporary variable is enough to avoid the bad code generation. I only experienced a problem with the AID field, but chose to make the same change for the capability information field for good measure. I can provide annotated examples of code generation if anyone's interested. In addition to 4.5.2 (Linaro GCC 4.5-2011.02-0), I tested 4.3.3 (CodeSourcery), 4.4.5 (GCC), and mainline 4.5.2 (GCC). None of the other compilers miscompiled this code. Since this bug is restricted to Linaro GCC 4.5 targeting MIPS, and I doubt many others are targeting MIPS with this compiler, I'm not sending this patch upstream to hostapd at this point. Signed-off-by: Mark Mentovai <m...@moxienet.com> --- Index: package/hostapd/patches/001-mips_linaro_gcc45_codegen.patch =================================================================== --- package/hostapd/patches/001-mips_linaro_gcc45_codegen.patch (revision 0) +++ package/hostapd/patches/001-mips_linaro_gcc45_codegen.patch (revision 0) @@ -0,0 +1,18 @@ +--- a/src/ap/ieee802_11.c ++++ b/src/ap/ieee802_11.c +@@ -837,11 +837,11 @@ + + send_len = IEEE80211_HDRLEN; + send_len += sizeof(reply->u.assoc_resp); +- reply->u.assoc_resp.capab_info = +- host_to_le16(hostapd_own_capab_info(hapd, sta, 0)); ++ u16 capab_info = hostapd_own_capab_info(hapd, sta, 0); ++ reply->u.assoc_resp.capab_info = host_to_le16(capab_info); + reply->u.assoc_resp.status_code = host_to_le16(status_code); +- reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) +- | BIT(14) | BIT(15)); ++ u16 aid = sta ? sta->aid : 0; ++ reply->u.assoc_resp.aid = host_to_le16(aid | BIT(14) | BIT(15)); + /* Supported rates */ + p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable); + /* Extended supported rates */ _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel