From: Kees Cook keescook@chromium.org
stable inclusion from stable-v6.6.33 commit ed74398642fcb19f6ff385c35a7d512c6663e17b category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IA6SBS CVE: CVE-2024-38562
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ Upstream commit 838c7b8f1f278404d9d684c34a8cb26dc41aaaa1 ]
Before request->channels[] can be used, request->n_channels must be set. Additionally, address calculations for memory after the "channels" array need to be calculated from the allocation base ("request") rather than via the first "out of bounds" index of "channels", otherwise run-time bounds checking will throw a warning.
Reported-by: Nathan Chancellor nathan@kernel.org Fixes: e3eac9f32ec0 ("wifi: cfg80211: Annotate struct cfg80211_scan_request with __counted_by") Signed-off-by: Kees Cook keescook@chromium.org Tested-by: Nathan Chancellor nathan@kernel.org Link: https://msgid.link/20240424220057.work.819-kees@kernel.org Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Liu Jian liujian56@huawei.com --- net/wireless/nl80211.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c4f08f7eb741..8f8f077e6cd4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -9153,6 +9153,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err, tmp, n_ssids = 0, n_channels, i; size_t ie_len, size; + size_t ssids_offset, ie_offset;
wiphy = &rdev->wiphy;
@@ -9198,21 +9199,20 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) return -EINVAL;
size = struct_size(request, channels, n_channels); + ssids_offset = size; size = size_add(size, array_size(sizeof(*request->ssids), n_ssids)); + ie_offset = size; size = size_add(size, ie_len); request = kzalloc(size, GFP_KERNEL); if (!request) return -ENOMEM; + request->n_channels = n_channels;
if (n_ssids) - request->ssids = (void *)&request->channels[n_channels]; + request->ssids = (void *)request + ssids_offset; request->n_ssids = n_ssids; - if (ie_len) { - if (n_ssids) - request->ie = (void *)(request->ssids + n_ssids); - else - request->ie = (void *)(request->channels + n_channels); - } + if (ie_len) + request->ie = (void *)request + ie_offset;
i = 0; if (scan_freqs) {