All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
@ 2023-11-06 22:17 Johannes Berg
  2023-11-28 14:44   ` Michael Walle
  2023-11-28 17:47 ` Michael Krause
  0 siblings, 2 replies; 14+ messages in thread
From: Johannes Berg @ 2023-11-06 22:17 UTC (permalink / raw)
  To: linux-wireless; +Cc: Max Schulze, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

My prior race fix here broke CQM when ranges aren't used, as
the reporting worker now requires the cqm_config to be set in
the wdev, but isn't set when there's no range configured.

Rather than continuing to special-case the range version, set
the cqm_config always and configure accordingly, also tracking
if range was used or not to be able to clear the configuration
appropriately with the same API, which was actually not right
if both were implemented by a driver for some reason, as is
the case with mac80211 (though there the implementations are
equivalent so it doesn't matter.)

Also, the original multiple-RSSI commit lost checking for the
callback, so might have potentially crashed if a driver had
neither implementation, and userspace tried to use it despite
not being advertised as supported.

Cc: stable@vger.kernel.org
Fixes: 4a4b8169501b ("cfg80211: Accept multiple RSSI thresholds for CQM")
Fixes: 37c20b2effe9 ("wifi: cfg80211: fix cqm_config access race")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/wireless/core.h    |  1 +
 net/wireless/nl80211.c | 50 ++++++++++++++++++++++++++----------------
 2 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/net/wireless/core.h b/net/wireless/core.h
index 4c692c7faf30..cb61d33d4f1e 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -293,6 +293,7 @@ struct cfg80211_cqm_config {
 	u32 rssi_hyst;
 	s32 last_rssi_event_value;
 	enum nl80211_cqm_rssi_threshold_event last_rssi_event_type;
+	bool use_range_api;
 	int n_rssi_thresholds;
 	s32 rssi_thresholds[] __counted_by(n_rssi_thresholds);
 };
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 569234bc2be6..dbfed5a2d7b6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -12787,10 +12787,6 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
 	int i, n, low_index;
 	int err;
 
-	/* RSSI reporting disabled? */
-	if (!cqm_config)
-		return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
-
 	/*
 	 * Obtain current RSSI value if possible, if not and no RSSI threshold
 	 * event has been received yet, we should receive an event after a
@@ -12865,23 +12861,25 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
 	    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
 		return -EOPNOTSUPP;
 
-	if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
-		if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
-			return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
-
-		return rdev_set_cqm_rssi_config(rdev, dev,
-						thresholds[0], hysteresis);
-	}
-
-	if (!wiphy_ext_feature_isset(&rdev->wiphy,
-				     NL80211_EXT_FEATURE_CQM_RSSI_LIST))
-		return -EOPNOTSUPP;
-
 	if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
 		n_thresholds = 0;
 
 	old = wiphy_dereference(wdev->wiphy, wdev->cqm_config);
 
+	/* if already disabled just succeed */
+	if (!n_thresholds && !old)
+		return 0;
+
+	if (n_thresholds > 1) {
+		if (!wiphy_ext_feature_isset(&rdev->wiphy,
+					     NL80211_EXT_FEATURE_CQM_RSSI_LIST) ||
+		    !rdev->ops->set_cqm_rssi_range_config)
+			return -EOPNOTSUPP;
+	} else {
+		if (!rdev->ops->set_cqm_rssi_config)
+			return -EOPNOTSUPP;
+	}
+
 	if (n_thresholds) {
 		cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
 						 n_thresholds),
@@ -12894,13 +12892,26 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
 		memcpy(cqm_config->rssi_thresholds, thresholds,
 		       flex_array_size(cqm_config, rssi_thresholds,
 				       n_thresholds));
+		cqm_config->use_range_api = n_thresholds > 1 ||
+					    !rdev->ops->set_cqm_rssi_config;
 
 		rcu_assign_pointer(wdev->cqm_config, cqm_config);
+
+		if (cqm_config->use_range_api)
+			err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config);
+		else
+			err = rdev_set_cqm_rssi_config(rdev, dev,
+						       thresholds[0],
+						       hysteresis);
 	} else {
 		RCU_INIT_POINTER(wdev->cqm_config, NULL);
+		/* if enabled as range also disable via range */
+		if (old->use_range_api)
+			err = rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
+		else
+			err = rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
 	}
 
-	err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config);
 	if (err) {
 		rcu_assign_pointer(wdev->cqm_config, old);
 		kfree_rcu(cqm_config, rcu_head);
@@ -19009,10 +19020,11 @@ void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, struct wiphy_work *work)
 	s32 rssi_level;
 
 	cqm_config = wiphy_dereference(wdev->wiphy, wdev->cqm_config);
-	if (!wdev->cqm_config)
+	if (!cqm_config)
 		return;
 
-	cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config);
+	if (cqm_config->use_range_api)
+		cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config);
 
 	rssi_level = cqm_config->last_rssi_event_value;
 	rssi_event = cqm_config->last_rssi_event_type;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
@ 2023-11-28 14:44   ` Michael Walle
  0 siblings, 0 replies; 14+ messages in thread
From: kernel test robot @ 2023-11-09  0:02 UTC (permalink / raw)
  To: Johannes Berg; +Cc: oe-kbuild-all

Hi Johannes,

[This is a private test report for your RFC patch.]
kernel test robot noticed the following build warnings:

[auto build test WARNING on wireless-next/main]
[also build test WARNING on wireless/main linus/master next-20231108]
[cannot apply to v6.6]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Johannes-Berg/wifi-cfg80211-fix-CQM-for-non-range-use/20231107-071337
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
patch link:    https://lore.kernel.org/r/20231106231715.3a506ac2dadb.Ie774b85b9d4ff934a1236e77096cb9c6c9fe6561%40changeid
patch subject: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
config: x86_64-buildonly-randconfig-006-20231108 (https://download.01.org/0day-ci/archive/20231109/202311090752.hWcJWAHL-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231109/202311090752.hWcJWAHL-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202311090752.hWcJWAHL-lkp@intel.com/

All warnings (new ones prefixed by >>):

   net/wireless/nl80211.c: In function 'nl80211_set_cqm_rssi.isra':
>> net/wireless/nl80211.c:12892:17: warning: 'memcpy' specified bound 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]
   12892 |                 memcpy(cqm_config->rssi_thresholds, thresholds,
         |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   12893 |                        flex_array_size(cqm_config, rssi_thresholds,
         |                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   12894 |                                        n_thresholds));
         |                                        ~~~~~~~~~~~~~~


vim +/memcpy +12892 net/wireless/nl80211.c

4a4b8169501b18 Andrew Zaborowski 2017-02-10  12840  
d6dc1a38635897 Juuso Oikarinen   2010-03-23  12841  static int nl80211_set_cqm_rssi(struct genl_info *info,
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12842  				const s32 *thresholds, int n_thresholds,
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12843  				u32 hysteresis)
d6dc1a38635897 Juuso Oikarinen   2010-03-23  12844  {
4c476991062a0a Johannes Berg     2010-10-04  12845  	struct cfg80211_registered_device *rdev = info->user_ptr[0];
37c20b2effe987 Johannes Berg     2023-08-16  12846  	struct cfg80211_cqm_config *cqm_config = NULL, *old;
4c476991062a0a Johannes Berg     2010-10-04  12847  	struct net_device *dev = info->user_ptr[1];
1da5fcc86d7104 Johannes Berg     2013-08-06  12848  	struct wireless_dev *wdev = dev->ieee80211_ptr;
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12849  	s32 prev = S32_MIN;
7d6904bf26b96e Johannes Berg     2023-10-05  12850  	int i, err;
d6dc1a38635897 Juuso Oikarinen   2010-03-23  12851  
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12852  	/* Check all values negative and sorted */
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12853  	for (i = 0; i < n_thresholds; i++) {
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12854  		if (thresholds[i] > 0 || thresholds[i] <= prev)
d6dc1a38635897 Juuso Oikarinen   2010-03-23  12855  			return -EINVAL;
d6dc1a38635897 Juuso Oikarinen   2010-03-23  12856  
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12857  		prev = thresholds[i];
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12858  	}
d6dc1a38635897 Juuso Oikarinen   2010-03-23  12859  
074ac8df9f93f2 Johannes Berg     2010-09-16  12860  	if (wdev->iftype != NL80211_IFTYPE_STATION &&
4c476991062a0a Johannes Berg     2010-10-04  12861  	    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
4c476991062a0a Johannes Berg     2010-10-04  12862  		return -EOPNOTSUPP;
d6dc1a38635897 Juuso Oikarinen   2010-03-23  12863  
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12864  	if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12865  		n_thresholds = 0;
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12866  
7d6904bf26b96e Johannes Berg     2023-10-05  12867  	old = wiphy_dereference(wdev->wiphy, wdev->cqm_config);
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12868  
54e1e1c490f4db Johannes Berg     2023-11-06  12869  	/* if already disabled just succeed */
54e1e1c490f4db Johannes Berg     2023-11-06  12870  	if (!n_thresholds && !old)
54e1e1c490f4db Johannes Berg     2023-11-06  12871  		return 0;
54e1e1c490f4db Johannes Berg     2023-11-06  12872  
54e1e1c490f4db Johannes Berg     2023-11-06  12873  	if (n_thresholds > 1) {
54e1e1c490f4db Johannes Berg     2023-11-06  12874  		if (!wiphy_ext_feature_isset(&rdev->wiphy,
54e1e1c490f4db Johannes Berg     2023-11-06  12875  					     NL80211_EXT_FEATURE_CQM_RSSI_LIST) ||
54e1e1c490f4db Johannes Berg     2023-11-06  12876  		    !rdev->ops->set_cqm_rssi_range_config)
54e1e1c490f4db Johannes Berg     2023-11-06  12877  			return -EOPNOTSUPP;
54e1e1c490f4db Johannes Berg     2023-11-06  12878  	} else {
54e1e1c490f4db Johannes Berg     2023-11-06  12879  		if (!rdev->ops->set_cqm_rssi_config)
54e1e1c490f4db Johannes Berg     2023-11-06  12880  			return -EOPNOTSUPP;
54e1e1c490f4db Johannes Berg     2023-11-06  12881  	}
54e1e1c490f4db Johannes Berg     2023-11-06  12882  
37c20b2effe987 Johannes Berg     2023-08-16  12883  	if (n_thresholds) {
40f231e75a1d98 Len Baker         2021-09-19  12884  		cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
40f231e75a1d98 Len Baker         2021-09-19  12885  						 n_thresholds),
40f231e75a1d98 Len Baker         2021-09-19  12886  				     GFP_KERNEL);
076fc8775dafe9 Johannes Berg     2023-08-29  12887  		if (!cqm_config)
076fc8775dafe9 Johannes Berg     2023-08-29  12888  			return -ENOMEM;
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12889  
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12890  		cqm_config->rssi_hyst = hysteresis;
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12891  		cqm_config->n_rssi_thresholds = n_thresholds;
4a4b8169501b18 Andrew Zaborowski 2017-02-10 @12892  		memcpy(cqm_config->rssi_thresholds, thresholds,
40f231e75a1d98 Len Baker         2021-09-19  12893  		       flex_array_size(cqm_config, rssi_thresholds,
40f231e75a1d98 Len Baker         2021-09-19  12894  				       n_thresholds));
54e1e1c490f4db Johannes Berg     2023-11-06  12895  		cqm_config->use_range_api = n_thresholds > 1 ||
54e1e1c490f4db Johannes Berg     2023-11-06  12896  					    !rdev->ops->set_cqm_rssi_config;
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12897  
37c20b2effe987 Johannes Berg     2023-08-16  12898  		rcu_assign_pointer(wdev->cqm_config, cqm_config);
54e1e1c490f4db Johannes Berg     2023-11-06  12899  
54e1e1c490f4db Johannes Berg     2023-11-06  12900  		if (cqm_config->use_range_api)
54e1e1c490f4db Johannes Berg     2023-11-06  12901  			err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config);
54e1e1c490f4db Johannes Berg     2023-11-06  12902  		else
54e1e1c490f4db Johannes Berg     2023-11-06  12903  			err = rdev_set_cqm_rssi_config(rdev, dev,
54e1e1c490f4db Johannes Berg     2023-11-06  12904  						       thresholds[0],
54e1e1c490f4db Johannes Berg     2023-11-06  12905  						       hysteresis);
37c20b2effe987 Johannes Berg     2023-08-16  12906  	} else {
37c20b2effe987 Johannes Berg     2023-08-16  12907  		RCU_INIT_POINTER(wdev->cqm_config, NULL);
54e1e1c490f4db Johannes Berg     2023-11-06  12908  		/* if enabled as range also disable via range */
54e1e1c490f4db Johannes Berg     2023-11-06  12909  		if (old->use_range_api)
54e1e1c490f4db Johannes Berg     2023-11-06  12910  			err = rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
54e1e1c490f4db Johannes Berg     2023-11-06  12911  		else
54e1e1c490f4db Johannes Berg     2023-11-06  12912  			err = rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12913  	}
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12914  
37c20b2effe987 Johannes Berg     2023-08-16  12915  	if (err) {
37c20b2effe987 Johannes Berg     2023-08-16  12916  		rcu_assign_pointer(wdev->cqm_config, old);
37c20b2effe987 Johannes Berg     2023-08-16  12917  		kfree_rcu(cqm_config, rcu_head);
37c20b2effe987 Johannes Berg     2023-08-16  12918  	} else {
37c20b2effe987 Johannes Berg     2023-08-16  12919  		kfree_rcu(old, rcu_head);
37c20b2effe987 Johannes Berg     2023-08-16  12920  	}
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12921  
4a4b8169501b18 Andrew Zaborowski 2017-02-10  12922  	return err;
d6dc1a38635897 Juuso Oikarinen   2010-03-23  12923  }
d6dc1a38635897 Juuso Oikarinen   2010-03-23  12924  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
@ 2023-11-28 14:44   ` Michael Walle
  0 siblings, 0 replies; 14+ messages in thread
From: Michael Walle @ 2023-11-28 14:44 UTC (permalink / raw)
  To: johannes; +Cc: lkp, oe-kbuild-all, linux-wireless, Max Schulze, Michael Walle

Hi,

> net/wireless/nl80211.c: In function 'nl80211_set_cqm_rssi.isra':
> net/wireless/nl80211.c:12892:17: warning: 'memcpy' specified bound
> 18446744073709551615 exceeds maximum object size 9223372036854775807
> [-Wstringop-overflow=]

FWIW, I'm getting the same error with the current next (next-20231128).

-michael

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-06 22:17 [RFC PATCH] wifi: cfg80211: fix CQM for non-range use Johannes Berg
  2023-11-28 14:44   ` Michael Walle
@ 2023-11-28 17:47 ` Michael Krause
  1 sibling, 0 replies; 14+ messages in thread
From: Michael Krause @ 2023-11-28 17:47 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless

Dear Johannes,

You are probably aware of this already, but I believe this patch is quite crucial as your earlier patch may have effectively broken some roaming scenarios using wpa_supplicant.

The supplicant is using CQM to monitor for RSSI threshold changes (non-ranged) to switch between short (few seconds) and very long (1 *hour* in the default NetworkManager setting) background scan intervals. With a current lts kernel (6.1.63) on Arch I do not see RSSI change events at all and wpa_supplicant will almost never (1 hour timeout) scan for a better AP as long as the current AP is still in range.

I applied your patch against 6.1.63 with some additional `goto unlock`s and it resolves the issue for me. I've been running the kernel for 2 days now.

cheers,
Michael

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-28 14:44   ` Michael Walle
  (?)
@ 2023-11-28 18:23   ` Johannes Berg
  2023-11-28 21:01     ` Jeff Johnson
  -1 siblings, 1 reply; 14+ messages in thread
From: Johannes Berg @ 2023-11-28 18:23 UTC (permalink / raw)
  To: Michael Walle; +Cc: lkp, oe-kbuild-all, linux-wireless, Max Schulze

On Tue, 2023-11-28 at 15:44 +0100, Michael Walle wrote:
> Hi,
> 
> > net/wireless/nl80211.c: In function 'nl80211_set_cqm_rssi.isra':
> > net/wireless/nl80211.c:12892:17: warning: 'memcpy' specified bound
> > 18446744073709551615 exceeds maximum object size 9223372036854775807
> > [-Wstringop-overflow=]
> 
> FWIW, I'm getting the same error with the current next (next-20231128).
> 

I actually forgot about that, but does anyone actually know what this is
trying to tell me?

The code seems to be

        if (n_thresholds) {
                cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
                                                 n_thresholds),
                                     GFP_KERNEL);
                if (!cqm_config)
                        return -ENOMEM;

                cqm_config->rssi_hyst = hysteresis;
                cqm_config->n_rssi_thresholds = n_thresholds;
                memcpy(cqm_config->rssi_thresholds, thresholds,
                       flex_array_size(cqm_config, rssi_thresholds,
                                       n_thresholds));


Or does it just want to say n_thresholds shouldn't be a signed variable?

johannes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-28 18:23   ` Johannes Berg
@ 2023-11-28 21:01     ` Jeff Johnson
  2023-11-30 18:32       ` Kees Cook
  0 siblings, 1 reply; 14+ messages in thread
From: Jeff Johnson @ 2023-11-28 21:01 UTC (permalink / raw)
  To: Johannes Berg, Michael Walle, Kees Cook
  Cc: lkp, oe-kbuild-all, linux-wireless, Max Schulze

On 11/28/2023 10:23 AM, Johannes Berg wrote:
> On Tue, 2023-11-28 at 15:44 +0100, Michael Walle wrote:
>> Hi,
>>
>>> net/wireless/nl80211.c: In function 'nl80211_set_cqm_rssi.isra':
>>> net/wireless/nl80211.c:12892:17: warning: 'memcpy' specified bound
>>> 18446744073709551615 exceeds maximum object size 9223372036854775807
>>> [-Wstringop-overflow=]
>>
>> FWIW, I'm getting the same error with the current next (next-20231128).
>>
> 
> I actually forgot about that, but does anyone actually know what this is
> trying to tell me?
> 
> The code seems to be
> 
>         if (n_thresholds) {
>                 cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
>                                                  n_thresholds),
>                                      GFP_KERNEL);
>                 if (!cqm_config)
>                         return -ENOMEM;
> 
>                 cqm_config->rssi_hyst = hysteresis;
>                 cqm_config->n_rssi_thresholds = n_thresholds;
>                 memcpy(cqm_config->rssi_thresholds, thresholds,
>                        flex_array_size(cqm_config, rssi_thresholds,
>                                        n_thresholds));
> 
> 
> Or does it just want to say n_thresholds shouldn't be a signed variable?

+Kees for flex array education :)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-28 21:01     ` Jeff Johnson
@ 2023-11-30 18:32       ` Kees Cook
  2023-11-30 18:40         ` Johannes Berg
  0 siblings, 1 reply; 14+ messages in thread
From: Kees Cook @ 2023-11-30 18:32 UTC (permalink / raw)
  To: Jeff Johnson
  Cc: Johannes Berg, Michael Walle, lkp, oe-kbuild-all, linux-wireless,
	Max Schulze

On Tue, Nov 28, 2023 at 01:01:20PM -0800, Jeff Johnson wrote:
> On 11/28/2023 10:23 AM, Johannes Berg wrote:
> > On Tue, 2023-11-28 at 15:44 +0100, Michael Walle wrote:
> >> Hi,
> >>
> >>> net/wireless/nl80211.c: In function 'nl80211_set_cqm_rssi.isra':
> >>> net/wireless/nl80211.c:12892:17: warning: 'memcpy' specified bound
> >>> 18446744073709551615 exceeds maximum object size 9223372036854775807
> >>> [-Wstringop-overflow=]
> >>
> >> FWIW, I'm getting the same error with the current next (next-20231128).
> >>
> > 
> > I actually forgot about that, but does anyone actually know what this is
> > trying to tell me?
> > 
> > The code seems to be
> > 
> >         if (n_thresholds) {
> >                 cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
> >                                                  n_thresholds),
> >                                      GFP_KERNEL);
> >                 if (!cqm_config)
> >                         return -ENOMEM;
> > 
> >                 cqm_config->rssi_hyst = hysteresis;
> >                 cqm_config->n_rssi_thresholds = n_thresholds;
> >                 memcpy(cqm_config->rssi_thresholds, thresholds,
> >                        flex_array_size(cqm_config, rssi_thresholds,
> >                                        n_thresholds));
> > 
> > 
> > Or does it just want to say n_thresholds shouldn't be a signed variable?
> 
> +Kees for flex array education :)

Yeah, I would expect this to mean that there is a code path that
GCC found where the value could overflow. It does this when a variable
"value range" gets bounded (e.g. an int isn't the full -INT_MAX to INT_MAX
range).And flex_array_size() was designed to saturate at SIZE_MIX rather
than wrapping around to an unexpected small value, so these are playing
together it seems.

However, I would have expected the kzalloc() to blow up _first_.

Regardless, I suspect the addition of "if (n_thresholds > 1)" is what is
tripping GCC.

                int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
		...
                return nl80211_set_cqm_rssi(info, thresholds, len / 4,
                                            hysteresis);

Now it "knows" there is a path where n_threasholds could be [2,
INT_MAX].

Does this warning go away if "len" is made unsigned?

Does adding an upper bounds sanity check help as a work-around, like:

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d0f499227c29..2cb78ac44b6c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -12855,6 +12855,9 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
 	s32 prev = S32_MIN;
 	int i, err;
 
+	if (n_thresholds > INT_MAX / sizeof(*thresholds))
+		return -EINVAL;
+
 	/* Check all values negative and sorted */
 	for (i = 0; i < n_thresholds; i++) {
 		if (thresholds[i] > 0 || thresholds[i] <= prev)



-- 
Kees Cook

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-30 18:32       ` Kees Cook
@ 2023-11-30 18:40         ` Johannes Berg
  2023-11-30 18:46           ` Kees Cook
                             ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Johannes Berg @ 2023-11-30 18:40 UTC (permalink / raw)
  To: Kees Cook, Jeff Johnson
  Cc: Michael Walle, lkp, oe-kbuild-all, linux-wireless, Max Schulze

On Thu, 2023-11-30 at 10:32 -0800, Kees Cook wrote:
> Yeah, I would expect this to mean that there is a code path that
> GCC found where the value could overflow. It does this when a variable
> "value range" gets bounded (e.g. an int isn't the full -INT_MAX to INT_MAX
> range).And flex_array_size() was designed to saturate at SIZE_MIX rather
> than wrapping around to an unexpected small value, so these are playing
> together it seems.
> 
> However, I would have expected the kzalloc() to blow up _first_.

Hmm.

> Regardless, I suspect the addition of "if (n_thresholds > 1)" is what is
> tripping GCC.
> 
>                 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
> 		...
>                 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
>                                             hysteresis);
> 
> Now it "knows" there is a path where n_threasholds could be [2,
> INT_MAX].

Yeah, it's not _really_ bounded, apart from the message length? But then
struct_size() should saturate and fail? But I guess it cannot know that,
and limits the object size to 1<<63 - 1 whereas the copy is 1<<64 - 1...

> Does this warning go away if "len" is made unsigned?

Thing is, neither Kalle nor I can even reproduce the warning locally, so
it's a bit hard to check ... not even with their config and gcc 12.2.0
(nix, rather than debian though.)

> Does adding an upper bounds sanity check help as a work-around, like:

So ... no idea!

I guess I can push something to a branch and see if the robot picks it
up ...

johannes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-30 18:40         ` Johannes Berg
@ 2023-11-30 18:46           ` Kees Cook
  2023-11-30 18:52             ` Johannes Berg
  2023-11-30 18:52           ` Kees Cook
  2023-11-30 18:55           ` Kees Cook
  2 siblings, 1 reply; 14+ messages in thread
From: Kees Cook @ 2023-11-30 18:46 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Jeff Johnson, Michael Walle, lkp, oe-kbuild-all, linux-wireless,
	Max Schulze

On Thu, Nov 30, 2023 at 07:40:26PM +0100, Johannes Berg wrote:
> On Thu, 2023-11-30 at 10:32 -0800, Kees Cook wrote:
> > Yeah, I would expect this to mean that there is a code path that
> > GCC found where the value could overflow. It does this when a variable
> > "value range" gets bounded (e.g. an int isn't the full -INT_MAX to INT_MAX
> > range).And flex_array_size() was designed to saturate at SIZE_MIX rather
> > than wrapping around to an unexpected small value, so these are playing
> > together it seems.
> > 
> > However, I would have expected the kzalloc() to blow up _first_.
> 
> Hmm.
> 
> > Regardless, I suspect the addition of "if (n_thresholds > 1)" is what is
> > tripping GCC.
> > 
> >                 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
> > 		...
> >                 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
> >                                             hysteresis);
> > 
> > Now it "knows" there is a path where n_threasholds could be [2,
> > INT_MAX].
> 
> Yeah, it's not _really_ bounded, apart from the message length? But then
> struct_size() should saturate and fail? But I guess it cannot know that,
> and limits the object size to 1<<63 - 1 whereas the copy is 1<<64 - 1...
> 
> > Does this warning go away if "len" is made unsigned?
> 
> Thing is, neither Kalle nor I can even reproduce the warning locally, so
> it's a bit hard to check ... not even with their config and gcc 12.2.0
> (nix, rather than debian though.)

Ah! Hmm. Let me see if I can coax out the warning locally...

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-30 18:46           ` Kees Cook
@ 2023-11-30 18:52             ` Johannes Berg
  0 siblings, 0 replies; 14+ messages in thread
From: Johannes Berg @ 2023-11-30 18:52 UTC (permalink / raw)
  To: Kees Cook
  Cc: Jeff Johnson, Michael Walle, lkp, oe-kbuild-all, linux-wireless,
	Max Schulze

On Thu, 2023-11-30 at 10:46 -0800, Kees Cook wrote:
> > 
> > > Does this warning go away if "len" is made unsigned?
> > 
> > Thing is, neither Kalle nor I can even reproduce the warning locally, so
> > it's a bit hard to check ... not even with their config and gcc 12.2.0
> > (nix, rather than debian though.)
> 
> Ah! Hmm. Let me see if I can coax out the warning locally...
> 
Actually, I see it now with wireless-next + that patch ... I had put it
into wireless, not wireless-next :)

johannes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-30 18:40         ` Johannes Berg
  2023-11-30 18:46           ` Kees Cook
@ 2023-11-30 18:52           ` Kees Cook
  2023-11-30 18:54             ` Johannes Berg
  2023-11-30 18:55           ` Kees Cook
  2 siblings, 1 reply; 14+ messages in thread
From: Kees Cook @ 2023-11-30 18:52 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Jeff Johnson, Michael Walle, lkp, oe-kbuild-all, linux-wireless,
	Max Schulze

On Thu, Nov 30, 2023 at 07:40:26PM +0100, Johannes Berg wrote:
> On Thu, 2023-11-30 at 10:32 -0800, Kees Cook wrote:
> > Yeah, I would expect this to mean that there is a code path that
> > GCC found where the value could overflow. It does this when a variable
> > "value range" gets bounded (e.g. an int isn't the full -INT_MAX to INT_MAX
> > range).And flex_array_size() was designed to saturate at SIZE_MIX rather
> > than wrapping around to an unexpected small value, so these are playing
> > together it seems.
> > 
> > However, I would have expected the kzalloc() to blow up _first_.
> 
> Hmm.
> 
> > Regardless, I suspect the addition of "if (n_thresholds > 1)" is what is
> > tripping GCC.
> > 
> >                 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
> > 		...
> >                 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
> >                                             hysteresis);
> > 
> > Now it "knows" there is a path where n_threasholds could be [2,
> > INT_MAX].
> 
> Yeah, it's not _really_ bounded, apart from the message length? But then
> struct_size() should saturate and fail? But I guess it cannot know that,
> and limits the object size to 1<<63 - 1 whereas the copy is 1<<64 - 1...
> 
> > Does this warning go away if "len" is made unsigned?
> 
> Thing is, neither Kalle nor I can even reproduce the warning locally, so
> it's a bit hard to check ... not even with their config and gcc 12.2.0
> (nix, rather than debian though.)

I was able to see it with Ubuntu's GCC 12.3.0 and their config. This
fixed it for me:


diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d0f499227c29..7735d178a393 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -12845,7 +12845,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
 }
 
 static int nl80211_set_cqm_rssi(struct genl_info *info,
-				const s32 *thresholds, int n_thresholds,
+				const s32 *thresholds, u32 n_thresholds,
 				u32 hysteresis)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -12948,7 +12948,7 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
 	    attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
 		const s32 *thresholds =
 			nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
-		int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
+		u32 len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
 		u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
 
 		if (len % 4)


If that's sensible, I can send a proper patch?

(Oh, it looks like nla_len is actually u16 ... should I use that instead
of u32?)

-- 
Kees Cook

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-30 18:52           ` Kees Cook
@ 2023-11-30 18:54             ` Johannes Berg
  0 siblings, 0 replies; 14+ messages in thread
From: Johannes Berg @ 2023-11-30 18:54 UTC (permalink / raw)
  To: Kees Cook
  Cc: Jeff Johnson, Michael Walle, lkp, oe-kbuild-all, linux-wireless,
	Max Schulze

On Thu, 2023-11-30 at 10:52 -0800, Kees Cook wrote:
> 
> I was able to see it with Ubuntu's GCC 12.3.0 and their config. This
> fixed it for me:

OK. I guess kernel tree also mattered somehow, and I got confused
because I'd applied the patch on wireless, where the robot did it on
wireless-next. Not sure how that's different, but OK.


> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index d0f499227c29..7735d178a393 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -12845,7 +12845,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
>  }
>  
>  static int nl80211_set_cqm_rssi(struct genl_info *info,
> -				const s32 *thresholds, int n_thresholds,
> +				const s32 *thresholds, u32 n_thresholds,
>  				u32 hysteresis)
>  {
>  	struct cfg80211_registered_device *rdev = info->user_ptr[0];
> @@ -12948,7 +12948,7 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
>  	    attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
>  		const s32 *thresholds =
>  			nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
> -		int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
> +		u32 len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
>  		u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
>  
>  		if (len % 4)
> 
> 
> If that's sensible, I can send a proper patch?

Sure, that seems reasonable.

> (Oh, it looks like nla_len is actually u16 ... should I use that instead
> of u32?)

Yeah it's a 16-bit field in the message format. Doesn't really matter?

johannes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-30 18:40         ` Johannes Berg
  2023-11-30 18:46           ` Kees Cook
  2023-11-30 18:52           ` Kees Cook
@ 2023-11-30 18:55           ` Kees Cook
  2023-11-30 19:00             ` Johannes Berg
  2 siblings, 1 reply; 14+ messages in thread
From: Kees Cook @ 2023-11-30 18:55 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Jeff Johnson, Michael Walle, lkp, oe-kbuild-all, linux-wireless,
	Max Schulze

On Thu, Nov 30, 2023 at 07:40:26PM +0100, Johannes Berg wrote:
> On Thu, 2023-11-30 at 10:32 -0800, Kees Cook wrote:
> > Yeah, I would expect this to mean that there is a code path that
> > GCC found where the value could overflow. It does this when a variable
> > "value range" gets bounded (e.g. an int isn't the full -INT_MAX to INT_MAX
> > range).And flex_array_size() was designed to saturate at SIZE_MIX rather
> > than wrapping around to an unexpected small value, so these are playing
> > together it seems.
> > 
> > However, I would have expected the kzalloc() to blow up _first_.
> 
> Hmm.
> 
> > Regardless, I suspect the addition of "if (n_thresholds > 1)" is what is
> > tripping GCC.
> > 
> >                 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
> > 		...
> >                 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
> >                                             hysteresis);
> > 
> > Now it "knows" there is a path where n_threasholds could be [2,
> > INT_MAX].
> 
> Yeah, it's not _really_ bounded, apart from the message length? But then
> struct_size() should saturate and fail? But I guess it cannot know that,
> and limits the object size to 1<<63 - 1 whereas the copy is 1<<64 - 1...
> 
> > Does this warning go away if "len" is made unsigned?

Actually, this alone fixes it too:

diff --git a/include/net/netlink.h b/include/net/netlink.h
index 167b91348e57..c59679524705 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -1214,9 +1214,9 @@ static inline void *nla_data(const struct nlattr *nla)
  * nla_len - length of payload
  * @nla: netlink attribute
  */
-static inline int nla_len(const struct nlattr *nla)
+static inline u16 nla_len(const struct nlattr *nla)
 {
-	return nla->nla_len - NLA_HDRLEN;
+	return nla->nla_len > NLA_HDRLEN ? nla->nla_len - NLA_HDRLEN : 0;
 }
 
 /**

-- 
Kees Cook

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [RFC PATCH] wifi: cfg80211: fix CQM for non-range use
  2023-11-30 18:55           ` Kees Cook
@ 2023-11-30 19:00             ` Johannes Berg
  0 siblings, 0 replies; 14+ messages in thread
From: Johannes Berg @ 2023-11-30 19:00 UTC (permalink / raw)
  To: Kees Cook
  Cc: Jeff Johnson, Michael Walle, lkp, oe-kbuild-all, linux-wireless,
	Max Schulze, netdev

On Thu, 2023-11-30 at 10:55 -0800, Kees Cook wrote:
> On Thu, Nov 30, 2023 at 07:40:26PM +0100, Johannes Berg wrote:
> > On Thu, 2023-11-30 at 10:32 -0800, Kees Cook wrote:
> > > Yeah, I would expect this to mean that there is a code path that
> > > GCC found where the value could overflow. It does this when a variable
> > > "value range" gets bounded (e.g. an int isn't the full -INT_MAX to INT_MAX
> > > range).And flex_array_size() was designed to saturate at SIZE_MIX rather
> > > than wrapping around to an unexpected small value, so these are playing
> > > together it seems.
> > > 
> > > However, I would have expected the kzalloc() to blow up _first_.
> > 
> > Hmm.
> > 
> > > Regardless, I suspect the addition of "if (n_thresholds > 1)" is what is
> > > tripping GCC.
> > > 
> > >                 int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
> > > 		...
> > >                 return nl80211_set_cqm_rssi(info, thresholds, len / 4,
> > >                                             hysteresis);
> > > 
> > > Now it "knows" there is a path where n_threasholds could be [2,
> > > INT_MAX].
> > 
> > Yeah, it's not _really_ bounded, apart from the message length? But then
> > struct_size() should saturate and fail? But I guess it cannot know that,
> > and limits the object size to 1<<63 - 1 whereas the copy is 1<<64 - 1...
> > 
> > > Does this warning go away if "len" is made unsigned?
> 
> Actually, this alone fixes it too:
> 
> diff --git a/include/net/netlink.h b/include/net/netlink.h
> index 167b91348e57..c59679524705 100644
> --- a/include/net/netlink.h
> +++ b/include/net/netlink.h
> @@ -1214,9 +1214,9 @@ static inline void *nla_data(const struct nlattr *nla)
>   * nla_len - length of payload
>   * @nla: netlink attribute
>   */
> -static inline int nla_len(const struct nlattr *nla)
> +static inline u16 nla_len(const struct nlattr *nla)
>  {
> -	return nla->nla_len - NLA_HDRLEN;
> +	return nla->nla_len > NLA_HDRLEN ? nla->nla_len - NLA_HDRLEN : 0;
>  }
> 

Heh. If you can sell that to Jakub I don't mind, but that might be a
harder sell than the int/u32 in our code...

johannes

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2023-11-30 19:00 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-06 22:17 [RFC PATCH] wifi: cfg80211: fix CQM for non-range use Johannes Berg
2023-11-09  0:02 ` kernel test robot
2023-11-28 14:44   ` Michael Walle
2023-11-28 18:23   ` Johannes Berg
2023-11-28 21:01     ` Jeff Johnson
2023-11-30 18:32       ` Kees Cook
2023-11-30 18:40         ` Johannes Berg
2023-11-30 18:46           ` Kees Cook
2023-11-30 18:52             ` Johannes Berg
2023-11-30 18:52           ` Kees Cook
2023-11-30 18:54             ` Johannes Berg
2023-11-30 18:55           ` Kees Cook
2023-11-30 19:00             ` Johannes Berg
2023-11-28 17:47 ` Michael Krause

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.