From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qv1-f46.google.com (mail-qv1-f46.google.com [209.85.219.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 84D4347ECC6 for ; Fri, 15 May 2026 12:12:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.46 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778847149; cv=none; b=Rz4xTaZ8y6B88QhW5ZWRkwBPu8YECzEAODv/LVckjd/mp9l4jNWKkz9iQGLKq+WLv1bUVTqvkVaqXWcau5NidD5n4oukEBrzbhVVZKB5hm7rzwwn4q+/qCTy3cJ1OMcyG/GgysfVTT45eiKRKUx7dyrzu+HAVqPzgeh2H3cIVRY= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778847149; c=relaxed/simple; bh=nHcMBK6wG0TOu22YqkQZEX4prF+OO2NceKdzMNQ1dEA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WHkFtTtJOCh0BCCY28ybXMd6QeobABDznlWvZmyVm6I8s74QNkNxt6eXePTKU2MMplr9NLcqxqPggC30eRBkfzDTopzBJv2qEY34KjaXRyY90xIifSTcLCWA5hH9Q4scRYteGlTRhBhVFJ5AktKp8ctyt0UiPJHAvZzgmZNuCbU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=C48BC3qt; arc=none smtp.client-ip=209.85.219.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="C48BC3qt" Received: by mail-qv1-f46.google.com with SMTP id 6a1803df08f44-899d6b7b073so88498496d6.2 for ; Fri, 15 May 2026 05:12:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778847146; x=1779451946; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=rUcmngTs7ey+uIUzuqkXpKib26TeG2lJPiT+fn8FBYQ=; b=C48BC3qtQ/OEIcT6iVMy8ZntDBUF4J7uQIHsgV7vRP7+l7C039gUMXoe2zxXsxTfPB efexjD9gl7Akx9q8z6Savg0ii+7yBfoyczswGzXDfjR1Ec2GAyTpYRKux4TRubgPSi8R 4IYjUPqXDm50QzDc2Q9pORCCvrqcaewyuphXPuOAZWjINFskWsiyMLqga7r9K56152wT 0Uj+uM1gQRVy6ozQYHgZzFzm3SKKeBvntzIyzxdydXJz6wRiWngnvD9cqa6XwwD9RIRI v3j+xjCLdEZD718L/uvZ6kwEqls2Jt0zqDAAeiIOkNtS4CLiTm9y/gSxxRTgL3F86dOG 43HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778847146; x=1779451946; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=rUcmngTs7ey+uIUzuqkXpKib26TeG2lJPiT+fn8FBYQ=; b=Zm8pena23XMXIv3bEPKFIDfcLBADBS8EzYcVNBmsC3WORw2dUHfA8msMlpmPtlTRHY 5IKs7BZ1xQHL1lh86K64wQIoKVAu+UIkFrq+lwBwwCamN9CSyFHgy9LHsEKK24W1hkWs W1gSuCl883avaoloQVdJUIWomaJjvsOAC1lqSqv/I8pqF0f9FcHhZzN4eZ54c3XVqPhi e57nYvBsrsB6Nuhn5JH3HNZp8uMR8Y70wxoC0uDNId9MkQHcGFnwqiESolOzw0yOSKW+ 4k9H64TVhpop0ySWcrNceqt07+kyXlgMolFPp6RTBl+HkanEdJKmbDkYqRl8sMlxh94s BdzQ== X-Forwarded-Encrypted: i=1; AFNElJ/YWWhRRyO2BZH+kEhn1SbHeZSxjQATYI9mMVEPeoBvWj2qZ0bk6CM9lsZYWziDjrbVJ0V0qPEuvuRx3Ts=@vger.kernel.org X-Gm-Message-State: AOJu0Yy0/T0bsjHCJhyiBYhJL4b4d9aoe8EQzoWB4hcpWanZndEAq2mc slg3seG16YevyFx+YFUjX0OA7ONrwX7kdrEE1XfohtOtGfVv13VMEpCH X-Gm-Gg: Acq92OEa1P+yhNBhvxkZcEFsCyGFmYxqRXp3jpBwGSHOf5iCY+EaLcScrZ++SKuIno2 IjM3tSHQ7nIeDX+kzgsUZBhZ5YNPydfc4VrR/tO1kXpKD+RNu4kjLTCfNUdaUPhxLCs7OA7qhfN COyi/b0Ohp4yLTUcvqEh4huw6m6yf+Fm7DuqLIhkYr0CPfvVPzhGVYqdhKh1bSKEQwktz6wp4DZ LFNo9IfpSHvYViSE3SvH4QTAI7DMe6VVXA3FgSge5onCWE/D9i+yS9mvf/taQdULIsOrnBExiW4 AQQxxpV4NgEkfK3LtO7WwfW/tsNOGYRdgGMj07ZJPYkwUm5Um0oMvWlKNJlFnZursxFrJLGzUKZ ke7Cswnf9Da8mBNczBnOFhVttbuvQg24aO38m9wsBwfa0LrL9wiVd4c3bZqIH0j5920GknR4tWv U0qXYPU740oRuzV8B4hADbQO2qwd0Lc0qMYUb9tL7Vm8+Yf5NDbVcak3gkWydG1szSW+Kd/fHKv wfSiBAnbunmlanIKIyjnZjA2JQijZuG71tsNYvnFQE= X-Received: by 2002:a05:622a:1e89:b0:509:30b0:8323 with SMTP id d75a77b69052e-5165a0a4269mr49097671cf.31.1778847146567; Fri, 15 May 2026 05:12:26 -0700 (PDT) Received: from server0.tail6e7dd.ts.net (c-68-48-65-54.hsd1.mi.comcast.net. [68.48.65.54]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-516456888f6sm45534491cf.3.2026.05.15.05.12.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2026 05:12:26 -0700 (PDT) From: Michael Bommarito To: Miri Korenblit Cc: Johannes Berg , Emmanuel Grumbach , linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH 2/4] wifi: iwlwifi: mvm: clamp set_freqs iteration to n_nd_channels Date: Fri, 15 May 2026 08:10:58 -0400 Message-ID: <20260515121100.649334-3-michael.bommarito@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260515121100.649334-1-michael.bommarito@gmail.com> References: <20260515121100.649334-1-michael.bommarito@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit iwl_mvm_query_set_freqs() iterates over bit positions 0 .. SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8 - 1 (= 0..55 on the v2 path, 0..39 on the v1 path) and, for each set bit, performs: match->channels[n_channels++] = mvm->nd_channels[i]->center_freq; without constraining i against mvm->n_nd_channels. The pointer table mvm->nd_channels is kmemdup()ed at suspend time with exactly mvm->n_nd_channels entries (whatever the userspace NL80211_CMD_SET_WOWLAN request supplied as nd_config->n_channels; typical real-world values are 5..50). If the firmware response contains any matching_channels[] bit set at a position >= mvm->n_nd_channels, the indexed load reads a u8* slot past the end of the pointer-table allocation, then the immediate ->center_freq dereferences that wild pointer. The pre-existing caller guard if (mvm->n_nd_channels < n_channels) continue; compares the bitmap's popcount to the table length, not the bit positions to the table length. A bitmap with three set bits at positions {50, 51, 52} has popcount 3 and passes the guard unconditionally, then walks 50+ entries off the end of mvm->nd_channels. Reproduced under UML+KASAN via a KUnit harness that lifts the iteration logic. With nd_channels allocated as 5 entries and matching_channels bits set at positions 7 (immediate redzone) and 50 (far OOB), the kernel panics on the wild deref: Kernel panic - not syncing: Segfault with no mm RIP: 0033:set_freqs_buggy.constprop.0+0xc1/0x15e (The selector 0x0033 in the RIP line 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/mvm/d3.o under x86_64 allmodconfig with the fix applied yields no new warnings. Clamp the iteration upper bound to min(matching-bits-width, mvm->n_nd_channels) so high-position bits, however the firmware emitted them, cannot index past the pointer table. Mirror the fix for the v1 fallback arm. Cc: stable@vger.kernel.org Fixes: 8ed4e659f34c ("iwlwifi: mvm: add channel information to the netdetect notifications") Signed-off-by: Michael Bommarito Assisted-by: Claude:claude-opus-4-7 --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index c17ac62feec3..b04d8dd26cd0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -2514,16 +2514,20 @@ static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm, IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) { struct iwl_scan_offload_profile_match *matches = (void *)results->matches; + int max = min_t(int, SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8, + mvm->n_nd_channels); - for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; i++) + for (i = 0; i < max; i++) if (matches[idx].matching_channels[i / 8] & (BIT(i % 8))) match->channels[n_channels++] = mvm->nd_channels[i]->center_freq; } else { struct iwl_scan_offload_profile_match_v1 *matches = (void *)results->matches; + int max = min_t(int, SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 * 8, + mvm->n_nd_channels); - for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 * 8; i++) + for (i = 0; i < max; i++) if (matches[idx].matching_channels[i / 8] & (BIT(i % 8))) match->channels[n_channels++] = mvm->nd_channels[i]->center_freq; -- 2.53.0