Linux kernel -stable discussions
 help / color / mirror / Atom feed
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


      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