diff mbox series

[wireless-next,v14,2/4] wifi: cfg80211: Add Support to Set RTS Threshold for each Radio

Message ID 20250605111040.3451328-3-quic_rdevanat@quicinc.com
State Superseded
Headers show
Series wifi: cfg80211/mac80211: Set/get wiphy parameters on per-radio basis | expand

Commit Message

Roopni Devanathan June 5, 2025, 11:10 a.m. UTC
Currently, setting RTS threshold is based on per-phy basis, i.e., all the
radios present in a wiphy will take RTS threshold value to be the one sent
from userspace. But each radio in a multi-radio wiphy can have different
RTS threshold requirements.

To extend support to set RTS threshold for each radio, get the radio for
which RTS threshold needs to be changed from the user. Use the attribute
in NL - NL80211_ATTR_WIPHY_RADIO_INDEX, to identify the radio of interest.
Create a new structure - wiphy_radio_cfg and add rts_threshold in it as a
u32 value to store RTS threshold of each radio in a wiphy and allocate
memory for it during wiphy register based on the wiphy.n_radio updated by
drivers. Pass radio id received from the user to mac80211 drivers along
with its corresponding RTS threshold.

Signed-off-by: Roopni Devanathan <quic_rdevanat@quicinc.com>
---
 include/net/cfg80211.h | 18 +++++++++++++
 net/wireless/core.c    | 19 +++++++++++++
 net/wireless/nl80211.c | 60 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 95 insertions(+), 2 deletions(-)

Comments

kernel test robot June 10, 2025, 8:44 a.m. UTC | #1
Hello,

kernel test robot noticed "BUG:KASAN:use-after-free_in_wiphy_free" on:

commit: d99fe2735afd3ea67b732b98ab4b2d47408d4f0f ("[PATCH wireless-next v14 2/4] wifi: cfg80211: Add Support to Set RTS Threshold for each Radio")
url: https://github.com/intel-lab-lkp/linux/commits/Roopni-Devanathan/wifi-cfg80211-mac80211-Add-support-to-get-radio-index/20250605-191329
patch link: https://lore.kernel.org/all/20250605111040.3451328-3-quic_rdevanat@quicinc.com/
patch subject: [PATCH wireless-next v14 2/4] wifi: cfg80211: Add Support to Set RTS Threshold for each Radio

in testcase: hwsim
version: hwsim-x86_64-b01c4843b-1_20250601
with following parameters:

	test: group-30



config: x86_64-rhel-9.4-func
compiler: gcc-12
test machine: 8 threads 1 sockets Intel(R) Core(TM) i7-4790 v3 @ 3.60GHz (Haswell) with 6G memory

(please refer to attached dmesg/kmsg for entire log/backtrace)



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 <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202506101652.625ca3c4-lkp@intel.com


The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20250610/202506101652.625ca3c4-lkp@intel.com


[  277.261476][ T7020] ==================================================================
[  277.263650][  T332] beacon_int=100
[  277.265556][ T7020] BUG: KASAN: use-after-free in wiphy_free+0x45/0x50 [cfg80211]
[  277.273470][  T332] 
[  277.276843][ T7020] Read of size 8 at addr ffff888192fe0530 by task python3/7020
[  277.276847][ T7020] 
[  277.276860][ T7020] CPU: 7 UID: 0 PID: 7020 Comm: python3 Tainted: G S                  6.15.0-rc7-01660-gd99fe2735afd #1 PREEMPT(voluntary) 
[  277.276865][ T7020] Tainted: [S]=CPU_OUT_OF_SPEC
[  277.276866][ T7020] Hardware name: Dell Inc. OptiPlex 9020/03CPWF, BIOS A11 04/01/2015
[  277.276868][ T7020] Call Trace:
[  277.276880][ T7020]  <TASK>
[  277.276882][ T7020]  dump_stack_lvl+0x4f/0x70
[  277.276889][ T7020]  print_address_description+0x2c/0x3b0
[  277.276894][ T7020]  ? wiphy_free+0x45/0x50 [cfg80211]
[  277.276971][ T7020]  print_report+0xb9/0x280
[  277.276974][ T7020]  ? kasan_addr_to_slab+0x9/0x90
[  277.276978][ T7020]  ? wiphy_free+0x45/0x50 [cfg80211]
[  277.277058][ T7020]  kasan_report+0xb4/0xe0
[  277.277061][ T7020]  ? wiphy_free+0x45/0x50 [cfg80211]
[  277.277132][ T7020]  wiphy_free+0x45/0x50 [cfg80211]
[  277.277212][ T7020]  hwsim_del_radio_nl+0x53f/0x820 [mac80211_hwsim]
[  277.277222][ T7020]  genl_family_rcv_msg_doit+0x1d4/0x2b0
[  277.277227][ T7020]  ? __pfx_genl_family_rcv_msg_doit+0x10/0x10
[  277.277232][ T7020]  ? security_capable+0xab/0xc0
[  277.277236][ T7020]  genl_family_rcv_msg+0x337/0x520
[  277.277240][ T7020]  ? __pfx_genl_family_rcv_msg+0x10/0x10
[  277.277243][ T7020]  ? __pfx_hwsim_del_radio_nl+0x10/0x10 [mac80211_hwsim]
[  277.277250][ T7020]  ? __pfx_mutex_lock+0x10/0x10
[  277.277254][ T7020]  ? __pfx_stack_trace_save+0x10/0x10
[  277.277257][ T7020]  ? stack_depot_save_flags+0x3d/0x610
[  277.277262][ T7020]  genl_rcv_msg+0x9f/0x130
[  277.277265][ T7020]  netlink_rcv_skb+0x122/0x380
[  277.277268][ T7020]  ? __pfx_genl_rcv_msg+0x10/0x10
[  277.277271][ T7020]  ? __pfx_netlink_rcv_skb+0x10/0x10
[  277.277274][ T7020]  ? __pfx_netlink_lookup+0x10/0x10
[  277.277277][ T7020]  ? _copy_from_iter+0x271/0x16b0
[  277.277281][ T7020]  genl_rcv+0x24/0x40
[  277.277284][ T7020]  netlink_unicast+0x687/0x9c0
[  277.277287][ T7020]  ? __pfx_netlink_unicast+0x10/0x10
[  277.277290][ T7020]  ? 0xffffffff81000000
[  277.277292][ T7020]  ? __check_object_size+0x75/0x1d0
[  277.277296][ T7020]  netlink_sendmsg+0x745/0xbf0
[  277.277299][ T7020]  ? __pfx_netlink_sendmsg+0x10/0x10
[  277.277302][ T7020]  ? fdget+0x54/0x3b0
[  277.277306][ T7020]  ? file_update_time+0x110/0x160
[  277.277309][ T7020]  __sys_sendto+0x399/0x410
[  277.277312][ T7020]  ? __pfx___sys_sendto+0x10/0x10
[  277.277315][ T7020]  ? __pfx_vfs_write+0x10/0x10
[  277.277318][ T7020]  ? __pfx_current_time+0x10/0x10
[  277.277321][ T7020]  ? fdget_pos+0x1cb/0x4b0
[  277.277324][ T7020]  ? inode_needs_update_time+0x15c/0x1e0
[  277.277327][ T7020]  __x64_sys_sendto+0xdc/0x1b0
[  277.277329][ T7020]  ? vfs_write+0x76d/0xc40
[  277.277331][ T7020]  ? vfs_write+0x76d/0xc40
[  277.277333][ T7020]  do_syscall_64+0x79/0x160
[  277.277347][ T7020]  ? syscall_exit_to_user_mode+0xc/0x1e0
[  277.277350][ T7020]  ? do_syscall_64+0x85/0x160
[  277.277353][ T7020]  ? put_timespec64+0xa8/0x100
[  277.277356][ T7020]  ? fdget_pos+0x54/0x4b0
[  277.277369][ T7020]  ? ksys_write+0x17c/0x1c0
[  277.277371][ T7020]  ? __pfx_ksys_write+0x10/0x10
[  277.277374][ T7020]  ? do_syscall_64+0x85/0x160
[  277.277377][ T7020]  ? syscall_exit_to_user_mode+0xc/0x1e0
[  277.277379][ T7020]  ? do_syscall_64+0x85/0x160
[  277.277382][ T7020]  ? __asan_memset+0x1f/0x40
[  277.277386][ T7020]  ? rseq_ip_fixup+0x2a3/0x410
[  277.277390][ T7020]  ? __pfx_rseq_ip_fixup+0x10/0x10
[  277.277393][ T7020]  ? __pfx_mem_cgroup_handle_over_high+0x10/0x10
[  277.277397][ T7020]  ? __pfx___x64_sys_pselect6+0x10/0x10
[  277.277400][ T7020]  ? fpregs_restore_userregs+0xe3/0x1f0
[  277.277404][ T7020]  ? syscall_exit_to_user_mode+0x1c1/0x1e0
[  277.277406][ T7020]  ? do_syscall_64+0x85/0x160
[  277.277409][ T7020]  ? do_syscall_64+0x85/0x160
[  277.277411][ T7020]  ? syscall_exit_to_user_mode+0xc/0x1e0
[  277.277414][ T7020]  ? do_syscall_64+0x85/0x160
[  277.277416][ T7020]  ? syscall_exit_to_user_mode+0xc/0x1e0
[  277.277419][ T7020]  ? do_syscall_64+0x85/0x160
[  277.277421][ T7020]  ? do_syscall_64+0x85/0x160
[  277.277423][ T7020]  ? exc_page_fault+0x57/0xc0
[  277.277426][ T7020]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[  277.277430][ T7020] RIP: 0033:0x7f6527464b09
[  277.277432][ T7020] Code: ff 64 89 02 eb bd 66 2e 0f 1f 84 00 00 00 00 00 90 80 3d e1 fa 0c 00 00 41 89 ca 74 1c 45 31 c9 45 31 c0 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 67 c3 66 0f 1f 44 00 00 55 48 83 ec 20 48 89
[  277.277435][ T7020] RSP: 002b:00007ffd0dd36fa8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
[  277.277438][ T7020] RAX: ffffffffffffffda RBX: 00007ffd0dd37050 RCX: 00007f6527464b09
[  277.277440][ T7020] RDX: 000000000000001c RSI: 00007f65241197d0 RDI: 0000000000000013
[  277.277441][ T7020] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[  277.277443][ T7020] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
[  277.277444][ T7020] R13: ffffffffc4653600 R14: 0000000000000000 R15: 0000000000000000
[  277.277447][ T7020]  </TASK>
[  277.277448][ T7020] 
[  277.284535][  T332] dtim_period=2
[  277.286491][ T7020] The buggy address belongs to the physical page:
[  277.286492][ T7020] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff888192fe4000 pfn:0x192fe0
[  277.286495][ T7020] flags: 0x17ffffc0000000(node=0|zone=2|lastcpupid=0x1fffff)
[  277.286510][ T7020] raw: 0017ffffc0000000 ffffea0004bcfc08 ffff8881341c6f70 0000000000000000
[  277.293892][  T332] 
[  277.296053][ T7020] raw: ffff888192fe4000 0000000000000000 00000000ffffffff 0000000000000000
[  277.296054][ T7020] page dumped because: kasan: bad access detected
[  277.296055][ T7020] 
[  277.296056][ T7020] Memory state around the buggy address:
[  277.296058][ T7020]  ffff888192fe0400: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[  277.309044][  T332] eht_oper_chwidth=0
[  277.313290][ T7020]  ffff888192fe0480: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[  277.313292][ T7020] >ffff888192fe0500: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[  277.313294][ T7020]                                      ^
[  277.313295][ T7020]  ffff888192fe0580: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[  277.313296][ T7020]  ffff888192fe0600: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[  277.313308][ T7020] ==================================================================
[  277.321213][  T332] 
[  277.324328][ T7020] Disabling lock debugging due to kernel taint
diff mbox series

Patch

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index c14e4c2210b3..bcb2d36dcc44 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5446,6 +5446,18 @@  struct wiphy_iftype_akm_suites {
 	int n_akm_suites;
 };
 
+/**
+ * struct wiphy_radio_cfg - physical radio config of a wiphy
+ * This structure describes the configurations of a physical radio in a
+ * wiphy. It is used to denote per-radio attributes belonging to a wiphy.
+ *
+ * @rts_threshold: RTS threshold (dot11RTSThreshold);
+ *	-1 (default) = RTS/CTS disabled
+ */
+struct wiphy_radio_cfg {
+	u32 rts_threshold;
+};
+
 /**
  * struct wiphy_radio_freq_range - wiphy frequency range
  * @start_freq:  start range edge frequency (kHz)
@@ -5701,6 +5713,10 @@  struct wiphy_radio {
  *	supports enabling HW timestamping for all peers (i.e. no need to
  *	specify a mac address).
  *
+ * @radio_cfg: configuration of radios belonging to a muli-radio wiphy. This
+ *	struct contains a list of all radio specific attributes and should be
+ *	used only for multi-radio wiphy.
+ *
  * @radio: radios belonging to this wiphy
  * @n_radio: number of radios
  */
@@ -5790,6 +5806,8 @@  struct wiphy {
 	void (*reg_notifier)(struct wiphy *wiphy,
 			     struct regulatory_request *request);
 
+	struct wiphy_radio_cfg *radio_cfg;
+
 	/* fields below are read-only, assigned by cfg80211 */
 
 	const struct ieee80211_regdomain __rcu *regd;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index dcce326fdb8c..32306593d449 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -995,6 +995,24 @@  int wiphy_register(struct wiphy *wiphy)
 		 wiphy->max_num_akm_suites > CFG80211_MAX_NUM_AKM_SUITES)
 		return -EINVAL;
 
+	/* Allocate radio configuration space for multi-radio wiphy */
+	if (wiphy->n_radio > 0) {
+		int idx;
+
+		wiphy->radio_cfg = kcalloc(wiphy->n_radio,
+					   sizeof(*wiphy->radio_cfg),
+					   GFP_KERNEL);
+		if (!wiphy->radio_cfg)
+			return -ENOMEM;
+		/*
+		 * Initialize wiphy radio parameters to IEEE 802.11
+		 * MIB default values. RTS threshold is disabled by
+		 * default with the special -1 value.
+		 */
+		for (idx = 0; idx < wiphy->n_radio; idx++)
+			wiphy->radio_cfg[idx].rts_threshold = (u32)-1;
+	}
+
 	/* check and set up bitrates */
 	ieee80211_set_bitrate_flags(wiphy);
 
@@ -1223,6 +1241,7 @@  void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
 void wiphy_free(struct wiphy *wiphy)
 {
 	put_device(&wiphy->dev);
+	kfree(wiphy->radio_cfg);
 }
 EXPORT_SYMBOL(wiphy_free);
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c1bc3662da8d..23f4bfd404e9 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3609,6 +3609,33 @@  static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
 	return __nl80211_set_channel(rdev, netdev, info, link_id);
 }
 
+static int nl80211_set_wiphy_radio(struct genl_info *info,
+				   struct cfg80211_registered_device *rdev,
+				   int radio_idx)
+{
+	u32 rts_threshold = 0, old_rts, changed = 0;
+	int result;
+
+	if (!rdev->ops->set_wiphy_params)
+		return -EOPNOTSUPP;
+
+	if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
+		rts_threshold = nla_get_u32(
+				info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
+		changed |= WIPHY_PARAM_RTS_THRESHOLD;
+	}
+
+	old_rts = rdev->wiphy.radio_cfg[radio_idx].rts_threshold;
+
+	rdev->wiphy.radio_cfg[radio_idx].rts_threshold = rts_threshold;
+
+	result = rdev_set_wiphy_params(rdev, radio_idx, changed);
+	if (result)
+		rdev->wiphy.radio_cfg[radio_idx].rts_threshold = old_rts;
+
+	return 0;
+}
+
 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = NULL;
@@ -3681,6 +3708,8 @@  static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 				info->attrs[NL80211_ATTR_WIPHY_RADIO_INDEX]);
 		if (radio_idx >= rdev->wiphy.n_radio)
 			return -EINVAL;
+
+		return nl80211_set_wiphy_radio(info, rdev, radio_idx);
 	}
 
 	if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
@@ -3893,16 +3922,30 @@  static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 	if (changed) {
 		u8 old_retry_short, old_retry_long;
 		u32 old_frag_threshold, old_rts_threshold;
-		u8 old_coverage_class;
+		u8 old_coverage_class, i;
 		u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
+		u32 *old_radio_rts_threshold = NULL;
 
 		if (!rdev->ops->set_wiphy_params)
 			return -EOPNOTSUPP;
 
+		if (rdev->wiphy.n_radio) {
+			old_radio_rts_threshold = kcalloc(rdev->wiphy.n_radio,
+							  sizeof(u32),
+							  GFP_KERNEL);
+			if (!old_radio_rts_threshold)
+				return -ENOMEM;
+		}
+
 		old_retry_short = rdev->wiphy.retry_short;
 		old_retry_long = rdev->wiphy.retry_long;
 		old_frag_threshold = rdev->wiphy.frag_threshold;
 		old_rts_threshold = rdev->wiphy.rts_threshold;
+		if (old_radio_rts_threshold) {
+			for (i = 0 ; i < rdev->wiphy.n_radio; i++)
+				old_radio_rts_threshold[i] =
+					rdev->wiphy.radio_cfg[i].rts_threshold;
+		}
 		old_coverage_class = rdev->wiphy.coverage_class;
 		old_txq_limit = rdev->wiphy.txq_limit;
 		old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
@@ -3914,8 +3957,13 @@  static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 			rdev->wiphy.retry_long = retry_long;
 		if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
 			rdev->wiphy.frag_threshold = frag_threshold;
-		if (changed & WIPHY_PARAM_RTS_THRESHOLD)
+		if ((changed & WIPHY_PARAM_RTS_THRESHOLD) &&
+		    old_radio_rts_threshold) {
 			rdev->wiphy.rts_threshold = rts_threshold;
+			for (i = 0 ; i < rdev->wiphy.n_radio; i++)
+				rdev->wiphy.radio_cfg[i].rts_threshold =
+					rdev->wiphy.rts_threshold;
+		}
 		if (changed & WIPHY_PARAM_COVERAGE_CLASS)
 			rdev->wiphy.coverage_class = coverage_class;
 		if (changed & WIPHY_PARAM_TXQ_LIMIT)
@@ -3931,12 +3979,20 @@  static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 			rdev->wiphy.retry_long = old_retry_long;
 			rdev->wiphy.frag_threshold = old_frag_threshold;
 			rdev->wiphy.rts_threshold = old_rts_threshold;
+			if (old_radio_rts_threshold) {
+				for (i = 0 ; i < rdev->wiphy.n_radio; i++)
+					rdev->wiphy.radio_cfg[i].rts_threshold =
+						old_radio_rts_threshold[i];
+			}
 			rdev->wiphy.coverage_class = old_coverage_class;
 			rdev->wiphy.txq_limit = old_txq_limit;
 			rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
 			rdev->wiphy.txq_quantum = old_txq_quantum;
 			return result;
 		}
+
+		kfree(old_radio_rts_threshold);
+		return result;
 	}
 
 	return 0;