Message ID | 20230403184155.8670-2-quic_nmaran@quicinc.com (mailing list archive) |
---|---|
State | Accepted |
Commit | a06bfb3c9f69f303692cdae87bc0899d2ae8b2a6 |
Delegated to: | Kalle Valo |
Headers | show |
Series | wifi: ath11k: Ignore frags from uninitialized peer in dp | expand |
Nagarajan Maran <quic_nmaran@quicinc.com> wrote: > When max virtual ap interfaces are configured in all the bands with > ACS and hostapd restart is done every 60s, a crash is observed at > random times. > In this certain scenario, a fragmented packet is received for > self peer, for which rx_tid and rx_frags are not initialized in > datapath. While handling this fragment, crash is observed as the > rx_frag list is uninitialised and when we walk in > ath11k_dp_rx_h_sort_frags, skb null leads to exception. > > To address this, before processing received fragments we check > dp_setup_done flag is set to ensure that peer has completed its > dp peer setup for fragment queue, else ignore processing the > fragments. > > Call trace: > ath11k_dp_process_rx_err+0x550/0x1084 [ath11k] > ath11k_dp_service_srng+0x70/0x370 [ath11k] > 0xffffffc009693a04 > __napi_poll+0x30/0xa4 > net_rx_action+0x118/0x270 > __do_softirq+0x10c/0x244 > irq_exit+0x64/0xb4 > __handle_domain_irq+0x88/0xac > gic_handle_irq+0x74/0xbc > el1_irq+0xf0/0x1c0 > arch_cpu_idle+0x10/0x18 > do_idle+0x104/0x248 > cpu_startup_entry+0x20/0x64 > rest_init+0xd0/0xdc > arch_call_rest_init+0xc/0x14 > start_kernel+0x480/0x4b8 > Code: f9400281 f94066a2 91405021 b94a0023 (f9406401) > > Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 > > Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com> > Signed-off-by: Nagarajan Maran <quic_nmaran@quicinc.com> > Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> 2 patches applied to ath-next branch of ath.git, thanks. a06bfb3c9f69 wifi: ath11k: Ignore frags from uninitialized peer in dp. 41e02bf4ae32 wifi: ath11k: fix undefined behavior with __fls in dp
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c index f5156a7fbdd7..d070bcb3fe24 100644 --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c @@ -36,6 +36,7 @@ void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr) } ath11k_peer_rx_tid_cleanup(ar, peer); + peer->dp_setup_done = false; crypto_free_shash(peer->tfm_mmic); spin_unlock_bh(&ab->base_lock); } @@ -72,7 +73,8 @@ int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr) ret = ath11k_peer_rx_frag_setup(ar, addr, vdev_id); if (ret) { ath11k_warn(ab, "failed to setup rx defrag context\n"); - return ret; + tid--; + goto peer_clean; } /* TODO: Setup other peer specific resource used in data path */ diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 99859b59138e..2893f6757e3e 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -3127,6 +3127,7 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id } peer->tfm_mmic = tfm; + peer->dp_setup_done = true; spin_unlock_bh(&ab->base_lock); return 0; @@ -3572,6 +3573,13 @@ static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar, ret = -ENOENT; goto out_unlock; } + if (!peer->dp_setup_done) { + ath11k_warn(ab, "The peer %pM [%d] has uninitialized datapath\n", + peer->addr, peer_id); + ret = -ENOENT; + goto out_unlock; + } + rx_tid = &peer->rx_tid[tid]; if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) || diff --git a/drivers/net/wireless/ath/ath11k/peer.h b/drivers/net/wireless/ath/ath11k/peer.h index 6dd17bafe3a0..9bd385d0a38c 100644 --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h @@ -35,6 +35,7 @@ struct ath11k_peer { u16 sec_type; u16 sec_type_grp; bool is_authorized; + bool dp_setup_done; }; void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);