Commit 0373512
committed
wifi: rtw89: fix use-after-free in rtw89_core_tx_kick_off_and_wait()
JIRA: https://issues.redhat.com/browse/RHEL-114889
commit 3e31a6b
Author: Fedor Pchelkin <pchelkin@ispras.ru>
Date: Sat Sep 20 00:08:47 2025 +0300
wifi: rtw89: fix use-after-free in rtw89_core_tx_kick_off_and_wait()
There is a bug observed when rtw89_core_tx_kick_off_and_wait() tries to
access already freed skb_data:
BUG: KFENCE: use-after-free write in rtw89_core_tx_kick_off_and_wait drivers/net/wireless/realtek/rtw89/core.c:1110
CPU: 6 UID: 0 PID: 41377 Comm: kworker/u64:24 Not tainted 6.17.0-rc1+ #1 PREEMPT(lazy)
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS edk2-20250523-14.fc42 05/23/2025
Workqueue: events_unbound cfg80211_wiphy_work [cfg80211]
Use-after-free write at 0x0000000020309d9d (in kfence-#251):
rtw89_core_tx_kick_off_and_wait drivers/net/wireless/realtek/rtw89/core.c:1110
rtw89_core_scan_complete drivers/net/wireless/realtek/rtw89/core.c:5338
rtw89_hw_scan_complete_cb drivers/net/wireless/realtek/rtw89/fw.c:7979
rtw89_chanctx_proceed_cb drivers/net/wireless/realtek/rtw89/chan.c:3165
rtw89_chanctx_proceed drivers/net/wireless/realtek/rtw89/chan.h:141
rtw89_hw_scan_complete drivers/net/wireless/realtek/rtw89/fw.c:8012
rtw89_mac_c2h_scanofld_rsp drivers/net/wireless/realtek/rtw89/mac.c:5059
rtw89_fw_c2h_work drivers/net/wireless/realtek/rtw89/fw.c:6758
process_one_work kernel/workqueue.c:3241
worker_thread kernel/workqueue.c:3400
kthread kernel/kthread.c:463
ret_from_fork arch/x86/kernel/process.c:154
ret_from_fork_asm arch/x86/entry/entry_64.S:258
kfence-#251: 0x0000000056e2393d-0x000000009943cb62, size=232, cache=skbuff_head_cache
allocated by task 41377 on cpu 6 at 77869.159548s (0.009551s ago):
__alloc_skb net/core/skbuff.c:659
__netdev_alloc_skb net/core/skbuff.c:734
ieee80211_nullfunc_get net/mac80211/tx.c:5844
rtw89_core_send_nullfunc drivers/net/wireless/realtek/rtw89/core.c:3431
rtw89_core_scan_complete drivers/net/wireless/realtek/rtw89/core.c:5338
rtw89_hw_scan_complete_cb drivers/net/wireless/realtek/rtw89/fw.c:7979
rtw89_chanctx_proceed_cb drivers/net/wireless/realtek/rtw89/chan.c:3165
rtw89_chanctx_proceed drivers/net/wireless/realtek/rtw89/chan.c:3194
rtw89_hw_scan_complete drivers/net/wireless/realtek/rtw89/fw.c:8012
rtw89_mac_c2h_scanofld_rsp drivers/net/wireless/realtek/rtw89/mac.c:5059
rtw89_fw_c2h_work drivers/net/wireless/realtek/rtw89/fw.c:6758
process_one_work kernel/workqueue.c:3241
worker_thread kernel/workqueue.c:3400
kthread kernel/kthread.c:463
ret_from_fork arch/x86/kernel/process.c:154
ret_from_fork_asm arch/x86/entry/entry_64.S:258
freed by task 1045 on cpu 9 at 77869.168393s (0.001557s ago):
ieee80211_tx_status_skb net/mac80211/status.c:1117
rtw89_pci_release_txwd_skb drivers/net/wireless/realtek/rtw89/pci.c:564
rtw89_pci_release_tx_skbs.isra.0 drivers/net/wireless/realtek/rtw89/pci.c:651
rtw89_pci_release_tx drivers/net/wireless/realtek/rtw89/pci.c:676
rtw89_pci_napi_poll drivers/net/wireless/realtek/rtw89/pci.c:4238
__napi_poll net/core/dev.c:7495
net_rx_action net/core/dev.c:7557 net/core/dev.c:7684
handle_softirqs kernel/softirq.c:580
do_softirq.part.0 kernel/softirq.c:480
__local_bh_enable_ip kernel/softirq.c:407
rtw89_pci_interrupt_threadfn drivers/net/wireless/realtek/rtw89/pci.c:927
irq_thread_fn kernel/irq/manage.c:1133
irq_thread kernel/irq/manage.c:1257
kthread kernel/kthread.c:463
ret_from_fork arch/x86/kernel/process.c:154
ret_from_fork_asm arch/x86/entry/entry_64.S:258
It is a consequence of a race between the waiting and the signaling side
of the completion:
Waiting thread Completing thread
rtw89_core_tx_kick_off_and_wait()
rcu_assign_pointer(skb_data->wait, wait)
/* start waiting */
wait_for_completion_timeout()
rtw89_pci_tx_status()
rtw89_core_tx_wait_complete()
rcu_read_lock()
/* signals completion and
* proceeds further
*/
complete(&wait->completion)
rcu_read_unlock()
...
/* frees skb_data */
ieee80211_tx_status_ni()
/* returns (exit status doesn't matter) */
wait_for_completion_timeout()
...
/* accesses the already freed skb_data */
rcu_assign_pointer(skb_data->wait, NULL)
The completing side might proceed and free the underlying skb even before
the waiting side is fully awoken and run to execution. Actually the race
happens regardless of wait_for_completion_timeout() exit status, e.g.
the waiting side may hit a timeout and the concurrent completing side is
still able to free the skb.
Skbs which are sent by rtw89_core_tx_kick_off_and_wait() are owned by the
driver. They don't come from core ieee80211 stack so no need to pass them
to ieee80211_tx_status_ni() on completing side.
Introduce a work function which will act as a garbage collector for
rtw89_tx_wait_info objects and the associated skbs. Thus no potentially
heavy locks are required on the completing side.
Found by Linux Verification Center (linuxtesting.org).
Fixes: 1ae5ca6 ("wifi: rtw89: add function to wait for completion of TX skbs")
Cc: stable@vger.kernel.org
Suggested-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250919210852.823912-2-pchelkin@ispras.ru
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>1 parent 4320565 commit 0373512
4 files changed
+61
-9
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1073 | 1073 | | |
1074 | 1074 | | |
1075 | 1075 | | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
1076 | 1084 | | |
1077 | 1085 | | |
1078 | 1086 | | |
| |||
1090 | 1098 | | |
1091 | 1099 | | |
1092 | 1100 | | |
| 1101 | + | |
| 1102 | + | |
1093 | 1103 | | |
1094 | 1104 | | |
1095 | 1105 | | |
1096 | 1106 | | |
1097 | 1107 | | |
1098 | 1108 | | |
1099 | 1109 | | |
| 1110 | + | |
1100 | 1111 | | |
1101 | 1112 | | |
1102 | 1113 | | |
1103 | 1114 | | |
1104 | 1115 | | |
1105 | | - | |
1106 | | - | |
1107 | | - | |
1108 | | - | |
1109 | 1116 | | |
1110 | | - | |
1111 | | - | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |
| 1126 | + | |
1112 | 1127 | | |
1113 | 1128 | | |
1114 | 1129 | | |
| |||
4979 | 4994 | | |
4980 | 4995 | | |
4981 | 4996 | | |
| 4997 | + | |
4982 | 4998 | | |
4983 | 4999 | | |
4984 | 5000 | | |
| |||
5204 | 5220 | | |
5205 | 5221 | | |
5206 | 5222 | | |
| 5223 | + | |
5207 | 5224 | | |
5208 | 5225 | | |
5209 | 5226 | | |
| |||
5215 | 5232 | | |
5216 | 5233 | | |
5217 | 5234 | | |
| 5235 | + | |
5218 | 5236 | | |
5219 | 5237 | | |
5220 | 5238 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3506 | 3506 | | |
3507 | 3507 | | |
3508 | 3508 | | |
| 3509 | + | |
3509 | 3510 | | |
3510 | 3511 | | |
| 3512 | + | |
3511 | 3513 | | |
| 3514 | + | |
3512 | 3515 | | |
3513 | 3516 | | |
3514 | 3517 | | |
| |||
5925 | 5928 | | |
5926 | 5929 | | |
5927 | 5930 | | |
| 5931 | + | |
| 5932 | + | |
| 5933 | + | |
5928 | 5934 | | |
5929 | 5935 | | |
5930 | 5936 | | |
| |||
6181 | 6187 | | |
6182 | 6188 | | |
6183 | 6189 | | |
| 6190 | + | |
| 6191 | + | |
| 6192 | + | |
| 6193 | + | |
| 6194 | + | |
| 6195 | + | |
| 6196 | + | |
| 6197 | + | |
| 6198 | + | |
| 6199 | + | |
| 6200 | + | |
| 6201 | + | |
| 6202 | + | |
| 6203 | + | |
| 6204 | + | |
| 6205 | + | |
| 6206 | + | |
| 6207 | + | |
| 6208 | + | |
| 6209 | + | |
6184 | 6210 | | |
6185 | 6211 | | |
6186 | 6212 | | |
| |||
6190 | 6216 | | |
6191 | 6217 | | |
6192 | 6218 | | |
| 6219 | + | |
6193 | 6220 | | |
6194 | 6221 | | |
6195 | 6222 | | |
| |||
7258 | 7285 | | |
7259 | 7286 | | |
7260 | 7287 | | |
7261 | | - | |
| 7288 | + | |
7262 | 7289 | | |
7263 | 7290 | | |
7264 | 7291 | | |
7265 | 7292 | | |
| 7293 | + | |
7266 | 7294 | | |
7267 | 7295 | | |
7268 | 7296 | | |
7269 | 7297 | | |
7270 | 7298 | | |
7271 | 7299 | | |
7272 | 7300 | | |
| 7301 | + | |
7273 | 7302 | | |
7274 | | - | |
| 7303 | + | |
| 7304 | + | |
7275 | 7305 | | |
7276 | 7306 | | |
7277 | 7307 | | |
| 7308 | + | |
7278 | 7309 | | |
7279 | 7310 | | |
7280 | 7311 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
464 | 464 | | |
465 | 465 | | |
466 | 466 | | |
467 | | - | |
| 467 | + | |
| 468 | + | |
468 | 469 | | |
469 | 470 | | |
470 | 471 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
502 | 502 | | |
503 | 503 | | |
504 | 504 | | |
| 505 | + | |
505 | 506 | | |
| 507 | + | |
506 | 508 | | |
507 | 509 | | |
508 | 510 | | |
| |||
0 commit comments