Skip to content

Commit f7a8b10

Browse files
committed
wifi: cfg80211: fix 6 GHz scan request building
The 6 GHz scan request struct allocated by cfg80211_scan_6ghz() is meant to be formed this way: [base struct][channels][ssids][6ghz_params] It is allocated with [channels] as the maximum number of channels supported by the driver in the 6 GHz band, since allocation is before knowing how many there will be. However, the inner pointers are set incorrectly: initially, the 6 GHz scan parameters pointer is set: [base struct][channels] ^ scan_6ghz_params and later the SSID pointer is set to the end of the actually _used_ channels. [base struct][channels] ^ ssids If many APs were to be discovered, and many channels used, and there were many SSIDs, then the SSIDs could overlap the 6 GHz parameters. Additionally, the request->ssids for most of the function points to the original request still (given the struct copy) but is used normally, which is confusing. Clear this up, by actually using the allocated space for 6 GHz parameters _after_ the SSIDs, and set up the SSIDs initially so they are used more clearly. Just like in nl80211.c, set them only if there actually are SSIDs though. Finally, also copy the elements (ie/ie_len) so they're part of the same request, not pointing to the old request. Co-developed-by: Miri Korenblit <[email protected]> Signed-off-by: Miri Korenblit <[email protected]> Reviewed-by: Ilan Peer <[email protected]> Signed-off-by: Johannes Berg <[email protected]> Link: https://msgid.link/20240510113738.4190692ef4ee.I0cb19188be17a8abd029805e3373c0a7777c214c@changeid Signed-off-by: Johannes Berg <[email protected]>
1 parent 177c6ae commit f7a8b10

File tree

2 files changed

+36
-17
lines changed

2 files changed

+36
-17
lines changed

net/wireless/rdev-ops.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/*
33
* Portions of this file
44
* Copyright(c) 2016-2017 Intel Deutschland GmbH
5-
* Copyright (C) 2018, 2021-2023 Intel Corporation
5+
* Copyright (C) 2018, 2021-2024 Intel Corporation
66
*/
77
#ifndef __CFG80211_RDEV_OPS
88
#define __CFG80211_RDEV_OPS
@@ -458,6 +458,10 @@ static inline int rdev_scan(struct cfg80211_registered_device *rdev,
458458
struct cfg80211_scan_request *request)
459459
{
460460
int ret;
461+
462+
if (WARN_ON_ONCE(!request->n_ssids && request->ssids))
463+
return -EINVAL;
464+
461465
trace_rdev_scan(&rdev->wiphy, request);
462466
ret = rdev->ops->scan(&rdev->wiphy, request);
463467
trace_rdev_return_int(&rdev->wiphy, ret);

net/wireless/scan.c

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,7 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
812812
LIST_HEAD(coloc_ap_list);
813813
bool need_scan_psc = true;
814814
const struct ieee80211_sband_iftype_data *iftd;
815+
size_t size, offs_ssids, offs_6ghz_params, offs_ies;
815816

816817
rdev_req->scan_6ghz = true;
817818

@@ -877,19 +878,42 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
877878
spin_unlock_bh(&rdev->bss_lock);
878879
}
879880

880-
request = kzalloc(struct_size(request, channels, n_channels) +
881-
sizeof(*request->scan_6ghz_params) * count +
882-
sizeof(*request->ssids) * rdev_req->n_ssids,
883-
GFP_KERNEL);
881+
size = struct_size(request, channels, n_channels);
882+
offs_ssids = size;
883+
size += sizeof(*request->ssids) * rdev_req->n_ssids;
884+
offs_6ghz_params = size;
885+
size += sizeof(*request->scan_6ghz_params) * count;
886+
offs_ies = size;
887+
size += rdev_req->ie_len;
888+
889+
request = kzalloc(size, GFP_KERNEL);
884890
if (!request) {
885891
cfg80211_free_coloc_ap_list(&coloc_ap_list);
886892
return -ENOMEM;
887893
}
888894

889895
*request = *rdev_req;
890896
request->n_channels = 0;
891-
request->scan_6ghz_params =
892-
(void *)&request->channels[n_channels];
897+
request->n_6ghz_params = 0;
898+
if (rdev_req->n_ssids) {
899+
/*
900+
* Add the ssids from the parent scan request to the new
901+
* scan request, so the driver would be able to use them
902+
* in its probe requests to discover hidden APs on PSC
903+
* channels.
904+
*/
905+
request->ssids = (void *)request + offs_ssids;
906+
memcpy(request->ssids, rdev_req->ssids,
907+
sizeof(*request->ssids) * request->n_ssids);
908+
}
909+
request->scan_6ghz_params = (void *)request + offs_6ghz_params;
910+
911+
if (rdev_req->ie_len) {
912+
void *ie = (void *)request + offs_ies;
913+
914+
memcpy(ie, rdev_req->ie, rdev_req->ie_len);
915+
request->ie = ie;
916+
}
893917

894918
/*
895919
* PSC channels should not be scanned in case of direct scan with 1 SSID
@@ -978,17 +1002,8 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
9781002

9791003
if (request->n_channels) {
9801004
struct cfg80211_scan_request *old = rdev->int_scan_req;
981-
rdev->int_scan_req = request;
9821005

983-
/*
984-
* Add the ssids from the parent scan request to the new scan
985-
* request, so the driver would be able to use them in its
986-
* probe requests to discover hidden APs on PSC channels.
987-
*/
988-
request->ssids = (void *)&request->channels[request->n_channels];
989-
request->n_ssids = rdev_req->n_ssids;
990-
memcpy(request->ssids, rdev_req->ssids, sizeof(*request->ssids) *
991-
request->n_ssids);
1006+
rdev->int_scan_req = request;
9921007

9931008
/*
9941009
* If this scan follows a previous scan, save the scan start

0 commit comments

Comments
 (0)