aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-05-26 06:02:58 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2014-05-27 05:32:02 -0400
commit7147a13135ee717397969d33a139204dfe793022 (patch)
tree4eedc3cdbe991c96025e9050c89d3cbc25d36b01
parent4b81d1776092125db98301b0044476478e1e8de2 (diff)
ath10k: protect src_ring state with ce_lock in tx_sg()
It was possible to read invalid state of CE ring buffer indexes. This could lead to scatter-gather transfer failure in mid-way and crash firmware later by leaving garbage data on the ring. Reported-By: Avery Pennarun <apenwarr@gmail.com> Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 71ab110a4c4d..b1eb9153c7f4 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -762,13 +762,17 @@ static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
762 struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id]; 762 struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id];
763 struct ath10k_ce_pipe *ce_pipe = pci_pipe->ce_hdl; 763 struct ath10k_ce_pipe *ce_pipe = pci_pipe->ce_hdl;
764 struct ath10k_ce_ring *src_ring = ce_pipe->src_ring; 764 struct ath10k_ce_ring *src_ring = ce_pipe->src_ring;
765 unsigned int nentries_mask = src_ring->nentries_mask; 765 unsigned int nentries_mask;
766 unsigned int sw_index = src_ring->sw_index; 766 unsigned int sw_index;
767 unsigned int write_index = src_ring->write_index; 767 unsigned int write_index;
768 int err, i; 768 int err, i;
769 769
770 spin_lock_bh(&ar_pci->ce_lock); 770 spin_lock_bh(&ar_pci->ce_lock);
771 771
772 nentries_mask = src_ring->nentries_mask;
773 sw_index = src_ring->sw_index;
774 write_index = src_ring->write_index;
775
772 if (unlikely(CE_RING_DELTA(nentries_mask, 776 if (unlikely(CE_RING_DELTA(nentries_mask,
773 write_index, sw_index - 1) < n_items)) { 777 write_index, sw_index - 1) < n_items)) {
774 err = -ENOBUFS; 778 err = -ENOBUFS;