Repository navigation
fix: preserve WPA3 on Broadcom BCM4364 and Apple Silicon Macs #13024
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: quattro
Are you sure you want to change the base?
Changes from all commits
6c7353c
672e034
a1dc829
1d3ef55
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,35 +1,44 @@ | ||
| # Apple Macs ship Broadcom Wi-Fi driven by brcmfmac, whose firmware runs the WPA | ||
| # handshake itself. On these parts that offload fails against an access point in | ||
| # WPA2/WPA3 transition mode: the client associates, the four-way handshake never | ||
| # completes, and NetworkManager reports the password as wrong. | ||
| # Apple Macs ship Broadcom Wi-Fi driven by brcmfmac. On legacy pre-T2 parts | ||
| # (such as BCM43602 and BCM4350), the 2015-era firmware offload fails against | ||
| # access points in WPA2/WPA3 transition mode: the client associates, the | ||
| # four-way handshake never completes, and NetworkManager reports the password | ||
| # as wrong. wpa_supplicant 2.11 made it worse on every brcmfmac part by | ||
| # completing WPA state from the driver's authorization event, which broke | ||
| # WPA2-PSK and WPA3-SAE association outright. That change (hostap 41638606054a) | ||
| # is still in hostap 2.12 and main; what clears it here is Arch's downstream | ||
| # revert of it, 0008-Revert-Mark-authorization-completed-on-driver-indica.patch | ||
| # at the root of the wpa_supplicant packaging directory, taken from Fedora and | ||
| # first shipped in wpa_supplicant 2:2.12-1. | ||
| # A wpa_supplicant release that drops that patch brings the breakage back, and | ||
| # the T2 group below is where to notice it. | ||
| # | ||
| # feature_disable turns off the firmware supplicant (FWSUP, 0x2000) and firmware | ||
| # authenticator (FWAUTH, 0x80000), handing the handshake back to wpa_supplicant | ||
| # in software. | ||
| # Disabling the firmware supplicant (FWSUP, 0x2000) and SAE (0x80000) hands the | ||
| # WPA2 handshake back to wpa_supplicant in software. | ||
| # | ||
| # This quirk already shipped for T2 Macs, detected by the T2 PCI ID that every | ||
| # one of them carries. The bug is in the Broadcom firmware, not in the T2 bridge, | ||
| # so every Mac whose Wi-Fi brcmfmac drives needs it: a MacBookPro11,4 with | ||
| # BCM43602 and 2015 firmware fails exactly this way, and connects once the | ||
| # offload is disabled. | ||
| # This workaround MUST NOT be applied to modern Broadcom chips, which | ||
| # offload both the handshake and SAE and so lose WPA3-only support when it is | ||
| # applied: | ||
| # 1. BCM4364 (14e4:4464, in the T2 Macs and iMac19,x): disabling SAE offload | ||
| # prevents connecting to WPA3-only networks (#9802). | ||
| # 2. Apple Silicon (14e4:4425 / 4433): brcmfmac wedges completely with this | ||
| # quirk (#7439). | ||
| # | ||
| # The IDs are brcmfmac's own, from brcm_hw_ids.h: BCM43602 and its single-band | ||
| # variants in 2015-2017 Macs, BCM4350, BCM4355 and BCM4364 in the 2018-2019 | ||
| # machines including the T2-less iMac19,1 and iMac19,2, and BCM4377/4378/4387 | ||
| # from the T2 era on. The BCM4360 in 2013-2015 Macs is deliberately absent: it | ||
| # runs the out-of-tree wl driver, which never reads a brcmfmac option. | ||
| # Therefore, only apply to legacy pre-T2 Broadcom hardware with known-affected parts: | ||
| # BCM43602 (43ba, 43bb, 43bc) and BCM4350 (43a3). BCM4355 (43dc) and BCM4377 | ||
| # (4488) are deliberately absent: Linux documents both only on T2 Macs, which | ||
| # the T2 check below already excludes. | ||
| sys_vendor="$(cat /sys/class/dmi/id/sys_vendor 2>/dev/null || true)" | ||
|
|
||
| if lspci -nn | grep "106b:180[12]" >/dev/null || | ||
| { [[ $sys_vendor == Apple* ]] && | ||
| lspci -nn | grep -E "14e4:(43ba|43bb|43bc|43a3|43dc|4464|4488|4425|4433)" >/dev/null; }; then | ||
| echo "Detected a Mac with Broadcom Wi-Fi; running the WPA handshake in software" | ||
| if [[ $sys_vendor == Apple* ]] && | ||
| ! lspci -nn | grep "106b:180[12]" >/dev/null && | ||
| lspci -nn | grep -E "14e4:(43ba|43bb|43bc|43a3)" >/dev/null; then | ||
| echo "Detected a legacy Mac with Broadcom Wi-Fi; running the WPA handshake in software" | ||
|
|
||
| mkdir -p /etc/modprobe.d | ||
| cat > /etc/modprobe.d/brcmfmac.conf <<'EOF' | ||
| # Broadcom's firmware supplicant and authenticator fail the WPA four-way | ||
| # handshake on Apple hardware, which surfaces as a rejected password. Disable | ||
| # both so wpa_supplicant performs the handshake instead. | ||
| # Broadcom firmware on pre-T2 Macs fails the WPA four-way handshake on | ||
| # transition-mode networks. Disable firmware supplication and SAE so | ||
| # transition-mode networks use the software WPA2 handshake instead. | ||
| options brcmfmac feature_disable=0x82000 | ||
| EOF | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| echo "Restore WPA3 support on Broadcom BCM4364 and Apple Silicon Macs" | ||
|
|
||
| # Broadcom BCM4364 and Apple Silicon (BCM4378/4387) carry modern firmware and | ||
| # must not have SAE disabled by Omarchy's 0x82000 transition-mode quirk. The | ||
| # T2 Macs that never carried BCM4364 -- MacBook Air 13" Late 2018 / True Tone | ||
| # 2019 (BCM4355, 14e4:43dc) and MacBook Pro 13" Touch 2019 / 2020 and MacBook | ||
| # Air 13" Scissor 2020 (BCM4377, 14e4:4488) -- are excluded as a group, since | ||
| # the quirk is a wpa_supplicant workaround rather than a firmware one. Remove | ||
| # only the exact blocks written by the old T2 installer and the Broadcom | ||
| # supplicant setup, wherever they sit in the file. Administrator-authored | ||
| # variants remain untouched. | ||
| conf="${OMARCHY_BRCMFMAC_CONF:-/etc/modprobe.d/brcmfmac.conf}" | ||
|
|
||
| # Only run cleanup on Macs that carried the unneeded quirk: | ||
| # 1. T2 Macs (106b:180[12]) | ||
| # 2. BCM4364 Macs (14e4:4464) | ||
| # 3. Apple Silicon Macs (14e4:(4425|4433)) | ||
| if ! lspci -nn | grep -E "106b:180[12]|14e4:(4464|4425|4433)" >/dev/null; then | ||
| exit 0 | ||
| fi | ||
|
|
||
| [[ -f $conf ]] || exit 0 | ||
|
|
||
| # Read through sudo so a root-only file fails the migration and gets retried | ||
| # rather than reading as empty and burning the per-user migration marker. | ||
| content="$(sudo cat "$conf")" | ||
|
|
||
| legacy_block='# Fix for T2 MacBook WiFi connectivity issues | ||
| options brcmfmac feature_disable=0x82000' | ||
|
|
||
| current_block="# Broadcom's firmware supplicant and authenticator fail the WPA four-way | ||
| # handshake on Apple hardware, which surfaces as a rejected password. Disable | ||
| # both so wpa_supplicant performs the handshake instead. | ||
| options brcmfmac feature_disable=0x82000" | ||
|
|
||
| # Drop either owned block wherever it sits on whole-line boundaries, copying | ||
| # every other line through untouched. Matching line sequences literally (rather | ||
| # than as a shell pattern) keeps a reworded comment or an administrator-merged | ||
| # options line out of scope, and lets a block sandwiched between two user lines | ||
| # go the same way as a trailing one. | ||
| rest="$(printf '%s\n' "$content" | awk -v legacy="$legacy_block" -v current="$current_block" ' | ||
| BEGIN { | ||
| legacy_count = split(legacy, legacy_line, "\n") | ||
| current_count = split(current, current_line, "\n") | ||
| } | ||
| { line[NR] = $0 } | ||
| END { | ||
| i = 1 | ||
| while (i <= NR) { | ||
| if (owned(i, legacy_count, legacy_line)) count = legacy_count | ||
| else if (owned(i, current_count, current_line)) count = current_count | ||
| else count = 0 | ||
|
|
||
| if (count > 0) { | ||
| for (j = 0; j < count; j++) owned_line[i + j] = 1 | ||
| i += count | ||
| } else { | ||
| i++ | ||
| } | ||
| } | ||
|
|
||
| for (k = 1; k <= NR; k++) if (!(k in owned_line)) print line[k] | ||
| } | ||
| function owned(start, count, text, j) { | ||
| if (start + count - 1 > NR) return 0 | ||
| for (j = 0; j < count; j++) if (line[start + j] != text[j + 1]) return 0 | ||
| return 1 | ||
| } | ||
| ')" | ||
|
|
||
| # Both sides have their trailing newlines stripped by command substitution, so | ||
| # an untouched file compares equal to itself. Anything else means an owned block | ||
| # was removed. | ||
| [[ $rest != "$content" ]] || exit 0 | ||
|
|
||
| # Request the reboot before editing because brcmfmac reads module options only | ||
| # when it loads. Do not reload it during an update carried over Wi-Fi. | ||
| omarchy-state set reboot-required | ||
|
|
||
| if [[ -z $rest ]]; then | ||
| if [[ -L $conf ]]; then | ||
| : | sudo tee "$conf" >/dev/null | ||
| else | ||
| sudo rm -f "$conf" | ||
| fi | ||
| else | ||
| printf '%s\n' "$rest" | sudo tee "$conf" >/dev/null | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an owned block is removed, command substitution strips trailing newlines from the retained content, and this |
||
| fi | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When this migration removes an Omarchy block from a file that also contains administrator settings,
teetruncates the file before writing the remaining content. If the update is interrupted or the write fails, those settings can be lost or left incomplete. A later retry may no longer find a complete block to remove and can mark the migration finished. Write the replacement completely before changing the original, while retaining the tested symlink behavior.