diff options
author | Michal Kazior <michal.kazior@tieto.com> | 2014-05-26 06:02:58 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2014-05-27 05:32:02 -0400 |
commit | 7147a13135ee717397969d33a139204dfe793022 (patch) | |
tree | 4eedc3cdbe991c96025e9050c89d3cbc25d36b01 | |
parent | 4b81d1776092125db98301b0044476478e1e8de2 (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.c | 10 |
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; |