diff mbox series

[RFC,v2] wifi: cfg80211: fix cqm_config access race

Message ID 20230815134247.4b4bd52ea708.I1a1bb102329fc88e4712eaf394cba3025ada0dc7@changeid
State Superseded
Headers show
Series [RFC,v2] wifi: cfg80211: fix cqm_config access race | expand

Commit Message

Johannes Berg Aug. 15, 2023, 11:42 a.m. UTC
From: Johannes Berg <johannes.berg@intel.com>

Max Schulze reports crashes with brcmfmac. The reason seems
to be a race between userspace removing the CQM config and
the driver calling cfg80211_cqm_rssi_notify(), where if the
data is freed while cfg80211_cqm_rssi_notify() runs it will
crash since it assumes wdev->cqm_config is set. This can't
be fixed with a simple non-NULL check since there's nothing
we can do for locking easily, so use RCU instead to protect
the pointer, but that requires pulling the updates out into
an asynchronous worker so they can sleep and call back into
the driver.

Since we need to change the free anyway, also change it to
go back to the old settings if changing the settings fails.

Reported-by: Max Schulze <max.schulze@online.de>
Closes: https://lore.kernel.org/r/ac96309a-8d8d-4435-36e6-6d152eb31876@online.de
Fixes: 4a4b8169501b ("cfg80211: Accept multiple RSSI thresholds for CQM")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/cfg80211.h |  3 +-
 net/wireless/core.c    | 14 +++----
 net/wireless/core.h    |  7 +++-
 net/wireless/nl80211.c | 84 ++++++++++++++++++++++++++++--------------
 4 files changed, 70 insertions(+), 38 deletions(-)

Comments

Johannes Berg Aug. 15, 2023, 1:25 p.m. UTC | #1
On Tue, 2023-08-15 at 15:24 +0200, Max Schulze wrote:
> Thanks again. I have to back-port it to 6.1.45 manually and will do testing.
> 

Ah, you can't port this to 6.1 series, it depends on commit a3ee4dc84c4e
("wifi: cfg80211: add a work abstraction with special semantics") which
is only in 6.5-rc...

Maybe you can cherry-pick that patch too.

johannes
Max Schulze Aug. 16, 2023, 7:23 a.m. UTC | #2
Johannes, thank you very much.

However, bad luck again, I get the following crash. Scouring the logs, this time I have no "rcu notice" or any other error beforehand.

But the timing again suggest a strong connection with RSSI update in progress.


h63 wpa_supplicant[433]: wlan0: CTRL-EVENT-CONNECTED - Connection to xx:xx:xx:xx:00:91 completed [id=0 id_str=]
h63 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI -57 dBm
h63 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI -57 dBm
h63 wpa_supplicant[433]: wlan0: CTRL-EVENT-SUBNET-STATUS-UPDATE status=0
h63 NetworkManager[429]: <info>  [1692169608.6737] device (wlan0): supplicant interface state: associating -> completed
h63 NetworkManager[429]: <info>  [1692169608.6764] device (p2p-dev-wlan0): supplicant management interface state: associating -> completed
h63 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI -57 dBm
h63 kernel: brcmfmac: brcmf_rx_event Enter: mmc1:0001:1: rxp=00000000414022d6
h63 kernel: brcmfmac: brcmf_fweh_event_worker event RSSI (56) ifidx 0 bsscfg 0 addr 00:00:00:00:00:00
h63 kernel: brcmfmac: brcmf_fweh_event_worker   version 2 flags 0 status 0 reason 0
h63 kernel: brcmutil: event payload, len=12
h63 kernel: 00000000: ff ff ff c6 00 00 00 00 ff ff ff a5 ............
h63 kernel: brcmfmac: brcmf_netdev_start_xmit wlan0: insufficient headroom (0)
h63 kernel: Unable to handle kernel paging request at virtual address ffff8061d9850028
h63 kernel: Mem abort info:
h63 kernel:   ESR = 0x0000000096000004
h63 kernel:   EC = 0x25: DABT (current EL), IL = 32 bits
h63 kernel:   SET = 0, FnV = 0
h63 kernel:   EA = 0, S1PTW = 0
h63 kernel:   FSC = 0x04: level 0 translation fault
h63 kernel: Data abort info:
h63 kernel:   ISV = 0, ISS = 0x00000004
h63 kernel:   CM = 0, WnR = 0
h63 kernel: [ffff8061d9850028] address between user and kernel address ranges
h63 kernel: Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
h63 kernel: Modules linked in: rtc_pcf85063 regmap_i2c ov9281 v3d brcmfmac vc4 gpu_sched raspberrypi_hwmon drm_shmem_helper binfmt_misc brcmutil gpio_keys snd_soc_hdmi_codec i2c_mux_pinctrl>
h63 kernel: CPU: 3 PID: 493 Comm: Xorg Tainted: G         C 6.1.45-v8-gdc69f9d60872 #3
h63 kernel: Hardware name: Raspberry Pi Compute Module 4 Rev 1.0 (DT)
h63 kernel: pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
h63 kernel: pc : dma_resv_add_fence+0x80/0x260
h63 kernel: lr : v3d_attach_fences_and_unlock_reservation+0x6c/0x1c0 [v3d]
h63 kernel: sp : ffffffc0093abb00
h63 kernel: x29: ffffffc0093abb00 x28: 0000000000000048 x27: ffffffc0093abd38
h63 kernel: x26: 0000000000000001 x25: ffffff80481e8e00 x24: ffffffc0093abc08
h63 kernel: x23: 0000000000000001 x22: ffffff805701ac40 x21: ffffffc0093abc20
h63 kernel: x20: ffffff804b995200 x19: ffff8061d9850000 x18: 0000000000000000
h63 kernel: x17: 0000000000000000 x16: ffffffdcdd1b9ba0 x15: 00000055b7e860c0
h63 kernel: x14: 0000000000000000 x13: 0000000000000202 x12: 0000000000000202
h63 kernel: x11: 0000000000000202 x10: 0000000000001a90 x9 : ffffffdc7c7bdecc
h63 kernel: x8 : 0000000000000228 x7 : ffffff804416caa8 x6 : 0000000000000000
h63 kernel: x5 : ffffff805701ac40 x4 : ffffff805701ac78 x3 : 0000000000000000
h63 kernel: x2 : ffffffdc7c685478 x1 : ffffffdcdd680ce8 x0 : ffffffdcdd680d30
h63 kernel: Call trace:
h63 kernel:  dma_resv_add_fence+0x80/0x260
h63 kernel:  v3d_attach_fences_and_unlock_reservation+0x6c/0x1c0 [v3d]
h63 kernel:  v3d_submit_cl_ioctl+0x540/0x70c [v3d]
h63 kernel:  drm_ioctl_kernel+0xcc/0x180 [drm]
h63 kernel:  drm_ioctl+0x210/0x440 [drm]
h63 kernel:  __arm64_sys_ioctl+0xb0/0xf4
h63 kernel:  invoke_syscall+0x50/0x120
h63 kernel:  el0_svc_common.constprop.0+0x68/0x124
h63 kernel:  do_el0_svc+0x34/0xd0
h63 kernel:  el0_svc+0x30/0x94
h63 kernel:  el0t_64_sync_handler+0xb8/0xbc
h63 kernel:  el0t_64_sync+0x18c/0x190
h63 kernel: Code: fa401044 54000061 d4210000 d503201f (f9401678)
h63 kernel: ---[ end trace 0000000000000000 ]---
Johannes Berg Aug. 16, 2023, 7:30 a.m. UTC | #3
Hi,

This is ... pretty odd?

> h63 kernel: Unable to handle kernel paging request at virtual address ffff8061d9850028
> h63 kernel: Mem abort info:
> h63 kernel:   ESR = 0x0000000096000004
> h63 kernel:   EC = 0x25: DABT (current EL), IL = 32 bits
> h63 kernel:   SET = 0, FnV = 0
> h63 kernel:   EA = 0, S1PTW = 0
> h63 kernel:   FSC = 0x04: level 0 translation fault
> h63 kernel: Data abort info:
> h63 kernel:   ISV = 0, ISS = 0x00000004
> h63 kernel:   CM = 0, WnR = 0
> h63 kernel: [ffff8061d9850028] address between user and kernel address ranges
> h63 kernel: Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
> h63 kernel: Modules linked in: [...]
> h63 kernel: CPU: 3 PID: 493 Comm: Xorg Tainted: G         C 6.1.45-v8-gdc69f9d60872 #3
> h63 kernel: Hardware name: Raspberry Pi Compute Module 4 Rev 1.0 (DT)
> h63 kernel: pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> h63 kernel: pc : dma_resv_add_fence+0x80/0x260

I mean, that's in some other code entirely?

> h63 kernel: Call trace:
> h63 kernel:  dma_resv_add_fence+0x80/0x260
> h63 kernel:  v3d_attach_fences_and_unlock_reservation+0x6c/0x1c0 [v3d]
> h63 kernel:  v3d_submit_cl_ioctl+0x540/0x70c [v3d]
> h63 kernel:  drm_ioctl_kernel+0xcc/0x180 [drm]
> h63 kernel:  drm_ioctl+0x210/0x440 [drm]
> h63 kernel:  __arm64_sys_ioctl+0xb0/0xf4
> h63 kernel:  invoke_syscall+0x50/0x120
> h63 kernel:  el0_svc_common.constprop.0+0x68/0x124
> h63 kernel:  do_el0_svc+0x34/0xd0
> h63 kernel:  el0_svc+0x30/0x94
> h63 kernel:  el0t_64_sync_handler+0xb8/0xbc
> h63 kernel:  el0t_64_sync+0x18c/0x190
> h63 kernel: Code: fa401044 54000061 d4210000 d503201f (f9401678)

Unless my code caused some really bad corruption somewhere, I'm not sure
I see how that would happen?


Were you able to reproduce it multiple times? Maybe we can see a pattern
out of multiple reports.

johannes
Max Schulze Aug. 16, 2023, 11:24 a.m. UTC | #4
You are right, I have no clear proof.

However, here is a second trace from the same system.
Another system has crashed, I have not recovered the trace yet.

The context, that there is a RSSI notification just beforehand, is exactly the same (as the initial bug report).

You have a clue?


Aug 16 11:03:32 h63 wpa_supplicant[389]: wlan0: Associated with 
xx:xx:xx:xx:00:91
Aug 16 11:03:32 h63 wpa_supplicant[389]: wlan0: CTRL-EVENT-CONNECTED - 
Connection to xx:xx:xx:xx:00:91 completed [id=0 id_str=]
Aug 16 11:03:32 h63 wpa_supplicant[389]: wlan0: 
CTRL-EVENT-SUBNET-STATUS-UPDATE status=0
Aug 16 11:03:32 h63 NetworkManager[373]: <info>  [1692176612.2898] 
device (wlan0): supplicant interface state: associating -> completed
Aug 16 11:03:32 h63 NetworkManager[373]: <info>  [1692176612.2933] 
device (p2p-dev-wlan0): supplicant management interface state: 
associating -> completed
Aug 16 11:03:32 h63 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI 
-63 dBm
Aug 16 11:03:32 h63 kernel: brcmfmac: brcmf_rx_event Enter: mmc1:0001:1: 
rxp=00000000b1aa24a9
Aug 16 11:03:32 h63 kernel: brcmfmac: brcmf_fweh_event_worker event RSSI 
(56) ifidx 0 bsscfg 0 addr 00:00:00:ab:c0:c1
Aug 16 11:03:32 h63 kernel: brcmfmac: brcmf_fweh_event_worker   version 
2 flags 0 status 0 reason 0
Aug 16 11:03:32 h63 kernel: brcmutil: event payload, len=12
Aug 16 11:03:32 h63 kernel: 00000000: ff ff ff c1 00 00 00 00 ff ff ff 
a5              ............
Aug 16 11:03:35 h63 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI 
-63 dBm
Aug 16 11:03:40 h63 kernel: Unable to handle kernel NULL pointer 
dereference at virtual address 00000000000000cc
Aug 16 11:03:40 h63 kernel: Mem abort info:
Aug 16 11:03:41 h63 kernel:   ESR = 0x0000000096000005
Aug 16 11:03:41 h63 kernel:   EC = 0x25: DABT (current EL), IL = 32 bits
Aug 16 11:03:41 h63 kernel:   SET = 0, FnV = 0
Aug 16 11:03:41 h63 kernel:   EA = 0, S1PTW = 0
Aug 16 11:03:41 h63 kernel:   FSC = 0x05: level 1 translation fault
Aug 16 11:03:41 h63 kernel: Data abort info:
Aug 16 11:03:41 h63 kernel:   ISV = 0, ISS = 0x00000005
Aug 16 11:03:41 h63 kernel:   CM = 0, WnR = 0
Aug 16 11:03:41 h63 kernel: user pgtable: 4k pages, 39-bit VAs, 
pgdp=0000000049427000
Aug 16 11:03:41 h63 kernel: [00000000000000cc] pgd=0000000000000000, 
p4d=0000000000000000, pud=0000000000000000
Aug 16 11:03:41 h63 kernel: Internal error: Oops: 0000000096000005 [#1] 
PREEMPT SMP
Aug 16 11:03:41 h63 kernel: Modules linked in: rtc_pcf85063 ov9281 
regmap_i2c brcmfmac vc4 brcmutil cfg80211 snd_soc_hdmi_codec 
drm_display_helper cec drm_dma_helper drm_kms_helper v3d gpu_sched 
binfmt_mis>
Aug 16 11:03:41 h63 kernel: CPU: 2 PID: 491 Comm: Xorg Tainted: G 
 C         6.1.45-v8-gdc69f9d60872 #3
Aug 16 11:03:41 h63 kernel: Hardware name: Raspberry Pi Compute Module 4 
Rev 1.0 (DT)
Aug 16 11:03:41 h63 kernel: pstate: 80000005 (Nzcv daif -PAN -UAO -TCO 
-DIT -SSBS BTYPE=--)
Aug 16 11:03:41 h63 kernel: pc : drm_ioctl+0x284/0x440 [drm]
Aug 16 11:03:41 h63 kernel: lr : drm_ioctl+0xac/0x440 [drm]
Aug 16 11:03:41 h63 kernel: sp : ffffffc00935bca0
Aug 16 11:03:41 h63 kernel: x29: ffffffc00935bcb0 x28: ffffff8045499f00 
x27: 0000000000000000
Aug 16 11:03:41 h63 kernel: x26: 0000000000000000 x25: ffffff804806a800 
x24: 0000000000000041
Aug 16 11:03:41 h63 kernel: x23: ffffff804946d900 x22: 00000000c0106441 
x21: 0000007fc2a766f8
Aug 16 11:03:41 h63 kernel: x20: ffffff8040370000 x19: 0000000000000001 
x18: 0000000000000000
Aug 16 11:03:41 h63 kernel: x17: 0000000000000000 x16: ffffffe34ff1a2d0 
x15: 0000000000000000
Aug 16 11:03:41 h63 kernel: x14: 0000000000000000 x13: 0000000000000000 
x12: 0000000000000000
Aug 16 11:03:41 h63 kernel: x11: 0000000000000000 x10: 0000000000000000 
x9 : ffffffe315a9eed0
Aug 16 11:03:41 h63 kernel: x8 : 0000000000000000 x7 : 0000000000000000 
x6 : 0000000000159ba4
Aug 16 11:03:41 h63 kernel: x5 : 0000000000159ba5 x4 : 0000000000000000 
x3 : 0000000000000001
Aug 16 11:03:41 h63 kernel: x2 : ffffff8045499f00 x1 : ffffff9d2eca5000 
x0 : 0000000000000004
Aug 16 11:03:41 h63 kernel: Call trace:
Aug 16 11:03:41 h63 kernel:  drm_ioctl+0x284/0x440 [drm]
Aug 16 11:03:41 h63 kernel:  __arm64_sys_ioctl+0xb0/0xf4
Aug 16 11:03:41 h63 kernel:  invoke_syscall+0x50/0x120
Aug 16 11:03:41 h63 kernel:  el0_svc_common.constprop.0+0x68/0x124
Aug 16 11:03:41 h63 kernel:  do_el0_svc+0x34/0xd0
Aug 16 11:03:41 h63 kernel:  el0_svc+0x30/0x94
Aug 16 11:03:41 h63 kernel:  el0t_64_sync_handler+0xb8/0xbc
Aug 16 11:03:41 h63 kernel:  el0t_64_sync+0x18c/0x190
Aug 16 11:03:41 h63 kernel: Code: 35000455 a94673fb 17ffff7b f9401a80 
(b940c800)
Aug 16 11:03:41 h63 kernel: ---[ end trace 0000000000000000 ]---
Aug 16 11:03:41 h63 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI 
-67 dBm
Aug 16 11:03:45 h63 kernel: brcmfmac: brcmf_netdev_start_xmit wlan0: 
insufficient headroom (0)
Aug 16 11:03:45 h63 kernel: brcmfmac: brcmf_netdev_start_xmit wlan0: 
insufficient headroom (0)
Max Schulze Aug. 16, 2023, 1:08 p.m. UTC | #5
Trace from the system I couldn't reach.

Looks similar to the first.

There must be something at odds with the patch.

Aug 16 09:27:03 h91 wpa_supplicant[367]: wlan0: Associated with 
xx:xx:xx:xx:a1:80
Aug 16 09:27:03 h91 wpa_supplicant[367]: wlan0: CTRL-EVENT-CONNECTED - 
Connection to xx:xx:xx:xx:a1:80 completed [id=0 id_str=]
Aug 16 09:27:03 h91 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI 
-54 dBm
Aug 16 09:27:03 h91 kernel: brcmfmac: brcmf_setup_wiphybands nmode=1, 
vhtmode=1, bw_cap=(3, 7)
Aug 16 09:27:03 h91 kernel: brcmfmac: brcmf_setup_wiphybands nchain=1
Aug 16 09:27:03 h91 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI 
-54 dBm
Aug 16 09:27:03 h91 wpa_supplicant[367]: wlan0: 
CTRL-EVENT-SUBNET-STATUS-UPDATE status=0
Aug 16 09:27:03 h91 wpa_supplicant[367]: wlan0: CTRL-EVENT-REGDOM-CHANGE 
init=COUNTRY_IE type=COUNTRY alpha2=US
Aug 16 09:27:03 h91 NetworkManager[342]: <info>  [1692170823.3861] 
device (wlan0): supplicant interface state: associating -> completed
Aug 16 09:27:03 h91 NetworkManager[342]: <info>  [1692170823.3862] 
device (p2p-dev-wlan0): supplicant management interface state: 
associating -> completed
Aug 16 09:27:03 h91 kernel: brcmfmac: brcmf_rx_event Enter: mmc1:0001:1: 
rxp=000000007fc0b9df
Aug 16 09:27:03 h91 kernel: brcmfmac: brcmf_fweh_event_worker event RSSI 
(56) ifidx 0 bsscfg 0 addr 00:00:00:00:00:00
Aug 16 09:27:03 h91 kernel: brcmfmac: brcmf_fweh_event_worker   version 
2 flags 0 status 0 reason 0
Aug 16 09:27:03 h91 kernel: brcmutil: event payload, len=12
Aug 16 09:27:03 h91 kernel: 00000000: ff ff ff ca 00 00 00 00 ff ff ff 
a5              ............
Aug 16 09:27:04 h91 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI 
-57 dBm
Aug 16 09:27:05 h91 kernel: Unable to handle kernel NULL pointer 
dereference at virtual address 00000000000000cf
Aug 16 09:27:05 h91 kernel: Mem abort info:
Aug 16 09:27:05 h91 kernel:   ESR = 0x0000000096000005
Aug 16 09:27:05 h91 kernel:   EC = 0x25: DABT (current EL), IL = 32 bits
Aug 16 09:27:05 h91 kernel:   SET = 0, FnV = 0
Aug 16 09:27:05 h91 kernel:   EA = 0, S1PTW = 0
Aug 16 09:27:05 h91 kernel:   FSC = 0x05: level 1 translation fault
Aug 16 09:27:05 h91 kernel: Data abort info:
Aug 16 09:27:05 h91 kernel:   ISV = 0, ISS = 0x00000005
Aug 16 09:27:05 h91 kernel:   CM = 0, WnR = 0
Aug 16 09:27:05 h91 kernel: user pgtable: 4k pages, 39-bit VAs, 
pgdp=000000004b56b000
Aug 16 09:27:05 h91 kernel: [00000000000000cf] pgd=0000000000000000, 
p4d=0000000000000000, pud=0000000000000000
Aug 16 09:27:05 h91 kernel: Internal error: Oops: 0000000096000005 [#1] 
PREEMPT SMP
Aug 16 09:27:05 h91 kernel: Modules linked in: ov9281 rtc_pcf85063 
regmap_i2c vc4 snd_soc_hdmi_codec drm_display_helper cec drm_dma_helper 
v3d brcmfmac drm_kms_helper gpu_sched drm_shmem_helper brcmutil g>
Aug 16 09:27:05 h91 kernel: CPU: 3 PID: 488 Comm: Xorg Tainted: G 
 C         6.1.45-v8-gdc69f9d60872 #3
Aug 16 09:27:05 h91 kernel: Hardware name: Raspberry Pi Compute Module 4 
Rev 1.0 (DT)
Aug 16 09:27:05 h91 kernel: pstate: 80000005 (Nzcv daif -PAN -UAO -TCO 
-DIT -SSBS BTYPE=--)
Aug 16 09:27:05 h91 kernel: pc : drm_ioctl+0x284/0x440 [drm]
Aug 16 09:27:05 h91 kernel: lr : drm_ioctl+0xac/0x440 [drm]
Aug 16 09:27:05 h91 kernel: sp : ffffffc00933bca0
Aug 16 09:27:05 h91 kernel: x29: ffffffc00933bcb0 x28: ffffff8044acdd00 
x27: 0000000000000000
Aug 16 09:27:05 h91 kernel: x26: 0000000000000000 x25: ffffff804376a800 
x24: 0000000000000041
Aug 16 09:27:05 h91 kernel: x23: ffffff804e849200 x22: 00000000c0106441 
x21: 0000007ffd46ebf8
Aug 16 09:27:05 h91 kernel: x20: ffffff8040a4e000 x19: 0000000000000001 
x18: 0000000000000000
Aug 16 09:27:05 h91 kernel: x17: 0000000000000000 x16: ffffffea06d1a2d0 
x15: 0000000000000000
Aug 16 09:27:05 h91 kernel: x14: 0000000000000000 x13: 0000000000000000 
x12: 0000000000000000
Aug 16 09:27:05 h91 kernel: x11: 0000000000000000 x10: 0000000000000000 
x9 : ffffffe9a6773ed0
Aug 16 09:27:05 h91 kernel: x8 : 0000000000000000 x7 : 0000000000000000 
x6 : 000000000005e9e5
Aug 16 09:27:05 h91 kernel: x5 : 000000000005e9e5 x4 : 0000000000000000 
x3 : 0000000000000001
Aug 16 09:27:05 h91 kernel: x2 : ffffff8044acdd00 x1 : ffffff9677ec2000 
x0 : 0000000000000007
Aug 16 09:27:05 h91 kernel: Call trace:
Aug 16 09:27:05 h91 kernel:  drm_ioctl+0x284/0x440 [drm]
Aug 16 09:27:05 h91 kernel:  __arm64_sys_ioctl+0xb0/0xf4
Aug 16 09:27:05 h91 kernel:  invoke_syscall+0x50/0x120
Aug 16 09:27:05 h91 kernel:  el0_svc_common.constprop.0+0x68/0x124
Aug 16 09:27:05 h91 kernel:  do_el0_svc+0x34/0xd0
Aug 16 09:27:05 h91 kernel:  el0_svc+0x30/0x94
Aug 16 09:27:05 h91 kernel:  el0t_64_sync_handler+0xb8/0xbc
Aug 16 09:27:05 h91 kernel:  el0t_64_sync+0x18c/0x190
Aug 16 09:27:05 h91 kernel: Code: 35000455 a94673fb 17ffff7b f9401a80 
(b940c800)
Aug 16 09:27:05 h91 kernel: ---[ end trace 0000000000000000 ]---
Aug 16 09:27:10 h91 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI 
-58 dBm
Aug 16 09:27:16 h91 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI 
-58 dBm
Johannes Berg Aug. 16, 2023, 1:17 p.m. UTC | #6
On Wed, 2023-08-16 at 15:08 +0200, Max Schulze wrote:
> Trace from the system I couldn't reach.
> 
> Looks similar to the first.

Thanks.

> There must be something at odds with the patch.

Yeah I guess I haven't made it any better, have I :)


> Aug 16 09:27:04 h91 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI -57 dBm

It's kind of interesting that we see this preceding the crash - even if
the crash then is in something else entirely. Makes me think something
else got corrupted here. I'll take a look at the patch again, maybe I
can spot something.

johannes
Johannes Berg Aug. 16, 2023, 1:27 p.m. UTC | #7
On Tue, 2023-08-15 at 15:37 +0200, Johannes Berg wrote:
> 
>  
> -	err = cfg80211_cqm_rssi_update(rdev, dev);
> +	err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config);
> +	if (err) {
> +		rcu_assign_pointer(wdev->cqm_config, old);
> +		kfree(cqm_config);


OK, that's wrong wrt. RCU handling, maybe that causes heap corruption if
someone sees wdev->cqm_config under RCU but it was freed and re-
allocated.

I think I'll just remove this failure path handling change entirely and
do it separately.

johannes
Max Schulze Aug. 16, 2023, 1:33 p.m. UTC | #8
Look, this trace points to something in the worker structure/mm:

14:04:50 h63 wpa_supplicant[376]: wlan0: CTRL-EVENT-CONNECTED - Connection to xx:xx:xx:xx:c7:a8 completed [id=0 id_str=]

14:04:50 h63 kernel: brcmfmac: brcmf_wifi_prioritize_acparams ACI 0 aifsn 3 acm 0 ecwmin 4 ecwmax 10

14:04:50 h63 kernel: brcmfmac: brcmf_wifi_prioritize_acparams ACI 1 aifsn 7 acm 0 ecwmin 4 ecwmax 10

14:04:50 h63 kernel: brcmfmac: brcmf_wifi_prioritize_acparams ACI 2 aifsn 2 acm 0 ecwmin 3 ecwmax 4

14:04:50 h63 kernel: brcmfmac: brcmf_wifi_prioritize_acparams ACI 3 aifsn 2 acm 0 ecwmin 2 ecwmax 3

14:04:50 h63 kernel: brcmfmac: brcmf_wifi_prioritize_acparams Adj prio BE 0->1, BK 1->0, BK 2->0, BE 3->1

14:04:50 h63 kernel: brcmfmac: brcmf_wifi_prioritize_acparams Adj prio VI 4->2, VI 5->2, VO 6->3, VO 7->3

14:04:50 h63 kernel: brcmfmac: brcmf_get_assoc_ies req len (76) resp len (33)

14:04:50 h63 kernel: brcmfmac: brcmf_inform_single_bss bssid: xx:xx:xx:xx:c7:a8

14:04:50 h63 kernel: brcmfmac: brcmf_inform_single_bss Channel: 3(2422)

14:04:50 h63 kernel: brcmfmac: brcmf_inform_single_bss Capability: 431

14:04:50 h63 kernel: brcmfmac: brcmf_inform_single_bss Beacon interval: 100

14:04:50 h63 kernel: brcmfmac: brcmf_inform_single_bss Signal: -5400

14:04:50 h63 kernel: brcmfmac: brcmf_bss_connect_done Report connect result - connection succeeded

14:04:50 h63 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI -54 dBm

14:04:50 h63 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI -54 dBm

14:04:50 h63 wpa_supplicant[376]: wlan0: CTRL-EVENT-SUBNET-STATUS-UPDATE status=0

14:04:50 h63 NetworkManager[362]: <info>  [1692187490.4879] device (wlan0): supplicant interface state: associating -> completed

14:04:50 h63 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI -54 dBm

14:04:50 h63 NetworkManager[362]: <info>  [1692187490.4907] device (p2p-dev-wlan0): supplicant management interface state: associating -> completed

14:04:50 h63 kernel: brcmfmac: brcmf_rx_event Enter: mmc1:0001:1: rxp=00000000f4393a20

14:04:50 h63 kernel: brcmfmac: brcmf_fweh_event_worker event RSSI (56) ifidx 0 bsscfg 0 addr 00:00:00:00:00:00

14:04:50 h63 kernel: brcmfmac: brcmf_fweh_event_worker   version 2 flags 0 status 0 reason 0

14:04:50 h63 kernel: brcmutil: event payload, len=12

14:04:50 h63 kernel: 00000000: ff ff ff ca 00 00 00 00 ff ff ff a5              ............

14:04:55 h63 kernel: brcmfmac: brcmf_cfg80211_get_station RSSI -47 dBm

14:04:59 h63 kernel: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000070

14:04:59 h63 kernel: Mem abort info:

14:04:59 h63 kernel:   ESR = 0x0000000096000005

14:04:59 h63 kernel:   EC = 0x25: DABT (current EL), IL = 32 bits

14:04:59 h63 kernel:   SET = 0, FnV = 0

14:04:59 h63 kernel:   EA = 0, S1PTW = 0

14:04:59 h63 kernel:   FSC = 0x05: level 1 translation fault

14:04:59 h63 kernel: Data abort info:

14:04:59 h63 kernel:   ISV = 0, ISS = 0x00000005

14:04:59 h63 kernel:   CM = 0, WnR = 0

14:04:59 h63 kernel: user pgtable: 4k pages, 39-bit VAs, pgdp=00000000465b3000

14:04:59 h63 kernel: [0000000000000070] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000

14:04:59 h63 kernel: Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP

14:04:59 h63 kernel: Modules linked in: ov9281 rtc_pcf85063 regmap_i2c vc4 brcmfmac snd_soc_hdmi_codec brcmutil drm_display_helper cec drm_dma_helper v3d cfg80211 gpio_keys i2c_mux_pinctrl drm_kms_helper i2c_mux gpu_sched drm_shmem_helper bcm2835_unicam bcm2835_codec(C) rpivid_hevc(C) snd_soc_core v4l2_dv_timings raspberrypi_hwmon v4l2_fwnode bcm2835_v4l2(C) v4l2_async v4l2_mem2mem bcm2835_isp(C) bcm2835_mmal_vchiq(C) videobuf2_vmalloc i2c_brcmstb videobuf2_dma_contig snd_compress videobuf2_memops snd_bcm2835(C) videobuf2_v4l2 videobuf2_common binfmt_misc snd_pcm_dmaengine videodev snd_pcm rfkill snd_timer i2c_bcm2835 snd vc_sm_cma(C) mc syscopyarea sysfillrect sysimgblt fb_sys_fops nvmem_rmem uio_pdrv_genirq uio drm dm_mod fuse drm_panel_orientation_quirks backlight ip_tables x_tables ipv6

14:04:59 h63 kernel: CPU: 0 PID: 1184 Comm: kworker/0:0 Tainted: G         C         6.1.45-v8-gdc69f9d60872 #3

14:04:59 h63 kernel: Hardware name: Raspberry Pi Compute Module 4 Rev 1.0 (DT)

14:04:59 h63 kernel: pstate: 00000005 (nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)

14:04:59 h63 kernel: pc : wq_worker_running+0x20/0x94

14:04:59 h63 kernel: lr : wq_worker_running+0x1c/0x94

14:04:59 h63 kernel: sp : ffffffc00a8c3dd0

14:04:59 h63 kernel: x29: ffffffc00a8c3dd0 x28: 0000000000000000 x27: 0000000000000000

14:04:59 h63 kernel: x26: ffffffdf40bfe498 x25: ffffffdf40a060f0 x24: ffffffdf409e6000

14:04:59 h63 kernel: x23: ffffffdf409e69c0 x22: ffffff807fb5dc28 x21: ffffff80445c9630

14:04:59 h63 kernel: x20: ffffff8045395d00 x19: 0000000000000000 x18: 0000000000000000

14:04:59 h63 kernel: x17: 0000000000000001 x16: 0000000000000001 x15: 00cddc74a125b114

14:04:59 h63 kernel: x14: 006cbf5eacfa360a x13: ffffffdf401fbc00 x12: 00000000fa83b2da

14:04:59 h63 kernel: x11: 00000000000003f3 x10: 0000000000001a90 x9 : ffffffdf3f6ae7ac

14:04:59 h63 kernel: x8 : ffffff80453977f0 x7 : 0000000000000001 x6 : 0000000000000000

14:04:59 h63 kernel: x5 : ffffffdf409ee000 x4 : ffffffdf409ee118 x3 : 0000000000000000

14:04:59 h63 kernel: x2 : 0000000000000001 x1 : 0000000004208060 x0 : 0000000000000000

14:04:59 h63 kernel: Call trace:

14:04:59 h63 kernel:  wq_worker_running+0x20/0x94

14:04:59 h63 kernel:  schedule+0x8c/0x100

14:04:59 h63 kernel:  worker_thread+0x1d0/0x450

14:04:59 h63 kernel:  kthread+0x104/0x110

14:04:59 h63 kernel:  ret_from_fork+0x10/0x20

14:04:59 h63 kernel: Code: 910003fd f9000bf3 940018bb aa0003f3 (b9407000)

14:04:59 h63 kernel: ---[ end trace 0000000000000000 ]---

14:04:59 h63 kernel: Unable to handle kernel paging request at virtual address fffffffffffffff8

14:04:59 h63 kernel: Mem abort info:

14:04:59 h63 kernel:   ESR = 0x0000000096000005

14:04:59 h63 kernel:   EC = 0x25: DABT (current EL), IL = 32 bits

14:05:00 h63 kernel:   SET = 0, FnV = 0

14:05:00 h63 kernel:   EA = 0, S1PTW = 0

14:05:00 h63 kernel:   FSC = 0x05: level 1 translation fault

14:05:00 h63 kernel: Data abort info:

14:05:00 h63 kernel:   ISV = 0, ISS = 0x00000005

14:05:00 h63 kernel:   CM = 0, WnR = 0

14:05:00 h63 kernel: swapper pgtable: 4k pages, 39-bit VAs, pgdp=00000000011d6000

14:05:00 h63 kernel: [fffffffffffffff8] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000

14:05:00 h63 kernel: Internal error: Oops: 0000000096000005 [#2] PREEMPT SMP

14:05:00 h63 kernel: Modules linked in: ov9281 rtc_pcf85063 regmap_i2c vc4 brcmfmac snd_soc_hdmi_codec brcmutil drm_display_helper cec drm_dma_helper v3d cfg80211 gpio_keys i2c_mux_pinctrl drm_kms_helper i2c_mux gpu_sched drm_shmem_helper bcm2835_unicam bcm2835_codec(C) rpivid_hevc(C) snd_soc_core v4l2_dv_timings raspberrypi_hwmon v4l2_fwnode bcm2835_v4l2(C) v4l2_async v4l2_mem2mem bcm2835_isp(C) bcm2835_mmal_vchiq(C) videobuf2_vmalloc i2c_brcmstb videobuf2_dma_contig snd_compress videobuf2_memops snd_bcm2835(C) videobuf2_v4l2 videobuf2_common binfmt_misc snd_pcm_dmaengine videodev snd_pcm rfkill snd_timer i2c_bcm2835 snd vc_sm_cma(C) mc syscopyarea sysfillrect sysimgblt fb_sys_fops nvmem_rmem uio_pdrv_genirq uio drm dm_mod fuse drm_panel_orientation_quirks backlight ip_tables x_tables ipv6

14:05:00 h63 kernel: CPU: 0 PID: 1184 Comm: kworker/0:0 Tainted: G      D  C         6.1.45-v8-gdc69f9d60872 #3

14:05:00 h63 kernel: Hardware name: Raspberry Pi Compute Module 4 Rev 1.0 (DT)

14:05:00 h63 kernel: pstate: 000000c5 (nzcv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)

14:05:00 h63 kernel: pc : complete+0x58/0x94

14:05:00 h63 kernel: lr : complete+0x2c/0x94

14:05:00 h63 kernel: sp : ffffffc00a8c3930

14:05:00 h63 kernel: x29: ffffffc00a8c3930 x28: ffffffc00a8c3ac3 x27: ffffffdf40489dc0

14:05:00 h63 kernel: x26: ffffffdf40489db8 x25: 0000000000000001 x24: ffffffdf3f6ae7b4

14:05:00 h63 kernel: x23: 0000000000000000 x22: 000000000000000b x21: 0000000000000000

14:05:00 h63 kernel: x20: ffffff8040b55ac8 x19: 0000000000000000 x18: 0000000000000000

14:05:00 h63 kernel: x17: 3030303030303030 x16: 3030303030303020 x15: 0000000000000030

14:05:00 h63 kernel: x14: 0000000000000000 x13: 2d2d2d5d20303030 x12: 3030303030303030

14:05:00 h63 kernel: x11: fffffffffffecd58 x10: fffffffffffecd08 x9 : ffffffdf401bbb5c

14:05:00 h63 kernel: x8 : ffffffdf40a0c788 x7 : ffffffdf40a64788 x6 : 0000000000000000

14:05:00 h63 kernel: x5 : ffffffc00a8c4000 x4 : ffffffc00a8c0000 x3 : 0000000000000000

14:05:00 h63 kernel: x2 : 0000000000000001 x1 : 0000000000000000 x0 : ffffff8040b55ad0

14:05:00 h63 kernel: Call trace:

14:05:00 h63 kernel:  complete+0x58/0x94

14:05:00 h63 kernel:  mm_release+0x58/0xd0

14:05:00 h63 kernel:  exit_mm_release+0x30/0x40

14:05:00 h63 kernel:  do_exit+0x214/0x9d0

14:05:00 h63 kernel:  make_task_dead+0xa8/0x1b0

14:05:00 h63 kernel:  die+0x1dc/0x218

14:05:00 h63 kernel:  die_kernel_fault+0x280/0x338

14:05:00 h63 kernel:  __do_kernel_fault+0x14c/0x1f4

14:05:00 h63 kernel:  do_page_fault+0xd8/0x3f4

14:05:00 h63 kernel:  do_translation_fault+0xb4/0xdc

14:05:00 h63 kernel:  do_mem_abort+0x4c/0xa0

14:05:00 h63 kernel:  el1_abort+0x44/0x74

14:05:00 h63 kernel:  el1h_64_sync_handler+0xd8/0xe4

14:05:00 h63 kernel:  el1h_64_sync+0x64/0x68

14:05:00 h63 kernel:  wq_worker_running+0x20/0x94

14:05:00 h63 kernel:  schedule+0x8c/0x100

14:05:00 h63 kernel:  worker_thread+0x1d0/0x450

14:05:00 h63 kernel:  kthread+0x104/0x110

14:05:00 h63 kernel:  ret_from_fork+0x10/0x20

14:05:00 h63 kernel: Code: 91002280 eb00003f 54000120 f9400a73 (f85f8260)

14:05:00 h63 kernel: ---[ end trace 0000000000000000 ]---

14:05:00 h63 kernel: note: kworker/0:0[1184] exited with irqs disabled

14:05:00 h63 kernel: note: kworker/0:0[1184] exited with preempt_count 2

14:05:00 h63 kernel: Fixing recursive fault but reboot is needed!

14:05:04 h63 kernel: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout

14:05:04 h63 kernel: brcmfmac: brcmf_sdio_readshared sdpcm_shared address 0x00206A70

14:05:04 h63 kernel: brcmfmac: brcmf_sdio_checkdied firmware not built with -assert

14:05:04 h63 kernel: ieee80211 phy0: brcmf_cfg80211_dump_station: BRCMF_C_GET_ASSOCLIST failed, err=-110

14:05:10 h63 kernel: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout

14:05:10 h63 kernel: brcmfmac: brcmf_sdio_readshared sdpcm_shared address 0x00206A70

14:05:10 h63 kernel: brcmfmac: brcmf_sdio_checkdied firmware not built with -assert

14:05:10 h63 kernel: ieee80211 phy0: brcmf_cfg80211_dump_station: BRCMF_C_GET_ASSOCLIST failed, err=-110

14:05:16 h63 kernel: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout

14:05:16 h63 kernel: brcmfmac: brcmf_sdio_readshared sdpcm_shared address 0x00206A70

14:05:16 h63 kernel: brcmfmac: brcmf_sdio_checkdied firmware not built with -assert

14:05:16 h63 kernel: ieee80211 phy0: brcmf_cfg80211_dump_station: BRCMF_C_GET_ASSOCLIST failed, err=-110

14:05:22 h63 kernel: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout

14:05:22 h63 kernel: brcmfmac: brcmf_sdio_readshared sdpcm_shared address 0x00206A70

14:05:22 h63 kernel: brcmfmac: brcmf_sdio_checkdied firmware not built with -assert

14:05:22 h63 kernel: ieee80211 phy0: brcmf_cfg80211_dump_station: BRCMF_C_GET_ASSOCLIST failed, err=-110

14:05:28 h63 kernel: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout

14:05:28 h63 kernel: brcmfmac: brcmf_sdio_readshared sdpcm_shared address 0x00206A70

14:05:28 h63 kernel: brcmfmac: brcmf_sdio_checkdied firmware not built with -assert

14:05:28 h63 kernel: ieee80211 phy0: brcmf_cfg80211_dump_station: BRCMF_C_GET_ASSOCLIST failed, err=-110

14:05:34 h63 kernel: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout

14:05:34 h63 kernel: brcmfmac: brcmf_sdio_readshared sdpcm_shared address 0x00206A70

14:05:34 h63 kernel: brcmfmac: brcmf_sdio_checkdied firmware not built with -assert

14:05:34 h63 kernel: ieee80211 phy0: brcmf_cfg80211_dump_station: BRCMF_C_GET_ASSOCLIST failed, err=-110

14:05:40 h63 kernel: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout

14:05:40 h63 kernel: brcmfmac: brcmf_sdio_readshared sdpcm_shared address 0x00206A70

14:05:40 h63 kernel: brcmfmac: brcmf_sdio_checkdied firmware not built with -assert

14:05:40 h63 kernel: ieee80211 phy0: brcmf_cfg80211_dump_station: BRCMF_C_GET_ASSOCLIST failed, err=-110

14:05:46 h63 kernel: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout

14:05:46 h63 kernel: brcmfmac: brcmf_sdio_readshared sdpcm_shared address 0x00206A70

14:05:46 h63 kernel: brcmfmac: brcmf_sdio_checkdied firmware not built with -assert

14:05:46 h63 kernel: ieee80211 phy0: brcmf_cfg80211_dump_station: BRCMF_C_GET_ASSOCLIST failed, err=-110

14:05:52 h63 kernel: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout

14:05:52 h63 kernel: brcmfmac: brcmf_sdio_readshared sdpcm_shared address 0x00206A70

14:05:52 h63 kernel: brcmfmac: brcmf_sdio_checkdied firmware not built with -assert

14:05:52 h63 kernel: ieee80211 phy0: brcmf_cfg80211_dump_station: BRCMF_C_GET_ASSOCLIST failed, err=-110

14:05:58 h63 kernel: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout

14:05:58 h63 kernel: brcmfmac: brcmf_sdio_readshared sdpcm_shared address 0x00206A70

14:05:58 h63 kernel: brcmfmac: brcmf_sdio_checkdied firmware not built with -assert

14:05:58 h63 kernel: ieee80211 phy0: brcmf_cfg80211_dump_station: BRCMF_C_GET_ASSOCLIST failed, err=-110

14:06:04 h63 kernel: ieee80211 phy0: brcmf_proto_bcdc_query_dcmd: brcmf_proto_bcdc_msg failed w/status -110
diff mbox series

Patch

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d6fa7c8767ad..c0250c81973e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6014,7 +6014,8 @@  struct wireless_dev {
 	} wext;
 #endif
 
-	struct cfg80211_cqm_config *cqm_config;
+	struct wiphy_work cqm_rssi_work;
+	struct cfg80211_cqm_config __rcu *cqm_config;
 
 	struct list_head pmsr_list;
 	spinlock_t pmsr_lock;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 25bc2e50a061..0f73e6373fe0 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1181,16 +1181,11 @@  void wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, bool blocked,
 }
 EXPORT_SYMBOL(wiphy_rfkill_set_hw_state_reason);
 
-void cfg80211_cqm_config_free(struct wireless_dev *wdev)
-{
-	kfree(wdev->cqm_config);
-	wdev->cqm_config = NULL;
-}
-
 static void _cfg80211_unregister_wdev(struct wireless_dev *wdev,
 				      bool unregister_netdev)
 {
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+	struct cfg80211_cqm_config *cqm_config;
 	unsigned int link_id;
 
 	ASSERT_RTNL();
@@ -1227,7 +1222,10 @@  static void _cfg80211_unregister_wdev(struct wireless_dev *wdev,
 	kfree_sensitive(wdev->wext.keys);
 	wdev->wext.keys = NULL;
 #endif
-	cfg80211_cqm_config_free(wdev);
+	/* deleted from the list, so can't be found from nl80211 any more */
+	cqm_config = rcu_access_pointer(wdev->cqm_config);
+	kfree_rcu(cqm_config, rcu_head);
+	wiphy_work_cancel(wdev->wiphy, &wdev->cqm_rssi_work);
 
 	/*
 	 * Ensure that all events have been processed and
@@ -1379,6 +1377,8 @@  void cfg80211_init_wdev(struct wireless_dev *wdev)
 	wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
 #endif
 
+	wiphy_work_init(&wdev->cqm_rssi_work, cfg80211_cqm_rssi_notify_work);
+
 	if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
 		wdev->ps = true;
 	else
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 8a807b609ef7..86f209abc06a 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -295,12 +295,17 @@  struct cfg80211_beacon_registration {
 };
 
 struct cfg80211_cqm_config {
+	struct rcu_head rcu_head;
 	u32 rssi_hyst;
 	s32 last_rssi_event_value;
+	enum nl80211_cqm_rssi_threshold_event last_rssi_event_type;
 	int n_rssi_thresholds;
 	s32 rssi_thresholds[];
 };
 
+void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy,
+				   struct wiphy_work *work);
+
 void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev);
 
 /* free object */
@@ -566,8 +571,6 @@  cfg80211_bss_update(struct cfg80211_registered_device *rdev,
 #define CFG80211_DEV_WARN_ON(cond)	({bool __r = (cond); __r; })
 #endif
 
-void cfg80211_cqm_config_free(struct wireless_dev *wdev);
-
 void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid);
 void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev);
 void cfg80211_pmsr_free_wk(struct work_struct *work);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8bcf8e293308..7513c549d577 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -12796,7 +12796,8 @@  static int nl80211_set_cqm_txe(struct genl_info *info,
 }
 
 static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
-				    struct net_device *dev)
+				    struct net_device *dev,
+				    struct cfg80211_cqm_config *cqm_config)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	s32 last, low, high;
@@ -12805,7 +12806,7 @@  static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
 	int err;
 
 	/* RSSI reporting disabled? */
-	if (!wdev->cqm_config)
+	if (!cqm_config)
 		return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
 
 	/*
@@ -12814,7 +12815,7 @@  static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
 	 * connection is established and enough beacons received to calculate
 	 * the average.
 	 */
-	if (!wdev->cqm_config->last_rssi_event_value &&
+	if (!cqm_config->last_rssi_event_value &&
 	    wdev->links[0].client.current_bss &&
 	    rdev->ops->get_station) {
 		struct station_info sinfo = {};
@@ -12828,30 +12829,30 @@  static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
 
 		cfg80211_sinfo_release_content(&sinfo);
 		if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
-			wdev->cqm_config->last_rssi_event_value =
+			cqm_config->last_rssi_event_value =
 				(s8) sinfo.rx_beacon_signal_avg;
 	}
 
-	last = wdev->cqm_config->last_rssi_event_value;
-	hyst = wdev->cqm_config->rssi_hyst;
-	n = wdev->cqm_config->n_rssi_thresholds;
+	last = cqm_config->last_rssi_event_value;
+	hyst = cqm_config->rssi_hyst;
+	n = cqm_config->n_rssi_thresholds;
 
 	for (i = 0; i < n; i++) {
 		i = array_index_nospec(i, n);
-		if (last < wdev->cqm_config->rssi_thresholds[i])
+		if (last < cqm_config->rssi_thresholds[i])
 			break;
 	}
 
 	low_index = i - 1;
 	if (low_index >= 0) {
 		low_index = array_index_nospec(low_index, n);
-		low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
+		low = cqm_config->rssi_thresholds[low_index] - hyst;
 	} else {
 		low = S32_MIN;
 	}
 	if (i < n) {
 		i = array_index_nospec(i, n);
-		high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
+		high = cqm_config->rssi_thresholds[i] + hyst - 1;
 	} else {
 		high = S32_MAX;
 	}
@@ -12864,6 +12865,7 @@  static int nl80211_set_cqm_rssi(struct genl_info *info,
 				u32 hysteresis)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct cfg80211_cqm_config *cqm_config = NULL, *old;
 	struct net_device *dev = info->user_ptr[1];
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	int i, err;
@@ -12881,10 +12883,6 @@  static int nl80211_set_cqm_rssi(struct genl_info *info,
 	    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
 		return -EOPNOTSUPP;
 
-	wdev_lock(wdev);
-	cfg80211_cqm_config_free(wdev);
-	wdev_unlock(wdev);
-
 	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);
@@ -12901,9 +12899,9 @@  static int nl80211_set_cqm_rssi(struct genl_info *info,
 		n_thresholds = 0;
 
 	wdev_lock(wdev);
+	old = rcu_dereference_protected(wdev->cqm_config,
+					lockdep_is_held(&wdev->mtx));
 	if (n_thresholds) {
-		struct cfg80211_cqm_config *cqm_config;
-
 		cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
 						 n_thresholds),
 				     GFP_KERNEL);
@@ -12918,10 +12916,16 @@  static int nl80211_set_cqm_rssi(struct genl_info *info,
 		       flex_array_size(cqm_config, rssi_thresholds,
 				       n_thresholds));
 
-		wdev->cqm_config = cqm_config;
+		rcu_assign_pointer(wdev->cqm_config, cqm_config);
 	}
 
-	err = cfg80211_cqm_rssi_update(rdev, dev);
+	err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config);
+	if (err) {
+		rcu_assign_pointer(wdev->cqm_config, old);
+		kfree(cqm_config);
+	} else {
+		kfree_rcu(old, rcu_head);
+	}
 
 unlock:
 	wdev_unlock(wdev);
@@ -19073,9 +19077,8 @@  void cfg80211_cqm_rssi_notify(struct net_device *dev,
 			      enum nl80211_cqm_rssi_threshold_event rssi_event,
 			      s32 rssi_level, gfp_t gfp)
 {
-	struct sk_buff *msg;
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+	struct cfg80211_cqm_config *cqm_config;
 
 	trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
 
@@ -19083,16 +19086,42 @@  void cfg80211_cqm_rssi_notify(struct net_device *dev,
 		    rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
 		return;
 
-	if (wdev->cqm_config) {
-		wdev->cqm_config->last_rssi_event_value = rssi_level;
+	rcu_read_lock();
+	cqm_config = rcu_dereference(wdev->cqm_config);
+	if (cqm_config) {
+		cqm_config->last_rssi_event_value = rssi_level;
+		cqm_config->last_rssi_event_type = rssi_event;
+		wiphy_work_queue(wdev->wiphy, &wdev->cqm_rssi_work);
+	}
+	rcu_read_unlock();
+}
+EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
 
-		cfg80211_cqm_rssi_update(rdev, dev);
+void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, struct wiphy_work *work)
+{
+	struct wireless_dev *wdev = container_of(work, struct wireless_dev,
+						 cqm_rssi_work);
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+	enum nl80211_cqm_rssi_threshold_event rssi_event;
+	struct cfg80211_cqm_config *cqm_config;
+	struct sk_buff *msg;
+	s32 rssi_level;
 
-		if (rssi_level == 0)
-			rssi_level = wdev->cqm_config->last_rssi_event_value;
+	wdev_lock(wdev);
+	cqm_config = rcu_dereference_protected(wdev->cqm_config,
+					       lockdep_is_held(&wdev->mtx));
+	if (!wdev->cqm_config) {
+		wdev_unlock(wdev);
+		return;
 	}
 
-	msg = cfg80211_prepare_cqm(dev, NULL, gfp);
+	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;
+	wdev_unlock(wdev);
+
+	msg = cfg80211_prepare_cqm(wdev->netdev, NULL, GFP_KERNEL);
 	if (!msg)
 		return;
 
@@ -19104,14 +19133,13 @@  void cfg80211_cqm_rssi_notify(struct net_device *dev,
 				      rssi_level))
 		goto nla_put_failure;
 
-	cfg80211_send_cqm(msg, gfp);
+	cfg80211_send_cqm(msg, GFP_KERNEL);
 
 	return;
 
  nla_put_failure:
 	nlmsg_free(msg);
 }
-EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
 
 void cfg80211_cqm_txe_notify(struct net_device *dev,
 			     const u8 *peer, u32 num_packets,