Skip to content

Commit dd66185

Browse files
ajaykathatKalle Valo
authored andcommitted
wifi: wilc1000: add missing read critical sections around vif list traversal
Some code manipulating the vif list is still missing some srcu_read_lock / srcu_read_unlock, and so can trigger RCU warnings: ============================= WARNING: suspicious RCU usage 6.8.0-rc1+ #37 Not tainted ----------------------------- drivers/net/wireless/microchip/wilc1000/hif.c:110 RCU-list traversed without holding the required lock!! [...] stack backtrace: CPU: 0 PID: 6 Comm: kworker/0:0 Not tainted 6.8.0-rc1+ #37 Hardware name: Atmel SAMA5 Workqueue: events sdio_irq_work unwind_backtrace from show_stack+0x18/0x1c show_stack from dump_stack_lvl+0x34/0x58 dump_stack_lvl from wilc_get_vif_from_idx+0x158/0x180 wilc_get_vif_from_idx from wilc_network_info_received+0x80/0x48c wilc_network_info_received from wilc_handle_isr+0xa10/0xd30 wilc_handle_isr from wilc_sdio_interrupt+0x44/0x58 wilc_sdio_interrupt from process_sdio_pending_irqs+0x1c8/0x60c process_sdio_pending_irqs from sdio_irq_work+0x6c/0x14c sdio_irq_work from process_one_work+0x8d4/0x169c process_one_work from worker_thread+0x8cc/0x1340 worker_thread from kthread+0x448/0x510 kthread from ret_from_fork+0x14/0x28 Fix those warnings by adding the needed lock around the corresponding critical sections Signed-off-by: Ajay Singh <[email protected]> Co-developed-by: Alexis Lothoré <[email protected]> Signed-off-by: Alexis Lothoré <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://msgid.link/[email protected]
1 parent 51e4aa8 commit dd66185

File tree

2 files changed

+35
-25
lines changed

2 files changed

+35
-25
lines changed

drivers/net/wireless/microchip/wilc1000/hif.c

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,23 +1570,25 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
15701570
struct host_if_drv *hif_drv;
15711571
struct host_if_msg *msg;
15721572
struct wilc_vif *vif;
1573+
int srcu_idx;
15731574
int result;
15741575
int id;
15751576

15761577
id = get_unaligned_le32(&buffer[length - 4]);
1578+
srcu_idx = srcu_read_lock(&wilc->srcu);
15771579
vif = wilc_get_vif_from_idx(wilc, id);
15781580
if (!vif)
1579-
return;
1580-
hif_drv = vif->hif_drv;
1581+
goto out;
15811582

1583+
hif_drv = vif->hif_drv;
15821584
if (!hif_drv) {
15831585
netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
1584-
return;
1586+
goto out;
15851587
}
15861588

15871589
msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
15881590
if (IS_ERR(msg))
1589-
return;
1591+
goto out;
15901592

15911593
msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1;
15921594
msg->body.net_info.rssi = buffer[8];
@@ -1595,7 +1597,7 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
15951597
GFP_KERNEL);
15961598
if (!msg->body.net_info.mgmt) {
15971599
kfree(msg);
1598-
return;
1600+
goto out;
15991601
}
16001602

16011603
result = wilc_enqueue_work(msg);
@@ -1604,76 +1606,78 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
16041606
kfree(msg->body.net_info.mgmt);
16051607
kfree(msg);
16061608
}
1609+
out:
1610+
srcu_read_unlock(&wilc->srcu, srcu_idx);
16071611
}
16081612

16091613
void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
16101614
{
16111615
struct host_if_drv *hif_drv;
16121616
struct host_if_msg *msg;
16131617
struct wilc_vif *vif;
1618+
int srcu_idx;
16141619
int result;
16151620
int id;
16161621

16171622
mutex_lock(&wilc->deinit_lock);
16181623

16191624
id = get_unaligned_le32(&buffer[length - 4]);
1625+
srcu_idx = srcu_read_lock(&wilc->srcu);
16201626
vif = wilc_get_vif_from_idx(wilc, id);
1621-
if (!vif) {
1622-
mutex_unlock(&wilc->deinit_lock);
1623-
return;
1624-
}
1627+
if (!vif)
1628+
goto out;
16251629

16261630
hif_drv = vif->hif_drv;
16271631

16281632
if (!hif_drv) {
1629-
mutex_unlock(&wilc->deinit_lock);
1630-
return;
1633+
goto out;
16311634
}
16321635

16331636
if (!hif_drv->conn_info.conn_result) {
16341637
netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
1635-
mutex_unlock(&wilc->deinit_lock);
1636-
return;
1638+
goto out;
16371639
}
16381640

16391641
msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
1640-
if (IS_ERR(msg)) {
1641-
mutex_unlock(&wilc->deinit_lock);
1642-
return;
1643-
}
1642+
if (IS_ERR(msg))
1643+
goto out;
16441644

16451645
msg->body.mac_info.status = buffer[7];
16461646
result = wilc_enqueue_work(msg);
16471647
if (result) {
16481648
netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
16491649
kfree(msg);
16501650
}
1651-
1651+
out:
1652+
srcu_read_unlock(&wilc->srcu, srcu_idx);
16521653
mutex_unlock(&wilc->deinit_lock);
16531654
}
16541655

16551656
void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
16561657
{
16571658
struct host_if_drv *hif_drv;
16581659
struct wilc_vif *vif;
1660+
int srcu_idx;
16591661
int result;
16601662
int id;
16611663

16621664
id = get_unaligned_le32(&buffer[length - 4]);
1665+
srcu_idx = srcu_read_lock(&wilc->srcu);
16631666
vif = wilc_get_vif_from_idx(wilc, id);
16641667
if (!vif)
1665-
return;
1666-
hif_drv = vif->hif_drv;
1668+
goto out;
16671669

1668-
if (!hif_drv)
1669-
return;
1670+
hif_drv = vif->hif_drv;
1671+
if (!hif_drv) {
1672+
goto out;
1673+
}
16701674

16711675
if (hif_drv->usr_scan_req.scan_result) {
16721676
struct host_if_msg *msg;
16731677

16741678
msg = wilc_alloc_work(vif, handle_scan_complete, false);
16751679
if (IS_ERR(msg))
1676-
return;
1680+
goto out;
16771681

16781682
result = wilc_enqueue_work(msg);
16791683
if (result) {
@@ -1682,6 +1686,8 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
16821686
kfree(msg);
16831687
}
16841688
}
1689+
out:
1690+
srcu_read_unlock(&wilc->srcu, srcu_idx);
16851691
}
16861692

16871693
int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie, u16 chan,

drivers/net/wireless/microchip/wilc1000/netdev.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -819,14 +819,16 @@ void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
819819
unsigned int frame_len = 0;
820820
struct wilc_vif *vif;
821821
struct sk_buff *skb;
822+
int srcu_idx;
822823
int stats;
823824

824825
if (!wilc)
825826
return;
826827

828+
srcu_idx = srcu_read_lock(&wilc->srcu);
827829
wilc_netdev = get_if_handler(wilc, buff);
828830
if (!wilc_netdev)
829-
return;
831+
goto out;
830832

831833
buff += pkt_offset;
832834
vif = netdev_priv(wilc_netdev);
@@ -837,7 +839,7 @@ void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
837839

838840
skb = dev_alloc_skb(frame_len);
839841
if (!skb)
840-
return;
842+
goto out;
841843

842844
skb->dev = wilc_netdev;
843845

@@ -850,6 +852,8 @@ void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
850852
stats = netif_rx(skb);
851853
netdev_dbg(wilc_netdev, "netif_rx ret value is: %d\n", stats);
852854
}
855+
out:
856+
srcu_read_unlock(&wilc->srcu, srcu_idx);
853857
}
854858

855859
void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size, bool is_auth)

0 commit comments

Comments
 (0)