Skip to content

Fix VIF WCID collision, unchecked MCU returns, and firmware validation overflow in mt76x02/mt76x2#12

Merged
HiGarfield merged 3 commits intomasterfrom
copilot/fix-mt7603-mt7602-mt7612-bugs
Mar 31, 2026
Merged

Fix VIF WCID collision, unchecked MCU returns, and firmware validation overflow in mt76x02/mt76x2#12
HiGarfield merged 3 commits intomasterfrom
copilot/fix-mt7603-mt7602-mt7612-bugs

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

Comprehensive bug audit of mt7603/mt76x02/mt76x2 driver code. Six bugs fixed across four files.

VIF WCID collision (mt76x02_mac.h)

MT_VIF_WCID used & 7 mask, causing station VIFs (idx 8–15) to collide with AP VIFs (idx 0–7):

// Before: idx 0 and idx 8 both map to WCID 254
#define MT_VIF_WCID(_n)  (254 - ((_n) & 7))
#define MT_MAX_VIFS      8

// After: all 16 indices map to unique WCIDs (239–254)
#define MT_VIF_WCID(_n)  (254 - ((_n) & 0xf))
#define MT_MAX_VIFS      16

Unchecked MCU return values

  • mt76x2_mcu_set_channel() — first mt76_mcu_send_msg() result was silently discarded; failure in the initial channel switch was masked
  • mt76x2_mcu_init()mt76x02_mcu_function_select() result was ignored

Integer overflow in firmware size validation (pci_mcu.c, usb_mcu.c)

Both PCI and USB firmware loaders accumulated sizes into int len via sizeof(*hdr) + ilm_len + dlm_len, which overflows on 32-bit when fed crafted firmware. Replaced with overflow-safe sequential subtraction against fw->size using u32 types, along with INT_MAX bounds checks (since downstream copy APIs take int len / int data_len) and 4-byte alignment validation for PCI (since mt76_mmio_write_copy uses ALIGN(len, 4) which can read past the firmware buffer):

// Before: overflows if ilm_len + dlm_len wraps
int len = sizeof(*hdr) + ilm_len + dlm_len;
if (fw->size != len) goto error;

// After (PCI): bounds, alignment, and size checks on untrusted values
if (ilm_len > INT_MAX || dlm_len > INT_MAX ||
    (ilm_len | dlm_len) & 3 ||
    ilm_len > fw->size - sizeof(*hdr) ||
    dlm_len != fw->size - sizeof(*hdr) - ilm_len)
    goto error;

// After (USB): bounds and size checks on untrusted values
if (ilm_len > INT_MAX || dlm_len > INT_MAX ||
    ilm_len > fw->size - sizeof(*hdr) ||
    dlm_len != fw->size - sizeof(*hdr) - ilm_len)
    goto error;

…turns, firmware validation overflow

Agent-Logs-Url: https://github.com/HiGarfield/mt76/sessions/c3ba98dd-c66d-4a8f-83b4-d405222de6f8

Co-authored-by: HiGarfield <32226909+HiGarfield@users.noreply.github.com>
@HiGarfield HiGarfield marked this pull request as ready for review March 31, 2026 16:11
Copilot AI review requested due to automatic review settings March 31, 2026 16:11
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes multiple robustness and correctness issues in the mt76x02/mt76x2 WiFi driver family, covering VIF WCID allocation, MCU error propagation, and firmware image validation.

Changes:

  • Prevent VIF WCID collisions by expanding MT_VIF_WCID() masking and increasing MT_MAX_VIFS to 16.
  • Propagate previously ignored MCU command failures in mt76x2_mcu_set_channel() and mt76x2_mcu_init().
  • Make USB/PCI firmware length validation overflow-safe by avoiding unchecked additive length computations.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
mt76x2/usb_mcu.c Hardens USB firmware size validation against integer overflow.
mt76x2/pci_mcu.c Hardens PCI firmware size validation; propagates MCU function-select failure; uses validated segment lengths for copying.
mt76x2/mcu.c Returns early when initial channel-switch MCU message fails.
mt76x02_mac.h Expands VIF WCID mapping and maximum VIF count to cover indices 0–15 uniquely.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +99 to +103
ilm_len = le32_to_cpu(hdr->ilm_len);
dlm_len = le32_to_cpu(hdr->dlm_len);

if (fw->size != len)
if (ilm_len > fw->size - sizeof(*hdr) ||
dlm_len != fw->size - sizeof(*hdr) - ilm_len)
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The firmware header length fields are still not validated for 4-byte alignment or for fitting into the int len that mt76_wr_copy() ultimately takes. If dlm_len is not a multiple of 4, mt76_mmio_write_copy() will read up to ALIGN(dlm_len, 4) bytes and can read past the end of the firmware buffer; additionally cur += ilm_len / sizeof(*cur) becomes incorrect when ilm_len is not 4-byte aligned. Please reject firmware where ilm_len/dlm_len are not 4-byte aligned and where either length exceeds INT_MAX (or the bus copy API is updated to take size_t).

Copilot uses AI. Check for mistakes.
Comment on lines 161 to 167
hdr = (const struct mt76x02_fw_header *)fw->data;
ilm_len = le32_to_cpu(hdr->ilm_len);
dlm_len = le32_to_cpu(hdr->dlm_len);
len = sizeof(*hdr) + ilm_len + dlm_len;
if (fw->size != len) {

if (ilm_len > fw->size - sizeof(*hdr) ||
dlm_len != fw->size - sizeof(*hdr) - ilm_len) {
err = -EINVAL;
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mt76x02u_mcu_fw_send_data() takes an int data_len, but ilm_len/dlm_len are now u32 from an untrusted firmware header. Even with the total-size check, values > INT_MAX will truncate when passed as int, potentially turning into negative/short lengths and causing incorrect behavior. Please add explicit bounds checks that both lengths are <= INT_MAX before calling the upload helper (or change the helper signature to size_t).

Copilot uses AI. Check for mistakes.
@HiGarfield
Copy link
Copy Markdown
Owner

@copilot apply changes based on the comments in this thread

Copilot AI and others added 2 commits March 31, 2026 16:43
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

@copilot apply changes based on the comments in this thread

Applied both review changes in commits df6dad5 and 3b23a2a:

  • pci_mcu.c: Added 4-byte alignment check (ilm_len | dlm_len) & 3 to reject unaligned firmware segments (prevents mt76_mmio_write_copy reading past buffer via ALIGN(len, 4)), plus INT_MAX bounds checks since mt76_mmio_write_copy takes int len.
  • usb_mcu.c: Added INT_MAX bounds checks for ilm_len/dlm_len since mt76x02u_mcu_fw_send_data() takes int data_len.

Copilot AI requested a review from HiGarfield March 31, 2026 16:47
@HiGarfield
Copy link
Copy Markdown
Owner

@copilot apply changes based on the comments in this thread

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

@copilot apply changes based on the comments in this thread

These changes are already applied in commits df6dad5 and 3b23a2a:

  • pci_mcu.c: INT_MAX bounds checks + 4-byte alignment check (ilm_len | dlm_len) & 3 + overflow-safe size validation
  • usb_mcu.c: INT_MAX bounds checks + overflow-safe size validation

@HiGarfield HiGarfield merged commit 9228f3e into master Mar 31, 2026
1 check passed
@HiGarfield HiGarfield deleted the copilot/fix-mt7603-mt7602-mt7612-bugs branch March 31, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants