From: Michael Bommarito <michael.bommarito@gmail.com>
To: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Cc: Johannes Berg <johannes.berg@intel.com>,
Emmanuel Grumbach <emmanuel.grumbach@intel.com>,
linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: [PATCH 4/4] wifi: iwlwifi: mld: clamp netdetect channel iteration to n_channels
Date: Fri, 15 May 2026 08:11:00 -0400 [thread overview]
Message-ID: <20260515121100.649334-5-michael.bommarito@gmail.com> (raw)
In-Reply-To: <20260515121100.649334-1-michael.bommarito@gmail.com>
iwl_mld_set_netdetect_info() walks the per-match matching_channels[]
bitmap and emits one center_freq per set bit by indexing
netdetect_cfg->channels[]:
for_each_set_bit(j,
(unsigned long *)&matches[i].matching_channels[0],
sizeof(matches[i].matching_channels)) {
match->channels[match->n_channels] =
netdetect_cfg->channels[j]->center_freq;
match->n_channels++;
}
Two problems here.
First, the third argument to for_each_set_bit(bit, addr, size) is
the number of BITS to walk, not bytes.
sizeof(matches[i].matching_channels) is
SCAN_OFFLOAD_MATCHING_CHANNELS_LEN = 7 BYTES, so the macro only
visits j = 0..6 and silently misses bits 7..55 of the 56-bit
bitmap. This is a functional defect (per-match channel reporting
is truncated to the first 7 entries of the bitmap).
Second, the loop body indexes netdetect_cfg->channels[j] without
bounding j against netdetect_cfg->n_channels. netdetect_cfg
->channels is a kmemdup()'ed array of pointers sized at exactly
n_channels entries (the user's WoWLAN net-detect channel list).
If n_channels < 7 (a 2.4 GHz only configuration, or a small saved-
SSID channel allowlist) and the firmware sets a match bit at any
position in [n_channels, 6], the indexed load reads past the end
of the allocation, and ->center_freq then dereferences whatever
that wild pointer fetched.
Reproduced under UML+KASAN via a KUnit harness that lifts the
iteration logic. With netdetect_cfg->channels sized at 5 entries
and matching_channels bit 5 set, the kernel panics on the wild
deref:
Kernel panic - not syncing: Segfault with no mm
RIP: 0033:mld_set_freqs_buggy.constprop.0+0x116/0x1c2
(The selector 0x0033 is UML's user-mode segment; under UML,
in-kernel code runs in ring 3 on the host. The trap is a
kernel-context page fault on the wild-pointer deref.)
Building drivers/net/wireless/intel/iwlwifi/mld/d3.o under
x86_64 allmodconfig with the fix applied yields no new warnings.
Rewrite the iteration as an explicit indexed loop with an upper
bound of min(bitmap-width-in-bits, n_channels). This addresses
both issues in one step: bits-correct iteration over the bitmap,
and a hard clamp against the channels-table length. Address the
two together because applying only the bits-correct iteration
without the clamp would widen the OOB exposure from j < 7 to
j < 56.
A short comment is added because the clamp's purpose (avoiding an
OOB pointer fetch from netdetect_cfg->channels) is not obvious
from the expression alone, and a future reader could otherwise
"simplify" the bound back to the underlying constant.
Cc: stable@vger.kernel.org
Fixes: d1e879ec600f ("wifi: iwlwifi: add iwlmld sub-driver")
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Assisted-by: Claude:claude-opus-4-7
---
drivers/net/wireless/intel/iwlwifi/mld/d3.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c
index e89ec531cb06..51abf414bb1e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c
@@ -1165,7 +1165,7 @@ iwl_mld_set_netdetect_info(struct iwl_mld *mld,
for_each_set_bit(i, &matched_profiles, netdetect_cfg->n_match_sets) {
struct cfg80211_wowlan_nd_match *match;
- int idx, j, n_channels = 0;
+ int idx, j, max, n_channels = 0;
struct iwl_scan_offload_profile_match *matches =
(void *)netdetect_res->matches;
@@ -1192,9 +1192,19 @@ iwl_mld_set_netdetect_info(struct iwl_mld *mld,
if (netdetect_cfg->n_channels < n_channels)
continue;
- for_each_set_bit(j,
- (unsigned long *)&matches[i].matching_channels[0],
- sizeof(matches[i].matching_channels)) {
+ /* Clamp bit-index iteration to the channels table length:
+ * a firmware-set bit past n_channels would otherwise index
+ * past the kmemdup'd netdetect_cfg->channels[] allocation.
+ */
+ max = min_t(int, BITS_PER_BYTE *
+ sizeof(matches[i].matching_channels),
+ netdetect_cfg->n_channels);
+
+ for (j = 0; j < max; j++) {
+ if (!(matches[i].matching_channels[j / BITS_PER_BYTE] &
+ BIT(j % BITS_PER_BYTE)))
+ continue;
+
match->channels[match->n_channels] =
netdetect_cfg->channels[j]->center_freq;
match->n_channels++;
--
2.53.0
prev parent reply other threads:[~2026-05-15 12:12 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-15 12:10 [PATCH 0/4] wifi: iwlwifi: harden netdetect resume-path parsing against firmware-controlled inputs (mvm + mld) Michael Bommarito
2026-05-15 12:10 ` [PATCH 1/4] wifi: iwlwifi: mvm: include matches_len in scan-offload-query length check Michael Bommarito
2026-05-15 12:10 ` [PATCH 2/4] wifi: iwlwifi: mvm: clamp set_freqs iteration to n_nd_channels Michael Bommarito
2026-05-15 12:10 ` [PATCH 3/4] wifi: iwlwifi: mld: include matches tail in match-info length check Michael Bommarito
2026-05-15 12:11 ` Michael Bommarito [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260515121100.649334-5-michael.bommarito@gmail.com \
--to=michael.bommarito@gmail.com \
--cc=emmanuel.grumbach@intel.com \
--cc=johannes.berg@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=miriam.rachel.korenblit@intel.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox